diff options
Diffstat (limited to 'lang')
309 files changed, 42589 insertions, 14 deletions
diff --git a/lang/Makefile.am b/lang/Makefile.am index 854d934..fd3ce4e 100644 --- a/lang/Makefile.am +++ b/lang/Makefile.am @@ -17,6 +17,7 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA -SUBDIRS = cl +SUBDIRS = $(ENABLED_LANGUAGES) +DIST_SUBDIRS = cl cpp qt python EXTRA_DIST = README diff --git a/lang/Makefile.in b/lang/Makefile.in index 3dc49d0..5c96b8f 100644 --- a/lang/Makefile.in +++ b/lang/Makefile.in @@ -100,12 +100,16 @@ subdir = lang DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/mkinstalldirs README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -167,7 +171,6 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -208,6 +211,7 @@ BUILD_REVISION = @BUILD_REVISION@ BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ @@ -219,12 +223,14 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ @@ -235,15 +241,23 @@ GLIB_LIBS = @GLIB_LIBS@ GLIB_MKENUMS = @GLIB_MKENUMS@ GOBJECT_QUERY = @GOBJECT_QUERY@ GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -254,10 +268,16 @@ LDFLAGS = @LDFLAGS@ LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -267,6 +287,8 @@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -283,14 +305,27 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ -QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@ -QT4_CORE_LIBS = @QT4_CORE_LIBS@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ RANLIB = @RANLIB@ RC = @RC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ SYSROOT = @SYSROOT@ VERSION = @VERSION@ VERSION_NUMBER = @VERSION_NUMBER@ @@ -339,9 +374,13 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -350,7 +389,8 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = cl +SUBDIRS = $(ENABLED_LANGUAGES) +DIST_SUBDIRS = cl cpp qt python EXTRA_DIST = README all: all-recursive diff --git a/lang/README b/lang/README index da54c78..f7a1595 100644 --- a/lang/README +++ b/lang/README @@ -10,3 +10,6 @@ sub-directory. Directory Language cl Common Lisp +cpp C++ +qt Qt-Framework API +python Python 2 and 3 (port of PyME 0.9.0) diff --git a/lang/cl/Makefile.in b/lang/cl/Makefile.in index 954fc18..7a79757 100644 --- a/lang/cl/Makefile.in +++ b/lang/cl/Makefile.in @@ -103,12 +103,16 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/gpgme.asd.in \ $(dist_clfiles_DATA) README ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \ - $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \ +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ - $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) @@ -180,6 +184,7 @@ BUILD_REVISION = @BUILD_REVISION@ BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ @@ -191,12 +196,14 @@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ @@ -207,15 +214,23 @@ GLIB_LIBS = @GLIB_LIBS@ GLIB_MKENUMS = @GLIB_MKENUMS@ GOBJECT_QUERY = @GOBJECT_QUERY@ GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -226,10 +241,16 @@ LDFLAGS = @LDFLAGS@ LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -239,6 +260,8 @@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -255,14 +278,27 @@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ -QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@ -QT4_CORE_LIBS = @QT4_CORE_LIBS@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ RANLIB = @RANLIB@ RC = @RC@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ SYSROOT = @SYSROOT@ VERSION = @VERSION@ VERSION_NUMBER = @VERSION_NUMBER@ @@ -311,9 +347,13 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/lang/cl/gpgme.asd b/lang/cl/gpgme.asd index 9030a65..c192da7 100644 --- a/lang/cl/gpgme.asd +++ b/lang/cl/gpgme.asd @@ -27,7 +27,7 @@ (defsystem gpgme :description "GnuPG Made Easy." :author "g10 Code GmbH" - :version "1.6.0" + :version "1.7.0" :licence "GPL" :depends-on ("cffi" "gpg-error") :components ((:file "gpgme-package") diff --git a/lang/cpp/Makefile.am b/lang/cpp/Makefile.am new file mode 100644 index 0000000..7fbaca8 --- /dev/null +++ b/lang/cpp/Makefile.am @@ -0,0 +1,23 @@ +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +SUBDIRS = src + +EXTRA_DIST = README diff --git a/lang/cpp/Makefile.in b/lang/cpp/Makefile.in new file mode 100644 index 0000000..f042f77 --- /dev/null +++ b/lang/cpp/Makefile.in @@ -0,0 +1,709 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/cpp +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = src +EXTRA_DIST = README +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/cpp/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/cpp/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/cpp/README b/lang/cpp/README new file mode 100644 index 0000000..b9a48da --- /dev/null +++ b/lang/cpp/README @@ -0,0 +1,101 @@ +GpgMEpp - C++ bindings/wrapper for GPGME +---------------------------------------- +Based on KF5gpgmepp + +Overview +-------- + +GpgMEpp 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). + +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. +6. Use of STL containers for improved memory management and + dealing with lists. +7. Complete abstraction of the C-API so "gpgme.h" should not + be needed in your project using GpgME++. +8. Abstraction of GnuPG's edit-key interface by prepared + Editinteractor classes. + +GpgMEpp was originally developed as part of the KDEPIM community. + +Usage +----- + +The usage pattern of GpgMEpp closely follows GPGMEs core usage +pattern so the documentation for GPGME itself provides a good +way to start. + +The context structure in GPGME is mapped to a Context object in +GpgMEpp. Additional convienience code provides Data objects and +a Dataprovider interface that can be used to implement GPGME's +data with any subclass by implementing the right callbacks. + +EditInteractor subclasses provide ready to use classes for +common --edit-key tasks. You can implement your own editinteractor +classes by implementing the EditInteractor interface and using +your subclass as an interactor in the edit function. + +Example to set the ownertrust of a key: + + /* Create an edit interactor */ + EditInteractor *ei = new GpgSetOwnerTrustEditInteractor(Key::Ultimate); + /* Obtain a Context */ + Context *ctx = Context::createForProtocol(Protocol::OpenPGP); + /* Create an in memory data object */ + Data data; + /* Start the edit on some key previously obtained. */ + Error e = ctx->edit(key, std::unique_ptr<EditInteractor>(ei), data); + /* Errors provide boolean comparision */ + if (!e) + ... + /* Delete the context */ + delete ctx; + +Examples / Tests +---------------- + +GpgMEpp is tested through the Qt API. You can refer to the +tests in qt/tests for examples of usage or refer to +the actual QGpgME*Job.cpp implementations which rely +on GpgMEpp and should cover most use cases. + +Hacking +------- + +GpgMEpp follows KDE Coding styles. See: +https://techbase.kde.org/Policies/Frameworks_Coding_Style +for more info. + +License +------- +GPGMEpp is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +GPGMEpp is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with GPGME++; see the file COPYING.LIB. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. diff --git a/lang/cpp/src/GpgmeppConfig.cmake.in.in b/lang/cpp/src/GpgmeppConfig.cmake.in.in new file mode 100644 index 0000000..d54011e --- /dev/null +++ b/lang/cpp/src/GpgmeppConfig.cmake.in.in @@ -0,0 +1,108 @@ +# CMake Config file for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +# based on a generated file from cmake. +# Generated by CMake 3.0.2 + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget KF5::Gpgmepp Gpgmepp) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) + +# Create imported target Gpgmepp +add_library(Gpgmepp SHARED IMPORTED) + +set_target_properties(Gpgmepp PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/gpgme++" + INTERFACE_LINK_LIBRARIES "pthread;@resolved_libdir@/libgpgme@libsuffix@;@LIBASSUAN_LIBS@" + IMPORTED_LOCATION "@resolved_libdir@/libgpgmepp@libsuffix@" +) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) + +get_filename_component(QGpgme_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) +# Pull in QGpgme for compatibility with KF5 variant. +find_package(QGpgme CONFIG) diff --git a/lang/cpp/src/GpgmeppConfigVersion.cmake.in b/lang/cpp/src/GpgmeppConfigVersion.cmake.in new file mode 100644 index 0000000..43d6512 --- /dev/null +++ b/lang/cpp/src/GpgmeppConfigVersion.cmake.in @@ -0,0 +1,31 @@ +# CMake Version file for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +# based on a generated file from cmake. +set(PACKAGE_VERSION "@LIBGPGMEPP_LT_CURRENT@.@LIBGPGMEPP_LT_AGE@.@LIBGPGMEPP_LT_REVISION@.@BUILD_REVISION@") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/lang/cpp/src/Makefile.am b/lang/cpp/src/Makefile.am new file mode 100644 index 0000000..e65a875 --- /dev/null +++ b/lang/cpp/src/Makefile.am @@ -0,0 +1,99 @@ +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +EXTRA_DIST = GpgmeppConfig.cmake.in.in GpgmeppConfigVersion.cmake.in \ + gpgmepp_version.h.in + +lib_LTLIBRARIES = libgpgmepp.la + +main_sources = \ + exception.cpp context.cpp key.cpp trustitem.cpp data.cpp callbacks.cpp \ + eventloopinteractor.cpp editinteractor.cpp \ + keylistresult.cpp keygenerationresult.cpp importresult.cpp \ + decryptionresult.cpp verificationresult.cpp \ + signingresult.cpp encryptionresult.cpp \ + engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \ + gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \ + gpgadduserideditinteractor.cpp defaultassuantransaction.cpp \ + scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \ + vfsmountresult.cpp configuration.cpp tofuinfo.cpp + +gpgmepp_headers = \ + configuration.h context.h data.h decryptionresult.h \ + defaultassuantransaction.h editinteractor.h encryptionresult.h \ + engineinfo.h error.h eventloopinteractor.h exception.h global.h \ + gpgadduserideditinteractor.h gpgagentgetinfoassuantransaction.h \ + gpgmefw.h gpgsetexpirytimeeditinteractor.h \ + gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \ + importresult.h keygenerationresult.h key.h keylistresult.h \ + notation.h result.h scdgetinfoassuantransaction.h signingresult.h \ + trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \ + tofuinfo.h + +private_gpgmepp_headers = \ + result_p.h context_p.h util.h callbacks.h data_p.h + +interface_headers= \ + interfaces/assuantransaction.h interfaces/dataprovider.h \ + interfaces/passphraseprovider.h interfaces/progressprovider.h + +gpgmeppincludedir = $(includedir)/gpgme++ +gpgmeppinclude_HEADERS = $(gpgmepp_headers) +nobase_gpgmeppinclude_HEADERS = $(interface_headers) +nodist_include_HEADERS = gpgmepp_version.h + +libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \ + $(interface_headers) $(private_gpgmepp_headers) + +AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \ + -DBUILDING_GPGMEPP + +libgpgmepp_la_LIBADD = ../../../src/libgpgme.la @LIBASSUAN_LIBS@ +libgpgmepp_la_LDFLAGS = -version-info \ + @LIBGPGMEPP_LT_CURRENT@:@LIBGPGMEPP_LT_REVISION@:@LIBGPGMEPP_LT_AGE@ + +if HAVE_W32_SYSTEM +libsuffix=.dll.a +else +libsuffix=.so +endif + +GpgmeppConfig.cmake: GpgmeppConfig.cmake.in + sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@" + sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2 + mv "$@".2 "$@" + +install-cmake-files: GpgmeppConfig.cmake GpgmeppConfigVersion.cmake + -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp + $(INSTALL) GpgmeppConfig.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake + $(INSTALL) GpgmeppConfigVersion.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake + +uninstall-cmake-files: + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake + -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/ + +install-data-local: install-cmake-files + +uninstall-local: uninstall-cmake-files + +CLEANFILES = GpgmeppConfig.cmake diff --git a/lang/cpp/src/Makefile.in b/lang/cpp/src/Makefile.in new file mode 100644 index 0000000..9237d27 --- /dev/null +++ b/lang/cpp/src/Makefile.in @@ -0,0 +1,955 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/cpp/src +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs \ + $(srcdir)/GpgmeppConfig.cmake.in.in \ + $(srcdir)/GpgmeppConfigVersion.cmake.in \ + $(srcdir)/gpgmepp_version.h.in $(top_srcdir)/build-aux/depcomp \ + $(gpgmeppinclude_HEADERS) $(nobase_gpgmeppinclude_HEADERS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = GpgmeppConfig.cmake.in GpgmeppConfigVersion.cmake \ + gpgmepp_version.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(gpgmeppincludedir)" \ + "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libgpgmepp_la_DEPENDENCIES = ../../../src/libgpgme.la +am__objects_1 = exception.lo context.lo key.lo trustitem.lo data.lo \ + callbacks.lo eventloopinteractor.lo editinteractor.lo \ + keylistresult.lo keygenerationresult.lo importresult.lo \ + decryptionresult.lo verificationresult.lo signingresult.lo \ + encryptionresult.lo engineinfo.lo \ + gpgsetexpirytimeeditinteractor.lo \ + gpgsetownertrusteditinteractor.lo gpgsignkeyeditinteractor.lo \ + gpgadduserideditinteractor.lo defaultassuantransaction.lo \ + scdgetinfoassuantransaction.lo \ + gpgagentgetinfoassuantransaction.lo vfsmountresult.lo \ + configuration.lo tofuinfo.lo +am__objects_2 = +am_libgpgmepp_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + context_vanilla.lo $(am__objects_2) $(am__objects_2) +libgpgmepp_la_OBJECTS = $(am_libgpgmepp_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libgpgmepp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ + $(AM_CXXFLAGS) $(CXXFLAGS) $(libgpgmepp_la_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libgpgmepp_la_SOURCES) +DIST_SOURCES = $(libgpgmepp_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(gpgmeppinclude_HEADERS) $(nobase_gpgmeppinclude_HEADERS) \ + $(nodist_include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = GpgmeppConfig.cmake.in.in GpgmeppConfigVersion.cmake.in \ + gpgmepp_version.h.in + +lib_LTLIBRARIES = libgpgmepp.la +main_sources = \ + exception.cpp context.cpp key.cpp trustitem.cpp data.cpp callbacks.cpp \ + eventloopinteractor.cpp editinteractor.cpp \ + keylistresult.cpp keygenerationresult.cpp importresult.cpp \ + decryptionresult.cpp verificationresult.cpp \ + signingresult.cpp encryptionresult.cpp \ + engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \ + gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \ + gpgadduserideditinteractor.cpp defaultassuantransaction.cpp \ + scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \ + vfsmountresult.cpp configuration.cpp tofuinfo.cpp + +gpgmepp_headers = \ + configuration.h context.h data.h decryptionresult.h \ + defaultassuantransaction.h editinteractor.h encryptionresult.h \ + engineinfo.h error.h eventloopinteractor.h exception.h global.h \ + gpgadduserideditinteractor.h gpgagentgetinfoassuantransaction.h \ + gpgmefw.h gpgsetexpirytimeeditinteractor.h \ + gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \ + importresult.h keygenerationresult.h key.h keylistresult.h \ + notation.h result.h scdgetinfoassuantransaction.h signingresult.h \ + trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \ + tofuinfo.h + +private_gpgmepp_headers = \ + result_p.h context_p.h util.h callbacks.h data_p.h + +interface_headers = \ + interfaces/assuantransaction.h interfaces/dataprovider.h \ + interfaces/passphraseprovider.h interfaces/progressprovider.h + +gpgmeppincludedir = $(includedir)/gpgme++ +gpgmeppinclude_HEADERS = $(gpgmepp_headers) +nobase_gpgmeppinclude_HEADERS = $(interface_headers) +nodist_include_HEADERS = gpgmepp_version.h +libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \ + $(interface_headers) $(private_gpgmepp_headers) + +AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \ + -DBUILDING_GPGMEPP + +libgpgmepp_la_LIBADD = ../../../src/libgpgme.la @LIBASSUAN_LIBS@ +libgpgmepp_la_LDFLAGS = -version-info \ + @LIBGPGMEPP_LT_CURRENT@:@LIBGPGMEPP_LT_REVISION@:@LIBGPGMEPP_LT_AGE@ + +@HAVE_W32_SYSTEM_FALSE@libsuffix = .so +@HAVE_W32_SYSTEM_TRUE@libsuffix = .dll.a +CLEANFILES = GpgmeppConfig.cmake +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/cpp/src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/cpp/src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +GpgmeppConfig.cmake.in: $(top_builddir)/config.status $(srcdir)/GpgmeppConfig.cmake.in.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +GpgmeppConfigVersion.cmake: $(top_builddir)/config.status $(srcdir)/GpgmeppConfigVersion.cmake.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +gpgmepp_version.h: $(top_builddir)/config.status $(srcdir)/gpgmepp_version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libgpgmepp.la: $(libgpgmepp_la_OBJECTS) $(libgpgmepp_la_DEPENDENCIES) $(EXTRA_libgpgmepp_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libgpgmepp_la_LINK) -rpath $(libdir) $(libgpgmepp_la_OBJECTS) $(libgpgmepp_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callbacks.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context_vanilla.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decryptionresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultassuantransaction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/editinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryptionresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/engineinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eventloopinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgadduserideditinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsetexpirytimeeditinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsetownertrusteditinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsignkeyeditinteractor.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/importresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygenerationresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keylistresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scdgetinfoassuantransaction.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signingresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tofuinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trustitem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verificationresult.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfsmountresult.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-gpgmeppincludeHEADERS: $(gpgmeppinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(gpgmeppincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(gpgmeppincludedir)" || exit $$?; \ + done + +uninstall-gpgmeppincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(gpgmeppincludedir)'; $(am__uninstall_files_from_dir) +install-nobase_gpgmeppincludeHEADERS: $(nobase_gpgmeppinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(gpgmeppincludedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(gpgmeppincludedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_gpgmeppincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(gpgmeppincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_includeHEADERS: $(nodist_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-data-local install-gpgmeppincludeHEADERS \ + install-nobase_gpgmeppincludeHEADERS \ + install-nodist_includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-gpgmeppincludeHEADERS uninstall-libLTLIBRARIES \ + uninstall-local uninstall-nobase_gpgmeppincludeHEADERS \ + uninstall-nodist_includeHEADERS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-data-local install-dvi install-dvi-am \ + install-exec install-exec-am install-gpgmeppincludeHEADERS \ + install-html install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man \ + install-nobase_gpgmeppincludeHEADERS \ + install-nodist_includeHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am \ + uninstall-gpgmeppincludeHEADERS uninstall-libLTLIBRARIES \ + uninstall-local uninstall-nobase_gpgmeppincludeHEADERS \ + uninstall-nodist_includeHEADERS + + +GpgmeppConfig.cmake: GpgmeppConfig.cmake.in + sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@" + sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2 + mv "$@".2 "$@" + +install-cmake-files: GpgmeppConfig.cmake GpgmeppConfigVersion.cmake + -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp + $(INSTALL) GpgmeppConfig.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake + $(INSTALL) GpgmeppConfigVersion.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake + +uninstall-cmake-files: + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake + -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/ + +install-data-local: install-cmake-files + +uninstall-local: uninstall-cmake-files + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/cpp/src/callbacks.cpp b/lang/cpp/src/callbacks.cpp new file mode 100644 index 0000000..4b4dd80 --- /dev/null +++ b/lang/cpp/src/callbacks.cpp @@ -0,0 +1,149 @@ +/* + callbacks.cpp - callback targets for internal use: + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "callbacks.h" +#include "util.h" + +#include <interfaces/progressprovider.h> +#include <interfaces/passphraseprovider.h> +#include <interfaces/dataprovider.h> +#include <error.h> + +#include <gpgme.h> +#include <gpg-error.h> + +#include <cassert> +#include <cerrno> +#include <cstring> +#include <unistd.h> +#include <stdlib.h> + +static inline gpgme_error_t make_err_from_syserror() +{ + return gpgme_error_from_syserror(); +} + +using GpgME::ProgressProvider; +using GpgME::PassphraseProvider; +using GpgME::DataProvider; + +void progress_callback(void *opaque, const char *what, + int type, int current, int total) +{ + ProgressProvider *provider = static_cast<ProgressProvider *>(opaque); + if (provider) { + provider->showProgress(what, type, current, total); + } +} + +/* To avoid that a compiler optimizes certain memset calls away, these + macros may be used instead. */ +#define wipememory2(_ptr,_set,_len) do { \ + volatile char *_vptr=(volatile char *)(_ptr); \ + size_t _vlen=(_len); \ + while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ + } while(0) +#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) + +gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, const char *desc, + int prev_was_bad, int fd) +{ + PassphraseProvider *provider = static_cast<PassphraseProvider *>(opaque); + bool canceled = false; + gpgme_error_t err = GPG_ERR_NO_ERROR; + char *passphrase = provider ? provider->getPassphrase(uid_hint, desc, prev_was_bad, canceled) : 0 ; + if (canceled) { + err = make_error(GPG_ERR_CANCELED); + } else { + if (passphrase && *passphrase) { + size_t passphrase_length = std::strlen(passphrase); + size_t written = 0; + do { + ssize_t now_written = gpgme_io_write(fd, passphrase + written, passphrase_length - written); + if (now_written < 0) { + err = make_err_from_syserror(); + break; + } + written += now_written; + } while (written < passphrase_length); + } + } + + if (passphrase && *passphrase) { + wipememory(passphrase, std::strlen(passphrase)); + } + free(passphrase); + gpgme_io_write(fd, "\n", 1); + return err; +} + +static gpgme_ssize_t +data_read_callback(void *opaque, void *buf, size_t buflen) +{ + DataProvider *provider = static_cast<DataProvider *>(opaque); + if (!provider) { + gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL)); + return -1; + } + return (gpgme_ssize_t)provider->read(buf, buflen); +} + +static gpgme_ssize_t +data_write_callback(void *opaque, const void *buf, size_t buflen) +{ + DataProvider *provider = static_cast<DataProvider *>(opaque); + if (!provider) { + gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL)); + return -1; + } + return (gpgme_ssize_t)provider->write(buf, buflen); +} + +static gpgme_off_t +data_seek_callback(void *opaque, gpgme_off_t offset, int whence) +{ + DataProvider *provider = static_cast<DataProvider *>(opaque); + if (!provider) { + gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL)); + return -1; + } + if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) { + gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL)); + return -1; + } + return provider->seek((off_t)offset, whence); +} + +static void data_release_callback(void *opaque) +{ + DataProvider *provider = static_cast<DataProvider *>(opaque); + if (provider) { + provider->release(); + } +} + +const gpgme_data_cbs GpgME::data_provider_callbacks = { + &data_read_callback, + &data_write_callback, + &data_seek_callback, + &data_release_callback +}; diff --git a/lang/cpp/src/callbacks.h b/lang/cpp/src/callbacks.h new file mode 100644 index 0000000..4206637 --- /dev/null +++ b/lang/cpp/src/callbacks.h @@ -0,0 +1,45 @@ +/* + callbacks.h - callback targets for internal use: + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + This is an internal header file, subject to change without + notice. DO NOT USE. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_CALLBACKS_H__ +#define __GPGMEPP_CALLBACKS_H__ + +#include <gpgme.h> + +extern "C" { + + void progress_callback(void *opaque, const char *what, + int type, int current, int total); + gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, + const char *desc, int prev_was_bad, int fd); +} + +namespace GpgME +{ +extern const gpgme_data_cbs data_provider_callbacks; +extern const gpgme_edit_cb_t edit_interactor_callback; +} + +#endif // __GPGME_CALLBACKS_H__ diff --git a/lang/cpp/src/configuration.cpp b/lang/cpp/src/configuration.cpp new file mode 100644 index 0000000..7ef2883 --- /dev/null +++ b/lang/cpp/src/configuration.cpp @@ -0,0 +1,934 @@ +/* + configuration.cpp - wraps gpgme configuration components + Copyright (C) 2010 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "configuration.h" +#include "error.h" +#include "util.h" + +#include <gpgme.h> + +#include <iterator> +#include <algorithm> +#include <ostream> +#include <cstring> +#include <assert.h> + +using namespace GpgME; +using namespace GpgME::Configuration; + +typedef std::shared_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t; +typedef std::weak_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t; + +typedef std::shared_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t; +typedef std::weak_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t; + +typedef std::shared_ptr< std::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t; +typedef std::weak_ptr< std::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t; + +namespace +{ +struct nodelete { + template <typename T> void operator()(T *) {} +}; +} + +// static +std::vector<Component> Component::load(Error &returnedError) +{ + + // + // 1. get a context: + // + gpgme_ctx_t ctx_native = 0; + if (const gpgme_error_t err = gpgme_new(&ctx_native)) { + returnedError = Error(err); + return std::vector<Component>(); + } + const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release); + + // + // 2. load the config: + // + gpgme_conf_comp_t conf_list_native = 0; + if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) { + returnedError = Error(err); + return std::vector<Component>(); + } + shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release); + + // + // 3. convert to vector<Component>: + // + std::vector<Component> result; + + while (head) { + // secure 'head->next' (if any) against memleaks: + shared_gpgme_conf_comp_t next; + if (head->next) { + next.reset(head->next, &gpgme_conf_release); + } + + // now prevent double-free of next.get() and following: + head->next = 0; + + // now add a new Component to 'result' (may throw): + result.resize(result.size() + 1); + result.back().comp.swap(head); // .comp = std::move( head ); + head.swap(next); // head = std::move( next ); + } + + return result; +} + +Error Component::save() const +{ + + if (isNull()) { + return Error(make_error(GPG_ERR_INV_ARG)); + } + + // + // 1. get a context: + // + gpgme_ctx_t ctx_native = 0; + if (const gpgme_error_t err = gpgme_new(&ctx_native)) { + return Error(err); + } + const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release); + + // + // 2. save the config: + // + return Error(gpgme_op_conf_save(ctx.get(), comp.get())); +} + +const char *Component::name() const +{ + return comp ? comp->name : 0 ; +} + +const char *Component::description() const +{ + return comp ? comp->description : 0 ; +} + +const char *Component::programName() const +{ + return comp ? comp->program_name : 0 ; +} + +Option Component::option(unsigned int idx) const +{ + gpgme_conf_opt_t opt = 0; + if (comp) { + opt = comp->options; + } + while (opt && idx) { + opt = opt->next; + --idx; + } + if (opt) { + return Option(comp, opt); + } + return Option(); +} + +Option Component::option(const char *name) const +{ + gpgme_conf_opt_t opt = 0; + if (comp) { + opt = comp->options; + } + using namespace std; // for strcmp + while (opt && strcmp(name, opt->name) != 0) { + opt = opt->next; + } + if (opt) { + return Option(comp, opt); + } + return Option(); +} + +unsigned int Component::numOptions() const +{ + unsigned int result = 0; + for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) { + ++result; + } + return result; +} + +std::vector<Option> Component::options() const +{ + std::vector<Option> result; + for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) { + result.push_back(Option(comp, opt)); + } + return result; +} + +static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type) +{ + gpgme_conf_arg_t result = 0, last = 0; + for (gpgme_conf_arg_t a = other ; a ; a = a->next) { + gpgme_conf_arg_t arg = 0; + const gpgme_error_t err + = gpgme_conf_arg_new(&arg, type, + a->no_arg ? 0 : + type == GPGME_CONF_STRING ? a->value.string : + /* else */ static_cast<void *>(&a->value)); + if (err) { + gpgme_conf_arg_release(result, type); + return 0; + } + assert(arg); + if (result) { + last->next = arg; + } else { + result = arg; + } + last = arg; + } + return result; +} + +Component Option::parent() const +{ + return Component(comp.lock()); +} + +unsigned int Option::flags() const +{ + return isNull() ? 0 : opt->flags; +} + +Level Option::level() const +{ + return isNull() ? Internal : static_cast<Level>(opt->level) ; +} + +const char *Option::name() const +{ + return isNull() ? 0 : opt->name ; +} + +const char *Option::description() const +{ + return isNull() ? 0 : opt->description ; +} + +const char *Option::argumentName() const +{ + return isNull() ? 0 : opt->argname ; +} + +Type Option::type() const +{ + return isNull() ? NoType : static_cast<Type>(opt->type) ; +} + +Type Option::alternateType() const +{ + return isNull() ? NoType : static_cast<Type>(opt->alt_type) ; +} + +#if 0 +static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg) +{ + assert(arg); + switch (type) { + case GPGME_CONF_NONE: + if (list) { + // return the count (number of times set): + return arg->value.count; + } else { + return none; + } + case GPGME_CONF_INT32: + if (list) { + std::vector<int> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.int32); + } + return result; + } else { + return arg->value.int32; + } + case GPGME_CONF_UINT32: + if (list) { + std::vector<unsigned int> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.uint32); + } + return result; + } else { + return arg->value.uint32; + } + case GPGME_CONF_FILENAME: + case GPGME_CONF_LDAP_SERVER: + case GPGME_CONF_KEY_FPR: + case GPGME_CONF_PUB_KEY: + case GPGME_CONF_SEC_KEY: + case GPGME_CONF_ALIAS_LIST: + // these should not happen in alt_type, but fall through + case GPGME_CONF_STRING: + if (list) { + std::vector<const char *> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.string); + } + return result; + } else { + return arg->value.string; + } + } + assert(!"Option: unknown alt_type!"); + return Option::Variant(); +} + +namespace +{ +inline const void *to_void_star(const char *s) +{ + return s; +} +inline const void *to_void_star(const std::string &s) +{ + return s.c_str(); +} +inline const void *to_void_star(const int &i) +{ + return &i; // const-&: sic! +} +inline const void *to_void_star(const unsigned int &i) +{ + return &i; // const-&: sic! +} + +struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> { + static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value) + { + gpgme_conf_arg_t arg = 0; +#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE + if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) { + return 0; + } +#else + if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) { + return 0; + } +#endif + else { + return arg; + } + } + + gpgme_conf_arg_t operator()(bool v) const + { + return v ? make_argument(0) : 0 ; + } + + gpgme_conf_arg_t operator()(const char *s) const + { + return make_argument(s ? s : ""); + } + + gpgme_conf_arg_t operator()(const std::string &s) const + { + return operator()(s.c_str()); + } + + gpgme_conf_arg_t operator()(int i) const + { + return make_argument(&i); + } + + gpgme_conf_arg_t operator()(unsigned int i) const + { + return make_argument(&i); + } + + template <typename T> + gpgme_conf_arg_t operator()(const std::vector<T> &value) const + { + gpgme_conf_arg_t result = 0; + gpgme_conf_arg_t last = 0; + for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) { + if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) { + if (last) { + last = last->next = arg; + } else { + result = last = arg; + } + } + } + return result; + } + +}; +} + +static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value) +{ + VariantToArgumentVisitor v; + return apply_visitor(v, value); +} + +optional<Option::Variant> Option::defaultValue() const +{ + if (isNull()) { + return optional<Variant>(); + } else { + return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value); + } +} +#endif + +Argument Option::defaultValue() const +{ + if (isNull()) { + return Argument(); + } else { + return Argument(comp.lock(), opt, opt->default_value, false); + } +} + +const char *Option::defaultDescription() const +{ + return isNull() ? 0 : opt->default_description ; +} + +Argument Option::noArgumentValue() const +{ + if (isNull()) { + return Argument(); + } else { + return Argument(comp.lock(), opt, opt->no_arg_value, false); + } +} + +const char *Option::noArgumentDescription() const +{ + return isNull() ? 0 : opt->no_arg_description ; +} + +Argument Option::activeValue() const +{ + if (isNull()) { + return Argument(); + } else { + return Argument(comp.lock(), opt, opt->value, false); + } +} + +Argument Option::currentValue() const +{ + if (isNull()) { + return Argument(); + } + const gpgme_conf_arg_t arg = + opt->change_value ? opt->new_value ? opt->new_value : opt->default_value : + opt->value ? opt->value : + /* else */ opt->default_value ; + return Argument(comp.lock(), opt, arg, false); +} + +Argument Option::newValue() const +{ + if (isNull()) { + return Argument(); + } else { + return Argument(comp.lock(), opt, opt->new_value, false); + } +} + +bool Option::set() const +{ + if (isNull()) { + return false; + } else if (opt->change_value) { + return opt->new_value; + } else { + return opt->value; + } +} + +bool Option::dirty() const +{ + return !isNull() && opt->change_value ; +} + +Error Option::setNewValue(const Argument &argument) +{ + if (isNull()) { + return Error(make_error(GPG_ERR_INV_ARG)); + } else if (argument.isNull()) { + return resetToDefaultValue(); + } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) { + return Error(gpgme_conf_opt_change(opt, 0, arg)); + } else { + return Error(make_error(GPG_ERR_ENOMEM)); + } +} + +Error Option::resetToActiveValue() +{ + if (isNull()) { + return Error(make_error(GPG_ERR_INV_ARG)); + } else { + return Error(gpgme_conf_opt_change(opt, 1, 0)); + } +} + +Error Option::resetToDefaultValue() +{ + if (isNull()) { + return Error(make_error(GPG_ERR_INV_ARG)); + } else { + return Error(gpgme_conf_opt_change(opt, 0, 0)); + } +} + +static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value) +{ + gpgme_conf_arg_t arg = 0; + if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) { + return 0; + } else { + return arg; + } +} + +Argument Option::createNoneArgument(bool set) const +{ + if (isNull() || alternateType() != NoType) { + return Argument(); + } else { + if (set) { + return createNoneListArgument(1); + } + } + return Argument(); +} + +Argument Option::createStringArgument(const char *value) const +{ + if (isNull() || alternateType() != StringType) { + return Argument(); + } else { + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); + } +} + +Argument Option::createStringArgument(const std::string &value) const +{ + if (isNull() || alternateType() != StringType) { + return Argument(); + } else { + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true); + } +} + +Argument Option::createIntArgument(int value) const +{ + if (isNull() || alternateType() != IntegerType) { + return Argument(); + } else { + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true); + } +} + +Argument Option::createUIntArgument(unsigned int value) const +{ + if (isNull() || alternateType() != UnsignedIntegerType) { + return Argument(); + } else { + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true); + } +} + +namespace +{ +const void *to_void_star(const char *s) +{ + return s; +} +const void *to_void_star(const std::string &s) +{ + return s.c_str(); +} +const void *to_void_star(const int &i) +{ + return &i; // const-&: sic! +} +const void *to_void_star(const unsigned int &i) +{ + return &i; // const-&: sic! +} + +template <typename T> +gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value) +{ + gpgme_conf_arg_t result = 0; + gpgme_conf_arg_t last = 0; + for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) { + if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) { + if (last) { + last = last->next = arg; + } else { + result = last = arg; + } + } + } + return result; +} +} + +Argument Option::createNoneListArgument(unsigned int value) const +{ + if (value) { + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true); + } + return Argument(); +} + +Argument Option::createStringListArgument(const std::vector<const char *> &value) const +{ + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); +} + +Argument Option::createStringListArgument(const std::vector<std::string> &value) const +{ + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); +} + +Argument Option::createIntListArgument(const std::vector<int> &value) const +{ + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true); +} + +Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const +{ + return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true); +} + +Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns) + : comp(comp), + opt(opt), + arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +{ + +} + +#if 0 +Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg) + : comp(comp), + opt(opt), + arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +{ + +} +#endif + +Argument::Argument(const Argument &other) + : comp(other.comp), + opt(other.opt), + arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +{ + +} + +Argument::~Argument() +{ + gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE); +} + +Option Argument::parent() const +{ + return Option(comp.lock(), opt); +} + +bool Argument::boolValue() const +{ + return numberOfTimesSet(); +} + +unsigned int Argument::numElements() const +{ + if (isNull()) { + return 0; + } + unsigned int result = 0; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + ++result; + } + return result; +} + +const char *Argument::stringValue(unsigned int idx) const +{ + if (isNull() || opt->alt_type != GPGME_CONF_STRING) { + return 0; + } + gpgme_conf_arg_t a = arg; + while (a && idx) { + a = a->next; + --idx; + } + return a ? a->value.string : 0 ; +} + +int Argument::intValue(unsigned int idx) const +{ + if (isNull() || opt->alt_type != GPGME_CONF_INT32) { + return 0; + } + gpgme_conf_arg_t a = arg; + while (a && idx) { + a = a->next; + --idx; + } + return a ? a->value.int32 : 0 ; +} + +unsigned int Argument::uintValue(unsigned int idx) const +{ + if (isNull() || opt->alt_type != GPGME_CONF_UINT32) { + return 0; + } + gpgme_conf_arg_t a = arg; + while (a && idx) { + a = a->next; + --idx; + } + return a ? a->value.uint32 : 0 ; +} + +unsigned int Argument::numberOfTimesSet() const +{ + if (isNull() || opt->alt_type != GPGME_CONF_NONE) { + return 0; + } + return arg->value.count; +} + +std::vector<const char *> Argument::stringValues() const +{ + if (isNull() || opt->alt_type != GPGME_CONF_STRING) { + return std::vector<const char *>(); + } + std::vector<const char *> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.string); + } + return result; +} + +std::vector<int> Argument::intValues() const +{ + if (isNull() || opt->alt_type != GPGME_CONF_INT32) { + return std::vector<int>(); + } + std::vector<int> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.int32); + } + return result; +} + +std::vector<unsigned int> Argument::uintValues() const +{ + if (isNull() || opt->alt_type != GPGME_CONF_UINT32) { + return std::vector<unsigned int>(); + } + std::vector<unsigned int> result; + for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { + result.push_back(a->value.uint32); + } + return result; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Level level) +{ + switch (level) { + case Basic: return os << "Basic"; + case Advanced: return os << "Advanced"; + case Expert: return os << "Expert"; + case Invisible: return os << "Invisible"; + case Internal: return os << "Internal"; + case NumLevels: ; + } + return os << "<unknown>"; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Type type) +{ + switch (type) { + case NoType: return os << "None"; + case StringType: return os << "String"; + case IntegerType: return os << "Integer"; + case UnsignedIntegerType: return os << "UnsignedInteger"; + case FilenameType: return os << "Filename"; + case LdapServerType: return os << "LdapServer"; + case KeyFingerprintType: return os << "KeyFingerprint"; + case PublicKeyType: return os << "PublicKey"; + case SecretKeyType: return os << "SecretKey"; + case AliasListType: return os << "AliasList"; + case MaxType: ; + } + return os << "<unknown>"; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Flag f) +{ + unsigned int flags = f; + std::vector<const char *> s; + if (flags & Group) { + s.push_back("Group"); + } + if (flags & Optional) { + s.push_back("Optional"); + } + if (flags & List) { + s.push_back("List"); + } + if (flags & Runtime) { + s.push_back("Runtime"); + } + if (flags & Default) { + s.push_back("Default"); + } + if (flags & DefaultDescription) { + s.push_back("DefaultDescription"); + } + if (flags & NoArgumentDescription) { + s.push_back("NoArgumentDescription"); + } + if (flags & NoChange) { + s.push_back("NoChange"); + } + flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange); + if (flags) { + s.push_back("other flags("); + } + std::copy(s.begin(), s.end(), + std::ostream_iterator<const char *>(os, "|")); + if (flags) { + os << flags << ')'; + } + return os; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Component &c) +{ + os << "Component[" + << "\n name : " << protect(c.name()) + << "\n description: " << protect(c.description()) + << "\n programName: " << protect(c.programName()) + << "\n options : \n"; + const std::vector<Option> options = c.options(); + std::copy(options.begin(), options.end(), + std::ostream_iterator<Option>(os, "\n")); + os << "\n]"; + return os; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Option &o) +{ + return os << "Option[" + << "\n name: : " << protect(o.name()) + << "\n description : " << protect(o.description()) + << "\n argName : " << protect(o.argumentName()) + << "\n flags : " << static_cast<Flag>(o.flags()) + << "\n level : " << o.level() + << "\n type : " << o.type() + << "\n alt_type : " << o.alternateType() + << "\n default_val : " << o.defaultValue() + << "\n default_desc: " << protect(o.defaultDescription()) + << "\n no_arg_value: " << o.noArgumentValue() + << "\n no_arg_desc : " << protect(o.noArgumentDescription()) + << "\n active_value: " << o.activeValue() + << "\n new_value : " << o.newValue() + << "\n --> cur_val : " << o.currentValue() + << "\n set : " << o.set() + << "\n dirty : " << o.dirty() + << "\n]" + ; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a) +{ + const Option o = a.parent(); + const bool list = o.flags() & List; + os << "Argument["; + if (a) { + switch (o.alternateType()) { + case NoType: + if (list) { + os << a.numberOfTimesSet() << 'x'; + } else { + os << a.boolValue(); + } + break; + default: + case StringType: + if (list) { + const std::vector<const char *> v = a.stringValues(); + os << v.size() << ':'; + // can't use std::copy + ostream_iterator here, since we need the protect() call + bool first = true; + std::for_each(v.begin(), v.end(), [&first, &os](const char *s) { + if (first) { + first = false; + } else { + os << ','; + } + os << protect(s); + }); + } else { + os << protect(a.stringValue()); + } + break; + case IntegerType: + if (list) { + const std::vector<int> v = a.intValues(); + os << v.size() << ':'; + std::copy(v.begin(), v.end(), + std::ostream_iterator<int>(os, ",")); + } else { + os << a.intValue(); + } + break; + case UnsignedIntegerType: + if (list) { + const std::vector<unsigned int> v = a.uintValues(); + os << v.size() << ':'; + std::copy(v.begin(), v.end(), + std::ostream_iterator<unsigned int>(os, ",")); + } else { + os << a.intValue(); + } + break; + } + } + return os << ']'; +} diff --git a/lang/cpp/src/configuration.h b/lang/cpp/src/configuration.h new file mode 100644 index 0000000..288a410 --- /dev/null +++ b/lang/cpp/src/configuration.h @@ -0,0 +1,290 @@ +/* + configuration.h - wraps gpgme configuration components + Copyright (C) 2010 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_CONFIGURATION_H__ +#define __GPGMEPP_CONFIGURATION_H__ + +#include "global.h" + +#include "gpgmefw.h" + +#include <iosfwd> +#include <vector> +#include <string> +#include <algorithm> +#include <memory> + +namespace GpgME +{ +namespace Configuration +{ + +typedef std::shared_ptr< std::remove_pointer<gpgme_conf_comp_t>::type > shared_gpgme_conf_comp_t; +typedef std::weak_ptr< std::remove_pointer<gpgme_conf_comp_t>::type > weak_gpgme_conf_comp_t; + +class Argument; +class Option; +class Component; + +enum Level { + Basic, + Advanced, + Expert, + Invisible, + Internal, + + NumLevels +}; + +enum Type { + NoType, + StringType, + IntegerType, + UnsignedIntegerType, + + FilenameType = 32, + LdapServerType, + KeyFingerprintType, + PublicKeyType, + SecretKeyType, + AliasListType, + + MaxType +}; + +enum Flag { + Group = (1 << 0), + Optional = (1 << 1), + List = (1 << 2), + Runtime = (1 << 3), + Default = (1 << 4), + DefaultDescription = (1 << 5), + NoArgumentDescription = (1 << 6), + NoChange = (1 << 7), + + LastFlag = NoChange +}; + +// +// class Component +// + +class GPGMEPP_EXPORT Component +{ +public: + Component() : comp() {} + explicit Component(const shared_gpgme_conf_comp_t &comp) + : comp(comp) {} + + // copy ctor is ok + + const Component &operator=(const Component &other) + { + if (this != &other) { + Component(other).swap(*this); + } + return *this; + } + + void swap(Component &other) + { + using std::swap; + swap(this->comp, other.comp); + } + + bool isNull() const + { + return !comp; + } + + static std::vector<Component> load(Error &err); + Error save() const; + + const char *name() const; + const char *description() const; + const char *programName() const; + + Option option(unsigned int index) const; + Option option(const char *name) const; + + unsigned int numOptions() const; + + std::vector<Option> options() const; + + GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull()) +private: + shared_gpgme_conf_comp_t comp; +}; + +// +// class Option +// + +class GPGMEPP_EXPORT Option +{ +public: + Option() : comp(), opt(0) {} + Option(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt) + : comp(comp), opt(opt) {} + + const Option &operator=(const Option &other) + { + if (this != &other) { + Option(other).swap(*this); + } + return *this; + } + + void swap(Option &other) + { + using std::swap; + swap(this->comp, other.comp); + swap(this->opt, other.opt); + } + + bool isNull() const + { + return comp.expired() || !opt; + } + + Component parent() const; + + unsigned int flags() const; + + Level level() const; + + const char *name() const; + const char *description() const; + const char *argumentName() const; + + Type type() const; + Type alternateType() const; + + Argument defaultValue() const; + const char *defaultDescription() const; + + Argument noArgumentValue() const; + const char *noArgumentDescription() const; + + /*! The value that is in the config file (or null, if it's not set). */ + Argument activeValue() const; + /*! The value that is in this object, ie. either activeValue(), newValue(), or defaultValue() */ + Argument currentValue() const; + + Argument newValue() const; + bool set() const; + bool dirty() const; + + Error setNewValue(const Argument &argument); + Error resetToDefaultValue(); + Error resetToActiveValue(); + + Argument createNoneArgument(bool set) const; + Argument createStringArgument(const char *value) const; + Argument createStringArgument(const std::string &value) const; + Argument createIntArgument(int value) const; + Argument createUIntArgument(unsigned int value) const; + + Argument createNoneListArgument(unsigned int count) const; + Argument createStringListArgument(const std::vector<const char *> &value) const; + Argument createStringListArgument(const std::vector<std::string> &value) const; + Argument createIntListArgument(const std::vector<int> &values) const; + Argument createUIntListArgument(const std::vector<unsigned int> &values) const; + + GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull()) +private: + weak_gpgme_conf_comp_t comp; + gpgme_conf_opt_t opt; +}; + +// +// class Argument +// + +class GPGMEPP_EXPORT Argument +{ + friend class ::GpgME::Configuration::Option; + Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns); +public: + Argument() : comp(), opt(0), arg(0) {} + //Argument( const shared_gpgme_conf_comp_t & comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg ); + Argument(const Argument &other); + ~Argument(); + + const Argument &operator=(const Argument &other) + { + if (this != &other) { + Argument(other).swap(*this); + } + return *this; + } + + void swap(Argument &other) + { + using std::swap; + swap(this->comp, other.comp); + swap(this->opt, other.opt); + swap(this->arg, other.arg); + } + + bool isNull() const + { + return comp.expired() || !opt || !arg; + } + + Option parent() const; + + unsigned int numElements() const; + + bool boolValue() const; + const char *stringValue(unsigned int index = 0) const; + int intValue(unsigned int index = 0) const; + unsigned int uintValue(unsigned int index = 0) const; + + unsigned int numberOfTimesSet() const; + std::vector<const char *> stringValues() const; + std::vector<int> intValues() const; + std::vector<unsigned int> uintValues() const; + + GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull()) +private: + weak_gpgme_conf_comp_t comp; + gpgme_conf_opt_t opt; + gpgme_conf_arg_t arg; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Level level); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Type type); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Flag flag); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Component &component); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Option &option); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Argument &argument); + +} // namespace Configuration +} // namespace GpgME + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Component) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Option) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Argument) + +#endif // __GPGMEPP_CONFIGURATION_H__ diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp new file mode 100644 index 0000000..00f397b --- /dev/null +++ b/lang/cpp/src/context.cpp @@ -0,0 +1,1639 @@ +/* + context.cpp - wraps a gpgme key context + Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <context.h> +#include <eventloopinteractor.h> +#include <trustitem.h> +#include <keylistresult.h> +#include <keygenerationresult.h> +#include <importresult.h> +#include <decryptionresult.h> +#include <verificationresult.h> +#include <signingresult.h> +#include <encryptionresult.h> +#include <engineinfo.h> +#include <editinteractor.h> +#include <vfsmountresult.h> + +#include <interfaces/assuantransaction.h> +#include <defaultassuantransaction.h> + +#include "callbacks.h" +#include "data_p.h" +#include "context_p.h" +#include "util.h" +#include "tofuinfo.h" + +#include <gpgme.h> + +#include <istream> +#ifndef NDEBUG +#include <iostream> +using std::cerr; +using std::endl; +#endif + +#include <cassert> + +namespace GpgME +{ + +static inline unsigned int xtoi_1(const char *str) +{ + const unsigned int ch = *str; + const unsigned int result = + ch <= '9' ? ch - '0' : + ch <= 'F' ? ch - 'A' + 10 : + /* else */ ch - 'a' + 10 ; + return result < 16 ? result : 0 ; +} +static inline int xtoi_2(const char *str) +{ + return xtoi_1(str) * 16U + xtoi_1(str + 1); +} + +static void percent_unescape(std::string &s, bool plus2space) +{ + std::string::iterator src = s.begin(), dest = s.begin(), end = s.end(); + while (src != end) { + if (*src == '%' && end - src > 2) { + *dest++ = xtoi_2(&*++src); + src += 2; + } else if (*src == '+' && plus2space) { + *dest++ = ' '; + ++src; + } else { + *dest++ = *src++; + } + } + s.erase(dest, end); +} + +void initializeLibrary() +{ + gpgme_check_version(0); +} + +Error initializeLibrary(int) +{ + if (gpgme_check_version(GPGME_VERSION)) { + return Error(); + } else { + return Error::fromCode(GPG_ERR_USER_1); + } +} + +static void format_error(gpgme_error_t err, std::string &str) +{ + char buffer[ 1024 ]; + gpgme_strerror_r(err, buffer, sizeof buffer); + buffer[ sizeof buffer - 1 ] = '\0'; + str = buffer; +} + +const char *Error::source() const +{ + return gpgme_strsource((gpgme_error_t)mErr); +} + +const char *Error::asString() const +{ + if (mMessage.empty()) { + format_error(static_cast<gpgme_error_t>(mErr), mMessage); + } + return mMessage.c_str(); +} + +int Error::code() const +{ + return gpgme_err_code(mErr); +} + +int Error::sourceID() const +{ + return gpgme_err_source(mErr); +} + +bool Error::isCanceled() const +{ + return code() == GPG_ERR_CANCELED; +} + +int Error::toErrno() const +{ +//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS + return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code())); +//#else +// return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) ); +//#endif +} + +// static +bool Error::hasSystemError() +{ + return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ; +} + +// static +void Error::setSystemError(gpg_err_code_t err) +{ + setErrno(gpgme_err_code_to_errno(err)); +} + +// static +void Error::setErrno(int err) +{ + gpgme_err_set_errno(err); +} + +// static +Error Error::fromSystemError(unsigned int src) +{ + return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror())); +} + +// static +Error Error::fromErrno(int err, unsigned int src) +{ + return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err))); +} + +// static +Error Error::fromCode(unsigned int err, unsigned int src) +{ + return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err))); +} + +std::ostream &operator<<(std::ostream &os, const Error &err) +{ + return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))"; +} + +Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx)) +{ +} + +Context::~Context() +{ + delete d; +} + +Context *Context::createForProtocol(Protocol proto) +{ + gpgme_ctx_t ctx = 0; + if (gpgme_new(&ctx) != 0) { + return 0; + } + + switch (proto) { + case OpenPGP: + if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) { + gpgme_release(ctx); + return 0; + } + break; + case CMS: + if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) { + gpgme_release(ctx); + return 0; + } + break; + default: + return 0; + } + + return new Context(ctx); +} + +std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error) +{ + gpgme_ctx_t ctx = 0; + if (const gpgme_error_t err = gpgme_new(&ctx)) { + if (error) { + *error = Error(err); + } + return std::unique_ptr<Context>(); + } + + switch (eng) { + case AssuanEngine: + if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) { + gpgme_release(ctx); + if (error) { + *error = Error(err); + } + return std::unique_ptr<Context>(); + } + break; + case G13Engine: + if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) { + gpgme_release(ctx); + if (error) { + *error = Error(err); + } + return std::unique_ptr<Context>(); + } + break; + case SpawnEngine: + if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) { + gpgme_release(ctx); + if (error) { + *error = Error(err); + } + return std::unique_ptr<Context>(); + } + break; + default: + if (error) { + *error = Error::fromCode(GPG_ERR_INV_ARG); + } + return std::unique_ptr<Context>(); + } + + if (error) { + *error = Error(); + } + + return std::unique_ptr<Context>(new Context(ctx)); +} + +// +// +// Context::Private +// +// + +Context::Private::Private(gpgme_ctx_t c) + : ctx(c), + iocbs(0), + lastop(None), + lasterr(GPG_ERR_NO_ERROR), + lastAssuanInquireData(Data::null), + lastAssuanTransaction(), + lastEditInteractor(), + lastCardEditInteractor() +{ + +} + +Context::Private::~Private() +{ + if (ctx) { + gpgme_release(ctx); + } + ctx = 0; + delete iocbs; +} + +// +// +// Context attributes: +// +// + +Protocol Context::protocol() const +{ + gpgme_protocol_t p = gpgme_get_protocol(d->ctx); + switch (p) { + case GPGME_PROTOCOL_OpenPGP: return OpenPGP; + case GPGME_PROTOCOL_CMS: return CMS; + default: return UnknownProtocol; + } +} + +void Context::setArmor(bool useArmor) +{ + gpgme_set_armor(d->ctx, int(useArmor)); +} +bool Context::armor() const +{ + return gpgme_get_armor(d->ctx); +} + +void Context::setTextMode(bool useTextMode) +{ + gpgme_set_textmode(d->ctx, int(useTextMode)); +} +bool Context::textMode() const +{ + return gpgme_get_textmode(d->ctx); +} + +void Context::setOffline(bool useOfflineMode) +{ + gpgme_set_offline(d->ctx, int(useOfflineMode)); +} +bool Context::offline() const +{ + return gpgme_get_offline(d->ctx); +} + +void Context::setIncludeCertificates(int which) +{ + if (which == DefaultCertificates) { + which = GPGME_INCLUDE_CERTS_DEFAULT; + } + gpgme_set_include_certs(d->ctx, which); +} + +int Context::includeCertificates() const +{ + return gpgme_get_include_certs(d->ctx); +} + +void Context::setKeyListMode(unsigned int mode) +{ + gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode)); +} + +void Context::addKeyListMode(unsigned int mode) +{ + const unsigned int cur = gpgme_get_keylist_mode(d->ctx); + gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode)); +} + +unsigned int Context::keyListMode() const +{ + return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx)); +} + +void Context::setProgressProvider(ProgressProvider *provider) +{ + gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider); +} +ProgressProvider *Context::progressProvider() const +{ + void *pp = 0; + gpgme_progress_cb_t pcb = &progress_callback; + gpgme_get_progress_cb(d->ctx, &pcb, &pp); + return static_cast<ProgressProvider *>(pp); +} + +void Context::setPassphraseProvider(PassphraseProvider *provider) +{ + gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider); +} + +PassphraseProvider *Context::passphraseProvider() const +{ + void *pp = 0; + gpgme_passphrase_cb_t pcb = &passphrase_callback; + gpgme_get_passphrase_cb(d->ctx, &pcb, &pp); + return static_cast<PassphraseProvider *>(pp); +} + +void Context::setManagedByEventLoopInteractor(bool manage) +{ + if (!EventLoopInteractor::instance()) { +#ifndef NDEBUG + cerr << "Context::setManagedByEventLoopInteractor(): " + "You must create an instance of EventLoopInteractor " + "before using anything that needs one." << endl; +#endif + return; + } + if (manage) { + EventLoopInteractor::instance()->manage(this); + } else { + EventLoopInteractor::instance()->unmanage(this); + } +} +bool Context::managedByEventLoopInteractor() const +{ + return d->iocbs != 0; +} + +void Context::installIOCallbacks(gpgme_io_cbs *iocbs) +{ + if (!iocbs) { + uninstallIOCallbacks(); + return; + } + gpgme_set_io_cbs(d->ctx, iocbs); + delete d->iocbs; d->iocbs = iocbs; +} + +void Context::uninstallIOCallbacks() +{ + static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 }; + // io.add == 0 means disable io callbacks: + gpgme_set_io_cbs(d->ctx, &noiocbs); + delete d->iocbs; d->iocbs = 0; +} + +Error Context::setLocale(int cat, const char *val) +{ + return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val)); +} + +EngineInfo Context::engineInfo() const +{ + return EngineInfo(gpgme_ctx_get_engine_info(d->ctx)); +} + +Error Context::setEngineFileName(const char *filename) +{ + const char *const home_dir = engineInfo().homeDirectory(); + return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir)); +} + +Error Context::setEngineHomeDirectory(const char *home_dir) +{ + const char *const filename = engineInfo().fileName(); + return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir)); +} + +// +// +// Key Management +// +// + +Error Context::startKeyListing(const char *pattern, bool secretOnly) +{ + d->lastop = Private::KeyList; + return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly))); +} + +Error Context::startKeyListing(const char *patterns[], bool secretOnly) +{ + d->lastop = Private::KeyList; +#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN + if (!patterns || !patterns[0] || !patterns[1]) { + // max. one pattern -> use the non-ext version + return startKeyListing(patterns ? patterns[0] : 0, secretOnly); + } +#endif + return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0)); +} + +Key Context::nextKey(GpgME::Error &e) +{ + d->lastop = Private::KeyList; + gpgme_key_t key; + e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key)); + return Key(key, false); +} + +KeyListResult Context::endKeyListing() +{ + d->lasterr = gpgme_op_keylist_end(d->ctx); + return keyListResult(); +} + +KeyListResult Context::keyListResult() const +{ + return KeyListResult(d->ctx, Error(d->lasterr)); +} + +Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/) +{ + d->lastop = Private::KeyList; + gpgme_key_t key; + e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/)); + return Key(key, false); +} + +KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey) +{ + d->lastop = Private::KeyGen; + Data::Private *const dp = pubKey.impl(); + d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0); + return KeyGenerationResult(d->ctx, Error(d->lasterr)); +} + +Error Context::startKeyGeneration(const char *parameters, Data &pubKey) +{ + d->lastop = Private::KeyGen; + Data::Private *const dp = pubKey.impl(); + return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0)); +} + +KeyGenerationResult Context::keyGenerationResult() const +{ + if (d->lastop & Private::KeyGen) { + return KeyGenerationResult(d->ctx, Error(d->lasterr)); + } else { + return KeyGenerationResult(); + } +} + +Error Context::exportPublicKeys(const char *pattern, Data &keyData) +{ + d->lastop = Private::Export; + Data::Private *const dp = keyData.impl(); + return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0)); +} + +Error Context::exportPublicKeys(const char *patterns[], Data &keyData) +{ + d->lastop = Private::Export; +#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN + if (!patterns || !patterns[0] || !patterns[1]) { + // max. one pattern -> use the non-ext version + return exportPublicKeys(patterns ? patterns[0] : 0, keyData); + } +#endif + Data::Private *const dp = keyData.impl(); + return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0)); +} + +Error Context::startPublicKeyExport(const char *pattern, Data &keyData) +{ + d->lastop = Private::Export; + Data::Private *const dp = keyData.impl(); + return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0)); +} + +Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) +{ + d->lastop = Private::Export; +#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN + if (!patterns || !patterns[0] || !patterns[1]) { + // max. one pattern -> use the non-ext version + return startPublicKeyExport(patterns ? patterns[0] : 0, keyData); + } +#endif + Data::Private *const dp = keyData.impl(); + return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0)); +} + +ImportResult Context::importKeys(const Data &data) +{ + d->lastop = Private::Import; + const Data::Private *const dp = data.impl(); + d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0); + return ImportResult(d->ctx, Error(d->lasterr)); +} + +ImportResult Context::importKeys(const std::vector<Key> &kk) +{ + d->lastop = Private::Import; + d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED); + + bool shouldHaveResult = false; + gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ]; + gpgme_key_t *keys_it = &keys[0]; + for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { + if (it->impl()) { + *keys_it++ = it->impl(); + } + } + *keys_it++ = 0; + d->lasterr = gpgme_op_import_keys(d->ctx, keys); + shouldHaveResult = true; + if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED || + gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) && + protocol() == CMS) { + // ok, try the workaround (export+import): + std::vector<const char *> fprs; + for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { + if (const char *fpr = it->primaryFingerprint()) { + if (*fpr) { + fprs.push_back(fpr); + } + } else if (const char *keyid = it->keyID()) { + if (*keyid) { + fprs.push_back(keyid); + } + } + } + fprs.push_back(0); + Data data; + Data::Private *const dp = data.impl(); + const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx); + gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN); + d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0); + gpgme_set_keylist_mode(d->ctx, oldMode); + if (!d->lasterr) { + data.seek(0, SEEK_SET); + d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0); + shouldHaveResult = true; + } + } + delete[] keys; + if (shouldHaveResult) { + return ImportResult(d->ctx, Error(d->lasterr)); + } else { + return ImportResult(Error(d->lasterr)); + } +} + +Error Context::startKeyImport(const Data &data) +{ + d->lastop = Private::Import; + const Data::Private *const dp = data.impl(); + return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0)); +} + +Error Context::startKeyImport(const std::vector<Key> &kk) +{ + d->lastop = Private::Import; + gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ]; + gpgme_key_t *keys_it = &keys[0]; + for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) { + if (it->impl()) { + *keys_it++ = it->impl(); + } + } + *keys_it++ = 0; + Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys)); + delete[] keys; + return err; +} + +ImportResult Context::importResult() const +{ + if (d->lastop & Private::Import) { + return ImportResult(d->ctx, Error(d->lasterr)); + } else { + return ImportResult(); + } +} + +Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion) +{ + d->lastop = Private::Delete; + return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion))); +} + +Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion) +{ + d->lastop = Private::Delete; + return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion))); +} + +Error Context::passwd(const Key &key) +{ + d->lastop = Private::Passwd; + return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U)); +} + +Error Context::startPasswd(const Key &key) +{ + d->lastop = Private::Passwd; + return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U)); +} + + +#pragma GCC push_diagnostics +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) +{ + d->lastop = Private::Edit; + d->lastEditInteractor = std::move(func); + Data::Private *const dp = data.impl(); + return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(), + d->lastEditInteractor.get() ? edit_interactor_callback : 0, + d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0, + dp ? dp->data : 0)); +} + + +Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) +{ + d->lastop = Private::Edit; + d->lastEditInteractor = std::move(func); + Data::Private *const dp = data.impl(); + return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(), + d->lastEditInteractor.get() ? edit_interactor_callback : 0, + d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0, + dp ? dp->data : 0)); +} + + +EditInteractor *Context::lastEditInteractor() const +{ + return d->lastEditInteractor.get(); +} + +std::unique_ptr<EditInteractor> Context::takeLastEditInteractor() +{ + return std::move(d->lastEditInteractor); +} + + +Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) +{ + d->lastop = Private::CardEdit; + d->lastCardEditInteractor = std::move(func); + Data::Private *const dp = data.impl(); + return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(), + d->lastCardEditInteractor.get() ? edit_interactor_callback : 0, + d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0, + dp ? dp->data : 0)); +} + +Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data) +{ + d->lastop = Private::CardEdit; + d->lastCardEditInteractor = std::move(func); + Data::Private *const dp = data.impl(); + return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(), + d->lastCardEditInteractor.get() ? edit_interactor_callback : 0, + d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0, + dp ? dp->data : 0)); +} + +#pragma GCC pop_diagnostics + +EditInteractor *Context::lastCardEditInteractor() const +{ + return d->lastCardEditInteractor.get(); +} + +std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor() +{ + return std::move(d->lastCardEditInteractor); +} + +Error Context::startTrustItemListing(const char *pattern, int maxLevel) +{ + d->lastop = Private::TrustList; + return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel)); +} + +TrustItem Context::nextTrustItem(Error &e) +{ + gpgme_trust_item_t ti = 0; + e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti)); + return TrustItem(ti); +} + +Error Context::endTrustItemListing() +{ + return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx)); +} + +static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen) +{ + assert(opaque); + AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque); + return t->data(static_cast<const char *>(data), datalen).encodedError(); +} + +static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data) +{ + assert(opaque); + Context::Private *p = static_cast<Context::Private *>(opaque); + AssuanTransaction *t = p->lastAssuanTransaction.get(); + assert(t); + Error err; + if (name) { + p->lastAssuanInquireData = t->inquire(name, args, err); + } else { + p->lastAssuanInquireData = Data::null; + } + if (!p->lastAssuanInquireData.isNull()) { + *r_data = p->lastAssuanInquireData.impl()->data; + } + return err.encodedError(); +} + +static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args) +{ + assert(opaque); + AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque); + std::string a = args; + percent_unescape(a, true); // ### why doesn't gpgme do this?? + return t->status(status, a.c_str()).encodedError(); +} + +Error Context::assuanTransact(const char *command) +{ + return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction)); +} + +Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction) +{ + gpgme_error_t err, operr; + + d->lastop = Private::AssuanTransact; + d->lastAssuanTransaction = std::move(transaction); + if (!d->lastAssuanTransaction.get()) { + return Error(d->lasterr = make_error(GPG_ERR_INV_ARG)); + } + err = gpgme_op_assuan_transact_ext + (d->ctx, + command, + assuan_transaction_data_callback, + d->lastAssuanTransaction.get(), + assuan_transaction_inquire_callback, + d, + assuan_transaction_status_callback, + d->lastAssuanTransaction.get(), + &operr); + + if (!err) + err = operr; + d->lasterr = err; + + return Error(d->lasterr); +} + +Error Context::startAssuanTransaction(const char *command) +{ + return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction)); +} + +Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction) +{ + gpgme_error_t err; + + d->lastop = Private::AssuanTransact; + d->lastAssuanTransaction = std::move(transaction); + if (!d->lastAssuanTransaction.get()) { + return Error(d->lasterr = make_error(GPG_ERR_INV_ARG)); + } + err = gpgme_op_assuan_transact_start + (d->ctx, + command, + assuan_transaction_data_callback, + d->lastAssuanTransaction.get(), + assuan_transaction_inquire_callback, + d, + assuan_transaction_status_callback, + d->lastAssuanTransaction.get()); + + d->lasterr = err; + + return Error(d->lasterr); +} + +AssuanTransaction *Context::lastAssuanTransaction() const +{ + return d->lastAssuanTransaction.get(); +} + +std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction() +{ + return std::move(d->lastAssuanTransaction); +} + +DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText) +{ + d->lastop = Private::Decrypt; + const Data::Private *const cdp = cipherText.impl(); + Data::Private *const pdp = plainText.impl(); + d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0); + return DecryptionResult(d->ctx, Error(d->lasterr)); +} + +Error Context::startDecryption(const Data &cipherText, Data &plainText) +{ + d->lastop = Private::Decrypt; + const Data::Private *const cdp = cipherText.impl(); + Data::Private *const pdp = plainText.impl(); + return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0)); +} + +DecryptionResult Context::decryptionResult() const +{ + if (d->lastop & Private::Decrypt) { + return DecryptionResult(d->ctx, Error(d->lasterr)); + } else { + return DecryptionResult(); + } +} + +VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText) +{ + d->lastop = Private::Verify; + const Data::Private *const sdp = signature.impl(); + const Data::Private *const tdp = signedText.impl(); + d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0); + return VerificationResult(d->ctx, Error(d->lasterr)); +} + +VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText) +{ + d->lastop = Private::Verify; + const Data::Private *const sdp = signedData.impl(); + Data::Private *const pdp = plainText.impl(); + d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0); + return VerificationResult(d->ctx, Error(d->lasterr)); +} + +Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText) +{ + d->lastop = Private::Verify; + const Data::Private *const sdp = signature.impl(); + const Data::Private *const tdp = signedText.impl(); + return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0)); +} + +Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText) +{ + d->lastop = Private::Verify; + const Data::Private *const sdp = signedData.impl(); + Data::Private *const pdp = plainText.impl(); + return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0)); +} + +VerificationResult Context::verificationResult() const +{ + if (d->lastop & Private::Verify) { + return VerificationResult(d->ctx, Error(d->lasterr)); + } else { + return VerificationResult(); + } +} + +std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText) +{ + d->lastop = Private::DecryptAndVerify; + const Data::Private *const cdp = cipherText.impl(); + Data::Private *const pdp = plainText.impl(); + d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0); + return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)), + VerificationResult(d->ctx, Error(d->lasterr))); +} + +Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText) +{ + d->lastop = Private::DecryptAndVerify; + const Data::Private *const cdp = cipherText.impl(); + Data::Private *const pdp = plainText.impl(); + return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0)); +} + +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; +} + +Error Context::startGetAuditLog(Data &output, unsigned int flags) +{ + d->lastop = Private::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))); +} + +Error Context::getAuditLog(Data &output, unsigned int flags) +{ + d->lastop = Private::GetAuditLog; + Data::Private *const odp = output.impl(); + return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags))); +} + +void Context::clearSigningKeys() +{ + gpgme_signers_clear(d->ctx); +} + +Error Context::addSigningKey(const Key &key) +{ + return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl())); +} + +Key Context::signingKey(unsigned int idx) const +{ + gpgme_key_t key = gpgme_signers_enum(d->ctx, idx); + return Key(key, false); +} + +std::vector<Key> Context::signingKeys() const +{ + std::vector<Key> result; + gpgme_key_t key; + for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) { + result.push_back(Key(key, false)); + } + return result; +} + +void Context::clearSignatureNotations() +{ + gpgme_sig_notation_clear(d->ctx); +} + +GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags) +{ + return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags))); +} + +GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical) +{ + return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0)); +} + +const char *Context::signaturePolicyURL() const +{ + for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { + if (!n->name) { + return n->value; + } + } +} + +Notation Context::signatureNotation(unsigned int idx) const +{ + for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { + if (n->name) { + if (idx-- == 0) { + return Notation(n); + } + } + } + return Notation(); +} + +std::vector<Notation> Context::signatureNotations() const +{ + std::vector<Notation> result; + for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) { + if (n->name) { + result.push_back(Notation(n)); + } + } + return result; +} + +static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode) +{ + switch (mode) { + default: + case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL; + case Detached: return GPGME_SIG_MODE_DETACH; + case Clearsigned: return GPGME_SIG_MODE_CLEAR; + } +} + +SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode) +{ + d->lastop = Private::Sign; + const Data::Private *const pdp = plainText.impl(); + Data::Private *const sdp = signature.impl(); + d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)); + return SigningResult(d->ctx, Error(d->lasterr)); +} + +Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode) +{ + d->lastop = Private::Sign; + const Data::Private *const pdp = plainText.impl(); + Data::Private *const sdp = signature.impl(); + return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode))); +} + +SigningResult Context::signingResult() const +{ + if (d->lastop & Private::Sign) { + return SigningResult(d->ctx, Error(d->lasterr)); + } else { + return SigningResult(); + } +} + +static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags) +{ + unsigned int result = 0; + if (flags & Context::AlwaysTrust) { + result |= GPGME_ENCRYPT_ALWAYS_TRUST; + } + if (flags & Context::NoEncryptTo) { + result |= GPGME_ENCRYPT_NO_ENCRYPT_TO; + } + if (flags & Context::Prepare) { + result |= GPGME_ENCRYPT_PREPARE; + } + if (flags & Context::ExpectSign) { + result |= GPGME_ENCRYPT_EXPECT_SIGN; + } + if (flags & Context::NoCompress) { + result |= GPGME_ENCRYPT_NO_COMPRESS; + } + if (flags & Context::Symmetric) { + result |= GPGME_ENCRYPT_SYMMETRIC; + } + return static_cast<gpgme_encrypt_flags_t>(result); +} + +gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients) +{ + if (recipients.empty()) { + return nullptr; + } + gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ]; + gpgme_key_t *keys_it = ret; + for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) { + if (it->impl()) { + *keys_it++ = it->impl(); + } + } + *keys_it++ = 0; + return ret; +} + +EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) +{ + d->lastop = Private::Encrypt; + if (flags & NoEncryptTo) { + return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED))); + } + const Data::Private *const pdp = plainText.impl(); + Data::Private *const cdp = cipherText.impl(); + gpgme_key_t *const keys = getKeysFromRecipients(recipients); + d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags), + pdp ? pdp->data : 0, cdp ? cdp->data : 0); + if (keys) { + delete[] keys; + } + return EncryptionResult(d->ctx, Error(d->lasterr)); +} + +Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText) +{ + d->lastop = Private::Encrypt; + const Data::Private *const pdp = plainText.impl(); + Data::Private *const cdp = cipherText.impl(); + return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0, + pdp ? pdp->data : 0, cdp ? cdp->data : 0)); +} + +Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) +{ + d->lastop = Private::Encrypt; + if (flags & NoEncryptTo) { + return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)); + } + const Data::Private *const pdp = plainText.impl(); + Data::Private *const cdp = cipherText.impl(); + gpgme_key_t *const keys = getKeysFromRecipients(recipients); + d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags), + pdp ? pdp->data : 0, cdp ? cdp->data : 0); + if (keys) { + delete[] keys; + } + return Error(d->lasterr); +} + +EncryptionResult Context::encryptionResult() const +{ + if (d->lastop & Private::Encrypt) { + return EncryptionResult(d->ctx, Error(d->lasterr)); + } else { + return EncryptionResult(); + } +} + +std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) +{ + d->lastop = Private::SignAndEncrypt; + const Data::Private *const pdp = plainText.impl(); + Data::Private *const cdp = cipherText.impl(); + gpgme_key_t *const keys = getKeysFromRecipients(recipients); + d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags), + pdp ? pdp->data : 0, cdp ? cdp->data : 0); + if (keys) { + delete[] keys; + } + return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)), + EncryptionResult(d->ctx, Error(d->lasterr))); +} + +Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags) +{ + d->lastop = Private::SignAndEncrypt; + const Data::Private *const pdp = plainText.impl(); + Data::Private *const cdp = cipherText.impl(); + gpgme_key_t *const keys = getKeysFromRecipients(recipients); + d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags), + pdp ? pdp->data : 0, cdp ? cdp->data : 0); + if (keys) { + delete[] keys; + } + return Error(d->lasterr); +} + +Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients) +{ + d->lastop = Private::CreateVFS; + gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ]; + gpgme_key_t *keys_it = keys; + for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) { + if (it->impl()) { + *keys_it++ = it->impl(); + } + } + *keys_it++ = 0; + + gpgme_error_t op_err; + d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err); + delete[] keys; + Error error(d->lasterr); + if (error) { + return error; + } + return Error(d->lasterr = op_err); +} + +VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir) +{ + d->lastop = Private::MountVFS; + gpgme_error_t op_err; + d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err); + return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err)); +} + +Error Context::cancelPendingOperation() +{ + return Error(gpgme_cancel_async(d->ctx)); +} + +bool Context::poll() +{ + gpgme_error_t e = GPG_ERR_NO_ERROR; + const bool finished = gpgme_wait(d->ctx, &e, 0); + if (finished) { + d->lasterr = e; + } + return finished; +} + +Error Context::wait() +{ + gpgme_error_t e = GPG_ERR_NO_ERROR; + gpgme_wait(d->ctx, &e, 1); + return Error(d->lasterr = e); +} + +Error Context::lastError() const +{ + return Error(d->lasterr); +} + +Context::PinentryMode Context::pinentryMode() const +{ + switch (gpgme_get_pinentry_mode (d->ctx)) { + case GPGME_PINENTRY_MODE_ASK: + return PinentryAsk; + case GPGME_PINENTRY_MODE_CANCEL: + return PinentryCancel; + case GPGME_PINENTRY_MODE_ERROR: + return PinentryError; + case GPGME_PINENTRY_MODE_LOOPBACK: + return PinentryLoopback; + case GPGME_PINENTRY_MODE_DEFAULT: + default: + return PinentryDefault; + } +} + +Error Context::setPinentryMode(PinentryMode which) +{ + gpgme_pinentry_mode_t mode; + switch (which) { + case PinentryAsk: + mode = GPGME_PINENTRY_MODE_ASK; + break; + case PinentryCancel: + mode = GPGME_PINENTRY_MODE_CANCEL; + break; + case PinentryError: + mode = GPGME_PINENTRY_MODE_ERROR; + break; + case PinentryLoopback: + mode = GPGME_PINENTRY_MODE_LOOPBACK; + break; + case PinentryDefault: + default: + mode = GPGME_PINENTRY_MODE_DEFAULT; + } + return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode)); +} + +static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy) +{ + switch (policy) { + case TofuInfo::PolicyNone: + return GPGME_TOFU_POLICY_NONE; + case TofuInfo::PolicyAuto: + return GPGME_TOFU_POLICY_AUTO; + case TofuInfo::PolicyGood: + return GPGME_TOFU_POLICY_GOOD; + case TofuInfo::PolicyBad: + return GPGME_TOFU_POLICY_BAD; + case TofuInfo::PolicyAsk: + return GPGME_TOFU_POLICY_ASK; + case TofuInfo::PolicyUnknown: + return GPGME_TOFU_POLICY_UNKNOWN; + } +} + +Error Context::setTofuPolicy(const Key &k, unsigned int policy) +{ + return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx, + k.impl(), to_tofu_policy_t(policy))); +} + +Error Context::setTofuPolicyStart(const Key &k, unsigned int policy) +{ + return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx, + k.impl(), to_tofu_policy_t(policy))); +} + +// Engine Spawn stuff +Error Context::spawn(const char *file, const char *argv[], + Data &input, Data &output, Data &err, + SpawnFlags flags) +{ + return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv, + input.impl() ? input.impl()->data : nullptr, + output.impl() ? output.impl()->data : nullptr, + err.impl() ? err.impl()->data : nullptr, + static_cast<int>(flags))); +} + +Error Context::spawnAsync(const char *file, const char *argv[], + Data &input, Data &output, Data &err, + SpawnFlags flags) +{ + return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv, + input.impl() ? input.impl()->data : nullptr, + output.impl() ? output.impl()->data : nullptr, + err.impl() ? err.impl()->data : nullptr, + static_cast<int>(flags))); +} + +std::ostream &operator<<(std::ostream &os, Protocol proto) +{ + os << "GpgME::Protocol("; + switch (proto) { + case OpenPGP: + os << "OpenPGP"; + break; + case CMS: + os << "CMS"; + break; + default: + case UnknownProtocol: + os << "UnknownProtocol"; + break; + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, Engine eng) +{ + os << "GpgME::Engine("; + switch (eng) { + case GpgEngine: + os << "GpgEngine"; + break; + case GpgSMEngine: + os << "GpgSMEngine"; + break; + case GpgConfEngine: + os << "GpgConfEngine"; + break; + case AssuanEngine: + os << "AssuanEngine"; + break; + case SpawnEngine: + os << "SpawnEngine"; + break; + default: + case UnknownEngine: + os << "UnknownEngine"; + break; + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl) +{ + os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl); + switch (incl) { + case Context::DefaultCertificates: + os << "(DefaultCertificates)"; + break; + case Context::AllCertificatesExceptRoot: + os << "(AllCertificatesExceptRoot)"; + break; + case Context::AllCertificates: + os << "(AllCertificates)"; + break; + case Context::NoCertificates: + os << "(NoCertificates)"; + break; + case Context::OnlySenderCertificate: + os << "(OnlySenderCertificate)"; + break; + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, KeyListMode mode) +{ + os << "GpgME::KeyListMode("; +#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0) + CHECK(Local); + CHECK(Extern); + CHECK(Signatures); + CHECK(Validate); + CHECK(Ephemeral); + CHECK(WithTofu); +#undef CHECK + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, SignatureMode mode) +{ + os << "GpgME::SignatureMode("; + switch (mode) { +#define CHECK( x ) case x: os << #x; break + CHECK(NormalSignatureMode); + CHECK(Detached); + CHECK(Clearsigned); +#undef CHECK + default: + os << "???" "(" << static_cast<int>(mode) << ')'; + break; + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags) +{ + os << "GpgME::Context::EncryptionFlags("; +#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) + CHECK(AlwaysTrust); + CHECK(NoEncryptTo); + CHECK(Prepare); + CHECK(ExpectSign); + CHECK(NoCompress); + CHECK(Symmetric); +#undef CHECK + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags) +{ + os << "GpgME::Context::AuditLogFlags("; +#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) + CHECK(HtmlAuditLog); + CHECK(AuditLogWithHelp); +#undef CHECK + return os << ')'; +} + +} // namespace GpgME + +GpgME::Error GpgME::setDefaultLocale(int cat, const char *val) +{ + return Error(gpgme_set_locale(0, cat, val)); +} + +GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto) +{ + gpgme_engine_info_t ei = 0; + if (gpgme_get_engine_info(&ei)) { + return EngineInfo(); + } + + const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; + + for (gpgme_engine_info_t i = ei ; i ; i = i->next) { + if (i->protocol == p) { + return EngineInfo(i); + } + } + + return EngineInfo(); +} + +const char *GpgME::dirInfo(const char *what) +{ + return gpgme_get_dirinfo(what); +} + +GpgME::Error GpgME::checkEngine(GpgME::Protocol proto) +{ + const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; + + return Error(gpgme_engine_check_version(p)); +} + +static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255); + +static gpgme_protocol_t engine2protocol(const GpgME::Engine engine) +{ + switch (engine) { + case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP; + case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS; + case GpgME::GpgConfEngine: + return GPGME_PROTOCOL_GPGCONF; + case GpgME::AssuanEngine: + return GPGME_PROTOCOL_ASSUAN; + case GpgME::G13Engine: + return GPGME_PROTOCOL_G13; + case GpgME::SpawnEngine: + return GPGME_PROTOCOL_SPAWN; + case GpgME::UnknownEngine: + ; + } + return UNKNOWN_PROTOCOL; +} + +GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine) +{ + gpgme_engine_info_t ei = 0; + if (gpgme_get_engine_info(&ei)) { + return EngineInfo(); + } + + const gpgme_protocol_t p = engine2protocol(engine); + + for (gpgme_engine_info_t i = ei ; i ; i = i->next) { + if (i->protocol == p) { + return EngineInfo(i); + } + } + + return EngineInfo(); +} + +GpgME::Error GpgME::checkEngine(GpgME::Engine engine) +{ + const gpgme_protocol_t p = engine2protocol(engine); + + return Error(gpgme_engine_check_version(p)); +} + +static const unsigned long supported_features = 0 + | GpgME::ValidatingKeylistModeFeature + | GpgME::CancelOperationFeature + | GpgME::WrongKeyUsageFeature + | GpgME::DefaultCertificateInclusionFeature + | GpgME::GetSetEngineInfoFeature + | GpgME::ClearAddGetSignatureNotationsFeature + | GpgME::SetDataFileNameFeeature + | GpgME::SignatureNotationsKeylistModeFeature + | GpgME::KeySignatureNotationsFeature + | GpgME::KeyIsQualifiedFeature + | GpgME::SignatureNotationsCriticalFlagFeature + | GpgME::SignatureNotationsFlagsFeature + | GpgME::SignatureNotationsHumanReadableFlagFeature + | GpgME::SubkeyIsQualifiedFeature + | GpgME::EngineInfoHomeDirFeature + | GpgME::DecryptionResultFileNameFeature + | GpgME::DecryptionResultRecipientsFeature + | GpgME::VerificationResultFileNameFeature + | GpgME::SignaturePkaFieldsFeature + | GpgME::SignatureAlgorithmFieldsFeature + | GpgME::FdPointerFeature + | GpgME::AuditLogFeature + | GpgME::GpgConfEngineFeature + | GpgME::CancelOperationAsyncFeature + | GpgME::NoEncryptToEncryptionFlagFeature + | GpgME::CardKeyFeature + | GpgME::AssuanEngineFeature + | GpgME::EphemeralKeylistModeFeature + | GpgME::ImportFromKeyserverFeature + | GpgME::G13VFSFeature + | GpgME::PasswdFeature + ; + +static const unsigned long supported_features2 = 0 + | GpgME::BinaryAndFineGrainedIdentify + ; + +bool GpgME::hasFeature(unsigned long features) +{ + return features == (features & supported_features); +} + +bool GpgME::hasFeature(unsigned long features, unsigned long features2) +{ + return features == (features & supported_features) + && features2 == (features2 & supported_features2) + ; +} diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h new file mode 100644 index 0000000..b1e4f5f --- /dev/null +++ b/lang/cpp/src/context.h @@ -0,0 +1,420 @@ +/* + context.h - wraps a gpgme key context + Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_CONTEXT_H__ +#define __GPGMEPP_CONTEXT_H__ + +#include "global.h" + +#include "error.h" +#include "verificationresult.h" // for Signature::Notation + +#include <memory> +#include <vector> +#include <utility> +#include <iosfwd> + +namespace GpgME +{ + +class Key; +class Data; +class TrustItem; +class ProgressProvider; +class PassphraseProvider; +class EventLoopInteractor; +class EditInteractor; +class AssuanTransaction; + +class KeyListResult; +class KeyGenerationResult; +class ImportResult; +class DecryptionResult; +class VerificationResult; +class SigningResult; +class EncryptionResult; +class VfsMountResult; + +class EngineInfo; + +class GPGMEPP_EXPORT Context +{ + explicit Context(gpgme_ctx_t); +public: + //using GpgME::Protocol; + + // + // Creation and destruction: + // + + static Context *createForProtocol(Protocol proto); + static std::unique_ptr<Context> createForEngine(Engine engine, Error *err = 0); + virtual ~Context(); + + // + // Context Attributes + // + + Protocol protocol() const; + + void setArmor(bool useArmor); + bool armor() const; + + void setTextMode(bool useTextMode); + bool textMode() const; + + void setOffline(bool useOfflineMode); + bool offline() const; + + enum CertificateInclusion { + DefaultCertificates = -256, + AllCertificatesExceptRoot = -2, + AllCertificates = -1, + NoCertificates = 0, + OnlySenderCertificate = 1 + }; + void setIncludeCertificates(int which); + int includeCertificates() const; + + //using GpgME::KeyListMode; + void setKeyListMode(unsigned int keyListMode); + void addKeyListMode(unsigned int keyListMode); + unsigned int keyListMode() const; + + /** Set the passphrase provider + * + * To avoid problems where a class using a context registers + * itself as the provider the Context does not take ownership + * of the provider and the caller must ensure that the provider + * is deleted if it is no longer needed. + */ + void setPassphraseProvider(PassphraseProvider *provider); + PassphraseProvider *passphraseProvider() const; + + /** Set the progress provider + * + * To avoid problems where a class using a context registers + * itself as the provider the Context does not take ownership + * of the provider and the caller must ensure that the provider + * is deleted if it is no longer needed. + */ + void setProgressProvider(ProgressProvider *provider); + ProgressProvider *progressProvider() const; + + void setManagedByEventLoopInteractor(bool managed); + bool managedByEventLoopInteractor() const; + + GpgME::Error setLocale(int category, const char *value); + + EngineInfo engineInfo() const; + GpgME::Error setEngineFileName(const char *filename); + GpgME::Error setEngineHomeDirectory(const char *filename); + + enum PinentryMode{ + PinentryDefault = 0, + PinentryAsk = 1, + PinentryCancel = 2, + PinentryError = 3, + PinentryLoopback = 4 + }; + GpgME::Error setPinentryMode(PinentryMode which); + PinentryMode pinentryMode() const; + +private: + friend class ::GpgME::EventLoopInteractor; + void installIOCallbacks(gpgme_io_cbs *iocbs); + void uninstallIOCallbacks(); + +public: + // + // + // Key Management + // + // + + // + // Key Listing + // + + GpgME::Error startKeyListing(const char *pattern = 0, bool secretOnly = false); + GpgME::Error startKeyListing(const char *patterns[], bool secretOnly = false); + + Key nextKey(GpgME::Error &e); + + KeyListResult endKeyListing(); + KeyListResult keyListResult() const; + + Key key(const char *fingerprint, GpgME::Error &e, bool secret = false); + + // + // Key Generation + // + + KeyGenerationResult generateKey(const char *parameters, Data &pubKey); + GpgME::Error startKeyGeneration(const char *parameters, Data &pubkey); + KeyGenerationResult keyGenerationResult() const; + + // + // Key Export + // + + GpgME::Error exportPublicKeys(const char *pattern, Data &keyData); + GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData); + GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData); + GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData); + + // + // Key Import + // + + ImportResult importKeys(const Data &data); + ImportResult importKeys(const std::vector<Key> &keys); + GpgME::Error startKeyImport(const Data &data); + GpgME::Error startKeyImport(const std::vector<Key> &keys); + ImportResult importResult() const; + + // + // Key Deletion + // + + GpgME::Error deleteKey(const Key &key, bool allowSecretKeyDeletion = false); + GpgME::Error startKeyDeletion(const Key &key, bool allowSecretKeyDeletion = false); + + // + // Passphrase changing + // + + GpgME::Error passwd(const Key &key); + GpgME::Error startPasswd(const Key &key); + + // + // Key Editing + // + + GpgME::Error edit(const Key &key, std::unique_ptr<EditInteractor> function, Data &out); + GpgME::Error startEditing(const Key &key, std::unique_ptr<EditInteractor> function, Data &out); + + // using TofuInfo::Policy + Error setTofuPolicy(const Key &k, unsigned int policy); + Error setTofuPolicyStart(const Key &k, unsigned int policy); + + EditInteractor *lastEditInteractor() const; + std::unique_ptr<EditInteractor> takeLastEditInteractor(); + + // + // SmartCard Editing + // + + GpgME::Error cardEdit(const Key &key, std::unique_ptr<EditInteractor> function, Data &out); + GpgME::Error startCardEditing(const Key &key, std::unique_ptr<EditInteractor> function, Data &out); + + EditInteractor *lastCardEditInteractor() const; + std::unique_ptr<EditInteractor> takeLastCardEditInteractor(); + + // + // Trust Item Management + // + + GpgME::Error startTrustItemListing(const char *pattern, int maxLevel); + TrustItem nextTrustItem(GpgME::Error &e); + GpgME::Error endTrustItemListing(); + + // + // Assuan Transactions + // + + GpgME::Error assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction); + GpgME::Error assuanTransact(const char *command); + GpgME::Error startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction); + GpgME::Error startAssuanTransaction(const char *command); + + AssuanTransaction *lastAssuanTransaction() const; + std::unique_ptr<AssuanTransaction> takeLastAssuanTransaction(); + + // + // + // Crypto Operations + // + // + + // + // Decryption + // + + DecryptionResult decrypt(const Data &cipherText, Data &plainText); + GpgME::Error startDecryption(const Data &cipherText, Data &plainText); + DecryptionResult decryptionResult() const; + + // + // Signature Verification + // + + VerificationResult verifyDetachedSignature(const Data &signature, const Data &signedText); + VerificationResult verifyOpaqueSignature(const Data &signedData, Data &plainText); + GpgME::Error startDetachedSignatureVerification(const Data &signature, const Data &signedText); + GpgME::Error startOpaqueSignatureVerification(const Data &signedData, Data &plainText); + VerificationResult verificationResult() const; + + // + // Combined Decryption and Signature Verification + // + + std::pair<DecryptionResult, VerificationResult> decryptAndVerify(const Data &cipherText, Data &plainText); + GpgME::Error startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText); + // use verificationResult() and decryptionResult() to retrieve the result objects... + + // + // Signing + // + + void clearSigningKeys(); + GpgME::Error addSigningKey(const Key &signer); + Key signingKey(unsigned int index) const; + std::vector<Key> signingKeys() const; + + void clearSignatureNotations(); + GpgME::Error addSignatureNotation(const char *name, const char *value, unsigned int flags = 0); + GpgME::Error addSignaturePolicyURL(const char *url, bool critical = false); + const char *signaturePolicyURL() const; + Notation signatureNotation(unsigned int index) const; + std::vector<Notation> signatureNotations() const; + + //using GpgME::SignatureMode; + SigningResult sign(const Data &plainText, Data &signature, SignatureMode mode); + GpgME::Error startSigning(const Data &plainText, Data &signature, SignatureMode mode); + SigningResult signingResult() const; + + // + // Encryption + // + + enum EncryptionFlags { + None = 0, + AlwaysTrust = 1, + NoEncryptTo = 2, + Prepare = 4, + ExpectSign = 8, + NoCompress = 16, + Symmetric = 32 + }; + EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); + GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText); + GpgME::Error startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); + EncryptionResult encryptionResult() const; + + // + // Combined Signing and Encryption + // + + std::pair<SigningResult, EncryptionResult> signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); + GpgME::Error startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); + // use encryptionResult() and signingResult() to retrieve the result objects... + + // + // + // Audit Log + // + // + enum AuditLogFlags { + HtmlAuditLog = 1, + AuditLogWithHelp = 128 + }; + GpgME::Error startGetAuditLog(Data &output, unsigned int flags = 0); + GpgME::Error getAuditLog(Data &output, unsigned int flags = 0); + + // + // + // G13 crypto container operations + // + // + GpgME::Error createVFS(const char *containerFile, const std::vector<Key> &recipients); + VfsMountResult mountVFS(const char *containerFile, const char *mountDir); + + // Spawn Engine + enum SpawnFlags { + SpawnNone = 0, + SpawnDetached = 1, + SpawnAllowSetFg = 2 + }; + /** Spwan the process \a file with arguments \a argv. + * + * If a data parameter is null the /dev/null will be + * used. (Or other platform stuff). + * + * @param file The executable to start. + * @param argv list of arguments file should be argv[0]. + * @param input The data to be sent through stdin. + * @param output The data to be recieve the stdout. + * @param err The data to recieve stderr. + * @param flags Additional flags. + * + * @returns An error or empty error. + */ + GpgME::Error spawn(const char *file, const char *argv[], + Data &input, Data &output, Data &err, + SpawnFlags flags); + /** Async variant of spawn. Immediately returns after starting the + * process. */ + GpgME::Error spawnAsync(const char *file, const char *argv[], + Data &input, Data &output, + Data &err, SpawnFlags flags); + // + // + // Run Control + // + // + + bool poll(); + GpgME::Error wait(); + GpgME::Error lastError() const; + GpgME::Error cancelPendingOperation(); + + class Private; + const Private *impl() const + { + return d; + } + Private *impl() + { + return d; + } +private: + // Helper functions that need to be context because they rely + // on the "Friendlyness" of context to access the gpgme types. + gpgme_key_t *getKeysFromRecipients(const std::vector<Key> &recipients); + +private: + Private *const d; + +private: // disable... + Context(const Context &); + const Context &operator=(const Context &); +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags); + +} // namespace GpgME + +#endif // __GPGMEPP_CONTEXT_H__ diff --git a/lang/cpp/src/context_p.h b/lang/cpp/src/context_p.h new file mode 100644 index 0000000..be34783 --- /dev/null +++ b/lang/cpp/src/context_p.h @@ -0,0 +1,84 @@ +/* + context_p.h - wraps a gpgme context (private part) + Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_CONTEXT_P_H__ +#define __GPGMEPP_CONTEXT_P_H__ + +#include <context.h> +#include <data.h> + +#include <gpgme.h> + +namespace GpgME +{ + +class Context::Private +{ +public: + enum Operation { + None = 0, + + Encrypt = 0x001, + Decrypt = 0x002, + Sign = 0x004, + Verify = 0x008, + DecryptAndVerify = Decrypt | Verify, + SignAndEncrypt = Sign | Encrypt, + + Import = 0x010, + Export = 0x020, // no gpgme_export_result_t, but nevertheless... + Delete = 0x040, // no gpgme_delete_result_t, but nevertheless... + + KeyGen = 0x080, + KeyList = 0x100, + TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless... + + Edit = 0x400, // no gpgme_edit_result_t, but nevertheless... + CardEdit = 0x800, // no gpgme_card_edit_result_t, but nevertheless... + + GetAuditLog = 0x1000, // no gpgme_getauditlog_result_t, but nevertheless... + + AssuanTransact = 0x2000, + Passwd = 0x4000, // no gpgme_passwd_result_t, but nevertheless... + + CreateVFS = 0x4000, + MountVFS = 0x8000, + + EndMarker + }; + + Private(gpgme_ctx_t c = 0); + ~Private(); + + gpgme_ctx_t ctx; + gpgme_io_cbs *iocbs; + Operation lastop; + gpgme_error_t lasterr; + Data lastAssuanInquireData; + std::unique_ptr<AssuanTransaction> lastAssuanTransaction; + std::unique_ptr<EditInteractor> lastEditInteractor, lastCardEditInteractor; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_CONTEXT_P_H__ diff --git a/lang/cpp/src/context_vanilla.cpp b/lang/cpp/src/context_vanilla.cpp new file mode 100644 index 0000000..984d41b --- /dev/null +++ b/lang/cpp/src/context_vanilla.cpp @@ -0,0 +1,33 @@ +/* + context_vanilla.cpp - wraps a gpgme key context, gpgme (vanilla)-specific functions + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <global.h> + +GIOChannel *GpgME::getGIOChannel(int) +{ + return 0; +} + +QIODevice *GpgME::getQIODevice(int) +{ + return 0; +} diff --git a/lang/cpp/src/data.cpp b/lang/cpp/src/data.cpp new file mode 100644 index 0000000..9527b2f --- /dev/null +++ b/lang/cpp/src/data.cpp @@ -0,0 +1,222 @@ +/* + data.cpp - wraps a gpgme data object + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "data_p.h" +#include <error.h> +#include <interfaces/dataprovider.h> + +#include <gpgme.h> + +#ifndef NDEBUG +#include <iostream> +#endif + +GpgME::Data::Private::~Private() +{ + if (data) { + gpgme_data_release(data); + } +} + +const GpgME::Data::Null GpgME::Data::null; + +GpgME::Data::Data() +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new(&data); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(const Null &) + : d(new Private(0)) +{ + +} + +GpgME::Data::Data(gpgme_data_t data) + : d(new Private(data)) +{ + +} + +GpgME::Data::Data(const char *buffer, size_t size, bool copy) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_mem(&data, buffer, size, int(copy)); + std::string sizestr = std::to_string(size); + // Ignore errors as this is optional + gpgme_data_set_flag(data, "size-hint", sizestr.c_str()); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(const char *filename) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new(&data); + d.reset(new Private(e ? 0 : data)); + if (!e) { + setFileName(filename); + } +} + +GpgME::Data::Data(const char *filename, off_t offset, size_t length) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_filepart(&data, filename, 0, offset, length); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(FILE *fp) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_stream(&data, fp); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(FILE *fp, off_t offset, size_t length) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_filepart(&data, 0, fp, offset, length); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(int fd) +{ + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_fd(&data, fd); + d.reset(new Private(e ? 0 : data)); +} + +GpgME::Data::Data(DataProvider *dp) +{ + d.reset(new Private); + if (!dp) { + return; + } + if (!dp->isSupported(DataProvider::Read)) { + d->cbs.read = 0; + } + if (!dp->isSupported(DataProvider::Write)) { + d->cbs.write = 0; + } + if (!dp->isSupported(DataProvider::Seek)) { + d->cbs.seek = 0; + } + if (!dp->isSupported(DataProvider::Release)) { + d->cbs.release = 0; + } + const gpgme_error_t e = gpgme_data_new_from_cbs(&d->data, &d->cbs, dp); + if (e) { + d->data = 0; + } + if (dp->isSupported(DataProvider::Seek)) { + off_t size = seek(0, SEEK_END); + seek(0, SEEK_SET); + std::string sizestr = std::to_string(size); + // Ignore errors as this is optional + gpgme_data_set_flag(d->data, "size-hint", sizestr.c_str()); + } +#ifndef NDEBUG + //std::cerr << "GpgME::Data(): DataProvider supports: " + // << ( d->cbs.read ? "read" : "no read" ) << ", " + // << ( d->cbs.write ? "write" : "no write" ) << ", " + // << ( d->cbs.seek ? "seek" : "no seek" ) << ", " + // << ( d->cbs.release ? "release" : "no release" ) << std::endl; +#endif +} + +bool GpgME::Data::isNull() const +{ + return !d || !d->data; +} + +GpgME::Data::Encoding GpgME::Data::encoding() const +{ + switch (gpgme_data_get_encoding(d->data)) { + case GPGME_DATA_ENCODING_NONE: return AutoEncoding; + case GPGME_DATA_ENCODING_BINARY: return BinaryEncoding; + case GPGME_DATA_ENCODING_BASE64: return Base64Encoding; + case GPGME_DATA_ENCODING_ARMOR: return ArmorEncoding; + case GPGME_DATA_ENCODING_MIME: return MimeEncoding; + } + return AutoEncoding; +} + +GpgME::Error GpgME::Data::setEncoding(Encoding enc) +{ + gpgme_data_encoding_t ge = GPGME_DATA_ENCODING_NONE; + switch (enc) { + case AutoEncoding: ge = GPGME_DATA_ENCODING_NONE; break; + case BinaryEncoding: ge = GPGME_DATA_ENCODING_BINARY; break; + case Base64Encoding: ge = GPGME_DATA_ENCODING_BASE64; break; + case ArmorEncoding: ge = GPGME_DATA_ENCODING_ARMOR; break; + case MimeEncoding: ge = GPGME_DATA_ENCODING_MIME; break; + } + return Error(gpgme_data_set_encoding(d->data, ge)); +} + +GpgME::Data::Type GpgME::Data::type() const +{ + if (isNull()) { + return Invalid; + } + switch (gpgme_data_identify(d->data, 0)) { + case GPGME_DATA_TYPE_INVALID: return Invalid; + case GPGME_DATA_TYPE_UNKNOWN: return Unknown; + case GPGME_DATA_TYPE_PGP_SIGNED: return PGPSigned; + case GPGME_DATA_TYPE_PGP_OTHER: return PGPOther; + case GPGME_DATA_TYPE_PGP_KEY: return PGPKey; + case GPGME_DATA_TYPE_CMS_SIGNED: return CMSSigned; + case GPGME_DATA_TYPE_CMS_ENCRYPTED: return CMSEncrypted; + case GPGME_DATA_TYPE_CMS_OTHER: return CMSOther; + case GPGME_DATA_TYPE_X509_CERT: return X509Cert; + case GPGME_DATA_TYPE_PKCS12: return PKCS12; + case GPGME_DATA_TYPE_PGP_ENCRYPTED: return PGPEncrypted; + case GPGME_DATA_TYPE_PGP_SIGNATURE: return PGPSignature; + } + return Invalid; +} + +char *GpgME::Data::fileName() const +{ + return gpgme_data_get_file_name(d->data); +} + +GpgME::Error GpgME::Data::setFileName(const char *name) +{ + return Error(gpgme_data_set_file_name(d->data, name)); +} + +ssize_t GpgME::Data::read(void *buffer, size_t length) +{ + return gpgme_data_read(d->data, buffer, length); +} + +ssize_t GpgME::Data::write(const void *buffer, size_t length) +{ + return gpgme_data_write(d->data, buffer, length); +} + +off_t GpgME::Data::seek(off_t offset, int whence) +{ + return gpgme_data_seek(d->data, offset, whence); +} diff --git a/lang/cpp/src/data.h b/lang/cpp/src/data.h new file mode 100644 index 0000000..b2f2173 --- /dev/null +++ b/lang/cpp/src/data.h @@ -0,0 +1,126 @@ +/* + data.h - wraps a gpgme data object + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_DATA_H__ +#define __GPGMEPP_DATA_H__ + +#include "global.h" + +#include <sys/types.h> // for size_t, off_t +#include <cstdio> // FILE +#include <algorithm> +#include <memory> + +namespace GpgME +{ + +class DataProvider; +class Error; + +class GPGMEPP_EXPORT Data +{ + struct Null { + Null() {} + }; +public: + /* implicit */ Data(const Null &); + Data(); + explicit Data(gpgme_data_t data); + + // Memory-Based Data Buffers: + Data(const char *buffer, size_t size, bool copy = true); + explicit Data(const char *filename); + Data(const char *filename, off_t offset, size_t length); + Data(std::FILE *fp, off_t offset, size_t length); + // File-Based Data Buffers: + explicit Data(std::FILE *fp); + explicit Data(int fd); + // Callback-Based Data Buffers: + explicit Data(DataProvider *provider); + + static const Null null; + + const Data &operator=(Data other) + { + swap(other); + return *this; + } + + void swap(Data &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + enum Encoding { + AutoEncoding, + BinaryEncoding, + Base64Encoding, + ArmorEncoding, + MimeEncoding + }; + Encoding encoding() const; + Error setEncoding(Encoding encoding); + + enum Type { + Invalid, + Unknown, + PGPSigned, + PGPOther, + PGPKey, + CMSSigned, + CMSEncrypted, + CMSOther, + X509Cert, + PKCS12, + PGPEncrypted, + PGPSignature, + }; + Type type() const; + + char *fileName() const; + Error setFileName(const char *name); + + ssize_t read(void *buffer, size_t length); + ssize_t write(const void *buffer, size_t length); + off_t seek(off_t offset, int whence); + + class Private; + Private *impl() + { + return d.get(); + } + const Private *impl() const + { + return d.get(); + } +private: + std::shared_ptr<Private> d; +}; + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Data) + +#endif // __GPGMEPP_DATA_H__ diff --git a/lang/cpp/src/data_p.h b/lang/cpp/src/data_p.h new file mode 100644 index 0000000..38ba55a --- /dev/null +++ b/lang/cpp/src/data_p.h @@ -0,0 +1,40 @@ +/* + data_p.h - wraps a gpgme data object, private part -*- c++ -*- + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_DATA_P_H__ +#define __GPGMEPP_DATA_P_H__ + +#include <data.h> +#include "callbacks.h" + +class GpgME::Data::Private +{ +public: + explicit Private(gpgme_data_t d = 0) + : data(d), cbs(data_provider_callbacks) {} + ~Private(); + + gpgme_data_t data; + gpgme_data_cbs cbs; +}; + +#endif // __GPGMEPP_DATA_P_H__ diff --git a/lang/cpp/src/decryptionresult.cpp b/lang/cpp/src/decryptionresult.cpp new file mode 100644 index 0000000..78a2b1b --- /dev/null +++ b/lang/cpp/src/decryptionresult.cpp @@ -0,0 +1,240 @@ +/* + decryptionresult.cpp - wraps a gpgme keygen result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <decryptionresult.h> +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <algorithm> +#include <iterator> +#include <cstring> +#include <cstdlib> +#include <istream> + +#include <string.h> + +class GpgME::DecryptionResult::Private +{ +public: + explicit Private(const _gpgme_op_decrypt_result &r) : res(r) + { + if (res.unsupported_algorithm) { + res.unsupported_algorithm = strdup(res.unsupported_algorithm); + } + if (res.file_name) { + res.file_name = strdup(res.file_name); + } + //FIXME: copying gpgme_recipient_t objects invalidates the keyid member, + //thus we use _keyid for now (internal API) + for (gpgme_recipient_t r = res.recipients ; r ; r = r->next) { + recipients.push_back(*r); + } + res.recipients = 0; + } + ~Private() + { + if (res.unsupported_algorithm) { + std::free(res.unsupported_algorithm); + } + res.unsupported_algorithm = 0; + if (res.file_name) { + std::free(res.file_name); + } + res.file_name = 0; + } + + _gpgme_op_decrypt_result res; + std::vector<_gpgme_recipient> recipients; +}; + +GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::DecryptionResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx); + if (!res) { + return; + } + d.reset(new Private(*res)); +} + +make_standard_stuff(DecryptionResult) + +const char *GpgME::DecryptionResult::unsupportedAlgorithm() const +{ + return d ? d->res.unsupported_algorithm : 0 ; +} + +bool GpgME::DecryptionResult::isWrongKeyUsage() const +{ + return d && d->res.wrong_key_usage; +} + +const char *GpgME::DecryptionResult::fileName() const +{ + return d ? d->res.file_name : 0 ; +} + +unsigned int GpgME::DecryptionResult::numRecipients() const +{ + return d ? d->recipients.size() : 0 ; +} + +GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient(unsigned int idx) const +{ + if (d && idx < d->recipients.size()) { + return Recipient(&d->recipients[idx]); + } + return Recipient(); +} + +namespace +{ +struct make_recipient { + GpgME::DecryptionResult::Recipient operator()(_gpgme_recipient &t) + { + return GpgME::DecryptionResult::Recipient(&t); + } +}; +} + +std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const +{ + std::vector<Recipient> result; + if (d) { + result.reserve(d->recipients.size()); + std::transform(d->recipients.begin(), d->recipients.end(), + std::back_inserter(result), + make_recipient()); + } + return result; +} + +class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient +{ +public: + Private(gpgme_recipient_t reci) : _gpgme_recipient(*reci) {} +}; + +GpgME::DecryptionResult::Recipient::Recipient() + : d() +{ + +} + +GpgME::DecryptionResult::Recipient::Recipient(gpgme_recipient_t r) + : d() +{ + if (r) { + d.reset(new Private(r)); + } +} + +bool GpgME::DecryptionResult::Recipient::isNull() const +{ + return !d; +} + +const char *GpgME::DecryptionResult::Recipient::keyID() const +{ + //_keyid is internal API, but the public keyid is invalid after copying (see above) + if (d) { + return d->_keyid; + } + return 0; +} + +const char *GpgME::DecryptionResult::Recipient::shortKeyID() const +{ + //_keyid is internal API, but the public keyid is invalid after copying (see above) + if (d) { + return d->_keyid + 8; + } + return 0; +} + +unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const +{ + if (d) { + return d->pubkey_algo; + } + return 0; +} + +const char *GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const +{ + if (d) { + return gpgme_pubkey_algo_name(d->pubkey_algo); + } + return 0; +} + +GpgME::Error GpgME::DecryptionResult::Recipient::status() const +{ + if (d) { + return Error(d->status); + } + return Error(); +} + +std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result) +{ + os << "GpgME::DecryptionResult("; + if (!result.isNull()) { + os << "\n error: " << result.error() + << "\n fileName: " << protect(result.fileName()) + << "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm()) + << "\n isWrongKeyUsage: " << result.isWrongKeyUsage() + << "\n recipients:\n"; + const std::vector<DecryptionResult::Recipient> recipients = result.recipients(); + std::copy(recipients.begin(), recipients.end(), + std::ostream_iterator<DecryptionResult::Recipient>(os, "\n")); + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult::Recipient &reci) +{ + os << "GpgME::DecryptionResult::Recipient("; + if (!reci.isNull()) { + os << "\n keyID: " << protect(reci.keyID()) + << "\n shortKeyID: " << protect(reci.shortKeyID()) + << "\n publicKeyAlgorithm: " << protect(reci.publicKeyAlgorithmAsString()) + << "\n status: " << reci.status(); + } + return os << ')'; +} diff --git a/lang/cpp/src/decryptionresult.h b/lang/cpp/src/decryptionresult.h new file mode 100644 index 0000000..60b78d9 --- /dev/null +++ b/lang/cpp/src/decryptionresult.h @@ -0,0 +1,130 @@ +/* + decryptionresult.h - wraps a gpgme keygen result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_DECRYPTIONRESULT_H__ +#define __GPGMEPP_DECRYPTIONRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <vector> +#include <algorithm> +#include <iosfwd> +#include <memory> + +namespace GpgME +{ + +class Error; + +class GPGMEPP_EXPORT DecryptionResult : public Result +{ +public: + DecryptionResult(); + DecryptionResult(gpgme_ctx_t ctx, int error); + DecryptionResult(gpgme_ctx_t ctx, const Error &err); + explicit DecryptionResult(const Error &err); + + const DecryptionResult &operator=(DecryptionResult other) + { + swap(other); + return *this; + } + + void swap(DecryptionResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + GPGMEPP_DEPRECATED const char *unsupportedAlgortihm() const + { + return unsupportedAlgorithm(); + } + const char *unsupportedAlgorithm() const; + + GPGMEPP_DEPRECATED bool wrongKeyUsage() const + { + return isWrongKeyUsage(); + } + bool isWrongKeyUsage() const; + + const char *fileName() const; + + class Recipient; + + unsigned int numRecipients() const; + Recipient recipient(unsigned int idx) const; + std::vector<Recipient> recipients() const; + +private: + class Private; + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult &result); + +class GPGMEPP_EXPORT DecryptionResult::Recipient +{ +public: + Recipient(); + explicit Recipient(gpgme_recipient_t reci); + + const Recipient &operator=(Recipient other) + { + swap(other); + return *this; + } + + void swap(Recipient &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + const char *keyID() const; + const char *shortKeyID() const; + + unsigned int publicKeyAlgorithm() const; + const char *publicKeyAlgorithmAsString() const; + + Error status() const; + +private: + class Private; + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult::Recipient &reci); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(DecryptionResult) + +#endif // __GPGMEPP_DECRYPTIONRESULT_H__ diff --git a/lang/cpp/src/defaultassuantransaction.cpp b/lang/cpp/src/defaultassuantransaction.cpp new file mode 100644 index 0000000..5bcf970 --- /dev/null +++ b/lang/cpp/src/defaultassuantransaction.cpp @@ -0,0 +1,78 @@ +/* + defaultassuantransaction.cpp - default Assuan Transaction that just stores data and status lines + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "defaultassuantransaction.h" +#include "error.h" +#include "data.h" + +#include <sstream> + +using namespace GpgME; + +DefaultAssuanTransaction::DefaultAssuanTransaction() + : AssuanTransaction(), + m_status(), + m_data() +{ + +} + +DefaultAssuanTransaction::~DefaultAssuanTransaction() {} + +Error DefaultAssuanTransaction::data(const char *data, size_t len) +{ + m_data.append(data, len); + return Error(); +} + +Data DefaultAssuanTransaction::inquire(const char *name, const char *args, Error &err) +{ + (void)name; (void)args; (void)err; + return Data::null; +} + +Error DefaultAssuanTransaction::status(const char *status, const char *args) +{ + m_status.push_back(std::pair<std::string, std::string>(status, args)); + return Error(); +} + +std::vector<std::string> DefaultAssuanTransaction::statusLine(const char *tag) const +{ + std::vector<std::string> result; + for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) { + if (it->first == tag) { + result.push_back(it->second); + } + } + return result; +} + +std::string DefaultAssuanTransaction::firstStatusLine(const char *tag) const +{ + for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) { + if (it->first == tag) { + return it->second; + } + } + return std::string(); +} diff --git a/lang/cpp/src/defaultassuantransaction.h b/lang/cpp/src/defaultassuantransaction.h new file mode 100644 index 0000000..bf4b839 --- /dev/null +++ b/lang/cpp/src/defaultassuantransaction.h @@ -0,0 +1,65 @@ +/* + defaultassuantransaction.h - default Assuan Transaction that just stores data and status lines + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__ +#define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__ + +#include <interfaces/assuantransaction.h> + +#include <string> +#include <vector> +#include <utility> + +namespace GpgME +{ + +class GPGMEPP_EXPORT DefaultAssuanTransaction : public AssuanTransaction +{ +public: + explicit DefaultAssuanTransaction(); + ~DefaultAssuanTransaction(); + + const std::vector< std::pair<std::string, std::string> > &statusLines() const + { + return m_status; + } + std::vector<std::string> statusLine(const char *tag) const; + std::string firstStatusLine(const char *tag) const; + + const std::string &data() const + { + return m_data; + } + +private: + /* reimp */ Error data(const char *data, size_t datalen); + /* reimp */ Data inquire(const char *name, const char *args, Error &err); + /* reimp */ Error status(const char *status, const char *args); + +private: + std::vector< std::pair<std::string, std::string> > m_status; + std::string m_data; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_DEFAULTASSUANTRANSACTION_H__ diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp new file mode 100644 index 0000000..07dc26d --- /dev/null +++ b/lang/cpp/src/editinteractor.cpp @@ -0,0 +1,339 @@ +/* + editinteractor.cpp - Interface for edit interactors + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "editinteractor.h" +#include "callbacks.h" +#include "error.h" + +#include <gpgme.h> + +#ifdef _WIN32 +# include <io.h> +#include <windows.h> +#else +# include <unistd.h> +#endif + +#include <cerrno> +#include <cstring> + +#ifndef GPG_ERR_ALREADY_SIGNED +# define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1 +#endif + +using namespace GpgME; + +static const char *status_to_string(unsigned int status); +static Error status_to_error(unsigned int status); + +class EditInteractor::Private +{ + friend class ::GpgME::EditInteractor; + friend class ::GpgME::CallbackHelper; + EditInteractor *const q; +public: + explicit Private(EditInteractor *qq); + ~Private(); + +private: + unsigned int state; + Error error; + std::FILE *debug; +}; + +class GpgME::CallbackHelper +{ +private: + static int writeAll(int fd, const void *buf, size_t count) + { + size_t toWrite = count; + while (toWrite > 0) { + const int n = gpgme_io_write(fd, buf, toWrite); + if (n < 0) { + return n; + } + toWrite -= n; + } + return count; + } + +public: + static int edit_interactor_callback_impl(void *opaque, gpgme_status_code_t status, const char *args, int fd) + { + EditInteractor::Private *ei = (EditInteractor::Private *)opaque; + + Error err = status_to_error(status); + + if (!err) { + + // advance to next state based on input: + const unsigned int oldState = ei->state; + ei->state = ei->q->nextState(status, args, err); + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n", + oldState, status_to_string(status), args ? args : "<null>", ei->state); + } + if (err) { + ei->state = oldState; + goto error; + } + + if (ei->state != oldState && + // if there was an error from before, we stop here (### this looks weird, can this happen at all?) + ei->error.code() == GPG_ERR_NO_ERROR) { + + // successful state change -> call action + if (const char *const result = ei->q->action(err)) { + if (err) { + goto error; + } + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: action result \"%s\"\n", result); + } + // if there's a result, write it: + if (*result) { + gpgme_err_set_errno(0); + const ssize_t len = std::strlen(result); + if (writeAll(fd, result, len) != len) { + err = Error::fromSystemError(); + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString()); + } + goto error; + } + } + gpgme_err_set_errno(0); + if (writeAll(fd, "\n", 1) != 1) { + err = Error::fromSystemError(); + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString()); + } + goto error; + } + } else { + if (err) { + goto error; + } + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: no action result\n"); + } + } + } else { + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: no action executed\n"); + } + } + } + + error: + if (err) { + ei->error = err; + ei->state = EditInteractor::ErrorState; + } + + if (ei->debug) { + std::fprintf(ei->debug, "EditInteractor: error now %u (%s)\n", + ei->error.encodedError(), gpgme_strerror(ei->error.encodedError())); + } + + return ei->error.encodedError(); + } +}; + +static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t status, const char *args, int fd) +{ + return CallbackHelper::edit_interactor_callback_impl(opaque, status, args, fd); +} + +const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback; + +EditInteractor::Private::Private(EditInteractor *qq) + : q(qq), + state(StartState), + error(), + debug(0) +{ + +} + +EditInteractor::Private::~Private() {} + +EditInteractor::EditInteractor() + : d(new Private(this)) +{ + +} + +EditInteractor::~EditInteractor() +{ + delete d; +} + +unsigned int EditInteractor::state() const +{ + return d->state; +} + +Error EditInteractor::lastError() const +{ + return d->error; +} + +bool EditInteractor::needsNoResponse(unsigned int status) const +{ + switch (status) { + case GPGME_STATUS_ALREADY_SIGNED: + case GPGME_STATUS_ERROR: + case GPGME_STATUS_GET_BOOL: + case GPGME_STATUS_GET_LINE: + case GPGME_STATUS_KEY_CREATED: + case GPGME_STATUS_NEED_PASSPHRASE_SYM: + case GPGME_STATUS_SC_OP_FAILURE: + return false; + default: + return true; + } +} + +// static +Error status_to_error(unsigned int status) +{ + switch (status) { + case GPGME_STATUS_MISSING_PASSPHRASE: + return Error::fromCode(GPG_ERR_NO_PASSPHRASE); + case GPGME_STATUS_ALREADY_SIGNED: + return Error::fromCode(GPG_ERR_ALREADY_SIGNED); + case GPGME_STATUS_SIGEXPIRED: + return Error::fromCode(GPG_ERR_SIG_EXPIRED); + } + return Error(); +} + +void EditInteractor::setDebugChannel(std::FILE *debug) +{ + d->debug = debug; +} + +static const char *const status_strings[] = { + "EOF", + /* mkstatus processing starts here */ + "ENTER", + "LEAVE", + "ABORT", + + "GOODSIG", + "BADSIG", + "ERRSIG", + + "BADARMOR", + + "RSA_OR_IDEA", + "KEYEXPIRED", + "KEYREVOKED", + + "TRUST_UNDEFINED", + "TRUST_NEVER", + "TRUST_MARGINAL", + "TRUST_FULLY", + "TRUST_ULTIMATE", + + "SHM_INFO", + "SHM_GET", + "SHM_GET_BOOL", + "SHM_GET_HIDDEN", + + "NEED_PASSPHRASE", + "VALIDSIG", + "SIG_ID", + "ENC_TO", + "NODATA", + "BAD_PASSPHRASE", + "NO_PUBKEY", + "NO_SECKEY", + "NEED_PASSPHRASE_SYM", + "DECRYPTION_FAILED", + "DECRYPTION_OKAY", + "MISSING_PASSPHRASE", + "GOOD_PASSPHRASE", + "GOODMDC", + "BADMDC", + "ERRMDC", + "IMPORTED", + "IMPORT_OK", + "IMPORT_PROBLEM", + "IMPORT_RES", + "FILE_START", + "FILE_DONE", + "FILE_ERROR", + + "BEGIN_DECRYPTION", + "END_DECRYPTION", + "BEGIN_ENCRYPTION", + "END_ENCRYPTION", + + "DELETE_PROBLEM", + "GET_BOOL", + "GET_LINE", + "GET_HIDDEN", + "GOT_IT", + "PROGRESS", + "SIG_CREATED", + "SESSION_KEY", + "NOTATION_NAME", + "NOTATION_DATA", + "POLICY_URL", + "BEGIN_STREAM", + "END_STREAM", + "KEY_CREATED", + "USERID_HINT", + "UNEXPECTED", + "INV_RECP", + "NO_RECP", + "ALREADY_SIGNED", + "SIGEXPIRED", + "EXPSIG", + "EXPKEYSIG", + "TRUNCATED", + "ERROR", + "NEWSIG", + "REVKEYSIG", + "SIG_SUBPACKET", + "NEED_PASSPHRASE_PIN", + "SC_OP_FAILURE", + "SC_OP_SUCCESS", + "CARDCTRL", + "BACKUP_KEY_CREATED", + "PKA_TRUST_BAD", + "PKA_TRUST_GOOD", + + "PLAINTEXT", +}; +static const unsigned int num_status_strings = sizeof status_strings / sizeof * status_strings ; + +const char *status_to_string(unsigned int idx) +{ + if (idx < num_status_strings) { + return status_strings[idx]; + } else { + return "(unknown)"; + } +} diff --git a/lang/cpp/src/editinteractor.h b/lang/cpp/src/editinteractor.h new file mode 100644 index 0000000..2122052 --- /dev/null +++ b/lang/cpp/src/editinteractor.h @@ -0,0 +1,68 @@ +/* + editinteractor.h - Interface for edit interactors + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_EDITINTERACTOR_H__ +#define __GPGMEPP_EDITINTERACTOR_H__ + +#include "gpgmepp_export.h" + +#include <cstdio> + +namespace GpgME +{ + +class Error; +class Context; +class CallbackHelper; + +class GPGMEPP_EXPORT EditInteractor +{ + friend class ::GpgME::Context; + friend class ::GpgME::CallbackHelper; + EditInteractor(const EditInteractor &); + EditInteractor &operator=(const EditInteractor &); +public: + EditInteractor(); + virtual ~EditInteractor(); + + enum { + StartState = 0, + ErrorState = 0xFFFFFFFF + }; + + virtual const char *action(Error &err) const = 0; + virtual unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const = 0; + + unsigned int state() const; + Error lastError() const; + bool needsNoResponse(unsigned int statusCode) const; + + void setDebugChannel(std::FILE *file); + +private: + class Private; + Private *const d; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_EDITINTERACTOR_H__ diff --git a/lang/cpp/src/encryptionresult.cpp b/lang/cpp/src/encryptionresult.cpp new file mode 100644 index 0000000..c4e7df5 --- /dev/null +++ b/lang/cpp/src/encryptionresult.cpp @@ -0,0 +1,159 @@ +/* + encryptionresult.cpp - wraps a gpgme verify result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <encryptionresult.h> +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> +#include <istream> +#include <algorithm> +#include <iterator> + +#include <string.h> + +class GpgME::EncryptionResult::Private +{ +public: + explicit Private(const gpgme_encrypt_result_t r) + { + if (!r) { + return; + } + for (gpgme_invalid_key_t ik = r->invalid_recipients ; ik ; ik = ik->next) { + gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik); + if (ik->fpr) { + copy->fpr = strdup(ik->fpr); + } + copy->next = 0; + invalid.push_back(copy); + } + } + ~Private() + { + for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) { + std::free((*it)->fpr); + delete *it; *it = 0; + } + } + + std::vector<gpgme_invalid_key_t> invalid; +}; + +GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::EncryptionResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_encrypt_result_t res = gpgme_op_encrypt_result(ctx); + if (!res) { + return; + } + d.reset(new Private(res)); +} + +make_standard_stuff(EncryptionResult) + +unsigned int GpgME::EncryptionResult::numInvalidRecipients() const +{ + return d ? d->invalid.size() : 0 ; +} + +GpgME::InvalidRecipient GpgME::EncryptionResult::invalidEncryptionKey(unsigned int idx) const +{ + return InvalidRecipient(d, idx); +} + +std::vector<GpgME::InvalidRecipient> GpgME::EncryptionResult::invalidEncryptionKeys() const +{ + if (!d) { + return std::vector<GpgME::InvalidRecipient>(); + } + std::vector<GpgME::InvalidRecipient> result; + result.reserve(d->invalid.size()); + for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) { + result.push_back(InvalidRecipient(d, i)); + } + return result; +} + +GpgME::InvalidRecipient::InvalidRecipient(const std::shared_ptr<EncryptionResult::Private> &parent, unsigned int i) + : d(parent), idx(i) +{ + +} + +GpgME::InvalidRecipient::InvalidRecipient() : d(), idx(0) {} + +bool GpgME::InvalidRecipient::isNull() const +{ + return !d || idx >= d->invalid.size() ; +} + +const char *GpgME::InvalidRecipient::fingerprint() const +{ + return isNull() ? 0 : d->invalid[idx]->fpr ; +} + +GpgME::Error GpgME::InvalidRecipient::reason() const +{ + return Error(isNull() ? 0 : d->invalid[idx]->reason); +} + +std::ostream &GpgME::operator<<(std::ostream &os, const EncryptionResult &result) +{ + os << "GpgME::EncryptionResult("; + if (!result.isNull()) { + os << "\n error: " << result.error() + << "\n invalid recipients:\n"; + const std::vector<InvalidRecipient> ir = result.invalidEncryptionKeys(); + std::copy(ir.begin(), ir.end(), + std::ostream_iterator<InvalidRecipient>(os, "\n")); + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const InvalidRecipient &ir) +{ + os << "GpgME::InvalidRecipient("; + if (!ir.isNull()) { + os << "\n fingerprint: " << protect(ir.fingerprint()) + << "\n reason: " << ir.reason() + << '\n'; + } + return os << ')'; +} diff --git a/lang/cpp/src/encryptionresult.h b/lang/cpp/src/encryptionresult.h new file mode 100644 index 0000000..edc400f --- /dev/null +++ b/lang/cpp/src/encryptionresult.h @@ -0,0 +1,113 @@ +/* + encryptionresult.h - wraps a gpgme sign result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_ENCRYPTIONRESULT_H__ +#define __GPGMEPP_ENCRYPTIONRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <memory> + +#include <vector> +#include <iosfwd> + +namespace GpgME +{ + +class Error; +class InvalidRecipient; + +class GPGMEPP_EXPORT EncryptionResult : public Result +{ +public: + EncryptionResult(); + EncryptionResult(gpgme_ctx_t ctx, int error); + EncryptionResult(gpgme_ctx_t ctx, const Error &error); + EncryptionResult(const Error &err); + + const EncryptionResult &operator=(EncryptionResult other) + { + swap(other); + return *this; + } + + void swap(EncryptionResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + unsigned int numInvalidRecipients() const; + + InvalidRecipient invalidEncryptionKey(unsigned int index) const; + std::vector<InvalidRecipient> invalidEncryptionKeys() const; + + class Private; +private: + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const EncryptionResult &result); + +class GPGMEPP_EXPORT InvalidRecipient +{ + friend class ::GpgME::EncryptionResult; + InvalidRecipient(const std::shared_ptr<EncryptionResult::Private> &parent, unsigned int index); +public: + InvalidRecipient(); + + const InvalidRecipient &operator=(InvalidRecipient other) + { + swap(other); + return *this; + } + + void swap(InvalidRecipient &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + const char *fingerprint() const; + Error reason() const; + +private: + std::shared_ptr<EncryptionResult::Private> d; + unsigned int idx; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidRecipient &recipient); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EncryptionResult) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidRecipient) + +#endif // __GPGMEPP_ENCRYPTIONRESULT_H__ diff --git a/lang/cpp/src/engineinfo.cpp b/lang/cpp/src/engineinfo.cpp new file mode 100644 index 0000000..c3b3e04 --- /dev/null +++ b/lang/cpp/src/engineinfo.cpp @@ -0,0 +1,88 @@ +/* + engineinfo.h + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "engineinfo.h" + +#include <gpgme.h> + +class GpgME::EngineInfo::Private +{ +public: + Private(gpgme_engine_info_t engine = 0) : info(engine) {} + ~Private() + { + info = 0; + } + + gpgme_engine_info_t info; +}; + +GpgME::EngineInfo::EngineInfo() : d() {} + +GpgME::EngineInfo::EngineInfo(gpgme_engine_info_t engine) + : d(new Private(engine)) +{ + +} + +bool GpgME::EngineInfo::isNull() const +{ + return !d || !d->info; +} + +GpgME::Protocol GpgME::EngineInfo::protocol() const +{ + if (isNull()) { + return UnknownProtocol; + } + switch (d->info->protocol) { + case GPGME_PROTOCOL_OpenPGP: return OpenPGP; + case GPGME_PROTOCOL_CMS: return CMS; + default: + return UnknownProtocol; + } +} + +const char *GpgME::EngineInfo::fileName() const +{ + return isNull() ? 0 : d->info->file_name; +} + +const char *GpgME::EngineInfo::version() const +{ + return isNull() ? 0 : d->info->version; +} + +GpgME::EngineInfo::Version GpgME::EngineInfo::engineVersion() const +{ + return Version(version()); +} + +const char *GpgME::EngineInfo::requiredVersion() const +{ + return isNull() ? 0 : d->info->req_version; +} + +const char *GpgME::EngineInfo::homeDirectory() const +{ + return isNull() ? 0 : d->info->home_dir; +} diff --git a/lang/cpp/src/engineinfo.h b/lang/cpp/src/engineinfo.h new file mode 100644 index 0000000..72e125c --- /dev/null +++ b/lang/cpp/src/engineinfo.h @@ -0,0 +1,126 @@ +/* + engineinfo.h + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_ENGINEINFO_H__ +#define __GPGMEPP_ENGINEINFO_H__ + +#include "global.h" + +#include <memory> + +#include <algorithm> +#include <string> +#include <iostream> + +namespace GpgME +{ + +class GPGMEPP_EXPORT EngineInfo +{ +public: + struct Version + { + int major, minor, patch; + + Version(const std::string& version) + { + if (version.empty() || + std::sscanf(version.c_str(), "%d.%d.%d", &major, &minor, &patch) != 3) { + major = 0; + minor = 0; + patch = 0; + } + } + + bool operator < (const Version& other) + { + if (major < other.major) + return true; + if (minor < other.minor) + return true; + if (patch < other.patch) + return true; + return false; + } + + bool operator < (const char* other) + { + return operator<(Version(other)); + } + + bool operator == (const Version& other) + { + return major == other.major + && minor == other.minor + && patch == other.patch; + } + + bool operator == (const char* other) + { + return operator==(Version(other)); + } + + friend std::ostream& operator << (std::ostream& stream, const Version& ver) + { + stream << ver.major; + stream << '.'; + stream << ver.minor; + stream << '.'; + stream << ver.patch; + return stream; + } + }; + + EngineInfo(); + explicit EngineInfo(gpgme_engine_info_t engine); + + const EngineInfo &operator=(EngineInfo other) + { + swap(other); + return *this; + } + + void swap(EngineInfo &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + Protocol protocol() const; + const char *fileName() const; + const char *version() const; + Version engineVersion() const; + const char *requiredVersion() const; + const char *homeDirectory() const; + +private: + class Private; + std::shared_ptr<Private> d; +}; + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EngineInfo) + +#endif // __GPGMEPP_ENGINEINFO_H__ diff --git a/lang/cpp/src/error.h b/lang/cpp/src/error.h new file mode 100644 index 0000000..009fe20 --- /dev/null +++ b/lang/cpp/src/error.h @@ -0,0 +1,78 @@ +/* + error.h - wraps a gpgme error + Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_ERROR_H__ +#define __GPGMEPP_ERROR_H__ + +#include "global.h" + +#include <string> +#include <iosfwd> + +#include <gpg-error.h> + +#ifndef GPGMEPP_ERR_SOURCE_DEFAULT +# define GPGMEPP_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1 +#endif + +namespace GpgME +{ + +class GPGMEPP_EXPORT Error +{ +public: + Error() : mErr(0), mMessage() {} + explicit Error(unsigned int e) : mErr(e), mMessage() {} + + const char *source() const; + const char *asString() const; + + int code() const; + int sourceID() const; + + bool isCanceled() const; + + unsigned int encodedError() const + { + return mErr; + } + int toErrno() const; + + static bool hasSystemError(); + static Error fromSystemError(unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); + static void setSystemError(gpg_err_code_t err); + static void setErrno(int err); + static Error fromErrno(int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); + static Error fromCode(unsigned int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT); + + GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(mErr &&!isCanceled()) +private: + unsigned int mErr; + mutable std::string mMessage; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Error &err); + +} // namespace GpgME + +#endif /* __GPGMEPP_ERROR_H__ */ diff --git a/lang/cpp/src/eventloopinteractor.cpp b/lang/cpp/src/eventloopinteractor.cpp new file mode 100644 index 0000000..7ec258c --- /dev/null +++ b/lang/cpp/src/eventloopinteractor.cpp @@ -0,0 +1,199 @@ +/* + eventloopinteractor.cpp + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <eventloopinteractor.h> + +#include <context.h> +#include "context_p.h" +#include <key.h> +#include <trustitem.h> + +#include <gpgme.h> + +#include <vector> +using std::vector; +#ifndef NDEBUG +# include <iostream> +#endif +#include <cassert> + +namespace GpgME +{ + +// +// EventLoopInteractor::Private Declaration +// + +class EventLoopInteractor::Private +{ +public: + struct OneFD { + OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc, + void *aFncData, void *aExternalTag) + : fd(aFd), dir(aDir), fnc(aFnc), + fncData(aFncData), externalTag(aExternalTag) {} + int fd; + int dir; + gpgme_io_cb_t fnc; + void *fncData; + void *externalTag; + }; + + vector<OneFD *> mCallbacks; + + static void removeIOCb(void *tag); + static gpgme_error_t registerIOCb(void *data, int fd, int dir, + gpgme_io_cb_t fnc, void *fnc_data, + void **r_tag); + static void eventIOCb(void *, gpgme_event_io_t type, void *type_data); + + static const gpgme_io_cbs iocbs; +}; + +const gpgme_io_cbs EventLoopInteractor::Private::iocbs = { + &EventLoopInteractor::Private::registerIOCb, + 0, + &EventLoopInteractor::Private::removeIOCb, + &EventLoopInteractor::Private::eventIOCb, + 0 +}; + +// +// EventLoopInteractor::Private IO Callback Implementations +// + +gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir, + gpgme_io_cb_t fnc, void *fnc_data, + void **r_tag) +{ + assert(instance()); assert(instance()->d); + bool ok = false; + void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok); + if (!ok) { + return gpgme_error(GPG_ERR_GENERAL); + } + instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag)); + if (r_tag) { + *r_tag = instance()->d->mCallbacks.back(); + } + return GPG_ERR_NO_ERROR; +} + +void EventLoopInteractor::Private::removeIOCb(void *tag) +{ + + if (!instance() || !instance()->d) { + return; + } + for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin(); + it != instance()->d->mCallbacks.end() ; ++it) { + if (*it == tag) { + instance()->unregisterWatcher((*it)->externalTag); + delete *it; *it = 0; + instance()->d->mCallbacks.erase(it); + return; + } + } +} + +void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data) +{ + assert(instance()); + Context *ctx = static_cast<Context *>(data); + switch (type) { + case GPGME_EVENT_START: { + instance()->operationStartEvent(ctx); + // TODO: what's in type_data? + } + break; + case GPGME_EVENT_DONE: { + gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data); + if (ctx && ctx->impl()) { + ctx->impl()->lasterr = e; + } + instance()->operationDoneEvent(ctx, Error(e)); + } + break; + case GPGME_EVENT_NEXT_KEY: { + gpgme_key_t key = static_cast<gpgme_key_t>(type_data); + instance()->nextKeyEvent(ctx, Key(key, false)); + } + break; + case GPGME_EVENT_NEXT_TRUSTITEM: { + gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data); + instance()->nextTrustItemEvent(ctx, TrustItem(item)); + gpgme_trust_item_unref(item); + } + break; + default: // warn + ; + } +} + +// +// EventLoopInteractor Implementation +// + +EventLoopInteractor *EventLoopInteractor::mSelf = 0; + +EventLoopInteractor::EventLoopInteractor() : d(new Private) +{ + assert(!mSelf); + mSelf = this; +} + +EventLoopInteractor::~EventLoopInteractor() +{ + // warn if there are still callbacks registered + mSelf = 0; + delete d; +} + +void EventLoopInteractor::manage(Context *context) +{ + if (!context || context->managedByEventLoopInteractor()) { + return; + } + gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs); + iocbs->event_priv = context; + context->installIOCallbacks(iocbs); +} + +void EventLoopInteractor::unmanage(Context *context) +{ + if (context) { + context->uninstallIOCallbacks(); + } +} + +void EventLoopInteractor::actOn(int fd, Direction dir) +{ + for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin(); + it != d->mCallbacks.end() ; ++it) { + if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) { + (*((*it)->fnc))((*it)->fncData, fd); + break; + } + } +} + +} // namespace GpgME diff --git a/lang/cpp/src/eventloopinteractor.h b/lang/cpp/src/eventloopinteractor.h new file mode 100644 index 0000000..94821d6 --- /dev/null +++ b/lang/cpp/src/eventloopinteractor.h @@ -0,0 +1,156 @@ +/* + eventloopinteractor.h + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_EVENTLOOPINTERACTOR_H__ +#define __GPGMEPP_EVENTLOOPINTERACTOR_H__ + +#include "gpgmepp_export.h" + +namespace GpgME +{ + +class Context; +class Error; +class TrustItem; +class Key; + +/*! \file eventloopinteractor.h + \brief Abstract base class for gpgme's external event loop support + + This class does most of the work involved with hooking GpgME++ + up with external event loops, such as the GTK or Qt ones. + + It actually provides two interfaces: An interface to the gpgme + IO Callback handling and one for gpgme events. The IO Callback + interface consists of the three methods \c actOn(), \c + registerWatcher() and \c unregisterWatcher(). The event + interface consists of the three methods \c nextTrustItemEvent(), + \c nextKeyEvent() and \c operationDoneEvent(). + + \sect General Usage + + \c EventLoopInteractor is designed to be used as a + singleton. However, in order to make any use of it, you have to + subclass it and reimplement it's pure virtual methods (see + below). We suggest you keep the constructor protected and + provide a static \c instance() method that returns the single + instance. Alternatively, you can create an instance on the + stack, e.g. in \c main(). + + If you want \c EventLoopInteractor to manage a particular \c + Context, just call \c manage() on the \c Context. OTOH, if you + want to disable IO callbacks for a \c Context, use \c unmanage(). + + \sect IO Callback Interface + + One part of this interface is represented by \c + registerWatcher() and \c unregisterWatcher(), both of which are + pure virtual. \c registerWatcher() should do anything necessary + to hook up watching of file descriptor \c fd for reading (\c dir + = \c Read) or writing (\c dir = Write) to the event loop you use + and return a tag identifying that particular watching process + uniquely. This could be the index into an array of objects you + use for that purpose or the address of such an object. E.g. in + Qt, you'd essentially just create a new \c QSocketNotifier: + + \verbatim + void * registerWatcher( int fd, Direction dir ) { + return new QSocketNotifier( fd, dir == Read ? QSocketNotifier::Read : QSocketNotifier::Write ); + // misses connecting to the activated() signal... + } + \endverbatim + + which uses the address of the created object as unique tag. The + tag returned by \c registerWatcher is stored by \c + EventLoopInteractor and passed as argument to \c + unregisterWatcher(). So, in the picture above, you'd implement \c + unregisterWatcher() like this: + + \verbatim + void unregisterWatcher( void * tag ) { + delete static_cast<QSocketNotifier*>( tag ); + } + \endverbatim + + The other part of the IO callback interface is \c actOn(), which + you should call if you receive notification from your event loop + about activity on file descriptor \c fd in direction \c dir. In + the picture above, you'd call this from the slot connected to + the socket notifier's \c activated() signal. + + \note \c registerWatcher() as well as \c unregisterWatcher() may + be called from within \c actOn(), so be careful with + e.g. locking in threaded environments and keep in mind that the + object you used to find the \c fd and \c dir fo the \c actOn() + call might be deleted when \c actOn() returns! + + \sect Event Handler Interface + +*/ +class GPGMEPP_EXPORT EventLoopInteractor +{ +protected: + EventLoopInteractor(); +public: + virtual ~EventLoopInteractor(); + + static EventLoopInteractor *instance() + { + return mSelf; + } + + void manage(Context *context); + void unmanage(Context *context); + + enum Direction { Read, Write }; +protected: + // + // IO Notification Interface + // + + /** Call this if your event loop detected activity on file + descriptor fd, with direction dir */ + void actOn(int fd, Direction dir); + + virtual void *registerWatcher(int fd, Direction dir, bool &ok) = 0; + virtual void unregisterWatcher(void *tag) = 0; + + // + // Event Handler Interface + // + + virtual void operationStartEvent(Context *context) = 0; + virtual void nextTrustItemEvent(Context *context, const TrustItem &item) = 0; + virtual void nextKeyEvent(Context *context, const Key &key) = 0; + virtual void operationDoneEvent(Context *context, const Error &e) = 0; + +private: + class Private; + friend class Private; + Private *const d; + static EventLoopInteractor *mSelf; +}; + +} + +#endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__ diff --git a/lang/cpp/src/exception.cpp b/lang/cpp/src/exception.cpp new file mode 100644 index 0000000..c687024 --- /dev/null +++ b/lang/cpp/src/exception.cpp @@ -0,0 +1,58 @@ +/* + exception.cpp - exception wrapping a gpgme error + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#include "exception.h" + +#include <gpgme.h> + +#include <sstream> + +using namespace GpgME; +using namespace std; // only safe b/c it's so small a file! + +Exception::~Exception() throw() {} + +// static +string Exception::make_message(const Error &err, const string &msg) +{ + return make_message(err, msg, NoOptions); +} + +// static +string Exception::make_message(const Error &err, const string &msg, Options opt) +{ + if (opt & MessageOnly) { + return msg; + } + char error_string[128]; + error_string[0] = '\0'; + gpgme_strerror_r(err.encodedError(), error_string, sizeof error_string); + error_string[sizeof error_string - 1] = '\0'; + stringstream ss; + ss << gpgme_strsource(err.encodedError()) << ": "; + if (!msg.empty()) { + ss << msg << ": "; + } + ss << error_string << " (" << static_cast<unsigned long>(err.encodedError()) << ')'; + return ss.str(); +} diff --git a/lang/cpp/src/exception.h b/lang/cpp/src/exception.h new file mode 100644 index 0000000..8f40b0e --- /dev/null +++ b/lang/cpp/src/exception.h @@ -0,0 +1,68 @@ +/* + exception.h - exception wrapping a gpgme error + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_EXCEPTION_H__ +#define __GPGMEPP_EXCEPTION_H__ + +#include "error.h" + +#include <stdexcept> +#include <string> + +namespace GpgME +{ + +class GPGMEPP_EXPORT Exception : public std::runtime_error +{ +public: + enum Options { + NoOptions = 0x0, + MessageOnly = 0x1, + + AllOptions = MessageOnly + }; + + explicit Exception(const GpgME::Error &err, const std::string &msg = std::string(), Options opt = NoOptions) + : std::runtime_error(make_message(err, msg, opt)), m_error(err), m_message(msg) {} + + ~Exception() throw(); + + Error error() const + { + return m_error; + } + const std::string &message() const + { + return m_message; + } +private: + static std::string make_message(const GpgME::Error &err, const std::string &msg); + static std::string make_message(const GpgME::Error &err, const std::string &msg, Options opt); +private: + const GpgME::Error m_error; + const std::string m_message; +}; + +} // namespace GpgME + +#endif /* __GPGMEPP_EXCEPTION_H__ */ diff --git a/lang/cpp/src/global.h b/lang/cpp/src/global.h new file mode 100644 index 0000000..15cc027 --- /dev/null +++ b/lang/cpp/src/global.h @@ -0,0 +1,218 @@ +/* + global.h - global gpgme functions and enums + Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_GLOBAL_H__ +#define __GPGMEPP_GLOBAL_H__ + +#include "gpgmefw.h" +#include "gpgmepp_export.h" + +#include <iosfwd> +#include <cstring> + +namespace GpgME +{ +class Error; +class EngineInfo; +class Context; +} + +struct _GIOChannel; +typedef struct _GIOChannel GIOChannel; +class QIODevice; + +namespace GpgME +{ + +GPGMEPP_EXPORT void initializeLibrary(); +/*! + Initializes the library, returns Error::code() == + GPG_ERR_USER_1 if underlying gpgme is too old. +*/ +GPGMEPP_EXPORT Error initializeLibrary(int); + +enum Protocol { OpenPGP, CMS, UnknownProtocol }; + +enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine, G13Engine, SpawnEngine }; + +enum KeyListMode { + Local = 0x1, + Extern = 0x2, + Signatures = 0x4, + SignatureNotations = 0x8, + Validate = 0x10, + Ephemeral = 0x20, + WithTofu = 0x40 +}; + +enum SignatureMode { NormalSignatureMode, Detached, Clearsigned }; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Protocol proto); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Engine eng); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, KeyListMode mode); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, SignatureMode mode); + +GPGMEPP_EXPORT Error setDefaultLocale(int category, const char *value); + +GPGMEPP_EXPORT Context *wait(Error &e, bool hang = true); +typedef void (*IdleFunction)(void); +GPGMEPP_EXPORT IdleFunction registerIdleFunction(IdleFunction idleFunction); + +typedef void (*IOCallback)(void *data, int fd); + +GPGMEPP_EXPORT EngineInfo engineInfo(Protocol proto); +GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine); +/** Wrapper around gpgme_get_dirinfo. What can be: +homedir, sysconfdir, bindir, libexecdir, libdir, +datadir, localedir, agent-socket, agent-ssh-socket, +dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name, +gpgsm-name, g13-name + +This may be extended in the future. +*/ +GPGMEPP_EXPORT const char *dirInfo(const char *what); + +GPGMEPP_EXPORT Error checkEngine(Protocol proto); +GPGMEPP_EXPORT Error checkEngine(Engine engine); + +GPGMEPP_EXPORT GIOChannel *getGIOChannel(int fd); +GPGMEPP_EXPORT QIODevice *getQIODevice(int fd); + +enum Feature { + ValidatingKeylistModeFeature = 0x00000001, + CancelOperationFeature = 0x00000002, + WrongKeyUsageFeature = 0x00000004, + DefaultCertificateInclusionFeature = 0x00000008, + + GetSetEngineInfoFeature = 0x00000010, + EngineInfoHomeDirFeature = 0x00000020, + NoEncryptToEncryptionFlagFeature = 0x00000040, + EphemeralKeylistModeFeature = 0x00000080, + + SetDataFileNameFeeature = 0x00000100, + VerificationResultFileNameFeature = 0x00000200, + DecryptionResultFileNameFeature = 0x00000400, + DecryptionResultRecipientsFeature = 0x00000800, + + AuditLogFeature = 0x00001000, + GpgConfEngineFeature = 0x00002000, + CancelOperationAsyncFeature = 0x00004000, + AssuanEngineFeature = 0x00008000, + + ClearAddGetSignatureNotationsFeature = 0x00010000, + SignatureNotationsKeylistModeFeature = 0x00020000, + KeySignatureNotationsFeature = 0x00040000, + SignatureNotationsFlagsFeature = 0x00080000, + SignatureNotationsCriticalFlagFeature = 0x00100000, + SignatureNotationsHumanReadableFlagFeature = 0x00200000, + CardKeyFeature = 0x00400000, + ImportFromKeyserverFeature = 0x00800000, + + KeyIsQualifiedFeature = 0x01000200, + SubkeyIsQualifiedFeature = 0x02000000, + SignaturePkaFieldsFeature = 0x04000000, + SignatureAlgorithmFieldsFeature = 0x08000000, + + FdPointerFeature = 0x10000000, + G13VFSFeature = 0x20000000, + PasswdFeature = 0x40000000, // gpgme >= 1.3.0 + // unusable (max value) + + FeatureMaxValue = 0x80000000 +}; +enum Feature2 { + BinaryAndFineGrainedIdentify = 0x00000001, // gpgme >= 1.7.0 + Feature2MaxValue = 0x80000000 +}; + +// use hasFeature( unsigned long, unsigned long ) instead +GPGMEPP_DEPRECATED_EXPORT bool hasFeature(unsigned long feature); +GPGMEPP_EXPORT bool hasFeature(unsigned long feature, unsigned long feature2); + +} // namespace GpgME + +# ifndef GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION +# define GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Class ) \ + namespace std { template <> inline void swap< GpgME::Class >( GpgME::Class & lhs, GpgME::Class & rhs ) { lhs.swap( rhs ); } } +# endif + +# ifndef GPGMEPP_MAKE_SAFE_BOOL_OPERATOR +# define GPGMEPP_MAKE_SAFE_BOOL_OPERATOR( Cond ) \ + private: \ + struct __safe_bool_dummy__ { void nonnull() {} }; \ + typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \ + public: \ + operator unspecified_bool_type() const { return ( Cond ) ? &__safe_bool_dummy__::nonnull : 0 ; } +# endif + +inline int _gpgmepp_strcmp(const char *s1, const char *s2) +{ + return s1 ? s2 ? std::strcmp(s1, s2) : 1 : s2 ? -1 : 0; +} + +#define _GPGMEPP_MAKE_STRCMP( Name, expr, cmp ) \ + template <template <typename U> class Op> \ + struct Name { \ + typedef bool result_type; \ + \ + bool operator()( const char * lhs, const char * rhs ) const { \ + return Op<int>()( cmp, 0 ); \ + } \ + \ + bool operator()( const std::string & lhs, const std::string & rhs ) const { \ + return operator()( lhs.c_str(), rhs.c_str() ); \ + } \ + bool operator()( const char * lhs, const std::string & rhs ) const { \ + return operator()( lhs, rhs.c_str() ); \ + } \ + bool operator()( const std::string & lhs, const char * rhs ) const { \ + return operator()( lhs.c_str(), rhs ); \ + } \ + \ + template <typename T> \ + bool operator()( const T & lhs, const T & rhs ) const { \ + return operator()( (lhs expr), (rhs expr) ); \ + } \ + template <typename T> \ + bool operator()( const T & lhs, const char * rhs ) const { \ + return operator()( (lhs expr), rhs ); \ + } \ + template <typename T> \ + bool operator()( const char * lhs, const T & rhs ) const { \ + return operator()( lhs, (rhs expr) ); \ + } \ + template <typename T> \ + bool operator()( const T & lhs, const std::string & rhs ) const { \ + return operator()( (lhs expr), rhs ); \ + } \ + template <typename T> \ + bool operator()( const std::string & lhs, const T & rhs ) const { \ + return operator()( lhs, (rhs expr) ); \ + } \ + } + +#define GPGMEPP_MAKE_STRCMP( Name, expr ) \ + _GPGMEPP_MAKE_STRCMP( Name, expr, _gpgmepp_strcmp( lhs, rhs ) ) + + +#endif // __GPGMEPP_GLOBAL_H__ diff --git a/lang/cpp/src/gpgadduserideditinteractor.cpp b/lang/cpp/src/gpgadduserideditinteractor.cpp new file mode 100644 index 0000000..43c8592 --- /dev/null +++ b/lang/cpp/src/gpgadduserideditinteractor.cpp @@ -0,0 +1,189 @@ +/* + gpgadduserideditinteractor.cpp - Edit Interactor to add a new UID to an OpenPGP key + Copyright (C) 2008 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "gpgadduserideditinteractor.h" + +#include "error.h" + +#include <gpgme.h> + +#include <cstring> + +using std::strcmp; + +// avoid conflict (msvc) +#ifdef ERROR +# undef ERROR +#endif + +using namespace GpgME; + +GpgAddUserIDEditInteractor::GpgAddUserIDEditInteractor() + : EditInteractor(), + m_name(), + m_email(), + m_comment() +{ + +} + +GpgAddUserIDEditInteractor::~GpgAddUserIDEditInteractor() {} + +void GpgAddUserIDEditInteractor::setNameUtf8(const std::string &name) +{ + m_name = name; +} + +void GpgAddUserIDEditInteractor::setEmailUtf8(const std::string &email) +{ + m_email = email; +} + +void GpgAddUserIDEditInteractor::setCommentUtf8(const std::string &comment) +{ + m_comment = comment; +} + +// work around --enable-final +namespace GpgAddUserIDEditInteractor_Private +{ +enum { + START = EditInteractor::StartState, + COMMAND, + NAME, + EMAIL, + COMMENT, + QUIT, + SAVE, + + ERROR = EditInteractor::ErrorState +}; +} + +const char *GpgAddUserIDEditInteractor::action(Error &err) const +{ + + using namespace GpgAddUserIDEditInteractor_Private; + + switch (state()) { + case COMMAND: + return "adduid"; + case NAME: + return m_name.c_str(); + case EMAIL: + return m_email.c_str(); + case COMMENT: + return m_comment.c_str(); + case QUIT: + return "quit"; + case SAVE: + return "Y"; + case START: + case ERROR: + return 0; + default: + err = Error::fromCode(GPG_ERR_GENERAL); + return 0; + } +} + +unsigned int GpgAddUserIDEditInteractor::nextState(unsigned int status, const char *args, Error &err) const +{ + + static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); + static const Error INV_NAME_ERROR = Error::fromCode(GPG_ERR_INV_NAME); + static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); + static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); + + if (needsNoResponse(status)) { + return state(); + } + + using namespace GpgAddUserIDEditInteractor_Private; + + switch (state()) { + case START: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return COMMAND; + } + err = GENERAL_ERROR; + return ERROR; + case COMMAND: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.name") == 0) { + return NAME; + } + err = GENERAL_ERROR; + return ERROR; + case NAME: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.email") == 0) { + return EMAIL; + } + err = GENERAL_ERROR; + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.name") == 0) { + err = INV_NAME_ERROR; + } + return ERROR; + case EMAIL: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.comment") == 0) { + return COMMENT; + } + err = GENERAL_ERROR; + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.email") == 0) { + err = INV_EMAIL_ERROR; + } + return ERROR; + case COMMENT: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } + err = GENERAL_ERROR; + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.comment") == 0) { + err = INV_COMMENT_ERROR; + } + return ERROR; + case QUIT: + if (status == GPGME_STATUS_GET_BOOL && + strcmp(args, "keyedit.save.okay") == 0) { + return SAVE; + } + err = GENERAL_ERROR; + return ERROR; + case ERROR: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } + err = lastError(); + return ERROR; + default: + err = GENERAL_ERROR; + return ERROR; + } +} diff --git a/lang/cpp/src/gpgadduserideditinteractor.h b/lang/cpp/src/gpgadduserideditinteractor.h new file mode 100644 index 0000000..12b6e46 --- /dev/null +++ b/lang/cpp/src/gpgadduserideditinteractor.h @@ -0,0 +1,67 @@ +/* + gpgadduserideditinteractor.h - Edit Interactor to add a new UID to an OpenPGP key + Copyright (C) 2008 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__ +#define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__ + +#include <editinteractor.h> + +#include <string> + +namespace GpgME +{ + +class GPGMEPP_EXPORT GpgAddUserIDEditInteractor : public EditInteractor +{ +public: + explicit GpgAddUserIDEditInteractor(); + ~GpgAddUserIDEditInteractor(); + + void setNameUtf8(const std::string &name); + const std::string &nameUtf8() const + { + return m_name; + } + + void setEmailUtf8(const std::string &email); + const std::string &emailUtf8() const + { + return m_email; + } + + void setCommentUtf8(const std::string &comment); + const std::string &commentUtf8() const + { + return m_comment; + } + +private: + /* reimp */ const char *action(Error &err) const; + /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const; + +private: + std::string m_name, m_email, m_comment; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__ diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp new file mode 100644 index 0000000..4739aa2 --- /dev/null +++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp @@ -0,0 +1,119 @@ +/* + gpgagentgetinfoassuantransaction.cpp - Assuan Transaction to get information from gpg-agent + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "gpgagentgetinfoassuantransaction.h" +#include "error.h" +#include "data.h" +#include "util.h" + +#include <assert.h> + +#include <sstream> + +using namespace GpgME; + +GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item) + : AssuanTransaction(), + m_item(item), + m_command(), + m_data() +{ + +} + +GpgAgentGetInfoAssuanTransaction::~GpgAgentGetInfoAssuanTransaction() {} + +std::string GpgAgentGetInfoAssuanTransaction::version() const +{ + if (m_item == Version) { + return m_data; + } else { + return std::string(); + } +} + +unsigned int GpgAgentGetInfoAssuanTransaction::pid() const +{ + if (m_item == Pid) { + return to_pid(m_data); + } else { + return 0U; + } +} + +std::string GpgAgentGetInfoAssuanTransaction::socketName() const +{ + if (m_item == SocketName) { + return m_data; + } else { + return std::string(); + } +} + +std::string GpgAgentGetInfoAssuanTransaction::sshSocketName() const +{ + if (m_item == SshSocketName) { + return m_data; + } else { + return std::string(); + } +} + +static const char *const gpgagent_getinfo_tokens[] = { + "version", + "pid", + "socket_name", + "ssh_socket_name", + "scd_running", +}; + +void GpgAgentGetInfoAssuanTransaction::makeCommand() const +{ + assert(m_item >= 0); + assert(m_item < LastInfoItem); + m_command = "GETINFO "; + m_command += gpgagent_getinfo_tokens[m_item]; +} + +const char *GpgAgentGetInfoAssuanTransaction::command() const +{ + makeCommand(); + return m_command.c_str(); +} + +Error GpgAgentGetInfoAssuanTransaction::data(const char *data, size_t len) +{ + m_data.append(data, len); + return Error(); +} + +Data GpgAgentGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err) +{ + (void)name; (void)args; (void)err; + return Data::null; +} + +Error GpgAgentGetInfoAssuanTransaction::status(const char *status, const char *args) +{ + (void)status; (void)args; + return Error(); +} diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.h b/lang/cpp/src/gpgagentgetinfoassuantransaction.h new file mode 100644 index 0000000..9e3e958 --- /dev/null +++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.h @@ -0,0 +1,73 @@ +/* + gpgagentgetinfoassuantransaction.h - Assuan Transaction to get information from gpg-agent + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__ +#define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__ + +#include <interfaces/assuantransaction.h> + +#include <string> +#include <vector> + +namespace GpgME +{ + +class GPGMEPP_EXPORT GpgAgentGetInfoAssuanTransaction : public AssuanTransaction +{ +public: + enum InfoItem { + Version, // string + Pid, // unsigned long + SocketName, // string (path) + SshSocketName, // string (path) + ScdRunning, // (none, returns GPG_ERR_GENERAL when scdaemon isn't running) + //CommandHasOption, // not supported + + LastInfoItem + }; + + explicit GpgAgentGetInfoAssuanTransaction(InfoItem item); + ~GpgAgentGetInfoAssuanTransaction(); + + std::string version() const; + unsigned int pid() const; + std::string socketName() const; + std::string sshSocketName() const; + +private: + /* reimp */ const char *command() const; + /* reimp */ Error data(const char *data, size_t datalen); + /* reimp */ Data inquire(const char *name, const char *args, Error &err); + /* reimp */ Error status(const char *status, const char *args); + +private: + void makeCommand() const; + +private: + InfoItem m_item; + mutable std::string m_command; + std::string m_data; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__ diff --git a/lang/cpp/src/gpgmefw.h b/lang/cpp/src/gpgmefw.h new file mode 100644 index 0000000..cbdd444 --- /dev/null +++ b/lang/cpp/src/gpgmefw.h @@ -0,0 +1,70 @@ +/* + gpgmefw.h - Forwards declarations for gpgme (0.3 and 0.4) + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGMEFW_H__ +#define __GPGMEPP_GPGMEFW_H__ + +struct gpgme_context; +typedef gpgme_context *gpgme_ctx_t; + +struct gpgme_data; +typedef gpgme_data *gpgme_data_t; + +struct gpgme_io_cbs; + +struct _gpgme_key; +typedef struct _gpgme_key *gpgme_key_t; + +struct _gpgme_trust_item; +typedef struct _gpgme_trust_item *gpgme_trust_item_t; + +struct _gpgme_subkey; +typedef struct _gpgme_subkey *gpgme_sub_key_t; + +struct _gpgme_user_id; +typedef struct _gpgme_user_id *gpgme_user_id_t; + +struct _gpgme_key_sig; +typedef struct _gpgme_key_sig *gpgme_key_sig_t; + +struct _gpgme_sig_notation; +typedef struct _gpgme_sig_notation *gpgme_sig_notation_t; + +struct _gpgme_engine_info; +typedef struct _gpgme_engine_info *gpgme_engine_info_t; + +struct _gpgme_op_keylist_result; +typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t; + +struct _gpgme_recipient; +typedef struct _gpgme_recipient *gpgme_recipient_t; + +struct gpgme_conf_opt; +typedef struct gpgme_conf_opt *gpgme_conf_opt_t; + +struct gpgme_conf_comp; +typedef struct gpgme_conf_comp *gpgme_conf_comp_t; + +struct gpgme_conf_arg; +typedef struct gpgme_conf_arg *gpgme_conf_arg_t; + +#endif // __GPGMEPP_GPGMEFW_H__ diff --git a/lang/cpp/src/gpgmepp_export.h b/lang/cpp/src/gpgmepp_export.h new file mode 100644 index 0000000..d660310 --- /dev/null +++ b/lang/cpp/src/gpgmepp_export.h @@ -0,0 +1,73 @@ +/*gpgmepp_export.h - Export macros for gpgmepp + Copyright (C) 2016, Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef GPGMEPP_EXPORT_H +#define GPGMEPP_EXPORT_H + +#ifdef GPGMEPP_STATIC_DEFINE +# define GPGMEPP_EXPORT +# define GPGMEPP_NO_EXPORT +#else +# ifndef GPGMEPP_EXPORT +# ifdef BUILDING_GPGMEPP + /* We are building this library */ +# ifdef WIN32 +# define GPGMEPP_EXPORT __declspec(dllexport) +# else +# define GPGMEPP_EXPORT __attribute__((visibility("default"))) +# endif +# else + /* We are using this library */ +# ifdef WIN32 +# define GPGMEPP_EXPORT __declspec(dllimport) +# else +# define GPGMEPP_EXPORT __attribute__((visibility("default"))) +# endif +# endif +# endif + +# ifndef GPGMEPP_NO_EXPORT +# ifdef WIN32 +# define GPGMEPP_NO_EXPORT +# else +# define GPGMEPP_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +# endif +#endif + +#ifndef GPGMEPP_DEPRECATED +# define GPGMEPP_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef GPGMEPP_DEPRECATED_EXPORT +# define GPGMEPP_DEPRECATED_EXPORT GPGMEPP_EXPORT GPGMEPP_DEPRECATED +#endif + +#ifndef GPGMEPP_DEPRECATED_NO_EXPORT +# define GPGMEPP_DEPRECATED_NO_EXPORT GPGMEPP_NO_EXPORT GPGMEPP_DEPRECATED +#endif + +#define DEFINE_NO_DEPRECATED 0 +#if DEFINE_NO_DEPRECATED +# define GPGMEPP_NO_DEPRECATED +#endif + +#endif diff --git a/lang/cpp/src/gpgmepp_version.h.in b/lang/cpp/src/gpgmepp_version.h.in new file mode 100644 index 0000000..3c33a30 --- /dev/null +++ b/lang/cpp/src/gpgmepp_version.h.in @@ -0,0 +1,32 @@ +/*gpgmepp_version.h - Version macros for gpgmepp + Copyright (C) 2016, Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#ifndef GPGMEPP_VERSION_H +#define GPGMEPP_VERSION_H + +#define GPGMEPP_VERSION_STRING "@LIBGPGMEPP_LT_CURRENT@.@LIBGPGMEPP_LT_AGE@.@LIBGPGMEPP_LT_REVISION@" +#define GPGMEPP_VERSION_MAJOR @LIBGPGMEPP_LT_CURRENT@ +#define GPGMEPP_VERSION_MINOR @LIBGPGMEPP_LT_AGE@ +#define GPGMEPP_VERSION_PATCH @LIBGPGMEPP_LT_REVISION@ +#define GPGMEPP_VERSION ((@LIBGPGMEPP_LT_CURRENT@<<16)|(@LIBGPGMEPP_LT_AGE@<<8)|(@LIBGPGMEPP_LT_REVISION@)) + +#endif diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp new file mode 100644 index 0000000..8af897c --- /dev/null +++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp @@ -0,0 +1,141 @@ +/* + gpgsetexpirytimeeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "gpgsetexpirytimeeditinteractor.h" +#include "error.h" + +#include <gpgme.h> + +#include <cstring> + +using std::strcmp; + +// avoid conflict (msvc) +#ifdef ERROR +# undef ERROR +#endif + +using namespace GpgME; + +GpgSetExpiryTimeEditInteractor::GpgSetExpiryTimeEditInteractor(const std::string &t) + : EditInteractor(), + m_strtime(t) +{ + +} + +GpgSetExpiryTimeEditInteractor::~GpgSetExpiryTimeEditInteractor() {} + +// work around --enable-final +namespace GpgSetExpiryTimeEditInteractor_Private +{ +enum { + START = EditInteractor::StartState, + COMMAND, + DATE, + QUIT, + SAVE, + + ERROR = EditInteractor::ErrorState +}; +} + +const char *GpgSetExpiryTimeEditInteractor::action(Error &err) const +{ + + using namespace GpgSetExpiryTimeEditInteractor_Private; + + switch (state()) { + case COMMAND: + return "expire"; + case DATE: + return m_strtime.c_str(); + case QUIT: + return "quit"; + case SAVE: + return "Y"; + case START: + case ERROR: + return 0; + default: + err = Error::fromCode(GPG_ERR_GENERAL); + return 0; + } +} + +unsigned int GpgSetExpiryTimeEditInteractor::nextState(unsigned int status, const char *args, Error &err) const +{ + + static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); + static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME); + + if (needsNoResponse(status)) { + return state(); + } + + using namespace GpgSetExpiryTimeEditInteractor_Private; + + switch (state()) { + case START: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return COMMAND; + } + err = GENERAL_ERROR; + return ERROR; + case COMMAND: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.valid") == 0) { + return DATE; + } + err = GENERAL_ERROR; + return ERROR; + case DATE: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } else if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keygen.valid")) { + err = INV_TIME_ERROR; + return ERROR; + } + err = GENERAL_ERROR; + return ERROR; + case QUIT: + if (status == GPGME_STATUS_GET_BOOL && + strcmp(args, "keyedit.save.okay") == 0) { + return SAVE; + } + err = GENERAL_ERROR; + return ERROR; + case ERROR: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } + err = lastError(); + return ERROR; + default: + err = GENERAL_ERROR; + return ERROR; + } +} diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.h b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h new file mode 100644 index 0000000..670b445 --- /dev/null +++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h @@ -0,0 +1,49 @@ +/* + gpgsetexpirytimeeditinteractor.h - Edit Interactor to change the expiry time of an OpenPGP key + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__ +#define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__ + +#include <editinteractor.h> + +#include <string> + +namespace GpgME +{ + +class GPGMEPP_EXPORT GpgSetExpiryTimeEditInteractor : public EditInteractor +{ +public: + explicit GpgSetExpiryTimeEditInteractor(const std::string &timeString = "0"); + ~GpgSetExpiryTimeEditInteractor(); + +private: + /* reimp */ const char *action(Error &err) const; + /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const; + +private: + const std::string m_strtime; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H___ diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.cpp b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp new file mode 100644 index 0000000..15b1269 --- /dev/null +++ b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp @@ -0,0 +1,151 @@ +/* + gpgsetownertrusteditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "gpgsetownertrusteditinteractor.h" +#include "error.h" + +#include <gpgme.h> + +#include <cstring> + +using std::strcmp; + +// avoid conflict (msvc) +#ifdef ERROR +# undef ERROR +#endif + +using namespace GpgME; + +GpgSetOwnerTrustEditInteractor::GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ot) + : EditInteractor(), + m_ownertrust(ot) +{ + +} + +GpgSetOwnerTrustEditInteractor::~GpgSetOwnerTrustEditInteractor() {} + +// work around --enable-final +namespace GpgSetOwnerTrustEditInteractor_Private +{ +enum { + START = EditInteractor::StartState, + COMMAND, + VALUE, + REALLY_ULTIMATE, + QUIT, + SAVE, + + ERROR = EditInteractor::ErrorState +}; +} + +const char *GpgSetOwnerTrustEditInteractor::action(Error &err) const +{ + static const char truststrings[][2] = { "1", "1", "2", "3", "4", "5" }; + + using namespace GpgSetOwnerTrustEditInteractor_Private; + + switch (state()) { + case COMMAND: + return "trust"; + case VALUE: + return truststrings[m_ownertrust]; + case REALLY_ULTIMATE: + return "Y"; + case QUIT: + return "quit"; + case SAVE: + return "Y"; + case START: + case ERROR: + return 0; + default: + err = Error::fromCode(GPG_ERR_GENERAL); + return 0; + } +} + +unsigned int GpgSetOwnerTrustEditInteractor::nextState(unsigned int status, const char *args, Error &err) const +{ + + static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); + //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME ); + + if (needsNoResponse(status)) { + return state(); + } + + using namespace GpgSetOwnerTrustEditInteractor_Private; + + switch (state()) { + case START: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return COMMAND; + } + err = GENERAL_ERROR; + return ERROR; + case COMMAND: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "edit_ownertrust.value") == 0) { + return VALUE; + } + err = GENERAL_ERROR; + return ERROR; + case VALUE: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } else if (status == GPGME_STATUS_GET_BOOL && + strcmp(args, "edit_ownertrust.set_ultimate.okay") == 0) { + return REALLY_ULTIMATE; + } + err = GENERAL_ERROR; + return ERROR; + case REALLY_ULTIMATE: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } + err = GENERAL_ERROR; + return ERROR; + case QUIT: + if (status == GPGME_STATUS_GET_BOOL && + strcmp(args, "keyedit.save.okay") == 0) { + return SAVE; + } + err = GENERAL_ERROR; + return ERROR; + case ERROR: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return QUIT; + } + err = lastError(); + return ERROR; + default: + err = GENERAL_ERROR; + return ERROR; + }; +} diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.h b/lang/cpp/src/gpgsetownertrusteditinteractor.h new file mode 100644 index 0000000..caf29ee --- /dev/null +++ b/lang/cpp/src/gpgsetownertrusteditinteractor.h @@ -0,0 +1,50 @@ +/* + gpgsetownertrusteditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__ +#define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__ + +#include <editinteractor.h> +#include <key.h> + +#include <string> + +namespace GpgME +{ + +class GPGMEPP_EXPORT GpgSetOwnerTrustEditInteractor : public EditInteractor +{ +public: + explicit GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ownertrust); + ~GpgSetOwnerTrustEditInteractor(); + +private: + /* reimp */ const char *action(Error &err) const; + /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const; + +private: + const Key::OwnerTrust m_ownertrust; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__ diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.cpp b/lang/cpp/src/gpgsignkeyeditinteractor.cpp new file mode 100644 index 0000000..fded90f --- /dev/null +++ b/lang/cpp/src/gpgsignkeyeditinteractor.cpp @@ -0,0 +1,318 @@ +/* + gpgsignkeyeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key + Copyright (C) 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "gpgsignkeyeditinteractor.h" +#include "error.h" +#include "key.h" + +#include <gpgme.h> + +#include <map> +#include <string> +#include <sstream> + +#include <cassert> +#include <cstring> + +using std::strcmp; + +// avoid conflict (msvc) +#ifdef ERROR +# undef ERROR +#endif + +#ifdef _MSC_VER +#undef snprintf +#define snprintf _snprintf +#endif + +using namespace GpgME; + +class GpgSignKeyEditInteractor::Private +{ +public: + Private(); + + std::string scratch; + bool started; + int options; + std::vector<unsigned int> userIDs; + std::vector<unsigned int>::const_iterator currentId, nextId; + unsigned int checkLevel; + + const char *command() const + { + const bool local = (options & Exportable) == 0; + const bool nonRevoc = options & NonRevocable; + const bool trust = options & Trust; + //TODO: check if all combinations are valid + if (local && nonRevoc && trust) { + return "ltnrsign"; + } + if (local && nonRevoc) { + return "lnrsign"; + } + if (local && trust) { + return "ltsign"; + } + if (local) { + return "lsign"; + } + if (nonRevoc && trust) { + return "tnrsign"; + } + if (nonRevoc) { + return "nrsign"; + } + if (trust) { + return "tsign"; + } + return "sign"; + } + + bool signAll() const + { + return userIDs.empty(); + } + unsigned int nextUserID() + { + assert(nextId != userIDs.end()); + currentId = nextId++; + return currentUserID(); + } + + bool allUserIDsListed() const + { + return nextId == userIDs.end(); + } + + unsigned int currentUserID() const + { + assert(currentId != userIDs.end()); + return *currentId + 1; + } + +}; + +GpgSignKeyEditInteractor::Private::Private() + : + started(false), + options(0), + userIDs(), + currentId(), + nextId(), + checkLevel(0) +{ +} + +GpgSignKeyEditInteractor::GpgSignKeyEditInteractor() + : EditInteractor(), d(new Private) +{ + +} + +GpgSignKeyEditInteractor::~GpgSignKeyEditInteractor() +{ + delete d; +} + +// work around --enable-final +namespace GpgSignKeyEditInteractor_Private +{ +enum SignKeyState { + START = EditInteractor::StartState, + COMMAND, + UIDS_ANSWER_SIGN_ALL, + UIDS_LIST_SEPARATELY, + // all these free slots belong to UIDS_LIST_SEPARATELY, too + // (we increase state() by one for each UID, so that action() is called) + UIDS_LIST_SEPARATELY_DONE = 1000000, + SET_EXPIRE, + SET_CHECK_LEVEL, + SET_TRUST_VALUE, + SET_TRUST_DEPTH, + SET_TRUST_REGEXP, + CONFIRM, + QUIT, + SAVE, + ERROR = EditInteractor::ErrorState +}; + +typedef std::map<std::tuple<SignKeyState, unsigned int, std::string>, SignKeyState> TransitionMap; + +} + +static const char *answer(bool b) +{ + return b ? "Y" : "N"; +} + +static GpgSignKeyEditInteractor_Private::TransitionMap makeTable() +{ + using namespace GpgSignKeyEditInteractor_Private; + TransitionMap tab; + const unsigned int GET_BOOL = GPGME_STATUS_GET_BOOL; + const unsigned int GET_LINE = GPGME_STATUS_GET_LINE; +#define addEntry( s1, status, str, s2 ) tab[std::make_tuple( s1, status, str)] = s2 + addEntry(START, GET_LINE, "keyedit.prompt", COMMAND); + addEntry(COMMAND, GET_BOOL, "keyedit.sign_all.okay", UIDS_ANSWER_SIGN_ALL); + addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM); + addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM); + addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE); + addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); + addEntry(SET_TRUST_VALUE, GET_LINE, "trustsign_prompt.trust_depth", SET_TRUST_DEPTH); + addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsign_prompt.trust_regexp", SET_TRUST_REGEXP); + addEntry(SET_TRUST_REGEXP, GET_LINE, "sign_uid.okay", CONFIRM); + addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM); + addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL); + addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM); + addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM); + addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND); + addEntry(CONFIRM, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE); + addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE); + addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); + addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM); + addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT); + addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT); + addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE); +#undef addEntry + return tab; +} + +const char *GpgSignKeyEditInteractor::action(Error &err) const +{ + static const char check_level_strings[][2] = { "0", "1", "2", "3" }; + using namespace GpgSignKeyEditInteractor_Private; + using namespace std; + + switch (const unsigned int st = state()) { + case COMMAND: + return d->command(); + case UIDS_ANSWER_SIGN_ALL: + return answer(d->signAll()); + case UIDS_LIST_SEPARATELY_DONE: + return d->command(); + case SET_EXPIRE: + return answer(true); + case SET_TRUST_VALUE: + // TODO + case SET_TRUST_DEPTH: + //TODO + case SET_TRUST_REGEXP: + //TODO + return 0; + case SET_CHECK_LEVEL: + return check_level_strings[d->checkLevel]; + case CONFIRM: + return answer(true); + case QUIT: + return "quit"; + case SAVE: + return answer(true); + default: + if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) { + std::stringstream ss; + ss << d->nextUserID(); + d->scratch = ss.str(); + return d->scratch.c_str(); + } + // fall through + case ERROR: + err = Error::fromCode(GPG_ERR_GENERAL); + return 0; + } +} + +unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const +{ + d->started = true; + using namespace GpgSignKeyEditInteractor_Private; + static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); + //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME ); + static const TransitionMap table(makeTable()); + if (needsNoResponse(status)) { + return state(); + } + + using namespace GpgSignKeyEditInteractor_Private; + + //lookup transition in map + const TransitionMap::const_iterator it = table.find(std::make_tuple(static_cast<SignKeyState>(state()), status, std::string(args))); + if (it != table.end()) { + return it->second; + } + + //handle cases that cannot be handled via the map + switch (const unsigned int st = state()) { + case UIDS_ANSWER_SIGN_ALL: + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + if (!d->signAll()) { + return UIDS_LIST_SEPARATELY; + } + err = Error::fromCode(GPG_ERR_UNUSABLE_PUBKEY); + return ERROR; + } + break; + default: + if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) { + if (status == GPGME_STATUS_GET_LINE && + strcmp(args, "keyedit.prompt") == 0) { + return d->allUserIDsListed() ? UIDS_LIST_SEPARATELY_DONE : st + 1 ; + } + } + break; + case CONFIRM: + case ERROR: + err = lastError(); + return ERROR; + } + + err = GENERAL_ERROR; + return ERROR; +} + +void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel) +{ + assert(!d->started); + assert(checkLevel <= 3); + d->checkLevel = checkLevel; +} + +void GpgSignKeyEditInteractor::setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign) +{ + assert(!d->started); + d->userIDs = userIDsToSign; + d->nextId = d->userIDs.begin(); + d->currentId = d->userIDs.end(); + +} +void GpgSignKeyEditInteractor::setSigningOptions(int options) +{ + assert(!d->started); + d->options = options; +} diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.h b/lang/cpp/src/gpgsignkeyeditinteractor.h new file mode 100644 index 0000000..47ff8e5 --- /dev/null +++ b/lang/cpp/src/gpgsignkeyeditinteractor.h @@ -0,0 +1,64 @@ +/* + gpgsignkeyeditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key + Copyright (C) 2008 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__ +#define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__ + +#include <editinteractor.h> + +#include <string> +#include <vector> + +namespace GpgME +{ + +class Key; +class UserID; + +class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor +{ +public: + enum SignOption { + Exportable = 0x1, + NonRevocable = 0x2, + Trust = 0x4 + }; + + GpgSignKeyEditInteractor(); + ~GpgSignKeyEditInteractor(); + + void setCheckLevel(unsigned int checkLevel); + void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign); + void setSigningOptions(int options); + +private: + /* reimp */ const char *action(Error &err) const; + /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const; + +private: + class Private; + Private *const d; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__ diff --git a/lang/cpp/src/importresult.cpp b/lang/cpp/src/importresult.cpp new file mode 100644 index 0000000..97e8239 --- /dev/null +++ b/lang/cpp/src/importresult.cpp @@ -0,0 +1,215 @@ +/* + importresult.cpp - wraps a gpgme import result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#include <importresult.h> +#include "result_p.h" + +#include <gpgme.h> +#include <cstdlib> +#include <cstring> + +#include <string.h> + +class GpgME::ImportResult::Private +{ +public: + Private(const _gpgme_op_import_result &r) : res(r) + { + // copy recursively, using compiler-generated copy ctor. + // We just need to handle the pointers in the structs: + for (gpgme_import_status_t is = r.imports ; is ; is = is->next) { + gpgme_import_status_t copy = new _gpgme_import_status(*is); + copy->fpr = strdup(is->fpr); + copy->next = 0; + imports.push_back(copy); + } + res.imports = 0; + } + ~Private() + { + for (std::vector<gpgme_import_status_t>::iterator it = imports.begin() ; it != imports.end() ; ++it) { + std::free((*it)->fpr); + delete *it; *it = 0; + } + } + + _gpgme_op_import_result res; + std::vector<gpgme_import_status_t> imports; +}; + +GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::ImportResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_import_result_t res = gpgme_op_import_result(ctx); + if (!res) { + return; + } + d.reset(new Private(*res)); +} + +make_standard_stuff(ImportResult) + +int GpgME::ImportResult::numConsidered() const +{ + return d ? d->res.considered : 0 ; +} + +int GpgME::ImportResult::numKeysWithoutUserID() const +{ + return d ? d->res.no_user_id : 0 ; +} + +int GpgME::ImportResult::numImported() const +{ + return d ? d->res.imported : 0 ; +} + +int GpgME::ImportResult::numRSAImported() const +{ + return d ? d->res.imported_rsa : 0 ; +} + +int GpgME::ImportResult::numUnchanged() const +{ + return d ? d->res.unchanged : 0 ; +} + +int GpgME::ImportResult::newUserIDs() const +{ + return d ? d->res.new_user_ids : 0 ; +} + +int GpgME::ImportResult::newSubkeys() const +{ + return d ? d->res.new_sub_keys : 0 ; +} + +int GpgME::ImportResult::newSignatures() const +{ + return d ? d->res.new_signatures : 0 ; +} + +int GpgME::ImportResult::newRevocations() const +{ + return d ? d->res.new_revocations : 0 ; +} + +int GpgME::ImportResult::numSecretKeysConsidered() const +{ + return d ? d->res.secret_read : 0 ; +} + +int GpgME::ImportResult::numSecretKeysImported() const +{ + return d ? d->res.secret_imported : 0 ; +} + +int GpgME::ImportResult::numSecretKeysUnchanged() const +{ + return d ? d->res.secret_unchanged : 0 ; +} + +int GpgME::ImportResult::notImported() const +{ + return d ? d->res.not_imported : 0 ; +} + +GpgME::Import GpgME::ImportResult::import(unsigned int idx) const +{ + return Import(d, idx); +} + +std::vector<GpgME::Import> GpgME::ImportResult::imports() const +{ + if (!d) { + return std::vector<Import>(); + } + std::vector<Import> result; + result.reserve(d->imports.size()); + for (unsigned int i = 0 ; i < d->imports.size() ; ++i) { + result.push_back(Import(d, i)); + } + return result; +} + +GpgME::Import::Import(const std::shared_ptr<ImportResult::Private> &parent, unsigned int i) + : d(parent), idx(i) +{ + +} + +GpgME::Import::Import() : d(), idx(0) {} + +bool GpgME::Import::isNull() const +{ + return !d || idx >= d->imports.size() ; +} + +const char *GpgME::Import::fingerprint() const +{ + return isNull() ? 0 : d->imports[idx]->fpr ; +} + +GpgME::Error GpgME::Import::error() const +{ + return Error(isNull() ? 0 : d->imports[idx]->result); +} + +GpgME::Import::Status GpgME::Import::status() const +{ + if (isNull()) { + return Unknown; + } + const unsigned int s = d->imports[idx]->status; + unsigned int result = Unknown; + if (s & GPGME_IMPORT_NEW) { + result |= NewKey; + } + if (s & GPGME_IMPORT_UID) { + result |= NewUserIDs; + } + if (s & GPGME_IMPORT_SIG) { + result |= NewSignatures; + } + if (s & GPGME_IMPORT_SUBKEY) { + result |= NewSubkeys; + } + if (s & GPGME_IMPORT_SECRET) { + result |= ContainedSecretKey; + } + return static_cast<Status>(result); +} diff --git a/lang/cpp/src/importresult.h b/lang/cpp/src/importresult.h new file mode 100644 index 0000000..adda80a --- /dev/null +++ b/lang/cpp/src/importresult.h @@ -0,0 +1,134 @@ +/* + importresult.h - wraps a gpgme import result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_IMPORTRESULT_H__ +#define __GPGMEPP_IMPORTRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <memory> + +#include <vector> + +namespace GpgME +{ + +class Error; +class Import; + +class GPGMEPP_EXPORT ImportResult : public Result +{ +public: + ImportResult(); + ImportResult(gpgme_ctx_t ctx, int error); + ImportResult(gpgme_ctx_t ctx, const Error &error); + explicit ImportResult(const Error &error); + + const ImportResult &operator=(ImportResult other) + { + swap(other); + return *this; + } + + void swap(ImportResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + int numConsidered() const; + int numKeysWithoutUserID() const; + int numImported() const; + int numRSAImported() const; + int numUnchanged() const; + + int newUserIDs() const; + int newSubkeys() const; + int newSignatures() const; + int newRevocations() const; + + int numSecretKeysConsidered() const; + int numSecretKeysImported() const; + int numSecretKeysUnchanged() const; + + int notImported() const; + + Import import(unsigned int idx) const; + std::vector<Import> imports() const; + + class Private; +private: + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +class GPGMEPP_EXPORT Import +{ + friend class ::GpgME::ImportResult; + Import(const std::shared_ptr<ImportResult::Private> &parent, unsigned int idx); +public: + Import(); + + const Import &operator=(Import other) + { + swap(other); + return *this; + } + + void swap(Import &other) + { + using std::swap; + swap(this->d, other.d); + swap(this->idx, other.idx); + } + + bool isNull() const; + + const char *fingerprint() const; + Error error() const; + + enum Status { + Unknown = 0x0, + NewKey = 0x1, + NewUserIDs = 0x2, + NewSignatures = 0x4, + NewSubkeys = 0x8, + ContainedSecretKey = 0x10 + }; + Status status() const; + +private: + std::shared_ptr<ImportResult::Private> d; + unsigned int idx; +}; + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(ImportResult) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Import) + +#endif // __GPGMEPP_IMPORTRESULT_H__ diff --git a/lang/cpp/src/interfaces/assuantransaction.h b/lang/cpp/src/interfaces/assuantransaction.h new file mode 100644 index 0000000..a382b05 --- /dev/null +++ b/lang/cpp/src/interfaces/assuantransaction.h @@ -0,0 +1,49 @@ +/* + assuantransaction.h - Interface for ASSUAN transactions + Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com> + Author: Marc Mutz <marc@kdab.com> + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ +#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ + +#include "gpgmepp_export.h" + +#include <stddef.h> + +namespace GpgME +{ + +class Error; +class Data; + +class GPGMEPP_EXPORT AssuanTransaction +{ +public: + virtual ~AssuanTransaction() {} + + virtual Error data(const char *data, size_t datalen) = 0; + virtual Data inquire(const char *name, const char *args, Error &err) = 0; + virtual Error status(const char *status, const char *args) = 0; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ diff --git a/lang/cpp/src/interfaces/dataprovider.h b/lang/cpp/src/interfaces/dataprovider.h new file mode 100644 index 0000000..166bb4e --- /dev/null +++ b/lang/cpp/src/interfaces/dataprovider.h @@ -0,0 +1,53 @@ +/* + interface/dataprovider.h - Interface for data sources + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_DATAPROVIDER_H__ +#define __GPGMEPP_INTERFACES_DATAPROVIDER_H__ + +#include <sys/types.h> + +#include "gpgmepp_export.h" + +#include <gpg-error.h> + +namespace GpgME +{ + +class GPGMEPP_EXPORT DataProvider +{ +public: + virtual ~DataProvider() {} + + enum Operation { + Read, Write, Seek, Release + }; + virtual bool isSupported(Operation op) const = 0; + + virtual ssize_t read(void *buffer, size_t bufSize) = 0; + virtual ssize_t write(const void *buffer, size_t bufSize) = 0; + virtual off_t seek(off_t offset, int whence) = 0; + virtual void release() = 0; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_DATAPROVIDER_H__ diff --git a/lang/cpp/src/interfaces/passphraseprovider.h b/lang/cpp/src/interfaces/passphraseprovider.h new file mode 100644 index 0000000..5275e44 --- /dev/null +++ b/lang/cpp/src/interfaces/passphraseprovider.h @@ -0,0 +1,40 @@ +/* + interface/passphraseprovider.h - Interface for passphrase callbacks + Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__ +#define __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__ + +namespace GpgME +{ + +class PassphraseProvider +{ +public: + virtual ~PassphraseProvider() {} + + virtual char *getPassphrase(const char *useridHint, const char *description, + bool previousWasBad, bool &canceled) = 0; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__ diff --git a/lang/cpp/src/interfaces/progressprovider.h b/lang/cpp/src/interfaces/progressprovider.h new file mode 100644 index 0000000..78bbdd7 --- /dev/null +++ b/lang/cpp/src/interfaces/progressprovider.h @@ -0,0 +1,40 @@ +/* + interface/progressprovider.h - Interface for progress reports + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__ +#define __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__ + +namespace GpgME +{ + +class ProgressProvider +{ +public: + virtual ~ProgressProvider() {} + + virtual void showProgress(const char *what, int type, + int current, int total) = 0; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__ diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp new file mode 100644 index 0000000..cfa1ba3 --- /dev/null +++ b/lang/cpp/src/key.cpp @@ -0,0 +1,912 @@ +/* + key.cpp - wraps a gpgme key + Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <key.h> + +#include "util.h" +#include "tofuinfo.h" +#include "context.h" + +#include <gpgme.h> + +#include <string.h> +#include <istream> +#include <iterator> + +const GpgME::Key::Null GpgME::Key::null; + +namespace GpgME +{ + +Key::Key() : key() {} + +Key::Key(const Null &) : key() {} + +Key::Key(const shared_gpgme_key_t &k) : key(k) {} + +Key::Key(gpgme_key_t k, bool ref) + : key(k + ? shared_gpgme_key_t(k, &gpgme_key_unref) + : shared_gpgme_key_t()) +{ + if (ref && impl()) { + gpgme_key_ref(impl()); + } +} + +UserID Key::userID(unsigned int index) const +{ + return UserID(key, index); +} + +Subkey Key::subkey(unsigned int index) const +{ + return Subkey(key, index); +} + +unsigned int Key::numUserIDs() const +{ + if (!key) { + return 0; + } + unsigned int count = 0; + for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) { + ++count; + } + return count; +} + +unsigned int Key::numSubkeys() const +{ + if (!key) { + return 0; + } + unsigned int count = 0; + for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) { + ++count; + } + return count; +} + +std::vector<UserID> Key::userIDs() const +{ + if (!key) { + return std::vector<UserID>(); + } + + std::vector<UserID> v; + v.reserve(numUserIDs()); + for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) { + v.push_back(UserID(key, uid)); + } + return v; +} + +std::vector<Subkey> Key::subkeys() const +{ + if (!key) { + return std::vector<Subkey>(); + } + + std::vector<Subkey> v; + v.reserve(numSubkeys()); + for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) { + v.push_back(Subkey(key, subkey)); + } + return v; +} + +Key::OwnerTrust Key::ownerTrust() const +{ + if (!key) { + return Unknown; + } + switch (key->owner_trust) { + default: + case GPGME_VALIDITY_UNKNOWN: return Unknown; + case GPGME_VALIDITY_UNDEFINED: return Undefined; + case GPGME_VALIDITY_NEVER: return Never; + case GPGME_VALIDITY_MARGINAL: return Marginal; + case GPGME_VALIDITY_FULL: return Full; + case GPGME_VALIDITY_ULTIMATE: return Ultimate; + } +} +char Key::ownerTrustAsString() const +{ + if (!key) { + return '?'; + } + switch (key->owner_trust) { + default: + case GPGME_VALIDITY_UNKNOWN: return '?'; + case GPGME_VALIDITY_UNDEFINED: return 'q'; + case GPGME_VALIDITY_NEVER: return 'n'; + case GPGME_VALIDITY_MARGINAL: return 'm'; + case GPGME_VALIDITY_FULL: return 'f'; + case GPGME_VALIDITY_ULTIMATE: return 'u'; + } +} + +Protocol Key::protocol() const +{ + if (!key) { + return UnknownProtocol; + } + switch (key->protocol) { + case GPGME_PROTOCOL_CMS: return CMS; + case GPGME_PROTOCOL_OpenPGP: return OpenPGP; + default: return UnknownProtocol; + } +} + +const char *Key::protocolAsString() const +{ + return key ? gpgme_get_protocol_name(key->protocol) : 0 ; +} + +bool Key::isRevoked() const +{ + return key && key->revoked; +} + +bool Key::isExpired() const +{ + return key && key->expired; +} + +bool Key::isDisabled() const +{ + return key && key->disabled; +} + +bool Key::isInvalid() const +{ + return key && key->invalid; +} + +bool Key::hasSecret() const +{ + return key && key->secret; +} + +bool Key::isRoot() const +{ + return key && key->subkeys && key->subkeys->fpr && key->chain_id && + strcasecmp(key->subkeys->fpr, key->chain_id) == 0; +} + +bool Key::canEncrypt() const +{ + return key && key->can_encrypt; +} + +bool Key::canSign() const +{ +#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN + if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) { + return true; + } +#endif + return canReallySign(); +} + +bool Key::canReallySign() const +{ + return key && key->can_sign; +} + +bool Key::canCertify() const +{ + return key && key->can_certify; +} + +bool Key::canAuthenticate() const +{ + return key && key->can_authenticate; +} + +bool Key::isQualified() const +{ + return key && key->is_qualified; +} + +const char *Key::issuerSerial() const +{ + return key ? key->issuer_serial : 0 ; +} +const char *Key::issuerName() const +{ + return key ? key->issuer_name : 0 ; +} +const char *Key::chainID() const +{ + return key ? key->chain_id : 0 ; +} + +const char *Key::keyID() const +{ + return key && key->subkeys ? key->subkeys->keyid : 0 ; +} + +const char *Key::shortKeyID() const +{ + if (!key || !key->subkeys || !key->subkeys->keyid) { + return 0; + } + const int len = strlen(key->subkeys->keyid); + if (len > 8) { + return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation) + } else { + return key->subkeys->keyid; + } +} + +const char *Key::primaryFingerprint() const +{ + if (!key) { + return nullptr; + } + if (key->fpr) { + /* Return what gpgme thinks is the primary fingerprint */ + return key->fpr; + } + if (key->subkeys) { + /* Return the first subkeys fingerprint */ + return key->subkeys->fpr; + } +} + +unsigned int Key::keyListMode() const +{ + return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ; +} + +const Key &Key::mergeWith(const Key &other) +{ + // ### incomplete. Just merges has* and can*, nothing else atm + // ### detach also missing + + if (!this->primaryFingerprint() || + !other.primaryFingerprint() || + strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) { + return *this; // only merge the Key object which describe the same key + } + + const gpgme_key_t me = impl(); + const gpgme_key_t him = other.impl(); + + if (!me || !him) { + return *this; + } + + me->revoked |= him->revoked; + me->expired |= him->expired; + me->disabled |= him->disabled; + me->invalid |= him->invalid; + me->can_encrypt |= him->can_encrypt; + me->can_sign |= him->can_sign; + me->can_certify |= him->can_certify; + me->secret |= him->secret; + me->can_authenticate |= him->can_authenticate; + me->is_qualified |= him->is_qualified; + me->keylist_mode |= him->keylist_mode; + + // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost: + for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) { + for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) { + if (strcmp(mysk->fpr, hissk->fpr) == 0) { + mysk->is_cardkey |= hissk->is_cardkey; + break; + } + } + } + + return *this; +} + +void Key::update() +{ + auto ctx = Context::createForProtocol(protocol()); + if (!ctx) { + return; + } + ctx->setKeyListMode(KeyListMode::Local | + KeyListMode::Signatures | + KeyListMode::SignatureNotations | + KeyListMode::Validate | + KeyListMode::WithTofu); + Error err; + auto newKey = ctx->key(primaryFingerprint(), err, hasSecret()); + delete ctx; + if (err) { + return; + } + swap(newKey); + return; +} + +// +// +// class Subkey +// +// + +gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx) +{ + if (key) { + for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) { + if (idx == 0) { + return s; + } + } + } + return 0; +} + +gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey) +{ + if (key) { + for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) { + if (s == subkey) { + return subkey; + } + } + } + return 0; +} + +Subkey::Subkey() : key(), subkey(0) {} + +Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx) + : key(k), subkey(find_subkey(k, idx)) +{ + +} + +Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk) + : key(k), subkey(verify_subkey(k, sk)) +{ + +} + +Key Subkey::parent() const +{ + return Key(key); +} + +const char *Subkey::keyID() const +{ + return subkey ? subkey->keyid : 0 ; +} + +const char *Subkey::fingerprint() const +{ + return subkey ? subkey->fpr : 0 ; +} + +Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const +{ + return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown; +} + +const char *Subkey::publicKeyAlgorithmAsString() const +{ + return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0); +} + +/* static */ +const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo) +{ + if (algo == AlgoUnknown) { + return NULL; + } + return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo)); +} + +std::string Subkey::algoName() const +{ + char *gpgmeStr; + if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) { + std::string ret = std::string(gpgmeStr); + gpgme_free(gpgmeStr); + return ret; + } + return std::string(); +} + +bool Subkey::canEncrypt() const +{ + return subkey && subkey->can_encrypt; +} + +bool Subkey::canSign() const +{ + return subkey && subkey->can_sign; +} + +bool Subkey::canCertify() const +{ + return subkey && subkey->can_certify; +} + +bool Subkey::canAuthenticate() const +{ + return subkey && subkey->can_authenticate; +} + +bool Subkey::isQualified() const +{ + return subkey && subkey->is_qualified; +} + +bool Subkey::isCardKey() const +{ + return subkey && subkey->is_cardkey; +} + +const char *Subkey::cardSerialNumber() const +{ + return subkey ? subkey->card_number : 0 ; +} + +bool Subkey::isSecret() const +{ + return subkey && subkey->secret; +} + +unsigned int Subkey::length() const +{ + return subkey ? subkey->length : 0 ; +} + +time_t Subkey::creationTime() const +{ + return static_cast<time_t>(subkey ? subkey->timestamp : 0); +} + +time_t Subkey::expirationTime() const +{ + return static_cast<time_t>(subkey ? subkey->expires : 0); +} + +bool Subkey::neverExpires() const +{ + return expirationTime() == time_t(0); +} + +bool Subkey::isRevoked() const +{ + return subkey && subkey->revoked; +} + +bool Subkey::isInvalid() const +{ + return subkey && subkey->invalid; +} + +bool Subkey::isExpired() const +{ + return subkey && subkey->expired; +} + +bool Subkey::isDisabled() const +{ + return subkey && subkey->disabled; +} + +// +// +// class UserID +// +// + +gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx) +{ + if (key) { + for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) { + if (idx == 0) { + return u; + } + } + } + return 0; +} + +gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid) +{ + if (key) { + for (gpgme_user_id_t u = key->uids ; u ; u = u->next) { + if (u == uid) { + return uid; + } + } + } + return 0; +} + +UserID::UserID() : key(), uid(0) {} + +UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u) + : key(k), uid(verify_uid(k, u)) +{ + +} + +UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx) + : key(k), uid(find_uid(k, idx)) +{ + +} + +Key UserID::parent() const +{ + return Key(key); +} + +UserID::Signature UserID::signature(unsigned int index) const +{ + return Signature(key, uid, index); +} + +unsigned int UserID::numSignatures() const +{ + if (!uid) { + return 0; + } + unsigned int count = 0; + for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) { + ++count; + } + return count; +} + +std::vector<UserID::Signature> UserID::signatures() const +{ + if (!uid) { + return std::vector<Signature>(); + } + + std::vector<Signature> v; + v.reserve(numSignatures()); + for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) { + v.push_back(Signature(key, uid, sig)); + } + return v; +} + +const char *UserID::id() const +{ + return uid ? uid->uid : 0 ; +} + +const char *UserID::name() const +{ + return uid ? uid->name : 0 ; +} + +const char *UserID::email() const +{ + return uid ? uid->email : 0 ; +} + +const char *UserID::comment() const +{ + return uid ? uid->comment : 0 ; +} + +UserID::Validity UserID::validity() const +{ + if (!uid) { + return Unknown; + } + switch (uid->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return Unknown; + case GPGME_VALIDITY_UNDEFINED: return Undefined; + case GPGME_VALIDITY_NEVER: return Never; + case GPGME_VALIDITY_MARGINAL: return Marginal; + case GPGME_VALIDITY_FULL: return Full; + case GPGME_VALIDITY_ULTIMATE: return Ultimate; + } +} + +char UserID::validityAsString() const +{ + if (!uid) { + return '?'; + } + switch (uid->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return '?'; + case GPGME_VALIDITY_UNDEFINED: return 'q'; + case GPGME_VALIDITY_NEVER: return 'n'; + case GPGME_VALIDITY_MARGINAL: return 'm'; + case GPGME_VALIDITY_FULL: return 'f'; + case GPGME_VALIDITY_ULTIMATE: return 'u'; + } +} + +bool UserID::isRevoked() const +{ + return uid && uid->revoked; +} + +bool UserID::isInvalid() const +{ + return uid && uid->invalid; +} + +TofuInfo UserID::tofuInfo() const +{ + if (!uid) { + return TofuInfo(); + } + return TofuInfo(uid->tofu); +} + +// +// +// class Signature +// +// + +gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx) +{ + if (uid) { + for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) { + if (idx == 0) { + return s; + } + } + } + return 0; +} + +gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig) +{ + if (uid) { + for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) { + if (s == sig) { + return sig; + } + } + } + return 0; +} + +UserID::Signature::Signature() : key(), uid(0), sig(0) {} + +UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx) + : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx)) +{ + +} + +UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s) + : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s)) +{ + +} + +UserID UserID::Signature::parent() const +{ + return UserID(key, uid); +} + +const char *UserID::Signature::signerKeyID() const +{ + return sig ? sig->keyid : 0 ; +} + +const char *UserID::Signature::algorithmAsString() const +{ + return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0); +} + +unsigned int UserID::Signature::algorithm() const +{ + return sig ? sig->pubkey_algo : 0 ; +} + +time_t UserID::Signature::creationTime() const +{ + return static_cast<time_t>(sig ? sig->timestamp : 0); +} + +time_t UserID::Signature::expirationTime() const +{ + return static_cast<time_t>(sig ? sig->expires : 0); +} + +bool UserID::Signature::neverExpires() const +{ + return expirationTime() == time_t(0); +} + +bool UserID::Signature::isRevokation() const +{ + return sig && sig->revoked; +} + +bool UserID::Signature::isInvalid() const +{ + return sig && sig->invalid; +} + +bool UserID::Signature::isExpired() const +{ + return sig && sig->expired; +} + +bool UserID::Signature::isExportable() const +{ + return sig && sig->exportable; +} + +const char *UserID::Signature::signerUserID() const +{ + return sig ? sig->uid : 0 ; +} + +const char *UserID::Signature::signerName() const +{ + return sig ? sig->name : 0 ; +} + +const char *UserID::Signature::signerEmail() const +{ + return sig ? sig->email : 0 ; +} + +const char *UserID::Signature::signerComment() const +{ + return sig ? sig->comment : 0 ; +} + +unsigned int UserID::Signature::certClass() const +{ + return sig ? sig->sig_class : 0 ; +} + +UserID::Signature::Status UserID::Signature::status() const +{ + if (!sig) { + return GeneralError; + } + + switch (gpgme_err_code(sig->status)) { + case GPG_ERR_NO_ERROR: return NoError; + case GPG_ERR_SIG_EXPIRED: return SigExpired; + case GPG_ERR_KEY_EXPIRED: return KeyExpired; + case GPG_ERR_BAD_SIGNATURE: return BadSignature; + case GPG_ERR_NO_PUBKEY: return NoPublicKey; + default: + case GPG_ERR_GENERAL: return GeneralError; + } +} + +std::string UserID::Signature::statusAsString() const +{ + if (!sig) { + return std::string(); + } + char buf[ 1024 ]; + gpgme_strerror_r(sig->status, buf, sizeof buf); + buf[ sizeof buf - 1 ] = '\0'; + return std::string(buf); +} + +GpgME::Notation UserID::Signature::notation(unsigned int idx) const +{ + if (!sig) { + return GpgME::Notation(); + } + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + if (idx-- == 0) { + return GpgME::Notation(nota); + } + } + } + return GpgME::Notation(); +} + +unsigned int UserID::Signature::numNotations() const +{ + if (!sig) { + return 0; + } + unsigned int count = 0; + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + ++count; // others are policy URLs... + } + } + return count; +} + +std::vector<Notation> UserID::Signature::notations() const +{ + if (!sig) { + return std::vector<GpgME::Notation>(); + } + std::vector<GpgME::Notation> v; + v.reserve(numNotations()); + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (nota->name) { + v.push_back(GpgME::Notation(nota)); + } + } + return v; +} + +const char *UserID::Signature::policyURL() const +{ + if (!sig) { + return 0; + } + for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) { + if (!nota->name) { + return nota->value; + } + } + return 0; +} + +std::ostream &operator<<(std::ostream &os, const UserID &uid) +{ + os << "GpgME::UserID("; + if (!uid.isNull()) { + os << "\n name: " << protect(uid.name()) + << "\n email: " << protect(uid.email()) + << "\n comment: " << protect(uid.comment()) + << "\n validity: " << uid.validityAsString() + << "\n revoked: " << uid.isRevoked() + << "\n invalid: " << uid.isInvalid() + << "\n numsigs: " << uid.numSignatures() + << "\n tofuinfo:\n" << uid.tofuInfo(); + } + return os << ')'; +} + +std::ostream &operator<<(std::ostream &os, const Key &key) +{ + os << "GpgME::Key("; + if (!key.isNull()) { + os << "\n protocol: " << protect(key.protocolAsString()) + << "\n ownertrust: " << key.ownerTrustAsString() + << "\n issuer: " << protect(key.issuerName()) + << "\n fingerprint:" << protect(key.primaryFingerprint()) + << "\n listmode: " << key.keyListMode() + << "\n canSign: " << key.canReallySign() + << "\n canEncrypt: " << key.canEncrypt() + << "\n canCertify: " << key.canCertify() + << "\n canAuth: " << key.canAuthenticate() + << "\n uids:\n"; + const std::vector<UserID> uids = key.userIDs(); + std::copy(uids.begin(), uids.end(), + std::ostream_iterator<UserID>(os, "\n")); + } + return os << ')'; +} + +} // namespace GpgME diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h new file mode 100644 index 0000000..f193093 --- /dev/null +++ b/lang/cpp/src/key.h @@ -0,0 +1,415 @@ +/* + key.h - wraps a gpgme key + Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_KEY_H__ +#define __GPGMEPP_KEY_H__ + +#include "global.h" +#include "notation.h" + +#include "gpgmefw.h" + +#include <memory> +#include <sys/time.h> + +#include <vector> +#include <algorithm> +#include <string> + +namespace GpgME +{ + +class Context; + +class Subkey; +class UserID; +class TofuInfo; + +typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t; + +// +// class Key +// + +class GPGMEPP_EXPORT Key +{ + friend class ::GpgME::Context; + struct Null { + Null() {} + }; +public: + Key(); + /* implicit */ Key(const Null &); + Key(const shared_gpgme_key_t &key); + Key(gpgme_key_t key, bool acquireRef); + + static const Null null; + + const Key &operator=(Key other) + { + swap(other); + return *this; + } + + const Key &mergeWith(const Key &other); + + void swap(Key &other) + { + using std::swap; + swap(this->key, other.key); + } + + bool isNull() const + { + return !key; + } + + UserID userID(unsigned int index) const; + Subkey subkey(unsigned int index) const; + + unsigned int numUserIDs() const; + unsigned int numSubkeys() const; + + std::vector<UserID> userIDs() const; + std::vector<Subkey> subkeys() const; + + bool isRevoked() const; + bool isExpired() const; + bool isDisabled() const; + bool isInvalid() const; + + bool canEncrypt() const; + /*! + This function contains a workaround for old gpgme's: all secret + OpenPGP keys canSign() == true, which canReallySign() doesn't + have. I don't have time to find what breaks when I remove this + workaround, but since Kleopatra merges secret into public keys, + the workaround is not necessary there (and actively harms), I've + added a new function instead. + */ + bool canSign() const; + bool canReallySign() const; + bool canCertify() const; + bool canAuthenticate() const; + bool isQualified() const; + + bool hasSecret() const; + GPGMEPP_DEPRECATED bool isSecret() const + { + return hasSecret(); + } + + /*! + @return true if this is a X.509 root certificate (currently + equivalent to something like + strcmp( chainID(), subkey(0).fingerprint() ) == 0 ) + */ + bool isRoot() const; + + enum OwnerTrust { Unknown = 0, Undefined = 1, Never = 2, + Marginal = 3, Full = 4, Ultimate = 5 + }; + + OwnerTrust ownerTrust() const; + char ownerTrustAsString() const; + + Protocol protocol() const; + const char *protocolAsString() const; + + const char *issuerSerial() const; + const char *issuerName() const; + const char *chainID() const; + + const char *keyID() const; + const char *shortKeyID() const; + const char *primaryFingerprint() const; + + unsigned int keyListMode() const; + + /*! Update information about this key. + * Starts a keylisting for this key with validity + * and tofu information gathering. Blocks for + * how long the keylisting takes.*/ + void update(); + +private: + gpgme_key_t impl() const + { + return key.get(); + } + shared_gpgme_key_t key; +}; + +// +// class Subkey +// + +class GPGMEPP_EXPORT Subkey +{ +public: + Subkey(); + Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey); + Subkey(const shared_gpgme_key_t &key, unsigned int idx); + + const Subkey &operator=(Subkey other) + { + swap(other); + return *this; + } + + void swap(Subkey &other) + { + using std::swap; + swap(this->key, other.key); + swap(this->subkey, other.subkey); + } + + bool isNull() const + { + return !key || !subkey; + } + + Key parent() const; + + const char *keyID() const; + const char *fingerprint() const; + + time_t creationTime() const; + time_t expirationTime() const; + bool neverExpires() const; + + bool isRevoked() const; + bool isExpired() const; + bool isInvalid() const; + bool isDisabled() const; + + bool canEncrypt() const; + bool canSign() const; + bool canCertify() const; + bool canAuthenticate() const; + bool isQualified() const; + bool isCardKey() const; + + bool isSecret() const; + + /** Same as gpgme_pubkey_algo_t */ + enum PubkeyAlgo { + AlgoUnknown = 0, + AlgoRSA = 1, + AlgoRSA_E = 2, + AlgoRSA_S = 3, + AlgoELG_E = 16, + AlgoDSA = 17, + AlgoECC = 18, + AlgoELG = 20, + AlgoECDSA = 301, + AlgoECDH = 302, + AlgoEDDSA = 303, + AlgoMax = 1 << 31 + }; + + PubkeyAlgo publicKeyAlgorithm() const; + + /** + @brief Get the public key algorithm name. + + This only works for the pre 2.1 algorithms for ECC NULL is returned. + + @returns a statically allocated string with the name of the public + key algorithm, or NULL if that name is not known. + */ + const char *publicKeyAlgorithmAsString() const; + + /** @brief Same as publicKeyAlgorithmAsString but static. */ + static const char *publicKeyAlgorithmAsString(PubkeyAlgo algo); + + /** + @brief Get the key algo string like GnuPG 2.1 prints it. + + This returns combinations of size and algorithm. Like + bp512 or rsa2048. Misnamed because publicKeyAlgorithmAsString + already used the older pubkey_algo_name. + Actually uses gpgme_pubkey_algo_string. + + @returns the key algorithm as string. Empty string on error. + */ + std::string algoName() const; + + unsigned int length() const; + + const char *cardSerialNumber() const; + +private: + shared_gpgme_key_t key; + gpgme_sub_key_t subkey; +}; + +// +// class UserID +// + +class GPGMEPP_EXPORT UserID +{ +public: + class Signature; + + UserID(); + UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid); + UserID(const shared_gpgme_key_t &key, unsigned int idx); + + const UserID &operator=(UserID other) + { + swap(other); + return *this; + } + + void swap(UserID &other) + { + using std::swap; + swap(this->key, other.key); + swap(this->uid, other.uid); + } + + bool isNull() const + { + return !key || !uid; + } + + Key parent() const; + + unsigned int numSignatures() const; + Signature signature(unsigned int index) const; + std::vector<Signature> signatures() const; + + const char *id() const; + const char *name() const; + const char *email() const; + const char *comment() const; + + enum Validity { Unknown = 0, Undefined = 1, Never = 2, + Marginal = 3, Full = 4, Ultimate = 5 + }; + + Validity validity() const; + char validityAsString() const; + + bool isRevoked() const; + bool isInvalid() const; + + /** TOFU info for this userid. + * @returns The TOFU stats or a null TofuInfo. + */ + GpgME::TofuInfo tofuInfo() const; +private: + shared_gpgme_key_t key; + gpgme_user_id_t uid; +}; + +// +// class UserID::Signature +// + +class GPGMEPP_EXPORT UserID::Signature +{ +public: + typedef GPGMEPP_DEPRECATED GpgME::Notation Notation; + + Signature(); + Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig); + Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx); + + const Signature &operator=(Signature other) + { + swap(other); + return *this; + } + + void swap(Signature &other) + { + using std::swap; + swap(this->key, other.key); + swap(this->uid, other.uid); + swap(this->sig, other.sig); + } + + bool isNull() const + { + return !sig || !uid || !key ; + } + + UserID parent() const; + + const char *signerKeyID() const; + + const char *algorithmAsString() const; + unsigned int algorithm() const; + time_t creationTime() const; + time_t expirationTime() const; + bool neverExpires() const; + + bool isRevokation() const; + bool isInvalid() const; + bool isExpired() const; + bool isExportable() const; + + const char *signerUserID() const; + const char *signerName() const; + const char *signerEmail() const; + const char *signerComment() const; + + unsigned int certClass() const; + + enum Status { NoError = 0, SigExpired, KeyExpired, + BadSignature, NoPublicKey, GeneralError + }; + Status status() const; + std::string statusAsString() const; + + const char *policyURL() const; + + unsigned int numNotations() const; + GpgME::Notation notation(unsigned int idx) const; + std::vector<GpgME::Notation> notations() const; + +private: + shared_gpgme_key_t key; + gpgme_user_id_t uid; + gpgme_key_sig_t sig; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key); + +} // namespace GpgME + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Key) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Subkey) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID::Signature) + +GPGMEPP_MAKE_STRCMP(ByFingerprint, .primaryFingerprint()); +GPGMEPP_MAKE_STRCMP(ByKeyID, .keyID()); +GPGMEPP_MAKE_STRCMP(ByShortKeyID, .shortKeyID()); +GPGMEPP_MAKE_STRCMP(ByChainID, .chainID()); + +#endif // __GPGMEPP_KEY_H__ diff --git a/lang/cpp/src/keygenerationresult.cpp b/lang/cpp/src/keygenerationresult.cpp new file mode 100644 index 0000000..7837e20 --- /dev/null +++ b/lang/cpp/src/keygenerationresult.cpp @@ -0,0 +1,92 @@ +/* + keygenerationresult.cpp - wraps a gpgme keygen result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <keygenerationresult.h> +#include "result_p.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> + +#include <string.h> + +class GpgME::KeyGenerationResult::Private +{ +public: + Private(const _gpgme_op_genkey_result &r) : res(r) + { + if (res.fpr) { + res.fpr = strdup(res.fpr); + } + } + ~Private() + { + if (res.fpr) { + std::free(res.fpr); + } + res.fpr = 0; + } + + _gpgme_op_genkey_result res; +}; + +GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::KeyGenerationResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_genkey_result_t res = gpgme_op_genkey_result(ctx); + if (!res) { + return; + } + d.reset(new Private(*res)); +} + +make_standard_stuff(KeyGenerationResult) + +bool GpgME::KeyGenerationResult::isPrimaryKeyGenerated() const +{ + return d && d->res.primary; +} + +bool GpgME::KeyGenerationResult::isSubkeyGenerated() const +{ + return d && d->res.sub; +} + +const char *GpgME::KeyGenerationResult::fingerprint() const +{ + return d ? d->res.fpr : 0 ; +} diff --git a/lang/cpp/src/keygenerationresult.h b/lang/cpp/src/keygenerationresult.h new file mode 100644 index 0000000..c35c504 --- /dev/null +++ b/lang/cpp/src/keygenerationresult.h @@ -0,0 +1,82 @@ +/* + keygenerationresult.h - wraps a gpgme keygen result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_KEYGENERATIONRESULT_H__ +#define __GPGMEPP_KEYGENERATIONRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <memory> + +namespace GpgME +{ + +class Error; + +class GPGMEPP_EXPORT KeyGenerationResult : public Result +{ +public: + KeyGenerationResult(); + KeyGenerationResult(gpgme_ctx_t ctx, int error); + KeyGenerationResult(gpgme_ctx_t ctx, const Error &error); + explicit KeyGenerationResult(const Error &err); + + const KeyGenerationResult &operator=(KeyGenerationResult other) + { + swap(other); + return *this; + } + + void swap(KeyGenerationResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + GPGMEPP_DEPRECATED bool primaryKeyGenerated() const + { + return isPrimaryKeyGenerated(); + } + GPGMEPP_DEPRECATED bool subkeyGenerated() const + { + return isSubkeyGenerated(); + } + bool isPrimaryKeyGenerated() const; + bool isSubkeyGenerated() const; + const char *fingerprint() const; + +private: + class Private; + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyGenerationResult) + +#endif // __GPGMEPP_KEYGENERATIONRESULT_H__ diff --git a/lang/cpp/src/keylistresult.cpp b/lang/cpp/src/keylistresult.cpp new file mode 100644 index 0000000..4512d3b --- /dev/null +++ b/lang/cpp/src/keylistresult.cpp @@ -0,0 +1,107 @@ +/* + keylistresult.cpp - wraps a gpgme keylist result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <keylistresult.h> +#include "result_p.h" + +#include <gpgme.h> + +#include <cstring> +#include <cassert> + +class GpgME::KeyListResult::Private +{ +public: + Private(const _gpgme_op_keylist_result &r) : res(r) {} + Private(const Private &other) : res(other.res) {} + + _gpgme_op_keylist_result res; +}; + +GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::KeyListResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_keylist_result_t res = gpgme_op_keylist_result(ctx); + if (!res) { + return; + } + d.reset(new Private(*res)); +} + +GpgME::KeyListResult::KeyListResult(const Error &error, const _gpgme_op_keylist_result &res) + : GpgME::Result(error), d(new Private(res)) +{ + +} + +make_standard_stuff(KeyListResult) + +void GpgME::KeyListResult::detach() +{ + if (!d || d.unique()) { + return; + } + d.reset(new Private(*d)); +} + +void GpgME::KeyListResult::mergeWith(const KeyListResult &other) +{ + if (other.isNull()) { + return; + } + if (isNull()) { // just assign + operator=(other); + return; + } + // merge the truncated flag (try to keep detaching to a minimum): + if (other.isTruncated() && !this->isTruncated()) { + assert(other.d); + detach(); + if (!d) { + d.reset(new Private(*other.d)); + } else { + d->res.truncated = true; + } + } + if (! bool(error())) { // only merge the error when there was none yet. + Result::operator=(other); + } +} + +bool GpgME::KeyListResult::isTruncated() const +{ + return d && d->res.truncated; +} diff --git a/lang/cpp/src/keylistresult.h b/lang/cpp/src/keylistresult.h new file mode 100644 index 0000000..7dfe2d7 --- /dev/null +++ b/lang/cpp/src/keylistresult.h @@ -0,0 +1,81 @@ +/* + keylistresult.h - wraps a gpgme keylist result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_KEYLISTRESULT_H__ +#define __GPGMEPP_KEYLISTRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <memory> + +namespace GpgME +{ + +class Error; + +class GPGMEPP_EXPORT KeyListResult : public Result +{ +public: + KeyListResult(); + KeyListResult(gpgme_ctx_t ctx, int error); + KeyListResult(gpgme_ctx_t ctx, const Error &error); + explicit KeyListResult(const Error &err); + KeyListResult(const Error &err, const _gpgme_op_keylist_result &res); + + const KeyListResult &operator=(KeyListResult other) + { + swap(other); + return *this; + } + void swap(KeyListResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + const KeyListResult &operator+=(const KeyListResult &other) + { + mergeWith(other); + return *this; + } + + void mergeWith(const KeyListResult &other); + + bool isNull() const; + + bool isTruncated() const; + +private: + void detach(); + void init(gpgme_ctx_t ctx); + class Private; + std::shared_ptr<Private> d; +}; + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyListResult) + +#endif // __GPGMEPP_KEYLISTRESULT_H__ diff --git a/lang/cpp/src/notation.h b/lang/cpp/src/notation.h new file mode 100644 index 0000000..807bdaa --- /dev/null +++ b/lang/cpp/src/notation.h @@ -0,0 +1,84 @@ +/* + notation.h - wraps a gpgme verify result + Copyright (C) 2004, 2007 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_NOTATION_H__ +#define __GPGMEPP_NOTATION_H__ + +#include "gpgmefw.h" +#include "verificationresult.h" +#include "gpgmepp_export.h" + +#include <memory> + +#include <iosfwd> + +namespace GpgME +{ + +class GPGMEPP_EXPORT Notation +{ + friend class ::GpgME::Signature; + Notation(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex); +public: + Notation(); + explicit Notation(gpgme_sig_notation_t nota); + + const Notation &operator=(Notation other) + { + swap(other); + return *this; + } + + void swap(Notation &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + const char *name() const; + const char *value() const; + + enum Flags { + NoFlags = 0, + HumanReadable = 1, + Critical = 2 + }; + Flags flags() const; + + bool isHumanReadable() const; + bool isCritical() const; + +private: + class Private; + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Notation ¬a); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Notation::Flags flags); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Notation) + +#endif // __GPGMEPP_NOTATION_H__ diff --git a/lang/cpp/src/result.h b/lang/cpp/src/result.h new file mode 100644 index 0000000..a86d81f --- /dev/null +++ b/lang/cpp/src/result.h @@ -0,0 +1,58 @@ +/* + result.h - base class for results + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_RESULT_H__ +#define __GPGMEPP_RESULT_H__ + +#include "gpgmefw.h" +#include "error.h" + +#include <algorithm> // std::swap + +namespace GpgME +{ + +class GPGMEPP_EXPORT Result +{ +protected: + explicit Result() : mError() {} + explicit Result(int err) : mError(err) {} + explicit Result(const Error &err) : mError(err) {} + + void swap(Result &other) + { + std::swap(other.mError, mError); + } + +public: + const Error &error() const + { + return mError; + } + +protected: + Error mError; +}; + +} + +#endif // __GPGMEPP_RESULT_H__ diff --git a/lang/cpp/src/result_p.h b/lang/cpp/src/result_p.h new file mode 100644 index 0000000..0cf73e4 --- /dev/null +++ b/lang/cpp/src/result_p.h @@ -0,0 +1,43 @@ +/* + result.h - base class for results + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_RESULT_P_H__ +#define __GPGMEPP_RESULT_P_H__ + +#define make_default_ctor(x) \ + GpgME::x::x() : GpgME::Result(), d() {} + +#define make_error_ctor(x) \ + GpgME::x::x( const Error & error ) \ + : GpgME::Result( error ), d() \ + { \ + \ + } + +#define make_isNull(x) bool GpgME::x::isNull() const { return !d && !bool(error()); } + +#define make_standard_stuff(x) \ + make_default_ctor(x) \ + make_error_ctor(x) \ + make_isNull(x) + +#endif // __GPGMEPP_RESULT_P_H__ diff --git a/lang/cpp/src/scdgetinfoassuantransaction.cpp b/lang/cpp/src/scdgetinfoassuantransaction.cpp new file mode 100644 index 0000000..073d772 --- /dev/null +++ b/lang/cpp/src/scdgetinfoassuantransaction.cpp @@ -0,0 +1,156 @@ +/* + scdgetinfoassuantransaction.cpp - Assuan Transaction to get information from scdaemon + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "scdgetinfoassuantransaction.h" +#include "error.h" +#include "data.h" +#include "util.h" + +#include <sstream> +#include <assert.h> + +using namespace GpgME; + +ScdGetInfoAssuanTransaction::ScdGetInfoAssuanTransaction(InfoItem item) + : AssuanTransaction(), + m_item(item), + m_command(), + m_data() +{ + +} + +ScdGetInfoAssuanTransaction::~ScdGetInfoAssuanTransaction() {} + +static std::vector<std::string> to_reader_list(const std::string &s) +{ + std::vector<std::string> result; + std::stringstream ss(s); + std::string tok; + while (std::getline(ss, tok, '\n')) { + result.push_back(tok); + } + return result; +} + +static std::vector<std::string> to_app_list(const std::string &s) +{ + return to_reader_list(s); +} + +std::string ScdGetInfoAssuanTransaction::version() const +{ + if (m_item == Version) { + return m_data; + } else { + return std::string(); + } +} + +unsigned int ScdGetInfoAssuanTransaction::pid() const +{ + if (m_item == Pid) { + return to_pid(m_data); + } else { + return 0U; + } +} + +std::string ScdGetInfoAssuanTransaction::socketName() const +{ + if (m_item == SocketName) { + return m_data; + } else { + return std::string(); + } +} + +char ScdGetInfoAssuanTransaction::status() const +{ + if (m_item == Status && !m_data.empty()) { + return m_data[0]; + } else { + return '\0'; + } +} + +std::vector<std::string> ScdGetInfoAssuanTransaction::readerList() const +{ + if (m_item == ReaderList) { + return to_reader_list(m_data); + } else { + return std::vector<std::string>(); + } +} + +std::vector<std::string> ScdGetInfoAssuanTransaction::applicationList() const +{ + if (m_item == ApplicationList) { + return to_app_list(m_data); + } else { + return std::vector<std::string>(); + } +} + +static const char *const scd_getinfo_tokens[] = { + "version", + "pid", + "socket_name", + "status", + "reader_list", + "deny_admin", + "app_list", +}; +static_assert((sizeof scd_getinfo_tokens / sizeof * scd_getinfo_tokens == ScdGetInfoAssuanTransaction::LastInfoItem), + "getinfo_tokens size mismatch"); + +void ScdGetInfoAssuanTransaction::makeCommand() const +{ + assert(m_item >= 0); + assert(m_item < LastInfoItem); + m_command = "SCD GETINFO "; + m_command += scd_getinfo_tokens[m_item]; +} + +const char *ScdGetInfoAssuanTransaction::command() const +{ + makeCommand(); + return m_command.c_str(); +} + +Error ScdGetInfoAssuanTransaction::data(const char *data, size_t len) +{ + m_data.append(data, len); + return Error(); +} + +Data ScdGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err) +{ + (void)name; (void)args; (void)err; + return Data::null; +} + +Error ScdGetInfoAssuanTransaction::status(const char *status, const char *args) +{ + (void)status; (void)args; + return Error(); +} diff --git a/lang/cpp/src/scdgetinfoassuantransaction.h b/lang/cpp/src/scdgetinfoassuantransaction.h new file mode 100644 index 0000000..a22a0ff --- /dev/null +++ b/lang/cpp/src/scdgetinfoassuantransaction.h @@ -0,0 +1,76 @@ +/* + scdgetinfoassuantransaction.h - Assuan Transaction to get information from scdaemon + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__ +#define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__ + +#include <interfaces/assuantransaction.h> + +#include <string> +#include <vector> + +namespace GpgME +{ + +class GPGMEPP_EXPORT ScdGetInfoAssuanTransaction : public AssuanTransaction +{ +public: + enum InfoItem { + Version, // string + Pid, // unsigned long + SocketName, // string (path) + Status, // char (status) + ReaderList, // string list + DenyAdmin, // (none, returns GPG_ERR_GENERAL when admin commands are allowed) + ApplicationList, // string list + + LastInfoItem + }; + + explicit ScdGetInfoAssuanTransaction(InfoItem item); + ~ScdGetInfoAssuanTransaction(); + + std::string version() const; + unsigned int pid() const; + std::string socketName() const; + char status() const; + std::vector<std::string> readerList() const; + std::vector<std::string> applicationList() const; + +private: + /* reimp */ const char *command() const; + /* reimp */ Error data(const char *data, size_t datalen); + /* reimp */ Data inquire(const char *name, const char *args, Error &err); + /* reimp */ Error status(const char *status, const char *args); + +private: + void makeCommand() const; + +private: + InfoItem m_item; + mutable std::string m_command; + std::string m_data; +}; + +} // namespace GpgME + +#endif // __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__ diff --git a/lang/cpp/src/signingresult.cpp b/lang/cpp/src/signingresult.cpp new file mode 100644 index 0000000..4f2ef72 --- /dev/null +++ b/lang/cpp/src/signingresult.cpp @@ -0,0 +1,265 @@ +/* + signingresult.cpp - wraps a gpgme verify result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <signingresult.h> +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> +#include <algorithm> +#include <istream> +#include <iterator> + +#include <string.h> + +class GpgME::SigningResult::Private +{ +public: + Private(const gpgme_sign_result_t r) + { + if (!r) { + return; + } + for (gpgme_new_signature_t is = r->signatures ; is ; is = is->next) { + gpgme_new_signature_t copy = new _gpgme_new_signature(*is); + if (is->fpr) { + copy->fpr = strdup(is->fpr); + } + copy->next = 0; + created.push_back(copy); + } + for (gpgme_invalid_key_t ik = r->invalid_signers ; ik ; ik = ik->next) { + gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik); + if (ik->fpr) { + copy->fpr = strdup(ik->fpr); + } + copy->next = 0; + invalid.push_back(copy); + } + } + ~Private() + { + for (std::vector<gpgme_new_signature_t>::iterator it = created.begin() ; it != created.end() ; ++it) { + std::free((*it)->fpr); + delete *it; *it = 0; + } + for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) { + std::free((*it)->fpr); + delete *it; *it = 0; + } + } + + std::vector<gpgme_new_signature_t> created; + std::vector<gpgme_invalid_key_t> invalid; +}; + +GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::SigningResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_sign_result_t res = gpgme_op_sign_result(ctx); + if (!res) { + return; + } + d.reset(new Private(res)); +} + +make_standard_stuff(SigningResult) + +GpgME::CreatedSignature GpgME::SigningResult::createdSignature(unsigned int idx) const +{ + return CreatedSignature(d, idx); +} + +std::vector<GpgME::CreatedSignature> GpgME::SigningResult::createdSignatures() const +{ + if (!d) { + return std::vector<CreatedSignature>(); + } + std::vector<CreatedSignature> result; + result.reserve(d->created.size()); + for (unsigned int i = 0 ; i < d->created.size() ; ++i) { + result.push_back(CreatedSignature(d, i)); + } + return result; +} + +GpgME::InvalidSigningKey GpgME::SigningResult::invalidSigningKey(unsigned int idx) const +{ + return InvalidSigningKey(d, idx); +} + +std::vector<GpgME::InvalidSigningKey> GpgME::SigningResult::invalidSigningKeys() const +{ + if (!d) { + return std::vector<GpgME::InvalidSigningKey>(); + } + std::vector<GpgME::InvalidSigningKey> result; + result.reserve(d->invalid.size()); + for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) { + result.push_back(InvalidSigningKey(d, i)); + } + return result; +} + +GpgME::InvalidSigningKey::InvalidSigningKey(const std::shared_ptr<SigningResult::Private> &parent, unsigned int i) + : d(parent), idx(i) +{ + +} + +GpgME::InvalidSigningKey::InvalidSigningKey() : d(), idx(0) {} + +bool GpgME::InvalidSigningKey::isNull() const +{ + return !d || idx >= d->invalid.size() ; +} + +const char *GpgME::InvalidSigningKey::fingerprint() const +{ + return isNull() ? 0 : d->invalid[idx]->fpr ; +} + +GpgME::Error GpgME::InvalidSigningKey::reason() const +{ + return Error(isNull() ? 0 : d->invalid[idx]->reason); +} + +GpgME::CreatedSignature::CreatedSignature(const std::shared_ptr<SigningResult::Private> &parent, unsigned int i) + : d(parent), idx(i) +{ + +} + +GpgME::CreatedSignature::CreatedSignature() : d(), idx(0) {} + +bool GpgME::CreatedSignature::isNull() const +{ + return !d || idx >= d->created.size() ; +} + +const char *GpgME::CreatedSignature::fingerprint() const +{ + return isNull() ? 0 : d->created[idx]->fpr ; +} + +time_t GpgME::CreatedSignature::creationTime() const +{ + return static_cast<time_t>(isNull() ? 0 : d->created[idx]->timestamp); +} + +GpgME::SignatureMode GpgME::CreatedSignature::mode() const +{ + if (isNull()) { + return NormalSignatureMode; + } + switch (d->created[idx]->type) { + default: + case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode; + case GPGME_SIG_MODE_DETACH: return Detached; + case GPGME_SIG_MODE_CLEAR: return Clearsigned; + } +} + +unsigned int GpgME::CreatedSignature::publicKeyAlgorithm() const +{ + return isNull() ? 0 : d->created[idx]->pubkey_algo ; +} + +const char *GpgME::CreatedSignature::publicKeyAlgorithmAsString() const +{ + return gpgme_pubkey_algo_name(isNull() ? (gpgme_pubkey_algo_t)0 : d->created[idx]->pubkey_algo); +} + +unsigned int GpgME::CreatedSignature::hashAlgorithm() const +{ + return isNull() ? 0 : d->created[idx]->hash_algo ; +} + +const char *GpgME::CreatedSignature::hashAlgorithmAsString() const +{ + return gpgme_hash_algo_name(isNull() ? (gpgme_hash_algo_t)0 : d->created[idx]->hash_algo); +} + +unsigned int GpgME::CreatedSignature::signatureClass() const +{ + return isNull() ? 0 : d->created[idx]->sig_class ; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const SigningResult &result) +{ + os << "GpgME::SigningResult("; + if (!result.isNull()) { + os << "\n error: " << result.error() + << "\n createdSignatures:\n"; + const std::vector<CreatedSignature> cs = result.createdSignatures(); + std::copy(cs.begin(), cs.end(), + std::ostream_iterator<CreatedSignature>(os, "\n")); + os << " invalidSigningKeys:\n"; + const std::vector<InvalidSigningKey> isk = result.invalidSigningKeys(); + std::copy(isk.begin(), isk.end(), + std::ostream_iterator<InvalidSigningKey>(os, "\n")); + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const CreatedSignature &sig) +{ + os << "GpgME::CreatedSignature("; + if (!sig.isNull()) { + os << "\n fingerprint: " << protect(sig.fingerprint()) + << "\n creationTime: " << sig.creationTime() + << "\n mode: " << sig.mode() + << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString()) + << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString()) + << "\n signatureClass: " << sig.signatureClass() + << '\n'; + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const InvalidSigningKey &key) +{ + os << "GpgME::InvalidSigningKey("; + if (!key.isNull()) { + os << "\n fingerprint: " << protect(key.fingerprint()) + << "\n reason: " << key.reason() + << '\n'; + } + return os << ')'; +} diff --git a/lang/cpp/src/signingresult.h b/lang/cpp/src/signingresult.h new file mode 100644 index 0000000..2c27454 --- /dev/null +++ b/lang/cpp/src/signingresult.h @@ -0,0 +1,162 @@ +/* + signingresult.h - wraps a gpgme sign result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_SIGNINGRESULT_H__ +#define __GPGMEPP_SIGNINGRESULT_H__ + +#include "global.h" +#include "result.h" + +#include <time.h> + +#include <memory> + +#include <vector> +#include <iosfwd> + +namespace GpgME +{ + +class Error; +class CreatedSignature; +class InvalidSigningKey; + +class GPGMEPP_EXPORT SigningResult : public Result +{ +public: + SigningResult(); + SigningResult(gpgme_ctx_t ctx, int error); + SigningResult(gpgme_ctx_t ctx, const Error &error); + explicit SigningResult(const Error &err); + + const SigningResult &operator=(SigningResult other) + { + swap(other); + return *this; + } + + void swap(SigningResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + CreatedSignature createdSignature(unsigned int index) const; + std::vector<CreatedSignature> createdSignatures() const; + + InvalidSigningKey invalidSigningKey(unsigned int index) const; + std::vector<InvalidSigningKey> invalidSigningKeys() const; + + class Private; +private: + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const SigningResult &result); + +class GPGMEPP_EXPORT InvalidSigningKey +{ + friend class ::GpgME::SigningResult; + InvalidSigningKey(const std::shared_ptr<SigningResult::Private> &parent, unsigned int index); +public: + InvalidSigningKey(); + + const InvalidSigningKey &operator=(InvalidSigningKey other) + { + swap(other); + return *this; + } + + void swap(InvalidSigningKey &other) + { + using std::swap; + swap(this->d, other.d); + swap(this->idx, other.idx); + } + + bool isNull() const; + + const char *fingerprint() const; + Error reason() const; + +private: + std::shared_ptr<SigningResult::Private> d; + unsigned int idx; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidSigningKey &key); + +class GPGMEPP_EXPORT CreatedSignature +{ + friend class ::GpgME::SigningResult; + CreatedSignature(const std::shared_ptr<SigningResult::Private> &parent, unsigned int index); +public: + + CreatedSignature(); + + const CreatedSignature &operator=(CreatedSignature other) + { + swap(other); + return *this; + } + + void swap(CreatedSignature &other) + { + using std::swap; + swap(this->d, other.d); + swap(this->idx, other.idx); + } + + bool isNull() const; + + const char *fingerprint() const; + + time_t creationTime() const; + + SignatureMode mode() const; + + unsigned int publicKeyAlgorithm() const; + const char *publicKeyAlgorithmAsString() const; + + unsigned int hashAlgorithm() const; + const char *hashAlgorithmAsString() const; + + unsigned int signatureClass() const; + +private: + std::shared_ptr<SigningResult::Private> d; + unsigned int idx; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const CreatedSignature &sig); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(SigningResult) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidSigningKey) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(CreatedSignature) + +#endif // __GPGMEPP_SIGNINGRESULT_H__ diff --git a/lang/cpp/src/tofuinfo.cpp b/lang/cpp/src/tofuinfo.cpp new file mode 100644 index 0000000..bb67fc8 --- /dev/null +++ b/lang/cpp/src/tofuinfo.cpp @@ -0,0 +1,167 @@ +/* tofuinfo.cpp - wraps gpgme tofu info + Copyright (C) 2016 Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tofuinfo.h" + +#include <istream> +#include "util.h" + +class GpgME::TofuInfo::Private +{ +public: + Private() {} + Private(gpgme_tofu_info_t info) + : mInfo(info ? new _gpgme_tofu_info(*info) : nullptr) + { + if (mInfo && mInfo->description) { + mInfo->description = strdup(mInfo->description); + } + } + + Private(const Private &other) + : mInfo(other.mInfo) + { + if (mInfo && mInfo->description) { + mInfo->description = strdup(mInfo->description); + } + } + + ~Private() + { + if (mInfo) { + std::free(mInfo->description); + mInfo->description = nullptr; + + delete mInfo; + } + } + + gpgme_tofu_info_t mInfo; +}; + +GpgME::TofuInfo::TofuInfo(gpgme_tofu_info_t info) + : d(new Private(info)) +{ +} + +GpgME::TofuInfo::TofuInfo() : d() +{ +} + +bool GpgME::TofuInfo::isNull() const +{ + return !d || !d->mInfo; +} + +GpgME::TofuInfo::Validity GpgME::TofuInfo::validity() const +{ + if (isNull()) { + return ValidityUnknown; + } + switch (d->mInfo->validity) { + case 0: + return Conflict; + case 1: + return NoHistory; + case 2: + return LittleHistory; + case 3: + return BasicHistory; + case 4: + return LargeHistory; + default: + return ValidityUnknown; + } +} + +GpgME::TofuInfo::Policy GpgME::TofuInfo::policy() const +{ + if (isNull()) { + return PolicyUnknown; + } + switch (d->mInfo->policy) { + case GPGME_TOFU_POLICY_NONE: + return PolicyNone; + case GPGME_TOFU_POLICY_AUTO: + return PolicyAuto; + case GPGME_TOFU_POLICY_GOOD: + return PolicyGood; + case GPGME_TOFU_POLICY_BAD: + return PolicyBad; + case GPGME_TOFU_POLICY_ASK: + return PolicyAsk; + case GPGME_TOFU_POLICY_UNKNOWN: + return PolicyUnknown; + } +} + +const char *GpgME::TofuInfo::description() const +{ + return isNull() ? nullptr : d->mInfo->description; +} + +unsigned short GpgME::TofuInfo::signCount() const +{ + return isNull() ? 0 : d->mInfo->signcount; +} + +unsigned short GpgME::TofuInfo::encrCount() const +{ + return isNull() ? 0 : d->mInfo->encrcount; +} + +unsigned long GpgME::TofuInfo::signFirst() const +{ + return isNull() ? 0 : d->mInfo->signfirst; +} + +unsigned long GpgME::TofuInfo::signLast() const +{ + return isNull() ? 0 : d->mInfo->signlast; +} + +unsigned long GpgME::TofuInfo::encrFirst() const +{ + return isNull() ? 0 : d->mInfo->encrfirst; +} + +unsigned long GpgME::TofuInfo::encrLast() const +{ + return isNull() ? 0 : d->mInfo->encrlast; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const GpgME::TofuInfo &info) +{ + os << "GpgME::Signature::TofuInfo("; + if (!info.isNull()) { + os << "\n desc: " << protect(info.description()) + << "\n validity: " << info.validity() + << "\n policy: " << info.policy() + << "\n signcount: "<< info.signCount() + << "\n signfirst: "<< info.signFirst() + << "\n signlast: " << info.signLast() + << "\n encrcount: "<< info.encrCount() + << "\n encrfirst: "<< info.encrFirst() + << "\n encrlast: " << info.encrLast() + << '\n'; + } + return os << ")"; +} diff --git a/lang/cpp/src/tofuinfo.h b/lang/cpp/src/tofuinfo.h new file mode 100644 index 0000000..c09c82a --- /dev/null +++ b/lang/cpp/src/tofuinfo.h @@ -0,0 +1,124 @@ +/* + tofuinfo.h - wraps gpgme tofu info + Copyright (C) 2016 Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_TOFUINFO_H__ +#define __GPGMEPP_TOFUINFO_H__ + +#include "gpgmepp_export.h" + +#include "gpgme.h" + +#include "global.h" + +#include <memory> + +namespace GpgME +{ + +class GPGMEPP_EXPORT TofuInfo +{ +public: + TofuInfo(); + explicit TofuInfo(gpgme_tofu_info_t info); + + const TofuInfo &operator=(TofuInfo other) + { + swap(other); + return *this; + } + + void swap(TofuInfo &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + /* @enum Validity + * @brief The TOFU Validity. */ + enum Validity : unsigned int { + /*! Unknown (uninitialized).*/ + ValidityUnknown, + /*! TOFU Conflict.*/ + Conflict, + /*! Key without history.*/ + NoHistory, + /*! Key with too little history.*/ + LittleHistory, + /*! Key with enough history for basic trust.*/ + BasicHistory, + /*! Key with a lot of history.*/ + LargeHistory, + }; + Validity validity() const; + + /* @enum Policy + * @brief The TOFU Validity. */ + enum Policy : unsigned int { + /*! GPGME_TOFU_POLICY_NONE */ + PolicyNone, + /*! GPGME_TOFU_POLICY_AUTO */ + PolicyAuto, + /*! GPGME_TOFU_POLICY_GOOD */ + PolicyGood, + /*! GPGME_TOFU_POLICY_UNKNOWN */ + PolicyUnknown, + /*! GPGME_TOFU_POLICY_BAD */ + PolicyBad, + /*! GPGME_TOFU_POLICY_ASK */ + PolicyAsk, + }; + Policy policy() const; + + /* Number of signatures seen for this binding. Capped at USHRT_MAX. */ + unsigned short signCount() const; + + /* Number of encryption done to this binding. Capped at USHRT_MAX. */ + unsigned short encrCount() const; + + /** Number of seconds since epoch when the first message was verified */ + unsigned long signFirst() const; + + /** Number of seconds since epoch when the last message was verified */ + unsigned long signLast() const; + + /** Number of seconds since epoch when the first message was encrypted */ + unsigned long encrFirst() const; + + /** Number of seconds since epoch when the last message was encrypted */ + unsigned long encrLast() const; + + /* If non-NULL a human readable string summarizing the TOFU data. */ + const char *description() const; + +private: + class Private; + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const TofuInfo &info); + +} // namespace GpgME + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TofuInfo) +#endif // __GPGMEPP_TOFUINFO_H__ diff --git a/lang/cpp/src/trustitem.cpp b/lang/cpp/src/trustitem.cpp new file mode 100644 index 0000000..fc7e4a6 --- /dev/null +++ b/lang/cpp/src/trustitem.cpp @@ -0,0 +1,114 @@ +/* + trustitem.cpp - wraps a gpgme trust item + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <trustitem.h> + +#include <gpgme.h> + +#include <cassert> + +namespace GpgME +{ + +class TrustItem::Private +{ +public: + Private(gpgme_trust_item_t aItem) + : item(aItem) + { + } + + gpgme_trust_item_t item; +}; + +TrustItem::TrustItem(gpgme_trust_item_t item) +{ + d = new Private(item); + if (d->item) { + gpgme_trust_item_ref(d->item); + } +} + +TrustItem::TrustItem(const TrustItem &other) +{ + d = new Private(other.d->item); + if (d->item) { + gpgme_trust_item_ref(d->item); + } +} + +TrustItem::~TrustItem() +{ + if (d->item) { + gpgme_trust_item_unref(d->item); + } + delete d; d = 0; +} + +bool TrustItem::isNull() const +{ + return !d || !d->item; +} + +gpgme_trust_item_t TrustItem::impl() const +{ + return d->item; +} + +const char *TrustItem::keyID() const +{ + return d->item ? d->item->keyid : 0 ; +} + +const char *TrustItem::userID() const +{ + return d->item ? d->item->name : 0 ; +} + +const char *TrustItem::ownerTrustAsString() const +{ + return d->item ? d->item->owner_trust : 0 ; +} + +const char *TrustItem::validityAsString() const +{ + return d->item ? d->item->validity : 0 ; +} + +int TrustItem::trustLevel() const +{ + return d->item ? d->item->level : 0 ; +} + +TrustItem::Type TrustItem::type() const +{ + if (!d->item) { + return Unknown; + } else { + return + d->item->type == 1 ? Key : + d->item->type == 2 ? UserID : + Unknown ; + } +} + +} // namespace GpgME diff --git a/lang/cpp/src/trustitem.h b/lang/cpp/src/trustitem.h new file mode 100644 index 0000000..65f109c --- /dev/null +++ b/lang/cpp/src/trustitem.h @@ -0,0 +1,81 @@ +/* + trustitem.h - wraps a gpgme trust item + Copyright (C) 2003 Klarälvdalens Datakonsult AB + + This file is part of GPGME. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_TRUSTITEM_H__ +#define __GPGMEPP_TRUSTITEM_H__ + +#include "gpgmefw.h" +#include <key.h> +#include "gpgmepp_export.h" + +#include <algorithm> + +namespace GpgME +{ + +class Context; + +class GPGMEPP_EXPORT TrustItem +{ + friend class ::GpgME::Context; +public: + explicit TrustItem(gpgme_trust_item_t item = 0); + TrustItem(const TrustItem &other); + virtual ~TrustItem(); + + const TrustItem &operator=(TrustItem other) + { + swap(other); + return *this; + } + + void swap(TrustItem &other) + { + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + const char *keyID() const; + const char *userID() const; + + const char *ownerTrustAsString() const; + const char *validityAsString() const; + + int trustLevel() const; + + enum Type { Unknown = 0, Key = 1, UserID = 2 }; + Type type() const; + +private: + gpgme_trust_item_t impl() const; + class Private; + Private *d; +}; + +} // namepace GpgME + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TrustItem) + +#endif // __GPGMEPP_TRUSTITEM_H__ diff --git a/lang/cpp/src/util.h b/lang/cpp/src/util.h new file mode 100644 index 0000000..b0d47e3 --- /dev/null +++ b/lang/cpp/src/util.h @@ -0,0 +1,149 @@ +/* + util.h - some inline helper functions + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// -*- c++ -*- +#ifndef __GPGMEPP_UTIL_H__ +#define __GPGMEPP_UTIL_H__ + +#include "global.h" +#include "notation.h" + +#include <gpgme.h> + +#ifndef NDEBUG +#include <iostream> +#endif +#include <sstream> +#include <string> + +static inline const char *protect(const char *s) +{ + return s ? s : "<null>" ; +} + +static inline gpgme_error_t make_error(gpgme_err_code_t code) +{ + return gpgme_err_make((gpgme_err_source_t)22, code); +} + +static inline unsigned long to_pid(const std::string &s) +{ + std::stringstream ss(s); + unsigned int result; + if (ss >> result) { + return result; + } else { + return 0U; + } +} + +static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t(unsigned int oldmode, unsigned int newmodes) +{ + if (newmodes & GpgME::Local) { + oldmode |= GPGME_KEYLIST_MODE_LOCAL; + } + if (newmodes & GpgME::Extern) { + oldmode |= GPGME_KEYLIST_MODE_EXTERN; + } + if (newmodes & GpgME::Signatures) { + oldmode |= GPGME_KEYLIST_MODE_SIGS; + } + if (newmodes & GpgME::SignatureNotations) { + oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS; + } + if (newmodes & GpgME::Ephemeral) { + oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL; + } + if (newmodes & GpgME::Validate) { + oldmode |= GPGME_KEYLIST_MODE_VALIDATE; + } + if (newmodes & GpgME::WithTofu) { + oldmode |= GPGME_KEYLIST_MODE_WITH_TOFU; + } +#ifndef NDEBUG + if (newmodes & ~(GpgME::Local | GpgME::Extern | GpgME::Signatures | GpgME::SignatureNotations | GpgME::Ephemeral | GpgME::Validate)) { + //std::cerr << "GpgME::Context: keylist mode must be one of Local, " + //"Extern, Signatures, SignatureNotations, or Validate, or a combination thereof!" << std::endl; + } +#endif + return static_cast<gpgme_keylist_mode_t>(oldmode); +} + +static inline unsigned int convert_from_gpgme_keylist_mode_t(unsigned int mode) +{ + unsigned int result = 0; + if (mode & GPGME_KEYLIST_MODE_LOCAL) { + result |= GpgME::Local; + } + if (mode & GPGME_KEYLIST_MODE_EXTERN) { + result |= GpgME::Extern; + } + if (mode & GPGME_KEYLIST_MODE_SIGS) { + result |= GpgME::Signatures; + } + if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) { + result |= GpgME::SignatureNotations; + } + if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) { + result |= GpgME::Ephemeral; + } + if (mode & GPGME_KEYLIST_MODE_VALIDATE) { + result |= GpgME::Validate; + } +#ifndef NDEBUG + if (mode & ~(GPGME_KEYLIST_MODE_LOCAL | + GPGME_KEYLIST_MODE_EXTERN | + GPGME_KEYLIST_MODE_SIG_NOTATIONS | + GPGME_KEYLIST_MODE_EPHEMERAL | + GPGME_KEYLIST_MODE_VALIDATE | + GPGME_KEYLIST_MODE_SIGS)) { + //std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl; + } +#endif // NDEBUG + return result; +} + +static inline GpgME::Notation::Flags convert_from_gpgme_sig_notation_flags_t(unsigned int flags) +{ + unsigned int result = 0; + if (flags & GPGME_SIG_NOTATION_HUMAN_READABLE) { + result |= GpgME::Notation::HumanReadable ; + } + if (flags & GPGME_SIG_NOTATION_CRITICAL) { + result |= GpgME::Notation::Critical ; + } + return static_cast<GpgME::Notation::Flags>(result); +} + +static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsigned int oldflags, unsigned int newflags) +{ + unsigned int result = oldflags; + if (newflags & GpgME::Notation::HumanReadable) { + result |= GPGME_SIG_NOTATION_HUMAN_READABLE; + } + if (newflags & GpgME::Notation::Critical) { + result |= GPGME_SIG_NOTATION_CRITICAL; + } + return static_cast<gpgme_sig_notation_flags_t>(result); +} + +#endif // __GPGMEPP_UTIL_H__ diff --git a/lang/cpp/src/verificationresult.cpp b/lang/cpp/src/verificationresult.cpp new file mode 100644 index 0000000..c62625d --- /dev/null +++ b/lang/cpp/src/verificationresult.cpp @@ -0,0 +1,575 @@ +/* + verificationresult.cpp - wraps a gpgme verify result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <verificationresult.h> +#include <notation.h> +#include "result_p.h" +#include "util.h" +#include "key.h" + +#include <gpgme.h> + +#include <istream> +#include <algorithm> +#include <iterator> +#include <string> +#include <cstring> +#include <cstdlib> + +#include <string.h> + +class GpgME::VerificationResult::Private +{ +public: + explicit Private(const gpgme_verify_result_t r) + { + if (!r) { + return; + } + if (r->file_name) { + file_name = r->file_name; + } + // 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); + } +// PENDING(marc) why does this crash on Windows in strdup()? +# ifndef _WIN32 + if (is->pka_address) { + scopy->pka_address = strdup(is->pka_address); + } +# else + scopy->pka_address = 0; +# endif + scopy->next = 0; + sigs.push_back(scopy); + // copy keys + if (scopy->key) { + keys.push_back(Key(scopy->key, true)); + } + // 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, in->flags }; + 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); + std::free((*it)->pka_address); + 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; + gpgme_sig_notation_flags_t flags; + }; + + std::vector<gpgme_signature_t> sigs; + std::vector< std::vector<Nota> > nota; + std::vector<GpgME::Key> keys; + std::vector<char *> purls; + std::string file_name; +}; + +GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, int error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, const Error &error) + : GpgME::Result(error), d() +{ + init(ctx); +} + +void GpgME::VerificationResult::init(gpgme_ctx_t ctx) +{ + if (!ctx) { + return; + } + gpgme_verify_result_t res = gpgme_op_verify_result(ctx); + if (!res) { + return; + } + d.reset(new Private(res)); +} + +make_standard_stuff(VerificationResult) + +const char *GpgME::VerificationResult::fileName() const +{ + return d ? d->file_name.c_str() : 0 ; +} + +unsigned int GpgME::VerificationResult::numSignatures() const +{ + return d ? d->sigs.size() : 0 ; +} + +GpgME::Signature GpgME::VerificationResult::signature(unsigned int idx) const +{ + return Signature(d, idx); +} + +std::vector<GpgME::Signature> GpgME::VerificationResult::signatures() const +{ + if (!d) { + return std::vector<Signature>(); + } + std::vector<Signature> result; + result.reserve(d->sigs.size()); + for (unsigned int i = 0 ; i < d->sigs.size() ; ++i) { + result.push_back(Signature(d, i)); + } + return result; +} + +GpgME::Signature::Signature(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int i) + : d(parent), idx(i) +{ +} + +GpgME::Signature::Signature() : d(), idx(0) {} + +bool GpgME::Signature::isNull() const +{ + return !d || idx >= d->sigs.size() ; +} + +GpgME::Signature::Summary GpgME::Signature::summary() const +{ + if (isNull()) { + return None; + } + gpgme_sigsum_t sigsum = d->sigs[idx]->summary; + unsigned int result = 0; + if (sigsum & GPGME_SIGSUM_VALID) { + result |= Valid; + } + if (sigsum & GPGME_SIGSUM_GREEN) { + result |= Green; + } + if (sigsum & GPGME_SIGSUM_RED) { + result |= Red; + } + if (sigsum & GPGME_SIGSUM_KEY_REVOKED) { + result |= KeyRevoked; + } + if (sigsum & GPGME_SIGSUM_KEY_EXPIRED) { + result |= KeyExpired; + } + if (sigsum & GPGME_SIGSUM_SIG_EXPIRED) { + result |= SigExpired; + } + if (sigsum & GPGME_SIGSUM_KEY_MISSING) { + result |= KeyMissing; + } + if (sigsum & GPGME_SIGSUM_CRL_MISSING) { + result |= CrlMissing; + } + if (sigsum & GPGME_SIGSUM_CRL_TOO_OLD) { + result |= CrlTooOld; + } + if (sigsum & GPGME_SIGSUM_BAD_POLICY) { + result |= BadPolicy; + } + if (sigsum & GPGME_SIGSUM_SYS_ERROR) { + result |= SysError; + } + if (sigsum & GPGME_SIGSUM_TOFU_CONFLICT) { + result |= TofuConflict; + } + return static_cast<Summary>(result); +} + +const char *GpgME::Signature::fingerprint() const +{ + return isNull() ? 0 : d->sigs[idx]->fpr ; +} + +GpgME::Error GpgME::Signature::status() const +{ + return Error(isNull() ? 0 : d->sigs[idx]->status); +} + +time_t GpgME::Signature::creationTime() const +{ + return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->timestamp); +} + +time_t GpgME::Signature::expirationTime() const +{ + return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->exp_timestamp); +} + +bool GpgME::Signature::neverExpires() const +{ + return expirationTime() == (time_t)0; +} + +bool GpgME::Signature::isWrongKeyUsage() const +{ + return !isNull() && d->sigs[idx]->wrong_key_usage; +} + +bool GpgME::Signature::isVerifiedUsingChainModel() const +{ + return !isNull() && d->sigs[idx]->chain_model; +} + +GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const +{ + if (!isNull()) { + return static_cast<PKAStatus>(d->sigs[idx]->pka_trust); + } + return UnknownPKAStatus; +} + +const char *GpgME::Signature::pkaAddress() const +{ + if (!isNull()) { + return d->sigs[idx]->pka_address; + } + return 0; +} + +GpgME::Signature::Validity GpgME::Signature::validity() const +{ + if (isNull()) { + return Unknown; + } + switch (d->sigs[idx]->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return Unknown; + case GPGME_VALIDITY_UNDEFINED: return Undefined; + case GPGME_VALIDITY_NEVER: return Never; + case GPGME_VALIDITY_MARGINAL: return Marginal; + case GPGME_VALIDITY_FULL: return Full; + case GPGME_VALIDITY_ULTIMATE: return Ultimate; + } +} + +char GpgME::Signature::validityAsString() const +{ + if (isNull()) { + return '?'; + } + switch (d->sigs[idx]->validity) { + default: + case GPGME_VALIDITY_UNKNOWN: return '?'; + case GPGME_VALIDITY_UNDEFINED: return 'q'; + case GPGME_VALIDITY_NEVER: return 'n'; + case GPGME_VALIDITY_MARGINAL: return 'm'; + case GPGME_VALIDITY_FULL: return 'f'; + case GPGME_VALIDITY_ULTIMATE: return 'u'; + } +} + +GpgME::Error GpgME::Signature::nonValidityReason() const +{ + return Error(isNull() ? 0 : d->sigs[idx]->validity_reason); +} + +unsigned int GpgME::Signature::publicKeyAlgorithm() const +{ + if (!isNull()) { + return d->sigs[idx]->pubkey_algo; + } + return 0; +} + +const char *GpgME::Signature::publicKeyAlgorithmAsString() const +{ + if (!isNull()) { + return gpgme_pubkey_algo_name(d->sigs[idx]->pubkey_algo); + } + return 0; +} + +unsigned int GpgME::Signature::hashAlgorithm() const +{ + if (!isNull()) { + return d->sigs[idx]->hash_algo; + } + return 0; +} + +const char *GpgME::Signature::hashAlgorithmAsString() const +{ + if (!isNull()) { + return gpgme_hash_algo_name(d->sigs[idx]->hash_algo); + } + return 0; +} + +const char *GpgME::Signature::policyURL() const +{ + return isNull() ? 0 : d->purls[idx] ; +} + +GpgME::Notation GpgME::Signature::notation(unsigned int nidx) const +{ + return GpgME::Notation(d, idx, nidx); +} + +std::vector<GpgME::Notation> GpgME::Signature::notations() const +{ + if (isNull()) { + return std::vector<GpgME::Notation>(); + } + std::vector<GpgME::Notation> result; + result.reserve(d->nota[idx].size()); + for (unsigned int i = 0 ; i < d->nota[idx].size() ; ++i) { + result.push_back(GpgME::Notation(d, idx, i)); + } + return result; +} + +GpgME::Key GpgME::Signature::key() const +{ + if (isNull()) { + return Key(); + } + return d->keys[idx]; +} + +class GpgME::Notation::Private +{ +public: + Private() : d(), sidx(0), nidx(0), nota(0) {} + Private(const std::shared_ptr<VerificationResult::Private> &priv, unsigned int sindex, unsigned int nindex) + : d(priv), sidx(sindex), nidx(nindex), nota(0) + { + + } + Private(gpgme_sig_notation_t n) + : d(), sidx(0), nidx(0), nota(n ? new _gpgme_sig_notation(*n) : 0) + { + if (nota && nota->name) { + nota->name = strdup(nota->name); + } + if (nota && nota->value) { + nota->value = strdup(nota->value); + } + } + Private(const Private &other) + : d(other.d), sidx(other.sidx), nidx(other.nidx), nota(other.nota) + { + if (nota) { + nota->name = strdup(nota->name); + nota->value = strdup(nota->value); + } + } + ~Private() + { + if (nota) { + std::free(nota->name); nota->name = 0; + std::free(nota->value); nota->value = 0; + delete nota; + } + } + + std::shared_ptr<VerificationResult::Private> d; + unsigned int sidx, nidx; + gpgme_sig_notation_t nota; +}; + +GpgME::Notation::Notation(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex) + : d(new Private(parent, sindex, nindex)) +{ + +} + +GpgME::Notation::Notation(gpgme_sig_notation_t nota) + : d(new Private(nota)) +{ + +} + +GpgME::Notation::Notation() : d() {} + +bool GpgME::Notation::isNull() const +{ + if (!d) { + return true; + } + if (d->d) { + return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ; + } + return !d->nota; +} + +const char *GpgME::Notation::name() const +{ + return + isNull() ? 0 : + d->d ? d->d->nota[d->sidx][d->nidx].name : + d->nota ? d->nota->name : 0 ; +} + +const char *GpgME::Notation::value() const +{ + return + isNull() ? 0 : + d->d ? d->d->nota[d->sidx][d->nidx].value : + d->nota ? d->nota->value : 0 ; +} + +GpgME::Notation::Flags GpgME::Notation::flags() const +{ + return + convert_from_gpgme_sig_notation_flags_t( + isNull() ? 0 : + d->d ? d->d->nota[d->sidx][d->nidx].flags : + d->nota ? d->nota->flags : 0); +} + +bool GpgME::Notation::isHumanReadable() const +{ + return flags() & HumanReadable; +} + +bool GpgME::Notation::isCritical() const +{ + return flags() & Critical; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const VerificationResult &result) +{ + os << "GpgME::VerificationResult("; + if (!result.isNull()) { + os << "\n error: " << result.error() + << "\n fileName: " << protect(result.fileName()) + << "\n signatures:\n"; + const std::vector<Signature> sigs = result.signatures(); + std::copy(sigs.begin(), sigs.end(), + std::ostream_iterator<Signature>(os, "\n")); + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, Signature::PKAStatus pkaStatus) +{ +#define OUTPUT( x ) if ( !(pkaStatus & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0) + os << "GpgME::Signature::PKAStatus("; + OUTPUT(UnknownPKAStatus); + OUTPUT(PKAVerificationFailed); + OUTPUT(PKAVerificationSucceeded); +#undef OUTPUT + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary) +{ +#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0) + os << "GpgME::Signature::Summary("; + OUTPUT(Valid); + OUTPUT(Green); + OUTPUT(Red); + OUTPUT(KeyRevoked); + OUTPUT(KeyExpired); + OUTPUT(SigExpired); + OUTPUT(KeyMissing); + OUTPUT(CrlMissing); + OUTPUT(CrlTooOld); + OUTPUT(BadPolicy); + OUTPUT(SysError); + OUTPUT(TofuConflict); +#undef OUTPUT + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig) +{ + os << "GpgME::Signature("; + if (!sig.isNull()) { + os << "\n Summary: " << sig.summary() + << "\n Fingerprint: " << protect(sig.fingerprint()) + << "\n Status: " << sig.status() + << "\n creationTime: " << sig.creationTime() + << "\n expirationTime: " << sig.expirationTime() + << "\n isWrongKeyUsage: " << sig.isWrongKeyUsage() + << "\n isVerifiedUsingChainModel: " << sig.isVerifiedUsingChainModel() + << "\n pkaStatus: " << sig.pkaStatus() + << "\n pkaAddress: " << protect(sig.pkaAddress()) + << "\n validity: " << sig.validityAsString() + << "\n nonValidityReason: " << sig.nonValidityReason() + << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString()) + << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString()) + << "\n policyURL: " << protect(sig.policyURL()) + << "\n notations:\n"; + const std::vector<Notation> nota = sig.notations(); + std::copy(nota.begin(), nota.end(), + std::ostream_iterator<Notation>(os, "\n")); + } + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags) +{ + os << "GpgME::Notation::Flags("; +#define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0) + OUTPUT(HumanReadable); + OUTPUT(Critical); +#undef OUTPUT + return os << ')'; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const Notation ¬a) +{ + os << "GpgME::Signature::Notation("; + if (!nota.isNull()) { + os << "\n name: " << protect(nota.name()) + << "\n value: " << protect(nota.value()) + << "\n flags: " << nota.flags() + << '\n'; + } + return os << ")"; +} diff --git a/lang/cpp/src/verificationresult.h b/lang/cpp/src/verificationresult.h new file mode 100644 index 0000000..93288af --- /dev/null +++ b/lang/cpp/src/verificationresult.h @@ -0,0 +1,180 @@ +/* + verificationresult.h - wraps a gpgme verify result + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_VERIFICATIONRESULT_H__ +#define __GPGMEPP_VERIFICATIONRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <time.h> + +#include <memory> + +#include <vector> +#include <iosfwd> + +namespace GpgME +{ + +class Error; +class Signature; +class Notation; +class Key; + +class GPGMEPP_EXPORT VerificationResult : public Result +{ +public: + VerificationResult(); + VerificationResult(gpgme_ctx_t ctx, int error); + VerificationResult(gpgme_ctx_t ctx, const Error &error); + explicit VerificationResult(const Error &err); + + const VerificationResult &operator=(VerificationResult other) + { + swap(other); + return *this; + } + + void swap(VerificationResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + + const char *fileName() const; + + unsigned int numSignatures() const; + Signature signature(unsigned int index) const; + std::vector<Signature> signatures() const; + + class Private; +private: + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VerificationResult &result); + +class GPGMEPP_EXPORT Signature +{ + friend class ::GpgME::VerificationResult; + Signature(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int index); +public: + typedef GPGMEPP_DEPRECATED GpgME::Notation Notation; + + Signature(); + + const Signature &operator=(Signature other) + { + swap(other); + return *this; + } + + void swap(Signature &other) + { + using std::swap; + swap(this->d, other.d); + swap(this->idx, other.idx); + } + + bool isNull() const; + + enum Summary { + None = 0x000, + Valid = 0x001, + Green = 0x002, + Red = 0x004, + KeyRevoked = 0x008, + KeyExpired = 0x010, + SigExpired = 0x020, + KeyMissing = 0x040, + CrlMissing = 0x080, + CrlTooOld = 0x100, + BadPolicy = 0x200, + SysError = 0x400, + TofuConflict= 0x800 + }; + Summary summary() const; + + const char *fingerprint() const; + + Error status() const; + + time_t creationTime() const; + time_t expirationTime() const; + bool neverExpires() const; + + GPGMEPP_DEPRECATED bool wrongKeyUsage() const + { + return isWrongKeyUsage(); + } + bool isWrongKeyUsage() const; + bool isVerifiedUsingChainModel() const; + + enum PKAStatus { + UnknownPKAStatus, PKAVerificationFailed, PKAVerificationSucceeded + }; + PKAStatus pkaStatus() const; + const char *pkaAddress() const; + + enum Validity { + Unknown, Undefined, Never, Marginal, Full, Ultimate + }; + Validity validity() const; + char validityAsString() const; + Error nonValidityReason() const; + + unsigned int publicKeyAlgorithm() const; + const char *publicKeyAlgorithmAsString() const; + + unsigned int hashAlgorithm() const; + const char *hashAlgorithmAsString() const; + + const char *policyURL() const; + GpgME::Notation notation(unsigned int index) const; + std::vector<GpgME::Notation> notations() const; + + /** Returns the key object associated with this signature. + * May be incomplete but will have at least the fingerprint + * set or the associated TOFU Information if applicable. */ + GpgME::Key key() const; + +private: + std::shared_ptr<VerificationResult::Private> d; + unsigned int idx; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Signature &sig); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::PKAStatus pkaStatus); +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::Summary summary); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VerificationResult) +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Signature) + +#endif // __GPGMEPP_VERIFICATIONRESULT_H__ diff --git a/lang/cpp/src/vfsmountresult.cpp b/lang/cpp/src/vfsmountresult.cpp new file mode 100644 index 0000000..c9fdd5e --- /dev/null +++ b/lang/cpp/src/vfsmountresult.cpp @@ -0,0 +1,90 @@ +/* + vfsmountresult.cpp - wraps a gpgme vfs mount result + Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com> + Author: Marc Mutz <marc@kdab.com>, Volker Krause <volker@kdab.com> + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <vfsmountresult.h> +#include "result_p.h" + +#include <gpgme.h> + +#include <istream> +#include <string.h> + +using namespace GpgME; + +class VfsMountResult::Private +{ +public: + explicit Private(const gpgme_vfs_mount_result_t r) : mountDir(0) + { + if (r && r->mount_dir) { + mountDir = strdup(r->mount_dir); + } + } + + ~Private() + { + std::free(mountDir); + } + + char *mountDir; +}; + +VfsMountResult::VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError) + : Result(error ? error : opError), d() +{ + init(ctx); +} + +void VfsMountResult::init(gpgme_ctx_t ctx) +{ + (void)ctx; + if (!ctx) { + return; + } + gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result(ctx); + if (!res) { + return; + } + d.reset(new Private(res)); +} + +make_standard_stuff(VfsMountResult) + +const char *VfsMountResult::mountDir() const +{ + if (d) { + return d->mountDir; + } + return 0; +} + +std::ostream &GpgME::operator<<(std::ostream &os, const VfsMountResult &result) +{ + os << "GpgME::VfsMountResult("; + if (!result.isNull()) { + os << "\n error: " << result.error() + << "\n mount dir: " << result.mountDir() + << "\n"; + } + return os << ')'; +} diff --git a/lang/cpp/src/vfsmountresult.h b/lang/cpp/src/vfsmountresult.h new file mode 100644 index 0000000..b46eeb1 --- /dev/null +++ b/lang/cpp/src/vfsmountresult.h @@ -0,0 +1,76 @@ +/* + vfsmountresult.h - wraps a gpgme vfs mount result + Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com> + Author: Marc Mutz <marc@kdab.com>, Volker Krause <volker@kdab.com> + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_VFSMOUNTRESULT_H__ +#define __GPGMEPP_VFSMOUNTRESULT_H__ + +#include "gpgmefw.h" +#include "result.h" +#include "gpgmepp_export.h" + +#include <memory> + +#include <vector> +#include <iosfwd> + +namespace GpgME +{ + +class Error; + +class GPGMEPP_EXPORT VfsMountResult : public Result +{ +public: + VfsMountResult(); + VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError); + explicit VfsMountResult(const Error &err); + + const VfsMountResult &operator=(VfsMountResult other) + { + swap(other); + return *this; + } + + void swap(VfsMountResult &other) + { + Result::swap(other); + using std::swap; + swap(this->d, other.d); + } + + bool isNull() const; + const char *mountDir() const; + + class Private; +private: + void init(gpgme_ctx_t ctx); + std::shared_ptr<Private> d; +}; + +GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VfsMountResult &result); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VfsMountResult) + +#endif // __GPGMEPP_VFSMOUNTRESULT_H__ diff --git a/lang/python/MANIFEST.in b/lang/python/MANIFEST.in new file mode 100644 index 0000000..eefdb83 --- /dev/null +++ b/lang/python/MANIFEST.in @@ -0,0 +1,4 @@ +recursive-include examples *.py +include gpgme-h-clean.py gpgme.i +include helpers.c helpers.h private.h +recursive-include pyme *.py diff --git a/lang/python/Makefile.am b/lang/python/Makefile.am new file mode 100644 index 0000000..2271ce0 --- /dev/null +++ b/lang/python/Makefile.am @@ -0,0 +1,106 @@ +# Makefile.am for the Python bindings. +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +EXTRA_DIST = \ + README \ + MANIFEST.in \ + gpgme.i \ + helpers.c helpers.h private.h \ + gpgme-h-clean.py \ + examples \ + pyme + +SUBDIRS = . tests + +COPY_FILES = \ + $(srcdir)/gpgme.i \ + $(srcdir)/README \ + $(srcdir)/MANIFEST.in \ + $(srcdir)/gpgme-h-clean.py \ + $(srcdir)/examples \ + $(srcdir)/helpers.c $(srcdir)/helpers.h $(srcdir)/private.h + +COPY_FILES_PYME = \ + $(srcdir)/pyme/callbacks.py \ + $(srcdir)/pyme/constants \ + $(srcdir)/pyme/core.py \ + $(srcdir)/pyme/errors.py \ + $(srcdir)/pyme/__init__.py \ + $(srcdir)/pyme/results.py \ + $(srcdir)/pyme/util.py + +# For VPATH builds we need to copy some files because Python's +# distutils are not VPATH-aware. +copystamp: $(COPY_FILES) $(COPY_FILES_PYME) + if test "$(srcdir)" != "$(builddir)" ; then \ + cp -R $(COPY_FILES) . ; \ + cp -R $(COPY_FILES_PYME) pyme ; \ + fi + touch $@ + +all-local: copystamp + for PYTHON in $(PYTHONS); do \ + CFLAGS="$(CFLAGS) -I$(top_srcdir)" \ + $$PYTHON setup.py build --verbose ; \ + done + +dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc: copystamp + CFLAGS="$(CFLAGS) -I$(top_srcdir)" \ + $(PYTHON) setup.py sdist --verbose + gpg2 --detach-sign --armor dist/pyme3-$(VERSION).tar.gz + +.PHONY: sdist +sdist: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc + +.PHONY: upload +upload: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc + twine upload $^ + +CLEANFILES = gpgme.h errors.i gpgme_wrap.c pyme/gpgme.py \ + copystamp + +# Remove the rest. +# +# 'make distclean' clears the write bit, breaking rm -rf. Fix the +# permissions. +clean-local: + rm -rf -- build + if test "$(srcdir)" != "$(builddir)" ; then \ + find . -type d ! -perm -200 -exec chmod u+w {} ';' ; \ + for F in $(COPY_FILES); do rm -rf -- `basename $$F` ; done ; \ + for F in $(COPY_FILES_PYME); do \ + rm -rf -- pyme/`basename $$F` ; \ + done ; \ + fi + +install-exec-local: + rm -f install_files.txt + for PYTHON in $(PYTHONS); do \ + $$PYTHON setup.py install \ + --prefix $(DESTDIR)$(prefix) \ + --record files.txt \ + --verbose ; \ + cat files.txt >> install_files.txt ; \ + rm files.txt ; \ + done + $(MKDIR_P) $(DESTDIR)$(pythondir)/pyme + mv install_files.txt $(DESTDIR)$(pythondir)/pyme + +uninstall-local: + xargs <$(DESTDIR)$(pythondir)/pyme/install_files.txt -- rm -rf -- + rm -rf -- $(DESTDIR)$(pythondir)/pyme diff --git a/lang/python/Makefile.in b/lang/python/Makefile.in new file mode 100644 index 0000000..6e6cfe6 --- /dev/null +++ b/lang/python/Makefile.in @@ -0,0 +1,798 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am for the Python bindings. +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/python +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/setup.py.in \ + README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = setup.py +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = \ + README \ + MANIFEST.in \ + gpgme.i \ + helpers.c helpers.h private.h \ + gpgme-h-clean.py \ + examples \ + pyme + +SUBDIRS = . tests +COPY_FILES = \ + $(srcdir)/gpgme.i \ + $(srcdir)/README \ + $(srcdir)/MANIFEST.in \ + $(srcdir)/gpgme-h-clean.py \ + $(srcdir)/examples \ + $(srcdir)/helpers.c $(srcdir)/helpers.h $(srcdir)/private.h + +COPY_FILES_PYME = \ + $(srcdir)/pyme/callbacks.py \ + $(srcdir)/pyme/constants \ + $(srcdir)/pyme/core.py \ + $(srcdir)/pyme/errors.py \ + $(srcdir)/pyme/__init__.py \ + $(srcdir)/pyme/results.py \ + $(srcdir)/pyme/util.py + +CLEANFILES = gpgme.h errors.i gpgme_wrap.c pyme/gpgme.py \ + copystamp + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/python/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +setup.py: $(top_builddir)/config.status $(srcdir)/setup.py.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile all-local +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-exec-local + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ + check check-am clean clean-generic clean-libtool clean-local \ + cscopelist-am ctags ctags-am distclean distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-local install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am uninstall-local + + +# For VPATH builds we need to copy some files because Python's +# distutils are not VPATH-aware. +copystamp: $(COPY_FILES) $(COPY_FILES_PYME) + if test "$(srcdir)" != "$(builddir)" ; then \ + cp -R $(COPY_FILES) . ; \ + cp -R $(COPY_FILES_PYME) pyme ; \ + fi + touch $@ + +all-local: copystamp + for PYTHON in $(PYTHONS); do \ + CFLAGS="$(CFLAGS) -I$(top_srcdir)" \ + $$PYTHON setup.py build --verbose ; \ + done + +dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc: copystamp + CFLAGS="$(CFLAGS) -I$(top_srcdir)" \ + $(PYTHON) setup.py sdist --verbose + gpg2 --detach-sign --armor dist/pyme3-$(VERSION).tar.gz + +.PHONY: sdist +sdist: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc + +.PHONY: upload +upload: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc + twine upload $^ + +# Remove the rest. +# +# 'make distclean' clears the write bit, breaking rm -rf. Fix the +# permissions. +clean-local: + rm -rf -- build + if test "$(srcdir)" != "$(builddir)" ; then \ + find . -type d ! -perm -200 -exec chmod u+w {} ';' ; \ + for F in $(COPY_FILES); do rm -rf -- `basename $$F` ; done ; \ + for F in $(COPY_FILES_PYME); do \ + rm -rf -- pyme/`basename $$F` ; \ + done ; \ + fi + +install-exec-local: + rm -f install_files.txt + for PYTHON in $(PYTHONS); do \ + $$PYTHON setup.py install \ + --prefix $(DESTDIR)$(prefix) \ + --record files.txt \ + --verbose ; \ + cat files.txt >> install_files.txt ; \ + rm files.txt ; \ + done + $(MKDIR_P) $(DESTDIR)$(pythondir)/pyme + mv install_files.txt $(DESTDIR)$(pythondir)/pyme + +uninstall-local: + xargs <$(DESTDIR)$(pythondir)/pyme/install_files.txt -- rm -rf -- + rm -rf -- $(DESTDIR)$(pythondir)/pyme + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/python/README b/lang/python/README new file mode 100644 index 0000000..98c007e --- /dev/null +++ b/lang/python/README @@ -0,0 +1,59 @@ +PyME - GPGME for Python -*- org -*- +======================= + +PyME is a python interface to the GPGME library: +https://www.gnupg.org/related_software/gpgme/ + +PyME offers two interfaces, one is a high-level, curated, and +idiomatic interface that is implemented as a shim on top of the +low-level interface automatically created using SWIG. + +This way we make simple things easy, while still providing the entire +functionality of the underlying library. + +* Mailing List + +For general discussion and help see the gnupg-users mailing list: +https://lists.gnupg.org/mailman/listinfo/gnupg-users + +For development see the gnupg-devel mailing list: +https://lists.gnupg.org/mailman/listinfo/gnupg-devel + +* Bugs + +Please report bugs using our bug tracker using the category 'gpgme', +and topic 'python': +https://bugs.gnupg.org/gnupg/ + +* Authors + +PyME has been created by John Goerzen, and maintained, developed, and +cherished by Igor Belyi, Martin Albrecht, Ben McGinnes, and everyone +who contributed to it in any way. + +In 2016 we merged a port of PyME to into the GPGME repository, and +development will continue there. Please see the VCS history for the +list of contributors, and if you do find bugs, or want to contribute, +please get in touch and help maintain PyME. + +Please see the section 'History' further down this document for +references to previous versions. + +* History + + - The bindings have been merged into the GPGME repository in 2016. + + - The latest version of PyME for Python 3.2 and above (as of + May, 2015) is v0.9.1. + https://git.gnupg.org/gpgme.git/lang/py3-pyme + + - The latest version of PyME for Python 2.6 and 2.7 (as of this + writing) is v0.9.0. https://bitbucket.org/malb/pyme + + - A previous version of PyME v0.8.0 can be found on sourceforge: + http://pyme.sourceforge.net/ + + - A previous version of PyME v0.5.1 which works with GPGME v0.3.15 + can be found on John Goerzen's PyME page: + http://quux.org/devel/pyme/ + http://www.complete.org/JohnGoerzen diff --git a/lang/python/examples/assuan.py b/lang/python/examples/assuan.py new file mode 100644 index 0000000..22960d3 --- /dev/null +++ b/lang/python/examples/assuan.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +"""Demonstrate the use of the Assuan protocol engine""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme + +with pyme.Context(protocol=pyme.constants.PROTOCOL_ASSUAN) as c: + # Invoke the pinentry to get a confirmation. + err = c.assuan_transact(['GET_CONFIRMATION', 'Hello there']) + print("You chose {}.".format("cancel" if err else "ok")) diff --git a/lang/python/examples/decryption-filter.py b/lang/python/examples/decryption-filter.py new file mode 100644 index 0000000..3007c2b --- /dev/null +++ b/lang/python/examples/decryption-filter.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +"""A decryption filter + +This demonstrates decryption using pyme3 in three lines of code. To +be used like this: + +./decryption-filter.py <message.gpg >message.plain + +""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme +pyme.Context().decrypt(sys.stdin, sink=sys.stdout) diff --git a/lang/python/examples/delkey.py b/lang/python/examples/delkey.py new file mode 100755 index 0000000..a02f412 --- /dev/null +++ b/lang/python/examples/delkey.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +# Sample of key deletion +# It deletes keys for joe@example.org generated by genkey.py script + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme + +with pyme.Context() as c: + # Note: We must not modify the key store during iteration, + # therefore, we explicitly make a list. + keys = list(c.keylist("joe+pyme@example.org")) + + for k in keys: + c.op_delete(k, True) diff --git a/lang/python/examples/encrypt-to-all.py b/lang/python/examples/encrypt-to-all.py new file mode 100755 index 0000000..35873bd --- /dev/null +++ b/lang/python/examples/encrypt-to-all.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2008 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +""" +This program will try to encrypt a simple message to each key on your +keyring. If your keyring has any invalid keys on it, those keys will +be skipped and it will re-try the encryption.""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme + +with pyme.Context(armor=True) as c: + recipients = list() + for key in c.keylist(): + valid = 0 + if any(sk.can_encrypt for sk in key.subkeys): + recipients.append(key) + print("Adding recipient {0}.".format(key.uids[0].uid)) + + ciphertext = None + while not ciphertext: + print("Encrypting to %d recipients" % len(recipients)) + try: + ciphertext, _, _ = c.encrypt(b'This is my message.', + recipients=recipients) + except pyme.errors.InvalidRecipients as e: + print("Encryption failed for these keys:\n{0!s}".format(e)) + + # filter out the bad keys + bad_keys = {bad.fpr for bad in e.recipients} + recipients = [r for r in recipients + if not r.subkeys[0].fpr in bad_keys] + + sys.stdout.buffer.write(ciphertext) diff --git a/lang/python/examples/exportimport.py b/lang/python/examples/exportimport.py new file mode 100755 index 0000000..bc946bc --- /dev/null +++ b/lang/python/examples/exportimport.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +# Sample of export and import of keys +# It uses keys for joe+pyme@example.org generated by genkey.py script + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import os +import pyme + +user = "joe+pyme@example.org" + +with pyme.Context(armor=True) as c, pyme.Data() as expkey: + print(" - Export %s's public keys - " % user) + c.op_export(user, 0, expkey) + + # print out exported data to see how it looks in armor. + expkey.seek(0, os.SEEK_SET) + expstring = expkey.read() + if expstring: + sys.stdout.buffer.write(expstring) + else: + sys.exit("No %s's keys to export!" % user) + +# delete keys to ensure that they came from our imported data. Note +# that if joe's key has private part as well we can only delete both +# of them. +with pyme.Context() as c: + # Note: We must not modify the key store during iteration, + # therfore, we explicitly make a list. + keys = list(c.keylist(user)) + + for k in keys: + c.op_delete(k, True) + +with pyme.Context() as c: + print(" - Import exported keys - ") + c.op_import(expstring) + result = c.op_import_result() + if result: + print(result) + else: + sys.exit(" - No import result - ") diff --git a/lang/python/examples/genkey.py b/lang/python/examples/genkey.py new file mode 100755 index 0000000..ee70303 --- /dev/null +++ b/lang/python/examples/genkey.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme + +# This is the example from the GPGME manual. + +parms = """<GnupgKeyParms format="internal"> +Key-Type: RSA +Key-Length: 2048 +Subkey-Type: RSA +Subkey-Length: 2048 +Name-Real: Joe Tester +Name-Comment: with stupid passphrase +Name-Email: joe+pyme@example.org +Passphrase: Crypt0R0cks +Expire-Date: 2020-12-31 +</GnupgKeyParms> +""" + +with pyme.Context() as c: + c.set_progress_cb(pyme.callbacks.progress_stdout) + c.op_genkey(parms, None, None) + print("Generated key with fingerprint {0}.".format( + c.op_genkey_result().fpr)) diff --git a/lang/python/examples/inter-edit.py b/lang/python/examples/inter-edit.py new file mode 100644 index 0000000..39d6f17 --- /dev/null +++ b/lang/python/examples/inter-edit.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +"""Simple interactive editor to test editor scripts""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme + +if len(sys.argv) != 2: + sys.exit("Usage: %s <Gpg key pattern>\n" % sys.argv[0]) + +name = sys.argv[1] + +with pyme.Context() as c: + keys = list(c.keylist(name)) + if len(keys) == 0: + sys.exit("No key matching {}.".format(name)) + if len(keys) > 1: + sys.exit("More than one key matching {}.".format(name)) + + key = keys[0] + print("Editing key {} ({}):".format(key.uids[0].uid, key.subkeys[0].fpr)) + + def edit_fnc(keyword, args): + print("Status: {} ({}), args: {} > ".format( + keyword, status, args), end='', flush=True) + + if not 'GET' in keyword: + # no prompt + print() + return None + + try: + return input() + except EOFError: + return "quit" + + c.interact(key, edit_fnc, sink=sys.stdout) diff --git a/lang/python/examples/sign.py b/lang/python/examples/sign.py new file mode 100755 index 0000000..2f235ba --- /dev/null +++ b/lang/python/examples/sign.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme +from pyme.constants.sig import mode + +with pyme.Context() as c: + signed, _ = c.sign(b"Test message", mode=mode.CLEAR) + sys.stdout.buffer.write(signed) diff --git a/lang/python/examples/signverify.py b/lang/python/examples/signverify.py new file mode 100755 index 0000000..03bc0a6 --- /dev/null +++ b/lang/python/examples/signverify.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +# Sample of unattended signing/verifying of a message. +# It uses keys for joe+pyme@example.org generated by genkey.py script + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme +from pyme.constants.sig import mode + +user = "joe+pyme" + +with pyme.Context(pinentry_mode=pyme.constants.PINENTRY_MODE_LOOPBACK) as c: + keys = list(c.keylist(user)) + if len(keys) == 0: + sys.exit("No key matching {}.".format(user)) + + c.signers = keys[:1] + c.set_passphrase_cb(lambda *args: "Crypt0R0cks") + signed_data, _ = c.sign(b"Test message", mode=mode.CLEAR) + + data, result = c.verify(signed_data, verify=keys[:1]) + print("Data: {!r}\nSignature: {!s}".format(data, result.signatures[0])) diff --git a/lang/python/examples/simple.py b/lang/python/examples/simple.py new file mode 100755 index 0000000..5598487 --- /dev/null +++ b/lang/python/examples/simple.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme + +with pyme.Context(armor=True) as c: + recipients = [] + print("Enter name of your recipient(s), end with a blank line.") + while True: + line = input() + if not line: + break + new = list(c.keylist(line)) + if not new: + print("Matched no known keys.") + else: + print("Adding {}.".format(", ".join(k.uids[0].name for k in new))) + recipients.extend(new) + + if not recipients: + sys.exit("No recipients.") + + print("Encrypting for {}.".format(", ".join(k.uids[0].name + for k in recipients))) + + ciphertext, _, _ = c.encrypt(b"This is my message,", recipients) + sys.stdout.buffer.write(ciphertext) diff --git a/lang/python/examples/testCMSgetkey.py b/lang/python/examples/testCMSgetkey.py new file mode 100644 index 0000000..4467b6c --- /dev/null +++ b/lang/python/examples/testCMSgetkey.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2008 Bernhard Reiter <bernhard@intevation.de> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +"""A test applicaton for the CMS protocol.""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme + +if len(sys.argv) != 2: + sys.exit("fingerprint or unique key ID for gpgme_get_key()") + +with pyme.Context(protocol=pyme.constants.PROTOCOL_CMS) as c: + key = c.get_key(sys.argv[1], False) + + print("got key: ", key.subkeys[0].fpr) + for uid in key.uids: + print(uid.uid) diff --git a/lang/python/examples/verifydetails.py b/lang/python/examples/verifydetails.py new file mode 100755 index 0000000..fa34926 --- /dev/null +++ b/lang/python/examples/verifydetails.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (c) 2008 Bernhard Reiter <bernhard@intevation.de> +# +# This program 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. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +from pyme import core +from pyme.constants import protocol + +def print_engine_infos(): + print("gpgme version:", core.check_version(None)) + print("engines:") + + for engine in core.get_engine_info(): + print(engine.file_name, engine.version) + + for proto in [protocol.OpenPGP, protocol.CMS]: + print("Have {}? {}".format(core.get_protocol_name(proto), + core.engine_check_version(proto))) + + +def verifyprintdetails(filename, detached_sig_filename=None): + """Verify a signature, print a lot of details.""" + with core.Context() as c: + + # Verify. + data, result = c.verify(open(filename), + open(detached_sig_filename) + if detached_sig_filename else None) + + # List results for all signatures. Status equal 0 means "Ok". + for index, sign in enumerate(result.signatures): + print("signature", index, ":") + print(" summary: %#0x" % (sign.summary)) + print(" status: %#0x" % (sign.status)) + print(" timestamp: ", sign.timestamp) + print(" fingerprint:", sign.fpr) + print(" uid: ", c.get_key(sign.fpr, 0).uids[0].uid) + + # Print "unsigned" text if inline signature + if data: + sys.stdout.buffer.write(data) + +def main(): + print_engine_infos() + print() + + argc = len(sys.argv) + if argc < 2 or argc > 3: + sys.exit( + "Usage: {} <filename>[ <detached_signature_filename>]".format( + sys.argv[0])) + + if argc == 2: + print("trying to verify file {}.".format(sys.argv[1])) + verifyprintdetails(sys.argv[1]) + if argc == 3: + print("trying to verify signature {1} for file {0}.".format(*sys.argv)) + verifyprintdetails(sys.argv[1], sys.argv[2]) + +if __name__ == "__main__": + main() diff --git a/lang/python/gpgme-h-clean.py b/lang/python/gpgme-h-clean.py new file mode 100755 index 0000000..52f8676 --- /dev/null +++ b/lang/python/gpgme-h-clean.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys, re + +if len(sys.argv) != 2: + sys.stderr.write("Usage: %s path/to/[gpgme|gpg-error].h\n" % sys.argv[0]) + sys.exit(1) + +deprec_func = re.compile(r'^(.*typedef.*|.*\(.*\)|[^#]+\s+.+)' + + r'\s*_GPGME_DEPRECATED(_OUTSIDE_GPGME)?\(.*\);\s*', + re.S) +line_break = re.compile(';|\\$|\\x0c|^\s*#|{'); + +if 'gpgme.h' in sys.argv[1]: + gpgme = open(sys.argv[1]) + tmp = gpgme.readline() + text = '' + while tmp: + text += re.sub(' class ', ' _py_obsolete_class ', tmp) + if line_break.search(tmp): + if not deprec_func.search(text): + sys.stdout.write(text) + text = '' + tmp = gpgme.readline() + sys.stdout.write(text) + gpgme.close() +else: + filter_re = re.compile(r'GPG_ERR_[^ ]* =') + rewrite_re = re.compile(r' *(.*) = .*') + for line in open(sys.argv[1]): + if not filter_re.search(line): + continue + print(rewrite_re.sub(r'%constant long \1 = \1;', line.strip())) diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i new file mode 100644 index 0000000..84addae --- /dev/null +++ b/lang/python/gpgme.i @@ -0,0 +1,625 @@ +/* +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +%module gpgme +%include "cpointer.i" +%include "cstring.i" + +/* Generate doc strings for all methods. + + This will generate docstrings of the form + + gpgme_op_encrypt(ctx, recp, flags, plain, cipher) -> gpgme_error_t + + which we transform into + + ctx.op_encrypt(recp, flags, plain, cipher) -> gpgme_error_t + + for automagically wrapped functions. */ +%feature("autodoc", "0"); + + +/* Allow use of Unicode objects, bytes, and None for strings. */ +%typemap(in) const char *(PyObject *encodedInput = NULL) { + if ($input == Py_None) + $1 = NULL; + else if (PyUnicode_Check($input)) + { + encodedInput = PyUnicode_AsUTF8String($input); + if (encodedInput == NULL) + return NULL; + $1 = PyBytes_AsString(encodedInput); + } + else if (PyBytes_Check($input)) + $1 = PyBytes_AsString($input); + else { + PyErr_Format(PyExc_TypeError, + "arg %d: expected str, bytes, or None, got %s", + $argnum, $input->ob_type->tp_name); + return NULL; + } +} +%typemap(freearg) const char * { + Py_XDECREF(encodedInput$argnum); +} + +/* Likewise for a list of strings. */ +%typemap(in) const char *[] (void *vector = NULL, + size_t size, + PyObject **pyVector = NULL) { + /* Check if is a list */ + if (PyList_Check($input)) { + size_t i, j; + size = PyList_Size($input); + $1 = (char **) (vector = malloc((size+1) * sizeof(char *))); + pyVector = calloc(sizeof *pyVector, size); + + for (i = 0; i < size; i++) { + PyObject *o = PyList_GetItem($input,i); + if (PyUnicode_Check(o)) + { + pyVector[i] = PyUnicode_AsUTF8String(o); + if (pyVector[i] == NULL) + { + free(vector); + for (j = 0; j < i; j++) + Py_XDECREF(pyVector[j]); + return NULL; + } + $1[i] = PyBytes_AsString(pyVector[i]); + } + else if (PyString_Check(o)) + $1[i] = PyString_AsString(o); + else { + PyErr_Format(PyExc_TypeError, + "arg %d: list must contain only str or bytes, got %s " + "at position %d", + $argnum, o->ob_type->tp_name, i); + free($1); + return NULL; + } + } + $1[i] = NULL; + } else { + PyErr_Format(PyExc_TypeError, + "arg %d: expected a list of str or bytes, got %s", + $argnum, $input->ob_type->tp_name); + return NULL; + } +} +%typemap(freearg) const char *[] { + size_t i; + free(vector$argnum); + for (i = 0; i < size$argnum; i++) + Py_XDECREF(pyVector$argnum[i]); +} + +// Release returned buffers as necessary. +%typemap(newfree) char * "free($1);"; +%newobject gpgme_data_release_and_get_mem; + +%typemap(arginit) gpgme_key_t [] { + $1 = NULL; +} + +%typemap(in) gpgme_key_t [] { + int i, numb = 0; + if (!PySequence_Check($input)) { + PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t", + $argnum); + return NULL; + } + if((numb = PySequence_Length($input)) != 0) { + $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t)); + for(i=0; i<numb; i++) { + PyObject *pypointer = PySequence_GetItem($input, i); + + /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */ + /* &1_descriptor = $&1_descriptor *1_descriptor = $*1_descriptor */ + + // Following code is from swig's python.swg + if ((SWIG_ConvertPtr(pypointer,(void **) &$1[i], $*1_descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) { + Py_DECREF(pypointer); + return NULL; + } + Py_DECREF(pypointer); + } + $1[numb] = NULL; + } +} +%typemap(freearg) gpgme_key_t [] { + if ($1) free($1); +} + +// Special handling for references to our objects. +%typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL, + PyObject *bytesio = NULL, + Py_buffer view, int have_view = 0) { + /* If we create a temporary wrapper object, we will store it in + wrapperN, where N is $argnum. Here in this fragment, SWIG will + automatically append $argnum. */ + memset(&view, 0, sizeof view); + if ($input == Py_None) + $1 = NULL; + else { + PyObject *pypointer; + pypointer = _pyme_obj2gpgme_data_t($input, $argnum, &wrapper, + &bytesio, &view); + if (pypointer == NULL) + return NULL; + have_view = !! view.obj; + + /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */ + + // Following code is from swig's python.swg + + if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor, + SWIG_POINTER_EXCEPTION | $disown )) == -1) { + Py_DECREF(pypointer); + return NULL; + } + Py_DECREF(pypointer); + } +} + +#if HAVE_DATA_H +/* If we are doing an in-tree build, we can use the internal + representation of struct gpgme_data for an very efficient check if + the buffer has been modified. */ +%{ +#include "src/data.h" /* For struct gpgme_data. */ +%} +#endif + +%typemap(freearg) gpgme_data_t DATAIN { + /* See whether we need to update the Python buffer. */ + if (resultobj && wrapper$argnum && view$argnum.buf) + { + int dirty; + char *new_data = NULL; + size_t new_size; + +#if HAVE_DATA_H + new_data = wrapper$argnum->data.mem.buffer; + new_size = wrapper$argnum->data.mem.length; + dirty = new_data != NULL; +#else + new_data = gpgme_data_release_and_get_mem (wrapper$argnum, &new_size); + wrapper$argnum = NULL; + dirty = new_size != view$argnum.len + || memcmp (new_data, view$argnum.buf, view$argnum.len); +#endif + + if (dirty) + { + /* The buffer is dirty. */ + if (view$argnum.readonly) + { + Py_XDECREF(resultobj); + resultobj = NULL; + PyErr_SetString(PyExc_ValueError, + "cannot update read-only buffer"); + } + + /* See if we need to truncate the buffer. */ + if (resultobj && view$argnum.len != new_size) + { + if (bytesio$argnum == NULL) + { + Py_XDECREF(resultobj); + resultobj = NULL; + PyErr_SetString(PyExc_ValueError, "cannot resize buffer"); + } + else + { + PyObject *retval; + PyBuffer_Release(&view$argnum); + assert(view$argnum.obj == NULL); + retval = PyObject_CallMethod(bytesio$argnum, "truncate", + "l", (long) new_size); + if (retval == NULL) + { + Py_XDECREF(resultobj); + resultobj = NULL; + } + else + { + Py_DECREF(retval); + + retval = PyObject_CallMethod(bytesio$argnum, + "getbuffer", NULL); + if (retval == NULL + || PyObject_GetBuffer(retval, &view$argnum, + PyBUF_SIMPLE|PyBUF_WRITABLE) < 0) + { + Py_XDECREF(resultobj); + resultobj = NULL; + } + + Py_XDECREF(retval); + + if (resultobj && view$argnum.len + != new_size) + { + Py_XDECREF(resultobj); + resultobj = NULL; + PyErr_Format(PyExc_ValueError, + "Expected buffer of length %zu, got %zi", + new_size, + view$argnum.len); + } + } + } + } + if (resultobj) + memcpy(view$argnum.buf, new_data, new_size); + } +#if ! HAVE_DATA_H + free (new_data); +#endif + } + + /* Free the temporary wrapper, if any. */ + if (wrapper$argnum) + gpgme_data_release(wrapper$argnum); + Py_XDECREF (bytesio$argnum); + if (have_view$argnum && view$argnum.buf) + PyBuffer_Release(&view$argnum); +} + +%apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher, + gpgme_data_t sig, gpgme_data_t signed_text, + gpgme_data_t plaintext, gpgme_data_t keydata, + gpgme_data_t pubkey, gpgme_data_t seckey, + gpgme_data_t out}; + +/* SWIG has problems interpreting ssize_t, off_t or gpgme_error_t in + gpgme.h. */ +/* XXX: This is wrong at least for off_t if compiled with LFS. */ +%typemap(out) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t { + $result = PyLong_FromLong($1); +} +/* XXX: This is wrong at least for off_t if compiled with LFS. */ +%typemap(in) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t { + $1 = PyLong_AsLong($input); +} + +// Those are for gpgme_data_read() and gpgme_strerror_r() +%typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) { + $2 = PyLong_AsLong($input); + if ($2 < 0) { + PyErr_SetString(PyExc_ValueError, "Positive integer expected"); + return NULL; + } + $1 = ($1_ltype) malloc($2+1); +} +%typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) { + Py_XDECREF($result); /* Blow away any previous result */ + if (result < 0) { /* Check for I/O error */ + free($1); + return PyErr_SetFromErrno(PyExc_RuntimeError); + } + $result = PyBytes_FromStringAndSize($1,result); + free($1); +} + +/* For gpgme_data_write, but should be universal. */ +%typemap(in) (const void *buffer, size_t size)(PyObject *encodedInput = NULL) { + Py_ssize_t ssize; + + if ($input == Py_None) + $1 = NULL, $2 = 0; + else if (PyUnicode_Check($input)) + { + encodedInput = PyUnicode_AsUTF8String($input); + if (encodedInput == NULL) + return NULL; + if (PyBytes_AsStringAndSize(encodedInput, (char **) &$1, &ssize) == -1) + { + Py_DECREF(encodedInput); + return NULL; + } + } + else if (PyBytes_Check($input)) + PyBytes_AsStringAndSize($input, (char **) &$1, &ssize); + else { + PyErr_Format(PyExc_TypeError, + "arg %d: expected str, bytes, or None, got %s", + $argnum, $input->ob_type->tp_name); + return NULL; + } + + if (! $1) + $2 = 0; + else + { + assert (ssize >= 0); + $2 = (size_t) ssize; + } +} +%typemap(freearg) (const void *buffer, size_t size) { + Py_XDECREF(encodedInput$argnum); +} + +// Make types containing 'next' field to be lists +%ignore next; +%typemap(out) gpgme_sig_notation_t, gpgme_subkey_t, + gpgme_key_sig_t, gpgme_user_id_t, gpgme_invalid_key_t, + gpgme_recipient_t, gpgme_new_signature_t, gpgme_signature_t, + gpgme_import_status_t, gpgme_conf_arg_t, gpgme_conf_opt_t, + gpgme_conf_comp_t, gpgme_tofu_info_t { + int i; + int size = 0; + $1_ltype curr; + for (curr = $1; curr != NULL; curr = curr->next) { + size++; + } + $result = PyList_New(size); + for (i=0,curr=$1; i<size; i++,curr=curr->next) { + PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags); + PyList_SetItem($result, i, o); + } +} + + + +/* Wrap the fragile result objects into robust Python ones. */ +%typemap(out) gpgme_encrypt_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "EncryptResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_decrypt_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "DecryptResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_sign_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "SignResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_verify_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "VerifyResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_import_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "ImportResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_genkey_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "GenkeyResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_keylist_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "KeylistResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_vfs_mount_result_t { + PyObject *fragile; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor, + %newpointer_flags); + $result = _pyme_wrap_result(fragile, "VFSMountResult"); + Py_DECREF(fragile); +} + +%typemap(out) gpgme_engine_info_t { + int i; + int size = 0; + $1_ltype curr; + for (curr = $1; curr != NULL; curr = curr->next) { + size++; + } + $result = PyList_New(size); + if ($result == NULL) + return NULL; /* raise */ + for (i=0,curr=$1; i<size; i++,curr=curr->next) { + PyObject *fragile, *o; + fragile = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, + %newpointer_flags); + if (fragile == NULL) + { + Py_DECREF($result); + return NULL; /* raise */ + } + o = _pyme_wrap_result(fragile, "EngineInfo"); + Py_DECREF(fragile); + if (o == NULL) + { + Py_DECREF($result); + return NULL; /* raise */ + } + PyList_SetItem($result, i, o); + } +} + + + +/* Include mapper for interact callbacks. */ +%typemap(in) (gpgme_interact_cb_t fnc, void *fnc_value) { + if (! PyTuple_Check($input)) + return PyErr_Format(PyExc_TypeError, "interact callback must be a tuple"); + if (PyTuple_Size($input) != 2 && PyTuple_Size($input) != 3) + return PyErr_Format(PyExc_TypeError, + "interact callback must be a tuple of size 2 or 3"); + + $1 = (gpgme_interact_cb_t) _pyme_interact_cb; + $2 = $input; +} + + + +/* The assuan protocol callbacks. */ +%typemap(in) (gpgme_assuan_data_cb_t data_cb, void *data_cb_value) { + if ($input == Py_None) + $1 = $2 = NULL; + else + { + if (! PyTuple_Check($input)) + return PyErr_Format(PyExc_TypeError, "callback must be a tuple"); + if (PyTuple_Size($input) != 2) + return PyErr_Format(PyExc_TypeError, + "callback must be a tuple of size 2"); + if (! PyCallable_Check(PyTuple_GetItem($input, 1))) + return PyErr_Format(PyExc_TypeError, "second item must be callable"); + $1 = _pyme_assuan_data_cb; + $2 = $input; + } +} + +%typemap(in) (gpgme_assuan_inquire_cb_t inq_cb, void *inq_cb_value) { + if ($input == Py_None) + $1 = $2 = NULL; + else + { + if (! PyTuple_Check($input)) + return PyErr_Format(PyExc_TypeError, "callback must be a tuple"); + if (PyTuple_Size($input) != 2) + return PyErr_Format(PyExc_TypeError, + "callback must be a tuple of size 2"); + if (! PyCallable_Check(PyTuple_GetItem($input, 1))) + return PyErr_Format(PyExc_TypeError, "second item must be callable"); + $1 = _pyme_assuan_inquire_cb; + $2 = $input; + } +} + +%typemap(in) (gpgme_assuan_status_cb_t stat_cb, void *stat_cb_value) { + if ($input == Py_None) + $1 = $2 = NULL; + else + { + if (! PyTuple_Check($input)) + return PyErr_Format(PyExc_TypeError, "callback must be a tuple"); + if (PyTuple_Size($input) != 2) + return PyErr_Format(PyExc_TypeError, + "callback must be a tuple of size 2"); + if (! PyCallable_Check(PyTuple_GetItem($input, 1))) + return PyErr_Format(PyExc_TypeError, "second item must be callable"); + $1 = _pyme_assuan_status_cb; + $2 = $input; + } +} + +/* Include the unmodified <gpgme.h> for cc, and the cleaned-up local + version for SWIG. We do, however, want to hide certain fields on + some structs, which we provide prior to including the version for + SWIG. */ +%{ +#include <gpgme.h> +%} + +/* This is for notations, where we want to hide the length fields, and + the unused bit field block. */ +struct _gpgme_sig_notation +{ + struct _gpgme_sig_notation *next; + + /* If NAME is a null pointer, then VALUE contains a policy URL + rather than a notation. */ + char *name; + + /* The value of the notation data. */ + char *value; + + /* The accumulated flags. */ + gpgme_sig_notation_flags_t flags; + + /* Notation data is human-readable. */ + unsigned int human_readable : 1; + + /* Notation data is critical. */ + unsigned int critical : 1; +}; + +/* Now include our local modified version. Any structs defined above + are ignored. */ +%include "gpgme.h" + +%include "errors.i" + +// Generating and handling pointers-to-pointers. + +%pointer_functions(gpgme_ctx_t, gpgme_ctx_t_p); +%pointer_functions(gpgme_data_t, gpgme_data_t_p); +%pointer_functions(gpgme_key_t, gpgme_key_t_p); +%pointer_functions(gpgme_error_t, gpgme_error_t_p); +%pointer_functions(gpgme_trust_item_t, gpgme_trust_item_t_p); +%pointer_functions(gpgme_engine_info_t, gpgme_engine_info_t_p); + +// Helper functions. + +%{ +#include <stdio.h> +%} +FILE *fdopen(int fildes, const char *mode); + +/* We include both headers in the generated c code... */ +%{ +#include "helpers.h" +#include "private.h" + +/* SWIG runtime support for helpers.c */ +PyObject * +_pyme_wrap_gpgme_data_t(gpgme_data_t data) +{ + return SWIG_Python_NewPointerObj(NULL, data, SWIGTYPE_p_gpgme_data, 0); +} + +gpgme_ctx_t +_pyme_unwrap_gpgme_ctx_t(PyObject *wrapped) +{ + gpgme_ctx_t result; + if (SWIG_ConvertPtr(wrapped, + (void **) &result, + SWIGTYPE_p_gpgme_context, + SWIG_POINTER_EXCEPTION) == -1) + return NULL; + return result; +} +%} + +/* ... but only the public definitions here. They will be exposed to + the Python world, so let's be careful. */ +%include "helpers.h" diff --git a/lang/python/helpers.c b/lang/python/helpers.c new file mode 100644 index 0000000..f9aec91 --- /dev/null +++ b/lang/python/helpers.c @@ -0,0 +1,1169 @@ +/* +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <assert.h> +#include <stdio.h> +#include <gpgme.h> +#include <stdlib.h> +#include <string.h> +#include "Python.h" + +#include "helpers.h" +#include "private.h" + +/* Flag specifying whether this is an in-tree build. */ +int pyme_in_tree_build = +#if IN_TREE_BUILD + 1 +#else + 0 +#endif + ; + +static PyObject *GPGMEError = NULL; + +void _pyme_exception_init(void) { + if (GPGMEError == NULL) { + PyObject *errors; + PyObject *from_list = PyList_New(0); + errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(), + PyEval_GetLocals(), from_list, 1); + Py_XDECREF(from_list); + if (errors) { + GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError"); + Py_XINCREF(GPGMEError); + } + } +} + +static PyObject * +_pyme_raise_exception(gpgme_error_t err) +{ + PyObject *e; + + _pyme_exception_init(); + if (GPGMEError == NULL) + return PyErr_Format(PyExc_RuntimeError, "Got gpgme_error_t %d", err); + + e = PyObject_CallFunction(GPGMEError, "l", (long) err); + if (e == NULL) + return NULL; + + PyErr_SetObject(GPGMEError, e); + Py_DECREF(e); + + return NULL; /* raise */ +} + +gpgme_error_t _pyme_exception2code(void) { + gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL); + if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) { + PyObject *type = 0, *value = 0, *traceback = 0; + PyObject *error = 0; + PyErr_Fetch(&type, &value, &traceback); + PyErr_NormalizeException(&type, &value, &traceback); + error = PyObject_GetAttrString(value, "error"); + err_status = PyLong_AsLong(error); + Py_DECREF(error); + PyErr_Restore(type, value, traceback); + } + return err_status; +} + +/* Exception support for callbacks. */ +#define EXCINFO "_callback_excinfo" + +static void _pyme_stash_callback_exception(PyObject *weak_self) +{ + PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo; + + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + excinfo = PyTuple_New(3); + PyTuple_SetItem(excinfo, 0, ptype); + + if (pvalue) + PyTuple_SetItem(excinfo, 1, pvalue); + else { + Py_INCREF(Py_None); + PyTuple_SetItem(excinfo, 1, Py_None); + } + + if (ptraceback) + PyTuple_SetItem(excinfo, 2, ptraceback); + else { + Py_INCREF(Py_None); + PyTuple_SetItem(excinfo, 2, Py_None); + } + + self = PyWeakref_GetObject(weak_self); + /* self only has a borrowed reference. */ + if (self == Py_None) { + /* This should not happen, as even if we're called from the data + release callback triggered from the wrappers destructor, the + object is still alive and hence the weak reference still refers + to the object. However, in case this ever changes, not seeing + any exceptions is worse than having a little extra code, so + here we go. */ + fprintf(stderr, + "Error occurred in callback, but the wrapper object " + "has been deallocated.\n"); + PyErr_Restore(ptype, pvalue, ptraceback); + PyErr_Print(); + } + else + PyObject_SetAttrString(self, EXCINFO, excinfo); + Py_DECREF(excinfo); +} + +PyObject *pyme_raise_callback_exception(PyObject *self) +{ + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *ptype, *pvalue, *ptraceback, *excinfo; + + if (! PyObject_HasAttrString(self, EXCINFO)) + goto leave; + + excinfo = PyObject_GetAttrString(self, EXCINFO); + if (! PyTuple_Check(excinfo)) + { + Py_DECREF(excinfo); + goto leave; + } + + ptype = PyTuple_GetItem(excinfo, 0); + Py_INCREF(excinfo); + + pvalue = PyTuple_GetItem(excinfo, 1); + if (pvalue == Py_None) + pvalue = NULL; + else + Py_INCREF(pvalue); + + ptraceback = PyTuple_GetItem(excinfo, 2); + if (ptraceback == Py_None) + ptraceback = NULL; + else + Py_INCREF(ptraceback); + + /* We now have references for the extracted items. */ + Py_DECREF(excinfo); + + /* Clear the exception information. It is important to do this + before setting the error, because setting the attribute may + execute python code, and the runtime system raises a SystemError + if an exception is set but values are returned. */ + Py_INCREF(Py_None); + PyObject_SetAttrString(self, EXCINFO, Py_None); + + /* Restore exception. */ + PyErr_Restore(ptype, pvalue, ptraceback); + PyGILState_Release(state); + return NULL; /* Raise exception. */ + + leave: + Py_INCREF(Py_None); + PyGILState_Release(state); + return Py_None; +} +#undef EXCINFO + +/* Argument conversion. */ + +/* Convert object to a pointer to gpgme type, generic version. */ +PyObject * +_pyme_obj2gpgme_t(PyObject *input, const char *objtype, int argnum) +{ + PyObject *pyname = NULL, *pypointer = NULL; + pyname = PyObject_GetAttrString(input, "_ctype"); + if (pyname && PyUnicode_Check(pyname)) + { + PyObject *encoded = PyUnicode_AsUTF8String(pyname); + if (strcmp(PyBytes_AsString(encoded), objtype) != 0) + { + PyErr_Format(PyExc_TypeError, + "arg %d: Expected value of type %s, but got %s", + argnum, objtype, PyBytes_AsString(encoded)); + Py_DECREF(encoded); + Py_DECREF(pyname); + return NULL; + } + Py_DECREF(encoded); + } + else + return NULL; + + Py_DECREF(pyname); + pypointer = PyObject_GetAttrString(input, "wrapped"); + if (pypointer == NULL) { + PyErr_Format(PyExc_TypeError, + "arg %d: Use of uninitialized Python object %s", + argnum, objtype); + return NULL; + } + return pypointer; +} + +/* Convert object to a pointer to gpgme type, version for data + objects. Constructs a wrapper Python on the fly e.g. for file-like + objects with a fileno method, returning it in WRAPPER. This object + must be de-referenced when no longer needed. */ +PyObject * +_pyme_obj2gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper, + PyObject **bytesio, Py_buffer *view) +{ + gpgme_error_t err; + PyObject *data; + PyObject *fd; + + /* See if it is a file-like object with file number. */ + fd = PyObject_CallMethod(input, "fileno", NULL); + if (fd) { + err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd)); + Py_DECREF(fd); + if (err) + return _pyme_raise_exception (err); + + return _pyme_wrap_gpgme_data_t(*wrapper); + } + else + PyErr_Clear(); + + /* No? Maybe it implements the buffer protocol. */ + data = PyObject_CallMethod(input, "getbuffer", NULL); + if (data) + { + /* Save a reference to input, which seems to be a BytesIO + object. */ + Py_INCREF(input); + *bytesio = input; + } + else + { + PyErr_Clear(); + + /* No, but maybe the user supplied a buffer object? */ + data = input; + } + + /* Do we have a buffer object? */ + if (PyObject_CheckBuffer(data)) + { + if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0) + return NULL; + + if (data != input) + Py_DECREF(data); + + assert (view->obj); + assert (view->ndim == 1); + assert (view->shape == NULL); + assert (view->strides == NULL); + assert (view->suboffsets == NULL); + + err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0); + if (err) + return _pyme_raise_exception (err); + + return _pyme_wrap_gpgme_data_t(*wrapper); + } + + /* As last resort we assume it is a wrapped data object. */ + if (PyObject_HasAttrString(data, "_ctype")) + return _pyme_obj2gpgme_t(data, "gpgme_data_t", argnum); + + return PyErr_Format(PyExc_TypeError, + "arg %d: expected pyme.Data, file, or an object " + "implementing the buffer protocol, got %s", + argnum, data->ob_type->tp_name); +} + + + +PyObject * +_pyme_wrap_result(PyObject *fragile, const char *classname) +{ + static PyObject *results; + PyObject *class; + PyObject *replacement; + + if (results == NULL) + { + PyObject *from_list = PyList_New(0); + if (from_list == NULL) + return NULL; + + results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(), + PyEval_GetLocals(), from_list, 1); + Py_DECREF(from_list); + + if (results == NULL) + return NULL; + } + + class = PyMapping_GetItemString(PyModule_GetDict(results), classname); + if (class == NULL) + return NULL; + + replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL); + Py_DECREF(class); + return replacement; +} + + + +/* Callback support. */ +static gpgme_error_t pyPassphraseCb(void *hook, + const char *uid_hint, + const char *passphrase_info, + int prev_was_bad, + int fd) { + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *args = NULL; + PyObject *retval = NULL; + PyObject *dataarg = NULL; + PyObject *encoded = NULL; + gpgme_error_t err_status = 0; + + _pyme_exception_init(); + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + if (PyTuple_Size(pyhook) == 3) { + dataarg = PyTuple_GetItem(pyhook, 2); + args = PyTuple_New(4); + } else { + args = PyTuple_New(3); + } + + if (uid_hint == NULL) + { + Py_INCREF(Py_None); + PyTuple_SetItem(args, 0, Py_None); + } + else + PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint), + "strict")); + if (PyErr_Occurred()) { + Py_DECREF(args); + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + + PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info)); + PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad)); + if (dataarg) { + Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ + PyTuple_SetItem(args, 3, dataarg); + } + + retval = PyObject_CallObject(func, args); + Py_DECREF(args); + if (PyErr_Occurred()) { + err_status = _pyme_exception2code(); + } else { + if (!retval) { + if (write(fd, "\n", 1) < 0) { + err_status = gpgme_error_from_syserror (); + _pyme_raise_exception (err_status); + } + } else { + char *buf; + size_t len; + if (PyBytes_Check(retval)) + buf = PyBytes_AsString(retval), len = PyBytes_Size(retval); + else if (PyUnicode_Check(retval)) + { + Py_ssize_t ssize; + encoded = PyUnicode_AsUTF8String(retval); + if (encoded == NULL) + { + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1) + { + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + assert (! buf || ssize >= 0); + len = (size_t) ssize; + } + else + { + PyErr_Format(PyExc_TypeError, + "expected str or bytes from passphrase callback, got %s", + retval->ob_type->tp_name); + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + + if (write(fd, buf, len) < 0) { + err_status = gpgme_error_from_syserror (); + _pyme_raise_exception (err_status); + } + if (! err_status && write(fd, "\n", 1) < 0) { + err_status = gpgme_error_from_syserror (); + _pyme_raise_exception (err_status); + } + + Py_DECREF(retval); + } + } + + leave: + if (err_status) + _pyme_stash_callback_exception(self); + + Py_XDECREF(encoded); + PyGILState_Release(state); + return err_status; +} + +PyObject * +pyme_set_passphrase_cb(PyObject *self, PyObject *cb) { + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + PyGILState_Release(state); + return NULL; + } + + ctx = _pyme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + + if (cb == Py_None) { + gpgme_set_passphrase_cb(ctx, NULL, NULL); + PyObject_SetAttrString(self, "_passphrase_cb", Py_None); + goto out; + } + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + + gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb, + (void *) cb); + PyObject_SetAttrString(self, "_passphrase_cb", cb); + + out: + Py_INCREF(Py_None); + PyGILState_Release(state); + return Py_None; +} + +static void pyProgressCb(void *hook, const char *what, int type, int current, + int total) { + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + if (PyTuple_Size(pyhook) == 3) { + dataarg = PyTuple_GetItem(pyhook, 2); + args = PyTuple_New(5); + } else { + args = PyTuple_New(4); + } + + PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what), + "strict")); + if (PyErr_Occurred()) { + _pyme_stash_callback_exception(self); + Py_DECREF(args); + PyGILState_Release(state); + return; + } + PyTuple_SetItem(args, 1, PyLong_FromLong((long) type)); + PyTuple_SetItem(args, 2, PyLong_FromLong((long) current)); + PyTuple_SetItem(args, 3, PyLong_FromLong((long) total)); + if (dataarg) { + Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ + PyTuple_SetItem(args, 4, dataarg); + } + + retval = PyObject_CallObject(func, args); + if (PyErr_Occurred()) + _pyme_stash_callback_exception(self); + Py_DECREF(args); + Py_XDECREF(retval); + PyGILState_Release(state); +} + +PyObject * +pyme_set_progress_cb(PyObject *self, PyObject *cb) { + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + PyGILState_Release(state); + return NULL; + } + + ctx = _pyme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + + if (cb == Py_None) { + gpgme_set_progress_cb(ctx, NULL, NULL); + PyObject_SetAttrString(self, "_progress_cb", Py_None); + goto out; + } + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + + gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb); + PyObject_SetAttrString(self, "_progress_cb", cb); + + out: + Py_INCREF(Py_None); + PyGILState_Release(state); + return Py_None; +} + +/* Status callbacks. */ +static gpgme_error_t pyStatusCb(void *hook, const char *keyword, + const char *args) { + PyGILState_STATE state = PyGILState_Ensure(); + gpgme_error_t err = 0; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *dataarg = NULL; + PyObject *pyargs = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + if (PyTuple_Size(pyhook) == 3) { + dataarg = PyTuple_GetItem(pyhook, 2); + pyargs = PyTuple_New(3); + } else { + pyargs = PyTuple_New(2); + } + + if (keyword) + PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword), + "strict")); + else + { + Py_INCREF(Py_None); + PyTuple_SetItem(pyargs, 0, Py_None); + } + PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args), + "strict")); + if (PyErr_Occurred()) { + err = gpg_error(GPG_ERR_GENERAL); + Py_DECREF(pyargs); + goto leave; + } + + if (dataarg) { + Py_INCREF(dataarg); + PyTuple_SetItem(pyargs, 2, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + if (PyErr_Occurred()) + err = _pyme_exception2code(); + Py_DECREF(pyargs); + Py_XDECREF(retval); + + leave: + if (err) + _pyme_stash_callback_exception(self); + PyGILState_Release(state); + return err; +} + +PyObject * +pyme_set_status_cb(PyObject *self, PyObject *cb) { + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *wrapped; + gpgme_ctx_t ctx; + + wrapped = PyObject_GetAttrString(self, "wrapped"); + if (wrapped == NULL) + { + assert (PyErr_Occurred ()); + PyGILState_Release(state); + return NULL; + } + + ctx = _pyme_unwrap_gpgme_ctx_t(wrapped); + Py_DECREF(wrapped); + if (ctx == NULL) + { + if (cb == Py_None) + goto out; + else + return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL"); + } + + if (cb == Py_None) { + gpgme_set_status_cb(ctx, NULL, NULL); + PyObject_SetAttrString(self, "_status_cb", Py_None); + goto out; + } + + if (! PyTuple_Check(cb)) + return PyErr_Format(PyExc_TypeError, "cb must be a tuple"); + if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3) + return PyErr_Format(PyExc_TypeError, + "cb must be a tuple of size 2 or 3"); + + gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb); + PyObject_SetAttrString(self, "_status_cb", cb); + + out: + Py_INCREF(Py_None); + PyGILState_Release(state); + return Py_None; +} + + + +/* Interact callbacks. */ +gpgme_error_t +_pyme_interact_cb(void *opaque, const char *keyword, + const char *args, int fd) +{ + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL; + PyObject *py_keyword; + PyObject *pyopaque = (PyObject *) opaque; + gpgme_error_t err_status = 0; + PyObject *self = NULL; + + _pyme_exception_init(); + + assert (PyTuple_Check(pyopaque)); + assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3); + self = PyTuple_GetItem(pyopaque, 0); + func = PyTuple_GetItem(pyopaque, 1); + if (PyTuple_Size(pyopaque) == 3) { + dataarg = PyTuple_GetItem(pyopaque, 2); + pyargs = PyTuple_New(3); + } else { + pyargs = PyTuple_New(2); + } + + if (keyword) + py_keyword = PyUnicode_FromString(keyword); + else + { + Py_INCREF(Py_None); + py_keyword = Py_None; + } + + PyTuple_SetItem(pyargs, 0, py_keyword); + PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args)); + if (dataarg) { + Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */ + PyTuple_SetItem(pyargs, 2, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + Py_DECREF(pyargs); + if (PyErr_Occurred()) { + err_status = _pyme_exception2code(); + } else { + if (fd>=0 && retval && PyUnicode_Check(retval)) { + PyObject *encoded = NULL; + char *buffer; + Py_ssize_t size; + + encoded = PyUnicode_AsUTF8String(retval); + if (encoded == NULL) + { + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1) + { + Py_DECREF(encoded); + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } + + if (write(fd, buffer, size) < 0) { + err_status = gpgme_error_from_syserror (); + _pyme_raise_exception (err_status); + } + if (! err_status && write(fd, "\n", 1) < 0) { + err_status = gpgme_error_from_syserror (); + _pyme_raise_exception (err_status); + } + Py_DECREF(encoded); + } + } + leave: + if (err_status) + _pyme_stash_callback_exception(self); + + Py_XDECREF(retval); + PyGILState_Release(state); + return err_status; +} + + + +/* Data callbacks. */ + +/* Read up to SIZE bytes into buffer BUFFER from the data object with + the handle HOOK. Return the number of characters read, 0 on EOF + and -1 on error. If an error occurs, errno is set. */ +static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size) +{ + PyGILState_STATE state = PyGILState_Ensure(); + ssize_t result; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *dataarg = NULL; + PyObject *pyargs = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6); + + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + if (PyTuple_Size(pyhook) == 6) { + dataarg = PyTuple_GetItem(pyhook, 5); + pyargs = PyTuple_New(2); + } else { + pyargs = PyTuple_New(1); + } + + PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size)); + if (dataarg) { + Py_INCREF(dataarg); + PyTuple_SetItem(pyargs, 1, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + Py_DECREF(pyargs); + if (PyErr_Occurred()) { + _pyme_stash_callback_exception(self); + result = -1; + goto leave; + } + + if (! PyBytes_Check(retval)) { + PyErr_Format(PyExc_TypeError, + "expected bytes from read callback, got %s", + retval->ob_type->tp_name); + _pyme_stash_callback_exception(self); + result = -1; + goto leave; + } + + if (PyBytes_Size(retval) > size) { + PyErr_Format(PyExc_TypeError, + "expected %zu bytes from read callback, got %zu", + size, PyBytes_Size(retval)); + _pyme_stash_callback_exception(self); + result = -1; + goto leave; + } + + memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval)); + result = PyBytes_Size(retval); + + leave: + Py_XDECREF(retval); + PyGILState_Release(state); + return result; +} + +/* Write up to SIZE bytes from buffer BUFFER to the data object with + the handle HOOK. Return the number of characters written, or -1 + on error. If an error occurs, errno is set. */ +static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size) +{ + PyGILState_STATE state = PyGILState_Ensure(); + ssize_t result; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *dataarg = NULL; + PyObject *pyargs = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6); + + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 2); + if (PyTuple_Size(pyhook) == 6) { + dataarg = PyTuple_GetItem(pyhook, 5); + pyargs = PyTuple_New(2); + } else { + pyargs = PyTuple_New(1); + } + + PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size)); + if (dataarg) { + Py_INCREF(dataarg); + PyTuple_SetItem(pyargs, 1, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + Py_DECREF(pyargs); + if (PyErr_Occurred()) { + _pyme_stash_callback_exception(self); + result = -1; + goto leave; + } + +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(retval)) + result = PyInt_AsSsize_t(retval); + else +#endif + if (PyLong_Check(retval)) + result = PyLong_AsSsize_t(retval); + else { + PyErr_Format(PyExc_TypeError, + "expected int from write callback, got %s", + retval->ob_type->tp_name); + _pyme_stash_callback_exception(self); + result = -1; + } + + leave: + Py_XDECREF(retval); + PyGILState_Release(state); + return result; +} + +/* Set the current position from where the next read or write starts + in the data object with the handle HOOK to OFFSET, relativ to + WHENCE. Returns the new offset in bytes from the beginning of the + data object. */ +static off_t pyDataSeekCb(void *hook, off_t offset, int whence) +{ + PyGILState_STATE state = PyGILState_Ensure(); + off_t result; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *dataarg = NULL; + PyObject *pyargs = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6); + + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 3); + if (PyTuple_Size(pyhook) == 6) { + dataarg = PyTuple_GetItem(pyhook, 5); + pyargs = PyTuple_New(3); + } else { + pyargs = PyTuple_New(2); + } + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 + PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset)); +#else + PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset)); +#endif + PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence)); + if (dataarg) { + Py_INCREF(dataarg); + PyTuple_SetItem(pyargs, 2, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + Py_DECREF(pyargs); + if (PyErr_Occurred()) { + _pyme_stash_callback_exception(self); + result = -1; + goto leave; + } + +#if PY_MAJOR_VERSION < 3 + if (PyInt_Check(retval)) + result = PyInt_AsLong(retval); + else +#endif + if (PyLong_Check(retval)) +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64 + result = PyLong_AsLongLong(retval); +#else + result = PyLong_AsLong(retval); +#endif + else { + PyErr_Format(PyExc_TypeError, + "expected int from seek callback, got %s", + retval->ob_type->tp_name); + _pyme_stash_callback_exception(self); + result = -1; + } + + leave: + Py_XDECREF(retval); + PyGILState_Release(state); + return result; +} + +/* Close the data object with the handle HOOK. */ +static void pyDataReleaseCb(void *hook) +{ + PyGILState_STATE state = PyGILState_Ensure(); + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *dataarg = NULL; + PyObject *pyargs = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6); + + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 4); + if (PyTuple_Size(pyhook) == 6) { + dataarg = PyTuple_GetItem(pyhook, 5); + pyargs = PyTuple_New(1); + } else { + pyargs = PyTuple_New(0); + } + + if (dataarg) { + Py_INCREF(dataarg); + PyTuple_SetItem(pyargs, 0, dataarg); + } + + retval = PyObject_CallObject(func, pyargs); + Py_XDECREF(retval); + Py_DECREF(pyargs); + if (PyErr_Occurred()) + _pyme_stash_callback_exception(self); + PyGILState_Release(state); +} + +PyObject * +pyme_data_new_from_cbs(PyObject *self, + PyObject *pycbs, + gpgme_data_t *r_data) +{ + PyGILState_STATE state = PyGILState_Ensure(); + static struct gpgme_data_cbs cbs = { + pyDataReadCb, + pyDataWriteCb, + pyDataSeekCb, + pyDataReleaseCb, + }; + gpgme_error_t err; + + if (! PyTuple_Check(pycbs)) + return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple"); + if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6) + return PyErr_Format(PyExc_TypeError, + "pycbs must be a tuple of size 5 or 6"); + + err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs); + if (err) + return _pyme_raise_exception(err); + + PyObject_SetAttrString(self, "_data_cbs", pycbs); + + Py_INCREF(Py_None); + PyGILState_Release(state); + return Py_None; +} + + + +/* The assuan callbacks. */ + +gpgme_error_t +_pyme_assuan_data_cb (void *hook, const void *data, size_t datalen) +{ + PyGILState_STATE state = PyGILState_Ensure(); + gpgme_error_t err = 0; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *py_data = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + assert (PyCallable_Check(func)); + + py_data = PyBytes_FromStringAndSize(data, datalen); + if (py_data == NULL) + { + err = _pyme_exception2code(); + goto leave; + } + + retval = PyObject_CallFunctionObjArgs(func, py_data, NULL); + if (PyErr_Occurred()) + err = _pyme_exception2code(); + Py_DECREF(py_data); + Py_XDECREF(retval); + + leave: + if (err) + _pyme_stash_callback_exception(self); + PyGILState_Release(state); + return err; +} + +gpgme_error_t +_pyme_assuan_inquire_cb (void *hook, const char *name, const char *args, + gpgme_data_t *r_data) +{ + PyGILState_STATE state = PyGILState_Ensure(); + gpgme_error_t err = 0; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *py_name = NULL; + PyObject *py_args = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + assert (PyCallable_Check(func)); + + py_name = PyUnicode_FromString(name); + if (py_name == NULL) + { + err = _pyme_exception2code(); + goto leave; + } + + py_args = PyUnicode_FromString(args); + if (py_args == NULL) + { + err = _pyme_exception2code(); + goto leave; + } + + retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL); + if (PyErr_Occurred()) + err = _pyme_exception2code(); + Py_XDECREF(retval); + + /* FIXME: Returning data is not yet implemented. */ + *r_data = NULL; + + leave: + Py_XDECREF(py_name); + Py_XDECREF(py_args); + if (err) + _pyme_stash_callback_exception(self); + PyGILState_Release(state); + return err; +} + +gpgme_error_t +_pyme_assuan_status_cb (void *hook, const char *status, const char *args) +{ + PyGILState_STATE state = PyGILState_Ensure(); + gpgme_error_t err = 0; + PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; + PyObject *func = NULL; + PyObject *py_status = NULL; + PyObject *py_args = NULL; + PyObject *retval = NULL; + + assert (PyTuple_Check(pyhook)); + assert (PyTuple_Size(pyhook) == 2); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + assert (PyCallable_Check(func)); + + py_status = PyUnicode_FromString(status); + if (py_status == NULL) + { + err = _pyme_exception2code(); + goto leave; + } + + py_args = PyUnicode_FromString(args); + if (py_args == NULL) + { + err = _pyme_exception2code(); + goto leave; + } + + retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL); + if (PyErr_Occurred()) + err = _pyme_exception2code(); + Py_XDECREF(retval); + + leave: + Py_XDECREF(py_status); + Py_XDECREF(py_args); + if (err) + _pyme_stash_callback_exception(self); + PyGILState_Release(state); + return err; +} diff --git a/lang/python/helpers.h b/lang/python/helpers.h new file mode 100644 index 0000000..9200f93 --- /dev/null +++ b/lang/python/helpers.h @@ -0,0 +1,39 @@ +/* +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <gpgme.h> +#include "Python.h" + +#ifdef _WIN32 +#include <windows.h> +#define write(fd, str, sz) {DWORD written; WriteFile((HANDLE) fd, str, sz, &written, 0);} +#endif + +/* Flag specifying whether this is an in-tree build. */ +extern int pyme_in_tree_build; + +PyObject *pyme_raise_callback_exception(PyObject *self); + +PyObject *pyme_set_passphrase_cb(PyObject *self, PyObject *cb); +PyObject *pyme_set_progress_cb(PyObject *self, PyObject *cb); +PyObject *pyme_set_status_cb(PyObject *self, PyObject *cb); + +PyObject *pyme_data_new_from_cbs(PyObject *self, PyObject *pycbs, + gpgme_data_t *r_data); diff --git a/lang/python/private.h b/lang/python/private.h new file mode 100644 index 0000000..3a903c1 --- /dev/null +++ b/lang/python/private.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 g10 Code GmbH + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <gpgme.h> + +#ifndef _PYME_PRIVATE_H_ +#define _PYME_PRIVATE_H_ + +/* GPGME glue. Implemented in helpers.c. */ + +void _pyme_exception_init(void); +gpgme_error_t _pyme_exception2code(void); + +PyObject *_pyme_obj2gpgme_t(PyObject *input, const char *objtype, int argnum); +PyObject *_pyme_obj2gpgme_data_t(PyObject *input, int argnum, + gpgme_data_t *wrapper, + PyObject **bytesio, Py_buffer *view); + +PyObject *_pyme_wrap_result(PyObject *fragile, const char *classname); + +gpgme_error_t _pyme_interact_cb(void *opaque, const char *keyword, + const char *args, int fd); +gpgme_error_t _pyme_assuan_data_cb (void *hook, + const void *data, size_t datalen); +gpgme_error_t _pyme_assuan_inquire_cb (void *hook, + const char *name, const char *args, + gpgme_data_t *r_data); +gpgme_error_t _pyme_assuan_status_cb (void *hook, + const char *status, const char *args); + + + +/* SWIG runtime support. Implemented in gpgme.i. */ + +PyObject *_pyme_wrap_gpgme_data_t(gpgme_data_t data); +gpgme_ctx_t _pyme_unwrap_gpgme_ctx_t(PyObject *wrapped); + +#endif /* _PYME_PRIVATE_H_ */ diff --git a/lang/python/pyme/__init__.py b/lang/python/pyme/__init__.py new file mode 100644 index 0000000..12c96c2 --- /dev/null +++ b/lang/python/pyme/__init__.py @@ -0,0 +1,125 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Pyme: GPGME Interface for Python + +Welcome to PyME, the GPGME Interface for Python. "Pyme", when prounced, +rhymes with "Pine". + +The latest release of this package may be obtained from +https://www.gnupg.org + +Previous releases of this package for Python 2 can be obtained from +http://pyme.sourceforge.net + +FEATURES +-------- + + * Feature-rich, full implementation of the GPGME library. Supports + all GPGME features. Callback functions may be written in pure + Python. Exceptions raised in callbacks are properly propagated. + + * Ability to sign, encrypt, decrypt, and verify data. + + * Ability to list keys, export and import keys, and manage the keyring. + + * Fully object-oriented with convenient classes and modules. + +QUICK EXAMPLE +------------- + + >>> import pyme + >>> with pyme.Context() as c: + >>> with pyme.Context() as c: + ... cipher, _, _ = c.encrypt("Hello world :)".encode(), + ... passphrase="abc") + ... c.decrypt(cipher, passphrase="abc") + ... + (b'Hello world :)', + <pyme.results.DecryptResult object at 0x7f5ab8121080>, + <pyme.results.VerifyResult object at 0x7f5ab81219b0>) + +GENERAL OVERVIEW +---------------- + +For those of you familiar with GPGME, you will be right at home here. + +Pyme is, for the most part, a direct interface to the C GPGME +library. However, it is re-packaged in a more Pythonic way -- +object-oriented with classes and modules. Take a look at the classes +defined here -- they correspond directly to certain object types in GPGME +for C. For instance, the following C code: + +gpgme_ctx_t context; +gpgme_new(&context); +... +gpgme_op_encrypt(context, recp, 1, plain, cipher); + +Translates into the following Python code: + +context = core.Context() +... +context.op_encrypt(recp, 1, plain, cipher) + +The Python module automatically does error-checking and raises Python +exception pyme.errors.GPGMEError when GPGME signals an error. getcode() +and getsource() of this exception return code and source of the error. + +IMPORTANT NOTE +-------------- +This documentation only covers a small subset of available GPGME functions and +methods. Please consult the documentation for the C library +for comprehensive coverage. + +This library uses Python's reflection to automatically detect the methods +that are available for each class, and as such, most of those methods +do not appear explicitly anywhere. You can use dir() python built-in command +on an object to see what methods and fields it has but their meaning can +be found only in GPGME documentation. + +FOR MORE INFORMATION +-------------------- +PYME3 homepage: https://www.gnupg.org/ +GPGME documentation: https://www.gnupg.org/documentation/manuals/gpgme/ + +""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import core +from . import errors +from . import constants +from . import util +from . import callbacks +from . import version +from .core import Context +from .core import Data + +# Interface hygiene. + +# Drop the low-level gpgme that creeps in for some reason. +gpgme = None +del gpgme + +# This is a white-list of symbols. Any other will alert pyflakes. +_ = [Context, Data, core, errors, constants, util, callbacks, version] +del _ + +__all__ = ["Context", "Data", + "core", "errors", "constants", "util", "callbacks", "version"] diff --git a/lang/python/pyme/__pycache__/__init__.cpython-34.pyc b/lang/python/pyme/__pycache__/__init__.cpython-34.pyc Binary files differnew file mode 100644 index 0000000..ba78937 --- /dev/null +++ b/lang/python/pyme/__pycache__/__init__.cpython-34.pyc diff --git a/lang/python/pyme/__pycache__/version.cpython-34.pyc b/lang/python/pyme/__pycache__/version.cpython-34.pyc Binary files differnew file mode 100644 index 0000000..658008a --- /dev/null +++ b/lang/python/pyme/__pycache__/version.cpython-34.pyc diff --git a/lang/python/pyme/callbacks.py b/lang/python/pyme/callbacks.py new file mode 100644 index 0000000..b25a9a7 --- /dev/null +++ b/lang/python/pyme/callbacks.py @@ -0,0 +1,49 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from getpass import getpass + +def passphrase_stdin(hint, desc, prev_bad, hook=None): + """This is a sample callback that will read a passphrase from + the terminal. The hook here, if present, will be used to describe + why the passphrase is needed.""" + why = '' + if hook != None: + why = ' ' + hook + if prev_bad: + why += ' (again)' + print("Please supply %s' password%s:" % (hint, why)) + return getpass() + +def progress_stdout(what, type, current, total, hook=None): + print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\ + (what, type, current, total)) + +def readcb_fh(count, hook): + """A callback for data. hook should be a Python file-like object.""" + if count: + # Should return '' on EOF + return hook.read(count) + else: + # Wants to rewind. + if not hasattr(hook, 'seek'): + return None + hook.seek(0, 0) + return None diff --git a/lang/python/pyme/constants/__init__.py b/lang/python/pyme/constants/__init__.py new file mode 100644 index 0000000..96d89e4 --- /dev/null +++ b/lang/python/pyme/constants/__init__.py @@ -0,0 +1,114 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_', globals()) + +__all__ = ['data', 'event', 'import', 'keylist', 'md', 'pk', + 'protocol', 'sig', 'sigsum', 'status', 'validity'] + +# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We +# implement pyme.Context.op_edit using gpgme_op_interact, so the +# callbacks will be called with string keywords instead of numeric +# status messages. Code that is using these constants will continue +# to work. + +STATUS_ABORT = "ABORT" +STATUS_ALREADY_SIGNED = "ALREADY_SIGNED" +STATUS_ATTRIBUTE = "ATTRIBUTE" +STATUS_BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" +STATUS_BAD_PASSPHRASE = "BAD_PASSPHRASE" +STATUS_BADARMOR = "BADARMOR" +STATUS_BADMDC = "BADMDC" +STATUS_BADSIG = "BADSIG" +STATUS_BEGIN_DECRYPTION = "BEGIN_DECRYPTION" +STATUS_BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" +STATUS_BEGIN_SIGNING = "BEGIN_SIGNING" +STATUS_BEGIN_STREAM = "BEGIN_STREAM" +STATUS_CARDCTRL = "CARDCTRL" +STATUS_DECRYPTION_FAILED = "DECRYPTION_FAILED" +STATUS_DECRYPTION_INFO = "DECRYPTION_INFO" +STATUS_DECRYPTION_OKAY = "DECRYPTION_OKAY" +STATUS_DELETE_PROBLEM = "DELETE_PROBLEM" +STATUS_ENC_TO = "ENC_TO" +STATUS_END_DECRYPTION = "END_DECRYPTION" +STATUS_END_ENCRYPTION = "END_ENCRYPTION" +STATUS_END_STREAM = "END_STREAM" +STATUS_ENTER = "ENTER" +STATUS_ERRMDC = "ERRMDC" +STATUS_ERROR = "ERROR" +STATUS_ERRSIG = "ERRSIG" +STATUS_EXPKEYSIG = "EXPKEYSIG" +STATUS_EXPSIG = "EXPSIG" +STATUS_FAILURE = "FAILURE" +STATUS_FILE_DONE = "FILE_DONE" +STATUS_FILE_ERROR = "FILE_ERROR" +STATUS_FILE_START = "FILE_START" +STATUS_GET_BOOL = "GET_BOOL" +STATUS_GET_HIDDEN = "GET_HIDDEN" +STATUS_GET_LINE = "GET_LINE" +STATUS_GOOD_PASSPHRASE = "GOOD_PASSPHRASE" +STATUS_GOODMDC = "GOODMDC" +STATUS_GOODSIG = "GOODSIG" +STATUS_GOT_IT = "GOT_IT" +STATUS_IMPORT_OK = "IMPORT_OK" +STATUS_IMPORT_PROBLEM = "IMPORT_PROBLEM" +STATUS_IMPORT_RES = "IMPORT_RES" +STATUS_IMPORTED = "IMPORTED" +STATUS_INQUIRE_MAXLEN = "INQUIRE_MAXLEN" +STATUS_INV_RECP = "INV_RECP" +STATUS_INV_SGNR = "INV_SGNR" +STATUS_KEY_CONSIDERED = "KEY_CONSIDERED" +STATUS_KEY_CREATED = "KEY_CREATED" +STATUS_KEY_NOT_CREATED = "KEY_NOT_CREATED" +STATUS_KEYEXPIRED = "KEYEXPIRED" +STATUS_KEYREVOKED = "KEYREVOKED" +STATUS_LEAVE = "LEAVE" +STATUS_MISSING_PASSPHRASE = "MISSING_PASSPHRASE" +STATUS_MOUNTPOINT = "MOUNTPOINT" +STATUS_NEED_PASSPHRASE = "NEED_PASSPHRASE" +STATUS_NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" +STATUS_NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" +STATUS_NEWSIG = "NEWSIG" +STATUS_NO_PUBKEY = "NO_PUBKEY" +STATUS_NO_RECP = "NO_RECP" +STATUS_NO_SECKEY = "NO_SECKEY" +STATUS_NO_SGNR = "NO_SGNR" +STATUS_NODATA = "NODATA" +STATUS_NOTATION_DATA = "NOTATION_DATA" +STATUS_NOTATION_FLAGS = "NOTATION_FLAGS" +STATUS_NOTATION_NAME = "NOTATION_NAME" +STATUS_PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" +STATUS_PKA_TRUST_BAD = "PKA_TRUST_BAD" +STATUS_PKA_TRUST_GOOD = "PKA_TRUST_GOOD" +STATUS_PLAINTEXT = "PLAINTEXT" +STATUS_PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" +STATUS_POLICY_URL = "POLICY_URL" +STATUS_PROGRESS = "PROGRESS" +STATUS_REVKEYSIG = "REVKEYSIG" +STATUS_RSA_OR_IDEA = "RSA_OR_IDEA" +STATUS_SC_OP_FAILURE = "SC_OP_FAILURE" +STATUS_SC_OP_SUCCESS = "SC_OP_SUCCESS" +STATUS_SESSION_KEY = "SESSION_KEY" +STATUS_SHM_GET = "SHM_GET" +STATUS_SHM_GET_BOOL = "SHM_GET_BOOL" +STATUS_SHM_GET_HIDDEN = "SHM_GET_HIDDEN" +STATUS_SHM_INFO = "SHM_INFO" +STATUS_SIG_CREATED = "SIG_CREATED" +STATUS_SIG_ID = "SIG_ID" +STATUS_SIG_SUBPACKET = "SIG_SUBPACKET" +STATUS_SIGEXPIRED = "SIGEXPIRED" +STATUS_SUCCESS = "SUCCESS" +STATUS_TOFU_STATS = "TOFU_STATS" +STATUS_TOFU_STATS_LONG = "TOFU_STATS_LONG" +STATUS_TOFU_USER = "TOFU_USER" +STATUS_TRUNCATED = "TRUNCATED" +STATUS_TRUST_FULLY = "TRUST_FULLY" +STATUS_TRUST_MARGINAL = "TRUST_MARGINAL" +STATUS_TRUST_NEVER = "TRUST_NEVER" +STATUS_TRUST_ULTIMATE = "TRUST_ULTIMATE" +STATUS_TRUST_UNDEFINED = "TRUST_UNDEFINED" +STATUS_UNEXPECTED = "UNEXPECTED" +STATUS_USERID_HINT = "USERID_HINT" +STATUS_VALIDSIG = "VALIDSIG" diff --git a/lang/python/pyme/constants/data/__init__.py b/lang/python/pyme/constants/data/__init__.py new file mode 100644 index 0000000..8274ab9 --- /dev/null +++ b/lang/python/pyme/constants/data/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import encoding +__all__ = ['encoding'] diff --git a/lang/python/pyme/constants/data/encoding.py b/lang/python/pyme/constants/data/encoding.py new file mode 100644 index 0000000..a05dbb4 --- /dev/null +++ b/lang/python/pyme/constants/data/encoding.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_DATA_ENCODING_', globals()) diff --git a/lang/python/pyme/constants/event.py b/lang/python/pyme/constants/event.py new file mode 100644 index 0000000..2e30c5e --- /dev/null +++ b/lang/python/pyme/constants/event.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_EVENT_', globals()) diff --git a/lang/python/pyme/constants/import.py b/lang/python/pyme/constants/import.py new file mode 100644 index 0000000..10e7d3c --- /dev/null +++ b/lang/python/pyme/constants/import.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_IMPORT_', globals()) diff --git a/lang/python/pyme/constants/keylist/__init__.py b/lang/python/pyme/constants/keylist/__init__.py new file mode 100644 index 0000000..2ce0edf --- /dev/null +++ b/lang/python/pyme/constants/keylist/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import mode +__all__ = ['mode'] diff --git a/lang/python/pyme/constants/keylist/mode.py b/lang/python/pyme/constants/keylist/mode.py new file mode 100644 index 0000000..000dd79 --- /dev/null +++ b/lang/python/pyme/constants/keylist/mode.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_KEYLIST_MODE_', globals()) diff --git a/lang/python/pyme/constants/md.py b/lang/python/pyme/constants/md.py new file mode 100644 index 0000000..dbd762c --- /dev/null +++ b/lang/python/pyme/constants/md.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_MD_', globals()) diff --git a/lang/python/pyme/constants/pk.py b/lang/python/pyme/constants/pk.py new file mode 100644 index 0000000..cfc5309 --- /dev/null +++ b/lang/python/pyme/constants/pk.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_PK_', globals()) diff --git a/lang/python/pyme/constants/protocol.py b/lang/python/pyme/constants/protocol.py new file mode 100644 index 0000000..a4b6583 --- /dev/null +++ b/lang/python/pyme/constants/protocol.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_PROTOCOL_', globals()) diff --git a/lang/python/pyme/constants/sig/__init__.py b/lang/python/pyme/constants/sig/__init__.py new file mode 100644 index 0000000..2ce0edf --- /dev/null +++ b/lang/python/pyme/constants/sig/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import mode +__all__ = ['mode'] diff --git a/lang/python/pyme/constants/sig/mode.py b/lang/python/pyme/constants/sig/mode.py new file mode 100644 index 0000000..fb534bc --- /dev/null +++ b/lang/python/pyme/constants/sig/mode.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_SIG_MODE_', globals()) diff --git a/lang/python/pyme/constants/sigsum.py b/lang/python/pyme/constants/sigsum.py new file mode 100644 index 0000000..3d94745 --- /dev/null +++ b/lang/python/pyme/constants/sigsum.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_SIGSUM_', globals()) diff --git a/lang/python/pyme/constants/status.py b/lang/python/pyme/constants/status.py new file mode 100644 index 0000000..a04d9aa --- /dev/null +++ b/lang/python/pyme/constants/status.py @@ -0,0 +1,124 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We +# implement pyme.Context.op_edit using gpgme_op_interact, so the +# callbacks will be called with string keywords instead of numeric +# status messages. Code that is using these constants will continue +# to work. + +ABORT = "ABORT" +ALREADY_SIGNED = "ALREADY_SIGNED" +ATTRIBUTE = "ATTRIBUTE" +BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" +BAD_PASSPHRASE = "BAD_PASSPHRASE" +BADARMOR = "BADARMOR" +BADMDC = "BADMDC" +BADSIG = "BADSIG" +BEGIN_DECRYPTION = "BEGIN_DECRYPTION" +BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" +BEGIN_SIGNING = "BEGIN_SIGNING" +BEGIN_STREAM = "BEGIN_STREAM" +CARDCTRL = "CARDCTRL" +DECRYPTION_FAILED = "DECRYPTION_FAILED" +DECRYPTION_INFO = "DECRYPTION_INFO" +DECRYPTION_OKAY = "DECRYPTION_OKAY" +DELETE_PROBLEM = "DELETE_PROBLEM" +ENC_TO = "ENC_TO" +END_DECRYPTION = "END_DECRYPTION" +END_ENCRYPTION = "END_ENCRYPTION" +END_STREAM = "END_STREAM" +ENTER = "ENTER" +ERRMDC = "ERRMDC" +ERROR = "ERROR" +ERRSIG = "ERRSIG" +EXPKEYSIG = "EXPKEYSIG" +EXPSIG = "EXPSIG" +FAILURE = "FAILURE" +FILE_DONE = "FILE_DONE" +FILE_ERROR = "FILE_ERROR" +FILE_START = "FILE_START" +GET_BOOL = "GET_BOOL" +GET_HIDDEN = "GET_HIDDEN" +GET_LINE = "GET_LINE" +GOOD_PASSPHRASE = "GOOD_PASSPHRASE" +GOODMDC = "GOODMDC" +GOODSIG = "GOODSIG" +GOT_IT = "GOT_IT" +IMPORT_OK = "IMPORT_OK" +IMPORT_PROBLEM = "IMPORT_PROBLEM" +IMPORT_RES = "IMPORT_RES" +IMPORTED = "IMPORTED" +INQUIRE_MAXLEN = "INQUIRE_MAXLEN" +INV_RECP = "INV_RECP" +INV_SGNR = "INV_SGNR" +KEY_CONSIDERED = "KEY_CONSIDERED" +KEY_CREATED = "KEY_CREATED" +KEY_NOT_CREATED = "KEY_NOT_CREATED" +KEYEXPIRED = "KEYEXPIRED" +KEYREVOKED = "KEYREVOKED" +LEAVE = "LEAVE" +MISSING_PASSPHRASE = "MISSING_PASSPHRASE" +MOUNTPOINT = "MOUNTPOINT" +NEED_PASSPHRASE = "NEED_PASSPHRASE" +NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" +NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" +NEWSIG = "NEWSIG" +NO_PUBKEY = "NO_PUBKEY" +NO_RECP = "NO_RECP" +NO_SECKEY = "NO_SECKEY" +NO_SGNR = "NO_SGNR" +NODATA = "NODATA" +NOTATION_DATA = "NOTATION_DATA" +NOTATION_FLAGS = "NOTATION_FLAGS" +NOTATION_NAME = "NOTATION_NAME" +PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" +PKA_TRUST_BAD = "PKA_TRUST_BAD" +PKA_TRUST_GOOD = "PKA_TRUST_GOOD" +PLAINTEXT = "PLAINTEXT" +PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" +POLICY_URL = "POLICY_URL" +PROGRESS = "PROGRESS" +REVKEYSIG = "REVKEYSIG" +RSA_OR_IDEA = "RSA_OR_IDEA" +SC_OP_FAILURE = "SC_OP_FAILURE" +SC_OP_SUCCESS = "SC_OP_SUCCESS" +SESSION_KEY = "SESSION_KEY" +SHM_GET = "SHM_GET" +SHM_GET_BOOL = "SHM_GET_BOOL" +SHM_GET_HIDDEN = "SHM_GET_HIDDEN" +SHM_INFO = "SHM_INFO" +SIG_CREATED = "SIG_CREATED" +SIG_ID = "SIG_ID" +SIG_SUBPACKET = "SIG_SUBPACKET" +SIGEXPIRED = "SIGEXPIRED" +SUCCESS = "SUCCESS" +TOFU_STATS = "TOFU_STATS" +TOFU_STATS_LONG = "TOFU_STATS_LONG" +TOFU_USER = "TOFU_USER" +TRUNCATED = "TRUNCATED" +TRUST_FULLY = "TRUST_FULLY" +TRUST_MARGINAL = "TRUST_MARGINAL" +TRUST_NEVER = "TRUST_NEVER" +TRUST_ULTIMATE = "TRUST_ULTIMATE" +TRUST_UNDEFINED = "TRUST_UNDEFINED" +UNEXPECTED = "UNEXPECTED" +USERID_HINT = "USERID_HINT" +VALIDSIG = "VALIDSIG" diff --git a/lang/python/pyme/constants/validity.py b/lang/python/pyme/constants/validity.py new file mode 100644 index 0000000..4ecd4d3 --- /dev/null +++ b/lang/python/pyme/constants/validity.py @@ -0,0 +1,22 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import util +util.process_constants('GPGME_VALIDITY_', globals()) diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py new file mode 100644 index 0000000..88a086b --- /dev/null +++ b/lang/python/pyme/core.py @@ -0,0 +1,1145 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Core functionality + +Core functionality of GPGME wrapped in a object-oriented fashion. +Provides the 'Context' class for performing cryptographic operations, +and the 'Data' class describing buffers of data. + +""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import re +import os +import warnings +import weakref +from . import gpgme +from .errors import errorcheck, GPGMEError +from . import constants +from . import errors +from . import util + +class GpgmeWrapper(object): + """Base wrapper class + + Not to be instantiated directly. + + """ + + def __init__(self, wrapped): + self._callback_excinfo = None + self.wrapped = wrapped + + def __repr__(self): + return '<{}/{!r}>'.format(super(GpgmeWrapper, self).__repr__(), + self.wrapped) + + def __str__(self): + acc = ['{}.{}'.format(__name__, self.__class__.__name__)] + flags = [f for f in self._boolean_properties if getattr(self, f)] + if flags: + acc.append('({})'.format(' '.join(flags))) + + return '<{}>'.format(' '.join(acc)) + + def __hash__(self): + return hash(repr(self.wrapped)) + + def __eq__(self, other): + if other == None: + return False + else: + return repr(self.wrapped) == repr(other.wrapped) + + @property + def _ctype(self): + """The name of the c type wrapped by this class + + Must be set by child classes. + + """ + raise NotImplementedError() + + @property + def _cprefix(self): + """The common prefix of c functions wrapped by this class + + Must be set by child classes. + + """ + raise NotImplementedError() + + def _errorcheck(self, name): + """Must be implemented by child classes. + + This function must return a trueish value for all c functions + returning gpgme_error_t.""" + raise NotImplementedError() + + """The set of all boolean properties""" + _boolean_properties = set() + + def __wrap_boolean_property(self, key, do_set=False, value=None): + get_func = getattr(gpgme, + "{}get_{}".format(self._cprefix, key)) + set_func = getattr(gpgme, + "{}set_{}".format(self._cprefix, key)) + def get(slf): + return bool(get_func(slf.wrapped)) + def set_(slf, value): + set_func(slf.wrapped, bool(value)) + + p = property(get, set_, doc="{} flag".format(key)) + setattr(self.__class__, key, p) + + if do_set: + set_(self, bool(value)) + else: + return get(self) + + _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)') + def __getattr__(self, key): + """On-the-fly generation of wrapper methods and properties""" + if key[0] == '_' or self._cprefix == None: + return None + + if key in self._boolean_properties: + return self.__wrap_boolean_property(key) + + name = self._cprefix + key + func = getattr(gpgme, name) + + if self._errorcheck(name): + def _funcwrap(slf, *args): + result = func(slf.wrapped, *args) + if slf._callback_excinfo: + gpgme.pyme_raise_callback_exception(slf) + return errorcheck(result, "Invocation of " + name) + else: + def _funcwrap(slf, *args): + result = func(slf.wrapped, *args) + if slf._callback_excinfo: + gpgme.pyme_raise_callback_exception(slf) + return result + + doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__")) + _funcwrap.__doc__ = doc + + # Monkey-patch the class. + setattr(self.__class__, key, _funcwrap) + + # Bind the method to 'self'. + def wrapper(*args): + return _funcwrap(self, *args) + wrapper.__doc__ = doc + + return wrapper + + def __setattr__(self, key, value): + """On-the-fly generation of properties""" + if key in self._boolean_properties: + self.__wrap_boolean_property(key, True, value) + else: + super(GpgmeWrapper, self).__setattr__(key, value) + +class Context(GpgmeWrapper): + """Context for cryptographic operations + + All cryptographic operations in GPGME are performed within a + context, which contains the internal state of the operation as + well as configuration parameters. By using several contexts you + can run several cryptographic operations in parallel, with + different configuration. + + Access to a context must be synchronized. + + """ + + def __init__(self, armor=False, textmode=False, offline=False, + signers=[], pinentry_mode=constants.PINENTRY_MODE_DEFAULT, + protocol=constants.PROTOCOL_OpenPGP, + wrapped=None): + """Construct a context object + + Keyword arguments: + armor -- enable ASCII armoring (default False) + textmode -- enable canonical text mode (default False) + offline -- do not contact external key sources (default False) + signers -- list of keys used for signing (default []) + pinentry_mode -- pinentry mode (default PINENTRY_MODE_DEFAULT) + protocol -- protocol to use (default PROTOCOL_OpenPGP) + + """ + if wrapped: + self.own = False + else: + tmp = gpgme.new_gpgme_ctx_t_p() + errorcheck(gpgme.gpgme_new(tmp)) + wrapped = gpgme.gpgme_ctx_t_p_value(tmp) + gpgme.delete_gpgme_ctx_t_p(tmp) + self.own = True + super(Context, self).__init__(wrapped) + self.armor = armor + self.textmode = textmode + self.offline = offline + self.signers = signers + self.pinentry_mode = pinentry_mode + self.protocol = protocol + + def encrypt(self, plaintext, recipients=[], sign=True, sink=None, + passphrase=None, always_trust=False, add_encrypt_to=False, + prepare=False, expect_sign=False, compress=True): + """Encrypt data + + Encrypt the given plaintext for the given recipients. If the + list of recipients is empty, the data is encrypted + symmetrically with a passphrase. + + The passphrase can be given as parameter, using a callback + registered at the context, or out-of-band via pinentry. + + Keyword arguments: + recipients -- list of keys to encrypt to + sign -- sign plaintext (default True) + sink -- write result to sink instead of returning it + passphrase -- for symmetric encryption + always_trust -- always trust the keys (default False) + add_encrypt_to -- encrypt to configured additional keys (default False) + prepare -- (ui) prepare for encryption (default False) + expect_sign -- (ui) prepare for signing (default False) + compress -- compress plaintext (default True) + + Returns: + ciphertext -- the encrypted data (or None if sink is given) + result -- additional information about the encryption + sign_result -- additional information about the signature(s) + + Raises: + InvalidRecipients -- if encryption using a particular key failed + InvalidSigners -- if signing using a particular key failed + GPGMEError -- as signaled by the underlying library + + """ + ciphertext = sink if sink else Data() + flags = 0 + flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST + flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO + flags |= prepare * constants.ENCRYPT_PREPARE + flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN + flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS + + if passphrase != None: + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + if sign: + self.op_encrypt_sign(recipients, flags, plaintext, ciphertext) + else: + self.op_encrypt(recipients, flags, plaintext, ciphertext) + except errors.GPGMEError as e: + if e.getcode() == errors.UNUSABLE_PUBKEY: + result = self.op_encrypt_result() + if result.invalid_recipients: + raise errors.InvalidRecipients(result.invalid_recipients) + if e.getcode() == errors.UNUSABLE_SECKEY: + sig_result = self.op_sign_result() + if sig_result.invalid_signers: + raise errors.InvalidSigners(sig_result.invalid_signers) + raise + finally: + if passphrase != None: + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + result = self.op_encrypt_result() + assert not result.invalid_recipients + sig_result = self.op_sign_result() if sign else None + assert not sig_result or not sig_result.invalid_signers + + cipherbytes = None + if not sink: + ciphertext.seek(0, os.SEEK_SET) + cipherbytes = ciphertext.read() + return cipherbytes, result, sig_result + + def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True): + """Decrypt data + + Decrypt the given ciphertext and verify any signatures. If + VERIFY is an iterable of keys, the ciphertext must be signed + by all those keys, otherwise an error is raised. + + If the ciphertext is symmetrically encrypted using a + passphrase, that passphrase can be given as parameter, using a + callback registered at the context, or out-of-band via + pinentry. + + Keyword arguments: + sink -- write result to sink instead of returning it + passphrase -- for symmetric decryption + verify -- check signatures (default True) + + Returns: + plaintext -- the decrypted data (or None if sink is given) + result -- additional information about the decryption + verify_result -- additional information about the signature(s) + + Raises: + UnsupportedAlgorithm -- if an unsupported algorithm was used + BadSignatures -- if a bad signature is encountered + MissingSignatures -- if expected signatures are missing or bad + GPGMEError -- as signaled by the underlying library + + """ + plaintext = sink if sink else Data() + + if passphrase != None: + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + if verify: + self.op_decrypt_verify(ciphertext, plaintext) + else: + self.op_decrypt(ciphertext, plaintext) + finally: + if passphrase != None: + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + result = self.op_decrypt_result() + verify_result = self.op_verify_result() if verify else None + if result.unsupported_algorithm: + raise errors.UnsupportedAlgorithm(result.unsupported_algorithm) + + if verify: + if any(s.status != errors.NO_ERROR + for s in verify_result.signatures): + raise errors.BadSignatures(verify_result) + + if verify and verify != True: + missing = list() + for key in verify: + ok = False + for subkey in key.subkeys: + for sig in verify_result.signatures: + if sig.summary & constants.SIGSUM_VALID == 0: + continue + if subkey.can_sign and subkey.fpr == sig.fpr: + ok = True + break + if ok: + break + if not ok: + missing.append(key) + if missing: + raise errors.MissingSignatures(verify_result, missing) + + plainbytes = None + if not sink: + plaintext.seek(0, os.SEEK_SET) + plainbytes = plaintext.read() + return plainbytes, result, verify_result + + def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL): + """Sign data + + Sign the given data with either the configured default local + key, or the 'signers' keys of this context. + + Keyword arguments: + mode -- signature mode (default: normal, see below) + sink -- write result to sink instead of returning it + + Returns: + either + signed_data -- encoded data and signature (normal mode) + signature -- only the signature data (detached mode) + cleartext -- data and signature as text (cleartext mode) + (or None if sink is given) + result -- additional information about the signature(s) + + Raises: + InvalidSigners -- if signing using a particular key failed + GPGMEError -- as signaled by the underlying library + + """ + signeddata = sink if sink else Data() + + try: + self.op_sign(data, signeddata, mode) + except errors.GPGMEError as e: + if e.getcode() == errors.UNUSABLE_SECKEY: + result = self.op_sign_result() + if result.invalid_signers: + raise errors.InvalidSigners(result.invalid_signers) + raise + + result = self.op_sign_result() + assert not result.invalid_signers + + signedbytes = None + if not sink: + signeddata.seek(0, os.SEEK_SET) + signedbytes = signeddata.read() + return signedbytes, result + + def verify(self, signed_data, signature=None, sink=None, verify=[]): + """Verify signatures + + Verify signatures over data. If VERIFY is an iterable of + keys, the ciphertext must be signed by all those keys, + otherwise an error is raised. + + Keyword arguments: + signature -- detached signature data + sink -- write result to sink instead of returning it + + Returns: + data -- the plain data + (or None if sink is given, or we verified a detached signature) + result -- additional information about the signature(s) + + Raises: + BadSignatures -- if a bad signature is encountered + MissingSignatures -- if expected signatures are missing or bad + GPGMEError -- as signaled by the underlying library + + """ + if signature: + # Detached signature, we don't return the plain text. + data = None + else: + data = sink if sink else Data() + + if signature: + self.op_verify(signature, signed_data, None) + else: + self.op_verify(signed_data, None, data) + + result = self.op_verify_result() + if any(s.status != errors.NO_ERROR for s in result.signatures): + raise errors.BadSignatures(result) + + missing = list() + for key in verify: + ok = False + for subkey in key.subkeys: + for sig in result.signatures: + if sig.summary & constants.SIGSUM_VALID == 0: + continue + if subkey.can_sign and subkey.fpr == sig.fpr: + ok = True + break + if ok: + break + if not ok: + missing.append(key) + if missing: + raise errors.MissingSignatures(result, missing) + + plainbytes = None + if data and not sink: + data.seek(0, os.SEEK_SET) + plainbytes = data.read() + return plainbytes, result + + def keylist(self, pattern=None, secret=False): + """List keys + + Keyword arguments: + pattern -- return keys matching pattern (default: all keys) + secret -- return only secret keys + + Returns: + -- an iterator returning key objects + + Raises: + GPGMEError -- as signaled by the underlying library + """ + return self.op_keylist_all(pattern, secret) + + def assuan_transact(self, command, + data_cb=None, inquire_cb=None, status_cb=None): + """Issue a raw assuan command + + This function can be used to issue a raw assuan command to the + engine. + + If command is a string or bytes, it will be used as-is. If it + is an iterable of strings, it will be properly escaped and + joined into an well-formed assuan command. + + Keyword arguments: + data_cb -- a callback receiving data lines + inquire_cb -- a callback providing more information + status_cb -- a callback receiving status lines + + Returns: + result -- the result of command as GPGMEError + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + + if isinstance(command, (str, bytes)): + cmd = command + else: + cmd = " ".join(util.percent_escape(f) for f in command) + + errptr = gpgme.new_gpgme_error_t_p() + + err = gpgme.gpgme_op_assuan_transact_ext( + self.wrapped, + cmd, + (weakref.ref(self), data_cb) if data_cb else None, + (weakref.ref(self), inquire_cb) if inquire_cb else None, + (weakref.ref(self), status_cb) if status_cb else None, + errptr) + + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + + errorcheck(err) + + status = gpgme.gpgme_error_t_p_value(errptr) + gpgme.delete_gpgme_error_t_p(errptr) + + return GPGMEError(status) if status != 0 else None + + def interact(self, key, func, sink=None, flags=0, fnc_value=None): + """Interact with the engine + + This method can be used to edit keys and cards interactively. + KEY is the key to edit, FUNC is called repeatedly with two + unicode arguments, 'keyword' and 'args'. See the GPGME manual + for details. + + Keyword arguments: + sink -- if given, additional output is written here + flags -- use constants.INTERACT_CARD to edit a card + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + if key == None: + raise ValueError("First argument cannot be None") + + if sink == None: + sink = Data() + + if fnc_value: + opaquedata = (weakref.ref(self), func, fnc_value) + else: + opaquedata = (weakref.ref(self), func) + + result = gpgme.gpgme_op_interact(self.wrapped, key, flags, + opaquedata, sink) + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + errorcheck(result) + + @property + def signers(self): + """Keys used for signing""" + return [self.signers_enum(i) for i in range(self.signers_count())] + @signers.setter + def signers(self, signers): + old = self.signers + self.signers_clear() + try: + for key in signers: + self.signers_add(key) + except: + self.signers = old + raise + + @property + def pinentry_mode(self): + """Pinentry mode""" + return self.get_pinentry_mode() + @pinentry_mode.setter + def pinentry_mode(self, value): + self.set_pinentry_mode(value) + + @property + def protocol(self): + """Protocol to use""" + return self.get_protocol() + @protocol.setter + def protocol(self, value): + errorcheck(gpgme.gpgme_engine_check_version(value)) + self.set_protocol(value) + + _ctype = 'gpgme_ctx_t' + _cprefix = 'gpgme_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + return ((name.startswith('gpgme_op_') + and not name.endswith('_result')) + or name in { + 'gpgme_set_ctx_flag', + 'gpgme_set_protocol', + 'gpgme_set_sub_protocol', + 'gpgme_set_keylist_mode', + 'gpgme_set_pinentry_mode', + 'gpgme_set_locale', + 'gpgme_set_engine_info', + 'gpgme_signers_add', + 'gpgme_get_sig_key', + 'gpgme_sig_notation_add', + 'gpgme_cancel', + 'gpgme_cancel_async', + 'gpgme_cancel_get_key', + }) + + _boolean_properties = {'armor', 'textmode', 'offline'} + + def __del__(self): + if not gpgme: + # At interpreter shutdown, gpgme is set to NONE. + return + + self._free_passcb() + self._free_progresscb() + self._free_statuscb() + if self.own and self.wrapped and gpgme.gpgme_release: + gpgme.gpgme_release(self.wrapped) + self.wrapped = None + + # Implement the context manager protocol. + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.__del__() + + def op_keylist_all(self, *args, **kwargs): + self.op_keylist_start(*args, **kwargs) + key = self.op_keylist_next() + while key: + yield key + key = self.op_keylist_next() + self.op_keylist_end() + + def op_keylist_next(self): + """Returns the next key in the list created + by a call to op_keylist_start(). The object returned + is of type Key.""" + ptr = gpgme.new_gpgme_key_t_p() + try: + errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr)) + key = gpgme.gpgme_key_t_p_value(ptr) + except errors.GPGMEError as excp: + key = None + if excp.getcode() != errors.EOF: + raise excp + gpgme.delete_gpgme_key_t_p(ptr) + if key: + key.__del__ = lambda self: gpgme.gpgme_key_unref(self) + return key + + def get_key(self, fpr, secret): + """Return the key corresponding to the fingerprint 'fpr'""" + ptr = gpgme.new_gpgme_key_t_p() + errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret)) + key = gpgme.gpgme_key_t_p_value(ptr) + gpgme.delete_gpgme_key_t_p(ptr) + if key: + key.__del__ = lambda self: gpgme.gpgme_key_unref(self) + return key + + def op_trustlist_all(self, *args, **kwargs): + self.op_trustlist_start(*args, **kwargs) + trust = self.op_trustlist_next() + while trust: + yield trust + trust = self.op_trustlist_next() + self.op_trustlist_end() + + def op_trustlist_next(self): + """Returns the next trust item in the list created + by a call to op_trustlist_start(). The object returned + is of type TrustItem.""" + ptr = gpgme.new_gpgme_trust_item_t_p() + try: + errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr)) + trust = gpgme.gpgme_trust_item_t_p_value(ptr) + except errors.GPGMEError as excp: + trust = None + if excp.getcode() != errors.EOF: + raise + gpgme.delete_gpgme_trust_item_t_p(ptr) + return trust + + def set_passphrase_cb(self, func, hook=None): + """Sets the passphrase callback to the function specified by func. + + When the system needs a passphrase, it will call func with three args: + hint, a string describing the key it needs the passphrase for; + desc, a string describing the passphrase it needs; + prev_bad, a boolean equal True if this is a call made after + unsuccessful previous attempt. + + If hook has a value other than None it will be passed into the func + as a forth argument. + + Please see the GPGME manual for more information. + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.pyme_set_passphrase_cb(self, hookdata) + + def _free_passcb(self): + if gpgme.pyme_set_passphrase_cb: + self.set_passphrase_cb(None) + + def set_progress_cb(self, func, hook=None): + """Sets the progress meter callback to the function specified by FUNC. + If FUNC is None, the callback will be cleared. + + This function will be called to provide an interactive update + of the system's progress. The function will be called with + three arguments, type, total, and current. If HOOK is not + None, it will be supplied as fourth argument. + + Please see the GPGME manual for more information. + + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.pyme_set_progress_cb(self, hookdata) + + def _free_progresscb(self): + if gpgme.pyme_set_progress_cb: + self.set_progress_cb(None) + + def set_status_cb(self, func, hook=None): + """Sets the status callback to the function specified by FUNC. If + FUNC is None, the callback will be cleared. + + The function will be called with two arguments, keyword and + args. If HOOK is not None, it will be supplied as third + argument. + + Please see the GPGME manual for more information. + + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.pyme_set_status_cb(self, hookdata) + + def _free_statuscb(self): + if gpgme.pyme_set_status_cb: + self.set_status_cb(None) + + @property + def engine_info(self): + """Configuration of the engine currently in use""" + p = self.protocol + infos = [i for i in self.get_engine_info() if i.protocol == p] + assert len(infos) == 1 + return infos[0] + + def get_engine_info(self): + """Get engine configuration + + Returns information about all configured and installed + engines. + + Returns: + infos -- a list of engine infos + + """ + return gpgme.gpgme_ctx_get_engine_info(self.wrapped) + + def set_engine_info(self, proto, file_name=None, home_dir=None): + """Change engine configuration + + Changes the configuration of the crypto engine implementing + the protocol 'proto' for the context. + + Keyword arguments: + file_name -- engine program file name (unchanged if None) + home_dir -- configuration directory (unchanged if None) + + """ + errorcheck(gpgme.gpgme_ctx_set_engine_info( + self.wrapped, proto, file_name, home_dir)) + + def wait(self, hang): + """Wait for asynchronous call to finish. Wait forever if hang is True. + Raises an exception on errors. + + Please read the GPGME manual for more information. + + """ + ptr = gpgme.new_gpgme_error_t_p() + gpgme.gpgme_wait(self.wrapped, ptr, hang) + status = gpgme.gpgme_error_t_p_value(ptr) + gpgme.delete_gpgme_error_t_p(ptr) + errorcheck(status) + + def op_edit(self, key, func, fnc_value, out): + """Start key editing using supplied callback function + + Note: This interface is deprecated and will be removed with + GPGME 1.8. Please use .interact instead. Furthermore, we + implement this using gpgme_op_interact, so callbacks will get + called with string keywords instead of numeric status + messages. Code that is using constants.STATUS_X or + constants.status.X will continue to work, whereas code using + magic numbers will break as a result. + + """ + warnings.warn("Call to deprecated method op_edit.", + category=DeprecationWarning) + return self.interact(key, func, sink=out, fnc_value=fnc_value) + + +class Data(GpgmeWrapper): + """Data buffer + + A lot of data has to be exchanged between the user and the crypto + engine, like plaintext messages, ciphertext, signatures and + information about the keys. The technical details about + exchanging the data information are completely abstracted by + GPGME. The user provides and receives the data via `gpgme_data_t' + objects, regardless of the communication protocol between GPGME + and the crypto engine in use. + + This Data class is the implementation of the GpgmeData objects. + + Please see the information about __init__ for instantiation. + + """ + + _ctype = 'gpgme_data_t' + _cprefix = 'gpgme_data_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + return name not in { + 'gpgme_data_release_and_get_mem', + 'gpgme_data_get_encoding', + 'gpgme_data_seek', + 'gpgme_data_get_file_name', + } + + def __init__(self, string=None, file=None, offset=None, + length=None, cbs=None, copy=True): + """Initialize a new gpgme_data_t object. + + If no args are specified, make it an empty object. + + If string alone is specified, initialize it with the data + contained there. + + If file, offset, and length are all specified, file must + be either a filename or a file-like object, and the object + will be initialized by reading the specified chunk from the file. + + If cbs is specified, it MUST be a tuple of the form: + + (read_cb, write_cb, seek_cb, release_cb[, hook]) + + where the first four items are functions implementing reading, + writing, seeking the data, and releasing any resources once + the data object is deallocated. The functions must match the + following prototypes: + + def read(amount, hook=None): + return <a b"bytes" object> + + def write(data, hook=None): + return <the number of bytes written> + + def seek(offset, whence, hook=None): + return <the new file position> + + def release(hook=None): + <return value and exceptions are ignored> + + The functions may be bound methods. In that case, you can + simply use the 'self' reference instead of using a hook. + + If file is specified without any other arguments, then + it must be a filename, and the object will be initialized from + that file. + + """ + super(Data, self).__init__(None) + self.data_cbs = None + + if cbs != None: + self.new_from_cbs(*cbs) + elif string != None: + self.new_from_mem(string, copy) + elif file != None and offset != None and length != None: + self.new_from_filepart(file, offset, length) + elif file != None: + if util.is_a_string(file): + self.new_from_file(file, copy) + else: + self.new_from_fd(file) + else: + self.new() + + def __del__(self): + if not gpgme: + # At interpreter shutdown, gpgme is set to NONE. + return + + if self.wrapped != None and gpgme.gpgme_data_release: + gpgme.gpgme_data_release(self.wrapped) + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + self.wrapped = None + self._free_datacbs() + + # Implement the context manager protocol. + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.__del__() + + def _free_datacbs(self): + self._data_cbs = None + + def new(self): + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new(tmp)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_mem(self, string, copy=True): + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new_from_mem(tmp,string,len(string),copy)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_file(self, filename, copy=True): + tmp = gpgme.new_gpgme_data_t_p() + try: + errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy)) + except errors.GPGMEError as e: + if e.getcode() == errors.INV_VALUE and not copy: + raise ValueError("delayed reads are not yet supported") + else: + raise e + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None): + tmp = gpgme.new_gpgme_data_t_p() + if hook != None: + hookdata = (weakref.ref(self), + read_cb, write_cb, seek_cb, release_cb, hook) + else: + hookdata = (weakref.ref(self), + read_cb, write_cb, seek_cb, release_cb) + gpgme.pyme_data_new_from_cbs(self, hookdata, tmp) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_filepart(self, file, offset, length): + """This wraps the GPGME gpgme_data_new_from_filepart() function. + The argument "file" may be: + + * a string specifying a file name, or + * a file-like object supporting the fileno() and the mode attribute. + + """ + + tmp = gpgme.new_gpgme_data_t_p() + filename = None + fp = None + + if util.is_a_string(file): + filename = file + else: + fp = gpgme.fdopen(file.fileno(), file.mode) + if fp == None: + raise ValueError("Failed to open file from %s arg %s" % \ + (str(type(file)), str(file))) + + errorcheck(gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, + offset, length)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_fd(self, file): + """This wraps the GPGME gpgme_data_new_from_fd() function. The + argument "file" must be a file-like object, supporting the + fileno() method. + + """ + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno())) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_stream(self, file): + """This wrap around gpgme_data_new_from_stream is an alias for + new_from_fd() method since in python there's not difference + between file stream and file descriptor""" + self.new_from_fd(file) + + def write(self, buffer): + """Write buffer given as string or bytes. + + If a string is given, it is implicitly encoded using UTF-8.""" + written = gpgme.gpgme_data_write(self.wrapped, buffer) + if written < 0: + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + else: + raise GPGMEError.fromSyserror() + return written + + def read(self, size = -1): + """Read at most size bytes, returned as bytes. + + If the size argument is negative or omitted, read until EOF is reached. + + Returns the data read, or the empty string if there was no data + to read before EOF was reached.""" + + if size == 0: + return '' + + if size > 0: + try: + result = gpgme.gpgme_data_read(self.wrapped, size) + except: + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + else: + raise + return result + else: + chunks = [] + while True: + try: + result = gpgme.gpgme_data_read(self.wrapped, 4096) + except: + if self._callback_excinfo: + gpgme.pyme_raise_callback_exception(self) + else: + raise + if len(result) == 0: + break + chunks.append(result) + return b''.join(chunks) + +def pubkey_algo_name(algo): + return gpgme.gpgme_pubkey_algo_name(algo) + +def hash_algo_name(algo): + return gpgme.gpgme_hash_algo_name(algo) + +def get_protocol_name(proto): + return gpgme.gpgme_get_protocol_name(proto) + +def check_version(version=None): + return gpgme.gpgme_check_version(version) + +# check_version also makes sure that several subsystems are properly +# initialized, and it must be run at least once before invoking any +# other function. We do it here so that the user does not have to do +# it unless she really wants to check for a certain version. +check_version() + +def engine_check_version (proto): + try: + errorcheck(gpgme.gpgme_engine_check_version(proto)) + return True + except errors.GPGMEError: + return False + +def get_engine_info(): + ptr = gpgme.new_gpgme_engine_info_t_p() + try: + errorcheck(gpgme.gpgme_get_engine_info(ptr)) + info = gpgme.gpgme_engine_info_t_p_value(ptr) + except errors.GPGMEError: + info = None + gpgme.delete_gpgme_engine_info_t_p(ptr) + return info + +def set_engine_info(proto, file_name, home_dir=None): + """Changes the default configuration of the crypto engine implementing + the protocol 'proto'. 'file_name' is the file name of + the executable program implementing this protocol. 'home_dir' is the + directory name of the configuration directory (engine's default is + used if omitted).""" + errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir)) + +def set_locale(category, value): + """Sets the default locale used by contexts""" + errorcheck(gpgme.gpgme_set_locale(None, category, value)) + +def wait(hang): + """Wait for asynchronous call on any Context to finish. + Wait forever if hang is True. + + For finished anynch calls it returns a tuple (status, context): + status - status return by asnynchronous call. + context - context which caused this call to return. + + Please read the GPGME manual of more information.""" + ptr = gpgme.new_gpgme_error_t_p() + context = gpgme.gpgme_wait(None, ptr, hang) + status = gpgme.gpgme_error_t_p_value(ptr) + gpgme.delete_gpgme_error_t_p(ptr) + if context == None: + errorcheck(status) + else: + context = Context(context) + return (status, context) diff --git a/lang/python/pyme/errors.py b/lang/python/pyme/errors.py new file mode 100644 index 0000000..e26c747 --- /dev/null +++ b/lang/python/pyme/errors.py @@ -0,0 +1,111 @@ +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import gpgme +from . import util + +util.process_constants('GPG_ERR_', globals()) + +# To appease static analysis tools, we define some constants here: +NO_ERROR = 0 + +class PymeError(Exception): + pass + +class GPGMEError(PymeError): + def __init__(self, error = None, message = None): + self.error = error + self.message = message + + @classmethod + def fromSyserror(cls): + return cls(gpgme.gpgme_err_code_from_syserror()) + + def getstring(self): + message = "%s: %s" % (gpgme.gpgme_strsource(self.error), + gpgme.gpgme_strerror(self.error)) + if self.message != None: + message = "%s: %s" % (self.message, message) + return message + + def getcode(self): + return gpgme.gpgme_err_code(self.error) + + def getsource(self): + return gpgme.gpgme_err_source(self.error) + + def __str__(self): + return self.getstring() + +def errorcheck(retval, extradata = None): + if retval: + raise GPGMEError(retval, extradata) + +# These errors are raised in the idiomatic interface code. + +class EncryptionError(PymeError): + pass + +class InvalidRecipients(EncryptionError): + def __init__(self, recipients): + self.recipients = recipients + def __str__(self): + return ", ".join("{}: {}".format(r.fpr, + gpgme.gpgme_strerror(r.reason)) + for r in self.recipients) + +class DeryptionError(PymeError): + pass + +class UnsupportedAlgorithm(DeryptionError): + def __init__(self, algorithm): + self.algorithm = algorithm + def __str__(self): + return self.algorithm + +class SigningError(PymeError): + pass + +class InvalidSigners(SigningError): + def __init__(self, signers): + self.signers = signers + def __str__(self): + return ", ".join("{}: {}".format(s.fpr, + gpgme.gpgme_strerror(s.reason)) + for s in self.signers) + +class VerificationError(PymeError): + pass + +class BadSignatures(VerificationError): + def __init__(self, result): + self.result = result + def __str__(self): + return ", ".join("{}: {}".format(s.fpr, + gpgme.gpgme_strerror(s.status)) + for s in self.result.signatures + if s.status != NO_ERROR) + +class MissingSignatures(VerificationError): + def __init__(self, result, missing): + self.result = result + self.missing = missing + def __str__(self): + return ", ".join(k.subkeys[0].fpr for k in self.missing) diff --git a/lang/python/pyme/gpgme.py b/lang/python/pyme/gpgme.py new file mode 100644 index 0000000..ea4983d --- /dev/null +++ b/lang/python/pyme/gpgme.py @@ -0,0 +1,125 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 3.0.7 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + + + + + +from sys import version_info +if version_info >= (2, 6, 0): + def swig_import_helper(): + from os.path import dirname + import imp + fp = None + try: + fp, pathname, description = imp.find_module('_gpgme', [dirname(__file__)]) + except ImportError: + import _gpgme + return _gpgme + if fp is not None: + try: + _mod = imp.load_module('_gpgme', fp, pathname, description) + finally: + fp.close() + return _mod + _gpgme = swig_import_helper() + del swig_import_helper +else: + import _gpgme +del version_info +from _gpgme import * +try: + _swig_property = property +except NameError: + pass # Python < 2.2 doesn't have 'property'. + + +def _swig_setattr_nondynamic(self, class_type, name, value, static=1): + if (name == "thisown"): + return self.this.own(value) + if (name == "this"): + if type(value).__name__ == 'SwigPyObject': + self.__dict__[name] = value + return + method = class_type.__swig_setmethods__.get(name, None) + if method: + return method(self, value) + if (not static): + if _newclass: + object.__setattr__(self, name, value) + else: + self.__dict__[name] = value + else: + raise AttributeError("You cannot add attributes to %s" % self) + + +def _swig_setattr(self, class_type, name, value): + return _swig_setattr_nondynamic(self, class_type, name, value, 0) + + +def _swig_getattr_nondynamic(self, class_type, name, static=1): + if (name == "thisown"): + return self.this.own() + method = class_type.__swig_getmethods__.get(name, None) + if method: + return method(self) + if (not static): + return object.__getattr__(self, name) + else: + raise AttributeError(name) + +def _swig_getattr(self, class_type, name): + return _swig_getattr_nondynamic(self, class_type, name, 0) + + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + +try: + _object = object + _newclass = 1 +except AttributeError: + class _object: + pass + _newclass = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This file is compatible with both classic and new-style classes. + + diff --git a/lang/python/pyme/results.py b/lang/python/pyme/results.py new file mode 100644 index 0000000..3383896 --- /dev/null +++ b/lang/python/pyme/results.py @@ -0,0 +1,118 @@ +# Robust result objects +# +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +"""Robust result objects + +Results returned by the underlying library are fragile, i.e. they are +only valid until the next operation is performed in the context. + +We cannot arbitrarily constrain the lifetime of Python objects, we +therefore create deep copies of the results. + +""" + +class Result(object): + """Result object + + Describes the result of an operation. + + """ + + """Convert to types""" + _type = {} + + """Map functions over list attributes""" + _map = {} + + """Automatically copy unless blacklisted""" + _blacklist = { + 'acquire', 'append', 'disown', 'next', 'own', 'this', 'thisown', + } + def __init__(self, fragile): + for key, func in self._type.items(): + if hasattr(fragile, key): + setattr(self, key, func(getattr(fragile, key))) + + for key, func in self._map.items(): + if hasattr(fragile, key): + setattr(self, key, list(map(func, getattr(fragile, key)))) + + for key in dir(fragile): + if key.startswith('_') or key in self._blacklist: + continue + if hasattr(self, key): + continue + + setattr(self, key, getattr(fragile, key)) + + def __str__(self): + return '<{} {}>'.format( + self.__class__.__name__, + ', '.join('{}: {}'.format(k, getattr(self, k)) + for k in dir(self) if not k.startswith('_'))) + +class InvalidKey(Result): + pass + +class EncryptResult(Result): + _map = dict(invalid_recipients=InvalidKey) + +class Recipient(Result): + pass + +class DecryptResult(Result): + _type = dict(wrong_key_usage=bool) + _map = dict(recipients=Recipient) + +class NewSignature(Result): + pass + +class SignResult(Result): + _map = dict(invalid_signers=InvalidKey, signatures=NewSignature) + +class Notation(Result): + pass + +class Signature(Result): + _type = dict(wrong_key_usage=bool, chain_model=bool) + _map = dict(notations=Notation) + +class VerifyResult(Result): + _map = dict(signatures=Signature) + +class ImportStatus(Result): + pass + +class ImportResult(Result): + _map = dict(imports=ImportStatus) + +class GenkeyResult(Result): + _type = dict(primary=bool, sub=bool) + +class KeylistResult(Result): + _type = dict(truncated=bool) + +class VFSMountResult(Result): + pass + +class EngineInfo(Result): + pass diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py new file mode 100644 index 0000000..e4fca4c --- /dev/null +++ b/lang/python/pyme/util.py @@ -0,0 +1,53 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys + +def process_constants(prefix, scope): + """Called by the constant modules to load up the constants from the C + library starting with PREFIX. Matching constants will be inserted + into SCOPE with PREFIX stripped from the names. Returns the names + of inserted constants. + + """ + from . import gpgme + index = len(prefix) + constants = {identifier[index:]: getattr(gpgme, identifier) + for identifier in dir(gpgme) + if identifier.startswith(prefix)} + scope.update(constants) + return list(constants.keys()) + +def percent_escape(s): + return ''.join( + '%{0:2x}'.format(ord(c)) + if c == '+' or c == '"' or c == '%' or ord(c) <= 0x20 else c + for c in s) + +# Python2/3 compatibility +if sys.version_info[0] == 3: + # Python3 + def is_a_string(x): + return isinstance(x, str) +else: + # Python2 + def is_a_string(x): + return isinstance(x, basestring) diff --git a/lang/python/pyme/version.py b/lang/python/pyme/version.py new file mode 100644 index 0000000..21a0122 --- /dev/null +++ b/lang/python/pyme/version.py @@ -0,0 +1,68 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2015 Ben McGinnes <ben@adversary.org> +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function +del absolute_import, print_function + +from . import gpgme + +productname = 'pyme' +versionstr = "1.7.0" +gpgme_versionstr = gpgme.GPGME_VERSION +in_tree_build = bool(gpgme.cvar.pyme_in_tree_build) + +versionlist = versionstr.split(".") +major = versionlist[0] +minor = versionlist[1] +patch = versionlist[2] + +copyright = """\ +Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes +Copyright (C) 2014-2015 Martin Albrecht +Copyright (C) 2004-2008 Igor Belyi +Copyright (C) 2002 John Goerzen""" + +author = "The GnuPG hackers" +author_email = "gnupg-devel@gnupg.org" + +description = "Python support for GPGME GnuPG cryptography library" +homepage = "https://gnupg.org" + +license = """Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes <ben@adversary.org> +Copyright (C) 2014, 2015 Martin Albrecht <martinralbrecht@googlemail.com> +Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net> +Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" + +# Interface hygiene. Keep this at the end. +del gpgme diff --git a/lang/python/pyme/version.py.in b/lang/python/pyme/version.py.in new file mode 100644 index 0000000..cfb9510 --- /dev/null +++ b/lang/python/pyme/version.py.in @@ -0,0 +1,68 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2015 Ben McGinnes <ben@adversary.org> +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function +del absolute_import, print_function + +from . import gpgme + +productname = 'pyme' +versionstr = "@VERSION@" +gpgme_versionstr = gpgme.GPGME_VERSION +in_tree_build = bool(gpgme.cvar.pyme_in_tree_build) + +versionlist = versionstr.split(".") +major = versionlist[0] +minor = versionlist[1] +patch = versionlist[2] + +copyright = """\ +Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes +Copyright (C) 2014-2015 Martin Albrecht +Copyright (C) 2004-2008 Igor Belyi +Copyright (C) 2002 John Goerzen""" + +author = "The GnuPG hackers" +author_email = "gnupg-devel@gnupg.org" + +description = "Python support for GPGME GnuPG cryptography library" +homepage = "https://gnupg.org" + +license = """Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes <ben@adversary.org> +Copyright (C) 2014, 2015 Martin Albrecht <martinralbrecht@googlemail.com> +Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net> +Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" + +# Interface hygiene. Keep this at the end. +del gpgme diff --git a/lang/python/setup.py.in b/lang/python/setup.py.in new file mode 100755 index 0000000..31892c1 --- /dev/null +++ b/lang/python/setup.py.in @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from distutils.core import setup, Extension +import os, os.path, sys +import glob +import subprocess + +# Out-of-tree build of the pyme3 bindings. +gpg_error_config = ["gpg-error-config"] +gpgme_config_flags = ["--thread=pthread"] +gpgme_config = ["gpgme-config"] + gpgme_config_flags +gpgme_h = "" +library_dirs = [] +in_tree = False +extra_swig_opts = [] +extra_macros = dict() + +if os.path.exists("../../src/gpgme-config"): + # In-tree build. + in_tree = True + gpgme_config = ["../../src/gpgme-config"] + gpgme_config_flags + gpgme_h = "../../src/gpgme.h" + library_dirs = ["../../src/.libs"] # XXX uses libtool internals + extra_macros.update( + HAVE_DATA_H=1, + IN_TREE_BUILD=1, + ) + +if hasattr(subprocess, "DEVNULL"): + devnull = subprocess.DEVNULL +else: + devnull = open(os.devnull, "w") + +try: + subprocess.check_call(gpg_error_config + ['--version'], + stdout=devnull) +except: + sys.exit("Could not find gpg-error-config. " + + "Please install the libgpg-error development package.") + +try: + subprocess.check_call(gpgme_config + ['--version'], + stdout=devnull) +except: + sys.exit("Could not find gpgme-config. " + + "Please install the libgpgme development package.") + +def getconfig(what, config=gpgme_config): + confdata = subprocess.Popen(config + ["--%s" % what], + stdout=subprocess.PIPE).communicate()[0] + return [x for x in confdata.decode('utf-8').split() if x != ''] + +version = version_raw = getconfig("version")[0] +if '-' in version: + version = version.split('-')[0] +major, minor, patch = map(int, version.split('.')) + +if not (major > 1 or (major == 1 and minor >= 6)): + sys.exit('Need at least GPGME version 1.6, found {}.'.format(version_raw)) + +if not gpgme_h: + gpgme_h = os.path.join(getconfig("prefix")[0], "include", "gpgme.h") + +gpg_error_prefix = getconfig("prefix", config=gpg_error_config)[0] +gpg_error_h = os.path.join(gpg_error_prefix, "include", "gpg-error.h") +if not os.path.exists(gpg_error_h): + gpg_error_h = \ + glob.glob(os.path.join(gpg_error_prefix, "include", + "*", "gpg-error.h"))[0] + +print("Building pyme3 using {} and {}.".format(gpgme_h, gpg_error_h)) + +# Cleanup gpgme.h from deprecated functions and typedefs. +subprocess.check_call([sys.executable, "gpgme-h-clean.py", gpgme_h], + stdout=open("gpgme.h", "w")) +subprocess.check_call([sys.executable, "gpgme-h-clean.py", gpg_error_h], + stdout=open("errors.i", "w")) + +include_dirs = [os.getcwd()] +define_macros = [] +libs = getconfig('libs') + +# Define extra_macros for both the SWIG and C code +for k, v in extra_macros.items(): + extra_swig_opts.append("-D{0}={1}".format(k, v)) + define_macros.append((k, str(v))) + +for item in getconfig('cflags'): + if item.startswith("-I"): + include_dirs.append(item[2:]) + elif item.startswith("-D"): + defitem = item[2:].split("=", 1) + if len(defitem)==2: + define_macros.append((defitem[0], defitem[1])) + else: + define_macros.append((defitem[0], None)) + +# Adjust include and library locations in case of win32 +uname_s = os.popen("uname -s").read() +if uname_s.startswith("MINGW32"): + mnts = [x.split()[0:3:2] for x in os.popen("mount").read().split("\n") if x] + tmplist = sorted([(len(x[1]), x[1], x[0]) for x in mnts]) + tmplist.reverse() + extra_dirs = [] + for item in include_dirs: + for ln, mnt, tgt in tmplist: + if item.startswith(mnt): + item = os.path.normpath(item[ln:]) + while item[0] == os.path.sep: + item = item[1:] + extra_dirs.append(os.path.join(tgt, item)) + break + include_dirs += extra_dirs + for item in [x[2:] for x in libs if x.startswith("-L")]: + for ln, mnt, tgt in tmplist: + if item.startswith(mnt): + item = os.path.normpath(item[ln:]) + while item[0] == os.path.sep: + item = item[1:] + library_dirs.append(os.path.join(tgt, item)) + break + +# We build an Extension using SWIG, which generates a Python module. +# By default, the 'build_py' step is run before 'build_ext', and +# therefore the generated Python module is not copied into the build +# directory. +# Bug: http://bugs.python.org/issue1016626 +# Workaround: +# http://stackoverflow.com/questions/12491328/python-distutils-not-include-the-swig-generated-module +from distutils.command.build import build +class BuildExtFirstHack(build): + def run(self): + self.run_command('build_ext') + build.run(self) + +swige = Extension("pyme._gpgme", ["gpgme.i", "helpers.c"], + swig_opts = ['-py3', '-builtin', '-threads', + '-outdir', 'pyme'] + extra_swig_opts, + include_dirs = include_dirs, + define_macros = define_macros, + library_dirs = library_dirs, + extra_link_args = libs) + +setup(name="pyme3", + cmdclass={'build': BuildExtFirstHack}, + version="@VERSION@", + description='Python bindings for GPGME GnuPG cryptography library', + # XXX add a long description + #long_description=long_description, + author='The GnuPG hackers', + author_email='gnupg-devel@gnupg.org', + url='https://www.gnupg.org', + ext_modules=[swige], + packages = ['pyme', 'pyme.constants', 'pyme.constants.data', + 'pyme.constants.keylist', 'pyme.constants.sig'], + license="LGPL2.1+ (the library), GPL2+ (tests and examples)", + classifiers=[ + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Operating System :: POSIX', + 'Operating System :: Microsoft :: Windows', + 'Topic :: Communications :: Email', + 'Topic :: Security :: Cryptography', + ], +) diff --git a/lang/python/tests/Makefile.am b/lang/python/tests/Makefile.am new file mode 100644 index 0000000..aa88bdc --- /dev/null +++ b/lang/python/tests/Makefile.am @@ -0,0 +1,114 @@ +# Makefile.am for the tests of the Python bindings. +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +GPG = gpg +GPG_AGENT = gpg-agent +export GNUPGHOME := $(abs_builddir) +export GPG_AGENT_INFO := + +test_srcdir = $(top_srcdir)/tests/gpg + +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) \ + LC_ALL=C GPG_AGENT_INFO= \ + top_srcdir=$(top_srcdir) \ + srcdir=$(srcdir) \ + LD_LIBRARY_PATH="../../../src/.libs:$(LD_LIBRARY_PATH)" + +py_tests = t-wrapper.py \ + t-callbacks.py \ + t-data.py \ + t-encrypt.py \ + t-encrypt-sym.py \ + t-encrypt-sign.py \ + t-sign.py \ + t-signers.py \ + t-decrypt.py \ + t-verify.py \ + t-decrypt-verify.py \ + t-sig-notation.py \ + t-export.py \ + t-import.py \ + t-trustlist.py \ + t-edit.py \ + t-keylist.py \ + t-wait.py \ + t-encrypt-large.py \ + t-file-name.py \ + t-idiomatic.py \ + t-protocol-assuan.py + +XTESTS = initial.py $(py_tests) final.py +EXTRA_DIST = support.py $(XTESTS) encrypt-only.asc sign-only.asc \ + run-tests.py + +# XXX: Currently, one cannot override automake's 'check' target. As a +# workaround, we avoid defining 'TESTS', thus automake will not emit +# the 'check' target. For extra robustness, we merely define a +# dependency on 'xcheck', so this hack should also work even if +# automake would emit the 'check' target, as adding dependencies to +# targets is okay. +check: xcheck + +.PHONY: xcheck + +xcheck: ./pubring-stamp + $(TESTS_ENVIRONMENT) $(PYTHON) $(srcdir)/run-tests.py \ + --interpreters="$(PYTHONS)" --srcdir=$(srcdir) $(TESTFLAGS) \ + $(XTESTS) + +CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \ + gpg-agent.conf pubring.kbx~ gpg.conf pubring.gpg~ \ + random_seed .gpg-v21-migrated \ + pubring-stamp private-keys-v1.d/gpg-sample.stamp + +private_keys = \ + $(test_srcdir)/13CD0F3BDF24BE53FE192D62F18737256FF6E4FD \ + $(test_srcdir)/76F7E2B35832976B50A27A282D9B87E44577EB66 \ + $(test_srcdir)/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD \ + $(test_srcdir)/13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F \ + $(test_srcdir)/7A030357C0F253A5BBCD282FFC4E521B37558F5C + +clean-local: + -$(top_srcdir)/tests/start-stop-agent --stop + -rm -fR -- private-keys-v1.d openpgp-revocs.d S.gpg-agent sshcontrol + + +./private-keys-v1.d/gpg-sample.stamp: $(private_keys) + test -d ./private-keys-v1.d || mkdir ./private-keys-v1.d + for k in $(private_keys); do \ + cp $$k private-keys-v1.d/$${k#$(test_srcdir)/}.key; \ + done + echo x > ./private-keys-v1.d/gpg-sample.stamp + +./pubring-stamp: $(test_srcdir)/pubdemo.asc \ + ./gpg.conf ./gpg-agent.conf \ + ./private-keys-v1.d/gpg-sample.stamp + $(GPG) --batch --no-permission-warning \ + --import $(test_srcdir)/pubdemo.asc + -$(GPG) --batch --no-permission-warning \ + --import $(test_srcdir)/secdemo.asc + echo x > ./pubring-stamp + +./gpg.conf: +# This is required for t-sig-notations. + echo no-force-v3-sigs > ./gpg.conf + +./gpg-agent.conf: +# This is required for gpg2, which does not support command fd. + echo pinentry-program $(abs_top_srcdir)/tests/gpg/pinentry >$@ + echo allow-loopback-pinentry >>$@ diff --git a/lang/python/tests/Makefile.in b/lang/python/tests/Makefile.in new file mode 100644 index 0000000..3886bf4 --- /dev/null +++ b/lang/python/tests/Makefile.in @@ -0,0 +1,620 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am for the tests of the Python bindings. +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/python/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GPG = gpg +GPG_AGENT = gpg-agent +test_srcdir = $(top_srcdir)/tests/gpg +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) \ + LC_ALL=C GPG_AGENT_INFO= \ + top_srcdir=$(top_srcdir) \ + srcdir=$(srcdir) \ + LD_LIBRARY_PATH="../../../src/.libs:$(LD_LIBRARY_PATH)" + +py_tests = t-wrapper.py \ + t-callbacks.py \ + t-data.py \ + t-encrypt.py \ + t-encrypt-sym.py \ + t-encrypt-sign.py \ + t-sign.py \ + t-signers.py \ + t-decrypt.py \ + t-verify.py \ + t-decrypt-verify.py \ + t-sig-notation.py \ + t-export.py \ + t-import.py \ + t-trustlist.py \ + t-edit.py \ + t-keylist.py \ + t-wait.py \ + t-encrypt-large.py \ + t-file-name.py \ + t-idiomatic.py \ + t-protocol-assuan.py + +XTESTS = initial.py $(py_tests) final.py +EXTRA_DIST = support.py $(XTESTS) encrypt-only.asc sign-only.asc \ + run-tests.py + +CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \ + gpg-agent.conf pubring.kbx~ gpg.conf pubring.gpg~ \ + random_seed .gpg-v21-migrated \ + pubring-stamp private-keys-v1.d/gpg-sample.stamp + +private_keys = \ + $(test_srcdir)/13CD0F3BDF24BE53FE192D62F18737256FF6E4FD \ + $(test_srcdir)/76F7E2B35832976B50A27A282D9B87E44577EB66 \ + $(test_srcdir)/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD \ + $(test_srcdir)/13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F \ + $(test_srcdir)/7A030357C0F253A5BBCD282FFC4E521B37558F5C + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/python/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/python/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + clean-local cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am + +export GNUPGHOME := $(abs_builddir) +export GPG_AGENT_INFO := + +# XXX: Currently, one cannot override automake's 'check' target. As a +# workaround, we avoid defining 'TESTS', thus automake will not emit +# the 'check' target. For extra robustness, we merely define a +# dependency on 'xcheck', so this hack should also work even if +# automake would emit the 'check' target, as adding dependencies to +# targets is okay. +check: xcheck + +.PHONY: xcheck + +xcheck: ./pubring-stamp + $(TESTS_ENVIRONMENT) $(PYTHON) $(srcdir)/run-tests.py \ + --interpreters="$(PYTHONS)" --srcdir=$(srcdir) $(TESTFLAGS) \ + $(XTESTS) + +clean-local: + -$(top_srcdir)/tests/start-stop-agent --stop + -rm -fR -- private-keys-v1.d openpgp-revocs.d S.gpg-agent sshcontrol + +./private-keys-v1.d/gpg-sample.stamp: $(private_keys) + test -d ./private-keys-v1.d || mkdir ./private-keys-v1.d + for k in $(private_keys); do \ + cp $$k private-keys-v1.d/$${k#$(test_srcdir)/}.key; \ + done + echo x > ./private-keys-v1.d/gpg-sample.stamp + +./pubring-stamp: $(test_srcdir)/pubdemo.asc \ + ./gpg.conf ./gpg-agent.conf \ + ./private-keys-v1.d/gpg-sample.stamp + $(GPG) --batch --no-permission-warning \ + --import $(test_srcdir)/pubdemo.asc + -$(GPG) --batch --no-permission-warning \ + --import $(test_srcdir)/secdemo.asc + echo x > ./pubring-stamp + +./gpg.conf: +# This is required for t-sig-notations. + echo no-force-v3-sigs > ./gpg.conf + +./gpg-agent.conf: +# This is required for gpg2, which does not support command fd. + echo pinentry-program $(abs_top_srcdir)/tests/gpg/pinentry >$@ + echo allow-loopback-pinentry >>$@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/python/tests/encrypt-only.asc b/lang/python/tests/encrypt-only.asc new file mode 100644 index 0000000..6e068a0 --- /dev/null +++ b/lang/python/tests/encrypt-only.asc @@ -0,0 +1,33 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v2 + +lQPGBFd/jL0BCAD8jfoblIrlHS0shDCbSiO7RFaT6sEa/6tSPkv6XzBba9oXOkuO +FLTkNpIwPb92U8SOS+27j7n9v6U5NW2tyZwIoeLb8lUyKnCBr22IUhTFVXf7fros +zmPugsJaDBi9f7RL0bqiCn4EV3DGKyAukZklk1k1JV4Ec3dEPMAmL9LmnvXreEjU +pQZZN9sJV32ew8CYkZ6AB8foFQwfxn4x0iUoKvj8kW9RsY1KMPucp4YiFhHeMZW1 +5wGAZdEIZYKyWEp4bi/wC9yn/TUR5uNWc0uVJzQvuHwaYjolPW89DinjBkPEJCBr +RwumaOWfbu/hb51wBoUTmUr9diVw93L2ROLPABEBAAH+BwMC1bmUAoPJKI/WBiHm +P6tSNRLdd+7etfjAFvKL7Ob2pNTrc3hbtyOLIQ9tuEaqXEyfnCms/DCg8QdkaFUv +Nkoj0W5+G/MQuR2jIvrq/wyL/4jIw0AFbp9/V1JbSXZh2g1eJLnnykn7uPxCbDFY +FrVeFmkhoxZ3pid6ZQSWlxXsdW+YMvbUfNIIZpbygI/alIBvbDS1YJYEBDCwFZjU +7quE2Ufxo8dm34EHcmbpYpn4r3DUrU5AHQ2fIprLIVqHn4+NUrR8WZS9nCnIeu/z +OaJUZ2lJFRjUC6Gpsbsw6Xwh4Ntwzyt2SsXc+UVZngjozw3yw0VpDifxMBqcd+9x +baSc7dfbOZF2BCZOwnB7/QrFZDaqe5b3n6rTdj1va/CrJMuxbgaNAjvLpdT2EUPZ +fHDAdPAjASofxBREv+HIKwksuPJ9cvavZU6Q4KQA7buo25hd7yjuba4WbLQhp0jH +AT1P7SdakMhk/IFcUKFdB3ZyZZZ1JTTPa2xZn9yDa3Jb1t7IMLYLwY6EFbjvaxH5 +WEGZvOAq2iEa941mxv4miwgf7MQPx6g9u0+dXc7iZApwWs9MNfJo3J25sKhWK5Be +Bu3w7c6nrlg40GtPuDRgaBvYWbVerJcepTA/EPfugEJtRsDJkt7wZq1H9lWHU7Ih +Up6/+XKtBzlCIqYjorzFLnC721pcKFcPhLgvtjjNJvUsLXbr9CwnBub/eTFcfRb2 +ro60H9cOhf0fQSQyvkZWfzq0BN6rG27G1KhyprsJAmpW0fTHHkB4V19788C2sTQv +D93VU3Nd6MWocwAYtPWmtwXPpuOAU9IcwAvVTxBeBJCXxbH3uyx1frwDXA7lf4Pb +a8hMoMMVU+rAG1uepKI5h4seBIKP7qKEKAPloI6/Vtf7/Ump4DKprS1QpfOW+lsX +aR48lgNR6sQXtDdFbmNyeXB0aW9uIE9ubHkgKHRlc3Qga2V5LCBkbyBub3QgdXNl +KSA8ZW9AZXhhbXBsZS5vcmc+iQE3BBMBCAAhBQJXf4y9AhsNBQsJCAcCBhUICQoL +AgQWAgMBAh4BAheAAAoJEJIFcnabn+Gc/KgH/07wzrsBzTqdI5L6cIqQ81Vq8ASj +tsuYoVfFxymB8F/AxpnLMhYRuWQTcoUHQ/olG2yA0C6o4e1JPAmh6LQGwr0eRnc2 +2tr4cbnQAhXpJ8xOR6kH9eE8nGeC7tlEeeV/Wnj3SLZOXOjYjnA9bA3JX9DP3qcz +w1sKQPEHsGkMJuT0ZadnlJ1qw8AnnNKLDlG4kIO9hz3qB8BjxFZf+j5f/nhFNv5I +pnNdMcDwQqHVrwD6WO+Xmmdykab0awL9To0S9DG9ohcXuJiTMa8vtXFSBM0koUDk +BWajEq+QAcDpmdFsQr4/gbzvHkAIVTQb0seJr4gpmXFZu3TMuGVD9j13GaI= +=38ri +-----END PGP PRIVATE KEY BLOCK----- diff --git a/lang/python/tests/final.py b/lang/python/tests/final.py new file mode 100755 index 0000000..8e7ab33 --- /dev/null +++ b/lang/python/tests/final.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +import subprocess + +subprocess.check_call([os.path.join(os.getenv('top_srcdir'), + "tests", "start-stop-agent"), "--stop"]) diff --git a/lang/python/tests/initial.py b/lang/python/tests/initial.py new file mode 100755 index 0000000..2d4827a --- /dev/null +++ b/lang/python/tests/initial.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +import subprocess +import pyme +import support +support.init_gpgme(pyme.constants.PROTOCOL_OpenPGP) + +subprocess.check_call([os.path.join(os.getenv('top_srcdir'), + "tests", "start-stop-agent"), "--start"]) + +with pyme.Context() as c: + alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False) + bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False) + + # Mark alpha as trusted. The signature verification tests expect + # this. + support.mark_key_trusted(c, alpha) + + c.op_import(open(support.in_srcdir("encrypt-only.asc"))) + c.op_import(open(support.in_srcdir("sign-only.asc"))) diff --git a/lang/python/tests/run-tests.py b/lang/python/tests/run-tests.py new file mode 100644 index 0000000..55d3f11 --- /dev/null +++ b/lang/python/tests/run-tests.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import argparse +import glob +import os +import subprocess +import sys + +class SplitAndAccumulate(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + current = getattr(namespace, self.dest, list()) + current.extend(values.split()) + setattr(namespace, self.dest, current) + +parser = argparse.ArgumentParser(description='Run tests.') +parser.add_argument('tests', metavar='TEST', type=str, nargs='+', + help='A test to run') +parser.add_argument('-v', '--verbose', action="store_true", default=False, + help='Be verbose.') +parser.add_argument('--interpreters', metavar='PYTHON', type=str, + default=[], action=SplitAndAccumulate, + help='Use these interpreters to run the tests, ' + + 'separated by spaces.') +parser.add_argument('--srcdir', type=str, + default=os.environ.get("srcdir", ""), + help='Location of the tests.') +parser.add_argument('--builddir', type=str, + default=os.environ.get("abs_builddir", ""), + help='Location of the tests.') + +args = parser.parse_args() +if not args.interpreters: + args.interpreters = [sys.executable] + +out = sys.stdout if args.verbose else None +err = sys.stderr if args.verbose else None + +def status_to_str(code): + return {0: "PASS", 77: "SKIP", 99: "ERROR"}.get(code, "FAIL") + +results = list() +for interpreter in args.interpreters: + version = subprocess.check_output( + [interpreter, "-c", "import sys; print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))"]).strip().decode() + + builddirs = glob.glob(os.path.join(args.builddir, "..", "build", + "lib*"+version)) + assert len(builddirs) == 1, \ + "Expected one build directory, got {0}".format(builddirs) + env = dict(os.environ) + env["PYTHONPATH"] = builddirs[0] + + print("Running tests using {0} ({1})...".format(interpreter, version)) + for test in args.tests: + status = subprocess.call( + [interpreter, os.path.join(args.srcdir, test)], + env=env, stdout=out, stderr=err) + print("{0}: {1}".format(status_to_str(status), test)) + results.append(status) + +def count(status): + return len(list(filter(lambda x: x == status, results))) +def failed(): + return len(list(filter(lambda x: x not in (0, 77, 99), results))) + +print("{0} tests run, {1} succeeded, {2} failed, {3} skipped.".format( + len(results), count(0), failed(), count(77))) +sys.exit(len(results) - count(0)) diff --git a/lang/python/tests/sign-only.asc b/lang/python/tests/sign-only.asc new file mode 100644 index 0000000..6e2a6f3 --- /dev/null +++ b/lang/python/tests/sign-only.asc @@ -0,0 +1,33 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- +Version: GnuPG v2 + +lQPFBFd/jO8BCADiull4EVJiKmJqclPyU6GhTlbJXw7Ch0zbFAauOWYT3ACmgr1U +KfJlZ2sPe2EezZkVSACxgIjTCzcgKQLh/swXdhO8uEgWEIN8f07WcSVDrcRGYwDS +KFSRsK0bfO/OQQDUsSkNQSHjcOdLnCHCinMrQi1mBZOs+Y/DXOkkEV1zbFFV7q6X +4vX9HSWwTRQTdOV9CFZykbwM+X1YIZlVtpOAKqSNJi3P17uQF7P9zko6HWKKKQ5S +96BfXUOIpBRl82R85/yQgeGrWlvZ2BT2ittscNQlBKqLHJ7LIeDr9ctbKlKZjHTn +Da7NYg+PoMHspbizjSONbEzpcR/9ZUq16oJJABEBAAH+BwMC7hQZNJSmlX/W6sfL +0wakX6kTsiCEMy2vMCRcZ769JKT234avHtkL/g7MBJEzqdG9HSEp7+LHGuOWJhfa +20f61WvPT5ujUIy//QXJ9a8z877jCm+fHKCTDXGYLLfCkJLfr3/GfTRy6gaIGTSw +BqZaRelPvHbMp+eiFqDkf8W/E1LO3/83k87+pXggjz4p0OasyMw8RcDmy+IKBMGG +bzet5WIKHIhpblIzuuucQHOjtwA8vCedub3F4lcRuULe2GW6sNuCB9kjSC9g6D1d +bJ+WYi5GiUUQARGSNXiWVoVPLpEo0i6/2bKJ7vBYGRewNp42ebVQU2bFW7uzhaIq +4itzNTjFNTpcxX3Lo0/mzJpe7pVRJwN+HGahNGT0EtPDsT/nNTFDUq8e8nt0U9/8 +0eekg4MRBJEzE3A+wosIHPjzCkQgu98+nh79rPMbCpZVxNfLb136cTkubmHCWptN +T2MbqK2L4hMcOxHGGOmI9SjFltNeKtTsVtkxh3Vj67UESPdN550centfasJYA0bj +guRQfHWHJXYIfFwblIFkl8xtIVLTeWlQMEvc7oI8jcJOc2ri8Zdjj/55xxv/RvjC +ZKzfjPpdkLYcN1zP/hETLD68u7WmiMAYCr8Eq9YQ3oKklUpWxRMCAAtmgjGGpm5P +QQW+36s96Q3cuG8R0Z4Wo8y89FgWzCEzuAhemCdffoUA8kn0HJQaVndnExJb1Ebz +wp+zsX/JqiOFvcKHJAWCaXkk0oXVi1aIV4tQyCPfhyjnd846K7g8UabAz51IJHvF +CXRAmqJvu26NqjYOfWBJJxZQsPH4FjPfYx+e/MFPZa+UTKCfzaOHClrePHUDHw58 +Ez5ItcORYn51IWW33r+c4tlhW5mrjMD7FcjFOuYT4EIivd5BSnwLP0fjBz8TBVAY +yyFO+YAXTQ+0MVNpZ24gT25seSAodGVzdCBrZXksIGRvIG5vdCB1c2UpIDxzb0Bl +eGFtcGxlLm9yZz6JATcEEwEIACEFAld/jO8CGwMFCwkIBwIGFQgJCgsCBBYCAwEC +HgECF4AACgkQ/tFT8S8Y9F3PAwgAvKav6+luvcAhrpBMO4z/Q8kDMtO5AW1KTEcz +neqpj5eTVJVbYUgDuBlEXbFYtcZmYyYtJC5KQkN3bxPmehVUzGk27UYWMWbPIWyU +riGcFL5BWWQaKSqiWUypzhNVnxYoiWVhHeJ36LICVMpLBaubgcpwCSW/j58yZo/7 +XRwf40OblXr4cevIW4Oq5GSxKOQF+DCErF6BeikC2i+NoqSxwNiIO/1NUxs8QfAI +z8UT/bSUXr62BWLfeCIDGgXutMMPth3tKi4DlvLCzI6eYJrd8E3Rt7iUZm9IH8OQ +Djv2DKnL/E/AP8oITItrOmICqfEWcj+Tk2Xep4pCCMNU+Pa0yg== +=gG5b +-----END PGP PRIVATE KEY BLOCK----- diff --git a/lang/python/tests/support.py b/lang/python/tests/support.py new file mode 100644 index 0000000..4d7135e --- /dev/null +++ b/lang/python/tests/support.py @@ -0,0 +1,69 @@ +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import os +from pyme import core + +# known keys +alpha = "A0FF4590BB6122EDEF6E3C542D727CC768697734" +bob = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2" +encrypt_only = "F52770D5C4DB41408D918C9F920572769B9FE19C" +sign_only = "7CCA20CCDE5394CEE71C9F0BFED153F12F18F45D" + +def make_filename(name): + return os.path.join(os.environ['top_srcdir'], 'tests', 'gpg', name) + +def in_srcdir(name): + return os.path.join(os.environ['srcdir'], name) + +def init_gpgme(proto): + core.engine_check_version(proto) + +verbose = int(os.environ.get('verbose', 0)) > 1 +def print_data(data): + if verbose: + try: + # See if it is a file-like object. + data.seek(0, os.SEEK_SET) + data = data.read() + except: + # Hope for the best. + pass + sys.stdout.buffer.write(data) + +def mark_key_trusted(ctx, key): + class Editor(object): + def __init__(self): + self.steps = ["trust", "save"] + def edit(self, status, args, out): + if args == "keyedit.prompt": + result = self.steps.pop(0) + elif args == "edit_ownertrust.value": + result = "5" + elif args == "edit_ownertrust.set_ultimate.okay": + result = "Y" + elif args == "keyedit.save.okay": + result = "Y" + else: + result = None + return result + with core.Data() as sink: + ctx.op_edit(key, Editor().edit, sink, sink) diff --git a/lang/python/tests/t-callbacks.py b/lang/python/tests/t-callbacks.py new file mode 100755 index 0000000..b3b4349 --- /dev/null +++ b/lang/python/tests/t-callbacks.py @@ -0,0 +1,257 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) + +c = core.Context() +c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) + +source = core.Data("Hallo Leute\n") +sink = core.Data() + +# Valid passphrases, both as string and bytes. +for passphrase in ('foo', b'foo'): + def passphrase_cb(hint, desc, prev_bad, hook=None): + assert hook == passphrase + return hook + + c.set_passphrase_cb(passphrase_cb, passphrase) + c.op_encrypt([], 0, source, sink) + +# Returning an invalid type. +def passphrase_cb(hint, desc, prev_bad, hook=None): + return 0 + +c.set_passphrase_cb(passphrase_cb, None) +try: + c.op_encrypt([], 0, source, sink) +except Exception as e: + assert type(e) == TypeError + assert str(e) == "expected str or bytes from passphrase callback, got int" +else: + assert False, "Expected an error, got none" + +# Raising an exception inside callback. +myException = Exception() +def passphrase_cb(hint, desc, prev_bad, hook=None): + raise myException + +c.set_passphrase_cb(passphrase_cb, None) +try: + c.op_encrypt([], 0, source, sink) +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + +# Wrong kind of callback function. +def bad_passphrase_cb(): + pass + +c.set_passphrase_cb(bad_passphrase_cb, None) +try: + c.op_encrypt([], 0, source, sink) +except Exception as e: + assert type(e) == TypeError +else: + assert False, "Expected an error, got none" + + + +# Test the progress callback. +parms = """<GnupgKeyParms format="internal"> +Key-Type: RSA +Key-Length: 1024 +Name-Real: Joe Tester +Name-Comment: with stupid passphrase +Name-Email: joe+pyme@example.org +Passphrase: Crypt0R0cks +Expire-Date: 2020-12-31 +</GnupgKeyParms> +""" + +messages = [] +def progress_cb(what, typ, current, total, hook=None): + assert hook == messages + messages.append( + "PROGRESS UPDATE: what = {}, type = {}, current = {}, total = {}" + .format(what, typ, current, total)) + +c = core.Context() +c.set_progress_cb(progress_cb, messages) +c.op_genkey(parms, None, None) +assert len(messages) > 0 + +# Test exception handling. +def progress_cb(what, typ, current, total, hook=None): + raise myException + +c = core.Context() +c.set_progress_cb(progress_cb, None) +try: + c.op_genkey(parms, None, None) +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + + +# Test the edit callback. +c = core.Context() +c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) +c.set_passphrase_cb(lambda *args: "abc") +sink = core.Data() +alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False) + +cookie = object() +edit_cb_called = False +def edit_cb(status, args, hook): + global edit_cb_called + edit_cb_called = True + assert hook == cookie + return "quit" if args == "keyedit.prompt" else None +c.op_edit(alpha, edit_cb, cookie, sink) +assert edit_cb_called + +# Test exceptions. +c = core.Context() +c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) +c.set_passphrase_cb(lambda *args: "abc") +sink = core.Data() + +def edit_cb(status, args): + raise myException +try: + c.op_edit(alpha, edit_cb, None, sink) +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + + + +# Test the status callback. +source = core.Data("Hallo Leute\n") +sink = core.Data() + +status_cb_called = False +def status_cb(keyword, args, hook=None): + global status_cb_called + status_cb_called = True + assert hook == cookie + +c = core.Context() +c.set_status_cb(status_cb, cookie) +c.set_ctx_flag("full-status", "1") +c.op_encrypt([alpha], constants.ENCRYPT_ALWAYS_TRUST, source, sink) +assert status_cb_called + +# Test exceptions. +source = core.Data("Hallo Leute\n") +sink = core.Data() + +def status_cb(keyword, args): + raise myException + +c = core.Context() +c.set_status_cb(status_cb, None) +c.set_ctx_flag("full-status", "1") +try: + c.op_encrypt([alpha], constants.ENCRYPT_ALWAYS_TRUST, source, sink) +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + + + +# Test the data callbacks. +def read_cb(amount, hook=None): + assert hook == cookie + return 0 +def release_cb(hook=None): + assert hook == cookie +data = core.Data(cbs=(read_cb, None, None, release_cb, cookie)) +try: + data.read() +except Exception as e: + assert type(e) == TypeError +else: + assert False, "Expected an error, got none" + +def read_cb(amount): + raise myException +data = core.Data(cbs=(read_cb, None, None, lambda: None)) +try: + data.read() +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + + +def write_cb(what, hook=None): + assert hook == cookie + return "wrong type" +data = core.Data(cbs=(None, write_cb, None, release_cb, cookie)) +try: + data.write(b'stuff') +except Exception as e: + assert type(e) == TypeError +else: + assert False, "Expected an error, got none" + +def write_cb(what): + raise myException +data = core.Data(cbs=(None, write_cb, None, lambda: None)) +try: + data.write(b'stuff') +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" + + +def seek_cb(offset, whence, hook=None): + assert hook == cookie + return "wrong type" +data = core.Data(cbs=(None, None, seek_cb, release_cb, cookie)) +try: + data.seek(0, os.SEEK_SET) +except Exception as e: + assert type(e) == TypeError +else: + assert False, "Expected an error, got none" + +def seek_cb(offset, whence): + raise myException +data = core.Data(cbs=(None, None, seek_cb, lambda: None)) +try: + data.seek(0, os.SEEK_SET) +except Exception as e: + assert e == myException +else: + assert False, "Expected an error, got none" diff --git a/lang/python/tests/t-data.py b/lang/python/tests/t-data.py new file mode 100755 index 0000000..4812a2e --- /dev/null +++ b/lang/python/tests/t-data.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import io +import os +import tempfile +from pyme import core + +data = core.Data('Hello world!') +assert data.read() == b'Hello world!' +assert data.read() == b'' + +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' +assert data.read() == b'' + +data = core.Data(b'Hello world!') +assert data.read() == b'Hello world!' + +data = core.Data(b'Hello world!', copy=False) +assert data.read() == b'Hello world!' + +data = core.Data() +data.write('Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' + +data = core.Data() +data.write(b'Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' + +binjunk = bytes(range(256)) +data = core.Data() +data.write(binjunk) +data.seek(0, os.SEEK_SET) +assert data.read() == binjunk + +data = core.Data() +data.set_file_name("foobar") +assert data.get_file_name() == "foobar" + +# Test reading from an existing file. +with tempfile.NamedTemporaryFile() as tmp: + tmp.write(binjunk) + tmp.flush() + tmp.seek(0) + + # Open using name. + data = core.Data(file=tmp.name) + assert data.read() == binjunk + + # Open using name, without copying. + if False: + # delayed reads are not yet supported + data = core.Data(file=tmp.name, copy=False) + assert data.read() == binjunk + + # Open using stream. + tmp.seek(0) + data = core.Data(file=tmp) + assert data.read() == binjunk + + # Open using stream, offset, and length. + data = core.Data(file=tmp, offset=0, length=42) + assert data.read() == binjunk[:42] + + # Open using name, offset, and length. + data = core.Data(file=tmp.name, offset=23, length=42) + assert data.read() == binjunk[23:23+42] + +# Test callbacks. +class DataObject(object): + def __init__(self): + self.buffer = io.BytesIO() + self.released = False + + def read(self, amount, hook=None): + assert not self.released + return self.buffer.read(amount) + + def write(self, data, hook=None): + assert not self.released + return self.buffer.write(data) + + def seek(self, offset, whence, hook=None): + assert not self.released + return self.buffer.seek(offset, whence) + + def release(self, hook=None): + assert not self.released + self.released = True + +do = DataObject() +cookie = object() +data = core.Data(cbs=(do.read, do.write, do.seek, do.release, cookie)) +data.write('Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' +del data +assert do.released + +# Again, without the cookie. +do = DataObject() +data = core.Data(cbs=(do.read, do.write, do.seek, do.release)) +data.write('Hello world!') +data.seek(0, os.SEEK_SET) +assert data.read() == b'Hello world!' +del data +assert do.released diff --git a/lang/python/tests/t-decrypt-verify.py b/lang/python/tests/t-decrypt-verify.py new file mode 100755 index 0000000..a38a965 --- /dev/null +++ b/lang/python/tests/t-decrypt-verify.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme +from pyme import core, constants, errors +import support + +def check_verify_result(result, summary, fpr, status): + assert len(result.signatures) == 1, "Unexpected number of signatures" + sig = result.signatures[0] + assert sig.summary == summary, "Unexpected signature summary" + assert sig.fpr == fpr + assert errors.GPGMEError(sig.status).getcode() == status + assert len(sig.notations) == 0 + assert not sig.wrong_key_usage + assert sig.validity == constants.VALIDITY_FULL + assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +source = core.Data(file=support.make_filename("cipher-2.asc")) +sink = core.Data() + +c.op_decrypt_verify(source, sink) +result = c.op_decrypt_result() +assert not result.unsupported_algorithm, \ + "Unsupported algorithm: {}".format(result.unsupported_algorithm) + +support.print_data(sink) + +verify_result = c.op_verify_result() +check_verify_result(verify_result, + constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR) + +# Idiomatic interface. +with pyme.Context() as c: + alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False) + bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False) + plaintext, _, verify_result = \ + c.decrypt(open(support.make_filename("cipher-2.asc")), verify=[alpha]) + assert plaintext.find(b'Wenn Sie dies lesen k') >= 0, \ + 'Plaintext not found' + check_verify_result(verify_result, + constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR) + + try: + c.decrypt(open(support.make_filename("cipher-2.asc")), + verify=[alpha, bob]) + except errors.MissingSignatures as e: + assert len(e.missing) == 1 + assert e.missing[0] == bob + else: + assert False, "Expected an error, got none" diff --git a/lang/python/tests/t-decrypt.py b/lang/python/tests/t-decrypt.py new file mode 100755 index 0000000..2d85bc2 --- /dev/null +++ b/lang/python/tests/t-decrypt.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +source = core.Data(file=support.make_filename("cipher-1.asc")) +sink = core.Data() + +c.op_decrypt(source, sink) +result = c.op_decrypt_result() +assert not result.unsupported_algorithm, \ + "Unsupported algorithm: {}".format(result.unsupported_algorithm) + +support.print_data(sink) + +# Idiomatic interface. +with pyme.Context() as c: + plaintext, _, _ = c.decrypt(open(support.make_filename("cipher-1.asc"))) + assert len(plaintext) > 0 + assert plaintext.find(b'Wenn Sie dies lesen k') >= 0, \ + 'Plaintext not found' diff --git a/lang/python/tests/t-edit.py b/lang/python/tests/t-edit.py new file mode 100755 index 0000000..18bcb94 --- /dev/null +++ b/lang/python/tests/t-edit.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net> +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import os +from pyme import core, constants +import support + +class KeyEditor(object): + def __init__(self): + self.steps = ["fpr", "expire", "1", "primary", "quit"] + self.step = 0 + self.done = False + self.verbose = int(os.environ.get('verbose', 0)) > 1 + + def edit_fnc(self, status, args, out=None): + if args == "keyedit.prompt": + result = self.steps[self.step] + self.step += 1 + elif args == "keyedit.save.okay": + result = "Y" + self.done = self.step == len(self.steps) + elif args == "keygen.valid": + result = "0" + else: + result = None + + if self.verbose: + sys.stderr.write("Code: {}, args: {!r}, Returning: {!r}\n" + .format(status, args, result)) + + return result + +support.init_gpgme(constants.PROTOCOL_OpenPGP) + +c = core.Context() +c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) +c.set_passphrase_cb(lambda *args: "abc") +c.set_armor(True) + +# The deprecated interface. +editor = KeyEditor() +c.interact(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False), + editor.edit_fnc) +assert editor.done + +# The deprecated interface. +sink = core.Data() +editor = KeyEditor() +c.op_edit(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False), + editor.edit_fnc, sink, sink) +assert editor.done diff --git a/lang/python/tests/t-encrypt-large.py b/lang/python/tests/t-encrypt-large.py new file mode 100755 index 0000000..b9cc3b5 --- /dev/null +++ b/lang/python/tests/t-encrypt-large.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import random +from pyme import core, constants +import support + +if len(sys.argv) == 2: + nbytes = int(sys.argv[1]) +else: + nbytes = 100000 + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +ntoread = nbytes +def read_cb(amount): + global ntoread + chunk = ntoread if ntoread < amount else amount + ntoread -= chunk + assert ntoread >= 0 + assert chunk >= 0 + return bytes(bytearray(random.randrange(256) for i in range(chunk))) + +nwritten = 0 +def write_cb(data): + global nwritten + nwritten += len(data) + return len(data) + +source = core.Data(cbs=(read_cb, None, None, lambda: None)) +sink = core.Data(cbs=(None, write_cb, None, lambda: None)) + +keys = [] +keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)) +keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)) + +c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, sink) +result = c.op_encrypt_result() +assert not result.invalid_recipients, \ + "Invalid recipient encountered: {}".format(result.invalid_recipients.fpr) +assert ntoread == 0 + +if support.verbose: + sys.stderr.write( + "plaintext={} bytes, ciphertext={} bytes\n".format(nbytes, nwritten)) diff --git a/lang/python/tests/t-encrypt-sign.py b/lang/python/tests/t-encrypt-sign.py new file mode 100755 index 0000000..a453f79 --- /dev/null +++ b/lang/python/tests/t-encrypt-sign.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import pyme +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +def check_result(r, typ): + if r.invalid_signers: + sys.exit("Invalid signer found: {}".format(r.invalid_signers.fpr)) + + if len(r.signatures) != 1: + sys.exit("Unexpected number of signatures created") + + signature = r.signatures[0] + if signature.type != typ: + sys.exit("Wrong type of signature created") + + if signature.pubkey_algo != constants.PK_DSA: + sys.exit("Wrong pubkey algorithm reported: {}".format( + signature.pubkey_algo)) + + if signature.hash_algo not in (constants.MD_SHA1, constants.MD_RMD160): + sys.exit("Wrong hash algorithm reported: {}".format( + signature.hash_algo)) + + if signature.sig_class != 0: + sys.exit("Wrong signature class reported: {}".format( + signature.sig_class)) + + if signature.fpr != "A0FF4590BB6122EDEF6E3C542D727CC768697734": + sys.exit("Wrong fingerprint reported: {}".format(signature.fpr)) + +keys = [] +keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)) +keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)) + +for recipients in (keys, []): + source = core.Data("Hallo Leute\n") + sink = core.Data() + + c.op_encrypt_sign(recipients, constants.ENCRYPT_ALWAYS_TRUST, source, sink) + result = c.op_encrypt_result() + assert not result.invalid_recipients, \ + "Invalid recipient encountered: {}".format( + result.invalid_recipients.fpr) + + result = c.op_sign_result() + check_result(result, constants.SIG_MODE_NORMAL) + + support.print_data(sink) + + +# Idiomatic interface. +with pyme.Context(armor=True) as c: + message = "Hallo Leute\n".encode() + ciphertext, _, sig_result = c.encrypt(message, + recipients=keys, + always_trust=True) + assert len(ciphertext) > 0 + assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found' + check_result(sig_result, constants.SIG_MODE_NORMAL) + + c.signers = [c.get_key(support.sign_only, True)] + c.encrypt(message, recipients=keys, always_trust=True) + + c.signers = [c.get_key(support.encrypt_only, True)] + try: + c.encrypt(message, recipients=keys, always_trust=True) + except pyme.errors.InvalidSigners as e: + assert len(e.signers) == 1 + assert support.encrypt_only.endswith(e.signers[0].fpr) + else: + assert False, "Expected an InvalidSigners error, got none" diff --git a/lang/python/tests/t-encrypt-sym.py b/lang/python/tests/t-encrypt-sym.py new file mode 100755 index 0000000..d577184 --- /dev/null +++ b/lang/python/tests/t-encrypt-sym.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +import pyme +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) + +for passphrase in ("abc", b"abc"): + c = core.Context() + c.set_armor(True) + c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) + + source = core.Data("Hallo Leute\n") + cipher = core.Data() + + passphrase_cb_called = 0 + def passphrase_cb(hint, desc, prev_bad, hook=None): + global passphrase_cb_called + passphrase_cb_called += 1 + return passphrase + + c.set_passphrase_cb(passphrase_cb, None) + + c.op_encrypt([], 0, source, cipher) + assert passphrase_cb_called == 1, \ + "Callback called {} times".format(passphrase_cb_called) + support.print_data(cipher) + + c = core.Context() + c.set_armor(True) + c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK) + c.set_passphrase_cb(passphrase_cb, None) + plain = core.Data() + cipher.seek(0, os.SEEK_SET) + + c.op_decrypt(cipher, plain) + # Seems like the passphrase is cached. + #assert passphrase_cb_called == 2, \ + # "Callback called {} times".format(passphrase_cb_called) + support.print_data(plain) + + plain.seek(0, os.SEEK_SET) + plaintext = plain.read() + assert plaintext == b"Hallo Leute\n", \ + "Wrong plaintext {!r}".format(plaintext) + +# Idiomatic interface. +for passphrase in ("abc", b"abc"): + with pyme.Context(armor=True) as c: + # Check that the passphrase callback is not altered. + def f(*args): + assert False + c.set_passphrase_cb(f) + + message = "Hallo Leute\n".encode() + ciphertext, _, _ = c.encrypt(message, + passphrase=passphrase, + sign=False) + assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found' + + plaintext, _, _ = c.decrypt(ciphertext, passphrase=passphrase) + assert plaintext == message, 'Message body not recovered' + + assert c._passphrase_cb[1] == f, "Passphrase callback not restored" diff --git a/lang/python/tests/t-encrypt.py b/lang/python/tests/t-encrypt.py new file mode 100755 index 0000000..65e7d24 --- /dev/null +++ b/lang/python/tests/t-encrypt.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +source = core.Data("Hallo Leute\n") +sink = core.Data() + +keys = [] +keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)) +keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)) + +c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, sink) +result = c.op_encrypt_result() +assert not result.invalid_recipients, \ + "Invalid recipients: {}".format(", ".join(r.fpr for r in result.recipients)) +support.print_data(sink) + +# Idiomatic interface. +with pyme.Context(armor=True) as c: + ciphertext, _, _ = c.encrypt("Hallo Leute\n".encode(), + recipients=keys, + sign=False, + always_trust=True) + assert len(ciphertext) > 0 + assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found' + + c.encrypt("Hallo Leute\n".encode(), + recipients=[c.get_key(support.encrypt_only, False)], + sign=False, always_trust=True) + + try: + c.encrypt("Hallo Leute\n".encode(), + recipients=[c.get_key(support.sign_only, False)], + sign=False, always_trust=True) + except pyme.errors.InvalidRecipients as e: + assert len(e.recipients) == 1 + assert support.sign_only.endswith(e.recipients[0].fpr) + else: + assert False, "Expected an InvalidRecipients error, got none" diff --git a/lang/python/tests/t-export.py b/lang/python/tests/t-export.py new file mode 100755 index 0000000..db36b98 --- /dev/null +++ b/lang/python/tests/t-export.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +sink = core.Data() +c.op_export_ext(['Alpha', 'Bob'], 0, sink) +support.print_data(sink) + +# Again. Now using a key array. +keys = [] +keys.append(c.get_key("0x68697734", False)) # Alpha +keys.append(c.get_key("0xA9E3B0B2", False)) # Bob +sink = core.Data() +c.op_export_keys(keys, 0, sink) +support.print_data(sink) diff --git a/lang/python/tests/t-file-name.py b/lang/python/tests/t-file-name.py new file mode 100755 index 0000000..e93b120 --- /dev/null +++ b/lang/python/tests/t-file-name.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +from pyme import core, constants +import support + +testname = "abcde12345" + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +source = core.Data("Hallo Leute\n") +source.set_file_name(testname) +cipher = core.Data() +plain = core.Data() + +keys = [] +keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)) + +c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, cipher) +cipher.seek(0, os.SEEK_SET) +c.op_decrypt(cipher, plain) +result = c.op_decrypt_result() +assert result.file_name == testname diff --git a/lang/python/tests/t-idiomatic.py b/lang/python/tests/t-idiomatic.py new file mode 100755 index 0000000..f063206 --- /dev/null +++ b/lang/python/tests/t-idiomatic.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import io +import os +import tempfile +import pyme +import support + +support.init_gpgme(pyme.constants.PROTOCOL_OpenPGP) + +# Both Context and Data can be used as context manager: +with pyme.Context() as c, pyme.Data() as d: + c.get_engine_info() + d.write(b"Halloechen") + leak_c = c + leak_d = d +assert leak_c.wrapped == None +assert leak_d.wrapped == None + +def sign_and_verify(source, signed, sink): + with pyme.Context() as c: + c.op_sign(source, signed, pyme.constants.SIG_MODE_NORMAL) + signed.seek(0, os.SEEK_SET) + c.op_verify(signed, None, sink) + result = c.op_verify_result() + + assert len(result.signatures) == 1, "Unexpected number of signatures" + sig = result.signatures[0] + assert sig.summary == (pyme.constants.SIGSUM_VALID | + pyme.constants.SIGSUM_GREEN) + assert pyme.errors.GPGMEError(sig.status).getcode() == pyme.errors.NO_ERROR + + sink.seek(0, os.SEEK_SET) + assert sink.read() == b"Hallo Leute\n" + +# Demonstrate automatic wrapping of file-like objects with 'fileno' +# method. +with tempfile.TemporaryFile() as source, \ + tempfile.TemporaryFile() as signed, \ + tempfile.TemporaryFile() as sink: + source.write(b"Hallo Leute\n") + source.seek(0, os.SEEK_SET) + + sign_and_verify(source, signed, sink) + +if sys.version_info[0] == 3: + # Python2's io.BytesIO does not implement the buffer interface, + # hence we cannot use it as sink. + + # XXX: Python's io.BytesIo.truncate does not work as advertised. + # http://bugs.python.org/issue27261 + bio = io.BytesIO() + bio.truncate(1) + if len(bio.getvalue()) != 1: + # This version of Python is affected, preallocate buffer. + preallocate = 128*b'\x00' + else: + preallocate = b'' + + # Demonstrate automatic wrapping of objects implementing the buffer + # interface, and the use of data objects with the 'with' statement. + with io.BytesIO(preallocate) as signed, pyme.Data() as sink: + sign_and_verify(b"Hallo Leute\n", signed, sink) diff --git a/lang/python/tests/t-import.py b/lang/python/tests/t-import.py new file mode 100755 index 0000000..0b50d02 --- /dev/null +++ b/lang/python/tests/t-import.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import core, constants +import support + +def check_result(result, fpr, secret): + assert result.considered == 1 or (secret and result.considered == 3) + assert result.no_user_id == 0 + assert not ((secret and result.imported != 0) + or (not secret and (result.imported != 0 + and result.imported != 1))) + assert result.imported_rsa == 0 + assert not ((secret and (result.unchanged != 0 and result.unchanged != 1)) + or (not secret and ((result.imported == 0 + and result.unchanged != 1) + or (result.imported == 1 + and result.unchanged != 0)))) + assert result.new_user_ids == 0 + assert result.new_sub_keys == 0 + assert not ((secret + and ((result.secret_imported == 0 + and result.new_signatures != 0) + or (result.secret_imported == 1 + and result.new_signatures > 1))) + or (not secret and result.new_signatures != 0)) + assert result.new_revocations == 0 + assert not ((secret and result.secret_read != 1 and result.secret_read != 3) + or (not secret and result.secret_read != 0)) + assert not ((secret and result.secret_imported != 0 + and result.secret_imported != 1 + and result.secret_imported != 2) + or (not secret and result.secret_imported != 0)) + assert not ((secret + and ((result.secret_imported == 0 + and result.secret_unchanged != 1 + and result.secret_unchanged != 2) + or (result.secret_imported == 1 + and result.secret_unchanged != 0))) + or (not secret and result.secret_unchanged != 0)) + assert result.not_imported == 0 + if secret: + assert not (len(result.imports) in (0, 3)) + else: + assert not (len(result.imports) in (0, 2)) + + assert fpr == result.imports[0].fpr + assert len(result.imports) == 1 or fpr == result.imports[1].fpr + assert result.imports[0].result == 0 + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +c.op_import(core.Data(file=support.make_filename("pubkey-1.asc"))) +result = c.op_import_result() +check_result(result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", False) + +c.op_import(core.Data(file=support.make_filename("seckey-1.asc"))) +result = c.op_import_result() +check_result(result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", True) diff --git a/lang/python/tests/t-keylist.py b/lang/python/tests/t-keylist.py new file mode 100755 index 0000000..5e8b333 --- /dev/null +++ b/lang/python/tests/t-keylist.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +# Check expration of keys. This test assumes three subkeys of which +# 2 are expired; it is used with the "Whisky" test key. It has +# already been checked that these 3 subkeys are available. +def check_whisky(name, key): + sub1 = key.subkeys[2] + sub2 = key.subkeys[3] + + assert sub1.expired and sub2.expired, \ + "Subkey of `{}' not flagged as expired".format(name) + assert sub1.expires == 1129636886 and sub2.expires == 1129636939, \ + "Subkey of `{}' has wrong expiration date".format(name) + +keys = [ + [ "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8", + [ [ "Alfa Test", "demo key", "alfa@example.net" ], + [ "Alpha Test", "demo key", "alpha@example.net" ], + [ "Alice", "demo key", "" ] ], 1 ], + [ "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F", + [ [ "Bob", "demo key", "" ], + [ "Bravo Test", "demo key", "bravo@example.net" ] ], 1 ], + [ "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60", + [ [ "Charlie Test", "demo key", "charlie@example.net" ] ], 1 ], + [ "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424", + [ [ "Delta Test", "demo key", "delta@example.net" ] ], 1 ], + [ "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D", + [ [ "Echelon", "demo key", "" ], + [ "Echo Test", "demo key", "echo@example.net" ], + [ "Eve", "demo key", "" ] ], 1 ], + [ "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E", + [ [ "Foxtrot Test", "demo key", "foxtrot@example.net" ] ], 1 ], + [ "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354", + [ [ "Golf Test", "demo key", "golf@example.net" ] ], 1 ], + [ "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A", + [ [ "Hotel Test", "demo key", "hotel@example.net" ] ], 1 ], + [ "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73", + [ [ "India Test", "demo key", "india@example.net" ] ], 1 ], + [ "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136", + [ [ "Juliet Test", "demo key", "juliet@example.net" ] ], 1 ], + [ "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02", + [ [ "Kilo Test", "demo key", "kilo@example.net" ] ], 1 ], + [ "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C", + [ [ "Lima Test", "demo key", "lima@example.net" ] ], 1 ], + [ "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8", + [ [ "Mallory", "demo key", "" ], + [ "Mike Test", "demo key", "mike@example.net" ] ], 1 ], + [ "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472", + [ [ "November Test", "demo key", "november@example.net" ] ], 1 ], + [ "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F", + [ [ "Oscar Test", "demo key", "oscar@example.net" ] ], 1 ], + [ "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C", + [ [ "Papa test", "demo key", "papa@example.net" ] ], 1 ], + [ "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4", + [ [ "Quebec Test", "demo key", "quebec@example.net" ] ], 1 ], + [ "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA", + [ [ "Romeo Test", "demo key", "romeo@example.net" ] ], 1 ], + [ "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4", + [ [ "Sierra Test", "demo key", "sierra@example.net" ] ], 1 ], + [ "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402", + [ [ "Tango Test", "demo key", "tango@example.net" ] ], 1 ], + [ "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9", + [ [ "Uniform Test", "demo key", "uniform@example.net" ] ], 1 ], + [ "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134", + [ [ "Victor Test", "demo key", "victor@example.org" ] ], 1 ], + [ "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6", + [ [ "Whisky Test", "demo key", "whisky@example.net" ] ], 3, + check_whisky ], + [ "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE", + [ [ "XRay Test", "demo key", "xray@example.net" ] ], 1 ], + [ "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD", + [ [ "Yankee Test", "demo key", "yankee@example.net" ] ], 1 ], + [ "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881", + [ [ "Zulu Test", "demo key", "zulu@example.net" ] ], 1 ], +] + +def check_global(key, uids, n_subkeys): + assert not key.revoked, "Key unexpectedly revoked" + assert not key.expired, "Key unexpectedly expired" + assert not key.disabled, "Key unexpectedly disabled" + assert not key.invalid, "Key unexpectedly invalid" + assert key.can_sign, "Key unexpectedly unusable for signing" + assert key.can_certify, "Key unexpectedly unusable for certifications" + assert not key.secret, "Key unexpectedly secret" + assert not key.protocol != constants.PROTOCOL_OpenPGP, \ + "Key has unexpected protocol: {}".format(key.protocol) + assert not key.issuer_serial, \ + "Key unexpectedly carries issuer serial: {}".format(key.issuer_serial) + assert not key.issuer_name, \ + "Key unexpectedly carries issuer name: {}".format(key.issuer_name) + assert not key.chain_id, \ + "Key unexpectedly carries chain ID: {}".format(key.chain_id) + + # Only key Alfa is trusted + assert key.uids[0].name == 'Alfa Test' \ + or key.owner_trust == constants.VALIDITY_UNKNOWN, \ + "Key has unexpected owner trust: {}".format(key.owner_trust) + assert key.uids[0].name != 'Alfa Test' \ + or key.owner_trust == constants.VALIDITY_ULTIMATE, \ + "Key has unexpected owner trust: {}".format(key.owner_trust) + + assert len(key.subkeys) - 1 == n_subkeys, \ + "Key `{}' has unexpected number of subkeys".format(uids[0][0]) + + +def check_subkey(fpr, which, subkey): + assert not subkey.revoked, which + " key unexpectedly revoked" + assert not subkey.expired, which + " key unexpectedly expired" + assert not subkey.disabled, which + " key unexpectedly disabled" + assert not subkey.invalid, which + " key unexpectedly invalid" + + if which == "Primary": + assert not subkey.can_encrypt, \ + which + " key unexpectedly usable for encryption" + assert subkey.can_sign, \ + which + " key unexpectedly unusable for signing" + assert subkey.can_certify, \ + which + " key unexpectedly unusable for certifications" + else: + assert subkey.can_encrypt, \ + which + " key unexpectedly unusable for encryption" + assert not subkey.can_sign, \ + which + " key unexpectedly usable for signing" + assert not subkey.can_certify, \ + which + " key unexpectedly usable for certifications" + + assert not subkey.secret, which + " key unexpectedly secret" + assert not subkey.is_cardkey, "Public key marked as card key" + assert not subkey.card_number, "Public key with card number set" + assert not subkey.pubkey_algo != (constants.PK_DSA if which == "Primary" + else constants.PK_ELG_E), \ + which + " key has unexpected public key algo: {}".\ + format(subkey.pubkey_algo) + assert subkey.length == 1024, \ + which + " key has unexpected length: {}".format(subkey.length) + assert fpr.endswith(subkey.keyid), \ + which + " key has unexpected key ID: {}".format(subkey.keyid) + assert which == "Secondary" or subkey.fpr == fpr, \ + which + " key has unexpected fingerprint: {}".format(subkey.fpr) + assert not subkey.expires, \ + which + " key unexpectedly expires: {}".format(subkey.expires) + +def check_uid(which, ref, uid): + assert not uid.revoked, which + " user ID unexpectedly revoked" + assert not uid.invalid, which + " user ID unexpectedly invalid" + assert uid.validity == (constants.VALIDITY_UNKNOWN + if uid.name.split()[0] + not in {'Alfa', 'Alpha', 'Alice'} else + constants.VALIDITY_ULTIMATE), \ + which + " user ID has unexpectedly validity: {}".format(uid.validity) + assert not uid.signatures, which + " user ID unexpectedly signed" + assert uid.name == ref[0], \ + "Unexpected name in {} user ID: {!r}".format(which.lower(), uid.name) + assert uid.comment == ref[1], \ + "Unexpected comment in {} user ID: {!r}".format(which.lower(), + uid.comment) + assert uid.email == ref[2], \ + "Unexpected email in {} user ID: {!r}".format(which.lower(), uid.email) + +i = 0 +c.op_keylist_start(None, False) +key = c.op_keylist_next () +while key: + try: + if len(keys[i]) == 4: + fpr, sec_keyid, uids, n_subkeys = keys[i] + misc_check = None + else: + fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i] + except IndexError: + # There are more keys. We don't check for that. + break + + # Global key flags. + check_global(key, uids, n_subkeys) + check_subkey(fpr, "Primary", key.subkeys[0]) + check_subkey(sec_keyid, "Secondary", key.subkeys[1]) + + assert len(key.uids) == len(uids) + check_uid("First", uids[0], key.uids[0]) + if len(key.uids) > 1: + check_uid("Second", uids[1], key.uids[1]) + if len(key.uids) > 2: + check_uid("Third", uids[2], key.uids[2]) + + if misc_check: + misc_check (uids[0][0], key) + key = c.op_keylist_next () + i += 1 + +c.op_keylist_end() +result = c.op_keylist_result() +assert not result.truncated, "Key listing unexpectedly truncated" + + +for i, key in enumerate(c.keylist()): + try: + if len(keys[i]) == 4: + fpr, sec_keyid, uids, n_subkeys = keys[i] + misc_check = None + else: + fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i] + except IndexError: + # There are more keys. We don't check for that. + break + + # Global key flags. + check_global(key, uids, n_subkeys) + check_subkey(fpr, "Primary", key.subkeys[0]) + check_subkey(sec_keyid, "Secondary", key.subkeys[1]) + + assert len(key.uids) == len(uids) + check_uid("First", uids[0], key.uids[0]) + if len(key.uids) > 1: + check_uid("Second", uids[1], key.uids[1]) + if len(key.uids) > 2: + check_uid("Third", uids[2], key.uids[2]) + + if misc_check: + misc_check (uids[0][0], key) diff --git a/lang/python/tests/t-protocol-assuan.py b/lang/python/tests/t-protocol-assuan.py new file mode 100755 index 0000000..172c7d0 --- /dev/null +++ b/lang/python/tests/t-protocol-assuan.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme + +with pyme.Context(protocol=pyme.constants.PROTOCOL_ASSUAN) as c: + # Do nothing. + c.assuan_transact('nop') + c.assuan_transact('NOP') + c.assuan_transact(['NOP']) + + err = c.assuan_transact('idontexist') + assert err.getsource() == pyme.errors.SOURCE_GPGAGENT + assert err.getcode() == pyme.errors.ASS_UNKNOWN_CMD + + # Invoke the pinentry to get a confirmation. + c.assuan_transact(['GET_CONFIRMATION', 'Hello there']) + + data = [] + def data_cb(line): + data.append(line) + + err = c.assuan_transact(['GETINFO', 'version'], data_cb=data_cb) + assert not err + assert len(data) == 1 + + data = [] + err = c.assuan_transact(['GETINFO', 's2k_count'], data_cb=data_cb) + if not err: + assert len(data) == 1 + assert int(data[0]) > 0 + + # XXX HELP sends status lines if we could use ASSUAN_CONVEY_COMMENTS. + + status = [] + def status_cb(line, args): + status.append((line, args)) + + alphas_grip = '76F7E2B35832976B50A27A282D9B87E44577EB66' + err = c.assuan_transact(['KEYINFO', alphas_grip], status_cb=status_cb) + if not err: + assert len(status) == 1 + line, args = status[0] + assert line.startswith('KEYINFO') + assert args.startswith(alphas_grip) + + # XXX: test these callbacks, e.g. using PRESET_PASSPHRASE + # XXX: once issue2428 is resolved + def inq_cb(name, args): + print("inq_cb", name, args) diff --git a/lang/python/tests/t-sig-notation.py b/lang/python/tests/t-sig-notation.py new file mode 100755 index 0000000..777bc0b --- /dev/null +++ b/lang/python/tests/t-sig-notation.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +from pyme import core, constants +import support + +expected_notations = { + "laughing@me": ("Just Squeeze Me", constants.SIG_NOTATION_HUMAN_READABLE), + "preferred-email-encoding@pgp.com": ("pgpmime", + constants.SIG_NOTATION_HUMAN_READABLE + | constants.SIG_NOTATION_CRITICAL), + None: ("http://www.gnu.org/policy/", 0), +} + +# GnuPG prior to 2.1.13 did not report the critical flag correctly. +with core.Context() as c: + version = c.engine_info.version + have_correct_sig_data = not (version.startswith("1.") + or version == "2.1.1" + or (version.startswith("2.1.1") + and version[5] < '3')) + +def check_result(result): + assert len(result.signatures) == 1, "Unexpected number of signatures" + sig = result.signatures[0] + assert len(sig.notations) == len(expected_notations) + + for r in sig.notations: + assert not 'name_len' in dir(r) + assert not 'value_len' in dir(r) + assert r.name in expected_notations + value, flags = expected_notations.pop(r.name) + + assert r.value == value, \ + "Expected {!r}, got {!r}".format(value, r.value) + assert r.human_readable \ + == bool(flags&constants.SIG_NOTATION_HUMAN_READABLE) + assert r.critical \ + == (bool(flags&constants.SIG_NOTATION_CRITICAL) + if have_correct_sig_data else False) + + assert len(expected_notations) == 0 + +support.init_gpgme(constants.PROTOCOL_OpenPGP) + +source = core.Data("Hallo Leute\n") +signed = core.Data() + +c = core.Context() +for name, (value, flags) in expected_notations.items(): + c.sig_notation_add(name, value, flags) + +c.op_sign(source, signed, constants.SIG_MODE_NORMAL) + +signed.seek(0, os.SEEK_SET) +sink = core.Data() +c.op_verify(signed, None, sink) +result = c.op_verify_result() +check_result(result) diff --git a/lang/python/tests/t-sign.py b/lang/python/tests/t-sign.py new file mode 100755 index 0000000..b0e211a --- /dev/null +++ b/lang/python/tests/t-sign.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import os +import pyme +from pyme import core, constants +import support + +def fail(msg): + raise RuntimeError(msg) + +def check_result(r, typ): + if r.invalid_signers: + fail("Invalid signer found: {}".format(r.invalid_signers.fpr)) + + if len(r.signatures) != 1: + fail("Unexpected number of signatures created") + + signature = r.signatures[0] + if signature.type != typ: + fail("Wrong type of signature created") + + if signature.pubkey_algo != constants.PK_DSA: + fail("Wrong pubkey algorithm reported: {}".format( + signature.pubkey_algo)) + + if signature.hash_algo != constants.MD_SHA1: + fail("Wrong hash algorithm reported: {}".format( + signature.hash_algo)) + + if signature.sig_class != 1: + fail("Wrong signature class reported: {}".format( + signature.sig_class)) + + if signature.fpr != "A0FF4590BB6122EDEF6E3C542D727CC768697734": + fail("Wrong fingerprint reported: {}".format(signature.fpr)) + + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_textmode(True) +c.set_armor(True) + +source = core.Data("Hallo Leute\n") +sink = core.Data() + +c.op_sign(source, sink, constants.SIG_MODE_NORMAL) + +result = c.op_sign_result() +check_result(result, constants.SIG_MODE_NORMAL) +support.print_data(sink) + +# Now a detached signature. +source.seek(0, os.SEEK_SET) +sink = core.Data() + +c.op_sign(source, sink, constants.SIG_MODE_DETACH) + +result = c.op_sign_result() +check_result(result, constants.SIG_MODE_DETACH) +support.print_data(sink) + +# And finally a cleartext signature. */ +source.seek(0, os.SEEK_SET) +sink = core.Data() + +c.op_sign(source, sink, constants.SIG_MODE_CLEAR) + +result = c.op_sign_result() +check_result(result, constants.SIG_MODE_CLEAR) +support.print_data(sink) + +# Idiomatic interface. +with pyme.Context(armor=True, textmode=True) as c: + message = "Hallo Leute\n".encode() + signed, _ = c.sign(message) + assert len(signed) > 0 + assert signed.find(b'BEGIN PGP MESSAGE') > 0, 'Message not found' + + signed, _ = c.sign(message, mode=pyme.constants.SIG_MODE_DETACH) + assert len(signed) > 0 + assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found' + + signed, _ = c.sign(message, mode=pyme.constants.SIG_MODE_CLEAR) + assert len(signed) > 0 + assert signed.find(b'BEGIN PGP SIGNED MESSAGE') > 0, 'Message not found' + assert signed.find(message) > 0, 'Message content not found' + assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found' + +with pyme.Context() as c: + message = "Hallo Leute\n".encode() + + c.signers = [c.get_key(support.sign_only, True)] + c.sign(message) + + c.signers = [c.get_key(support.encrypt_only, True)] + try: + c.sign(message) + except pyme.errors.InvalidSigners as e: + assert len(e.signers) == 1 + assert support.encrypt_only.endswith(e.signers[0].fpr) + else: + assert False, "Expected an InvalidSigners error, got none" diff --git a/lang/python/tests/t-signers.py b/lang/python/tests/t-signers.py new file mode 100755 index 0000000..11403af --- /dev/null +++ b/lang/python/tests/t-signers.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import pyme +from pyme import core, constants +import support + +def fail(msg): + raise RuntimeError(msg) + +def check_result(r, typ): + if r.invalid_signers: + fail("Invalid signer found: {}".format(r.invalid_signers.fpr)) + + if len(r.signatures) != 2: + fail("Unexpected number of signatures created") + + for signature in r.signatures: + if signature.type != typ: + fail("Wrong type of signature created") + + if signature.pubkey_algo != constants.PK_DSA: + fail("Wrong pubkey algorithm reported: {}".format( + signature.pubkey_algo)) + + if signature.hash_algo != constants.MD_SHA1: + fail("Wrong hash algorithm reported: {}".format( + signature.hash_algo)) + + if signature.sig_class != 1: + fail("Wrong signature class reported: got {}, want {}".format( + signature.sig_class, 1)) + + if signature.fpr not in ("A0FF4590BB6122EDEF6E3C542D727CC768697734", + "23FD347A419429BACCD5E72D6BC4778054ACD246"): + fail("Wrong fingerprint reported: {}".format(signature.fpr)) + + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_textmode(True) +c.set_armor(True) + +keys = [] +c.op_keylist_start('', True) +keys.append(c.op_keylist_next()) +keys.append(c.op_keylist_next()) +c.op_keylist_end() + +c.signers_add(keys[0]) +c.signers_add(keys[1]) + +for mode in (constants.SIG_MODE_NORMAL, constants.SIG_MODE_DETACH, + constants.SIG_MODE_CLEAR): + source = core.Data("Hallo Leute\n") + sink = core.Data() + + c.op_sign(source, sink, mode) + + result = c.op_sign_result() + check_result(result, mode) + support.print_data(sink) + +# Idiomatic interface. +with pyme.Context(armor=True, textmode=True, signers=keys) as c: + message = "Hallo Leute\n".encode() + signed, result = c.sign(message) + check_result(result, constants.SIG_MODE_NORMAL) + assert signed.find(b'BEGIN PGP MESSAGE') > 0, 'Message not found' + + signed, result = c.sign(message, mode=constants.SIG_MODE_DETACH) + check_result(result, constants.SIG_MODE_DETACH) + assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found' + + signed, result = c.sign(message, mode=constants.SIG_MODE_CLEAR) + check_result(result, constants.SIG_MODE_CLEAR) + assert signed.find(b'BEGIN PGP SIGNED MESSAGE') > 0, 'Message not found' + assert signed.find(message) > 0, 'Message content not found' + assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found' diff --git a/lang/python/tests/t-trustlist.py b/lang/python/tests/t-trustlist.py new file mode 100755 index 0000000..4253bd7 --- /dev/null +++ b/lang/python/tests/t-trustlist.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from pyme import core, constants +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() + +def dump_item(item): + print("l={} k={} t={} o={} v={} u={}".format( + item.level, item.keyid, item.type, item.owner_trust, + item.validity, item.name)) + +c.op_trustlist_start("alice", 0) +while True: + item = c.op_trustlist_next() + if not item: + break + dump_item(item) +c.op_trustlist_end() + +for item in c.op_trustlist_all("alice", 0): + dump_item(item) diff --git a/lang/python/tests/t-verify.py b/lang/python/tests/t-verify.py new file mode 100755 index 0000000..39f6176 --- /dev/null +++ b/lang/python/tests/t-verify.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys +import os +import pyme +from pyme import core, constants, errors +import support + +test_text1 = b"Just GNU it!\n" +test_text1f= b"Just GNU it?\n" +test_sig1 = b"""-----BEGIN PGP SIGNATURE----- + +iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt +bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv +b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw +Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc +dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA== +=nts1 +-----END PGP SIGNATURE----- +""" + +test_sig2 = b"""-----BEGIN PGP MESSAGE----- + +owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH +GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf +y1kvP4y+8D5a11ang0udywsA +=Crq6 +-----END PGP MESSAGE----- +""" + +# A message with a prepended but unsigned plaintext packet. +double_plaintext_sig = b"""-----BEGIN PGP MESSAGE----- + +rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l +c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV +UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF +erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn +UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA +=6+AK +-----END PGP MESSAGE----- +""" + +def check_result(result, summary, validity, fpr, status, notation): + assert len(result.signatures) == 1, "Unexpected number of signatures" + sig = result.signatures[0] + assert sig.summary == summary, \ + "Unexpected signature summary: {}, want: {}".format(sig.summary, + summary) + assert sig.fpr == fpr + assert errors.GPGMEError(sig.status).getcode() == status + + if notation: + expected_notations = { + "bar": (b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f" + + b" das waren Umlaute und jetzt ein prozent%-Zeichen" + if sys.version_info[0] < 3 else + b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f".decode() + + " das waren Umlaute und jetzt ein prozent%-Zeichen"), + "foobar.1": "this is a notation data with 2 lines", + None: "http://www.gu.org/policy/", + } + assert len(sig.notations) == len(expected_notations) + + for r in sig.notations: + assert not 'name_len' in dir(r) + assert not 'value_len' in dir(r) + assert r.name in expected_notations + assert r.value == expected_notations[r.name], \ + "Expected {!r}, got {!r}".format(expected_notations[r.name], + r.value) + expected_notations.pop(r.name) + + assert len(expected_notations) == 0 + + assert not sig.wrong_key_usage + assert sig.validity == validity, \ + "Unexpected signature validity: {}, want: {}".format( + sig.validity, validity) + assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR + + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +# Checking a valid message. +text = core.Data(test_text1) +sig = core.Data(test_sig1) +c.op_verify(sig, text, None) +result = c.op_verify_result() +check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + constants.VALIDITY_FULL, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR, True) + + +# Checking a manipulated message. +text = core.Data(test_text1f) +sig.seek(0, os.SEEK_SET) +c.op_verify(sig, text, None) +result = c.op_verify_result() +check_result(result, constants.SIGSUM_RED, constants.VALIDITY_UNKNOWN, + "2D727CC768697734", errors.BAD_SIGNATURE, False) + +# Checking a normal signature. +text = core.Data() +sig = core.Data(test_sig2) +c.op_verify(sig, None, text) +result = c.op_verify_result() +check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + constants.VALIDITY_FULL, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR, False) + +# Checking an invalid message. +text = core.Data() +sig = core.Data(double_plaintext_sig) +try: + c.op_verify(sig, None, text) +except Exception as e: + assert type(e) == errors.GPGMEError + assert e.getcode() == errors.BAD_DATA +else: + assert False, "Expected an error but got none." + + +# Idiomatic interface. +with pyme.Context(armor=True) as c: + # Checking a valid message. + _, result = c.verify(test_text1, test_sig1) + check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + constants.VALIDITY_FULL, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR, True) + + # Checking a manipulated message. + try: + c.verify(test_text1f, test_sig1) + except errors.BadSignatures as e: + check_result(e.result, constants.SIGSUM_RED, + constants.VALIDITY_UNKNOWN, + "2D727CC768697734", errors.BAD_SIGNATURE, False) + else: + assert False, "Expected an error but got none." + + # Checking a normal signature. + sig = core.Data(test_sig2) + data, result = c.verify(test_sig2) + check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN, + constants.VALIDITY_FULL, + "A0FF4590BB6122EDEF6E3C542D727CC768697734", + errors.NO_ERROR, False) + assert data == test_text1 + + # Checking an invalid message. + try: + c.verify(double_plaintext_sig) + except errors.GPGMEError as e: + assert e.getcode() == errors.BAD_DATA + else: + assert False, "Expected an error but got none." + + alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False) + bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False) + + # Checking a valid message. + c.verify(test_text1, test_sig1, verify=[alpha]) + + try: + c.verify(test_text1, test_sig1, verify=[alpha, bob]) + except errors.MissingSignatures as e: + assert len(e.missing) == 1 + assert e.missing[0] == bob + else: + assert False, "Expected an error, got none" diff --git a/lang/python/tests/t-wait.py b/lang/python/tests/t-wait.py new file mode 100755 index 0000000..b7d9a34 --- /dev/null +++ b/lang/python/tests/t-wait.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import time +from pyme import core, constants, errors +import support + +support.init_gpgme(constants.PROTOCOL_OpenPGP) +c = core.Context() +c.set_armor(True) + +# Checking a message without a signature. +sig = core.Data("foo\n") +text = core.Data() +c.op_verify_start(sig, None, text) + +try: + while True: + err = c.wait(False) + if err: + break + time.sleep(0.1) +except Exception as e: + assert e.getcode() == errors.NO_DATA +else: + assert False, "Expected an error, got none" diff --git a/lang/python/tests/t-wrapper.py b/lang/python/tests/t-wrapper.py new file mode 100755 index 0000000..d260264 --- /dev/null +++ b/lang/python/tests/t-wrapper.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +# Copyright (C) 2016 g10 Code GmbH +# +# 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +from pyme import core + +d0 = core.Data() +d0.seek # trigger on-demand-wrapping +assert d0.seek == d0.seek, "Generated wrapper functions are not cached" +assert hasattr(core.Data, 'seek'), "Generated wrapper functions are not shared" diff --git a/lang/qt/Makefile.am b/lang/qt/Makefile.am new file mode 100644 index 0000000..39eb55e --- /dev/null +++ b/lang/qt/Makefile.am @@ -0,0 +1,23 @@ +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +SUBDIRS = src tests doc + +EXTRA_DIST = README diff --git a/lang/qt/Makefile.in b/lang/qt/Makefile.in new file mode 100644 index 0000000..d8b48d2 --- /dev/null +++ b/lang/qt/Makefile.in @@ -0,0 +1,709 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/qt +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs README +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +SUBDIRS = src tests doc +EXTRA_DIST = README +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/qt/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-recursive +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-recursive + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-recursive + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(am__recursive_targets) install-am install-strip + +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/qt/README b/lang/qt/README new file mode 100644 index 0000000..6360a5b --- /dev/null +++ b/lang/qt/README @@ -0,0 +1,130 @@ +Qt API bindings/wrapper for GPGME +--------------------------------- +Based on KF5gpgmepp QGpgME and libkleo/backends/qgpgme + +Please note that QGpgME has a different license (GPL only) +then GPGME itself. See the License secion in this +document for more information. + +Overview +-------- +QGpgme provides a very high level Qt API around GpgMEpp. +As such it depends on GpgMEpp additionally to GpgME. + +There are two general concepts in QGpgME. Data abstraction +through GpgMEpp's Dataprovider interface and the Job pattern. + +Data can be provided with QByteArrayDataProvider or +QIODeviceDataProvider which can be constructed from their +respective types. This means you can pass a QFile, QProcess, +QString, etc.. directly to GPGME. + +To provide a stable API / ABI and because of historic reasons +in libkleo (Where QGpgME was originally developed as an abstract +crypto backend) QGpgME only provides abstract interfaces as +public API while the actual implementation happens in the +private QGpgME prefixed classes. + +Usage +----- + +To use QGpgME first you need to obtain a Protocol class +either for CMS (S/MIME) or OpenPGP. This Protocol class +can then be used to create a Job. + +Each Job can be started asynchronusly and emits a result +signal when done. The jobs are deleted automatically +with QObject::deleteLater so they can be started without +result handlers. + +The result signal provides a tuple of objects with the +appropiate result information for this job. For historic +reasons each result signal also includes an AuditLog +and an AuditLog Error. These are only useful for +S/MIME signature validation but are part of other jobs +for API stability reasons. + +Some jobs like the verification or decryption jobs have +dedicated result classes. Each result class at least +has the member function error() that can be used +to check if a job failed. Additionally errors are emited +in the result signal. + +Jobs also provide progress signal whenever GnuPG emits +a progress status line. + +Most jobs also provide a way synchronusly execute them. +Please not that synchronus use does not cause the autodeletion +to take place so you have to manually delete them. + +Async usage: + + /* Create a job */ + EncryptJob *job = openpgp()->encryptJob(/*ASCII Armor */false, /* Textmode */ false); + /* Connect something to the result signal */ + connect(job, &EncryptJob::result, this, [] (const GpgME::EncryptionResult &result, + const QByteArray &cipherText, + const QString, + const GpgME::Error) { + /* Handle the result / do something with the ciphertext */ + }); + /* Start the job */ + job->start(keys, inptr, outptr, Context::AlwaysTrust); + /* Do not delete the job as it is autodeleted. */ + +Syncronus usage: + + /* Create a job */ + KeyListJob *listjob = openpgp()->keyListJob(false, false, false); + /* Prepare result vector */ + std::vector<Key> keys; + /* Execute it synchronusly */ + KeyListResult result = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + /* Delete the job */ + delete listjob; + /* Work with the result */ + +See the generated documentation for more info on the classes +in QGpgME. (Subdir doc) + +Examples / Tests +---------------- + +The tests in the tests subdir can be used to get a better +idea of QGpgME's usage. They also serve to test the C++ +API. Kleopatra and KMails Messagelib also make extensive +use of QGpgME and can be used as further examples. + +Hacking +------- +QGpgME comes from a KDE background. As such it does not use +GNU Coding styles but KDE Coding styles. See: +https://techbase.kde.org/Policies/Frameworks_Coding_Style + +License +------- +QGpgME 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. + +QGpgME is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +In addition, as a special exception, the copyright holders give +permission to link the code of this program with any edition of +the Qt library by Trolltech AS, Norway (or with modified versions +of Qt that use the same license as Qt), and distribute linked +combinations including the two. You must obey the GNU General +Public License in all respects for all of the code used other than +Qt. If you modify this file, you may extend this exception to +your version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement from +your version. diff --git a/lang/qt/doc/Doxyfile.in b/lang/qt/doc/Doxyfile.in new file mode 100644 index 0000000..5d94f90 --- /dev/null +++ b/lang/qt/doc/Doxyfile.in @@ -0,0 +1,2352 @@ +# Doxyfile 1.8.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "QGpgME" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@.@BUILD_REVISION@" + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Qt API for GpgME" + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = "@abs_builddir@/generated" + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = "@top_srcdir@/lang/qt/src" + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when enabling USE_PDFLATEX this option is only used for generating +# bitmaps for formulas in the HTML output, but not in the Makefile that is +# written to the output directory. +# The default file is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. To get the times font for +# instance you can specify +# EXTRA_PACKAGES=times +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string, +# for the replacement values of the other commands the user is refered to +# HTML_HEADER. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's config +# file, i.e. a series of assignments. You only have to provide replacements, +# missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's config file. A template extensions file can be generated +# using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen +# Definitions (see http://autogen.sf.net) file that captures the structure of +# the code including all documentation. Note that this feature is still +# experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names +# in the source code. If set to NO only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external class will be listed in the +# class index. If set to NO only the inherited external classes will be listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in +# the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of 'which perl'). +# The default file (with absolute path) is: /usr/bin/perl. + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see: +# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: YES. + +HAVE_DOT = @HAVE_DOT@ + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, +# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, +# gif:cairo:gd, gif:gd, gif:gd:gd and svg. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. +# This tag requires that the tag HAVE_DOT is set to YES. + +PLANTUML_JAR_PATH = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/lang/qt/doc/Makefile.am b/lang/qt/doc/Makefile.am new file mode 100644 index 0000000..ddf4935 --- /dev/null +++ b/lang/qt/doc/Makefile.am @@ -0,0 +1,31 @@ +# Makefile.am - Makefile for GPGME Qt docs. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +## Process this file with automake to produce Makefile.in + +if HAVE_DOXYGEN +doxyfile.stamp: + $(DOXYGEN) Doxyfile + touch doxyfile.stamp + +CLEANFILES = doxyfile.stamp + +all-local: doxyfile.stamp +clean-local: + rm -rf $(abs_builddir)/generated +endif diff --git a/lang/qt/doc/Makefile.in b/lang/qt/doc/Makefile.in new file mode 100644 index 0000000..d6d9ef7 --- /dev/null +++ b/lang/qt/doc/Makefile.in @@ -0,0 +1,540 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am - Makefile for GPGME Qt docs. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/qt/doc +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/Doxyfile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = Doxyfile +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@HAVE_DOXYGEN_TRUE@CLEANFILES = doxyfile.stamp +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/qt/doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +@HAVE_DOXYGEN_TRUE@Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in +@HAVE_DOXYGEN_TRUE@ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +@HAVE_DOXYGEN_FALSE@all-local: +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +@HAVE_DOXYGEN_FALSE@clean-local: +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am distclean \ + distclean-generic distclean-libtool distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ + uninstall-am + + +@HAVE_DOXYGEN_TRUE@doxyfile.stamp: +@HAVE_DOXYGEN_TRUE@ $(DOXYGEN) Doxyfile +@HAVE_DOXYGEN_TRUE@ touch doxyfile.stamp + +@HAVE_DOXYGEN_TRUE@all-local: doxyfile.stamp +@HAVE_DOXYGEN_TRUE@clean-local: +@HAVE_DOXYGEN_TRUE@ rm -rf $(abs_builddir)/generated + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/qt/src/AddUserIDJob b/lang/qt/src/AddUserIDJob new file mode 100644 index 0000000..87d82ec --- /dev/null +++ b/lang/qt/src/AddUserIDJob @@ -0,0 +1 @@ +#include "qgpgme/adduseridjob.h" diff --git a/lang/qt/src/ChangeExpiryJob b/lang/qt/src/ChangeExpiryJob new file mode 100644 index 0000000..f5eea6a --- /dev/null +++ b/lang/qt/src/ChangeExpiryJob @@ -0,0 +1 @@ +#include "qgpgme/changeexpiryjob.h" diff --git a/lang/qt/src/ChangeOwnerTrustJob b/lang/qt/src/ChangeOwnerTrustJob new file mode 100644 index 0000000..03635d5 --- /dev/null +++ b/lang/qt/src/ChangeOwnerTrustJob @@ -0,0 +1 @@ +#include "qgpgme/changeownertrustjob.h" diff --git a/lang/qt/src/ChangePasswdJob b/lang/qt/src/ChangePasswdJob new file mode 100644 index 0000000..3660940 --- /dev/null +++ b/lang/qt/src/ChangePasswdJob @@ -0,0 +1 @@ +#include "qgpgme/changepasswdjob.h" diff --git a/lang/qt/src/CryptoConfig b/lang/qt/src/CryptoConfig new file mode 100644 index 0000000..4edbd19 --- /dev/null +++ b/lang/qt/src/CryptoConfig @@ -0,0 +1 @@ +#include "qgpgme/cryptoconfig.h" diff --git a/lang/qt/src/DataProvider b/lang/qt/src/DataProvider new file mode 100644 index 0000000..6a43c1d --- /dev/null +++ b/lang/qt/src/DataProvider @@ -0,0 +1 @@ +#include "qgpgme/dataprovider.h" diff --git a/lang/qt/src/DecryptJob b/lang/qt/src/DecryptJob new file mode 100644 index 0000000..c0f9845 --- /dev/null +++ b/lang/qt/src/DecryptJob @@ -0,0 +1 @@ +#include "qgpgme/decryptjob.h" diff --git a/lang/qt/src/DecryptVerifyJob b/lang/qt/src/DecryptVerifyJob new file mode 100644 index 0000000..e3de1cc --- /dev/null +++ b/lang/qt/src/DecryptVerifyJob @@ -0,0 +1 @@ +#include "qgpgme/decryptverifyjob.h" diff --git a/lang/qt/src/DefaultKeyGenerationJob b/lang/qt/src/DefaultKeyGenerationJob new file mode 100644 index 0000000..1dc8c40 --- /dev/null +++ b/lang/qt/src/DefaultKeyGenerationJob @@ -0,0 +1 @@ +#include "qgpgme/defaultkeygenerationjob.h" diff --git a/lang/qt/src/DeleteJob b/lang/qt/src/DeleteJob new file mode 100644 index 0000000..a2fdc4a --- /dev/null +++ b/lang/qt/src/DeleteJob @@ -0,0 +1 @@ +#include "qgpgme/deletejob.h" diff --git a/lang/qt/src/DownloadJob b/lang/qt/src/DownloadJob new file mode 100644 index 0000000..9b47aac --- /dev/null +++ b/lang/qt/src/DownloadJob @@ -0,0 +1 @@ +#include "qgpgme/downloadjob.h" diff --git a/lang/qt/src/EncryptJob b/lang/qt/src/EncryptJob new file mode 100644 index 0000000..59a878d --- /dev/null +++ b/lang/qt/src/EncryptJob @@ -0,0 +1 @@ +#include "qgpgme/encryptjob.h" diff --git a/lang/qt/src/ExportJob b/lang/qt/src/ExportJob new file mode 100644 index 0000000..1d053fd --- /dev/null +++ b/lang/qt/src/ExportJob @@ -0,0 +1 @@ +#include "qgpgme/exportjob.h" diff --git a/lang/qt/src/HierarchicalKeyKistJob b/lang/qt/src/HierarchicalKeyKistJob new file mode 100644 index 0000000..cd31f48 --- /dev/null +++ b/lang/qt/src/HierarchicalKeyKistJob @@ -0,0 +1 @@ +#include "qgpgme/hierarchicalkeykistjob.h" diff --git a/lang/qt/src/ImportFromKeyserverJob b/lang/qt/src/ImportFromKeyserverJob new file mode 100644 index 0000000..17a5fd6 --- /dev/null +++ b/lang/qt/src/ImportFromKeyserverJob @@ -0,0 +1 @@ +#include "qgpgme/importfromkeyserverjob.h" diff --git a/lang/qt/src/ImportJob b/lang/qt/src/ImportJob new file mode 100644 index 0000000..e5228d7 --- /dev/null +++ b/lang/qt/src/ImportJob @@ -0,0 +1 @@ +#include "qgpgme/importjob.h" diff --git a/lang/qt/src/Job b/lang/qt/src/Job new file mode 100644 index 0000000..3a45ca7 --- /dev/null +++ b/lang/qt/src/Job @@ -0,0 +1 @@ +#include "qgpgme/job.h" diff --git a/lang/qt/src/KeyForMailboxJob b/lang/qt/src/KeyForMailboxJob new file mode 100644 index 0000000..2d2b8cb --- /dev/null +++ b/lang/qt/src/KeyForMailboxJob @@ -0,0 +1 @@ +#include "qgpgme/keyformailboxjob.h" diff --git a/lang/qt/src/KeyGenerationJob b/lang/qt/src/KeyGenerationJob new file mode 100644 index 0000000..1612ba7 --- /dev/null +++ b/lang/qt/src/KeyGenerationJob @@ -0,0 +1 @@ +#include "qgpgme/keygenerationjob.h" diff --git a/lang/qt/src/KeyListJob b/lang/qt/src/KeyListJob new file mode 100644 index 0000000..7366665 --- /dev/null +++ b/lang/qt/src/KeyListJob @@ -0,0 +1 @@ +#include "qgpgme/keylistjob.h" diff --git a/lang/qt/src/ListAllKeysJob b/lang/qt/src/ListAllKeysJob new file mode 100644 index 0000000..8023f8f --- /dev/null +++ b/lang/qt/src/ListAllKeysJob @@ -0,0 +1 @@ +#include "qgpgme/listallkeysjob.h" diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am new file mode 100644 index 0000000..c15da18 --- /dev/null +++ b/lang/qt/src/Makefile.am @@ -0,0 +1,256 @@ +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA +lib_LTLIBRARIES = libqgpgme.la +EXTRA_DIST = QGpgmeConfig.cmake.in.in QGpgmeConfigVersion.cmake.in \ + gpgme_backend_debug.h qgpgme_version.h.in + +qgpgme_sources = \ + dataprovider.cpp job.cpp qgpgmeadduseridjob.cpp \ + qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \ + qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \ + qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \ + qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \ + qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \ + qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \ + qgpgmerefreshkeysjob.cpp \ + qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \ + qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \ + qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \ + qgpgmekeyformailboxjob.cpp gpgme_backend_debug.cpp \ + qgpgmetofupolicyjob.cpp \ + defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp + +# If you add one here make sure that you also add one in camelcase +qgpgme_headers= \ + adduseridjob.h \ + changeexpiryjob.h \ + changeownertrustjob.h \ + changepasswdjob.h \ + dataprovider.h \ + decryptjob.h \ + decryptverifyjob.h \ + downloadjob.h \ + encryptjob.h \ + exportjob.h \ + hierarchicalkeylistjob.h \ + job.h \ + keyformailboxjob.h \ + multideletejob.h \ + protocol.h \ + qgpgme_export.h \ + qgpgmenewcryptoconfig.h \ + signjob.h \ + signkeyjob.h \ + signencryptjob.h \ + verifyopaquejob.h \ + refreshkeysjob.h \ + cryptoconfig.h \ + deletejob.h \ + importfromkeyserverjob.h \ + importjob.h \ + keygenerationjob.h \ + keylistjob.h \ + listallkeysjob.h \ + verifydetachedjob.h \ + defaultkeygenerationjob.h \ + tofupolicyjob.h \ + wkspublishjob.h + +camelcase_headers= \ + AddUserIDJob \ + ChangeExpiryJob \ + ChangeOwnerTrustJob \ + ChangePasswdJob \ + DataProvider \ + DecryptJob \ + DecryptVerifyJob \ + DownloadJob \ + EncryptJob \ + ExportJob \ + HierarchicalKeyKistJob \ + Job \ + MultiDeleteJob \ + Protocol \ + QGpgMENewCryptoConfig \ + SignJob \ + SignKeyJob \ + SignEncryptJob \ + VerifyOpaqueJob \ + RefreshKeysJob \ + CryptoConfig \ + DeleteJob \ + ImportFromKeyserverJob \ + ImportJob \ + KeyGenerationJob \ + KeyListJob \ + ListAllKeysJob \ + VerifyDetachedJob \ + KeyForMailboxJob \ + DefaultKeyGenerationJob \ + WKSPublishJob \ + TofuPolicyJob + +private_qgpgme_headers = \ + qgpgme_export.h \ + abstractimportjob.h \ + protocol_p.h \ + qgpgmeadduseridjob.h \ + qgpgmebackend.h \ + qgpgmechangeexpiryjob.h \ + qgpgmechangeownertrustjob.h \ + qgpgmechangepasswdjob.h \ + qgpgmedecryptjob.h \ + qgpgmedecryptverifyjob.h \ + qgpgmedeletejob.h \ + qgpgmedownloadjob.h \ + qgpgmeencryptjob.h \ + qgpgmeexportjob.h \ + qgpgmeimportfromkeyserverjob.h \ + qgpgmeimportjob.h \ + qgpgmekeygenerationjob.h \ + qgpgmekeylistjob.h \ + qgpgmelistallkeysjob.h \ + qgpgmerefreshkeysjob.h \ + qgpgmesecretkeyexportjob.h \ + qgpgmesignencryptjob.h \ + qgpgmesignjob.h \ + qgpgmesignkeyjob.h \ + qgpgmeverifydetachedjob.h \ + qgpgmeverifyopaquejob.h \ + qgpgmekeyformailboxjob.h \ + qgpgmewkspublishjob.h \ + qgpgmetofupolicyjob.h \ + specialjob.h \ + threadedjobmixin.h + +qgpgme_moc_sources = \ + abstractimportjob.moc \ + adduseridjob.moc \ + changeexpiryjob.moc \ + changeownertrustjob.moc \ + changepasswdjob.moc \ + decryptjob.moc \ + decryptverifyjob.moc \ + deletejob.moc \ + downloadjob.moc \ + encryptjob.moc \ + exportjob.moc \ + hierarchicalkeylistjob.moc \ + importfromkeyserverjob.moc \ + importjob.moc \ + job.moc \ + keygenerationjob.moc \ + keylistjob.moc \ + listallkeysjob.moc \ + multideletejob.moc \ + qgpgmeadduseridjob.moc \ + qgpgmechangeexpiryjob.moc \ + qgpgmechangeownertrustjob.moc \ + qgpgmechangepasswdjob.moc \ + qgpgmedecryptjob.moc \ + qgpgmedecryptverifyjob.moc \ + qgpgmedeletejob.moc \ + qgpgmedownloadjob.moc \ + qgpgmeencryptjob.moc \ + qgpgmeexportjob.moc \ + qgpgmeimportfromkeyserverjob.moc \ + qgpgmeimportjob.moc \ + qgpgmekeygenerationjob.moc \ + qgpgmekeylistjob.moc \ + qgpgmelistallkeysjob.moc \ + qgpgmerefreshkeysjob.moc \ + qgpgmesecretkeyexportjob.moc \ + qgpgmesignencryptjob.moc \ + qgpgmesignjob.moc \ + qgpgmesignkeyjob.moc \ + qgpgmeverifydetachedjob.moc \ + qgpgmeverifyopaquejob.moc \ + qgpgmewkspublishjob.moc \ + tofupolicyjob.moc \ + qgpgmetofupolicyjob.moc \ + refreshkeysjob.moc \ + signencryptjob.moc \ + signjob.moc \ + signkeyjob.moc \ + specialjob.moc \ + verifydetachedjob.moc \ + verifyopaquejob.moc \ + keyformailboxjob.moc \ + wkspublishjob.moc \ + qgpgmekeyformailboxjob.moc \ + defaultkeygenerationjob.moc + +qgpgmeincludedir = $(includedir)/qgpgme +qgpgmeinclude_HEADERS = $(qgpgme_headers) +camelcaseincludedir = $(includedir)/QGpgME +camelcaseinclude_HEADERS = $(camelcase_headers) +nodist_include_HEADERS = qgpgme_version.h + +libqgpgme_la_SOURCES = $(qgpgme_sources) $(qgpgme_headers) $(private_qgpgme_headers) + +AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \ + @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \ + -DBUILDING_QGPGME + +libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \ + @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@ +libqgpgme_la_LDFLAGS = -version-info \ + @LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@ + +if HAVE_W32_SYSTEM +libsuffix=.dll.a +else +libsuffix=.so +endif + +QGpgmeConfig.cmake: QGpgmeConfig.cmake.in + sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@" + sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2 + mv "$@".2 "$@" + +$(camelcase_headers): Makefile.am + echo -n "#include \"qgpgme/" > "$@" + echo -n "$@" | tr '[:upper:]' '[:lower:]' >> "$@" + echo ".h\"" >> "$@" + +install-cmake-files: QGpgmeConfig.cmake QGpgmeConfigVersion.cmake + -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp + $(INSTALL) QGpgmeConfig.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake + $(INSTALL) QGpgmeConfigVersion.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake + +uninstall-cmake-files: + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake + -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/ + +install-data-local: install-cmake-files + +uninstall-local: uninstall-cmake-files + +BUILT_SOURCES = $(qgpgme_moc_sources) $(camelcase_headers) + +CLEANFILES = $(qgpgme_moc_sources) $(camelcase_headers) QGpgmeConfig.cmake + +nodist_libqgpgme_la_SOURCES = $(qgpgme_moc_sources) + +.h.moc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ diff --git a/lang/qt/src/Makefile.in b/lang/qt/src/Makefile.in new file mode 100644 index 0000000..d10eca3 --- /dev/null +++ b/lang/qt/src/Makefile.in @@ -0,0 +1,1123 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = lang/qt/src +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs \ + $(srcdir)/QGpgmeConfig.cmake.in.in \ + $(srcdir)/QGpgmeConfigVersion.cmake.in \ + $(srcdir)/qgpgme_version.h.in $(top_srcdir)/build-aux/depcomp \ + $(camelcaseinclude_HEADERS) $(qgpgmeinclude_HEADERS) +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = QGpgmeConfig.cmake.in QGpgmeConfigVersion.cmake \ + qgpgme_version.h +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(camelcaseincludedir)" "$(DESTDIR)$(includedir)" \ + "$(DESTDIR)$(qgpgmeincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libqgpgme_la_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../../../src/libgpgme.la +am__objects_1 = dataprovider.lo job.lo qgpgmeadduseridjob.lo \ + qgpgmebackend.lo qgpgmechangeexpiryjob.lo \ + qgpgmechangeownertrustjob.lo qgpgmechangepasswdjob.lo \ + qgpgmedecryptjob.lo qgpgmedecryptverifyjob.lo \ + qgpgmedeletejob.lo qgpgmedownloadjob.lo qgpgmeencryptjob.lo \ + qgpgmeexportjob.lo qgpgmeimportfromkeyserverjob.lo \ + qgpgmeimportjob.lo qgpgmekeygenerationjob.lo \ + qgpgmekeylistjob.lo qgpgmelistallkeysjob.lo \ + qgpgmenewcryptoconfig.lo qgpgmerefreshkeysjob.lo \ + qgpgmesecretkeyexportjob.lo qgpgmesignencryptjob.lo \ + qgpgmesignjob.lo qgpgmesignkeyjob.lo \ + qgpgmeverifydetachedjob.lo qgpgmeverifyopaquejob.lo \ + threadedjobmixin.lo qgpgmekeyformailboxjob.lo \ + gpgme_backend_debug.lo qgpgmetofupolicyjob.lo \ + defaultkeygenerationjob.lo qgpgmewkspublishjob.lo +am__objects_2 = +am_libqgpgme_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ + $(am__objects_2) +nodist_libqgpgme_la_OBJECTS = $(am__objects_2) +libqgpgme_la_OBJECTS = $(am_libqgpgme_la_OBJECTS) \ + $(nodist_libqgpgme_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libqgpgme_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(libqgpgme_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libqgpgme_la_SOURCES) $(nodist_libqgpgme_la_SOURCES) +DIST_SOURCES = $(libqgpgme_la_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(camelcaseinclude_HEADERS) $(nodist_include_HEADERS) \ + $(qgpgmeinclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Makefile.am for GPGMEPP. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGMEPP. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA +lib_LTLIBRARIES = libqgpgme.la +EXTRA_DIST = QGpgmeConfig.cmake.in.in QGpgmeConfigVersion.cmake.in \ + gpgme_backend_debug.h qgpgme_version.h.in + +qgpgme_sources = \ + dataprovider.cpp job.cpp qgpgmeadduseridjob.cpp \ + qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \ + qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \ + qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \ + qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \ + qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \ + qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \ + qgpgmerefreshkeysjob.cpp \ + qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \ + qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \ + qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \ + qgpgmekeyformailboxjob.cpp gpgme_backend_debug.cpp \ + qgpgmetofupolicyjob.cpp \ + defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp + + +# If you add one here make sure that you also add one in camelcase +qgpgme_headers = \ + adduseridjob.h \ + changeexpiryjob.h \ + changeownertrustjob.h \ + changepasswdjob.h \ + dataprovider.h \ + decryptjob.h \ + decryptverifyjob.h \ + downloadjob.h \ + encryptjob.h \ + exportjob.h \ + hierarchicalkeylistjob.h \ + job.h \ + keyformailboxjob.h \ + multideletejob.h \ + protocol.h \ + qgpgme_export.h \ + qgpgmenewcryptoconfig.h \ + signjob.h \ + signkeyjob.h \ + signencryptjob.h \ + verifyopaquejob.h \ + refreshkeysjob.h \ + cryptoconfig.h \ + deletejob.h \ + importfromkeyserverjob.h \ + importjob.h \ + keygenerationjob.h \ + keylistjob.h \ + listallkeysjob.h \ + verifydetachedjob.h \ + defaultkeygenerationjob.h \ + tofupolicyjob.h \ + wkspublishjob.h + +camelcase_headers = \ + AddUserIDJob \ + ChangeExpiryJob \ + ChangeOwnerTrustJob \ + ChangePasswdJob \ + DataProvider \ + DecryptJob \ + DecryptVerifyJob \ + DownloadJob \ + EncryptJob \ + ExportJob \ + HierarchicalKeyKistJob \ + Job \ + MultiDeleteJob \ + Protocol \ + QGpgMENewCryptoConfig \ + SignJob \ + SignKeyJob \ + SignEncryptJob \ + VerifyOpaqueJob \ + RefreshKeysJob \ + CryptoConfig \ + DeleteJob \ + ImportFromKeyserverJob \ + ImportJob \ + KeyGenerationJob \ + KeyListJob \ + ListAllKeysJob \ + VerifyDetachedJob \ + KeyForMailboxJob \ + DefaultKeyGenerationJob \ + WKSPublishJob \ + TofuPolicyJob + +private_qgpgme_headers = \ + qgpgme_export.h \ + abstractimportjob.h \ + protocol_p.h \ + qgpgmeadduseridjob.h \ + qgpgmebackend.h \ + qgpgmechangeexpiryjob.h \ + qgpgmechangeownertrustjob.h \ + qgpgmechangepasswdjob.h \ + qgpgmedecryptjob.h \ + qgpgmedecryptverifyjob.h \ + qgpgmedeletejob.h \ + qgpgmedownloadjob.h \ + qgpgmeencryptjob.h \ + qgpgmeexportjob.h \ + qgpgmeimportfromkeyserverjob.h \ + qgpgmeimportjob.h \ + qgpgmekeygenerationjob.h \ + qgpgmekeylistjob.h \ + qgpgmelistallkeysjob.h \ + qgpgmerefreshkeysjob.h \ + qgpgmesecretkeyexportjob.h \ + qgpgmesignencryptjob.h \ + qgpgmesignjob.h \ + qgpgmesignkeyjob.h \ + qgpgmeverifydetachedjob.h \ + qgpgmeverifyopaquejob.h \ + qgpgmekeyformailboxjob.h \ + qgpgmewkspublishjob.h \ + qgpgmetofupolicyjob.h \ + specialjob.h \ + threadedjobmixin.h + +qgpgme_moc_sources = \ + abstractimportjob.moc \ + adduseridjob.moc \ + changeexpiryjob.moc \ + changeownertrustjob.moc \ + changepasswdjob.moc \ + decryptjob.moc \ + decryptverifyjob.moc \ + deletejob.moc \ + downloadjob.moc \ + encryptjob.moc \ + exportjob.moc \ + hierarchicalkeylistjob.moc \ + importfromkeyserverjob.moc \ + importjob.moc \ + job.moc \ + keygenerationjob.moc \ + keylistjob.moc \ + listallkeysjob.moc \ + multideletejob.moc \ + qgpgmeadduseridjob.moc \ + qgpgmechangeexpiryjob.moc \ + qgpgmechangeownertrustjob.moc \ + qgpgmechangepasswdjob.moc \ + qgpgmedecryptjob.moc \ + qgpgmedecryptverifyjob.moc \ + qgpgmedeletejob.moc \ + qgpgmedownloadjob.moc \ + qgpgmeencryptjob.moc \ + qgpgmeexportjob.moc \ + qgpgmeimportfromkeyserverjob.moc \ + qgpgmeimportjob.moc \ + qgpgmekeygenerationjob.moc \ + qgpgmekeylistjob.moc \ + qgpgmelistallkeysjob.moc \ + qgpgmerefreshkeysjob.moc \ + qgpgmesecretkeyexportjob.moc \ + qgpgmesignencryptjob.moc \ + qgpgmesignjob.moc \ + qgpgmesignkeyjob.moc \ + qgpgmeverifydetachedjob.moc \ + qgpgmeverifyopaquejob.moc \ + qgpgmewkspublishjob.moc \ + tofupolicyjob.moc \ + qgpgmetofupolicyjob.moc \ + refreshkeysjob.moc \ + signencryptjob.moc \ + signjob.moc \ + signkeyjob.moc \ + specialjob.moc \ + verifydetachedjob.moc \ + verifyopaquejob.moc \ + keyformailboxjob.moc \ + wkspublishjob.moc \ + qgpgmekeyformailboxjob.moc \ + defaultkeygenerationjob.moc + +qgpgmeincludedir = $(includedir)/qgpgme +qgpgmeinclude_HEADERS = $(qgpgme_headers) +camelcaseincludedir = $(includedir)/QGpgME +camelcaseinclude_HEADERS = $(camelcase_headers) +nodist_include_HEADERS = qgpgme_version.h +libqgpgme_la_SOURCES = $(qgpgme_sources) $(qgpgme_headers) $(private_qgpgme_headers) +AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \ + @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \ + -DBUILDING_QGPGME + +libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \ + @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@ + +libqgpgme_la_LDFLAGS = -version-info \ + @LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@ + +@HAVE_W32_SYSTEM_FALSE@libsuffix = .so +@HAVE_W32_SYSTEM_TRUE@libsuffix = .dll.a +BUILT_SOURCES = $(qgpgme_moc_sources) $(camelcase_headers) +CLEANFILES = $(qgpgme_moc_sources) $(camelcase_headers) QGpgmeConfig.cmake +nodist_libqgpgme_la_SOURCES = $(qgpgme_moc_sources) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cpp .h .lo .moc .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/qt/src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +QGpgmeConfig.cmake.in: $(top_builddir)/config.status $(srcdir)/QGpgmeConfig.cmake.in.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +QGpgmeConfigVersion.cmake: $(top_builddir)/config.status $(srcdir)/QGpgmeConfigVersion.cmake.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +qgpgme_version.h: $(top_builddir)/config.status $(srcdir)/qgpgme_version.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libqgpgme.la: $(libqgpgme_la_OBJECTS) $(libqgpgme_la_DEPENDENCIES) $(EXTRA_libqgpgme_la_DEPENDENCIES) + $(AM_V_CXXLD)$(libqgpgme_la_LINK) -rpath $(libdir) $(libqgpgme_la_OBJECTS) $(libqgpgme_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dataprovider.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultkeygenerationjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgme_backend_debug.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeadduseridjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmebackend.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeexpiryjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeownertrustjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangepasswdjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedecryptjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedecryptverifyjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedeletejob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedownloadjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeencryptjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeexportjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeimportfromkeyserverjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeimportjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeyformailboxjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeygenerationjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeylistjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmelistallkeysjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmenewcryptoconfig.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmerefreshkeysjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignencryptjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignkeyjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmetofupolicyjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifydetachedjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifyopaquejob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkspublishjob.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadedjobmixin.Plo@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-camelcaseincludeHEADERS: $(camelcaseinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(camelcaseinclude_HEADERS)'; test -n "$(camelcaseincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(camelcaseincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(camelcaseincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(camelcaseincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(camelcaseincludedir)" || exit $$?; \ + done + +uninstall-camelcaseincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(camelcaseinclude_HEADERS)'; test -n "$(camelcaseincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(camelcaseincludedir)'; $(am__uninstall_files_from_dir) +install-nodist_includeHEADERS: $(nodist_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-nodist_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) +install-qgpgmeincludeHEADERS: $(qgpgmeinclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(qgpgmeinclude_HEADERS)'; test -n "$(qgpgmeincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(qgpgmeincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(qgpgmeincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(qgpgmeincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(qgpgmeincludedir)" || exit $$?; \ + done + +uninstall-qgpgmeincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(qgpgmeinclude_HEADERS)'; test -n "$(qgpgmeincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(qgpgmeincludedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(camelcaseincludedir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(qgpgmeincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-camelcaseincludeHEADERS install-data-local \ + install-nodist_includeHEADERS install-qgpgmeincludeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-camelcaseincludeHEADERS \ + uninstall-libLTLIBRARIES uninstall-local \ + uninstall-nodist_includeHEADERS uninstall-qgpgmeincludeHEADERS + +.MAKE: all check install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ + ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am \ + install-camelcaseincludeHEADERS install-data install-data-am \ + install-data-local install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-nodist_includeHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-qgpgmeincludeHEADERS \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ + uninstall-camelcaseincludeHEADERS uninstall-libLTLIBRARIES \ + uninstall-local uninstall-nodist_includeHEADERS \ + uninstall-qgpgmeincludeHEADERS + + +QGpgmeConfig.cmake: QGpgmeConfig.cmake.in + sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@" + sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2 + mv "$@".2 "$@" + +$(camelcase_headers): Makefile.am + echo -n "#include \"qgpgme/" > "$@" + echo -n "$@" | tr '[:upper:]' '[:lower:]' >> "$@" + echo ".h\"" >> "$@" + +install-cmake-files: QGpgmeConfig.cmake QGpgmeConfigVersion.cmake + -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp + $(INSTALL) QGpgmeConfig.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake + $(INSTALL) QGpgmeConfigVersion.cmake \ + $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake + +uninstall-cmake-files: + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake + -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake + -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/ + +install-data-local: install-cmake-files + +uninstall-local: uninstall-cmake-files + +.h.moc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/qt/src/MultiDeleteJob b/lang/qt/src/MultiDeleteJob new file mode 100644 index 0000000..e398c79 --- /dev/null +++ b/lang/qt/src/MultiDeleteJob @@ -0,0 +1 @@ +#include "qgpgme/multideletejob.h" diff --git a/lang/qt/src/Protocol b/lang/qt/src/Protocol new file mode 100644 index 0000000..6f92b75 --- /dev/null +++ b/lang/qt/src/Protocol @@ -0,0 +1 @@ +#include "qgpgme/protocol.h" diff --git a/lang/qt/src/QGpgMENewCryptoConfig b/lang/qt/src/QGpgMENewCryptoConfig new file mode 100644 index 0000000..99f353f --- /dev/null +++ b/lang/qt/src/QGpgMENewCryptoConfig @@ -0,0 +1 @@ +#include "qgpgme/qgpgmenewcryptoconfig.h" diff --git a/lang/qt/src/QGpgmeConfig.cmake.in.in b/lang/qt/src/QGpgmeConfig.cmake.in.in new file mode 100644 index 0000000..3d19696 --- /dev/null +++ b/lang/qt/src/QGpgmeConfig.cmake.in.in @@ -0,0 +1,107 @@ +# CMake Config file for QGPGME. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +# based on a generated file from cmake. +# Generated by CMake 3.0.2 + +if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) + message(FATAL_ERROR "CMake >= 2.6.0 required") +endif() +cmake_policy(PUSH) +cmake_policy(VERSION 2.6) +#---------------------------------------------------------------- +# Generated CMake target import file. +#---------------------------------------------------------------- + +# Commands may need to know the format version. +set(CMAKE_IMPORT_FILE_VERSION 1) + +# Protect against multiple inclusion, which would fail when already imported targets are added once more. +set(_targetsDefined) +set(_targetsNotDefined) +set(_expectedTargets) +foreach(_expectedTarget QGpgme KF5::QGpgme) + list(APPEND _expectedTargets ${_expectedTarget}) + if(NOT TARGET ${_expectedTarget}) + list(APPEND _targetsNotDefined ${_expectedTarget}) + endif() + if(TARGET ${_expectedTarget}) + list(APPEND _targetsDefined ${_expectedTarget}) + endif() +endforeach() +if("${_targetsDefined}" STREQUAL "${_expectedTargets}") + set(CMAKE_IMPORT_FILE_VERSION) + cmake_policy(POP) + return() +endif() +if(NOT "${_targetsDefined}" STREQUAL "") + message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") +endif() +unset(_targetsDefined) +unset(_targetsNotDefined) +unset(_expectedTargets) + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) + +# Create imported target QGpgme +add_library(QGpgme SHARED IMPORTED) + +set_target_properties(QGpgme PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include/qgpgme" + INTERFACE_LINK_LIBRARIES "Gpgmepp;Qt5::Core" + IMPORTED_LOCATION "@resolved_libdir@/libqgpgme@libsuffix@" +) + +if(CMAKE_VERSION VERSION_LESS 2.8.12) + message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.") +endif() + +# Cleanup temporary variables. +set(_IMPORT_PREFIX) + +# Loop over all imported files and verify that they actually exist +foreach(target ${_IMPORT_CHECK_TARGETS} ) + foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) + if(NOT EXISTS "${file}" ) + message(FATAL_ERROR "The imported target \"${target}\" references the file + \"${file}\" +but this file does not exist. Possible reasons include: +* The file was deleted, renamed, or moved to another location. +* An install or uninstall procedure did not complete successfully. +* The installation package was faulty and contained + \"${CMAKE_CURRENT_LIST_FILE}\" +but not all the files it references. +") + endif() + endforeach() + unset(_IMPORT_CHECK_FILES_FOR_${target}) +endforeach() +unset(_IMPORT_CHECK_TARGETS) + +# This file does not depend on other imported targets which have +# been exported from the same project but in a separate export set. + +# Commands beyond this point should not need to know the version. +set(CMAKE_IMPORT_FILE_VERSION) +cmake_policy(POP) diff --git a/lang/qt/src/QGpgmeConfigVersion.cmake.in b/lang/qt/src/QGpgmeConfigVersion.cmake.in new file mode 100644 index 0000000..04a12cb --- /dev/null +++ b/lang/qt/src/QGpgmeConfigVersion.cmake.in @@ -0,0 +1,31 @@ +# CMake Version file for QGPGME. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME-CL 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-CL 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA + +# based on a generated file from cmake. +set(PACKAGE_VERSION "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@.@BUILD_REVISION@") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/lang/qt/src/RefreshKeysJob b/lang/qt/src/RefreshKeysJob new file mode 100644 index 0000000..678d8d0 --- /dev/null +++ b/lang/qt/src/RefreshKeysJob @@ -0,0 +1 @@ +#include "qgpgme/refreshkeysjob.h" diff --git a/lang/qt/src/SignEncryptJob b/lang/qt/src/SignEncryptJob new file mode 100644 index 0000000..4075e49 --- /dev/null +++ b/lang/qt/src/SignEncryptJob @@ -0,0 +1 @@ +#include "qgpgme/signencryptjob.h" diff --git a/lang/qt/src/SignJob b/lang/qt/src/SignJob new file mode 100644 index 0000000..135cab1 --- /dev/null +++ b/lang/qt/src/SignJob @@ -0,0 +1 @@ +#include "qgpgme/signjob.h" diff --git a/lang/qt/src/SignKeyJob b/lang/qt/src/SignKeyJob new file mode 100644 index 0000000..094753c --- /dev/null +++ b/lang/qt/src/SignKeyJob @@ -0,0 +1 @@ +#include "qgpgme/signkeyjob.h" diff --git a/lang/qt/src/TofuPolicyJob b/lang/qt/src/TofuPolicyJob new file mode 100644 index 0000000..e379942 --- /dev/null +++ b/lang/qt/src/TofuPolicyJob @@ -0,0 +1 @@ +#include "qgpgme/tofupolicyjob.h" diff --git a/lang/qt/src/VerifyDetachedJob b/lang/qt/src/VerifyDetachedJob new file mode 100644 index 0000000..445fe27 --- /dev/null +++ b/lang/qt/src/VerifyDetachedJob @@ -0,0 +1 @@ +#include "qgpgme/verifydetachedjob.h" diff --git a/lang/qt/src/VerifyOpaqueJob b/lang/qt/src/VerifyOpaqueJob new file mode 100644 index 0000000..5292a70 --- /dev/null +++ b/lang/qt/src/VerifyOpaqueJob @@ -0,0 +1 @@ +#include "qgpgme/verifyopaquejob.h" diff --git a/lang/qt/src/WKSPublishJob b/lang/qt/src/WKSPublishJob new file mode 100644 index 0000000..747f7c8 --- /dev/null +++ b/lang/qt/src/WKSPublishJob @@ -0,0 +1 @@ +#include "qgpgme/wkspublishjob.h" diff --git a/lang/qt/src/abstractimportjob.h b/lang/qt/src/abstractimportjob.h new file mode 100644 index 0000000..572f203 --- /dev/null +++ b/lang/qt/src/abstractimportjob.h @@ -0,0 +1,64 @@ +/* + abstractimportjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2009 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_ABSTRACTIMPORTJOB_H__ +#define __KLEO_ABSTRACTIMPORTJOB_H__ + +#include "job.h" + +#include "qgpgme_export.h" + +namespace GpgME +{ +class Error; +class ImportResult; +} + +namespace QGpgME +{ + +class QGPGME_EXPORT AbstractImportJob : public Job +{ + Q_OBJECT +protected: + explicit AbstractImportJob(QObject *parent); +public: + ~AbstractImportJob(); + +Q_SIGNALS: + void result(const GpgME::ImportResult &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_IMPORTJOB_H__ diff --git a/lang/qt/src/adduseridjob.h b/lang/qt/src/adduseridjob.h new file mode 100644 index 0000000..1b5676f --- /dev/null +++ b/lang/qt/src/adduseridjob.h @@ -0,0 +1,84 @@ +/* + adduseridjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_ADDUSERIDJOB_H__ +#define __KLEO_ADDUSERIDJOB_H__ + +#include "job.h" + +#include <QtCore/QString> + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ + +/** + @short An abstract base class to asynchronously add UIDs to OpenPGP keys + + To use a AddUserIDJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the job with a call + to start(). This call might fail, in which case the AddUserIDJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the AddUserIDJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT AddUserIDJob : public Job +{ + Q_OBJECT +protected: + explicit AddUserIDJob(QObject *parent); +public: + ~AddUserIDJob(); + + /** + Starts the operation. \a key is the key to add the UID to. \a + name, \a email and \a comment are the components of the user id. + */ + virtual GpgME::Error start(const GpgME::Key &key, const QString &name, + const QString &email, const QString &comment = QString()) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_ADDUSERIDJOB_H__ diff --git a/lang/qt/src/changeexpiryjob.h b/lang/qt/src/changeexpiryjob.h new file mode 100644 index 0000000..7902cb8 --- /dev/null +++ b/lang/qt/src/changeexpiryjob.h @@ -0,0 +1,84 @@ +/* + changeexpiryjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CHANGEEXPIRYJOB_H__ +#define __KLEO_CHANGEEXPIRYJOB_H__ + +#include "job.h" + +namespace GpgME +{ +class Error; +class Key; +} + +class QDateTime; + +namespace QGpgME +{ + +/** + @short An abstract base class to change expiry asynchronously + + To use a ChangeExpiryJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the job with a call + to start(). This call might fail, in which case the ChangeExpiryJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ChangeExpiryJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ChangeExpiryJob : public Job +{ + Q_OBJECT +protected: + explicit ChangeExpiryJob(QObject *parent); +public: + ~ChangeExpiryJob(); + + /** + Starts the change-expiry operation. \a key is the key to change + the expiry of. \a expiry is the new expiry time. If \a expiry + is not valid, \a key is set to never expire. + */ + virtual GpgME::Error start(const GpgME::Key &key, const QDateTime &expiry) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_CHANGEEXPIRYJOB_H__ diff --git a/lang/qt/src/changeownertrustjob.h b/lang/qt/src/changeownertrustjob.h new file mode 100644 index 0000000..75c1163 --- /dev/null +++ b/lang/qt/src/changeownertrustjob.h @@ -0,0 +1,81 @@ +/* + changeownertrustjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CHANGEOWNERTRUST_H__ +#define __KLEO_CHANGEOWNERTRUST_H__ + +#include "job.h" + +#ifdef BUILDING_QGPGME +# include "key.h" +#else +# include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +/** + @short An abstract base class to change owner trust asynchronously + + To use a ChangeOwnerTrustJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the job with a call + to start(). This call might fail, in which case the ChangeOwnerTrustJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ChangeOwnerTrustJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ChangeOwnerTrustJob : public Job +{ + Q_OBJECT +protected: + explicit ChangeOwnerTrustJob(QObject *parent); +public: + ~ChangeOwnerTrustJob(); + + /** + Starts the change-owner trust operation. \a key is the key to change + the owner trust of . \a trust is the new trust level. + */ + virtual GpgME::Error start(const GpgME::Key &key, GpgME::Key::OwnerTrust trust) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_CHANGEOWNERTRUSTJOB_H__ diff --git a/lang/qt/src/changepasswdjob.h b/lang/qt/src/changepasswdjob.h new file mode 100644 index 0000000..7290898 --- /dev/null +++ b/lang/qt/src/changepasswdjob.h @@ -0,0 +1,82 @@ +/* + changepasswdjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2010 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CHANGEPASSWDJOB_H__ +#define __KLEO_CHANGEPASSWDJOB_H__ + +#include "job.h" + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ + +/** + @short An abstract base class to change a key's passphrase asynchronously + + To use a ChangePasswdJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the job with a call + to start(). This call might fail, in which case the ChangePasswdJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ChangePasswdJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ChangePasswdJob : public Job +{ + Q_OBJECT +protected: + explicit ChangePasswdJob(QObject *parent); +public: + ~ChangePasswdJob(); + + /** + Starts the passphrase-change operation. \a key is the key to + change the passphrase of. The passphrase is queried by the + backend directly, you cannot give it to the job beforehand. + */ + virtual GpgME::Error start(const GpgME::Key &key) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_CHANGEPASSWDJOB_H__ diff --git a/lang/qt/src/cryptoconfig.h b/lang/qt/src/cryptoconfig.h new file mode 100644 index 0000000..c3f0c7e --- /dev/null +++ b/lang/qt/src/cryptoconfig.h @@ -0,0 +1,400 @@ +/* + cryptoconfig.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef CRYPTOCONFIG_H +#define CRYPTOCONFIG_H + +#include "qgpgme_export.h" +#ifdef __cplusplus +/* we read this file from a C compiler, and are only interested in the + * enums... */ + +#include <QUrl> + +#include <vector> + +/* Start reading this file from the bottom up :) */ + +namespace QGpgME +{ + +/** + * Description of a single option + */ +class QGPGME_EXPORT CryptoConfigEntry +{ + +public: +#endif /* __cplusplus */ + /** + @li basic This option should always be offered to the user. + @li advanced This option may be offered to advanced users. + @li expert This option should only be offered to expert users. + */ + enum Level { Level_Basic = 0, + Level_Advanced = 1, + Level_Expert = 2 + }; + + /** + Type of the argument + @li ArgType_None The option is set or not set, but no argument. + @li ArgType_String An unformatted string. + @li ArgType_Int A signed integer number. + @li ArgType_UInt An unsigned integer number. + @li ArgType_Path A string that describes the pathname of a file. + The file does not necessarily need to exist. + Separated from string so that e.g. a FileDialog can be used. + @li ArgType_DirPath A string that describes the pathname of a directory. + The directory does not necessarily need to exist. + Separated from path so that e.g. a FileDialog can be used which only + allows directories to be selected. + @li ArgType_LDAPURL A LDAP URL + Separated from URL so that a more specific widget can be shown, hiding the url syntax + */ + enum ArgType { ArgType_None = 0, + ArgType_String = 1, + ArgType_Int = 2, + ArgType_UInt = 3, + ArgType_Path = 4, + /* Nr. 5 was URL historically. */ + ArgType_LDAPURL = 6, + ArgType_DirPath = 7, + + NumArgType + }; + +#ifdef __cplusplus + virtual ~CryptoConfigEntry() {} + + /** + * Return the internal name of this entry + */ + virtual QString name() const = 0; + + /** + * @return user-visible description of this entry + */ + virtual QString description() const = 0; + + /** + * @return "component/group/name" + */ + virtual QString path() const = 0; + + /** + * @return true if the argument is optional + */ + virtual bool isOptional() const = 0; + + /** + * @return true if the entry is readonly + */ + virtual bool isReadOnly() const = 0; + + /** + * @return true if the argument can be given multiple times + */ + virtual bool isList() const = 0; + + /** + * @return true if the argument can be changed at runtime + */ + virtual bool isRuntime() const = 0; + + /** + * User level + */ + virtual Level level() const = 0; + + /** + * Argument type + */ + virtual ArgType argType() const = 0; + + /** + * Return true if the option is set, i.e. different from default + */ + virtual bool isSet() const = 0; + + /** + * Return value as a bool (only allowed for ArgType_None) + */ + virtual bool boolValue() const = 0; + + /** + * Return value as a string (available for all argtypes) + * The returned string can be empty (explicitly set to empty) or null (not set). + */ + virtual QString stringValue() const = 0; + + /** + * Return value as a signed int + */ + virtual int intValue() const = 0; + + /** + * Return value as an unsigned int + */ + virtual unsigned int uintValue() const = 0; + + /** + * Return value as a URL (only meaningful for Path and URL argtypes) + */ + virtual QUrl urlValue() const = 0; + + /** + * Return number of times the option is set (only valid for ArgType_None, if isList()) + */ + virtual unsigned int numberOfTimesSet() const = 0; + + /** + * Return value as a list of signed ints + */ + virtual std::vector<int> intValueList() const = 0; + + /** + * Return value as a list of unsigned ints + */ + virtual std::vector<unsigned int> uintValueList() const = 0; + + /** + * Return value as a list of URLs (only meaningful for Path and URL argtypes, if isList()) + */ + virtual QList<QUrl> urlValueList() const = 0; + + /** + * Reset an option to its default value + */ + virtual void resetToDefault() = 0; + + /** + * Define whether the option is set or not (only allowed for ArgType_None) + * #### TODO: and for options with optional args + */ + virtual void setBoolValue(bool) = 0; + + /** + * Set string value (allowed for all argtypes) + */ + virtual void setStringValue(const QString &) = 0; + + /** + * Set a new signed int value + */ + virtual void setIntValue(int) = 0; + + /** + * Set a new unsigned int value + */ + virtual void setUIntValue(unsigned int) = 0; + + /** + * Set value as a URL (only meaningful for Path (if local) and URL argtypes) + */ + virtual void setURLValue(const QUrl &) = 0; + + /** + * Set the number of times the option is set (only valid for ArgType_None, if isList()) + */ + virtual void setNumberOfTimesSet(unsigned int) = 0; + + /** + * Set a new list of signed int values + */ + virtual void setIntValueList(const std::vector<int> &) = 0; + + /** + * Set a new list of unsigned int values + */ + virtual void setUIntValueList(const std::vector<unsigned int> &) = 0; + + /** + * Set value as a URL list (only meaningful for Path (if all URLs are local) and URL argtypes, if isList()) + */ + virtual void setURLValueList(const QList<QUrl> &) = 0; + + /** + * @return true if the value was changed + */ + virtual bool isDirty() const = 0; +}; + +/** + * Group containing a set of config options + */ +class QGPGME_EXPORT CryptoConfigGroup +{ + +public: + virtual ~CryptoConfigGroup() {} + + /** + * Return the internal name of this group + */ + virtual QString name() const = 0; + + /** + * Return the name of the icon for this group + */ + virtual QString iconName() const = 0; + + /** + * @return user-visible description of this group + */ + virtual QString description() const = 0; + + /** + * @return "component/group" + */ + virtual QString path() const = 0; + + /** + * User level + */ + virtual CryptoConfigEntry::Level level() const = 0; + + /** + * Returns the list of entries that are known by this group. + * + * @return list of group entry names. + **/ + virtual QStringList entryList() const = 0; + + /** + * @return the configuration object for a given entry in this group + * The object is owned by CryptoConfigGroup, don't delete it. + * Groups cannot be nested, so all entries returned here are pure entries, no groups. + */ + virtual CryptoConfigEntry *entry(const QString &name) const = 0; +}; + +/** + * Crypto config for one component (e.g. gpg-agent, dirmngr etc.) + */ +class QGPGME_EXPORT CryptoConfigComponent +{ + +public: + virtual ~CryptoConfigComponent() {} + + /** + * Return the internal name of this component + */ + virtual QString name() const = 0; + + /** + * Return the name of the icon for this component + */ + virtual QString iconName() const = 0; + + /** + * Return user-visible description of this component + */ + virtual QString description() const = 0; + + /** + * Returns the list of groups that are known about. + * + * @return list of group names. One of them can be "<nogroup>", which is the group where all + * "toplevel" options (belonging to no group) are. + */ + virtual QStringList groupList() const = 0; + + /** + * @return the configuration object for a given group + * The object is owned by CryptoConfigComponent, don't delete it. + */ + virtual CryptoConfigGroup *group(const QString &name) const = 0; + +}; + +/** + * Main interface to crypto configuration. + */ +class QGPGME_EXPORT CryptoConfig +{ + +public: + virtual ~CryptoConfig() {} + + /** + * Returns the list of known components (e.g. "gpg-agent", "dirmngr" etc.). + * Use @ref component() to retrieve more information about each one. + * @return list of component names. + **/ + virtual QStringList componentList() const = 0; + + /** + * @return the configuration object for a given component + * The object is owned by CryptoConfig, don't delete it. + */ + virtual CryptoConfigComponent *component(const QString &name) const = 0; + + /** + * Convenience method to get hold of a single configuration entry when + * its component, group and name are known. This can be used to read + * the value and/or to set a value to it. + * + * @return the configuration object for a single configuration entry, 0 if not found. + * The object is owned by CryptoConfig, don't delete it. + */ + CryptoConfigEntry *entry(const QString &componentName, const QString &groupName, const QString &entryName) const + { + const QGpgME::CryptoConfigComponent *comp = component(componentName); + const QGpgME::CryptoConfigGroup *group = comp ? comp->group(groupName) : 0; + return group ? group->entry(entryName) : 0; + } + + /** + * Write back changes + * + * @param runtime If this option is set, the changes will take effect at run-time, as + * far as this is possible. Otherwise, they will take effect at the next + * start of the respective backend programs. + */ + virtual void sync(bool runtime) = 0; + + /** + * Tells the CryptoConfig to discard any cached information, including + * all components, groups and entries. + * Call this to free some memory when you won't be using the object + * for some time. + * DON'T call this if you're holding pointers to components, groups or entries. + */ + virtual void clear() = 0; +}; + +} +#endif /* __cplusplus */ +#endif /* CRYPTOCONFIG_H */ diff --git a/lang/qt/src/dataprovider.cpp b/lang/qt/src/dataprovider.cpp new file mode 100644 index 0000000..533b67d --- /dev/null +++ b/lang/qt/src/dataprovider.cpp @@ -0,0 +1,282 @@ +/* dataprovider.cpp + Copyright (C) 2004 Klar�vdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + This file is part of QGPGME. + + QGPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + QGPGME is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with QGPGME; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +// -*- c++ -*- + +#include <dataprovider.h> + +#include <error.h> + +#include <QIODevice> +#include <QProcess> + +#include <cstdio> +#include <cstring> +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +// +// +// QByteArrayDataProvider +// +// + +static bool resizeAndInit(QByteArray &ba, size_t newSize) +{ + const size_t oldSize = ba.size(); + ba.resize(newSize); + const bool ok = (newSize == static_cast<size_t>(ba.size())); + if (ok) { + memset(ba.data() + oldSize, 0, newSize - oldSize); + } + return ok; +} + +QByteArrayDataProvider::QByteArrayDataProvider() + : GpgME::DataProvider(), mOff(0) {} + +QByteArrayDataProvider::QByteArrayDataProvider(const QByteArray &initialData) + : GpgME::DataProvider(), mArray(initialData), mOff(0) {} + +QByteArrayDataProvider::~QByteArrayDataProvider() {} + +ssize_t QByteArrayDataProvider::read(void *buffer, size_t bufSize) +{ +#ifndef NDEBUG + //qDebug( "QByteArrayDataProvider::read( %p, %d )", buffer, bufSize ); +#endif + if (bufSize == 0) { + return 0; + } + if (!buffer) { + Error::setSystemError(GPG_ERR_EINVAL); + return -1; + } + if (mOff >= mArray.size()) { + return 0; // EOF + } + size_t amount = qMin(bufSize, static_cast<size_t>(mArray.size() - mOff)); + assert(amount > 0); + memcpy(buffer, mArray.data() + mOff, amount); + mOff += amount; + return amount; +} + +ssize_t QByteArrayDataProvider::write(const void *buffer, size_t bufSize) +{ +#ifndef NDEBUG + //qDebug( "QByteArrayDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) ); +#endif + if (bufSize == 0) { + return 0; + } + if (!buffer) { + Error::setSystemError(GPG_ERR_EINVAL); + return -1; + } + if (mOff >= mArray.size()) { + resizeAndInit(mArray, mOff + bufSize); + } + if (mOff >= mArray.size()) { + Error::setSystemError(GPG_ERR_EIO); + return -1; + } + assert(bufSize <= static_cast<size_t>(mArray.size()) - mOff); + memcpy(mArray.data() + mOff, buffer, bufSize); + mOff += bufSize; + return bufSize; +} + +off_t QByteArrayDataProvider::seek(off_t offset, int whence) +{ +#ifndef NDEBUG + //qDebug( "QByteArrayDataProvider::seek( %d, %d )", int(offset), whence ); +#endif + int newOffset = mOff; + switch (whence) { + case SEEK_SET: + newOffset = offset; + break; + case SEEK_CUR: + newOffset += offset; + break; + case SEEK_END: + newOffset = mArray.size() + offset; + break; + default: + Error::setSystemError(GPG_ERR_EINVAL); + return (off_t) - 1; + } + return mOff = newOffset; +} + +void QByteArrayDataProvider::release() +{ +#ifndef NDEBUG + //qDebug( "QByteArrayDataProvider::release()" ); +#endif + mArray = QByteArray(); +} + +// +// +// QIODeviceDataProvider +// +// + +QIODeviceDataProvider::QIODeviceDataProvider(const std::shared_ptr<QIODevice> &io) + : GpgME::DataProvider(), + mIO(io), + mErrorOccurred(false), + mHaveQProcess(qobject_cast<QProcess *>(io.get())) +{ + assert(mIO); +} + +QIODeviceDataProvider::~QIODeviceDataProvider() {} + +bool QIODeviceDataProvider::isSupported(Operation op) const +{ + const QProcess *const proc = qobject_cast<QProcess *>(mIO.get()); + bool canRead = true; + if (proc) { + canRead = proc->readChannel() == QProcess::StandardOutput; + } + + switch (op) { + case Read: return mIO->isReadable() && canRead; + case Write: return mIO->isWritable(); + case Seek: return !mIO->isSequential(); + case Release: return true; + default: return false; + } +} + +static qint64 blocking_read(const std::shared_ptr<QIODevice> &io, char *buffer, qint64 maxSize) +{ + while (!io->bytesAvailable()) { + if (!io->waitForReadyRead(-1)) { + if (const QProcess *const p = qobject_cast<QProcess *>(io.get())) { + if (p->error() == QProcess::UnknownError && + p->exitStatus() == QProcess::NormalExit && + p->exitCode() == 0) { + return 0; + } else { + Error::setSystemError(GPG_ERR_EIO); + return -1; + } + } else { + return 0; // assume EOF (loses error cases :/ ) + } + } + } + return io->read(buffer, maxSize); +} + +ssize_t QIODeviceDataProvider::read(void *buffer, size_t bufSize) +{ +#ifndef NDEBUG + //qDebug( "QIODeviceDataProvider::read( %p, %lu )", buffer, bufSize ); +#endif + if (bufSize == 0) { + return 0; + } + if (!buffer) { + Error::setSystemError(GPG_ERR_EINVAL); + return -1; + } + const qint64 numRead = mHaveQProcess + ? blocking_read(mIO, static_cast<char *>(buffer), bufSize) + : mIO->read(static_cast<char *>(buffer), bufSize); + + //workaround: some QIODevices (known example: QProcess) might not return 0 (EOF), but immediately -1 when finished. If no + //errno is set, gpgme doesn't detect the error and loops forever. So return 0 on the very first -1 in case errno is 0 + + ssize_t rc = numRead; + if (numRead < 0 && !Error::hasSystemError()) { + if (mErrorOccurred) { + Error::setSystemError(GPG_ERR_EIO); + } else { + rc = 0; + } + } + if (numRead < 0) { + mErrorOccurred = true; + } + return rc; +} + +ssize_t QIODeviceDataProvider::write(const void *buffer, size_t bufSize) +{ +#ifndef NDEBUG + //qDebug( "QIODeviceDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) ); +#endif + if (bufSize == 0) { + return 0; + } + if (!buffer) { + Error::setSystemError(GPG_ERR_EINVAL); + return -1; + } + + return mIO->write(static_cast<const char *>(buffer), bufSize); +} + +off_t QIODeviceDataProvider::seek(off_t offset, int whence) +{ +#ifndef NDEBUG + //qDebug( "QIODeviceDataProvider::seek( %d, %d )", int(offset), whence ); +#endif + if (mIO->isSequential()) { + Error::setSystemError(GPG_ERR_ESPIPE); + return (off_t) - 1; + } + qint64 newOffset = mIO->pos(); + switch (whence) { + case SEEK_SET: + newOffset = offset; + break; + case SEEK_CUR: + newOffset += offset; + break; + case SEEK_END: + newOffset = mIO->size() + offset; + break; + default: + Error::setSystemError(GPG_ERR_EINVAL); + return (off_t) - 1; + } + if (!mIO->seek(newOffset)) { + Error::setSystemError(GPG_ERR_EINVAL); + return (off_t) - 1; + } + return newOffset; +} + +void QIODeviceDataProvider::release() +{ +#ifndef NDEBUG + //qDebug( "QIODeviceDataProvider::release()" ); +#endif + mIO->close(); +} diff --git a/lang/qt/src/dataprovider.h b/lang/qt/src/dataprovider.h new file mode 100644 index 0000000..337f264 --- /dev/null +++ b/lang/qt/src/dataprovider.h @@ -0,0 +1,95 @@ +/* dataprovider.h + Copyright (C) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + This file is part of QGPGME. + + QGPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + QGPGME is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with QGPGME; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +// -*- c++ -*- +#ifndef __QGPGME_DATAPROVIDER_H__ +#define __QGPGME_DATAPROVIDER_H__ + +#include "qgpgme_export.h" +#include <interfaces/dataprovider.h> +#include <memory> + +#include <QtCore/QByteArray> + + +class QIODevice; + +namespace QGpgME +{ + +class QGPGME_EXPORT QByteArrayDataProvider : public GpgME::DataProvider +{ +public: + QByteArrayDataProvider(); + explicit QByteArrayDataProvider(const QByteArray &initialData); + ~QByteArrayDataProvider(); + + const QByteArray &data() const + { + return mArray; + } + +private: + // these shall only be accessed through the dataprovider + // interface, where they're public: + bool isSupported(Operation) const + { + return true; + } + ssize_t read(void *buffer, size_t bufSize); + ssize_t write(const void *buffer, size_t bufSize); + off_t seek(off_t offset, int whence); + void release(); + +private: + QByteArray mArray; + off_t mOff; +}; + +class QGPGME_EXPORT QIODeviceDataProvider : public GpgME::DataProvider +{ +public: + explicit QIODeviceDataProvider(const std::shared_ptr<QIODevice> &initialData); + ~QIODeviceDataProvider(); + + const std::shared_ptr<QIODevice> &ioDevice() const + { + return mIO; + } + +private: + // these shall only be accessed through the dataprovider + // interface, where they're public: + bool isSupported(Operation) const; + ssize_t read(void *buffer, size_t bufSize); + ssize_t write(const void *buffer, size_t bufSize); + off_t seek(off_t offset, int whence); + void release(); + +private: + const std::shared_ptr<QIODevice> mIO; + bool mErrorOccurred : 1; + bool mHaveQProcess : 1; +}; + +} // namespace QGpgME + +#endif diff --git a/lang/qt/src/decryptjob.h b/lang/qt/src/decryptjob.h new file mode 100644 index 0000000..c4fc86f --- /dev/null +++ b/lang/qt/src/decryptjob.h @@ -0,0 +1,100 @@ +/* + decryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DECRYPTJOB_H__ +#define __KLEO_DECRYPTJOB_H__ + +#include "job.h" + +#include <memory> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class DecryptionResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous decrypters + + To use a DecryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the decryption with a + call to start(). This call might fail, in which case the + DecryptJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the DecryptJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT DecryptJob : public Job +{ + Q_OBJECT +protected: + explicit DecryptJob(QObject *parent); +public: + ~DecryptJob(); + + /** + Starts the decryption operation. \a cipherText is the data to + decrypt. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &cipherText) = 0; + + /*! + \overload + + If \a plainText is non-null, the plaintext is written + there. Otherwise, it will be delivered in the second argument + of result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0; + + virtual GpgME::DecryptionResult exec(const QByteArray &cipherText, + QByteArray &plainText) = 0; + +Q_SIGNALS: + void result(const GpgME::DecryptionResult &result, const QByteArray &plainText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_DECRYPTJOB_H__ diff --git a/lang/qt/src/decryptverifyjob.h b/lang/qt/src/decryptverifyjob.h new file mode 100644 index 0000000..97af008 --- /dev/null +++ b/lang/qt/src/decryptverifyjob.h @@ -0,0 +1,105 @@ +/* + decryptverifyjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DECRYPTVERIFYJOB_H__ +#define __KLEO_DECRYPTVERIFYJOB_H__ + +#include "job.h" + +#include <memory> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class DecryptionResult; +class VerificationResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous combined decrypters and verifiers + + To use a DecryptVerifyJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the operation with a + call to start(). This call might fail, in which case the + DecryptVerifyJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the DecryptVerifyJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT DecryptVerifyJob : public Job +{ + Q_OBJECT +protected: + explicit DecryptVerifyJob(QObject *parent); +public: + ~DecryptVerifyJob(); + + /** + Starts the combined decryption and verification operation. + \a cipherText is the data to decrypt and later verify. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &cipherText) = 0; + + /*! + \overload + + If \a plainText is non-null, the plaintext is written + there. Otherwise, it will be delivered in the third argument + of result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0; + + /** Synchronous equivalent of start() */ + virtual std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> + exec(const QByteArray &cipherText, QByteArray &plainText) = 0; + +Q_SIGNALS: + void result(const GpgME::DecryptionResult &decryptionresult, + const GpgME::VerificationResult &verificationresult, + const QByteArray &plainText, const QString &auditLogAsHtml = QString(), + const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_DECRYPTVERIFYJOB_H__ diff --git a/lang/qt/src/defaultkeygenerationjob.cpp b/lang/qt/src/defaultkeygenerationjob.cpp new file mode 100644 index 0000000..8257a72 --- /dev/null +++ b/lang/qt/src/defaultkeygenerationjob.cpp @@ -0,0 +1,125 @@ +/* defaultkeygenerationjob.cpp + + Copyright (c) 2016 Klarälvdalens Datakonsult AB + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "defaultkeygenerationjob.h" +#include "protocol.h" +#include "keygenerationjob.h" + +#include <QPointer> +#include <QEvent> + +using namespace QGpgME; + +namespace QGpgME { + +class DefaultKeyGenerationJob::Private +{ +public: + Private() + {} + + ~Private() + { + if (job) { + job->deleteLater(); + } + } + + QPointer<KeyGenerationJob> job; +}; +} + + +DefaultKeyGenerationJob::DefaultKeyGenerationJob(QObject* parent) + : Job(parent) + , d(new DefaultKeyGenerationJob::Private()) +{ +} + +DefaultKeyGenerationJob::~DefaultKeyGenerationJob() +{ + delete d; +} + +QString DefaultKeyGenerationJob::auditLogAsHtml() const +{ + return d->job ? d->job->auditLogAsHtml() : QString(); +} + +GpgME::Error DefaultKeyGenerationJob::auditLogError() const +{ + return d->job ? d->job->auditLogError() : GpgME::Error(); +} + +void DefaultKeyGenerationJob::slotCancel() +{ + if (d->job) { + d->job->slotCancel(); + } +} + +GpgME::Error DefaultKeyGenerationJob::start(const QString &email, const QString &name) +{ + const QString args = QStringLiteral("<GnupgKeyParms format=\"internal\">\n" + "%ask-passphrase\n" + "key-type: RSA\n" + "key-length: 2048\n" + "key-usage: sign\n" + "subkey-type: RSA\n" + "subkey-length: 2048\n" + "subkey-usage: encrypt\n" + "name-email: %1\n" + "name-real: %2\n" + "</GnupgKeyParms>").arg(email, name); + + d->job = openpgp()->keyGenerationJob(); + d->job->installEventFilter(this); + connect(d->job, &KeyGenerationJob::result, + this, &DefaultKeyGenerationJob::result); + connect(d->job, &KeyGenerationJob::done, + this, &DefaultKeyGenerationJob::done); + connect(d->job, &KeyGenerationJob::done, + this, &QObject::deleteLater); + return d->job->start(args); +} + +bool DefaultKeyGenerationJob::eventFilter(QObject *watched, QEvent *event) +{ + // Intercept the KeyGenerationJob's deferred delete event. We want the job + // to live at least as long as we do so we can delegate calls to it. We will + // delete the job manually afterwards. + if (watched == d->job && event->type() == QEvent::DeferredDelete) { + return true; + } + + return Job::eventFilter(watched, event); +} + +#include "defaultkeygenerationjob.moc" diff --git a/lang/qt/src/defaultkeygenerationjob.h b/lang/qt/src/defaultkeygenerationjob.h new file mode 100644 index 0000000..5b7334c --- /dev/null +++ b/lang/qt/src/defaultkeygenerationjob.h @@ -0,0 +1,76 @@ +/* defaultkeygenerationjob.h + + Copyright (c) 2016 Klarälvdalens Datakonsult AB + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef QGPGME_DEFAULTKEYGENERATION_H +#define QGPGME_DEFAULTKEYGENERATION_H + +#include "job.h" + +#include "qgpgme_export.h" + +namespace GpgME { +class KeyGenerationResult; +} + +namespace QGpgME{ + +/** + * Generates a PGP RSA/2048 bit key pair for given name and email address. + */ +class QGPGME_EXPORT DefaultKeyGenerationJob : public Job +{ + Q_OBJECT +public: + explicit DefaultKeyGenerationJob(QObject *parent = Q_NULLPTR); + ~DefaultKeyGenerationJob(); + + GpgME::Error start(const QString &email, const QString &name); + + QString auditLogAsHtml() const Q_DECL_OVERRIDE; + GpgME::Error auditLogError() const Q_DECL_OVERRIDE; + + +public Q_SLOTS: + void slotCancel() Q_DECL_OVERRIDE; + +Q_SIGNALS: + void result(const GpgME::KeyGenerationResult &result, const QByteArray &pubkeyData, + const QString &auditLogAsHtml, const GpgME::Error &auditLogError); + +protected: + bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE; + +private: + class Private; + Private * const d; +}; + +} + +#endif diff --git a/lang/qt/src/deletejob.h b/lang/qt/src/deletejob.h new file mode 100644 index 0000000..f8479b1 --- /dev/null +++ b/lang/qt/src/deletejob.h @@ -0,0 +1,83 @@ +/* + deletejob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DELETEJOB_H__ +#define __KLEO_DELETEJOB_H__ + +#include "qgpgme_export.h" +#include "job.h" + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous deleters + + To use a DeleteJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the delete with a call + to start(). This call might fail, in which case the DeleteJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the DeleteJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT DeleteJob : public Job +{ + Q_OBJECT +protected: + explicit DeleteJob(QObject *parent); +public: + ~DeleteJob(); + + /** + Starts the delete operation. \a key represents the key to + delete, \a allowSecretKeyDeletion specifies if a key may also + be deleted if the secret key part is available, too. + */ + virtual GpgME::Error start(const GpgME::Key &key, bool allowSecretKeyDeletion = false) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_DELETEJOB_H__ diff --git a/lang/qt/src/downloadjob.h b/lang/qt/src/downloadjob.h new file mode 100644 index 0000000..09eecf6 --- /dev/null +++ b/lang/qt/src/downloadjob.h @@ -0,0 +1,103 @@ +/* + downloadjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DOWNLOADJOB_H__ +#define __KLEO_DOWNLOADJOB_H__ + +#include "job.h" + +#include <QtCore/QByteArray> + +#include <memory> + +namespace GpgME +{ +class Error; +} + +class QStringList; +class QIODevice; +class QByteArray; + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous downloaders + + To use a DownloadJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the download with a call + to start(). This call might fail, in which case the DownloadJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the DownloadJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT DownloadJob : public Job +{ + Q_OBJECT +protected: + explicit DownloadJob(QObject *parent); +public: + ~DownloadJob(); + + /** + Starts the download operation. \a fingerprint is the + fingerprint of the key to download. If \a fingerprint is empty, + contains only whitespace or anything other than a fingerprint, + the result is undefined. + + Output is written to \a keyData, if given. Otherwise, it is + passed as the second argument of result(). + */ + virtual GpgME::Error start(const QByteArray &fingerprint, + const std::shared_ptr<QIODevice> &keyData) = 0; + + /** + Starts the download operation. \a fingerprints is a list of + fingerprints used to specify the list of keys downloaded. Empty + patterns are ignored. If \a fingerprints is empty, contains + only empty strings or anything other than fingerprints, the + result is undefined. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QStringList &fingerprints) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QByteArray &keyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_DOWNLOADJOB_H__ diff --git a/lang/qt/src/encryptjob.h b/lang/qt/src/encryptjob.h new file mode 100644 index 0000000..4ff9c82 --- /dev/null +++ b/lang/qt/src/encryptjob.h @@ -0,0 +1,136 @@ +/* + encryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_ENCRYPTJOB_H__ +#define __KLEO_ENCRYPTJOB_H__ + +#include "job.h" + +#include <memory> +#include <vector> + +#ifdef BUILDING_QGPGME +# include "context.h" +#else +# include <gpgme++/context.h> +#endif + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class Key; +class EncryptionResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous encrypters + + To use a EncryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the encryption with a + call to start(). This call might fail, in which case the + EncryptJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the EncryptJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT EncryptJob : public Job +{ + Q_OBJECT +protected: + explicit EncryptJob(QObject *parent); +public: + ~EncryptJob(); + + /** + Starts the encryption operation. \a recipients is the a list of + keys to encrypt \a plainText to. Empty (null) keys are + ignored. If \a recipients is empty, performs symmetric + (passphrase) encryption. + + If \a alwaysTrust is true, validity checking for the keys will + not be performed, but full validity assumed for all keys + without further checks. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, bool alwaysTrust = false) = 0; + + /*! + \overload + + If \a cipherText is non-null, the ciphertext is written + there. Otherwise, it will be delivered in the second argument of + result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(), + bool alwaysTrust = false) = 0; + + virtual GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, + bool alwaysTrust, QByteArray &cipherText) = 0; + /*! + This is a hack to request BASE64 output (instead of whatever + comes out normally). + */ + virtual void setOutputIsBase64Encoded(bool) = 0; + + /** Like start but with an additional argument for EncryptionFlags for + * more flexibility. */ + virtual void start(const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(), + const GpgME::Context::EncryptionFlags flags = GpgME::Context::None) = 0; + + /** Like exec but with an additional argument for EncryptionFlags for + * more flexibility. */ + virtual GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, + const GpgME::Context::EncryptionFlags flags, QByteArray &cipherText) = 0; +Q_SIGNALS: + void result(const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_ENCRYPTJOB_H__ diff --git a/lang/qt/src/exportjob.h b/lang/qt/src/exportjob.h new file mode 100644 index 0000000..583d4c0 --- /dev/null +++ b/lang/qt/src/exportjob.h @@ -0,0 +1,87 @@ +/* + exportjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_EXPORTJOB_H__ +#define __QGPGME_EXPORTJOB_H__ + +#include "qgpgme_export.h" +#include "job.h" + +#include <QtCore/QByteArray> + +namespace GpgME +{ +class Error; +} + +class QStringList; + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous exporters + + To use a ExportJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the export with a call + to start(). This call might fail, in which case the ExportJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ExportJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ExportJob : public Job +{ + Q_OBJECT +protected: + explicit ExportJob(QObject *parent); +public: + ~ExportJob(); + + /** + Starts the export operation. \a patterns is a list of patterns + used to restrict the list of keys exported. Empty patterns are + ignored. If \a patterns is empty or contains only empty + strings, all available keys are exported. + */ + virtual GpgME::Error start(const QStringList &patterns) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QByteArray &keyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __QGPGME_EXPORTJOB_H__ diff --git a/lang/qt/src/gpgme_backend_debug.cpp b/lang/qt/src/gpgme_backend_debug.cpp new file mode 100644 index 0000000..6dfb313 --- /dev/null +++ b/lang/qt/src/gpgme_backend_debug.cpp @@ -0,0 +1,10 @@ +// This file is autogenerated by CMake: DO NOT EDIT + +#include "gpgme_backend_debug.h" + + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) +Q_LOGGING_CATEGORY(GPGPME_BACKEND_LOG, "log_gpgme_backend", QtWarningMsg) +#else +Q_LOGGING_CATEGORY(GPGPME_BACKEND_LOG, "log_gpgme_backend") +#endif diff --git a/lang/qt/src/gpgme_backend_debug.h b/lang/qt/src/gpgme_backend_debug.h new file mode 100644 index 0000000..5ac93db --- /dev/null +++ b/lang/qt/src/gpgme_backend_debug.h @@ -0,0 +1,11 @@ +// This file is autogenerated by CMake: DO NOT EDIT + +#ifndef GPGPME_BACKEND_LOG_H +#define GPGPME_BACKEND_LOG_H + +#include <QLoggingCategory> + +Q_DECLARE_LOGGING_CATEGORY(GPGPME_BACKEND_LOG) + + +#endif diff --git a/lang/qt/src/hierarchicalkeylistjob.h b/lang/qt/src/hierarchicalkeylistjob.h new file mode 100644 index 0000000..2ec187d --- /dev/null +++ b/lang/qt/src/hierarchicalkeylistjob.h @@ -0,0 +1,125 @@ +/* + hierarchicalkeylistjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_HIERARCHICALKEYLISTJOB_H__ +#define __KLEO_HIERARCHICALKEYLISTJOB_H__ + +#include "qgpgme_export.h" +#include "keylistjob.h" +#include "cryptobackend.h" + +#ifdef BUILDING_QGPGME +# include "keylistresult.h" +#else +#include <gpgme++/keylistresult.h> +#endif + +#include <QPointer> + +#include <set> + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ +class KeyListJob; +} + +namespace QGpgME +{ + +/** + @short A convenience job that additionally fetches all available issuers. + + To use a HierarchicalKeyListJob, pass it a CryptoBackend + implementation, connect the progress() and result() signals to + suitable slots and then start the keylisting with a call to + start(). This call might fail, in which case the + HierarchicalKeyListJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the HierarchicalKeyListJob will + schedule its own destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT HierarchicalKeyListJob : public KeyListJob +{ + Q_OBJECT +public: + explicit HierarchicalKeyListJob(const Protocol *protocol, + bool remote = false, bool includeSigs = false, + bool validating = false); + ~HierarchicalKeyListJob(); + + /** + Starts the keylist operation. \a patterns is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. \a patterns must not be empty or contain only empty + patterns; use the normal KeyListJob for a full listing. + + The \a secretOnly parameter is ignored by + HierarchicalKeyListJob and must be set to false. + */ + GpgME::Error start(const QStringList &patterns, bool secretOnly = false) Q_DECL_OVERRIDE; + + GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly, + std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE; + +private Q_SLOTS: + void slotResult(const GpgME::KeyListResult &); + void slotNextKey(const GpgME::Key &key); + /* from Job */ + void slotCancel() Q_DECL_OVERRIDE; + +private: + GpgME::Error startAJob(); + +private: + const Protocol *const mProtocol; + const bool mRemote; + const bool mIncludeSigs; + const bool mValidating; + bool mTruncated; + std::set<QString> mSentSet; // keys already sent (prevent duplicates even if the backend should return them) + std::set<QString> mScheduledSet; // keys already scheduled (by starting a job for them) + std::set<QString> mNextSet; // keys to schedule for the next iteraton + GpgME::KeyListResult mIntermediateResult; + QPointer<KeyListJob> mJob; +}; + +} + +#endif // __KLEO_HIERARCHICALKEYLISTJOB_H__ diff --git a/lang/qt/src/importfromkeyserverjob.h b/lang/qt/src/importfromkeyserverjob.h new file mode 100644 index 0000000..f548ea7 --- /dev/null +++ b/lang/qt/src/importfromkeyserverjob.h @@ -0,0 +1,84 @@ +/* + importfromkeyserverjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_IMPORTFROMKEYSERVERJOB_H__ +#define __KLEO_IMPORTFROMKEYSERVERJOB_H__ + +#include "abstractimportjob.h" +#include "qgpgme_export.h" + +namespace GpgME +{ +class Key; +class Error; +class ImportResult; +} + +#include <vector> + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous keyserver-importers + + To use a ImportJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the import with a call + to start(). This call might fail, in which case the ImportJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ImportJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ImportFromKeyserverJob : public AbstractImportJob +{ + Q_OBJECT +protected: + explicit ImportFromKeyserverJob(QObject *parent); +public: + ~ImportFromKeyserverJob(); + + /** + Starts the importing operation. \a keyData contains the data to + import from. + */ + virtual GpgME::Error start(const std::vector<GpgME::Key> &keys) = 0; + + virtual GpgME::ImportResult exec(const std::vector<GpgME::Key> &keys) = 0; +}; + +} + +#endif // __KLEO_IMPORTFROMKEYSERVERJOB_H__ diff --git a/lang/qt/src/importjob.h b/lang/qt/src/importjob.h new file mode 100644 index 0000000..5c7b24d --- /dev/null +++ b/lang/qt/src/importjob.h @@ -0,0 +1,83 @@ +/* + importjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_IMPORTJOB_H__ +#define __KLEO_IMPORTJOB_H__ + +#include "abstractimportjob.h" +#include "qgpgme_export.h" + +#include <QtCore/QByteArray> + +namespace GpgME +{ +class Error; +class ImportResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous importers + + To use a ImportJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the import with a call + to start(). This call might fail, in which case the ImportJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ImportJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT ImportJob : public AbstractImportJob +{ + Q_OBJECT +protected: + explicit ImportJob(QObject *parent); +public: + ~ImportJob(); + + /** + Starts the importing operation. \a keyData contains the data to + import from. + */ + virtual GpgME::Error start(const QByteArray &keyData) = 0; + + virtual GpgME::ImportResult exec(const QByteArray &keyData) = 0; +}; + +} + +#endif // __KLEO_IMPORTJOB_H__ diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp new file mode 100644 index 0000000..8936ea5 --- /dev/null +++ b/lang/qt/src/job.cpp @@ -0,0 +1,159 @@ +/* + job.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "job.h" + +#include "keylistjob.h" +#include "listallkeysjob.h" +#include "encryptjob.h" +#include "decryptjob.h" +#include "decryptverifyjob.h" +#include "signjob.h" +#include "signkeyjob.h" +#include "signencryptjob.h" +#include "verifydetachedjob.h" +#include "verifyopaquejob.h" +#include "keygenerationjob.h" +#include "importjob.h" +#include "importfromkeyserverjob.h" +#include "exportjob.h" +#include "changeexpiryjob.h" +#include "changeownertrustjob.h" +#include "changepasswdjob.h" +#include "downloadjob.h" +#include "deletejob.h" +#include "refreshkeysjob.h" +#include "adduseridjob.h" +#include "specialjob.h" +#include "keyformailboxjob.h" +#include "wkspublishjob.h" +#include "tofupolicyjob.h" + +#include <QCoreApplication> +#include <QDebug> + +#include <gpg-error.h> + +QGpgME::Job::Job(QObject *parent) + : QObject(parent) +{ + if (QCoreApplication *app = QCoreApplication::instance()) { + connect(app, &QCoreApplication::aboutToQuit, this, &Job::slotCancel); + } +} + +QGpgME::Job::~Job() +{ + +} + +QString QGpgME::Job::auditLogAsHtml() const +{ + qDebug() << "QGpgME::Job::auditLogAsHtml() should be reimplemented in Kleo::Job subclasses!"; + return QString(); +} + +GpgME::Error QGpgME::Job::auditLogError() const +{ + qDebug() << "QGpgME::Job::auditLogError() should be reimplemented in Kleo::Job subclasses!"; + return GpgME::Error::fromCode(GPG_ERR_NOT_IMPLEMENTED); +} + +bool QGpgME::Job::isAuditLogSupported() const +{ + return auditLogError().code() != GPG_ERR_NOT_IMPLEMENTED; +} + +#define make_job_subclass_ext(x,y) \ + QGpgME::x::x( QObject * parent ) : y( parent ) {} \ + QGpgME::x::~x() {} + +#define make_job_subclass(x) make_job_subclass_ext(x,Job) + +make_job_subclass(KeyListJob) +make_job_subclass(ListAllKeysJob) +make_job_subclass(EncryptJob) +make_job_subclass(DecryptJob) +make_job_subclass(DecryptVerifyJob) +make_job_subclass(SignJob) +make_job_subclass(SignEncryptJob) +make_job_subclass(SignKeyJob) +make_job_subclass(VerifyDetachedJob) +make_job_subclass(VerifyOpaqueJob) +make_job_subclass(KeyGenerationJob) +make_job_subclass(AbstractImportJob) +make_job_subclass_ext(ImportJob, AbstractImportJob) +make_job_subclass_ext(ImportFromKeyserverJob, AbstractImportJob) +make_job_subclass(ExportJob) +make_job_subclass(ChangeExpiryJob) +make_job_subclass(ChangeOwnerTrustJob) +make_job_subclass(ChangePasswdJob) +make_job_subclass(DownloadJob) +make_job_subclass(DeleteJob) +make_job_subclass(RefreshKeysJob) +make_job_subclass(AddUserIDJob) +make_job_subclass(SpecialJob) +make_job_subclass(KeyForMailboxJob) +make_job_subclass(WKSPublishJob) +make_job_subclass(TofuPolicyJob) + +#undef make_job_subclass + +#include "job.moc" + +#include "keylistjob.moc" +#include "listallkeysjob.moc" +#include "encryptjob.moc" +#include "decryptjob.moc" +#include "decryptverifyjob.moc" +#include "signjob.moc" +#include "signencryptjob.moc" +#include "signkeyjob.moc" +#include "verifydetachedjob.moc" +#include "verifyopaquejob.moc" +#include "keygenerationjob.moc" +#include "abstractimportjob.moc" +#include "importjob.moc" +#include "importfromkeyserverjob.moc" +#include "exportjob.moc" +#include "changeexpiryjob.moc" +#include "changeownertrustjob.moc" +#include "changepasswdjob.moc" +#include "downloadjob.moc" +#include "deletejob.moc" +#include "refreshkeysjob.moc" +#include "adduseridjob.moc" +#include "specialjob.moc" +#include "keyformailboxjob.moc" +#include "wkspublishjob.moc" +#include "tofupolicyjob.moc" diff --git a/lang/qt/src/job.h b/lang/qt/src/job.h new file mode 100644 index 0000000..5767729 --- /dev/null +++ b/lang/qt/src/job.h @@ -0,0 +1,92 @@ +/* + job.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_JOB_H__ +#define __KLEO_JOB_H__ + +#include "qgpgme_export.h" + +#include <QObject> +#include <QString> + +#ifdef BUILDING_QGPGME +# include "error.h" +#else +# include <gpgme++/error.h> +#endif + +class QWidget; + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous crypto operations + + During the operation, you might receive progress updates through + the progress() signal as they arrive, but an implementation is + free to not send progress information. You should show a busy + progressbar until the first progress() signal is received. + + The done() signal is emitted _before_ the result() signals of + subclasses and should be used to hide and/or reset progress bars, + not to learn of the end of the operation. Use the result() + signals for that. + + To cancel the operation, simply call slotCancel(). The result() + signal of subclasses will still be emitted, though, and will + carry the information that the operation was canceled. +*/ +class QGPGME_EXPORT Job : public QObject +{ + Q_OBJECT +protected: + explicit Job(QObject *parent); +public: + ~Job(); + + virtual QString auditLogAsHtml() const; + virtual GpgME::Error auditLogError() const; + bool isAuditLogSupported() const; + +public Q_SLOTS: + virtual void slotCancel() = 0; + +Q_SIGNALS: + void progress(const QString &what, int current, int total); + void done(); +}; + +} + +#endif // __KLEO_JOB_H__ diff --git a/lang/qt/src/keyformailboxjob.h b/lang/qt/src/keyformailboxjob.h new file mode 100644 index 0000000..d8b6c6b --- /dev/null +++ b/lang/qt/src/keyformailboxjob.h @@ -0,0 +1,106 @@ +/* + keyformailboxjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef __KLEO_KEYFORMAILBOX_H__ +#define __KLEO_KEYFORMAILBOX_H__ + +#include <QString> + +#include "job.h" + +#ifdef BUILDING_QGPGME +# include "key.h" +#else +# include <gpgme++/key.h> +#endif + +namespace GpgME +{ +class Error; +class KeyListResult; +} + +namespace QGpgME +{ + +/** + @short Get the best key to use for a Mailbox + + To use the keyformailboxjob, first obtain an instance from the + CryptoBackend and either exec it or start and + conncet the result() signals to a suitable slot. + The job will be automatically deleted in which + case the KeylistJob instance will have schedules it's own + destruction with a call to QObject::deleteLater(). + + The best key is defined as the key with a UID that has an + E-Mail that matches the mailbox provided. If multiple + keys are found the one with the highest validity is returned. + + After result() is emitted, the + KeyListJob will schedule it's own destruction by calling + QObject::deleteLater(). +*/ +class QGPGME_EXPORT KeyForMailboxJob: public Job +{ + Q_OBJECT +protected: + explicit KeyForMailboxJob(QObject *parent); + +public: + ~KeyForMailboxJob(); + + /** + Starts the operation. \a mailbox is the mailbox to + look for. + + The result is the same as for the LocateKeysJob. + + If \a canEncrypt is true, only keys that have a subkey for encryption + usage are returned. Use this if you need to select a + key for signing. + */ + virtual GpgME::Error start(const QString &mailbox, bool canEncrypt = true) = 0; + + virtual GpgME::KeyListResult exec(const QString &mailbox, bool canEncrypt, GpgME::Key &key, GpgME::UserID &uid) = 0; + +Q_SIGNALS: + /** The result. \a Key is the key found or a Null key. + * + * The userid is the uid where the mailbox matches. + * + * The auditlog params are always null / empty. + */ + void result(const GpgME::KeyListResult &result, const GpgME::Key &key, const GpgME::UserID &uid, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} +#endif diff --git a/lang/qt/src/keygenerationjob.h b/lang/qt/src/keygenerationjob.h new file mode 100644 index 0000000..a0beeac --- /dev/null +++ b/lang/qt/src/keygenerationjob.h @@ -0,0 +1,85 @@ +/* + keygenerationjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYGENERATIONJOB_H__ +#define __KLEO_KEYGENERATIONJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#include <QtCore/QByteArray> + +namespace GpgME +{ +class Error; +class KeyGenerationResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous key generation + + To use a KeyGenerationJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the key generation with + a call to start(). This call might fail, in which case the + KeyGenerationJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the KeyGenerationJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT KeyGenerationJob : public Job +{ + Q_OBJECT +protected: + explicit KeyGenerationJob(QObject *parent); +public: + ~KeyGenerationJob(); + + /** + Starts the key generation operation. \a parameters is a + backend-specific string containing the parameters of the key to + create (length, capabilities, etc). + */ + virtual GpgME::Error start(const QString ¶meters) = 0; + +Q_SIGNALS: + void result(const GpgME::KeyGenerationResult &result, const QByteArray &pubKeyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_KEYGENERATIONJOB_H__ diff --git a/lang/qt/src/keylistjob.h b/lang/qt/src/keylistjob.h new file mode 100644 index 0000000..8dc736e --- /dev/null +++ b/lang/qt/src/keylistjob.h @@ -0,0 +1,109 @@ +/* + keylistjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYLISTJOB_H__ +#define __KLEO_KEYLISTJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#ifdef BUILDING_QGPGME +# include "key.h" +#else +# include <gpgme++/key.h> +#endif + +#include <vector> + +namespace GpgME +{ +class Error; +class KeyListResult; +} + +class QStringList; + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous key listers + + To use a KeyListJob, first obtain an instance from the + CryptoBackend implementation, connect the nextKey(), progress() + and result() signals to suitable slots and then start the key + listing with a call to start(). This call might fail, in which + case the KeylistJob instance will have schedules it's own + destruction with a call to QObject::deleteLater(). + + During keylisting, you will receive new key objects through the + nextKey() signal as they arrive. After result() is emitted, the + KeyListJob will schedule it's own destruction by calling + QObject::deleteLater(). +*/ +class QGPGME_EXPORT KeyListJob : public Job +{ + Q_OBJECT +protected: + explicit KeyListJob(QObject *parent); + +public: + ~KeyListJob(); + + /** + Starts the keylist operation. \a pattern is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. If \a pattern is empty or contains only empty strings, + all keys are returned (however, the backend is free to truncate + the result and should do so; when this happens, it will be + reported by the reult object). + + If \a secretOnly is true, only keys for which the secret key is + also available are returned. Use this if you need to select a + key for signing. + */ + virtual GpgME::Error start(const QStringList &patterns, bool secretOnly = false) = 0; + + virtual GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly, std::vector<GpgME::Key> &keys) = 0; + + /** Add a flag to the keylistmode used. */ + virtual void addMode(GpgME::KeyListMode mode) = 0; + +Q_SIGNALS: + void nextKey(const GpgME::Key &key); + void result(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys = std::vector<GpgME::Key>(), const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_KEYLISTJOB_H__ diff --git a/lang/qt/src/listallkeysjob.h b/lang/qt/src/listallkeysjob.h new file mode 100644 index 0000000..4fbb469 --- /dev/null +++ b/lang/qt/src/listallkeysjob.h @@ -0,0 +1,104 @@ +/* + listallkeysjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_LISTALLKEYSJOB_H__ +#define __KLEO_LISTALLKEYSJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#ifdef BUILDING_QGPGME +# include "key.h" +#else +# include <gpgme++/key.h> +#endif + +#include <vector> + +namespace GpgME +{ +class Error; +class KeyListResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronously listing all keys + + To use a ListAllKeysJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() + and result() signals to suitable slots and then start the key + listing with a call to start(). This call might fail, in which + case the ListAllKeysJob instance will have schedules it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the ListAllKeysJob will schedule it's + own destruction by calling QObject::deleteLater(). + + This is potentially much faster than a KeyListJob with empty + pattern. +*/ +class QGPGME_EXPORT ListAllKeysJob : public Job +{ + Q_OBJECT +protected: + explicit ListAllKeysJob(QObject *parent); + +public: + ~ListAllKeysJob(); + + /** + Starts the listallkeys operation. In general, all keys are + returned (however, the backend is free to truncate the result + and should do so; when this happens, it will be reported by the + result object). + + If \a mergeKeys is true, secret keys are merged into public + keys. + */ + virtual GpgME::Error start(bool mergeKeys = false) = 0; + + /** + Synchronous version of start(). + */ + virtual GpgME::KeyListResult exec(std::vector<GpgME::Key> &pub, std::vector<GpgME::Key> &sec, bool mergeKeys = false) = 0; + +Q_SIGNALS: + void result(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &pub = std::vector<GpgME::Key>(), const std::vector<GpgME::Key> &sec = std::vector<GpgME::Key>(), const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_LISTALLKEYSJOB_H__ diff --git a/lang/qt/src/multideletejob.h b/lang/qt/src/multideletejob.h new file mode 100644 index 0000000..8915cd1 --- /dev/null +++ b/lang/qt/src/multideletejob.h @@ -0,0 +1,107 @@ +/* + multideletejob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_MULTIDELETEJOB_H__ +#define __KLEO_MULTIDELETEJOB_H__ + +#include "qgpgme_export.h" +#include "job.h" +#include "cryptobackend.h" + +#include <QPointer> + +#include <vector> + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ +class DeleteJob; +} + +namespace QGpgME +{ + +/** + @short A convenience class bundling together multiple DeleteJobs. + + To use a MultiDeleteJob, pass it a CryptoBackend implementation, + connect the progress() and result() signals to suitable slots and + then start the delete with a call to start(). This call might + fail, in which case the MultiDeleteJob instance will have scheduled + it's own destruction with a call to QObject::deleteLater(). + + After result() is emitted, the MultiDeleteJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT MultiDeleteJob : public Job +{ + Q_OBJECT +public: + explicit MultiDeleteJob(const Protocol *protocol); + ~MultiDeleteJob(); + + /** + Starts the delete operation. \a keys is the list of keys to + delete, \a allowSecretKeyDeletion specifies if a key may also + be deleted if the secret key part is available, too. + */ + GpgME::Error start(const std::vector<GpgME::Key> &keys, bool allowSecretKeyDeletion = false); + + /* from Job */ + void slotCancel() Q_DECL_OVERRIDE; + +Q_SIGNALS: + void result(const GpgME::Error &result, const GpgME::Key &errorKey); + +private Q_SLOTS: + void slotResult(const GpgME::Error &); + +private: + GpgME::Error startAJob(); + +private: + const Protocol *mProtocol; + QPointer<DeleteJob> mJob; + std::vector<GpgME::Key> mKeys; + std::vector<GpgME::Key>::const_iterator mIt; + bool mAllowSecretKeyDeletion; +}; + +} + +#endif // __KLEO_MULTIDELETEJOB_H__ diff --git a/lang/qt/src/protocol.h b/lang/qt/src/protocol.h new file mode 100644 index 0000000..40ddcb5 --- /dev/null +++ b/lang/qt/src/protocol.h @@ -0,0 +1,183 @@ +/* + protocol.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef __QGPGME_PROTOCOL_H__ +#define __QGPGME_PROTOCOL_H__ + +#include <QString> +#include <QVariant> + +#include "qgpgme_export.h" + +namespace QGpgME { +class CryptoConfig; +class KeyListJob; +class ListAllKeysJob; +class KeyGenerationJob; +class ImportJob; +class ImportFromKeyserverJob; +class ExportJob; +class DownloadJob; +class DeleteJob; +class EncryptJob; +class DecryptJob; +class SignJob; +class SignKeyJob; +class VerifyDetachedJob; +class VerifyOpaqueJob; +class SignEncryptJob; +class DecryptVerifyJob; +class RefreshKeysJob; +class ChangeExpiryJob; +class ChangeOwnerTrustJob; +class ChangePasswdJob; +class AddUserIDJob; +class SpecialJob; +class KeyForMailboxJob; +class WKSPublishJob; +class TofuPolicyJob; + +/** The main entry point for QGpgME Comes in OpenPGP and SMIME(CMS) flavors. + * + * Use the proctocol class to obtain an instance of a job. Jobs + * provide async API for GnuPG that can be connected to signals / slots. + * + * A job is usually started with start() and emits a result signal. + * The parameters of the result signal depend on the job but the last + * two are always a QString for the auditlog and an GpgME::Error for + * an eventual error. + * + * In case async API is used and the result signal is emited a + * job schedules its own deletion. + * + * Most jobs also provide a synchronous call exec in which case + * you have to explicitly delete the job if you don't need it anymore. + * + * \code + * // Async example: + * KeyListJob *job = openpgp()->keyListJob(); + * connect(job, &KeyListJob::result, job, [this, job](KeyListResult, std::vector<Key> keys, QString, Error) + * { + * // keys and resuls can now be used. + * }); + * \endcode + * + * \code + * // Sync eaxmple: + * KeyListJob *job = openpgp()->keyListJob(false, false, false); + * std::vector<GpgME::Key> keys; + * GpgME::KeyListResult result = job->exec(QStringList() << + * QStringLiteral("alfa@example.net"), + * false, keys); + * delete job; + * \endcode + */ +class QGPGME_EXPORT Protocol +{ +public: + virtual ~Protocol() {} + + virtual QString name() const = 0; + + virtual QString displayName() const = 0; + + virtual KeyListJob *keyListJob(bool remote = false, bool includeSigs = false, bool validate = false) const = 0; + virtual ListAllKeysJob *listAllKeysJob(bool includeSigs = false, bool validate = false) const = 0; + virtual EncryptJob *encryptJob(bool armor = false, bool textmode = false) const = 0; + virtual DecryptJob *decryptJob() const = 0; + virtual SignJob *signJob(bool armor = false, bool textMode = false) const = 0; + virtual VerifyDetachedJob *verifyDetachedJob(bool textmode = false) const = 0; + virtual VerifyOpaqueJob *verifyOpaqueJob(bool textmode = false) const = 0; + virtual KeyGenerationJob *keyGenerationJob() const = 0; + virtual ImportJob *importJob() const = 0; + virtual ImportFromKeyserverJob *importFromKeyserverJob() const = 0; + virtual ExportJob *publicKeyExportJob(bool armor = false) const = 0; + // @param charset the encoding of the passphrase in the exported file + virtual ExportJob *secretKeyExportJob(bool armor = false, const QString &charset = QString()) const = 0; + virtual DownloadJob *downloadJob(bool armor = false) const = 0; + virtual DeleteJob *deleteJob() const = 0; + virtual SignEncryptJob *signEncryptJob(bool armor = false, bool textMode = false) const = 0; + virtual DecryptVerifyJob *decryptVerifyJob(bool textmode = false) const = 0; + virtual RefreshKeysJob *refreshKeysJob() const = 0; + virtual ChangeExpiryJob *changeExpiryJob() const = 0; + virtual SignKeyJob *signKeyJob() const = 0; + virtual ChangePasswdJob *changePasswdJob() const = 0; + virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0; + virtual AddUserIDJob *addUserIDJob() const = 0; + virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0; + + /** A key locate job. + * + * This tries to find a key in local + * and remote sources, if the key was remote it is imported + * by GnuPG. Same as KeyListJob but intended to be used + * to locate keys automatically. This ends up calling --locate-keys. + * + * Only available for OpenPGP + * + * Results are validated. As if keyListJob was called + * with both includeSigs and validate options. + */ + virtual KeyListJob *locateKeysJob() const = 0; + /** Find the best key to use for a mailbox. */ + virtual KeyForMailboxJob *keyForMailboxJob() const = 0; + + /** A Job for interacting with gnupg's wks tools. */ + virtual WKSPublishJob *wksPublishJob() const = 0; + + /** A Job to set tofu policy */ + virtual TofuPolicyJob *tofuPolicyJob() const = 0; +}; + +/** Obtain a reference to the OpenPGP Protocol. + * + * The reference is to a static object. + * @returns Refrence to the OpenPGP Protocol. + */ +QGPGME_EXPORT Protocol *openpgp(); + +/** Obtain a reference to the smime Protocol. + * + * The reference is to a static object. + * @returns Refrence to the smime Protocol. + */ +QGPGME_EXPORT Protocol *smime(); + +/** Obtain a reference to a cryptoConfig object. + * + * The reference is to a static object. + * @returns reference to cryptoConfig object. + */ +QGPGME_EXPORT CryptoConfig *cryptoConfig(); + +} +#endif diff --git a/lang/qt/src/protocol_p.h b/lang/qt/src/protocol_p.h new file mode 100644 index 0000000..7f66fa4 --- /dev/null +++ b/lang/qt/src/protocol_p.h @@ -0,0 +1,419 @@ +/* + protocol_p.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef __QGPGME_PROTOCOL_P_H__ +#define __QGPGME_PROTOCOL_P_H__ +#include "qgpgmenewcryptoconfig.h" + +#include "qgpgmekeygenerationjob.h" +#include "qgpgmekeylistjob.h" +#include "qgpgmelistallkeysjob.h" +#include "qgpgmedecryptjob.h" +#include "qgpgmedecryptverifyjob.h" +#include "qgpgmerefreshkeysjob.h" +#include "qgpgmedeletejob.h" +#include "qgpgmesecretkeyexportjob.h" +#include "qgpgmedownloadjob.h" +#include "qgpgmesignencryptjob.h" +#include "qgpgmeencryptjob.h" +#include "qgpgmesignjob.h" +#include "qgpgmesignkeyjob.h" +#include "qgpgmeexportjob.h" +#include "qgpgmeverifydetachedjob.h" +#include "qgpgmeimportjob.h" +#include "qgpgmeimportfromkeyserverjob.h" +#include "qgpgmeverifyopaquejob.h" +#include "qgpgmechangeexpiryjob.h" +#include "qgpgmechangeownertrustjob.h" +#include "qgpgmechangepasswdjob.h" +#include "qgpgmeadduseridjob.h" +#include "qgpgmekeyformailboxjob.h" +#include "qgpgmewkspublishjob.h" +#include "qgpgmetofupolicyjob.h" + +namespace +{ + +class Protocol : public QGpgME::Protocol +{ + GpgME::Protocol mProtocol; +public: + explicit Protocol(GpgME::Protocol proto) : mProtocol(proto) {} + + QString name() const Q_DECL_OVERRIDE + { + switch (mProtocol) { + case GpgME::OpenPGP: return QStringLiteral("OpenPGP"); + case GpgME::CMS: return QStringLiteral("SMIME"); + default: return QString(); + } + } + + QString displayName() const Q_DECL_OVERRIDE + { + // ah (2.4.16): Where is this used and isn't this inverted + // with name + switch (mProtocol) { + case GpgME::OpenPGP: return QStringLiteral("gpg"); + case GpgME::CMS: return QStringLiteral("gpgsm"); + default: return QStringLiteral("unknown"); + } + } + + QGpgME::SpecialJob *specialJob(const char *, const QMap<QString, QVariant> &) const Q_DECL_OVERRIDE + { + return 0; + } + + QGpgME::KeyListJob *keyListJob(bool remote, bool includeSigs, bool validate) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + unsigned int mode = context->keyListMode(); + if (remote) { + mode |= GpgME::Extern; + mode &= ~GpgME::Local; + } else { + mode |= GpgME::Local; + mode &= ~GpgME::Extern; + } + if (includeSigs) { + mode |= GpgME::Signatures; + } + if (validate) { + mode |= GpgME::Validate; + } + context->setKeyListMode(mode); + return new QGpgME::QGpgMEKeyListJob(context); + } + + QGpgME::ListAllKeysJob *listAllKeysJob(bool includeSigs, bool validate) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + unsigned int mode = context->keyListMode(); + mode |= GpgME::Local; + mode &= ~GpgME::Extern; + if (includeSigs) { + mode |= GpgME::Signatures; + } + if (validate) { + mode |= GpgME::Validate; + /* Setting the context to offline mode disables CRL / OCSP checks in + this Job. Otherwise we would try to fetch the CRL's for all CMS + keys in the users keyring because GpgME::Validate includes remote + resources by default in the validity check. + This setting only has any effect if gpgsm >= 2.1.6 is used. + */ + context->setOffline(true); + } + context->setKeyListMode(mode); + return new QGpgME::QGpgMEListAllKeysJob(context); + } + + QGpgME::EncryptJob *encryptJob(bool armor, bool textmode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setArmor(armor); + context->setTextMode(textmode); + return new QGpgME::QGpgMEEncryptJob(context); + } + + QGpgME::DecryptJob *decryptJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEDecryptJob(context); + } + + QGpgME::SignJob *signJob(bool armor, bool textMode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setArmor(armor); + context->setTextMode(textMode); + return new QGpgME::QGpgMESignJob(context); + } + + QGpgME::VerifyDetachedJob *verifyDetachedJob(bool textMode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setTextMode(textMode); + return new QGpgME::QGpgMEVerifyDetachedJob(context); + } + + QGpgME::VerifyOpaqueJob *verifyOpaqueJob(bool textMode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setTextMode(textMode); + return new QGpgME::QGpgMEVerifyOpaqueJob(context); + } + + QGpgME::KeyGenerationJob *keyGenerationJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEKeyGenerationJob(context); + } + + QGpgME::ImportJob *importJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEImportJob(context); + } + + QGpgME::ImportFromKeyserverJob *importFromKeyserverJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEImportFromKeyserverJob(context); + } + + QGpgME::ExportJob *publicKeyExportJob(bool armor) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setArmor(armor); + return new QGpgME::QGpgMEExportJob(context); + } + + QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &charset) const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too + return 0; + } + + // this operation is not supported by gpgme, so we have to call gpgsm ourselves: + return new QGpgME::QGpgMESecretKeyExportJob(armor, charset); + } + + QGpgME::RefreshKeysJob *refreshKeysJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too + return 0; + } + + // this operation is not supported by gpgme, so we have to call gpgsm ourselves: + return new QGpgME::QGpgMERefreshKeysJob(); + } + + QGpgME::DownloadJob *downloadJob(bool armor) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setArmor(armor); + // this is the hackish interface for downloading from keyserers currently: + context->setKeyListMode(GpgME::Extern); + return new QGpgME::QGpgMEDownloadJob(context); + } + + QGpgME::DeleteJob *deleteJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEDeleteJob(context); + } + + QGpgME::SignEncryptJob *signEncryptJob(bool armor, bool textMode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setArmor(armor); + context->setTextMode(textMode); + return new QGpgME::QGpgMESignEncryptJob(context); + } + + QGpgME::DecryptVerifyJob *decryptVerifyJob(bool textMode) const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + + context->setTextMode(textMode); + return new QGpgME::QGpgMEDecryptVerifyJob(context); + } + + QGpgME::ChangeExpiryJob *changeExpiryJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return 0; // only supported by gpg + } + + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEChangeExpiryJob(context); + } + + QGpgME::ChangePasswdJob *changePasswdJob() const Q_DECL_OVERRIDE + { + if (!GpgME::hasFeature(GpgME::PasswdFeature, 0)) { + return 0; + } + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEChangePasswdJob(context); + } + + QGpgME::SignKeyJob *signKeyJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return 0; // only supported by gpg + } + + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMESignKeyJob(context); + } + + QGpgME::ChangeOwnerTrustJob *changeOwnerTrustJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return 0; // only supported by gpg + } + + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEChangeOwnerTrustJob(context); + } + + QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return 0; // only supported by gpg + } + + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return 0; + } + return new QGpgME::QGpgMEAddUserIDJob(context); + } + + QGpgME::KeyListJob *locateKeysJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return Q_NULLPTR; + } + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return Q_NULLPTR; + } + context->setKeyListMode(GpgME::Extern | GpgME::Local | GpgME::Signatures | GpgME::Validate); + return new QGpgME::QGpgMEKeyListJob(context); + } + + QGpgME::KeyForMailboxJob *keyForMailboxJob() const Q_DECL_OVERRIDE + { + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return Q_NULLPTR; + } + return new QGpgME::QGpgMEKeyForMailboxJob(context); + } + + QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return Q_NULLPTR; + } + auto context = GpgME::Context::createForEngine(GpgME::SpawnEngine); + if (!context) { + return Q_NULLPTR; + } + return new QGpgME::QGpgMEWKSPublishJob(context.release()); + } + + QGpgME::TofuPolicyJob *tofuPolicyJob() const Q_DECL_OVERRIDE + { + if (mProtocol != GpgME::OpenPGP) { + return Q_NULLPTR; + } + GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol); + if (!context) { + return Q_NULLPTR; + } + return new QGpgME::QGpgMETofuPolicyJob(context); + } +}; + +} +#endif diff --git a/lang/qt/src/qgpgme_export.h b/lang/qt/src/qgpgme_export.h new file mode 100644 index 0000000..ceb3888 --- /dev/null +++ b/lang/qt/src/qgpgme_export.h @@ -0,0 +1,73 @@ +/*qgpgme_export.h - Export macros for qgpgme + Copyright (C) 2016, Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef QGPGME_EXPORT_H +#define QGPGME_EXPORT_H + +#ifdef QGPGME_STATIC_DEFINE +# define QGPGME_EXPORT +# define QGPGME_NO_EXPORT +#else +# ifndef QGPGME_EXPORT +# ifdef BUILDING_QGPGME + /* We are building this library */ +# ifdef WIN32 +# define QGPGME_EXPORT __declspec(dllexport) +# else +# define QGPGME_EXPORT __attribute__((visibility("default"))) +# endif +# else + /* We are using this library */ +# ifdef WIN32 +# define QGPGME_EXPORT __declspec(dllimport) +# else +# define QGPGME_EXPORT __attribute__((visibility("default"))) +# endif +# endif +# endif + +# ifndef QGPGME_NO_EXPORT +# ifdef WIN32 +# define QGPGME_NO_EXPORT +# else +# define QGPGME_NO_EXPORT __attribute__((visibility("hidden"))) +# endif +# endif +#endif + +#ifndef QGPGME_DEPRECATED +# define QGPGME_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef QGPGME_DEPRECATED_EXPORT +# define QGPGME_DEPRECATED_EXPORT QGPGME_EXPORT QGPGME_DEPRECATED +#endif + +#ifndef QGPGME_DEPRECATED_NO_EXPORT +# define QGPGME_DEPRECATED_NO_EXPORT QGPGME_NO_EXPORT QGPGME_DEPRECATED +#endif + +#define DEFINE_NO_DEPRECATED 0 +#if DEFINE_NO_DEPRECATED +# define QGPGME_NO_DEPRECATED +#endif + +#endif diff --git a/lang/qt/src/qgpgme_version.h.in b/lang/qt/src/qgpgme_version.h.in new file mode 100644 index 0000000..9fbe965 --- /dev/null +++ b/lang/qt/src/qgpgme_version.h.in @@ -0,0 +1,32 @@ +/*qgpgme_version.h - Version macros for qgpgme + Copyright (C) 2016, Intevation GmbH + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + + +#ifndef QGPGME_VERSION_H +#define QGPGME_VERSION_H + +#define QGPGME_VERSION_STRING "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@" +#define QGPGME_VERSION_MAJOR @LIBQGPGME_LT_CURRENT@ +#define QGPGME_VERSION_MINOR @LIBQGPGME_LT_AGE@ +#define QGPGME_VERSION_PATCH @LIBQGPGME_LT_REVISION@ +#define QGPGME_VERSION ((@LIBQGPGME_LT_CURRENT@<<16)|(@LIBQGPGME_LT_AGE@<<8)|(@LIBQGPGME_LT_REVISION@)) + +#endif diff --git a/lang/qt/src/qgpgmeadduseridjob.cpp b/lang/qt/src/qgpgmeadduseridjob.cpp new file mode 100644 index 0000000..eb3bfab --- /dev/null +++ b/lang/qt/src/qgpgmeadduseridjob.cpp @@ -0,0 +1,80 @@ +/* + qgpgmeadduseridjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeadduseridjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "gpgadduserideditinteractor.h" +#include "key.h" + +#include <cassert> +#include <memory> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEAddUserIDJob::QGpgMEAddUserIDJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEAddUserIDJob::~QGpgMEAddUserIDJob() {} + +static QGpgMEAddUserIDJob::result_type add_user_id(Context *ctx, const Key &key, const QString &name, const QString &email, const QString &comment) +{ + + GpgAddUserIDEditInteractor *gau = new GpgAddUserIDEditInteractor; + + gau->setNameUtf8(name.toUtf8().constData()); + gau->setEmailUtf8(email.toUtf8().constData()); + gau->setCommentUtf8(comment.toUtf8().constData()); + + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + assert(!data.isNull()); + const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (gau), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMEAddUserIDJob::start(const Key &key, const QString &name, const QString &email, const QString &comment) +{ + run(std::bind(&add_user_id, std::placeholders::_1, key, name, email, comment)); + return Error(); +} +#include "qgpgmeadduseridjob.moc" diff --git a/lang/qt/src/qgpgmeadduseridjob.h b/lang/qt/src/qgpgmeadduseridjob.h new file mode 100644 index 0000000..294eb6c --- /dev/null +++ b/lang/qt/src/qgpgmeadduseridjob.h @@ -0,0 +1,65 @@ +/* + qgpgmeadduseridjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEADDUSERIDJOB_H__ +#define __QGPGME_QGPGMEADDUSERIDJOB_H__ + +#include "adduseridjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEAddUserIDJob +#ifdef Q_MOC_RUN + : public AddUserIDJob +#else + : public _detail::ThreadedJobMixin<AddUserIDJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEAddUserIDJob(GpgME::Context *context); + ~QGpgMEAddUserIDJob(); + + /* from AddUserIDJob */ + GpgME::Error start(const GpgME::Key &key, const QString &name, const QString &email, const QString &comment) Q_DECL_OVERRIDE; +}; +} + +#endif // __QGPGME_QGPGMEADDUSERIDJOB_H__ diff --git a/lang/qt/src/qgpgmebackend.cpp b/lang/qt/src/qgpgmebackend.cpp new file mode 100644 index 0000000..797e58a --- /dev/null +++ b/lang/qt/src/qgpgmebackend.cpp @@ -0,0 +1,203 @@ +/* + qgpgmebackend.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmebackend.h" + + +#include "error.h" +#include "engineinfo.h" + +#include "protocol_p.h" + +#include <QFile> +#include <QString> + +const char QGpgME::QGpgMEBackend::OpenPGP[] = "OpenPGP"; +const char QGpgME::QGpgMEBackend::SMIME[] = "SMIME"; + + +QGpgME::QGpgMEBackend::QGpgMEBackend() + : mCryptoConfig(0), + mOpenPGPProtocol(0), + mSMIMEProtocol(0) +{ + GpgME::initializeLibrary(); +} + +QGpgME::QGpgMEBackend::~QGpgMEBackend() +{ + delete mCryptoConfig; mCryptoConfig = 0; + delete mOpenPGPProtocol; mOpenPGPProtocol = 0; + delete mSMIMEProtocol; mSMIMEProtocol = 0; +} + +QString QGpgME::QGpgMEBackend::name() const +{ + return QStringLiteral("gpgme"); +} + +QString QGpgME::QGpgMEBackend::displayName() const +{ + return QStringLiteral("GpgME"); +} + +QGpgME::CryptoConfig *QGpgME::QGpgMEBackend::config() const +{ + if (!mCryptoConfig) { + if (GpgME::hasFeature(GpgME::GpgConfEngineFeature, 0)) { + mCryptoConfig = new QGpgMENewCryptoConfig; + } + } + return mCryptoConfig; +} + +static bool check(GpgME::Protocol proto, QString *reason) +{ + if (!GpgME::checkEngine(proto)) { + return true; + } + if (!reason) { + return false; + } + // error, check why: +#if 0 +Port away from localised string or delete. + const GpgME::EngineInfo ei = GpgME::engineInfo(proto); + if (ei.isNull()) { + *reason = i18n("GPGME was compiled without support for %1.", proto == GpgME::CMS ? QLatin1String("S/MIME") : QLatin1String("OpenPGP")); + } else if (ei.fileName() && !ei.version()) { + *reason = i18n("Engine %1 is not installed properly.", QFile::decodeName(ei.fileName())); + } else if (ei.fileName() && ei.version() && ei.requiredVersion()) + *reason = i18n("Engine %1 version %2 installed, " + "but at least version %3 is required.", + QFile::decodeName(ei.fileName()), QLatin1String(ei.version()), QLatin1String(ei.requiredVersion())); + else { + *reason = i18n("Unknown problem with engine for protocol %1.", proto == GpgME::CMS ? QLatin1String("S/MIME") : QLatin1String("OpenPGP")); + } +#endif + return false; +} + +bool QGpgME::QGpgMEBackend::checkForOpenPGP(QString *reason) const +{ + return check(GpgME::OpenPGP, reason); +} + +bool QGpgME::QGpgMEBackend::checkForSMIME(QString *reason) const +{ + return check(GpgME::CMS, reason); +} + +bool QGpgME::QGpgMEBackend::checkForProtocol(const char *name, QString *reason) const +{ + if (qstricmp(name, OpenPGP) == 0) { + return check(GpgME::OpenPGP, reason); + } + if (qstricmp(name, SMIME) == 0) { + return check(GpgME::CMS, reason); + } + if (reason) { + *reason = QStringLiteral("Unsupported protocol \"%1\"").arg(QLatin1String(name)); + } + return false; +} + +QGpgME::Protocol *QGpgME::QGpgMEBackend::openpgp() const +{ + if (!mOpenPGPProtocol) + if (checkForOpenPGP()) { + mOpenPGPProtocol = new ::Protocol(GpgME::OpenPGP); + } + return mOpenPGPProtocol; +} + +QGpgME::Protocol *QGpgME::QGpgMEBackend::smime() const +{ + if (!mSMIMEProtocol) + if (checkForSMIME()) { + mSMIMEProtocol = new ::Protocol(GpgME::CMS); + } + return mSMIMEProtocol; +} + +QGpgME::Protocol *QGpgME::QGpgMEBackend::protocol(const char *name) const +{ + if (qstricmp(name, OpenPGP) == 0) { + return openpgp(); + } + if (qstricmp(name, SMIME) == 0) { + return smime(); + } + return 0; +} + +bool QGpgME::QGpgMEBackend::supportsProtocol(const char *name) const +{ + return qstricmp(name, OpenPGP) == 0 || qstricmp(name, SMIME) == 0; +} + +const char *QGpgME::QGpgMEBackend::enumerateProtocols(int i) const +{ + switch (i) { + case 0: return OpenPGP; + case 1: return SMIME; + default: return 0; + } +} + +static QGpgME::QGpgMEBackend *gpgmeBackend; + +QGpgME::CryptoConfig *QGpgME::cryptoConfig() +{ + if (!gpgmeBackend) { + gpgmeBackend = new QGpgME::QGpgMEBackend(); + } + return gpgmeBackend->config(); + +} + +QGpgME::Protocol *QGpgME::openpgp() +{ + if (!gpgmeBackend) { + gpgmeBackend = new QGpgME::QGpgMEBackend(); + } + return gpgmeBackend->openpgp(); +} + +QGpgME::Protocol *QGpgME::smime() +{ + if (!gpgmeBackend) { + gpgmeBackend = new QGpgME::QGpgMEBackend(); + } + return gpgmeBackend->smime(); +} diff --git a/lang/qt/src/qgpgmebackend.h b/lang/qt/src/qgpgmebackend.h new file mode 100644 index 0000000..cca8b71 --- /dev/null +++ b/lang/qt/src/qgpgmebackend.h @@ -0,0 +1,92 @@ +/* + qgpgmebackend.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEBACKEND_H__ +#define __QGPGME_QGPGMEBACKEND_H__ + +#include <QString> + +#include "protocol.h" + +class QString; +template <typename T_Key, typename T_Value> class QMap; + +namespace QGpgME +{ +class CryptoConfig; +class Protocol; + + +class QGpgMEBackend +{ +public: + QGpgMEBackend(); + ~QGpgMEBackend(); + + QString name() const; + QString displayName() const; + + CryptoConfig *config() const; + + Protocol *openpgp() const; + Protocol *smime() const; + Protocol *protocol(const char *name) const; + + static const char OpenPGP[]; + static const char SMIME[]; + + bool checkForOpenPGP(QString *reason = Q_NULLPTR) const; + bool checkForSMIME(QString *reason = Q_NULLPTR) const; + bool checkForProtocol(const char *name, QString *reason) const; + + bool supportsOpenPGP() const + { + return true; + } + bool supportsSMIME() const + { + return true; + } + bool supportsProtocol(const char *name) const; + + const char *enumerateProtocols(int i) const; + +private: + mutable QGpgME::CryptoConfig *mCryptoConfig; + mutable Protocol *mOpenPGPProtocol; + mutable Protocol *mSMIMEProtocol; +}; + +} + +#endif // __QGPGME_QGPGMEBACKEND_H__ diff --git a/lang/qt/src/qgpgmechangeexpiryjob.cpp b/lang/qt/src/qgpgmechangeexpiryjob.cpp new file mode 100644 index 0000000..43ceee3 --- /dev/null +++ b/lang/qt/src/qgpgmechangeexpiryjob.cpp @@ -0,0 +1,80 @@ +/* + qgpgmechangeexpiryjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmechangeexpiryjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "gpgsetexpirytimeeditinteractor.h" +#include "key.h" + +#include <QDateTime> + +#include <cassert> +#include <memory> +#include <string> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEChangeExpiryJob::QGpgMEChangeExpiryJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEChangeExpiryJob::~QGpgMEChangeExpiryJob() {} + +static QGpgMEChangeExpiryJob::result_type change_expiry(Context *ctx, const Key &key, const QDateTime &expiry) +{ + EditInteractor *ei = expiry.isValid() + ? new GpgSetExpiryTimeEditInteractor(expiry.date().toString(Qt::ISODate).toStdString()) + : new GpgSetExpiryTimeEditInteractor(); + + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + assert(!data.isNull()); + const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (ei), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry) +{ + run(std::bind(&change_expiry, std::placeholders::_1, key, expiry)); + return Error(); +} +#include "qgpgmechangeexpiryjob.moc" diff --git a/lang/qt/src/qgpgmechangeexpiryjob.h b/lang/qt/src/qgpgmechangeexpiryjob.h new file mode 100644 index 0000000..4abdf78 --- /dev/null +++ b/lang/qt/src/qgpgmechangeexpiryjob.h @@ -0,0 +1,66 @@ +/* + qgpgmechangeexpiryjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMECHANGEEXPIRYJOB_H__ +#define __QGPGME_QGPGMECHANGEEXPIRYJOB_H__ + +#include "changeexpiryjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEChangeExpiryJob +#ifdef Q_MOC_RUN + : public ChangeExpiryJob +#else + : public _detail::ThreadedJobMixin<ChangeExpiryJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEChangeExpiryJob(GpgME::Context *context); + ~QGpgMEChangeExpiryJob(); + + /* from ChangeExpiryJob */ + GpgME::Error start(const GpgME::Key &key, const QDateTime &expiry) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMECHANGEEXPIRYJOB_H__ diff --git a/lang/qt/src/qgpgmechangeownertrustjob.cpp b/lang/qt/src/qgpgmechangeownertrustjob.cpp new file mode 100644 index 0000000..55131d9 --- /dev/null +++ b/lang/qt/src/qgpgmechangeownertrustjob.cpp @@ -0,0 +1,76 @@ +/* + qgpgmechangeownertrustjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmechangeownertrustjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "gpgsetownertrusteditinteractor.h" +#include "key.h" + +#include <cassert> +#include <memory> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEChangeOwnerTrustJob::QGpgMEChangeOwnerTrustJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEChangeOwnerTrustJob::~QGpgMEChangeOwnerTrustJob() {} + +static QGpgMEChangeOwnerTrustJob::result_type change_ownertrust(Context *ctx, const Key &key, Key::OwnerTrust trust) +{ + EditInteractor *ei = new GpgSetOwnerTrustEditInteractor(trust); + + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + assert(!data.isNull()); + + const Error err = ctx->edit(key, std::unique_ptr<EditInteractor>(ei), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMEChangeOwnerTrustJob::start(const Key &key, Key::OwnerTrust trust) +{ + run(std::bind(&change_ownertrust, std::placeholders::_1, key, trust)); + return Error(); +} +#include "qgpgmechangeownertrustjob.moc" diff --git a/lang/qt/src/qgpgmechangeownertrustjob.h b/lang/qt/src/qgpgmechangeownertrustjob.h new file mode 100644 index 0000000..7740616 --- /dev/null +++ b/lang/qt/src/qgpgmechangeownertrustjob.h @@ -0,0 +1,65 @@ +/* + qgpgmechangeexpiryjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__ +#define __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__ + +#include "changeownertrustjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEChangeOwnerTrustJob +#ifdef Q_MOC_RUN + : public ChangeOwnerTrustJob +#else + : public _detail::ThreadedJobMixin<ChangeOwnerTrustJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEChangeOwnerTrustJob(GpgME::Context *context); + ~QGpgMEChangeOwnerTrustJob(); + + /* from ChangeOwnerTrustJob */ + GpgME::Error start(const GpgME::Key &key, GpgME::Key::OwnerTrust trust) Q_DECL_OVERRIDE; +}; +} + +#endif // __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__ diff --git a/lang/qt/src/qgpgmechangepasswdjob.cpp b/lang/qt/src/qgpgmechangepasswdjob.cpp new file mode 100644 index 0000000..0aec927 --- /dev/null +++ b/lang/qt/src/qgpgmechangepasswdjob.cpp @@ -0,0 +1,79 @@ +/* + qgpgmechangepasswdjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2010 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmechangepasswdjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "key.h" + +#include <cassert> +#include <memory> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEChangePasswdJob::QGpgMEChangePasswdJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEChangePasswdJob::~QGpgMEChangePasswdJob() {} + +static QGpgMEChangePasswdJob::result_type change_passwd(Context *ctx, const Key &key) +{ +#if 0 // in case we want to fall back to edit interactor for gpg... + std::unique_ptr<EditInteractor> ei(new GpgChangePasswdEditInteractor); + + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + assert(!data.isNull()); + const Error err = ctx->edit(key, ei, data); +#else + const Error err = ctx->passwd(key); +#endif + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMEChangePasswdJob::start(const Key &key) +{ + run(std::bind(&change_passwd, std::placeholders::_1, key)); + return Error(); +} + +#include "qgpgmechangepasswdjob.moc" diff --git a/lang/qt/src/qgpgmechangepasswdjob.h b/lang/qt/src/qgpgmechangepasswdjob.h new file mode 100644 index 0000000..e37789e --- /dev/null +++ b/lang/qt/src/qgpgmechangepasswdjob.h @@ -0,0 +1,66 @@ +/* + qgpgmechangepasswdjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2010 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMECHANGEPASSWDJOB_H__ +#define __QGPGME_QGPGMECHANGEPASSWDJOB_H__ + +#include "changepasswdjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEChangePasswdJob +#ifdef Q_MOC_RUN + : public ChangePasswdJob +#else + : public _detail::ThreadedJobMixin<ChangePasswdJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEChangePasswdJob(GpgME::Context *context); + ~QGpgMEChangePasswdJob(); + + /* from ChangePasswdJob */ + GpgME::Error start(const GpgME::Key &key) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMECHANGEPASSWDJOB_H__ diff --git a/lang/qt/src/qgpgmedecryptjob.cpp b/lang/qt/src/qgpgmedecryptjob.cpp new file mode 100644 index 0000000..7116449 --- /dev/null +++ b/lang/qt/src/qgpgmedecryptjob.cpp @@ -0,0 +1,128 @@ +/* + qgpgmedecryptjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmedecryptjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "decryptionresult.h" +#include "data.h" + +#include <QBuffer> + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEDecryptJob::QGpgMEDecryptJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEDecryptJob::~QGpgMEDecryptJob() {} + +static QGpgMEDecryptJob::result_type decrypt(Context *ctx, QThread *thread, + const std::weak_ptr<QIODevice> &cipherText_, + const std::weak_ptr<QIODevice> &plainText_) +{ + + const std::shared_ptr<QIODevice> cipherText = cipherText_.lock(); + const std::shared_ptr<QIODevice> plainText = plainText_.lock(); + + const _detail::ToThreadMover ctMover(cipherText, thread); + const _detail::ToThreadMover ptMover(plainText, thread); + + QGpgME::QIODeviceDataProvider in(cipherText); + const Data indata(&in); + + if (!plainText) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + const DecryptionResult res = ctx->decrypt(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(plainText); + Data outdata(&out); + + const DecryptionResult res = ctx->decrypt(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, QByteArray(), log, ae); + } + +} + +static QGpgMEDecryptJob::result_type decrypt_qba(Context *ctx, const QByteArray &cipherText) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(cipherText); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return decrypt(ctx, 0, buffer, std::shared_ptr<QIODevice>()); +} + +Error QGpgMEDecryptJob::start(const QByteArray &cipherText) +{ + run(std::bind(&decrypt_qba, std::placeholders::_1, cipherText)); + return Error(); +} + +void QGpgMEDecryptJob::start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) +{ + run(std::bind(&decrypt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), cipherText, plainText); +} + +GpgME::DecryptionResult QGpgME::QGpgMEDecryptJob::exec(const QByteArray &cipherText, + QByteArray &plainText) +{ + const result_type r = decrypt_qba(context(), cipherText); + plainText = std::get<1>(r); + resultHook(r); + return mResult; +} + +//PENDING(marc) implement showErrorDialog() + +void QGpgMEDecryptJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} + +#include "qgpgmedecryptjob.moc" diff --git a/lang/qt/src/qgpgmedecryptjob.h b/lang/qt/src/qgpgmedecryptjob.h new file mode 100644 index 0000000..5335e84 --- /dev/null +++ b/lang/qt/src/qgpgmedecryptjob.h @@ -0,0 +1,84 @@ +/* + qgpgmedecryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEDECRYPTJOB_H__ +#define __QGPGME_QGPGMEDECRYPTJOB_H__ + +#include "decryptjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "decryptionresult.h" +#else +#include <gpgme++/decryptionresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEDecryptJob +#ifdef Q_MOC_RUN + : public DecryptJob +#else + : public _detail::ThreadedJobMixin<DecryptJob, std::tuple<GpgME::DecryptionResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEDecryptJob(GpgME::Context *context); + ~QGpgMEDecryptJob(); + + /* from DecryptJob */ + GpgME::Error start(const QByteArray &cipherText) Q_DECL_OVERRIDE; + + /* from DecryptJob */ + void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE; + + /* from DecryptJob */ + GpgME::DecryptionResult exec(const QByteArray &cipherText, + QByteArray &plainText) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::DecryptionResult mResult; +}; + +} +#endif // __QGPGME_QGPGMEDECRYPTJOB_H__ diff --git a/lang/qt/src/qgpgmedecryptverifyjob.cpp b/lang/qt/src/qgpgmedecryptverifyjob.cpp new file mode 100644 index 0000000..d46a9b5 --- /dev/null +++ b/lang/qt/src/qgpgmedecryptverifyjob.cpp @@ -0,0 +1,135 @@ +/* + qgpgmedecryptverifyjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmedecryptverifyjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "decryptionresult.h" +#include "verificationresult.h" +#include "data.h" + +#include <QDebug> +#include "gpgme_backend_debug.h" + +#include <QBuffer> + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEDecryptVerifyJob::QGpgMEDecryptVerifyJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEDecryptVerifyJob::~QGpgMEDecryptVerifyJob() {} + +static QGpgMEDecryptVerifyJob::result_type decrypt_verify(Context *ctx, QThread *thread, + const std::weak_ptr<QIODevice> &cipherText_, + const std::weak_ptr<QIODevice> &plainText_) +{ + + qCDebug(GPGPME_BACKEND_LOG); + + const std::shared_ptr<QIODevice> cipherText = cipherText_.lock(); + const std::shared_ptr<QIODevice> plainText = plainText_.lock(); + + const _detail::ToThreadMover ctMover(cipherText, thread); + const _detail::ToThreadMover ptMover(plainText, thread); + + QGpgME::QIODeviceDataProvider in(cipherText); + const Data indata(&in); + + if (!plainText) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + const std::pair<DecryptionResult, VerificationResult> res = ctx->decryptAndVerify(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + qCDebug(GPGPME_BACKEND_LOG) << "End no plainText. Error: " << ae; + return std::make_tuple(res.first, res.second, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(plainText); + Data outdata(&out); + + const std::pair<DecryptionResult, VerificationResult> res = ctx->decryptAndVerify(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + qCDebug(GPGPME_BACKEND_LOG) << "End plainText. Error: " << ae; + return std::make_tuple(res.first, res.second, QByteArray(), log, ae); + } + +} + +static QGpgMEDecryptVerifyJob::result_type decrypt_verify_qba(Context *ctx, const QByteArray &cipherText) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(cipherText); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return decrypt_verify(ctx, 0, buffer, std::shared_ptr<QIODevice>()); +} + +Error QGpgMEDecryptVerifyJob::start(const QByteArray &cipherText) +{ + run(std::bind(&decrypt_verify_qba, std::placeholders::_1, cipherText)); + return Error(); +} + +void QGpgMEDecryptVerifyJob::start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) +{ + run(std::bind(&decrypt_verify, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), cipherText, plainText); +} + +std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> +QGpgME::QGpgMEDecryptVerifyJob::exec(const QByteArray &cipherText, QByteArray &plainText) +{ + const result_type r = decrypt_verify_qba(context(), cipherText); + plainText = std::get<2>(r); + resultHook(r); + return mResult; +} + +//PENDING(marc) implement showErrorDialog() + +void QGpgMEDecryptVerifyJob::resultHook(const result_type &tuple) +{ + mResult = std::make_pair(std::get<0>(tuple), std::get<1>(tuple)); +} +#include "qgpgmedecryptverifyjob.moc" diff --git a/lang/qt/src/qgpgmedecryptverifyjob.h b/lang/qt/src/qgpgmedecryptverifyjob.h new file mode 100644 index 0000000..de2bce7 --- /dev/null +++ b/lang/qt/src/qgpgmedecryptverifyjob.h @@ -0,0 +1,89 @@ +/* + qgpgmedecryptverifyjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__ +#define __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__ + +#include "decryptverifyjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "decryptionresult.h" +#else +#include <gpgme++/decryptionresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "verificationresult.h" +#else +#include <gpgme++/verificationresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEDecryptVerifyJob +#ifdef Q_MOC_RUN + : public DecryptVerifyJob +#else + : public _detail::ThreadedJobMixin<DecryptVerifyJob, std::tuple<GpgME::DecryptionResult, GpgME::VerificationResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEDecryptVerifyJob(GpgME::Context *context); + ~QGpgMEDecryptVerifyJob(); + + /* from DecryptVerifyJob */ + GpgME::Error start(const QByteArray &cipherText) Q_DECL_OVERRIDE; + + /* from DecryptVerifyJob */ + void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE; + + /* from DecryptVerifyJob */ + std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> + exec(const QByteArray &cipherText, QByteArray &plainText) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> mResult; +}; + +} +#endif // __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__ diff --git a/lang/qt/src/qgpgmedeletejob.cpp b/lang/qt/src/qgpgmedeletejob.cpp new file mode 100644 index 0000000..323aec4 --- /dev/null +++ b/lang/qt/src/qgpgmedeletejob.cpp @@ -0,0 +1,65 @@ +/* + qgpgmedeletejob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmedeletejob.h" + +#include "context.h" +#include "key.h" + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEDeleteJob::QGpgMEDeleteJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEDeleteJob::~QGpgMEDeleteJob() {} + +static QGpgMEDeleteJob::result_type delete_key(Context *ctx, const Key &key, bool allowSecretKeyDeletion) +{ + const Error err = ctx->deleteKey(key, allowSecretKeyDeletion); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMEDeleteJob::start(const Key &key, bool allowSecretKeyDeletion) +{ + run(std::bind(&delete_key, std::placeholders::_1, key, allowSecretKeyDeletion)); + return Error(); +} +#include "qgpgmedeletejob.moc" diff --git a/lang/qt/src/qgpgmedeletejob.h b/lang/qt/src/qgpgmedeletejob.h new file mode 100644 index 0000000..992442f --- /dev/null +++ b/lang/qt/src/qgpgmedeletejob.h @@ -0,0 +1,71 @@ +/* + qgpgmedeletejob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEDELETEJOB_H__ +#define __QGPGME_QGPGMEDELETEJOB_H__ + +#include "deletejob.h" + +#include "threadedjobmixin.h" + +namespace GpgME +{ +class Key; +} + +namespace QGpgME +{ + +class QGpgMEDeleteJob +#ifdef Q_MOC_RUN + : public DeleteJob +#else + : public _detail::ThreadedJobMixin<DeleteJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEDeleteJob(GpgME::Context *context); + ~QGpgMEDeleteJob(); + + /* from DeleteJob */ + GpgME::Error start(const GpgME::Key &key, bool allowSecretKeyDeletion) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMEDELETEJOB_H__ diff --git a/lang/qt/src/qgpgmedownloadjob.cpp b/lang/qt/src/qgpgmedownloadjob.cpp new file mode 100644 index 0000000..48cc907 --- /dev/null +++ b/lang/qt/src/qgpgmedownloadjob.cpp @@ -0,0 +1,100 @@ +/* + qgpgmedownloadjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmedownloadjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" + +#include <QStringList> + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEDownloadJob::QGpgMEDownloadJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEDownloadJob::~QGpgMEDownloadJob() {} + +static QGpgMEDownloadJob::result_type download_qsl(Context *ctx, const QStringList &pats) +{ + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + + const _detail::PatternConverter pc(pats); + + const Error err = ctx->exportPublicKeys(pc.patterns(), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, dp.data(), log, ae); +} + +static QGpgMEDownloadJob::result_type download(Context *ctx, QThread *thread, const QByteArray &fpr, const std::weak_ptr<QIODevice> &keyData_) +{ + const std::shared_ptr<QIODevice> keyData = keyData_.lock(); + if (!keyData) { + return download_qsl(ctx, QStringList(QString::fromUtf8(fpr))); + } + + const _detail::ToThreadMover kdMover(keyData, thread); + + QGpgME::QIODeviceDataProvider dp(keyData); + Data data(&dp); + + const _detail::PatternConverter pc(fpr); + + const Error err = ctx->exportPublicKeys(pc.patterns(), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, QByteArray(), log, ae); +} + +Error QGpgMEDownloadJob::start(const QStringList &pats) +{ + run(std::bind(&download_qsl, std::placeholders::_1, pats)); + return Error(); +} + +Error QGpgMEDownloadJob::start(const QByteArray &fpr, const std::shared_ptr<QIODevice> &keyData) +{ + run(std::bind(&download, std::placeholders::_1, std::placeholders::_2, fpr, std::placeholders::_3), keyData); + return Error(); +} +#include "qgpgmedownloadjob.moc" diff --git a/lang/qt/src/qgpgmedownloadjob.h b/lang/qt/src/qgpgmedownloadjob.h new file mode 100644 index 0000000..4091190 --- /dev/null +++ b/lang/qt/src/qgpgmedownloadjob.h @@ -0,0 +1,69 @@ +/* + qgpgmedownloadjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEDOWNLOADJOB_H__ +#define __QGPGME_QGPGMEDOWNLOADJOB_H__ + +#include "downloadjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEDownloadJob +#ifdef Q_MOC_RUN + : public DownloadJob +#else + : public _detail::ThreadedJobMixin<DownloadJob, std::tuple<GpgME::Error, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEDownloadJob(GpgME::Context *context); + ~QGpgMEDownloadJob(); + + /* from DownloadJob */ + GpgME::Error start(const QStringList &fingerprints) Q_DECL_OVERRIDE; + + /* from DownloadJob */ + GpgME::Error start(const QByteArray &fingerprint, const std::shared_ptr<QIODevice> &keyData) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMEDOWNLOADJOB_H__ diff --git a/lang/qt/src/qgpgmeencryptjob.cpp b/lang/qt/src/qgpgmeencryptjob.cpp new file mode 100644 index 0000000..82c8ed8 --- /dev/null +++ b/lang/qt/src/qgpgmeencryptjob.cpp @@ -0,0 +1,170 @@ +/* + qgpgmeencryptjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeencryptjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "encryptionresult.h" +#include "data.h" + +#include <QBuffer> + + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEEncryptJob::QGpgMEEncryptJob(Context *context) + : mixin_type(context), + mOutputIsBase64Encoded(false) +{ + lateInitialization(); +} + +QGpgMEEncryptJob::~QGpgMEEncryptJob() {} + +void QGpgMEEncryptJob::setOutputIsBase64Encoded(bool on) +{ + mOutputIsBase64Encoded = on; +} + +static QGpgMEEncryptJob::result_type encrypt(Context *ctx, QThread *thread, + const std::vector<Key> &recipients, + const std::weak_ptr<QIODevice> &plainText_, + const std::weak_ptr<QIODevice> &cipherText_, + const Context::EncryptionFlags eflags, + bool outputIsBsse64Encoded) +{ + + const std::shared_ptr<QIODevice> plainText = plainText_.lock(); + const std::shared_ptr<QIODevice> cipherText = cipherText_.lock(); + + const _detail::ToThreadMover ctMover(cipherText, thread); + const _detail::ToThreadMover ptMover(plainText, thread); + + QGpgME::QIODeviceDataProvider in(plainText); + const Data indata(&in); + + if (!cipherText) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const EncryptionResult res = ctx->encrypt(recipients, indata, outdata, eflags); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(cipherText); + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const EncryptionResult res = ctx->encrypt(recipients, indata, outdata, eflags); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, QByteArray(), log, ae); + } + +} + +static QGpgMEEncryptJob::result_type encrypt_qba(Context *ctx, const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(plainText); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return encrypt(ctx, 0, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded); +} + +Error QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust) +{ + run(std::bind(&encrypt_qba, std::placeholders::_1, recipients, plainText, + alwaysTrust ? Context::AlwaysTrust : Context::None, mOutputIsBase64Encoded)); + return Error(); +} + +void QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText, const Context::EncryptionFlags eflags) +{ + run(std::bind(&encrypt, + std::placeholders::_1, std::placeholders::_2, + recipients, + std::placeholders::_3, std::placeholders::_4, + eflags, + mOutputIsBase64Encoded), + plainText, cipherText); +} + +EncryptionResult QGpgMEEncryptJob::exec(const std::vector<Key> &recipients, const QByteArray &plainText, + const Context::EncryptionFlags eflags, QByteArray &cipherText) +{ + const result_type r = encrypt_qba(context(), recipients, plainText, eflags, mOutputIsBase64Encoded); + cipherText = std::get<1>(r); + resultHook(r); + return mResult; +} + +void QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, bool alwaysTrust) +{ + return start(recipients, plainText, cipherText, alwaysTrust ? Context::AlwaysTrust : Context::None); +} + +EncryptionResult QGpgMEEncryptJob::exec(const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust, QByteArray &cipherText) +{ + return exec(recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, cipherText); +} + +void QGpgMEEncryptJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} + +#if 0 +void QGpgMEEncryptJob::showErrorDialog(QWidget *parent, const QString &caption) const +{ + if (mResult.error() && !mResult.error().isCanceled()) { + MessageBox::error(parent, mResult, this, caption); + } +} +#endif +#include "qgpgmeencryptjob.moc" diff --git a/lang/qt/src/qgpgmeencryptjob.h b/lang/qt/src/qgpgmeencryptjob.h new file mode 100644 index 0000000..42c1c78 --- /dev/null +++ b/lang/qt/src/qgpgmeencryptjob.h @@ -0,0 +1,109 @@ +/* + qgpgmeencryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEENCRYPTJOB_H__ +#define __QGPGME_QGPGMEENCRYPTJOB_H__ + +#include "encryptjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "encryptionresult.h" +#else +#include <gpgme++/encryptionresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMEEncryptJob +#ifdef Q_MOC_RUN + : public EncryptJob +#else + : public _detail::ThreadedJobMixin<EncryptJob, std::tuple<GpgME::EncryptionResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEEncryptJob(GpgME::Context *context); + ~QGpgMEEncryptJob(); + + /* from EncryptJob */ + GpgME::Error start(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, bool alwaysTrust) Q_DECL_OVERRIDE; + + /* from EncryptJob */ + void start(const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText, + bool alwaysTrust) Q_DECL_OVERRIDE; + + /* from EncryptJob */ + GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, bool alwaysTrust, + QByteArray &cipherText) Q_DECL_OVERRIDE; + /* from EncryptJob */ + void start(const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText, + const GpgME::Context::EncryptionFlags flags) Q_DECL_OVERRIDE; + + /* from EncryptJob */ + GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, const GpgME::Context::EncryptionFlags flags, + QByteArray &cipherText) Q_DECL_OVERRIDE; + + /* from EncryptJob */ + void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + bool mOutputIsBase64Encoded; + GpgME::EncryptionResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMEENCRYPTJOB_H__ diff --git a/lang/qt/src/qgpgmeexportjob.cpp b/lang/qt/src/qgpgmeexportjob.cpp new file mode 100644 index 0000000..dfc5fc9 --- /dev/null +++ b/lang/qt/src/qgpgmeexportjob.cpp @@ -0,0 +1,76 @@ +/* + qgpgmeexportjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeexportjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "key.h" + +#include <QStringList> + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEExportJob::QGpgMEExportJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEExportJob::~QGpgMEExportJob() {} + +static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns) +{ + + const _detail::PatternConverter pc(patterns); + + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + + const Error err = ctx->exportPublicKeys(pc.patterns(), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, dp.data(), log, ae); +} + +Error QGpgMEExportJob::start(const QStringList &patterns) +{ + run(std::bind(&export_qba, std::placeholders::_1, patterns)); + return Error(); +} +#include "qgpgmeexportjob.moc" diff --git a/lang/qt/src/qgpgmeexportjob.h b/lang/qt/src/qgpgmeexportjob.h new file mode 100644 index 0000000..7561054 --- /dev/null +++ b/lang/qt/src/qgpgmeexportjob.h @@ -0,0 +1,66 @@ +/* + qgpgmeexportjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEEXPORTJOB_H__ +#define __QGPGME_QGPGMEEXPORTJOB_H__ + +#include "exportjob.h" + +#include "threadedjobmixin.h" + +namespace QGpgME +{ + +class QGpgMEExportJob +#ifdef Q_MOC_RUN + : public ExportJob +#else + : public _detail::ThreadedJobMixin<ExportJob, std::tuple<GpgME::Error, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEExportJob(GpgME::Context *context); + ~QGpgMEExportJob(); + + /* from ExportJob */ + GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMEEXPORTJOB_H__ diff --git a/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp b/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp new file mode 100644 index 0000000..0f19679 --- /dev/null +++ b/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp @@ -0,0 +1,82 @@ +/* + qgpgmeimportfromkeyserverjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeimportfromkeyserverjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "key.h" + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEImportFromKeyserverJob::QGpgMEImportFromKeyserverJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEImportFromKeyserverJob::~QGpgMEImportFromKeyserverJob() {} + +static QGpgMEImportFromKeyserverJob::result_type importfromkeyserver(Context *ctx, const std::vector<Key> &keys) +{ + const ImportResult res = ctx->importKeys(keys); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, log, ae); +} + +Error QGpgMEImportFromKeyserverJob::start(const std::vector<Key> &keys) +{ + run(std::bind(&importfromkeyserver, std::placeholders::_1, keys)); + return Error(); +} + +GpgME::ImportResult QGpgME::QGpgMEImportFromKeyserverJob::exec(const std::vector<Key> &keys) +{ + const result_type r = importfromkeyserver(context(), keys); + resultHook(r); + return mResult; +} + +// PENDING(marc) implement showErrorDialog() + +void QGpgME::QGpgMEImportFromKeyserverJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} +#include "qgpgmeimportfromkeyserverjob.moc" diff --git a/lang/qt/src/qgpgmeimportfromkeyserverjob.h b/lang/qt/src/qgpgmeimportfromkeyserverjob.h new file mode 100644 index 0000000..8c9f944 --- /dev/null +++ b/lang/qt/src/qgpgmeimportfromkeyserverjob.h @@ -0,0 +1,81 @@ +/* + qgpgmeimportfromkeyserverjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__ +#define __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__ + +#include "importfromkeyserverjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "importresult.h" +#else +#include <gpgme++/importresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEImportFromKeyserverJob +#ifdef Q_MOC_RUN + : public ImportFromKeyserverJob +#else + : public _detail::ThreadedJobMixin<ImportFromKeyserverJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEImportFromKeyserverJob(GpgME::Context *context); + ~QGpgMEImportFromKeyserverJob(); + + /* from ImportFromKeyserverJob */ + GpgME::Error start(const std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE; + + /* from ImportFromKeyserverJob */ + GpgME::ImportResult exec(const std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::ImportResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__ diff --git a/lang/qt/src/qgpgmeimportjob.cpp b/lang/qt/src/qgpgmeimportjob.cpp new file mode 100644 index 0000000..f125b12 --- /dev/null +++ b/lang/qt/src/qgpgmeimportjob.cpp @@ -0,0 +1,85 @@ +/* + qgpgmeimportjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeimportjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "key.h" + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEImportJob::QGpgMEImportJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEImportJob::~QGpgMEImportJob() {} + +static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData) +{ + QGpgME::QByteArrayDataProvider dp(certData); + Data data(&dp); + + const ImportResult res = ctx->importKeys(data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, log, ae); +} + +Error QGpgMEImportJob::start(const QByteArray &certData) +{ + run(std::bind(&import_qba, std::placeholders::_1, certData)); + return Error(); +} + +GpgME::ImportResult QGpgME::QGpgMEImportJob::exec(const QByteArray &keyData) +{ + const result_type r = import_qba(context(), keyData); + resultHook(r); + return mResult; +} + +// PENDING(marc) implement showErrorDialog() + +void QGpgME::QGpgMEImportJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} +#include "qgpgmeimportjob.moc" diff --git a/lang/qt/src/qgpgmeimportjob.h b/lang/qt/src/qgpgmeimportjob.h new file mode 100644 index 0000000..424cb50 --- /dev/null +++ b/lang/qt/src/qgpgmeimportjob.h @@ -0,0 +1,81 @@ +/* + qgpgmeimportjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEIMPORTJOB_H__ +#define __QGPGME_QGPGMEIMPORTJOB_H__ + +#include "importjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "importresult.h" +#else +#include <gpgme++/importresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEImportJob +#ifdef Q_MOC_RUN + : public ImportJob +#else + : public _detail::ThreadedJobMixin<ImportJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEImportJob(GpgME::Context *context); + ~QGpgMEImportJob(); + + /* from ImportJob */ + GpgME::Error start(const QByteArray &keyData) Q_DECL_OVERRIDE; + + /* from ImportJob */ + GpgME::ImportResult exec(const QByteArray &keyData) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::ImportResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMEIMPORTJOB_H__ diff --git a/lang/qt/src/qgpgmekeyformailboxjob.cpp b/lang/qt/src/qgpgmekeyformailboxjob.cpp new file mode 100644 index 0000000..803d0e6 --- /dev/null +++ b/lang/qt/src/qgpgmekeyformailboxjob.cpp @@ -0,0 +1,138 @@ +/* + qgpgmekeyformailboxjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmekeyformailboxjob.h" +#include "qgpgmekeylistjob.h" + +#include <QStringList> + +#include <tuple> + +using namespace GpgME; +using namespace QGpgME; + +QGpgMEKeyForMailboxJob::QGpgMEKeyForMailboxJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEKeyForMailboxJob::~QGpgMEKeyForMailboxJob() {} + +static bool keyIsOk(const Key k) +{ + return !k.isExpired() && !k.isRevoked() && !k.isInvalid() && !k.isDisabled(); +} + +static bool uidIsOk(const UserID uid) +{ + return keyIsOk(uid.parent()) && !uid.isRevoked() && !uid.isInvalid(); +} + +static bool subkeyIsOk(const Subkey s) +{ + return !s.isRevoked() && !s.isInvalid() && !s.isDisabled(); +} + +static QGpgMEKeyForMailboxJob::result_type do_work(Context *ctx, const QString &mailbox, bool canEncrypt) +{ + /* Do a Keylisting. */ + ctx->setKeyListMode(GpgME::Extern | GpgME::Local | GpgME::Signatures | GpgME::Validate); + std::vector<Key> keys; + QGpgMEKeyListJob *keylist = new QGpgMEKeyListJob(ctx); + + KeyListResult result = keylist->exec(QStringList() << mailbox, false, keys); + + if (result.error()) { + return std::make_tuple(result, Key(), UserID(), QString(), Error()); + } + + // This should ideally be decided by GnuPG and this Job changed + // to just call the according API in GpgME + // See: https://bugs.gnupg.org/gnupg/issue2359 + Key keyC; + UserID uidC; + Q_FOREACH (const Key k, keys) { + if (canEncrypt && !k.canEncrypt()) { + continue; + } + /* First get the uid that matches the mailbox */ + Q_FOREACH (const UserID u, k.userIDs()) { + if (QString::fromUtf8(u.email()).toLower() == mailbox.toLower()) { + if (uidC.isNull()) { + keyC = k; + uidC = u; + } else if ((!uidIsOk(uidC) && uidIsOk(u)) || uidC.validity() < u.validity()) { + /* Validity of the new key is better. */ + uidC = u; + keyC = k; + } else if (uidC.validity() == u.validity() && uidIsOk(u)) { + /* Both are the same check which one is newer. */ + time_t oldTime = 0; + Q_FOREACH (const Subkey s, keyC.subkeys()) { + if ((canEncrypt && s.canEncrypt()) && subkeyIsOk(s)) { + oldTime = s.creationTime(); + } + } + time_t newTime = 0; + Q_FOREACH (const Subkey s, k.subkeys()) { + if ((canEncrypt && s.canEncrypt()) && subkeyIsOk(s)) { + newTime = s.creationTime(); + } + } + if (newTime > oldTime) { + uidC = u; + keyC = k; + } + } + } + } + } + return std::make_tuple(result, keyC, uidC, QString(), Error()); +} + +Error QGpgMEKeyForMailboxJob::start(const QString &mailbox, bool canEncrypt) +{ + run(std::bind(&do_work, std::placeholders::_1, mailbox, canEncrypt)); + return Error(); +} + +KeyListResult QGpgMEKeyForMailboxJob::exec(const QString &mailbox, bool canEncrypt, Key &key, UserID &uid) +{ + const result_type r = do_work(context(), mailbox, canEncrypt); + resultHook(r); + key = std::get<1>(r); + uid = std::get<2>(r); + return std::get<0>(r); +} + +#include "qgpgmekeyformailboxjob.moc" diff --git a/lang/qt/src/qgpgmekeyformailboxjob.h b/lang/qt/src/qgpgmekeyformailboxjob.h new file mode 100644 index 0000000..8ac2c1f --- /dev/null +++ b/lang/qt/src/qgpgmekeyformailboxjob.h @@ -0,0 +1,84 @@ +/* + qgpgmekeyformailboxjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEKEYFORMAILBOXJOB_H__ +#define __QGPGME_QGPGMEKEYFORMAILBOXJOB_H__ +#include "keyformailboxjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "keylistresult.h" +# include "key.h" +#else +# include <gpgme++/keylistresult.h> +# include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMEKeyForMailboxJob +#ifdef Q_MOC_RUN + : public KeyForMailboxJob +#else + : public _detail::ThreadedJobMixin<KeyForMailboxJob, std::tuple<GpgME::KeyListResult, GpgME::Key, GpgME::UserID, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEKeyForMailboxJob(GpgME::Context *context); + ~QGpgMEKeyForMailboxJob(); + + /** + Starts the operation. \a mailbox is the mailbox to + look for. + + The result is the same as for the LocateKeysJob. + + If \a canEncrypt is true, only keys that have a subkey for encryption + usage are returned. Use this if you need to select a + key for signing. + */ + GpgME::Error start(const QString &mailbox, bool canEncrypt = true) Q_DECL_OVERRIDE; + + GpgME::KeyListResult exec(const QString &mailbox, bool canEncrypt, GpgME::Key &key, GpgME::UserID &uid) Q_DECL_OVERRIDE; +}; + +} +#endif diff --git a/lang/qt/src/qgpgmekeygenerationjob.cpp b/lang/qt/src/qgpgmekeygenerationjob.cpp new file mode 100644 index 0000000..cba6b76 --- /dev/null +++ b/lang/qt/src/qgpgmekeygenerationjob.cpp @@ -0,0 +1,71 @@ +/* + qgpgmekeygenerationjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmekeygenerationjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEKeyGenerationJob::QGpgMEKeyGenerationJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEKeyGenerationJob::~QGpgMEKeyGenerationJob() {} + +static QGpgMEKeyGenerationJob::result_type generate_key(Context *ctx, const QString ¶meters) +{ + QGpgME::QByteArrayDataProvider dp; + Data data = ctx->protocol() == CMS ? Data(&dp) : Data(Data::null); + assert(data.isNull() == (ctx->protocol() != CMS)); + + const KeyGenerationResult res = ctx->generateKey(parameters.toUtf8().constData(), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, dp.data(), log, ae); +} + +Error QGpgMEKeyGenerationJob::start(const QString ¶meters) +{ + run(std::bind(&generate_key, std::placeholders::_1, parameters)); + return Error(); +} +#include "qgpgmekeygenerationjob.moc" diff --git a/lang/qt/src/qgpgmekeygenerationjob.h b/lang/qt/src/qgpgmekeygenerationjob.h new file mode 100644 index 0000000..808b714 --- /dev/null +++ b/lang/qt/src/qgpgmekeygenerationjob.h @@ -0,0 +1,72 @@ +/* + qgpgmekeygenerationjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEKEYGENERATIONJOB_H__ +#define __QGPGME_QGPGMEKEYGENERATIONJOB_H__ + +#include "keygenerationjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "keygenerationresult.h" +#else +#include <gpgme++/keygenerationresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEKeyGenerationJob +#ifdef Q_MOC_RUN + : public KeyGenerationJob +#else + : public _detail::ThreadedJobMixin<KeyGenerationJob, std::tuple<GpgME::KeyGenerationResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +private Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEKeyGenerationJob(GpgME::Context *context); + ~QGpgMEKeyGenerationJob(); + + /* from KeygenerationJob */ + GpgME::Error start(const QString ¶meters) Q_DECL_OVERRIDE; +}; + +} + +#endif // __QGPGME_QGPGMEKEYGENERATIONJOB_H__ diff --git a/lang/qt/src/qgpgmekeylistjob.cpp b/lang/qt/src/qgpgmekeylistjob.cpp new file mode 100644 index 0000000..1169c46 --- /dev/null +++ b/lang/qt/src/qgpgmekeylistjob.cpp @@ -0,0 +1,172 @@ +/* + qgpgmekeylistjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmekeylistjob.h" + +#include "key.h" +#include "context.h" +#include "keylistresult.h" +#include <gpg-error.h> + +#include <QStringList> + +#include <algorithm> + +#include <cstdlib> +#include <cstring> +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEKeyListJob::QGpgMEKeyListJob(Context *context) + : mixin_type(context), + mResult(), mSecretOnly(false) +{ + lateInitialization(); +} + +QGpgMEKeyListJob::~QGpgMEKeyListJob() {} + +static KeyListResult do_list_keys(Context *ctx, const QStringList &pats, std::vector<Key> &keys, bool secretOnly) +{ + + const _detail::PatternConverter pc(pats); + + if (const Error err = ctx->startKeyListing(pc.patterns(), secretOnly)) { + return KeyListResult(0, err); + } + + Error err; + do { + keys.push_back(ctx->nextKey(err)); + } while (!err); + + keys.pop_back(); + + const KeyListResult result = ctx->endKeyListing(); + ctx->cancelPendingOperation(); + return result; +} + +static QGpgMEKeyListJob::result_type list_keys(Context *ctx, QStringList pats, bool secretOnly) +{ + if (pats.size() < 2) { + std::vector<Key> keys; + const KeyListResult r = do_list_keys(ctx, pats, keys, secretOnly); + return std::make_tuple(r, keys, QString(), Error()); + } + + // The communication channel between gpgme and gpgsm is limited in + // the number of patterns that can be transported, but they won't + // say to how much, so we need to find out ourselves if we get a + // LINE_TOO_LONG error back... + + // We could of course just feed them single patterns, and that would + // probably be easier, but the performance penalty would currently + // be noticeable. + + unsigned int chunkSize = pats.size(); +retry: + std::vector<Key> keys; + keys.reserve(pats.size()); + KeyListResult result; + do { + const KeyListResult this_result = do_list_keys(ctx, pats.mid(0, chunkSize), keys, secretOnly); + if (this_result.error().code() == GPG_ERR_LINE_TOO_LONG) { + // got LINE_TOO_LONG, try a smaller chunksize: + chunkSize /= 2; + if (chunkSize < 1) + // chunks smaller than one can't be -> return the error. + { + return std::make_tuple(this_result, keys, QString(), Error()); + } else { + goto retry; + } + } else if (this_result.error().code() == GPG_ERR_EOF) { + // early end of keylisting (can happen when ~/.gnupg doesn't + // exist). Fakeing an empty result: + return std::make_tuple(KeyListResult(), std::vector<Key>(), QString(), Error()); + } + // ok, that seemed to work... + result.mergeWith(this_result); + if (result.error().code()) { + break; + } + pats = pats.mid(chunkSize); + } while (!pats.empty()); + return std::make_tuple(result, keys, QString(), Error()); +} + +Error QGpgMEKeyListJob::start(const QStringList &patterns, bool secretOnly) +{ + mSecretOnly = secretOnly; + run(std::bind(&list_keys, std::placeholders::_1, patterns, secretOnly)); + return Error(); +} + +KeyListResult QGpgMEKeyListJob::exec(const QStringList &patterns, bool secretOnly, std::vector<Key> &keys) +{ + mSecretOnly = secretOnly; + const result_type r = list_keys(context(), patterns, secretOnly); + resultHook(r); + keys = std::get<1>(r); + return std::get<0>(r); +} + +void QGpgMEKeyListJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); + Q_FOREACH (const Key &key, std::get<1>(tuple)) { + Q_EMIT nextKey(key); + } +} + +void QGpgMEKeyListJob::addMode(KeyListMode mode) +{ + context()->addKeyListMode(mode); +} +#if 0 +void QGpgMEKeyListJob::showErrorDialog(QWidget *parent, const QString &caption) const +{ + if (!mResult.error() || mResult.error().isCanceled()) { + return; + } + const QString msg = i18n("<qt><p>An error occurred while fetching " + "the keys from the backend:</p>" + "<p><b>%1</b></p></qt>", + QString::fromLocal8Bit(mResult.error().asString())); + KMessageBox::error(parent, msg, caption); +} +#endif +#include "qgpgmekeylistjob.moc" diff --git a/lang/qt/src/qgpgmekeylistjob.h b/lang/qt/src/qgpgmekeylistjob.h new file mode 100644 index 0000000..2d5406a --- /dev/null +++ b/lang/qt/src/qgpgmekeylistjob.h @@ -0,0 +1,88 @@ +/* + qgpgmekeylistjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEKEYLISTJOB_H__ +#define __QGPGME_QGPGMEKEYLISTJOB_H__ + +#include "keylistjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "keylistresult.h" +#else +#include <gpgme++/keylistresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMEKeyListJob +#ifdef Q_MOC_RUN + : public KeyListJob +#else + : public _detail::ThreadedJobMixin<KeyListJob, std::tuple<GpgME::KeyListResult, std::vector<GpgME::Key>, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEKeyListJob(GpgME::Context *context); + ~QGpgMEKeyListJob(); + + /* from KeyListJob */ + GpgME::Error start(const QStringList &patterns, bool secretOnly) Q_DECL_OVERRIDE; + + /* from KeyListJob */ + GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly, std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE; + + void addMode(GpgME::KeyListMode mode) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &result) Q_DECL_OVERRIDE; +private: + GpgME::KeyListResult mResult; + bool mSecretOnly; +}; + +} + +#endif // __QGPGME_QGPGMEKEYLISTJOB_H__ diff --git a/lang/qt/src/qgpgmelistallkeysjob.cpp b/lang/qt/src/qgpgmelistallkeysjob.cpp new file mode 100644 index 0000000..fd8bfc3 --- /dev/null +++ b/lang/qt/src/qgpgmelistallkeysjob.cpp @@ -0,0 +1,168 @@ +/* + qgpgmelistallkeysjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmelistallkeysjob.h" + +#include "key.h" +#include "context.h" +#include "keylistresult.h" +#include <gpg-error.h> + +#include <algorithm> + +#include <cstdlib> +#include <cstring> +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEListAllKeysJob::QGpgMEListAllKeysJob(Context *context) + : mixin_type(context), + mResult() +{ + lateInitialization(); +} + +QGpgMEListAllKeysJob::~QGpgMEListAllKeysJob() {} + +static KeyListResult do_list_keys(Context *ctx, std::vector<Key> &keys, bool secretOnly) +{ + + const char **pat = 0; + if (const Error err = ctx->startKeyListing(pat, secretOnly)) { + return KeyListResult(0, err); + } + + Error err; + do { + keys.push_back(ctx->nextKey(err)); + } while (!err); + + keys.pop_back(); + + const KeyListResult result = ctx->endKeyListing(); + ctx->cancelPendingOperation(); + return result; +} + +namespace +{ + +template <typename ForwardIterator, typename BinaryPredicate> +ForwardIterator unique_by_merge(ForwardIterator first, ForwardIterator last, BinaryPredicate pred) +{ + first = std::adjacent_find(first, last, pred); + if (first == last) { + return last; + } + + ForwardIterator dest = first; + dest->mergeWith(*++first); + while (++first != last) + if (pred(*dest, *first)) { + dest->mergeWith(*first); + } else { + *++dest = *first; + } + return ++dest; +} + +} + +static void merge_keys(std::vector<Key> &merged, std::vector<Key> &pub, std::vector<Key> &sec) +{ + merged.reserve(pub.size() + sec.size()); + + std::merge(pub.begin(), pub.end(), + sec.begin(), sec.end(), + std::back_inserter(merged), + ByFingerprint<std::less>()); + + merged.erase(unique_by_merge(merged.begin(), merged.end(), ByFingerprint<std::equal_to>()), + merged.end()); +} + +static QGpgMEListAllKeysJob::result_type list_keys(Context *ctx, bool mergeKeys) +{ + std::vector<Key> pub, sec, merged; + KeyListResult r; + + r.mergeWith(do_list_keys(ctx, pub, false)); + std::sort(pub.begin(), pub.end(), ByFingerprint<std::less>()); + + r.mergeWith(do_list_keys(ctx, sec, true)); + std::sort(sec.begin(), sec.end(), ByFingerprint<std::less>()); + + if (mergeKeys) { + merge_keys(merged, pub, sec); + } else { + merged.swap(pub); + } + return std::make_tuple(r, merged, sec, QString(), Error()); +} + +Error QGpgMEListAllKeysJob::start(bool mergeKeys) +{ + run(std::bind(&list_keys, std::placeholders::_1, mergeKeys)); + return Error(); +} + +KeyListResult QGpgMEListAllKeysJob::exec(std::vector<Key> &pub, std::vector<Key> &sec, bool mergeKeys) +{ + const result_type r = list_keys(context(), mergeKeys); + resultHook(r); + pub = std::get<1>(r); + sec = std::get<2>(r); + return std::get<0>(r); +} + +void QGpgMEListAllKeysJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} + +#if 0 +void QGpgMEListAllKeysJob::showErrorDialog(QWidget *parent, const QString &caption) const +{ + if (!mResult.error() || mResult.error().isCanceled()) { + return; + } + const QString msg = i18n("<qt><p>An error occurred while fetching " + "the keys from the backend:</p>" + "<p><b>%1</b></p></qt>", + QString::fromLocal8Bit(mResult.error().asString())); + KMessageBox::error(parent, msg, caption); +} +#endif +#include "qgpgmelistallkeysjob.moc" diff --git a/lang/qt/src/qgpgmelistallkeysjob.h b/lang/qt/src/qgpgmelistallkeysjob.h new file mode 100644 index 0000000..1fc69d4 --- /dev/null +++ b/lang/qt/src/qgpgmelistallkeysjob.h @@ -0,0 +1,86 @@ +/* + qgpgmelistallkeysjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMELISTALLKEYSJOB_H__ +#define __QGPGME_QGPGMELISTALLKEYSJOB_H__ + +#include "listallkeysjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "keylistresult.h" +#else +#include <gpgme++/keylistresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMEListAllKeysJob +#ifdef Q_MOC_RUN + : public ListAllKeysJob +#else + : public _detail::ThreadedJobMixin<ListAllKeysJob, std::tuple<GpgME::KeyListResult, std::vector<GpgME::Key>, std::vector<GpgME::Key>, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEListAllKeysJob(GpgME::Context *context); + ~QGpgMEListAllKeysJob(); + + /* from ListAllKeysJob */ + GpgME::Error start(bool mergeKeys) Q_DECL_OVERRIDE; + + /* from ListAllKeysJob */ + GpgME::KeyListResult exec(std::vector<GpgME::Key> &pub, std::vector<GpgME::Key> &sec, bool mergeKeys) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &result) Q_DECL_OVERRIDE; + +private: + GpgME::KeyListResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMELISTALLKEYSJOB_H__ diff --git a/lang/qt/src/qgpgmenewcryptoconfig.cpp b/lang/qt/src/qgpgmenewcryptoconfig.cpp new file mode 100644 index 0000000..7303f10 --- /dev/null +++ b/lang/qt/src/qgpgmenewcryptoconfig.cpp @@ -0,0 +1,738 @@ +/* + qgpgmenewcryptoconfig.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2010 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmenewcryptoconfig.h" + +#include <QDebug> +#include "gpgme_backend_debug.h" + +#include <QFile> + +#include "global.h" +#include "error.h" + + +#include <sstream> +#include <string> +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; +using namespace GpgME::Configuration; + +namespace +{ +struct Select1St { + template <typename U, typename V> + const U &operator()(const std::pair<U, V> &p) const + { + return p.first; + } + template <typename U, typename V> + const U &operator()(const QPair<U, V> &p) const + { + return p.first; + } +}; +} + +// Just for the Q_ASSERT in the dtor. Not thread-safe, but who would +// have 2 threads talking to gpgconf anyway? :) +static bool s_duringClear = false; + +QGpgMENewCryptoConfig::QGpgMENewCryptoConfig() + : m_parsed(false) +{ +} + +QGpgMENewCryptoConfig::~QGpgMENewCryptoConfig() +{ + clear(); +} + +void QGpgMENewCryptoConfig::reloadConfiguration(bool showErrors) +{ + clear(); + + Error error; + const std::vector<Component> components = Component::load(error); +#ifndef NDEBUG + { + std::stringstream ss; + ss << "error: " << error + << "components:\n"; + std::copy(components.begin(), components.end(), + std::ostream_iterator<Component>(ss, "\n")); + qCDebug(GPGPME_BACKEND_LOG) << ss.str().c_str(); + } +#endif +#if 0 + TODO port? + if (error && showErrors) { + const QString wmsg = i18n("<qt>Failed to execute gpgconf:<p>%1</p></qt>", QString::fromLocal8Bit(error.asString())); + qCWarning(GPGPME_BACKEND_LOG) << wmsg; // to see it from test_cryptoconfig.cpp + KMessageBox::error(0, wmsg); + } +#endif + Q_FOREACH(const Component & c, components) { + const std::shared_ptr<QGpgMENewCryptoConfigComponent> comp(new QGpgMENewCryptoConfigComponent); + comp->setComponent(c); + m_componentsByName[ comp->name() ] = comp; + } + m_parsed = true; +} + +QStringList QGpgMENewCryptoConfig::componentList() const +{ + if (!m_parsed) { + const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(true); + } + QStringList result; + std::transform(m_componentsByName.begin(), m_componentsByName.end(), + std::back_inserter(result), + mem_fn(&QGpgMENewCryptoConfigComponent::name)); + return result; +} + +QGpgMENewCryptoConfigComponent *QGpgMENewCryptoConfig::component(const QString &name) const +{ + if (!m_parsed) { + const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(false); + } + return m_componentsByName.value(name).get(); +} + +void QGpgMENewCryptoConfig::sync(bool runtime) +{ + Q_FOREACH(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &c, m_componentsByName) + c->sync(runtime); +} + +void QGpgMENewCryptoConfig::clear() +{ + s_duringClear = true; + m_componentsByName.clear(); + s_duringClear = false; + m_parsed = false; // next call to componentList/component will need to run gpgconf again +} + +//// + +QGpgMENewCryptoConfigComponent::QGpgMENewCryptoConfigComponent() + : CryptoConfigComponent(), + m_component() +{ + +} + +void QGpgMENewCryptoConfigComponent::setComponent(const Component &component) +{ + m_component = component; + m_groupsByName.clear(); + + std::shared_ptr<QGpgMENewCryptoConfigGroup> group; + + const std::vector<Option> options = m_component.options(); + Q_FOREACH(const Option & o, options) + if (o.flags() & Group) { + if (group) { + m_groupsByName[group->name()] = group; + } + group.reset(new QGpgMENewCryptoConfigGroup(shared_from_this(), o)); + } else if (group) { + const std::shared_ptr<QGpgMENewCryptoConfigEntry> entry(new QGpgMENewCryptoConfigEntry(group, o)); + const QString name = entry->name(); + group->m_entryNames.push_back(name); + group->m_entriesByName[name] = entry; + } else { + qCWarning(GPGPME_BACKEND_LOG) << "found no group for entry" << o.name() << "of component" << name(); + } + if (group) { + m_groupsByName[group->name()] = group; + } + +} + +QGpgMENewCryptoConfigComponent::~QGpgMENewCryptoConfigComponent() {} + +QString QGpgMENewCryptoConfigComponent::name() const +{ + return QString::fromUtf8(m_component.name()); +} + +QString QGpgMENewCryptoConfigComponent::description() const +{ + return QString::fromUtf8(m_component.description()); +} + +QStringList QGpgMENewCryptoConfigComponent::groupList() const +{ + QStringList result; + result.reserve(m_groupsByName.size()); + std::transform(m_groupsByName.begin(), m_groupsByName.end(), + std::back_inserter(result), + std::mem_fn(&QGpgMENewCryptoConfigGroup::name)); + return result; +} + +QGpgMENewCryptoConfigGroup *QGpgMENewCryptoConfigComponent::group(const QString &name) const +{ + return m_groupsByName.value(name).get(); +} + +void QGpgMENewCryptoConfigComponent::sync(bool runtime) +{ + Q_UNUSED(runtime) + // ### how to pass --runtime to gpgconf? -> marcus: not yet supported (2010-11-20) + if (const Error err = m_component.save()) { +#if 0 + TODO port + const QString wmsg = i18n("Error from gpgconf while saving configuration: %1", QString::fromLocal8Bit(err.asString())); + qCWarning(GPGPME_BACKEND_LOG) << ":" << wmsg; + KMessageBox::error(0, wmsg); +#endif + } + // ### unset dirty state again +} + +//// + +QGpgMENewCryptoConfigGroup::QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &comp, const Option &option) + : CryptoConfigGroup(), + m_component(comp), + m_option(option) +{ +} + +QGpgMENewCryptoConfigGroup::~QGpgMENewCryptoConfigGroup() {} + +QString QGpgMENewCryptoConfigGroup::name() const +{ + return QString::fromUtf8(m_option.name()); +} + +QString QGpgMENewCryptoConfigGroup::description() const +{ + return QString::fromUtf8(m_option.description()); +} + +QString QGpgMENewCryptoConfigGroup::path() const +{ + if (const std::shared_ptr<QGpgMENewCryptoConfigComponent> c = m_component.lock()) { + return c->name() + QLatin1Char('/') + name(); + } else { + return QString(); + } +} + +CryptoConfigEntry::Level QGpgMENewCryptoConfigGroup::level() const +{ + // two casts to make SunCC happy: + return static_cast<CryptoConfigEntry::Level>(static_cast<unsigned int>(m_option.level())); +} + +QStringList QGpgMENewCryptoConfigGroup::entryList() const +{ + return m_entryNames; +} + +QGpgMENewCryptoConfigEntry *QGpgMENewCryptoConfigGroup::entry(const QString &name) const +{ + return m_entriesByName.value(name).get(); +} + +static QString urlpart_encode(const QString &str) +{ + QString enc(str); + enc.replace(QLatin1Char('%'), QStringLiteral("%25")); // first! + enc.replace(QLatin1Char(':'), QStringLiteral("%3a")); + //qCDebug(GPGPME_BACKEND_LOG) <<" urlpart_encode:" << str <<" ->" << enc; + return enc; +} + +static QString urlpart_decode(const QString &str) +{ + return QUrl::fromPercentEncoding(str.toLatin1()); +} + +// gpgconf arg type number -> NewCryptoConfigEntry arg type enum mapping +static QGpgME::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok) +{ + ok = true; + switch (argType) { + case 0: // none + return QGpgME::CryptoConfigEntry::ArgType_None; + case 1: // string + return QGpgME::CryptoConfigEntry::ArgType_String; + case 2: // int32 + return QGpgME::CryptoConfigEntry::ArgType_Int; + case 3: // uint32 + return QGpgME::CryptoConfigEntry::ArgType_UInt; + case 32: // pathname + return QGpgME::CryptoConfigEntry::ArgType_Path; + case 33: // ldap server + return QGpgME::CryptoConfigEntry::ArgType_LDAPURL; + default: + ok = false; + return QGpgME::CryptoConfigEntry::ArgType_None; + } +} + +QGpgMENewCryptoConfigEntry::QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const Option &option) + : m_group(group), m_option(option) +{ +} + +#if 0 +QVariant QGpgMENewCryptoConfigEntry::stringToValue(const QString &str, bool unescape) const +{ + const bool isString = isStringType(); + + if (isList()) { + if (argType() == ArgType_None) { + bool ok = true; + const QVariant v = str.isEmpty() ? 0U : str.toUInt(&ok); + if (!ok) { + qCWarning(GPGPME_BACKEND_LOG) << "list-of-none should have an unsigned int as value:" << str; + } + return v; + } + QList<QVariant> lst; + QStringList items = str.split(',', QString::SkipEmptyParts); + for (QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit) { + QString val = *valit; + if (isString) { + if (val.isEmpty()) { + lst << QVariant(QString()); + continue; + } else if (unescape) { + if (val[0] != '"') { // see README.gpgconf + qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val; + } + val = val.mid(1); + } + } + lst << QVariant(unescape ? gpgconf_unescape(val) : val); + } + return lst; + } else { // not a list + QString val(str); + if (isString) { + if (val.isEmpty()) { + return QVariant(QString()); // not set [ok with lists too?] + } else if (unescape) { + if (val[0] != '"') { // see README.gpgconf + qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val; + } + val = val.mid(1); + } + } + return QVariant(unescape ? gpgconf_unescape(val) : val); + } +} +#endif + +QGpgMENewCryptoConfigEntry::~QGpgMENewCryptoConfigEntry() +{ +#ifndef NDEBUG + if (!s_duringClear && m_option.dirty()) + qCWarning(GPGPME_BACKEND_LOG) << "Deleting a QGpgMENewCryptoConfigEntry that was modified (" << m_option.description() << ")" + << "You forgot to call sync() (to commit) or clear() (to discard)"; +#endif +} + +QString QGpgMENewCryptoConfigEntry::name() const +{ + return QString::fromUtf8(m_option.name()); +} + +QString QGpgMENewCryptoConfigEntry::description() const +{ + return QString::fromUtf8(m_option.description()); +} + +QString QGpgMENewCryptoConfigEntry::path() const +{ + if (const std::shared_ptr<QGpgMENewCryptoConfigGroup> g = m_group.lock()) { + return g->path() + QLatin1Char('/') + name(); + } else { + return QString(); + } +} + +bool QGpgMENewCryptoConfigEntry::isOptional() const +{ + return m_option.flags() & Optional; +} + +bool QGpgMENewCryptoConfigEntry::isReadOnly() const +{ + return m_option.flags() & NoChange; +} + +bool QGpgMENewCryptoConfigEntry::isList() const +{ + return m_option.flags() & List; +} + +bool QGpgMENewCryptoConfigEntry::isRuntime() const +{ + return m_option.flags() & Runtime; +} + +CryptoConfigEntry::Level QGpgMENewCryptoConfigEntry::level() const +{ + // two casts to make SunCC happy: + return static_cast<Level>(static_cast<unsigned int>(m_option.level())); +} + +CryptoConfigEntry::ArgType QGpgMENewCryptoConfigEntry::argType() const +{ + bool ok = false; + const ArgType type = knownArgType(m_option.type(), ok); + if (ok) { + return type; + } else { + return knownArgType(m_option.alternateType(), ok); + } +} + +bool QGpgMENewCryptoConfigEntry::isSet() const +{ + return m_option.set(); +} + +bool QGpgMENewCryptoConfigEntry::boolValue() const +{ + Q_ASSERT(m_option.alternateType() == NoType); + Q_ASSERT(!isList()); + return m_option.currentValue().boolValue(); +} + +QString QGpgMENewCryptoConfigEntry::stringValue() const +{ + //return toString( false ); + Q_ASSERT(m_option.alternateType() == StringType); + Q_ASSERT(!isList()); + return QString::fromUtf8(m_option.currentValue().stringValue()); +} + +int QGpgMENewCryptoConfigEntry::intValue() const +{ + Q_ASSERT(m_option.alternateType() == IntegerType); + Q_ASSERT(!isList()); + return m_option.currentValue().intValue(); +} + +unsigned int QGpgMENewCryptoConfigEntry::uintValue() const +{ + Q_ASSERT(m_option.alternateType() == UnsignedIntegerType); + Q_ASSERT(!isList()); + return m_option.currentValue().uintValue(); +} + +static QUrl parseURL(int mRealArgType, const QString &str) +{ + if (mRealArgType == 33) { // LDAP server + // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN + QStringList items = str.split(QLatin1Char(':')); + if (items.count() == 5) { + QStringList::const_iterator it = items.constBegin(); + QUrl url; + url.setScheme(QStringLiteral("ldap")); + url.setHost(urlpart_decode(*it++)); + + bool ok; + const int port = (*it++).toInt(&ok); + if (ok) { + url.setPort(port); + } else if (!it->isEmpty()) { + qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\""; + } + + const QString userName = urlpart_decode(*it++); + if (!userName.isEmpty()) { + url.setUserName(userName); + } + const QString passWord = urlpart_decode(*it++); + if (!passWord.isEmpty()) { + url.setPassword(passWord); + } + url.setQuery(urlpart_decode(*it)); + return url; + } else { + qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server:" << str; + } + } + // other URLs : assume wellformed URL syntax. + return QUrl(str); +} + +// The opposite of parseURL +static QString splitURL(int mRealArgType, const QUrl &url) +{ + if (mRealArgType == 33) { // LDAP server + // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN + Q_ASSERT(url.scheme() == QLatin1String("ldap")); + return urlpart_encode(url.host()) + QLatin1Char(':') + + (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') + // -1 is used for default ports, omit + urlpart_encode(url.userName()) + QLatin1Char(':') + + urlpart_encode(url.password()) + QLatin1Char(':') + + urlpart_encode(url.query()); + } + return url.path(); +} + +QUrl QGpgMENewCryptoConfigEntry::urlValue() const +{ + const Type type = m_option.type(); + Q_ASSERT(type == FilenameType || type == LdapServerType); + Q_ASSERT(!isList()); + if (type == FilenameType) { + QUrl url; + url.setPath(QFile::decodeName(m_option.currentValue().stringValue())); + return url; + } + return parseURL(type, stringValue()); +} + +unsigned int QGpgMENewCryptoConfigEntry::numberOfTimesSet() const +{ + Q_ASSERT(m_option.alternateType() == NoType); + Q_ASSERT(isList()); + return m_option.currentValue().uintValue(); +} + +std::vector<int> QGpgMENewCryptoConfigEntry::intValueList() const +{ + Q_ASSERT(m_option.alternateType() == IntegerType); + Q_ASSERT(isList()); + return m_option.currentValue().intValues(); +} + +std::vector<unsigned int> QGpgMENewCryptoConfigEntry::uintValueList() const +{ + Q_ASSERT(m_option.alternateType() == UnsignedIntegerType); + Q_ASSERT(isList()); + return m_option.currentValue().uintValues(); +} + +QList<QUrl> QGpgMENewCryptoConfigEntry::urlValueList() const +{ + const Type type = m_option.type(); + Q_ASSERT(type == FilenameType || type == LdapServerType); + Q_ASSERT(isList()); + const Argument arg = m_option.currentValue(); + const std::vector<const char *> values = arg.stringValues(); + QList<QUrl> ret; + Q_FOREACH(const char *value, values) + if (type == FilenameType) { + QUrl url; + url.setPath(QFile::decodeName(value)); + ret << url; + } else { + ret << parseURL(type, QString::fromUtf8(value)); + } + return ret; +} + +void QGpgMENewCryptoConfigEntry::resetToDefault() +{ + m_option.resetToDefaultValue(); +} + +void QGpgMENewCryptoConfigEntry::setBoolValue(bool b) +{ + Q_ASSERT(m_option.alternateType() == NoType); + Q_ASSERT(!isList()); + // A "no arg" option is either set or not set. + // Being set means createNoneArgument(), being unset means resetToDefault() + m_option.setNewValue(m_option.createNoneArgument(b)); +} + +void QGpgMENewCryptoConfigEntry::setStringValue(const QString &str) +{ + Q_ASSERT(m_option.alternateType() == StringType); + Q_ASSERT(!isList()); + const Type type = m_option.type(); + // When setting a string to empty (and there's no default), we need to act like resetToDefault + // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers: + // "gpgconf: argument required for option ocsp-responder" + if (str.isEmpty() && !isOptional()) { + m_option.resetToDefaultValue(); + } else if (type == FilenameType) { + m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData())); + } else { + m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData())); + } +} + +void QGpgMENewCryptoConfigEntry::setIntValue(int i) +{ + Q_ASSERT(m_option.alternateType() == IntegerType); + Q_ASSERT(!isList()); + m_option.setNewValue(m_option.createIntArgument(i)); +} + +void QGpgMENewCryptoConfigEntry::setUIntValue(unsigned int i) +{ + Q_ASSERT(m_option.alternateType() == UnsignedIntegerType); + Q_ASSERT(!isList()); + m_option.setNewValue(m_option.createUIntArgument(i)); +} + +void QGpgMENewCryptoConfigEntry::setURLValue(const QUrl &url) +{ + const Type type = m_option.type(); + Q_ASSERT(type == FilenameType || type == LdapServerType); + Q_ASSERT(!isList()); + const QString str = splitURL(type, url); + // cf. setStringValue() + if (str.isEmpty() && !isOptional()) { + m_option.resetToDefaultValue(); + } else if (type == FilenameType) { + m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData())); + } else { + m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData())); + } +} + +void QGpgMENewCryptoConfigEntry::setNumberOfTimesSet(unsigned int i) +{ + Q_ASSERT(m_option.alternateType() == NoType); + Q_ASSERT(isList()); + m_option.setNewValue(m_option.createNoneListArgument(i)); +} + +void QGpgMENewCryptoConfigEntry::setIntValueList(const std::vector<int> &lst) +{ + Q_ASSERT(m_option.alternateType() == IntegerType); + Q_ASSERT(isList()); + m_option.setNewValue(m_option.createIntListArgument(lst)); +} + +void QGpgMENewCryptoConfigEntry::setUIntValueList(const std::vector<unsigned int> &lst) +{ + Q_ASSERT(m_option.alternateType() == UnsignedIntegerType); + Q_ASSERT(isList()); + m_option.setNewValue(m_option.createUIntListArgument(lst)); +} + +void QGpgMENewCryptoConfigEntry::setURLValueList(const QList<QUrl> &urls) +{ + const Type type = m_option.type(); + Q_ASSERT(m_option.alternateType() == StringType); + Q_ASSERT(isList()); + std::vector<std::string> values; + values.reserve(urls.size()); + Q_FOREACH (const QUrl &url, urls) + if (type == FilenameType) { + values.push_back(QFile::encodeName(url.path()).constData()); + } else { + values.push_back(splitURL(type, url).toUtf8().constData()); + } + m_option.setNewValue(m_option.createStringListArgument(values)); +} + +bool QGpgMENewCryptoConfigEntry::isDirty() const +{ + return m_option.dirty(); +} + +#if 0 +QString QGpgMENewCryptoConfigEntry::toString(bool escape) const +{ + // Basically the opposite of stringToValue + if (isStringType()) { + if (mValue.isNull()) { + return QString(); + } else if (isList()) { // string list + QStringList lst = mValue.toStringList(); + if (escape) { + for (QStringList::iterator it = lst.begin(); it != lst.end(); ++it) { + if (!(*it).isNull()) { + *it = gpgconf_escape(*it).prepend("\""); + } + } + } + QString res = lst.join(","); + //qCDebug(GPGPME_BACKEND_LOG) <<"toString:" << res; + return res; + } else { // normal string + QString res = mValue.toString(); + if (escape) { + res = gpgconf_escape(res).prepend("\""); + } + return res; + } + } + if (!isList()) { // non-list non-string + if (mArgType == ArgType_None) { + return mValue.toBool() ? QString::fromLatin1("1") : QString(); + } else { // some int + Q_ASSERT(mArgType == ArgType_Int || mArgType == ArgType_UInt); + return mValue.toString(); // int to string conversion + } + } + + // Lists (of other types than strings) + if (mArgType == ArgType_None) { + return QString::number(numberOfTimesSet()); + } + QStringList ret; + QList<QVariant> lst = mValue.toList(); + for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) { + ret << (*it).toString(); // QVariant does the conversion + } + return ret.join(","); +} + +QString QGpgMENewCryptoConfigEntry::outputString() const +{ + Q_ASSERT(mSet); + return toString(true); +} + +bool QGpgMENewCryptoConfigEntry::isStringType() const +{ + return (mArgType == QGpgME::NewCryptoConfigEntry::ArgType_String + || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_Path + || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_URL + || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_LDAPURL); +} + +void QGpgMENewCryptoConfigEntry::setDirty(bool b) +{ + mDirty = b; +} +#endif diff --git a/lang/qt/src/qgpgmenewcryptoconfig.h b/lang/qt/src/qgpgmenewcryptoconfig.h new file mode 100644 index 0000000..81b4cb4 --- /dev/null +++ b/lang/qt/src/qgpgmenewcryptoconfig.h @@ -0,0 +1,189 @@ +/* + qgpgmenewcryptoconfig.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2010 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef QGPGME_QGPGMENEWCRYPTOCONFIG_H +#define QGPGME_QGPGMENEWCRYPTOCONFIG_H + +#include "qgpgme_export.h" +#include "cryptoconfig.h" + +#include <QHash> +#include <QStringList> +#include <QVariant> + +#ifdef BUILDING_QGPGME +# include "configuration.h" +#else +# include <gpgme++/configuration.h> +#endif + + +#include <vector> +#include <utility> + +class QGpgMENewCryptoConfig; +class QGpgMENewCryptoConfigComponent; +class QGpgMENewCryptoConfigGroup; +class QGpgMENewCryptoConfigEntry; + +class QGpgMENewCryptoConfigEntry : public QGpgME::CryptoConfigEntry +{ +public: + QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const GpgME::Configuration::Option &option); + ~QGpgMENewCryptoConfigEntry(); + + QString name() const Q_DECL_OVERRIDE; + QString description() const Q_DECL_OVERRIDE; + QString path() const Q_DECL_OVERRIDE; + bool isOptional() const Q_DECL_OVERRIDE; + bool isReadOnly() const Q_DECL_OVERRIDE; + bool isList() const Q_DECL_OVERRIDE; + bool isRuntime() const Q_DECL_OVERRIDE; + Level level() const Q_DECL_OVERRIDE; + ArgType argType() const Q_DECL_OVERRIDE; + bool isSet() const Q_DECL_OVERRIDE; + bool boolValue() const Q_DECL_OVERRIDE; + QString stringValue() const Q_DECL_OVERRIDE; + int intValue() const Q_DECL_OVERRIDE; + unsigned int uintValue() const Q_DECL_OVERRIDE; + QUrl urlValue() const Q_DECL_OVERRIDE; + unsigned int numberOfTimesSet() const Q_DECL_OVERRIDE; + std::vector<int> intValueList() const Q_DECL_OVERRIDE; + std::vector<unsigned int> uintValueList() const Q_DECL_OVERRIDE; + QList<QUrl> urlValueList() const Q_DECL_OVERRIDE; + void resetToDefault() Q_DECL_OVERRIDE; + void setBoolValue(bool) Q_DECL_OVERRIDE; + void setStringValue(const QString &) Q_DECL_OVERRIDE; + void setIntValue(int) Q_DECL_OVERRIDE; + void setUIntValue(unsigned int) Q_DECL_OVERRIDE; + void setURLValue(const QUrl &) Q_DECL_OVERRIDE; + void setNumberOfTimesSet(unsigned int) Q_DECL_OVERRIDE; + void setIntValueList(const std::vector<int> &) Q_DECL_OVERRIDE; + void setUIntValueList(const std::vector<unsigned int> &) Q_DECL_OVERRIDE; + void setURLValueList(const QList<QUrl> &) Q_DECL_OVERRIDE; + bool isDirty() const Q_DECL_OVERRIDE; + +#if 0 + void setDirty(bool b); + QString outputString() const; + +protected: + bool isStringType() const; + QVariant stringToValue(const QString &value, bool unescape) const; + QString toString(bool escape) const; +#endif +private: + std::weak_ptr<QGpgMENewCryptoConfigGroup> m_group; + GpgME::Configuration::Option m_option; +}; + +class QGpgMENewCryptoConfigGroup : public QGpgME::CryptoConfigGroup +{ +public: + QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &parent, const GpgME::Configuration::Option &option); + ~QGpgMENewCryptoConfigGroup(); + + QString name() const Q_DECL_OVERRIDE; + QString iconName() const Q_DECL_OVERRIDE + { + return QString(); + } + QString description() const Q_DECL_OVERRIDE; + QString path() const Q_DECL_OVERRIDE; + QGpgME::CryptoConfigEntry::Level level() const Q_DECL_OVERRIDE; + QStringList entryList() const Q_DECL_OVERRIDE; + QGpgMENewCryptoConfigEntry *entry(const QString &name) const Q_DECL_OVERRIDE; + +private: + friend class QGpgMENewCryptoConfigComponent; // it adds the entries + std::weak_ptr<QGpgMENewCryptoConfigComponent> m_component; + GpgME::Configuration::Option m_option; + QStringList m_entryNames; + QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigEntry> > m_entriesByName; +}; + +/// For docu, see kleo/cryptoconfig.h +class QGpgMENewCryptoConfigComponent : public QGpgME::CryptoConfigComponent, public std::enable_shared_from_this<QGpgMENewCryptoConfigComponent> +{ +public: + QGpgMENewCryptoConfigComponent(); + ~QGpgMENewCryptoConfigComponent(); + + void setComponent(const GpgME::Configuration::Component &component); + + QString name() const Q_DECL_OVERRIDE; + QString iconName() const Q_DECL_OVERRIDE + { + return name(); + } + QString description() const Q_DECL_OVERRIDE; + QStringList groupList() const Q_DECL_OVERRIDE; + QGpgMENewCryptoConfigGroup *group(const QString &name) const Q_DECL_OVERRIDE; + + void sync(bool runtime); + +private: + GpgME::Configuration::Component m_component; + QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigGroup> > m_groupsByName; +}; + +/** + * CryptoConfig implementation around the gpgconf command-line tool + * For method docu, see kleo/cryptoconfig.h + */ +class QGPGME_EXPORT QGpgMENewCryptoConfig : public QGpgME::CryptoConfig +{ +public: + /** + * Constructor + */ + QGpgMENewCryptoConfig(); + ~QGpgMENewCryptoConfig(); + + QStringList componentList() const Q_DECL_OVERRIDE; + + QGpgMENewCryptoConfigComponent *component(const QString &name) const Q_DECL_OVERRIDE; + + void clear() Q_DECL_OVERRIDE; + void sync(bool runtime) Q_DECL_OVERRIDE; + +private: + /// @param showErrors if true, a messagebox will be shown if e.g. gpgconf wasn't found + void reloadConfiguration(bool showErrors); + +private: + QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigComponent> > m_componentsByName; + bool m_parsed; +}; + +#endif /* QGPGME_QGPGMENEWCRYPTOCONFIG_H */ diff --git a/lang/qt/src/qgpgmerefreshkeysjob.cpp b/lang/qt/src/qgpgmerefreshkeysjob.cpp new file mode 100644 index 0000000..3d221f6 --- /dev/null +++ b/lang/qt/src/qgpgmerefreshkeysjob.cpp @@ -0,0 +1,225 @@ +/* + qgpgmerefreshkeysjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klar�vdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#define MAX_CMD_LENGTH 32768 + +#include "qgpgmerefreshkeysjob.h" + +#include <QDebug> +#include "gpgme_backend_debug.h" + +#include "context.h" + +#include <QByteArray> +#include <QStringList> + +#include <gpg-error.h> + +#include <assert.h> + +QGpgME::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob() + : RefreshKeysJob(0), + mProcess(0), + mError(0) +{ + +} + +QGpgME::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob() +{ + +} + +GpgME::Error QGpgME::QGpgMERefreshKeysJob::start(const QStringList &patterns) +{ + assert(mPatternsToDo.empty()); + + mPatternsToDo = patterns; + if (mPatternsToDo.empty()) { + mPatternsToDo.push_back(QStringLiteral(" ")); // empty list means all -> mae + } + // sure to fail the first + // startAProcess() guard clause + + return startAProcess(); +} + +#if MAX_CMD_LENGTH < 65 + 128 +#error MAX_CMD_LENGTH is too low +#endif + +GpgME::Error QGpgME::QGpgMERefreshKeysJob::startAProcess() +{ + if (mPatternsToDo.empty()) { + return GpgME::Error(); + } + // create and start gpgsm process: + mProcess = new QProcess(this); + mProcess->setObjectName(QStringLiteral("gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks")); + + // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance. + mProcess->setProgram(QStringLiteral("gpgsm")); + QStringList arguments; + arguments << QStringLiteral("-k") + << QStringLiteral("--with-validation") + << QStringLiteral("--force-crl-refresh") + << QStringLiteral("--enable-crl-checks"); + unsigned int commandLineLength = MAX_CMD_LENGTH; + commandLineLength -= + strlen("gpgsm") + 1 + strlen("-k") + 1 + + strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 + + strlen("--enable-crl-checks") + 1; + while (!mPatternsToDo.empty()) { + const QByteArray pat = mPatternsToDo.front().toUtf8().trimmed(); + const unsigned int patLength = pat.length(); + if (patLength >= commandLineLength) { + break; + } + mPatternsToDo.pop_front(); + if (pat.isEmpty()) { + continue; + } + arguments << QLatin1String(pat); + commandLineLength -= patLength + 1; + } + + mProcess->setArguments(arguments); + + connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + SLOT(slotProcessExited(int,QProcess::ExitStatus))); + connect(mProcess, SIGNAL(readyReadStandardOutput()), + SLOT(slotStdout())); + connect(mProcess, &QProcess::readyReadStandardError, + this, &QGpgMERefreshKeysJob::slotStderr); + + mProcess->start(); + if (!mProcess->waitForStarted()) { + mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else? + deleteLater(); + return mError; + } else { + return GpgME::Error(); + } +} + +void QGpgME::QGpgMERefreshKeysJob::slotCancel() +{ + if (mProcess) { + mProcess->kill(); + } + mProcess = 0; + mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM); +} + +void QGpgME::QGpgMERefreshKeysJob::slotStatus(QProcess *proc, const QString &type, const QStringList &args) +{ + if (proc != mProcess) { + return; + } + QStringList::const_iterator it = args.begin(); + bool ok = false; + + if (type == QLatin1String("ERROR")) { + + if (args.size() < 2) { + qCDebug(GPGPME_BACKEND_LOG) << "not recognising ERROR with < 2 args!"; + return; + } + const int source = (*++it).toInt(&ok); + if (!ok) { + qCDebug(GPGPME_BACKEND_LOG) << "expected number for first ERROR arg, got something else"; + return; + } + ok = false; + const int code = (*++it).toInt(&ok); + if (!ok) { + qCDebug(GPGPME_BACKEND_LOG) << "expected number for second ERROR arg, got something else"; + return; + } + mError = GpgME::Error::fromCode(code, source); + + } else if (type == QLatin1String("PROGRESS")) { + + if (args.size() < 4) { + qCDebug(GPGPME_BACKEND_LOG) << "not recognising PROGRESS with < 4 args!"; + return; + } + const QString what = *++it; + ok = false; + (*++it).toInt(&ok); + if (!ok) { + qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"type\", got something else"; + return; + } + ok = false; + const int cur = (*++it).toInt(&ok); + if (!ok) { + qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"cur\", got something else"; + return; + } + ok = false; + const int total = (*++it).toInt(&ok); + if (!ok) { + qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"total\", got something else"; + return; + } + // TODO port + Q_EMIT progress(QString(), cur, total); + + } +} + +void QGpgME::QGpgMERefreshKeysJob::slotStderr() +{ + // implement? or not? +} + +void QGpgME::QGpgMERefreshKeysJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) +{ + if (!mError && !mPatternsToDo.empty()) { + if (const GpgME::Error err = startAProcess()) { + mError = err; + } else { + return; + } + } + + Q_EMIT done(); + if (!mError && + (exitStatus != QProcess::NormalExit || exitCode != 0)) { + mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM); + } + Q_EMIT result(mError); + deleteLater(); +} +#include "qgpgmerefreshkeysjob.moc" diff --git a/lang/qt/src/qgpgmerefreshkeysjob.h b/lang/qt/src/qgpgmerefreshkeysjob.h new file mode 100644 index 0000000..2a54e38 --- /dev/null +++ b/lang/qt/src/qgpgmerefreshkeysjob.h @@ -0,0 +1,79 @@ +/* + qgpgmerefreshkeysjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEREFRESHKEYSJOB_H__ +#define __QGPGME_QGPGMEREFRESHKEYSJOB_H__ + +#include "refreshkeysjob.h" +#ifdef BUILDING_QGPGME +# include "context.h" +#else +#include "gpgme++/context.h" +#endif + +#include <QStringList> +#include <QProcess> + +namespace QGpgME +{ + +class QGpgMERefreshKeysJob : public RefreshKeysJob +{ + Q_OBJECT +public: + QGpgMERefreshKeysJob(); + ~QGpgMERefreshKeysJob(); + + /* from RefreshKeysJob */ + GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE; + +private Q_SLOTS: + /* from Job */ + void slotCancel() Q_DECL_OVERRIDE; + + void slotStatus(QProcess *, const QString &, const QStringList &); + void slotStderr(); + void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus); + +private: + GpgME::Error startAProcess(); + +private: + QProcess *mProcess; + GpgME::Error mError; + QStringList mPatternsToDo; +}; + +} + +#endif // __QGPGME_QGPGMEREFRESHKEYSJOB_H__ diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.cpp b/lang/qt/src/qgpgmesecretkeyexportjob.cpp new file mode 100644 index 0000000..f4ec698 --- /dev/null +++ b/lang/qt/src/qgpgmesecretkeyexportjob.cpp @@ -0,0 +1,142 @@ +/* + qgpgmesecretexportjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klar�vdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmesecretkeyexportjob.h" + +#include <QDebug> +#include "gpgme_backend_debug.h" + +#include "context.h" +#include "data.h" + +#include <QStringList> + +#include <gpg-error.h> + +#include <string.h> +#include <assert.h> + +QGpgME::QGpgMESecretKeyExportJob::QGpgMESecretKeyExportJob(bool armour, const QString &charset) + : ExportJob(0), + mProcess(0), + mError(0), + mArmour(armour), + mCharset(charset) +{ + +} + +QGpgME::QGpgMESecretKeyExportJob::~QGpgMESecretKeyExportJob() +{ + +} + +GpgME::Error QGpgME::QGpgMESecretKeyExportJob::start(const QStringList &patterns) +{ + assert(mKeyData.isEmpty()); + + if (patterns.size() != 1 || patterns.front().isEmpty()) { + deleteLater(); + return mError = GpgME::Error::fromCode(GPG_ERR_INV_VALUE, GPG_ERR_SOURCE_GPGSM); + } + + // create and start gpgsm process: + mProcess = new QProcess(this); + mProcess->setObjectName(QStringLiteral("gpgsm --export-secret-key-p12")); + + // FIXME: obtain the path to gpgsm from gpgme, so we use the same instance. + mProcess->setProgram("gpgsm"); + QStringList arguments; + arguments << QStringLiteral("--export-secret-key-p12"); + if (mArmour) { + arguments << QStringLiteral("--armor"); + } + if (!mCharset.isEmpty()) { + arguments << QStringLiteral("--p12-charset") << mCharset; + } + arguments << QLatin1String(patterns.front().toUtf8()); + + mProcess->setArguments(arguments); + connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + SLOT(slotProcessExited(int,QProcess::ExitStatus))); + connect(mProcess, &QProcess::readyReadStandardOutput, + this, &QGpgMESecretKeyExportJob::slotStdout); + connect(mProcess, &QProcess::readyReadStandardError, + this, &QGpgMESecretKeyExportJob::slotStderr); + + mProcess->start(); + if (!mProcess->waitForStarted()) { + mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else? + deleteLater(); + return mError; + } else { + return GpgME::Error(); + } +} + +void QGpgME::QGpgMESecretKeyExportJob::slotCancel() +{ + if (mProcess) { + mProcess->kill(); + } + mProcess = 0; + mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM); +} + +void QGpgME::QGpgMESecretKeyExportJob::slotStdout() +{ + QString line = QString::fromLocal8Bit(mProcess->readLine()); + if (!line.isEmpty()) { + return; + } + const unsigned int oldlen = mKeyData.size(); + mKeyData.resize(oldlen + line.length()); + memcpy(mKeyData.data() + oldlen, line.toLatin1(), line.length()); +} + +void QGpgME::QGpgMESecretKeyExportJob::slotStderr() +{ + // implement? or not? +} + +void QGpgME::QGpgMESecretKeyExportJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus) +{ + Q_EMIT done(); + if (!mError && + (exitStatus != QProcess::NormalExit || exitCode != 0)) { + mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM); + } + Q_EMIT result(mError, mKeyData); + deleteLater(); +} +#include "qgpgmesecretkeyexportjob.moc" diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.h b/lang/qt/src/qgpgmesecretkeyexportjob.h new file mode 100644 index 0000000..ad53f99 --- /dev/null +++ b/lang/qt/src/qgpgmesecretkeyexportjob.h @@ -0,0 +1,81 @@ +/* + qgpgmesecretkeyexportjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__ +#define __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__ + +#include "exportjob.h" +#ifdef BUILDING_QGPGME +# include "context.h" +#else +#include "gpgme++/context.h" +#endif +#include <QProcess> + +namespace GpgME +{ +class Data; +} + +namespace QGpgME +{ + +class QGpgMESecretKeyExportJob : public ExportJob +{ + Q_OBJECT +public: + QGpgMESecretKeyExportJob(bool armour, const QString &charset); + ~QGpgMESecretKeyExportJob(); + + /* from ExportJob */ + GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE; + +private Q_SLOTS: + /* from Job */ + void slotCancel() Q_DECL_OVERRIDE; + + void slotStdout(); + void slotStderr(); + void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus); + +private: + QProcess *mProcess; + QByteArray mKeyData; + GpgME::Error mError; + bool mArmour; + QString mCharset; +}; + +} + +#endif // __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__ diff --git a/lang/qt/src/qgpgmesignencryptjob.cpp b/lang/qt/src/qgpgmesignencryptjob.cpp new file mode 100644 index 0000000..d2e45b1 --- /dev/null +++ b/lang/qt/src/qgpgmesignencryptjob.cpp @@ -0,0 +1,171 @@ +/* + qgpgmesignencryptjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmesignencryptjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "key.h" +#include "exception.h" + +#include <QBuffer> + + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMESignEncryptJob::QGpgMESignEncryptJob(Context *context) + : mixin_type(context), + mOutputIsBase64Encoded(false) +{ + lateInitialization(); +} + +QGpgMESignEncryptJob::~QGpgMESignEncryptJob() {} + +void QGpgMESignEncryptJob::setOutputIsBase64Encoded(bool on) +{ + mOutputIsBase64Encoded = on; +} + +static QGpgMESignEncryptJob::result_type sign_encrypt(Context *ctx, QThread *thread, const std::vector<Key> &signers, + const std::vector<Key> &recipients, const std::weak_ptr<QIODevice> &plainText_, + const std::weak_ptr<QIODevice> &cipherText_, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded) +{ + const std::shared_ptr<QIODevice> &plainText = plainText_.lock(); + const std::shared_ptr<QIODevice> &cipherText = cipherText_.lock(); + + const _detail::ToThreadMover ctMover(cipherText, thread); + const _detail::ToThreadMover ptMover(plainText, thread); + + QGpgME::QIODeviceDataProvider in(plainText); + const Data indata(&in); + + ctx->clearSigningKeys(); + Q_FOREACH (const Key &signer, signers) + if (!signer.isNull()) + if (const Error err = ctx->addSigningKey(signer)) { + return std::make_tuple(SigningResult(err), EncryptionResult(), QByteArray(), QString(), Error()); + } + + if (!cipherText) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const std::pair<SigningResult, EncryptionResult> res = ctx->signAndEncrypt(recipients, indata, outdata, eflags); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res.first, res.second, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(cipherText); + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const std::pair<SigningResult, EncryptionResult> res = ctx->signAndEncrypt(recipients, indata, outdata, eflags); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res.first, res.second, QByteArray(), log, ae); + } + +} + +static QGpgMESignEncryptJob::result_type sign_encrypt_qba(Context *ctx, const std::vector<Key> &signers, + const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(plainText); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return sign_encrypt(ctx, 0, signers, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded); +} + +Error QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust) +{ + run(std::bind(&sign_encrypt_qba, std::placeholders::_1, signers, recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, mOutputIsBase64Encoded)); + return Error(); +} + +void QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, const Context::EncryptionFlags eflags) +{ + run(std::bind(&sign_encrypt, std::placeholders::_1, std::placeholders::_2, signers, recipients, std::placeholders::_3, std::placeholders::_4, eflags, mOutputIsBase64Encoded), plainText, cipherText); +} + +void QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, bool alwaysTrust) +{ + return start(signers, recipients, plainText, cipherText, alwaysTrust ? Context::AlwaysTrust : Context::None); +} + +std::pair<SigningResult, EncryptionResult> QGpgMESignEncryptJob::exec(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, QByteArray &cipherText) +{ + const result_type r = sign_encrypt_qba(context(), signers, recipients, plainText, eflags, mOutputIsBase64Encoded); + cipherText = std::get<2>(r); + resultHook(r); + return mResult; +} + +std::pair<SigningResult, EncryptionResult> QGpgMESignEncryptJob::exec(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust, QByteArray &cipherText) +{ + return exec(signers, recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, cipherText); +} + + +#if 0 + +TODO port? +void QGpgMESignEncryptJob::showErrorDialog(QWidget *parent, const QString &caption) const +{ + if ((mResult.first.error() && !mResult.first.error().isCanceled()) || + (mResult.second.error() && !mResult.second.error().isCanceled())) { + MessageBox::error(parent, mResult.first, mResult.second, this, caption); + } +} +#endif + +void QGpgMESignEncryptJob::resultHook(const result_type &tuple) +{ + mResult = std::make_pair(std::get<0>(tuple), std::get<1>(tuple)); +} +#include "qgpgmesignencryptjob.moc" diff --git a/lang/qt/src/qgpgmesignencryptjob.h b/lang/qt/src/qgpgmesignencryptjob.h new file mode 100644 index 0000000..e76c245 --- /dev/null +++ b/lang/qt/src/qgpgmesignencryptjob.h @@ -0,0 +1,121 @@ +/* + qgpgmesignencryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMESIGNENCRYPTJOB_H__ +#define __QGPGME_QGPGMESIGNENCRYPTJOB_H__ + +#include "signencryptjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "signingresult.h" +#else +#include <gpgme++/signingresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "encryptionresult.h" +#else +#include <gpgme++/encryptionresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +#include <utility> + +namespace QGpgME +{ + +class QGpgMESignEncryptJob +#ifdef Q_MOC_RUN + : public SignEncryptJob +#else + : public _detail::ThreadedJobMixin<SignEncryptJob, std::tuple<GpgME::SigningResult, GpgME::EncryptionResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMESignEncryptJob(GpgME::Context *context); + ~QGpgMESignEncryptJob(); + + /* from SignEncryptJob */ + GpgME::Error start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, bool alwaysTrust) Q_DECL_OVERRIDE; + + /* from SignEncryptJob */ + void start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText, + bool alwaysTrust) Q_DECL_OVERRIDE; + + void start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText, + const GpgME::Context::EncryptionFlags flags) Q_DECL_OVERRIDE; + + std::pair<GpgME::SigningResult, GpgME::EncryptionResult> + exec(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, bool alwaysTrust, + QByteArray &cipherText) Q_DECL_OVERRIDE; + + std::pair<GpgME::SigningResult, GpgME::EncryptionResult> + exec(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, const GpgME::Context::EncryptionFlags flags, + QByteArray &cipherText) Q_DECL_OVERRIDE; + + /* from SignEncryptJob */ + void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + bool mOutputIsBase64Encoded; + std::pair<GpgME::SigningResult, GpgME::EncryptionResult> mResult; +}; + +} + +#endif // __QGPGME_QGPGMESIGNENCRYPTJOB_H__ diff --git a/lang/qt/src/qgpgmesignjob.cpp b/lang/qt/src/qgpgmesignjob.cpp new file mode 100644 index 0000000..4e2312b --- /dev/null +++ b/lang/qt/src/qgpgmesignjob.cpp @@ -0,0 +1,163 @@ +/* + qgpgmesignjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmesignjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "signingresult.h" +#include "data.h" + +#include <QBuffer> + + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMESignJob::QGpgMESignJob(Context *context) + : mixin_type(context), + mOutputIsBase64Encoded(false) +{ + lateInitialization(); +} + +QGpgMESignJob::~QGpgMESignJob() {} + +void QGpgMESignJob::setOutputIsBase64Encoded(bool on) +{ + mOutputIsBase64Encoded = on; +} + +static QGpgMESignJob::result_type sign(Context *ctx, QThread *thread, + const std::vector<Key> &signers, + const std::weak_ptr<QIODevice> &plainText_, + const std::weak_ptr<QIODevice> &signature_, + SignatureMode mode, + bool outputIsBsse64Encoded) +{ + + const std::shared_ptr<QIODevice> plainText = plainText_.lock(); + const std::shared_ptr<QIODevice> signature = signature_.lock(); + + const _detail::ToThreadMover ptMover(plainText, thread); + const _detail::ToThreadMover sgMover(signature, thread); + + QGpgME::QIODeviceDataProvider in(plainText); + const Data indata(&in); + + ctx->clearSigningKeys(); + Q_FOREACH (const Key &signer, signers) + if (!signer.isNull()) + if (const Error err = ctx->addSigningKey(signer)) { + return std::make_tuple(SigningResult(err), QByteArray(), QString(), Error()); + } + + if (!signature) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const SigningResult res = ctx->sign(indata, outdata, mode); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(signature); + Data outdata(&out); + + if (outputIsBsse64Encoded) { + outdata.setEncoding(Data::Base64Encoding); + } + + const SigningResult res = ctx->sign(indata, outdata, mode); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, QByteArray(), log, ae); + } + +} + +static QGpgMESignJob::result_type sign_qba(Context *ctx, + const std::vector<Key> &signers, + const QByteArray &plainText, + SignatureMode mode, + bool outputIsBsse64Encoded) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(plainText); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return sign(ctx, 0, signers, buffer, std::shared_ptr<QIODevice>(), mode, outputIsBsse64Encoded); +} + +Error QGpgMESignJob::start(const std::vector<Key> &signers, const QByteArray &plainText, SignatureMode mode) +{ + run(std::bind(&sign_qba, std::placeholders::_1, signers, plainText, mode, mOutputIsBase64Encoded)); + return Error(); +} + +void QGpgMESignJob::start(const std::vector<Key> &signers, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &signature, SignatureMode mode) +{ + run(std::bind(&sign, std::placeholders::_1, std::placeholders::_2, signers, std::placeholders::_3, std::placeholders::_4, mode, mOutputIsBase64Encoded), plainText, signature); +} + +SigningResult QGpgMESignJob::exec(const std::vector<Key> &signers, const QByteArray &plainText, SignatureMode mode, QByteArray &signature) +{ + const result_type r = sign_qba(context(), signers, plainText, mode, mOutputIsBase64Encoded); + signature = std::get<1>(r); + resultHook(r); + return mResult; +} + +void QGpgMESignJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} + +#if 0 +TODO port +void QGpgMESignJob::showErrorDialog(QWidget *parent, const QString &caption) const +{ + if (mResult.error() && !mResult.error().isCanceled()) { + MessageBox::error(parent, mResult, this, caption); + } +} +#endif +#include "qgpgmesignjob.moc" diff --git a/lang/qt/src/qgpgmesignjob.h b/lang/qt/src/qgpgmesignjob.h new file mode 100644 index 0000000..1d4a174 --- /dev/null +++ b/lang/qt/src/qgpgmesignjob.h @@ -0,0 +1,101 @@ +/* + qgpgmesignjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMESIGNJOB_H__ +#define __QGPGME_QGPGMESIGNJOB_H__ + +#include "signjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "signingresult.h" +#else +#include <gpgme++/signingresult.h> +#endif +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMESignJob +#ifdef Q_MOC_RUN + : public SignJob +#else + : public _detail::ThreadedJobMixin<SignJob, std::tuple<GpgME::SigningResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMESignJob(GpgME::Context *context); + ~QGpgMESignJob(); + + /* from SignJob */ + GpgME::Error start(const std::vector<GpgME::Key> &signers, + const QByteArray &plainText, + GpgME::SignatureMode mode) Q_DECL_OVERRIDE; + + /* from SignJob */ + void start(const std::vector<GpgME::Key> &signers, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &signature, + GpgME::SignatureMode mode) Q_DECL_OVERRIDE; + + /* from SignJob */ + GpgME::SigningResult exec(const std::vector<GpgME::Key> &signers, + const QByteArray &plainText, + GpgME::SignatureMode mode, + QByteArray &signature) Q_DECL_OVERRIDE; + + /* from SignJob */ + void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::SigningResult mResult; + bool mOutputIsBase64Encoded; +}; + +} + +#endif // __QGPGME_QGPGMESIGNJOB_H__ diff --git a/lang/qt/src/qgpgmesignkeyjob.cpp b/lang/qt/src/qgpgmesignkeyjob.cpp new file mode 100644 index 0000000..e6c1478 --- /dev/null +++ b/lang/qt/src/qgpgmesignkeyjob.cpp @@ -0,0 +1,125 @@ +/* + qgpgmesignkeyjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmesignkeyjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "data.h" +#include "gpgsignkeyeditinteractor.h" + +#include <cassert> +#include <memory> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMESignKeyJob::QGpgMESignKeyJob(Context *context) + : mixin_type(context), + m_userIDsToSign(), + m_signingKey(), + m_checkLevel(0), + m_exportable(false), + m_nonRevocable(false), + m_started(false) +{ + lateInitialization(); +} + +QGpgMESignKeyJob::~QGpgMESignKeyJob() {} + +static QGpgMESignKeyJob::result_type sign_key(Context *ctx, const Key &key, const std::vector<unsigned int> &uids, unsigned int checkLevel, const Key &signer, unsigned int opts) +{ + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + + GpgSignKeyEditInteractor *skei(new GpgSignKeyEditInteractor); + skei->setUserIDsToSign(uids); + skei->setCheckLevel(checkLevel); + skei->setSigningOptions(opts); + + if (!signer.isNull()) + if (const Error err = ctx->addSigningKey(signer)) { + return std::make_tuple(err, QString(), Error()); + } + const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (skei), data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(err, log, ae); +} + +Error QGpgMESignKeyJob::start(const Key &key) +{ + unsigned int opts = 0; + if (m_nonRevocable) { + opts |= GpgSignKeyEditInteractor::NonRevocable; + } + if (m_exportable) { + opts |= GpgSignKeyEditInteractor::Exportable; + } + run(std::bind(&sign_key, std::placeholders::_1, key, m_userIDsToSign, m_checkLevel, m_signingKey, opts)); + m_started = true; + return Error(); +} + +void QGpgMESignKeyJob::setUserIDsToSign(const std::vector<unsigned int> &idsToSign) +{ + assert(!m_started); + m_userIDsToSign = idsToSign; +} + +void QGpgMESignKeyJob::setCheckLevel(unsigned int checkLevel) +{ + assert(!m_started); + m_checkLevel = checkLevel; +} + +void QGpgMESignKeyJob::setExportable(bool exportable) +{ + assert(!m_started); + m_exportable = exportable; +} + +void QGpgMESignKeyJob::setSigningKey(const Key &key) +{ + assert(!m_started); + m_signingKey = key; +} + +void QGpgMESignKeyJob::setNonRevocable(bool nonRevocable) +{ + assert(!m_started); + m_nonRevocable = nonRevocable; +} +#include "qgpgmesignkeyjob.moc" diff --git a/lang/qt/src/qgpgmesignkeyjob.h b/lang/qt/src/qgpgmesignkeyjob.h new file mode 100644 index 0000000..6cdb7db --- /dev/null +++ b/lang/qt/src/qgpgmesignkeyjob.h @@ -0,0 +1,94 @@ +/* + qgpgmesignkeyjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMESIGNKEYJOB_H__ +#define __QGPGME_QGPGMESIGNKEYJOB_H__ + +#include "signkeyjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "key.h" +#else +#include <gpgme++/key.h> +#endif + +namespace QGpgME +{ + +class QGpgMESignKeyJob +#ifdef Q_MOC_RUN + : public SignKeyJob +#else + : public _detail::ThreadedJobMixin<SignKeyJob> +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMESignKeyJob(GpgME::Context *context); + ~QGpgMESignKeyJob(); + + /* from SignKeyJob */ + GpgME::Error start(const GpgME::Key &key) Q_DECL_OVERRIDE; + + /* from SignKeyJob */ + void setUserIDsToSign(const std::vector<unsigned int> &idsToSign) Q_DECL_OVERRIDE; + + /* from SignKeyJob */ + void setCheckLevel(unsigned int checkLevel) Q_DECL_OVERRIDE; + + /* from SignKeyJob */ + void setExportable(bool exportable) Q_DECL_OVERRIDE; + + /* from SignKeyJob */ + void setSigningKey(const GpgME::Key &key) Q_DECL_OVERRIDE; + + /* from SignKeyJob */ + void setNonRevocable(bool nonRevocable) Q_DECL_OVERRIDE; + +private: + std::vector<unsigned int> m_userIDsToSign; + GpgME::Key m_signingKey; + unsigned int m_checkLevel; + bool m_exportable; + bool m_nonRevocable; + bool m_started; +}; +} + +#endif // __QGPGME_QGPGMESIGNKEYJOB_H__ diff --git a/lang/qt/src/qgpgmetofupolicyjob.cpp b/lang/qt/src/qgpgmetofupolicyjob.cpp new file mode 100644 index 0000000..a24c946 --- /dev/null +++ b/lang/qt/src/qgpgmetofupolicyjob.cpp @@ -0,0 +1,65 @@ +/* qgpgmetofupolicyjob.cpp + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmetofupolicyjob.h" + +#include "context.h" +#include "key.h" +#include "tofuinfo.h" + + +using namespace QGpgME; +using namespace GpgME; + +QGpgMETofuPolicyJob::QGpgMETofuPolicyJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMETofuPolicyJob::~QGpgMETofuPolicyJob() {} + +static QGpgMETofuPolicyJob::result_type policy_worker(Context *ctx, const Key &key, TofuInfo::Policy policy) +{ + return std::make_tuple (ctx->setTofuPolicy(key, policy), + QString(), Error()); +} + +void QGpgMETofuPolicyJob::start(const Key &key, TofuInfo::Policy policy) +{ + run(std::bind(&policy_worker, std::placeholders::_1, key, policy)); +} + +Error QGpgMETofuPolicyJob::exec(const Key &key, TofuInfo::Policy policy) +{ + return std::get<0>(policy_worker(context(), key, policy)); +} + +#include "qgpgmetofupolicyjob.moc" diff --git a/lang/qt/src/qgpgmetofupolicyjob.h b/lang/qt/src/qgpgmetofupolicyjob.h new file mode 100644 index 0000000..e7272e7 --- /dev/null +++ b/lang/qt/src/qgpgmetofupolicyjob.h @@ -0,0 +1,65 @@ +/* qgpgmetofupolicyjob.h + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef QGPGME_QGPGMETOFUPOLICYJOB_H +#define QGPGME_QGPGMETOFUPOLICYJOB_H + +#include "tofupolicyjob.h" + +#include "threadedjobmixin.h" +namespace GpgME +{ + class Key; +} // namespace GpgME + +namespace QGpgME { + +class QGpgMETofuPolicyJob +#ifdef Q_MOC_RUN + : public TofuPolicyJob +#else + : public _detail::ThreadedJobMixin<TofuPolicyJob, std::tuple<GpgME::Error, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMETofuPolicyJob(GpgME::Context *context); + ~QGpgMETofuPolicyJob(); + + void start(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) Q_DECL_OVERRIDE; + GpgME::Error exec(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) Q_DECL_OVERRIDE; +}; + +} + +#endif diff --git a/lang/qt/src/qgpgmeverifydetachedjob.cpp b/lang/qt/src/qgpgmeverifydetachedjob.cpp new file mode 100644 index 0000000..8efef05 --- /dev/null +++ b/lang/qt/src/qgpgmeverifydetachedjob.cpp @@ -0,0 +1,118 @@ +/* + qgpgmeverifydetachedjob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeverifydetachedjob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "verificationresult.h" +#include "data.h" + +#include <cassert> + + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEVerifyDetachedJob::~QGpgMEVerifyDetachedJob() {} + +static QGpgMEVerifyDetachedJob::result_type verify_detached(Context *ctx, QThread *thread, const std::weak_ptr<QIODevice> &signature_, const std::weak_ptr<QIODevice> &signedData_) +{ + const std::shared_ptr<QIODevice> signature = signature_.lock(); + const std::shared_ptr<QIODevice> signedData = signedData_.lock(); + + const _detail::ToThreadMover sgMover(signature, thread); + const _detail::ToThreadMover sdMover(signedData, thread); + + QGpgME::QIODeviceDataProvider sigDP(signature); + Data sig(&sigDP); + + QGpgME::QIODeviceDataProvider dataDP(signedData); + Data data(&dataDP); + + const VerificationResult res = ctx->verifyDetachedSignature(sig, data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + + return std::make_tuple(res, log, ae); +} + +static QGpgMEVerifyDetachedJob::result_type verify_detached_qba(Context *ctx, const QByteArray &signature, const QByteArray &signedData) +{ + QGpgME::QByteArrayDataProvider sigDP(signature); + Data sig(&sigDP); + + QGpgME::QByteArrayDataProvider dataDP(signedData); + Data data(&dataDP); + + const VerificationResult res = ctx->verifyDetachedSignature(sig, data); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + + return std::make_tuple(res, log, ae); + +} + +Error QGpgMEVerifyDetachedJob::start(const QByteArray &signature, const QByteArray &signedData) +{ + run(std::bind(&verify_detached_qba, std::placeholders::_1, signature, signedData)); + return Error(); +} + +void QGpgMEVerifyDetachedJob::start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData) +{ + run(std::bind(&verify_detached, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), signature, signedData); +} + +GpgME::VerificationResult QGpgME::QGpgMEVerifyDetachedJob::exec(const QByteArray &signature, + const QByteArray &signedData) +{ + const result_type r = verify_detached_qba(context(), signature, signedData); + resultHook(r); + return mResult; +} + +//PENDING(marc) implement showErrorDialog() + +void QGpgME::QGpgMEVerifyDetachedJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} +#include "qgpgmeverifydetachedjob.moc" diff --git a/lang/qt/src/qgpgmeverifydetachedjob.h b/lang/qt/src/qgpgmeverifydetachedjob.h new file mode 100644 index 0000000..051caf0 --- /dev/null +++ b/lang/qt/src/qgpgmeverifydetachedjob.h @@ -0,0 +1,85 @@ +/* + qgpgmeverifydetachedjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__ +#define __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__ + +#include "verifydetachedjob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "verificationresult.h" +#else +#include <gpgme++/verificationresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEVerifyDetachedJob +#ifdef Q_MOC_RUN + : public VerifyDetachedJob +#else + : public _detail::ThreadedJobMixin<VerifyDetachedJob, std::tuple<GpgME::VerificationResult, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEVerifyDetachedJob(GpgME::Context *context); + ~QGpgMEVerifyDetachedJob(); + + /* from VerifyDetachedJob */ + GpgME::Error start(const QByteArray &signature, const QByteArray &signedData) Q_DECL_OVERRIDE; + + /* from VerifyDetachedJob */ + void start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData) Q_DECL_OVERRIDE; + + /* from VerifyDetachedJob */ + GpgME::VerificationResult exec(const QByteArray &signature, + const QByteArray &signedData) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::VerificationResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__ diff --git a/lang/qt/src/qgpgmeverifyopaquejob.cpp b/lang/qt/src/qgpgmeverifyopaquejob.cpp new file mode 100644 index 0000000..b513f82 --- /dev/null +++ b/lang/qt/src/qgpgmeverifyopaquejob.cpp @@ -0,0 +1,125 @@ +/* + qgpgmeverifyopaquejob.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmeverifyopaquejob.h" + +#include "dataprovider.h" + +#include "context.h" +#include "verificationresult.h" +#include "data.h" + +#include <QBuffer> + + +#include <cassert> + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEVerifyOpaqueJob::~QGpgMEVerifyOpaqueJob() {} + +static QGpgMEVerifyOpaqueJob::result_type verify_opaque(Context *ctx, QThread *thread, const std::weak_ptr<QIODevice> &signedData_, const std::weak_ptr<QIODevice> &plainText_) +{ + + const std::shared_ptr<QIODevice> plainText = plainText_.lock(); + const std::shared_ptr<QIODevice> signedData = signedData_.lock(); + + const _detail::ToThreadMover ptMover(plainText, thread); + const _detail::ToThreadMover sdMover(signedData, thread); + + QGpgME::QIODeviceDataProvider in(signedData); + const Data indata(&in); + + if (!plainText) { + QGpgME::QByteArrayDataProvider out; + Data outdata(&out); + + const VerificationResult res = ctx->verifyOpaqueSignature(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, out.data(), log, ae); + } else { + QGpgME::QIODeviceDataProvider out(plainText); + Data outdata(&out); + + const VerificationResult res = ctx->verifyOpaqueSignature(indata, outdata); + Error ae; + const QString log = _detail::audit_log_as_html(ctx, ae); + return std::make_tuple(res, QByteArray(), log, ae); + } + +} + +static QGpgMEVerifyOpaqueJob::result_type verify_opaque_qba(Context *ctx, const QByteArray &signedData) +{ + const std::shared_ptr<QBuffer> buffer(new QBuffer); + buffer->setData(signedData); + if (!buffer->open(QIODevice::ReadOnly)) { + assert(!"This should never happen: QBuffer::open() failed"); + } + return verify_opaque(ctx, 0, buffer, std::shared_ptr<QIODevice>()); +} + +Error QGpgMEVerifyOpaqueJob::start(const QByteArray &signedData) +{ + run(std::bind(&verify_opaque_qba, std::placeholders::_1, signedData)); + return Error(); +} + +void QGpgMEVerifyOpaqueJob::start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText) +{ + run(std::bind(&verify_opaque, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), signedData, plainText); +} + +GpgME::VerificationResult QGpgME::QGpgMEVerifyOpaqueJob::exec(const QByteArray &signedData, QByteArray &plainText) +{ + const result_type r = verify_opaque_qba(context(), signedData); + plainText = std::get<1>(r); + resultHook(r); + return mResult; +} + +//PENDING(marc) implement showErrorDialog() + +void QGpgME::QGpgMEVerifyOpaqueJob::resultHook(const result_type &tuple) +{ + mResult = std::get<0>(tuple); +} +#include "qgpgmeverifyopaquejob.moc" diff --git a/lang/qt/src/qgpgmeverifyopaquejob.h b/lang/qt/src/qgpgmeverifyopaquejob.h new file mode 100644 index 0000000..87c94a3 --- /dev/null +++ b/lang/qt/src/qgpgmeverifyopaquejob.h @@ -0,0 +1,84 @@ +/* + qgpgmeverifyopaquejob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__ +#define __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__ + +#include "verifyopaquejob.h" + +#include "threadedjobmixin.h" + +#ifdef BUILDING_QGPGME +# include "verificationresult.h" +#else +#include <gpgme++/verificationresult.h> +#endif + +namespace QGpgME +{ + +class QGpgMEVerifyOpaqueJob +#ifdef Q_MOC_RUN + : public VerifyOpaqueJob +#else + : public _detail::ThreadedJobMixin<VerifyOpaqueJob, std::tuple<GpgME::VerificationResult, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEVerifyOpaqueJob(GpgME::Context *context); + ~QGpgMEVerifyOpaqueJob(); + + /* from VerifyOpaqueJob */ + GpgME::Error start(const QByteArray &signedData) Q_DECL_OVERRIDE; + + /* from VerifyOpaqueJob */ + void start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE; + + /* form VerifyOpaqueJob */ + GpgME::VerificationResult exec(const QByteArray &signedData, QByteArray &plainData) Q_DECL_OVERRIDE; + + /* from ThreadedJobMixin */ + void resultHook(const result_type &r) Q_DECL_OVERRIDE; + +private: + GpgME::VerificationResult mResult; +}; + +} + +#endif // __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__ diff --git a/lang/qt/src/qgpgmewkspublishjob.cpp b/lang/qt/src/qgpgmewkspublishjob.cpp new file mode 100644 index 0000000..8f97cb5 --- /dev/null +++ b/lang/qt/src/qgpgmewkspublishjob.cpp @@ -0,0 +1,189 @@ +/* wkspublishjob.cpp + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmewkspublishjob.h" + +#include "context.h" +#include "key.h" +#include "util.h" + +#include <QFileInfo> +#include <QDir> +#include <QProcess> + +/* Timeout for the WKS Processes will be 5 Minutes as + * they can involve pinentry questions. */ +#define TIMEOUT_VALUE (5*60*1000) + +using namespace QGpgME; +using namespace GpgME; + +QGpgMEWKSPublishJob::QGpgMEWKSPublishJob(Context *context) + : mixin_type(context) +{ + lateInitialization(); +} + +QGpgMEWKSPublishJob::~QGpgMEWKSPublishJob() {} + +static QString getWKSClient() +{ + auto libexecdir = QString::fromLocal8Bit(dirInfo("libexecdir")); + if (libexecdir.isEmpty()) { + return QString(); + } + + const QFileInfo fi(QDir(libexecdir).absoluteFilePath(QStringLiteral("gpg-wks-client"))); + if (fi.exists() && fi.isExecutable()) { + return fi.absoluteFilePath(); + } + return QString(); +} + +static QGpgMEWKSPublishJob::result_type check_worker(const QString &mail) +{ + if (mail.isEmpty()) { + return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)), + QByteArray(), QByteArray(), QString(), Error()); + } + + const auto wksPath = getWKSClient(); + if (wksPath.isEmpty()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + + /* QProcess instead of engine_spawn because engine_spawn does not communicate + * the return value of the process and we are in qt anyway. */ + QProcess proc; + proc.setProgram(wksPath); + proc.setArguments(QStringList() << QStringLiteral("--supported") << mail); + proc.start(); + if (!proc.waitForStarted()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + if (!proc.waitForFinished(TIMEOUT_VALUE)) { + return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)), + QByteArray(), QByteArray(), QString(), Error()); + } + if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) { + return std::make_tuple (Error(), QByteArray(), QByteArray(), QString(), Error()); + } + return std::make_tuple (Error(make_error(GPG_ERR_NOT_ENABLED)), + QByteArray(), QByteArray(), QString(), Error()); +} + +static QGpgMEWKSPublishJob::result_type create_worker(const char *fpr, const QString &mail) +{ + if (mail.isEmpty() || !fpr) { + return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)), + QByteArray(), QByteArray(), QString(), Error()); + } + + const auto wksPath = getWKSClient(); + if (wksPath.isEmpty()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + + QProcess proc; + proc.setProgram(wksPath); + proc.setArguments(QStringList() << QStringLiteral("--create") + << QLatin1String(fpr) + << mail); + proc.start(); + if (!proc.waitForStarted()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + + if (!proc.waitForFinished(TIMEOUT_VALUE)) { + return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)), + QByteArray(), QByteArray(), QString(), Error()); + } + if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) { + return std::make_tuple (Error(), proc.readAllStandardOutput(), + proc.readAllStandardError(), QString(), Error()); + } + return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)), + proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error()); +} + +static QGpgMEWKSPublishJob::result_type recieve_worker(const QByteArray &response) +{ + if (response.isEmpty()) { + return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)), + QByteArray(), QByteArray(), QString(), Error()); + } + + const auto wksPath = getWKSClient(); + if (wksPath.isEmpty()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + + QProcess proc; + proc.setProgram(wksPath); + proc.setArguments(QStringList() << QStringLiteral("--receive")); + proc.start(); + if (!proc.waitForStarted()) { + return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)), + QByteArray(), QByteArray(), QString(), Error()); + } + proc.write(response); + proc.closeWriteChannel(); + if (!proc.waitForFinished(TIMEOUT_VALUE)) { + return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)), + QByteArray(), QByteArray(), QString(), Error()); + } + if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) { + return std::make_tuple (Error(), proc.readAllStandardOutput(), + proc.readAllStandardError(), QString(), Error()); + } + return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)), + proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error()); +} + +void QGpgMEWKSPublishJob::startCheck(const QString &mailbox) +{ + run(std::bind(&check_worker, mailbox)); +} + +void QGpgMEWKSPublishJob::startCreate(const char *fpr, const QString &mailbox) { + run(std::bind(&create_worker, fpr, mailbox)); +} + +void QGpgMEWKSPublishJob::startRecieve(const QByteArray &response) +{ + run(std::bind(&recieve_worker, response)); +} + +#include "qgpgmewkspublishjob.moc" diff --git a/lang/qt/src/qgpgmewkspublishjob.h b/lang/qt/src/qgpgmewkspublishjob.h new file mode 100644 index 0000000..1a31149 --- /dev/null +++ b/lang/qt/src/qgpgmewkspublishjob.h @@ -0,0 +1,70 @@ +/* qgpgmewkspublishjob.h + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef QGPGME_QGPGMEWKSPUBLISHJOB_H +#define QGPGME_QGPGMEWKSPUBLISHJOB_H + +#include "wkspublishjob.h" + +#include "threadedjobmixin.h" +namespace GpgME +{ + class Key; +} // namespace GpgME + +namespace QGpgME { + +/** + * Handles Web Key Service Publishing. Needs WKS tools installed and + * server support. + */ +class QGpgMEWKSPublishJob +#ifdef Q_MOC_RUN + : public WKSPublishJob +#else + : public _detail::ThreadedJobMixin<WKSPublishJob, std::tuple<GpgME::Error, QByteArray, QByteArray, QString, GpgME::Error> > +#endif +{ + Q_OBJECT +#ifdef Q_MOC_RUN +public Q_SLOTS: + void slotFinished(); +#endif +public: + explicit QGpgMEWKSPublishJob(GpgME::Context *context); + ~QGpgMEWKSPublishJob(); + + void startCheck(const QString &mailbox) Q_DECL_OVERRIDE; + void startCreate(const char *fpr, const QString &mailbox) Q_DECL_OVERRIDE; + void startRecieve(const QByteArray &response) Q_DECL_OVERRIDE; +}; + +} + +#endif diff --git a/lang/qt/src/refreshkeysjob.h b/lang/qt/src/refreshkeysjob.h new file mode 100644 index 0000000..a97de80 --- /dev/null +++ b/lang/qt/src/refreshkeysjob.h @@ -0,0 +1,94 @@ +/* + refreshkeysjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_REFRESHKEYSJOB_H__ +#define __KLEO_REFRESHKEYSJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#include <vector> + +namespace GpgME +{ +class Error; +class Key; +} + +class QStringList; + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous key refreshers. + + To use a RefreshKeysJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the key refresh with a + call to start(). This call might fail, in which case the + RefreshKeysJob instance will have scheduled its own destruction + with a call to QObject::deleteLater(). + + After result() is emitted, the KeyListJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT RefreshKeysJob : public Job +{ + Q_OBJECT +protected: + explicit RefreshKeysJob(QObject *parent); +public: + ~RefreshKeysJob(); + + /** + Starts the keylist operation. \a pattern is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. If \a pattern is empty or contains only empty strings, + all keys are returned (however, the backend is free to truncate + the result and should do so; when this happens, it will be + reported by the reult object). + + If \a secretOnly is true, only keys for which the secret key is + also available are returned. Use this if you need to select a + key for signing. + */ + virtual GpgME::Error start(const QStringList &patterns) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &error); +}; + +} + +#endif // __KLEO_REFRESHKEYSJOB_H__ diff --git a/lang/qt/src/signencryptjob.h b/lang/qt/src/signencryptjob.h new file mode 100644 index 0000000..4e07744 --- /dev/null +++ b/lang/qt/src/signencryptjob.h @@ -0,0 +1,153 @@ +/* + signencryptjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SIGNENCRYPTJOB_H__ +#define __KLEO_SIGNENCRYPTJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#ifdef BUILDING_QGPGME +# include "global.h" +# include "context.h" +#else +# include <gpgme++/global.h> +# include <gpgme++/context.h> +#endif + +#include <memory> +#include <vector> +#include <utility> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class Key; +class SigningResult; +class EncryptionResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous combined signing and encrypting + + To use a SignEncryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the operation with a + call to start(). This call might fail, in which case the + SignEncryptJob instance will have scheduled it's own destruction + with a call to QObject::deleteLater(). + + After result() is emitted, the SignEncryptJob will schedule it's + own destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT SignEncryptJob : public Job +{ + Q_OBJECT +protected: + explicit SignEncryptJob(QObject *parent); +public: + ~SignEncryptJob(); + + /** + Starts the combined signing and encrypting operation. \a signers + is the list of keys to sign \a plainText with. \a recipients is + a list of keys to encrypt the signed \a plainText to. In both + lists, empty (null) keys are ignored. + + If \a alwaysTrust is true, validity checking for the + \em recipient keys will not be performed, but full validity + assumed for all \em recipient keys without further checks. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, + bool alwaysTrust = false) = 0; + + /*! + \overload + + If \a cipherText is non-null, the ciphertext is written + there. Otherwise, it will be delivered in the third argument of + result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(), + bool alwaysTrust = false) = 0; + + virtual std::pair<GpgME::SigningResult, GpgME::EncryptionResult> + exec(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, + bool alwaysTrust, QByteArray &cipherText) = 0; + + /*! + This is a hack to request BASE64 output (instead of whatever + comes out normally). + */ + virtual void setOutputIsBase64Encoded(bool) = 0; + + /** Like start but with an additional argument for EncryptionFlags for + * more flexibility. */ + virtual void start(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(), + const GpgME::Context::EncryptionFlags flags = GpgME::Context::None) = 0; + + /** Like exec but with an additional argument for EncryptionFlags for + * more flexibility. */ + virtual std::pair<GpgME::SigningResult, GpgME::EncryptionResult> + exec(const std::vector<GpgME::Key> &signers, + const std::vector<GpgME::Key> &recipients, + const QByteArray &plainText, + const GpgME::Context::EncryptionFlags flags, QByteArray &cipherText) = 0; +Q_SIGNALS: + void result(const GpgME::SigningResult &signingresult, + const GpgME::EncryptionResult &encryptionresult, + const QByteArray &cipherText, const QString &auditLogAsHtml = QString(), + const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_SIGNENCRYPTJOB_H__ diff --git a/lang/qt/src/signjob.h b/lang/qt/src/signjob.h new file mode 100644 index 0000000..cf5c628 --- /dev/null +++ b/lang/qt/src/signjob.h @@ -0,0 +1,122 @@ +/* + signjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SIGNJOB_H__ +#define __KLEO_SIGNJOB_H__ + +#include "job.h" + +#ifdef BUILDING_QGPGME +# include "global.h" +#else +# include <gpgme++/global.h> +#endif + + +#include <vector> +#include <memory> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class Key; +class SigningResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous signing + + To use a SignJob, first obtain an instance from the CryptoBackend + implementation, connect the progress() and result() signals to + suitable slots and then start the signing with a call to + start(). This call might fail, in which case the SignJob instance + will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the SignJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT SignJob : public Job +{ + Q_OBJECT +protected: + explicit SignJob(QObject *parent); +public: + ~SignJob(); + + /** + Starts the signing operation. \a signers is the list of keys to + sign \a plainText with. Empty (null) keys are ignored. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &signers, + const QByteArray &plainText, + GpgME::SignatureMode mode) = 0; + + /*! + \overload + + If \a signature is non-null the signature is written + there. Otherwise, it will be delivered in the second argument of + result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::vector<GpgME::Key> &signers, + const std::shared_ptr<QIODevice> &plainText, + const std::shared_ptr<QIODevice> &signature, + GpgME::SignatureMode mode) = 0; + + virtual GpgME::SigningResult exec(const std::vector<GpgME::Key> &signers, + const QByteArray &plainText, + GpgME::SignatureMode mode, + QByteArray &signature) = 0; + + /*! + This is a hack to request BASE64 output (instead of whatever + comes out normally). + */ + virtual void setOutputIsBase64Encoded(bool) = 0; + +Q_SIGNALS: + void result(const GpgME::SigningResult &result, const QByteArray &signature, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_SIGNJOB_H__ diff --git a/lang/qt/src/signkeyjob.h b/lang/qt/src/signkeyjob.h new file mode 100644 index 0000000..b5efc01 --- /dev/null +++ b/lang/qt/src/signkeyjob.h @@ -0,0 +1,117 @@ +/* + signkeyjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SIGNKEYJOB_H__ +#define __KLEO_SIGNKEYJOB_H__ + +#include "job.h" + +#include <vector> + +namespace GpgME +{ +class Error; +class Key; +} + +namespace QGpgME +{ + +/** + @short An abstract base class to sign keys asynchronously + + To use a SignKeyJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the job with a call + to start(). This call might fail, in which case the ChangeExpiryJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the SignKeyJob will schedule it's own + destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT SignKeyJob : public Job +{ + Q_OBJECT +protected: + explicit SignKeyJob(QObject *parent); +public: + ~SignKeyJob(); + + /** + Starts the key signing operation. \a key is the key to sign. + @param keyToSign the key to be signed + @param idsToSign the user IDs to sign + @param signingKey the secret key to use for signing + @param option the signing mode, either local or exportable + */ + virtual GpgME::Error start(const GpgME::Key &keyToSign) = 0; + + /** + * If explicitly specified, only the listed user IDs will be signed. Otherwise all user IDs + * are signed. + * @param list of user ID indexes (of the key to be signed). + */ + virtual void setUserIDsToSign(const std::vector<unsigned int> &idsToSign) = 0; + + /** + * sets the check level + * @param the check level, ranges from 0 (no claim) and 3 (extensively checked), + * default is 0 + */ + virtual void setCheckLevel(unsigned int checkLevel) = 0; + + /** + * sets whether the signature should be exportable, or local only. + * default is local. + */ + virtual void setExportable(bool exportable) = 0; + + /** + * sets an alternate signing key + */ + virtual void setSigningKey(const GpgME::Key &key) = 0; + + /** + * if set, the created signature won't be revocable. By default signatures + * can be revoked. + */ + virtual void setNonRevocable(bool nonRevocable) = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_SIGNKEYJOB_H__ diff --git a/lang/qt/src/specialjob.h b/lang/qt/src/specialjob.h new file mode 100644 index 0000000..2c80f20 --- /dev/null +++ b/lang/qt/src/specialjob.h @@ -0,0 +1,91 @@ +/* + specialjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SPECIALJOB_H__ +#define __KLEO_SPECIALJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +namespace GpgME +{ +class Error; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for protocol-specific jobs + + To use a SpecialJob, first obtain an instance from the + CryptoBackend implementation, connect progress() and result() + signals to suitable slots and then start the job with a call to + start(). This call might fail, in which case the SpecialJob + instance will have schedules its own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the SpecialJob will schedule its own + destruction by calling QObject::deleteLater(). + + Parameters are set using the Qt property system. More general, or + constructor parameters are given in the call to + QGpgME::Protocol::specialJob(). + + The result is made available through the result signal, and + through the read-only result property, the latter of which needs + to be defined in each SpecialJob subclass. +*/ +class QGPGME_EXPORT SpecialJob : public Job +{ + Q_OBJECT +protected: + explicit SpecialJob(QObject *parent); + +public: + ~SpecialJob(); + + /** + Starts the special operation. + */ + virtual GpgME::Error start() = 0; + + virtual GpgME::Error exec() = 0; + +Q_SIGNALS: + void result(const GpgME::Error &result, const QVariant &data); +}; + +} + +#endif // __KLEO_SPECIALJOB_H__ diff --git a/lang/qt/src/threadedjobmixin.cpp b/lang/qt/src/threadedjobmixin.cpp new file mode 100644 index 0000000..cd6ab5f --- /dev/null +++ b/lang/qt/src/threadedjobmixin.cpp @@ -0,0 +1,110 @@ +/* + threadedjobmixin.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "threadedjobmixin.h" + +#include "dataprovider.h" + +#include "data.h" + +#include <QString> +#include <QStringList> +#include <QByteArray> + + +#include <algorithm> +#include <iterator> + +using namespace QGpgME; +using namespace GpgME; + +static const unsigned int GetAuditLogFlags = Context::AuditLogWithHelp | Context::HtmlAuditLog; + +QString _detail::audit_log_as_html(Context *ctx, GpgME::Error &err) +{ + assert(ctx); + QGpgME::QByteArrayDataProvider dp; + Data data(&dp); + assert(!data.isNull()); + if ((err = ctx->lastError()) || (err = ctx->getAuditLog(data, GetAuditLogFlags))) { + return QString::fromLocal8Bit(err.asString()); + } + const QByteArray ba = dp.data(); + return QString::fromUtf8(ba.data(), ba.size()); +} + +static QList<QByteArray> from_sl(const QStringList &sl) +{ + QList<QByteArray> result; + Q_FOREACH (const QString &str, sl) { + result.append(str.toUtf8()); + } + +#if 0 + std::transform(sl.begin(), sl.end(), std::back_inserter(result), + mem_fn(static_cast<QByteArray()const>(&QString::toUtf8))); +#endif + return result; +} + +static QList<QByteArray> single(const QByteArray &ba) +{ + QList<QByteArray> result; + result.push_back(ba); + return result; +} + +_detail::PatternConverter::PatternConverter(const QByteArray &ba) + : m_list(single(ba)), m_patterns(0) {} +_detail::PatternConverter::PatternConverter(const QString &s) + : m_list(single(s.toUtf8())), m_patterns(0) {} +_detail::PatternConverter::PatternConverter(const QList<QByteArray> &lba) + : m_list(lba), m_patterns(0) {} +_detail::PatternConverter::PatternConverter(const QStringList &sl) + : m_list(from_sl(sl)), m_patterns(0) {} + +const char **_detail::PatternConverter::patterns() const +{ + if (!m_patterns) { + m_patterns = new const char *[ m_list.size() + 1 ]; + const char **end = std::transform(m_list.begin(), m_list.end(), m_patterns, + std::mem_fn(&QByteArray::constData)); + *end = 0; + } + return m_patterns; +} + +_detail::PatternConverter::~PatternConverter() +{ + delete [] m_patterns; +} diff --git a/lang/qt/src/threadedjobmixin.h b/lang/qt/src/threadedjobmixin.h new file mode 100644 index 0000000..62d7f1c --- /dev/null +++ b/lang/qt/src/threadedjobmixin.h @@ -0,0 +1,272 @@ +/* + threadedjobmixin.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2008 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __QGPGME_THREADEDJOBMIXING_H__ +#define __QGPGME_THREADEDJOBMIXING_H__ + +#include <QMutex> +#include <QMutexLocker> +#include <QThread> +#include <QString> +#include <QIODevice> + +#ifdef BUILDING_QGPGME +# include "context.h" +# include "interfaces/progressprovider.h" +#else +# include <gpgme++/context.h> +# include <gpgme++/interfaces/progressprovider.h> +#endif + + +#include <cassert> + +namespace QGpgME +{ +namespace _detail +{ + +QString audit_log_as_html(GpgME::Context *ctx, GpgME::Error &err); + +class PatternConverter +{ + const QList<QByteArray> m_list; + mutable const char **m_patterns; +public: + explicit PatternConverter(const QByteArray &ba); + explicit PatternConverter(const QString &s); + explicit PatternConverter(const QList<QByteArray> &lba); + explicit PatternConverter(const QStringList &sl); + ~PatternConverter(); + + const char **patterns() const; +}; + +class ToThreadMover +{ + QObject *const m_object; + QThread *const m_thread; +public: + ToThreadMover(QObject *o, QThread *t) : m_object(o), m_thread(t) {} + ToThreadMover(QObject &o, QThread *t) : m_object(&o), m_thread(t) {} + ToThreadMover(const std::shared_ptr<QObject> &o, QThread *t) : m_object(o.get()), m_thread(t) {} + ~ToThreadMover() + { + if (m_object && m_thread) { + m_object->moveToThread(m_thread); + } + } +}; + +template <typename T_result> +class Thread : public QThread +{ +public: + explicit Thread(QObject *parent = Q_NULLPTR) : QThread(parent) {} + + void setFunction(const std::function<T_result()> &function) + { + const QMutexLocker locker(&m_mutex); + m_function = function; + } + + T_result result() const + { + const QMutexLocker locker(&m_mutex); + return m_result; + } + +private: + void run() Q_DECL_OVERRIDE { + const QMutexLocker locker(&m_mutex); + m_result = m_function(); + } +private: + mutable QMutex m_mutex; + std::function<T_result()> m_function; + T_result m_result; +}; + +template <typename T_base, typename T_result = std::tuple<GpgME::Error, QString, GpgME::Error> > +class ThreadedJobMixin : public T_base, public GpgME::ProgressProvider +{ +public: + typedef ThreadedJobMixin<T_base, T_result> mixin_type; + typedef T_result result_type; + +protected: + static_assert(std::tuple_size<T_result>::value > 2, + "Result tuple too small"); + static_assert(std::is_same < + typename std::tuple_element < + std::tuple_size<T_result>::value - 2, + T_result + >::type, + QString + >::value, + "Second to last result type not a QString"); + static_assert(std::is_same < + typename std::tuple_element < + std::tuple_size<T_result>::value - 1, + T_result + >::type, + GpgME::Error + >::value, + "Last result type not a GpgME::Error"); + + explicit ThreadedJobMixin(GpgME::Context *ctx) + : T_base(0), m_ctx(ctx), m_thread(), m_auditLog(), m_auditLogError() + { + + } + + void lateInitialization() + { + assert(m_ctx); + QObject::connect(&m_thread, SIGNAL(finished()), this, SLOT(slotFinished())); + m_ctx->setProgressProvider(this); + } + + template <typename T_binder> + void run(const T_binder &func) + { + m_thread.setFunction(std::bind(func, this->context())); + m_thread.start(); + } + template <typename T_binder> + void run(const T_binder &func, const std::shared_ptr<QIODevice> &io) + { + if (io) { + io->moveToThread(&m_thread); + } + // the arguments passed here to the functor are stored in a QThread, and are not + // necessarily destroyed (living outside the UI thread) at the time the result signal + // is emitted and the signal receiver wants to clean up IO devices. + // To avoid such races, we pass std::weak_ptr's to the functor. + m_thread.setFunction(std::bind(func, this->context(), this->thread(), std::weak_ptr<QIODevice>(io))); + m_thread.start(); + } + template <typename T_binder> + void run(const T_binder &func, const std::shared_ptr<QIODevice> &io1, const std::shared_ptr<QIODevice> &io2) + { + if (io1) { + io1->moveToThread(&m_thread); + } + if (io2) { + io2->moveToThread(&m_thread); + } + // the arguments passed here to the functor are stored in a QThread, and are not + // necessarily destroyed (living outside the UI thread) at the time the result signal + // is emitted and the signal receiver wants to clean up IO devices. + // To avoid such races, we pass std::weak_ptr's to the functor. + m_thread.setFunction(std::bind(func, this->context(), this->thread(), std::weak_ptr<QIODevice>(io1), std::weak_ptr<QIODevice>(io2))); + m_thread.start(); + } + GpgME::Context *context() const + { + return m_ctx.get(); + } + + virtual void resultHook(const result_type &) {} + + void slotFinished() + { + const T_result r = m_thread.result(); + m_auditLog = std::get < std::tuple_size<T_result>::value - 2 > (r); + m_auditLogError = std::get < std::tuple_size<T_result>::value - 1 > (r); + resultHook(r); + Q_EMIT this->done(); + doEmitResult(r); + this->deleteLater(); + } + void slotCancel() Q_DECL_OVERRIDE { + if (m_ctx) + { + m_ctx->cancelPendingOperation(); + } + } + QString auditLogAsHtml() const Q_DECL_OVERRIDE + { + return m_auditLog; + } + GpgME::Error auditLogError() const Q_DECL_OVERRIDE + { + return m_auditLogError; + } + void showProgress(const char *what, int type, int current, int total) Q_DECL_OVERRIDE { + // will be called from the thread exec'ing the operation, so + // just bounce everything to the owning thread: + // ### hope this is thread-safe (meta obj is const, and + // ### portEvent is thread-safe, so should be ok) + QMetaObject::invokeMethod(this, "progress", Qt::QueuedConnection, + // TODO port + Q_ARG(QString, QString()), + Q_ARG(int, current), + Q_ARG(int, total)); + } +private: + template <typename T1, typename T2> + void doEmitResult(const std::tuple<T1, T2> &tuple) + { + Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple)); + } + + template <typename T1, typename T2, typename T3> + void doEmitResult(const std::tuple<T1, T2, T3> &tuple) + { + Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple)); + } + + template <typename T1, typename T2, typename T3, typename T4> + void doEmitResult(const std::tuple<T1, T2, T3, T4> &tuple) + { + Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple), std::get<3>(tuple)); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5> + void doEmitResult(const std::tuple<T1, T2, T3, T4, T5> &tuple) + { + Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple), std::get<3>(tuple), std::get<4>(tuple)); + } + +private: + std::shared_ptr<GpgME::Context> m_ctx; + Thread<T_result> m_thread; + QString m_auditLog; + GpgME::Error m_auditLogError; +}; + +} +} + +#endif /* __QGPGME_THREADEDJOBMIXING_H__ */ diff --git a/lang/qt/src/tofupolicyjob.h b/lang/qt/src/tofupolicyjob.h new file mode 100644 index 0000000..3079f91 --- /dev/null +++ b/lang/qt/src/tofupolicyjob.h @@ -0,0 +1,80 @@ +/* tofupolicyjob.h + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef QGPGME_TOFUPOLICYJOB_H +#define QGPGME_TOFUPOLICYJOB_H + +#include "job.h" + +#include "qgpgme_export.h" + +#ifdef BUILDING_QGPGME +# include "tofuinfo.h" +#else +# include <gpgme++/tofuinfo.h> +#endif + +namespace GpgME +{ + class Key; +} // namespace GpgME + +namespace QGpgME { + +/** + * Set the TOFU Policy for a key + */ +class QGPGME_EXPORT TofuPolicyJob: public Job +{ + Q_OBJECT +protected: + explicit TofuPolicyJob(QObject *parent); +public: + ~TofuPolicyJob(); + + + /* Set the policy to \a policy see the gpgme manual for + * policy explanations. */ + virtual void start(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) = 0; + + virtual GpgME::Error exec(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) = 0; + +Q_SIGNALS: + /* Result of the operation + * + * As usual auditLogAsHtml and auditLogError can be ignored. + **/ + void result(const GpgME::Error &error, + const QString &auditLogAsHtml = QString(), + const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif diff --git a/lang/qt/src/verifydetachedjob.h b/lang/qt/src/verifydetachedjob.h new file mode 100644 index 0000000..b339a8c --- /dev/null +++ b/lang/qt/src/verifydetachedjob.h @@ -0,0 +1,99 @@ +/* + verifydetachedjob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_VERIFYDETACHEDJOB_H__ +#define __KLEO_VERIFYDETACHEDJOB_H__ + +#include "job.h" +#include "qgpgme_export.h" + +#include <memory> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class VerificationResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous verification of detached signatures + + To use a VerifyDetachedJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the verification with a + call to start(). This call might fail, in which case the + VerifyDetachedJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the VerifyDetachedJob will schedule + it's own destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT VerifyDetachedJob : public Job +{ + Q_OBJECT +protected: + explicit VerifyDetachedJob(QObject *parent); +public: + ~VerifyDetachedJob(); + + /** + Starts the verification operation. \a signature contains the + signature data, while \a signedData contains the data over + which the signature was made. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &signature, + const QByteArray &signedData) = 0; + + /*! + \overload + + \throws GpgME::Exception if starting fails. + */ + virtual void start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData) = 0; + + virtual GpgME::VerificationResult exec(const QByteArray &signature, + const QByteArray &signedData) = 0; + +Q_SIGNALS: + void result(const GpgME::VerificationResult &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_VERIFYDETACHEDJOB_H__ diff --git a/lang/qt/src/verifyopaquejob.h b/lang/qt/src/verifyopaquejob.h new file mode 100644 index 0000000..f064049 --- /dev/null +++ b/lang/qt/src/verifyopaquejob.h @@ -0,0 +1,101 @@ +/* + verifyopaquejob.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_VERIFYOPAQUEJOB_H__ +#define __KLEO_VERIFYOPAQUEJOB_H__ + +#include "job.h" + +#include <memory> + +class QByteArray; +class QIODevice; + +namespace GpgME +{ +class Error; +class VerificationResult; +} + +namespace QGpgME +{ + +/** + @short An abstract base class for asynchronous verification of opaque signatures + + To use a VerifyOpaqueJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the verification with a + call to start(). This call might fail, in which case the + VerifyOpaqueJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the VerifyOpaqueJob will schedule + it's own destruction by calling QObject::deleteLater(). +*/ +class QGPGME_EXPORT VerifyOpaqueJob : public Job +{ + Q_OBJECT +protected: + explicit VerifyOpaqueJob(QObject *parent); +public: + ~VerifyOpaqueJob(); + + /** + Starts the verification operation. \a signature contains the + signature data, while \a signedData contains the data over + which the signature was made. + */ + virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &signedData) = 0; + + /*! + \overload + + If \a plainText is non-null, the plaintext is written + there. Otherwise, it will be delivered in the second argument + of result(). + + \throws GpgME::Exception if starting fails + */ + virtual void start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0; + + /** Synchronous version of @ref start */ + virtual GpgME::VerificationResult exec(const QByteArray &signedData, QByteArray &plainText) = 0; + +Q_SIGNALS: + void result(const GpgME::VerificationResult &result, const QByteArray &plainText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif // __KLEO_VERIFYOPAQUEJOB_H__ diff --git a/lang/qt/src/wkspublishjob.h b/lang/qt/src/wkspublishjob.h new file mode 100644 index 0000000..782112f --- /dev/null +++ b/lang/qt/src/wkspublishjob.h @@ -0,0 +1,101 @@ +/* wkspublishjob.h + + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef QGPGME_WKSPUBLISHJOB_H +#define QGPGME_WKSPUBLISHJOB_H + +#include "job.h" + +#include "qgpgme_export.h" + +namespace GpgME +{ + class Key; +} // namespace GpgME + +namespace QGpgME { + +/** + * Handles Web Key Service Publishing. Needs WKS tools installed and + * server support. + * + * Remember that after a result is emited the job is auto deleted + * so you can only use it for a single action. + */ +class QGPGME_EXPORT WKSPublishJob: public Job +{ + Q_OBJECT +protected: + explicit WKSPublishJob(QObject *parent); +public: + ~WKSPublishJob(); + + + /** Start a check if WKS Publishing is supported. As this involves + * an HTTP Query it might take a while. Returns GPG_ERR_NOT_SUPPORED + * result if GnuPG is too old or the required tools are not installed. + * + * The error GPG_ERR_NOT_ENABLED indicates that wks-tools failed to + * detect a working wks service for this. + * + * @param the mailbox to check for. + **/ + virtual void startCheck(const QString &mailbox) = 0; + + /** Create a publish request. + * The returned Data from the result will contain + * the full Mail as returned by gpg-wks-client --create + * + * @param fpr the fingerprint of the key to create the request for. + * @param mailbox A simple mail address without a Name. + */ + virtual void startCreate(const char *fpr, const QString &mailbox) = 0; + + /** Handle a submisson response. The returned Data will contain + * the full Mail as returned by gpg-wks-client --create + * + * @param response The response of the server. + **/ + virtual void startRecieve(const QByteArray &response) = 0; + +Q_SIGNALS: + /* Result of the operation returned Data and returned Error are + * the results from gpg-wks-client's stdout or stderr respectively. + * + * As usual auditLogAsHtml and auditLogError can be ignored. + **/ + void result(const GpgME::Error &error, const QByteArray &returnedData, + const QByteArray &returnedError, + const QString &auditLogAsHtml = QString(), + const GpgME::Error &auditLogError = GpgME::Error()); +}; + +} + +#endif diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am new file mode 100644 index 0000000..f243a55 --- /dev/null +++ b/lang/qt/tests/Makefile.am @@ -0,0 +1,95 @@ +# Makefile.am - Makefile for GPGME Qt tests. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +## Process this file with automake to produce Makefile.in + +GPG = gpg + +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) + +EXTRA_DIST = initial.test + +TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \ + t-encrypt t-wkspublish + +moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \ + t-encrypt.moc t-support.hmoc t-wkspublish.moc + +AM_LDFLAGS = -no-install + +LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \ + ../../../src/libgpgme.la @GPGME_QT_LIBS@ @GPG_ERROR_LIBS@ \ + @GPGME_QTTEST_LIBS@ -lstdc++ + +AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \ + @GPG_ERROR_CFLAGS@ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ \ + @LIBASSUAN_CFLAGS@ @GPGME_QTTEST_CFLAGS@ -DBUILDING_QGPGME \ + -I$(top_srcdir)/lang/qt/src \ + -DTOP_SRCDIR="$(top_srcdir)" + +check-local: ./pubring-stamp + +# To guarantee that check-local is run before any tests we +# add this dependency: +initial.test : check-local + +support_src = t-support.h t-support.cpp + +t_keylist_SOURCES = t-keylist.cpp $(support_src) +t_keylocate_SOURCES = t-keylocate.cpp $(support_src) +t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src) +t_tofuinfo_SOURCES = t-tofuinfo.cpp $(support_src) +t_encrypt_SOURCES = t-encrypt.cpp $(support_src) +t_wkspublish_SOURCES = t-wkspublish.cpp $(support_src) +run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp + +nodist_t_keylist_SOURCES = $(moc_files) + +BUILT_SOURCES = $(moc_files) + +noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \ + run-keyformailboxjob t-wkspublish + +CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \ + gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \ + random_seed S.gpg-agent .gpg-v21-migrated pubring-stamp $(moc_files) \ + gpg.conf + +clean-local: + -rm -fR private-keys-v1.d crls.d + +export GNUPGHOME := $(abs_builddir) + +./pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \ + $(top_srcdir)/tests/gpg/secdemo.asc + echo "ignore-invalid-option allow-loopback-pinentry" > $(abs_builddir)/gpg-agent.conf + echo "allow-loopback-pinentry" >> gpg-agent.conf + echo "ignore-invalid-option pinentry-mode" > gpg.conf + echo "pinentry-mode loopback" >> gpg.conf + $(GPG) --no-permission-warning \ + --import $(top_srcdir)/tests/gpg/pubdemo.asc + $(GPG) --no-permission-warning \ + --passphrase "abc" \ + --import $(top_srcdir)/tests/gpg/secdemo.asc + touch ./pubring-stamp + +.cpp.moc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ + +.h.hmoc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in new file mode 100644 index 0000000..45d4c76 --- /dev/null +++ b/lang/qt/tests/Makefile.in @@ -0,0 +1,951 @@ +# Makefile.in generated by automake 1.14.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2013 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program 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. + +@SET_MAKE@ + +# Makefile.am - Makefile for GPGME Qt tests. +# Copyright (C) 2016 Intevation GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 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 Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see <http://www.gnu.org/licenses/>. + +VPATH = @srcdir@ +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +TESTS = initial.test t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \ + t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \ + t-wkspublish$(EXEEXT) +noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \ + t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \ + run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT) +subdir = lang/qt/tests +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ + $(top_srcdir)/build-aux/mkinstalldirs \ + $(top_srcdir)/build-aux/depcomp +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_pkg_swig.m4 \ + $(top_srcdir)/m4/ax_python_devel.m4 \ + $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/gnupg-ttyname.m4 \ + $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \ + $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT) +run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS) +run_keyformailboxjob_LDADD = $(LDADD) +run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +am__objects_1 = t-support.$(OBJEXT) +am_t_encrypt_OBJECTS = t-encrypt.$(OBJEXT) $(am__objects_1) +t_encrypt_OBJECTS = $(am_t_encrypt_OBJECTS) +t_encrypt_LDADD = $(LDADD) +t_encrypt_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +am_t_keylist_OBJECTS = t-keylist.$(OBJEXT) $(am__objects_1) +am__objects_2 = +nodist_t_keylist_OBJECTS = $(am__objects_2) +t_keylist_OBJECTS = $(am_t_keylist_OBJECTS) \ + $(nodist_t_keylist_OBJECTS) +t_keylist_LDADD = $(LDADD) +t_keylist_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +am_t_keylocate_OBJECTS = t-keylocate.$(OBJEXT) $(am__objects_1) +t_keylocate_OBJECTS = $(am_t_keylocate_OBJECTS) +t_keylocate_LDADD = $(LDADD) +t_keylocate_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +am_t_ownertrust_OBJECTS = t-ownertrust.$(OBJEXT) $(am__objects_1) +t_ownertrust_OBJECTS = $(am_t_ownertrust_OBJECTS) +t_ownertrust_LDADD = $(LDADD) +t_ownertrust_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +am_t_tofuinfo_OBJECTS = t-tofuinfo.$(OBJEXT) $(am__objects_1) +t_tofuinfo_OBJECTS = $(am_t_tofuinfo_OBJECTS) +t_tofuinfo_LDADD = $(LDADD) +t_tofuinfo_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +am_t_wkspublish_OBJECTS = t-wkspublish.$(OBJEXT) $(am__objects_1) +t_wkspublish_OBJECTS = $(am_t_wkspublish_OBJECTS) +t_wkspublish_LDADD = $(LDADD) +t_wkspublish_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \ + ../src/libqgpgme.la ../../../src/libgpgme.la +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(run_keyformailboxjob_SOURCES) $(t_encrypt_SOURCES) \ + $(t_keylist_SOURCES) $(nodist_t_keylist_SOURCES) \ + $(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \ + $(t_tofuinfo_SOURCES) $(t_wkspublish_SOURCES) +DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_encrypt_SOURCES) \ + $(t_keylist_SOURCES) $(t_keylocate_SOURCES) \ + $(t_ownertrust_SOURCES) $(t_tofuinfo_SOURCES) \ + $(t_wkspublish_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_FILEVERSION = @BUILD_FILEVERSION@ +BUILD_REVISION = @BUILD_REVISION@ +BUILD_TIMESTAMP = @BUILD_TIMESTAMP@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLED_LANGUAGES = @ENABLED_LANGUAGES@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@ +GLIBC21 = @GLIBC21@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@ +GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@ +GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@ +GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@ +GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@ +GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@ +GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@ +GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@ +GPGME_QT_LIBS = @GPGME_QT_LIBS@ +GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@ +GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@ +GPG_ERROR_LIBS = @GPG_ERROR_LIBS@ +GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@ +GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@ +GRAPHVIZ = @GRAPHVIZ@ +GREP = @GREP@ +HAVE_CXX11 = @HAVE_CXX11@ +HAVE_DOT = @HAVE_DOT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@ +LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@ +LIBASSUAN_LIBS = @LIBASSUAN_LIBS@ +LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@ +LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@ +LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@ +LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@ +LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@ +LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@ +LIBOBJS = @LIBOBJS@ +LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@ +LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@ +LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MOC2 = @MOC2@ +NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PYTHON = @PYTHON@ +PYTHONS = @PYTHONS@ +PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@ +PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@ +PYTHON_LDFLAGS = @PYTHON_LDFLAGS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_SITE_PKG = @PYTHON_SITE_PKG@ +PYTHON_VERSION = @PYTHON_VERSION@ +PYTHON_VERSIONS = @PYTHON_VERSIONS@ +QTCHOOSER = @QTCHOOSER@ +RANLIB = @RANLIB@ +RC = @RC@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SWIG = @SWIG@ +SWIG_LIB = @SWIG_LIB@ +SYSROOT = @SYSROOT@ +VERSION = @VERSION@ +VERSION_NUMBER = @VERSION_NUMBER@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +emacs_local_vars_begin = @emacs_local_vars_begin@ +emacs_local_vars_end = @emacs_local_vars_end@ +emacs_local_vars_read_only = @emacs_local_vars_read_only@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +GPG = gpg +TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) +EXTRA_DIST = initial.test +moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \ + t-encrypt.moc t-support.hmoc t-wkspublish.moc + +AM_LDFLAGS = -no-install +LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \ + ../../../src/libgpgme.la @GPGME_QT_LIBS@ @GPG_ERROR_LIBS@ \ + @GPGME_QTTEST_LIBS@ -lstdc++ + +AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \ + @GPG_ERROR_CFLAGS@ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ \ + @LIBASSUAN_CFLAGS@ @GPGME_QTTEST_CFLAGS@ -DBUILDING_QGPGME \ + -I$(top_srcdir)/lang/qt/src \ + -DTOP_SRCDIR="$(top_srcdir)" + +support_src = t-support.h t-support.cpp +t_keylist_SOURCES = t-keylist.cpp $(support_src) +t_keylocate_SOURCES = t-keylocate.cpp $(support_src) +t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src) +t_tofuinfo_SOURCES = t-tofuinfo.cpp $(support_src) +t_encrypt_SOURCES = t-encrypt.cpp $(support_src) +t_wkspublish_SOURCES = t-wkspublish.cpp $(support_src) +run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp +nodist_t_keylist_SOURCES = $(moc_files) +BUILT_SOURCES = $(moc_files) +CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \ + gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \ + random_seed S.gpg-agent .gpg-v21-migrated pubring-stamp $(moc_files) \ + gpg.conf + +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .cpp .h .hmoc .lo .moc .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lang/qt/tests/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +run-keyformailboxjob$(EXEEXT): $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_DEPENDENCIES) $(EXTRA_run_keyformailboxjob_DEPENDENCIES) + @rm -f run-keyformailboxjob$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_LDADD) $(LIBS) + +t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_encrypt_DEPENDENCIES) + @rm -f t-encrypt$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_encrypt_OBJECTS) $(t_encrypt_LDADD) $(LIBS) + +t-keylist$(EXEEXT): $(t_keylist_OBJECTS) $(t_keylist_DEPENDENCIES) $(EXTRA_t_keylist_DEPENDENCIES) + @rm -f t-keylist$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_keylist_OBJECTS) $(t_keylist_LDADD) $(LIBS) + +t-keylocate$(EXEEXT): $(t_keylocate_OBJECTS) $(t_keylocate_DEPENDENCIES) $(EXTRA_t_keylocate_DEPENDENCIES) + @rm -f t-keylocate$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_keylocate_OBJECTS) $(t_keylocate_LDADD) $(LIBS) + +t-ownertrust$(EXEEXT): $(t_ownertrust_OBJECTS) $(t_ownertrust_DEPENDENCIES) $(EXTRA_t_ownertrust_DEPENDENCIES) + @rm -f t-ownertrust$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_ownertrust_OBJECTS) $(t_ownertrust_LDADD) $(LIBS) + +t-tofuinfo$(EXEEXT): $(t_tofuinfo_OBJECTS) $(t_tofuinfo_DEPENDENCIES) $(EXTRA_t_tofuinfo_DEPENDENCIES) + @rm -f t-tofuinfo$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_tofuinfo_OBJECTS) $(t_tofuinfo_LDADD) $(LIBS) + +t-wkspublish$(EXEEXT): $(t_wkspublish_OBJECTS) $(t_wkspublish_DEPENDENCIES) $(EXTRA_t_wkspublish_DEPENDENCIES) + @rm -f t-wkspublish$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(t_wkspublish_OBJECTS) $(t_wkspublish_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keyformailboxjob.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylist.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylocate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ownertrust.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-support.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-tofuinfo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + fi; \ + echo "$${col}$$dashes$${std}"; \ + echo "$${col}$$banner$${std}"; \ + test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ + test -z "$$report" || echo "$${col}$$report$${std}"; \ + echo "$${col}$$dashes$${std}"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: all check check-am install install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am \ + check-local clean clean-generic clean-libtool clean-local \ + clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am + + +check-local: ./pubring-stamp + +# To guarantee that check-local is run before any tests we +# add this dependency: +initial.test : check-local + +clean-local: + -rm -fR private-keys-v1.d crls.d + +export GNUPGHOME := $(abs_builddir) + +./pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \ + $(top_srcdir)/tests/gpg/secdemo.asc + echo "ignore-invalid-option allow-loopback-pinentry" > $(abs_builddir)/gpg-agent.conf + echo "allow-loopback-pinentry" >> gpg-agent.conf + echo "ignore-invalid-option pinentry-mode" > gpg.conf + echo "pinentry-mode loopback" >> gpg.conf + $(GPG) --no-permission-warning \ + --import $(top_srcdir)/tests/gpg/pubdemo.asc + $(GPG) --no-permission-warning \ + --passphrase "abc" \ + --import $(top_srcdir)/tests/gpg/secdemo.asc + touch ./pubring-stamp + +.cpp.moc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ + +.h.hmoc: + $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/lang/qt/tests/initial.test b/lang/qt/tests/initial.test new file mode 100755 index 0000000..039e4d0 --- /dev/null +++ b/lang/qt/tests/initial.test @@ -0,0 +1,2 @@ +#!/bin/sh +exit 0 diff --git a/lang/qt/tests/run-keyformailboxjob.cpp b/lang/qt/tests/run-keyformailboxjob.cpp new file mode 100644 index 0000000..9ac7668 --- /dev/null +++ b/lang/qt/tests/run-keyformailboxjob.cpp @@ -0,0 +1,56 @@ +/* + run-keyformailbox.cpp + + This file is part of QGpgME's test suite. + Copyright (c) 2016 Intevation GmbH + + QGpgME is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "keyformailboxjob.h" +#include "keylistjob.h" +#include "protocol.h" + +#include "key.h" +#include "keylistresult.h" + +#include <QDebug> + + +int main(int argc, char **argv) +{ + QString mailbox; + if (argc == 2) { + mailbox = QString::fromLocal8Bit(argv[1]); + } + + auto job = QGpgME::openpgp()->keyForMailboxJob(); + GpgME::Key k; + GpgME::UserID uid; + job->exec(mailbox, true, k, uid); + qDebug() << "UID Name: " << uid.name() << " Mail: " << uid.email() << " id: " << uid.id(); + qDebug() << "Key fpr: " << k.primaryFingerprint(); + return 0; +} diff --git a/lang/qt/tests/t-encrypt.cpp b/lang/qt/tests/t-encrypt.cpp new file mode 100644 index 0000000..3d4cfa9 --- /dev/null +++ b/lang/qt/tests/t-encrypt.cpp @@ -0,0 +1,254 @@ +/* t-encrypt.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#include <QDebug> +#include <QTest> +#include <QTemporaryDir> +#include <QSignalSpy> +#include <QBuffer> +#include "keylistjob.h" +#include "encryptjob.h" +#include "qgpgmeencryptjob.h" +#include "encryptionresult.h" +#include "decryptionresult.h" +#include "qgpgmedecryptjob.h" +#include "qgpgmebackend.h" +#include "keylistresult.h" +#include "engineinfo.h" +#include "t-support.h" + +#define PROGRESS_TEST_SIZE 1 * 1024 * 1024 + +using namespace QGpgME; +using namespace GpgME; + +class EncryptionTest : public QGpgMETest +{ + Q_OBJECT + +Q_SIGNALS: + void asyncDone(); + +private Q_SLOTS: + + void testSimpleEncryptDecrypt() + { + auto listjob = openpgp()->keyListJob(false, false, false); + std::vector<Key> keys; + auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + Q_ASSERT(!keylistresult.error()); + Q_ASSERT(keys.size() == 1); + delete listjob; + + auto job = openpgp()->encryptJob(/*ASCII Armor */true, /* Textmode */ true); + Q_ASSERT(job); + QByteArray cipherText; + auto result = job->exec(keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText); + delete job; + Q_ASSERT(!result.error()); + const auto cipherString = QString::fromUtf8(cipherText); + Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----")); + + /* Now decrypt */ + auto ctx = Context::createForProtocol(OpenPGP); + TestPassphraseProvider provider; + ctx->setPassphraseProvider(&provider); + ctx->setPinentryMode(Context::PinentryLoopback); + auto decJob = new QGpgMEDecryptJob(ctx); + QByteArray plainText; + auto decResult = decJob->exec(cipherText, plainText); + Q_ASSERT(!result.error()); + Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello World")); + delete decJob; + } + + void testProgress() + { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.15") { + // We can only test the progress with 2.1.15 as this started to + // have total progress for memory callbacks + return; + } + auto listjob = openpgp()->keyListJob(false, false, false); + std::vector<Key> keys; + auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + Q_ASSERT(!keylistresult.error()); + Q_ASSERT(keys.size() == 1); + delete listjob; + + auto job = openpgp()->encryptJob(/*ASCII Armor */false, /* Textmode */ false); + Q_ASSERT(job); + QByteArray plainBa; + plainBa.fill('X', PROGRESS_TEST_SIZE); + QByteArray cipherText; + + bool initSeen = false; + bool finishSeen = false; + connect(job, &Job::progress, this, [this, &initSeen, &finishSeen] (const QString& what, int current, int total) { + // We only check for progress 0 and max progress as the other progress + // lines depend on the system speed and are as such unreliable to test. + Q_ASSERT(total == PROGRESS_TEST_SIZE); + if (current == 0) { + initSeen = true; + } + if (current == total) { + finishSeen = true; + } + Q_ASSERT(current >= 0 && current <= total); + }); + connect(job, &EncryptJob::result, this, [this, &initSeen, &finishSeen] (const GpgME::EncryptionResult &result, + const QByteArray &cipherText, + const QString, + const GpgME::Error) { + Q_ASSERT(initSeen); + Q_ASSERT(finishSeen); + Q_EMIT asyncDone(); + }); + + auto inptr = std::shared_ptr<QIODevice>(new QBuffer(&plainBa)); + inptr->open(QIODevice::ReadOnly); + auto outptr = std::shared_ptr<QIODevice>(new QBuffer(&cipherText)); + outptr->open(QIODevice::WriteOnly); + + job->start(keys, inptr, outptr, Context::AlwaysTrust); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } + + void testSymmetricEncryptDecrypt() + { + auto ctx = Context::createForProtocol(OpenPGP); + TestPassphraseProvider provider; + ctx->setPassphraseProvider(&provider); + ctx->setPinentryMode(Context::PinentryLoopback); + ctx->setArmor(true); + ctx->setTextMode(true); + auto job = new QGpgMEEncryptJob(ctx); + QByteArray cipherText; + auto result = job->exec(std::vector<Key>(), QStringLiteral("Hello symmetric World").toUtf8(), Context::AlwaysTrust, cipherText); + delete job; + Q_ASSERT(!result.error()); + const auto cipherString = QString::fromUtf8(cipherText); + Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----")); + + killAgent(mDir.path()); + + auto ctx2 = Context::createForProtocol(OpenPGP); + ctx2->setPassphraseProvider(&provider); + ctx2->setPinentryMode(Context::PinentryLoopback); + auto decJob = new QGpgMEDecryptJob(ctx2); + QByteArray plainText; + auto decResult = decJob->exec(cipherText, plainText); + Q_ASSERT(!result.error()); + Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World")); + delete decJob; + } + +private: + /* Loopback and passphrase provider don't work for mixed encryption. + * So this test is disabled until gnupg(?) is fixed for this. */ + void testMixedEncryptDecrypt() + { + auto listjob = openpgp()->keyListJob(false, false, false); + std::vector<Key> keys; + auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + Q_ASSERT(!keylistresult.error()); + Q_ASSERT(keys.size() == 1); + delete listjob; + + auto ctx = Context::createForProtocol(OpenPGP); + ctx->setPassphraseProvider(new TestPassphraseProvider); + ctx->setPinentryMode(Context::PinentryLoopback); + ctx->setArmor(true); + ctx->setTextMode(true); + auto job = new QGpgMEEncryptJob(ctx); + QByteArray cipherText; + printf("Before exec, flags: %x\n", Context::Symmetric | Context::AlwaysTrust); + auto result = job->exec(keys, QStringLiteral("Hello symmetric World").toUtf8(), + static_cast<Context::EncryptionFlags>(Context::Symmetric | Context::AlwaysTrust), + cipherText); + printf("After exec\n"); + delete job; + Q_ASSERT(!result.error()); + printf("Cipher:\n%s\n", cipherText.constData()); + const auto cipherString = QString::fromUtf8(cipherText); + Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----")); + + killAgent(mDir.path()); + + /* Now create a new homedir which with we test symetric decrypt. */ + QTemporaryDir tmp; + qputenv("GNUPGHOME", tmp.path().toUtf8()); + QFile agentConf(tmp.path() + QStringLiteral("/gpg-agent.conf")); + Q_ASSERT(agentConf.open(QIODevice::WriteOnly)); + agentConf.write("allow-loopback-pinentry"); + agentConf.close(); + + auto ctx2 = Context::createForProtocol(OpenPGP); + ctx2->setPassphraseProvider(new TestPassphraseProvider); + ctx2->setPinentryMode(Context::PinentryLoopback); + ctx2->setTextMode(true); + auto decJob = new QGpgMEDecryptJob(ctx2); + QByteArray plainText; + auto decResult = decJob->exec(cipherText, plainText); + Q_ASSERT(!decResult.error()); + qDebug() << "Plain: " << plainText; + Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World")); + delete decJob; + + killAgent(tmp.path()); + qputenv("GNUPGHOME", mDir.path().toUtf8()); + } + +public Q_SLOT: + + void initTestCase() + { + QGpgMETest::initTestCase(); + const QString gpgHome = qgetenv("GNUPGHOME"); + qputenv("GNUPGHOME", mDir.path().toUtf8()); + Q_ASSERT(mDir.isValid()); + QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf")); + Q_ASSERT(agentConf.open(QIODevice::WriteOnly)); + agentConf.write("allow-loopback-pinentry"); + agentConf.close(); + Q_ASSERT(copyKeyrings(gpgHome, mDir.path())); + } + +private: + QTemporaryDir mDir; +}; + +QTEST_MAIN(EncryptionTest) + +#include "t-encrypt.moc" diff --git a/lang/qt/tests/t-keylist.cpp b/lang/qt/tests/t-keylist.cpp new file mode 100644 index 0000000..767c96b --- /dev/null +++ b/lang/qt/tests/t-keylist.cpp @@ -0,0 +1,107 @@ +/* t-keylist.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <QDebug> +#include <QTest> +#include <QSignalSpy> +#include <QMap> +#include "keylistjob.h" +#include "qgpgmebackend.h" +#include "keylistresult.h" + +#include "t-support.h" + +using namespace QGpgME; +using namespace GpgME; + +class KeyListTest : public QGpgMETest +{ + Q_OBJECT + +Q_SIGNALS: + void asyncDone(); + +private Q_SLOTS: + void testSingleKeyListSync() + { + KeyListJob *job = openpgp()->keyListJob(false, false, false); + std::vector<GpgME::Key> keys; + GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + delete job; + Q_ASSERT (!result.error()); + Q_ASSERT (keys.size() == 1); + const QString kId = QLatin1String(keys.front().keyID()); + Q_ASSERT (kId == QStringLiteral("2D727CC768697734")); + + Q_ASSERT (keys[0].subkeys().size() == 2); + Q_ASSERT (keys[0].subkeys()[0].publicKeyAlgorithm() == Subkey::AlgoDSA); + Q_ASSERT (keys[0].subkeys()[1].publicKeyAlgorithm() == Subkey::AlgoELG_E); + } + + void testPubkeyAlgoAsString() + { + static const QMap<Subkey::PubkeyAlgo, QString> expected { + { Subkey::AlgoRSA, QStringLiteral("RSA") }, + { Subkey::AlgoRSA_E, QStringLiteral("RSA-E") }, + { Subkey::AlgoRSA_S, QStringLiteral("RSA-S") }, + { Subkey::AlgoELG_E, QStringLiteral("ELG-E") }, + { Subkey::AlgoDSA, QStringLiteral("DSA") }, + { Subkey::AlgoECC, QStringLiteral("ECC") }, + { Subkey::AlgoELG, QStringLiteral("ELG") }, + { Subkey::AlgoECDSA, QStringLiteral("ECDSA") }, + { Subkey::AlgoECDH, QStringLiteral("ECDH") }, + { Subkey::AlgoEDDSA, QStringLiteral("EdDSA") }, + { Subkey::AlgoUnknown, QString() } + }; + Q_FOREACH (Subkey::PubkeyAlgo algo, expected.keys()) { + Q_ASSERT(QString::fromUtf8(Subkey::publicKeyAlgorithmAsString(algo)) == + expected.value(algo)); + } + } + + void testKeyListAsync() + { + KeyListJob *job = openpgp()->keyListJob(); + connect(job, &KeyListJob::result, job, [this, job](KeyListResult, std::vector<Key> keys, QString, Error) + { + Q_ASSERT(keys.size() == 1); + Q_EMIT asyncDone(); + }); + job->start(QStringList() << "alfa@example.net"); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } +}; + +QTEST_MAIN(KeyListTest) + +#include "t-keylist.moc" diff --git a/lang/qt/tests/t-keylocate.cpp b/lang/qt/tests/t-keylocate.cpp new file mode 100644 index 0000000..e75f24d --- /dev/null +++ b/lang/qt/tests/t-keylocate.cpp @@ -0,0 +1,130 @@ +/* t-keylocate.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#include <QDebug> +#include <QTest> +#include <QSignalSpy> +#include <QTemporaryDir> +#include "keylistjob.h" +#include "protocol.h" +#include "keylistresult.h" +#include "engineinfo.h" + +#include "t-support.h" + +using namespace QGpgME; +using namespace GpgME; + +class KeyLocateTest : public QGpgMETest +{ + Q_OBJECT + +Q_SIGNALS: + void asyncDone(); + +private Q_SLOTS: + +#ifdef DO_ONLINE_TESTS + void testDaneKeyLocate() + { + QTemporaryDir dir; + const QString oldHome = qgetenv("GNUPGHOME"); + qputenv("GNUPGHOME", dir.path().toUtf8()); + /* Could do this with gpgconf but this is not a gpgconf test ;-) */ + QFile conf(dir.path() + QStringLiteral("/gpg.conf")); + Q_ASSERT(conf.open(QIODevice::WriteOnly)); + conf.write("auto-key-locate dane"); + conf.close(); + + auto *job = openpgp()->locateKeysJob(); + mTestpattern = QStringLiteral("wk@gnupg.org"); + connect(job, &KeyListJob::result, job, [this, job](KeyListResult result, std::vector<Key> keys, QString, Error) + { + Q_ASSERT(!result.error()); + Q_ASSERT(keys.size() == 1); + + Key k = keys.front(); + Q_ASSERT(k.numUserIDs()); + bool found = false; + Q_FOREACH (const UserID uid, k.userIDs()) { + const QString mailBox = QString::fromUtf8(uid.email()); + if (mTestpattern.toLower() == mailBox.toLower()) { + found = true; + } + } + Q_ASSERT(found); + Q_EMIT asyncDone(); + }); + job->start(QStringList() << mTestpattern); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + qputenv("GNUPGHOME", oldHome.toUtf8()); + } +#endif + + void testKeyLocateSingle() + { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.10") { + return; + } + auto *job = openpgp()->locateKeysJob(); + mTestpattern = QStringLiteral("alfa@example.net"); + + connect(job, &KeyListJob::result, job, [this, job](KeyListResult result, std::vector<Key> keys, QString, Error) + { + Q_ASSERT(!result.isNull()); + Q_ASSERT(!result.isTruncated()); + Q_ASSERT(!result.error()); + Q_ASSERT(keys.size() == 1); + + Key k = keys.front(); + Q_ASSERT(k.numUserIDs()); + bool found = false; + Q_FOREACH (const UserID uid, k.userIDs()) { + const QString mailBox = QString::fromUtf8(uid.email()); + if (mTestpattern.toLower() == mailBox.toLower()) { + found = true; + } + } + Q_ASSERT(found); + Q_EMIT asyncDone(); + }); + job->start(QStringList() << mTestpattern); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } + +private: + QString mTestpattern; +}; + +QTEST_MAIN(KeyLocateTest) + +#include "t-keylocate.moc" diff --git a/lang/qt/tests/t-ownertrust.cpp b/lang/qt/tests/t-ownertrust.cpp new file mode 100644 index 0000000..b9efffd --- /dev/null +++ b/lang/qt/tests/t-ownertrust.cpp @@ -0,0 +1,107 @@ +/* t-ownertrust.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <QDebug> +#include <QTest> +#include <QSignalSpy> +#include "keylistjob.h" +#include "protocol.h" +#include "keylistresult.h" +#include "changeownertrustjob.h" + +#include "t-support.h" + +using namespace QGpgME; +using namespace GpgME; + +class ChangeOwnerTrustTest: public QGpgMETest +{ + Q_OBJECT + +Q_SIGNALS: + void asyncDone(); + +private Q_SLOTS: + + void testChangeOwnerTrust() + { + KeyListJob *job = openpgp()->keyListJob(false, true, true); + std::vector<GpgME::Key> keys; + GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + delete job; + Q_ASSERT (!result.error()); + Q_ASSERT (keys.size() == 1); + Key key = keys.front(); + Q_ASSERT (key.ownerTrust() == Key::Unknown); + + ChangeOwnerTrustJob *job2 = openpgp()->changeOwnerTrustJob(); + connect(job2, &ChangeOwnerTrustJob::result, this, [this](Error e) + { + if (e) { + qDebug() << "Error in result: " << e.asString(); + } + Q_ASSERT(!e); + Q_EMIT asyncDone(); + }); + job2->start(key, Key::Ultimate); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + + job = openpgp()->keyListJob(false, true, true); + result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + delete job; + key = keys.front(); + Q_ASSERT (key.ownerTrust() == Key::Ultimate); + + ChangeOwnerTrustJob *job3 = openpgp()->changeOwnerTrustJob(); + connect(job3, &ChangeOwnerTrustJob::result, this, [this](Error e) + { + Q_ASSERT(!e); + Q_EMIT asyncDone(); + }); + job3->start(key, Key::Unknown); + Q_ASSERT(spy.wait()); + + job = openpgp()->keyListJob(false, true, true); + result = job->exec(QStringList() << QStringLiteral("alfa@example.net"), + false, keys); + delete job; + + key = keys.front(); + Q_ASSERT (key.ownerTrust() == Key::Unknown); + } +}; + +QTEST_MAIN(ChangeOwnerTrustTest) + +#include "t-ownertrust.moc" diff --git a/lang/qt/tests/t-support.cpp b/lang/qt/tests/t-support.cpp new file mode 100644 index 0000000..86372f7 --- /dev/null +++ b/lang/qt/tests/t-support.cpp @@ -0,0 +1,95 @@ +/* t-support.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "t-support.h" + +#include <QTest> + +#include <QProcess> +#include <QCoreApplication> +#include <QObject> +#include <QDir> + +void QGpgMETest::initTestCase() +{ + const QString gpgHome = qgetenv("GNUPGHOME"); + QVERIFY2(!gpgHome.isEmpty(), "GNUPGHOME environment variable is not set."); +} + +void QGpgMETest::cleanupTestCase() +{ + QCoreApplication::sendPostedEvents(); + killAgent(); +} + +bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest) +{ + bool is21dir = QFileInfo(src + QDir::separator() + QStringLiteral("pubring.kbx")).exists(); + const QString name = is21dir ? QStringLiteral("pubring.kbx") : + QStringLiteral("pubring.gpg"); + if (!QFile::copy(src + QDir::separator() + name, dest + QDir::separator() + name)) { + return false; + } + if (!is21dir) { + return (QFile::copy(src + QDir::separator() + QStringLiteral("secring.gpg"), + dest + QDir::separator() + QStringLiteral("secring.gpg"))); + } + QDir dir (src + QDir::separator() + QStringLiteral("private-keys-v1.d")); + QDir target(dest); + if (!target.mkdir("private-keys-v1.d")) { + return false; + } + foreach (QString f, dir.entryList(QDir::Files)) { + if (!QFile::copy(dir.path() + QDir::separator() + f, + dest + QDir::separator() + + QStringLiteral("private-keys-v1.d") + QDir::separator() + f)) { + return false; + } + } + return true; +} + +void killAgent(const QString& dir) +{ + QProcess proc; + proc.setProgram(QStringLiteral("gpg-connect-agent")); + QStringList arguments; + arguments << "-S " << dir + "/S.gpg-agent"; + proc.start(); + proc.waitForStarted(); + proc.write("KILLAGENT\n"); + proc.write("BYE\n"); + proc.closeWriteChannel(); + proc.waitForFinished(); +} + + +#include "t-support.hmoc" diff --git a/lang/qt/tests/t-support.h b/lang/qt/tests/t-support.h new file mode 100644 index 0000000..59d9a4d --- /dev/null +++ b/lang/qt/tests/t-support.h @@ -0,0 +1,63 @@ +/* t-support.h + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#ifndef T_SUPPORT_H +#define T_SUPPORT_H + +#include "interfaces/passphraseprovider.h" +#include <QObject> + +namespace GpgME +{ +class TestPassphraseProvider : public PassphraseProvider +{ +public: + char *getPassphrase(const char *useridHint, const char *description, + bool previousWasBad, bool &canceled) Q_DECL_OVERRIDE + { + return strdup("abc"); + } +}; +} // namespace GpgME + +void killAgent(const QString &dir = qgetenv("GNUPGHOME")); + +class QGpgMETest : public QObject +{ + Q_OBJECT +protected: + bool copyKeyrings(const QString &from, const QString& to); + +public Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); +}; + +#endif // T_SUPPORT_H diff --git a/lang/qt/tests/t-tofuinfo.cpp b/lang/qt/tests/t-tofuinfo.cpp new file mode 100644 index 0000000..d76ff7b --- /dev/null +++ b/lang/qt/tests/t-tofuinfo.cpp @@ -0,0 +1,367 @@ +/* t-tofuinfo.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#include <QDebug> +#include <QTest> +#include <QTemporaryDir> +#include "protocol.h" +#include "tofuinfo.h" +#include "tofupolicyjob.h" +#include "verifyopaquejob.h" +#include "verificationresult.h" +#include "signingresult.h" +#include "keylistjob.h" +#include "keylistresult.h" +#include "qgpgmesignjob.h" +#include "key.h" +#include "t-support.h" +#include "engineinfo.h" +#include <iostream> + +using namespace QGpgME; +using namespace GpgME; + +static const char testMsg1[] = +"-----BEGIN PGP MESSAGE-----\n" +"\n" +"owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n" +"GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n" +"y1kvP4y+8D5a11ang0udywsA\n" +"=Crq6\n" +"-----END PGP MESSAGE-----\n"; + +class TofuInfoTest: public QGpgMETest +{ + Q_OBJECT + + bool testSupported() + { + return !(GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.16"); + } + + void testTofuCopy(TofuInfo other, const TofuInfo &orig) + { + Q_ASSERT(!orig.isNull()); + Q_ASSERT(!other.isNull()); + Q_ASSERT(orig.signLast() == other.signLast()); + Q_ASSERT(orig.signCount() == other.signCount()); + Q_ASSERT(orig.validity() == other.validity()); + Q_ASSERT(orig.policy() == other.policy()); + } + + void signAndVerify(const QString &what, const GpgME::Key &key, int expected) + { + Context *ctx = Context::createForProtocol(OpenPGP); + TestPassphraseProvider provider; + ctx->setPassphraseProvider(&provider); + ctx->setPinentryMode(Context::PinentryLoopback); + auto *job = new QGpgMESignJob(ctx); + + std::vector<Key> keys; + keys.push_back(key); + QByteArray signedData; + auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData); + delete job; + + Q_ASSERT(!sigResult.error()); + foreach (const auto uid, keys[0].userIDs()) { + auto info = uid.tofuInfo(); + Q_ASSERT(info.signCount() == expected - 1); + } + + auto verifyJob = openpgp()->verifyOpaqueJob(); + QByteArray verified; + + auto result = verifyJob->exec(signedData, verified); + delete verifyJob; + + Q_ASSERT(!result.error()); + Q_ASSERT(verified == what.toUtf8()); + + Q_ASSERT(result.numSignatures() == 1); + auto sig = result.signatures()[0]; + + auto key2 = sig.key(); + Q_ASSERT(!key.isNull()); + Q_ASSERT(!strcmp (key2.primaryFingerprint(), key.primaryFingerprint())); + Q_ASSERT(!strcmp (key.primaryFingerprint(), sig.fingerprint())); + auto stats = key2.userID(0).tofuInfo(); + Q_ASSERT(!stats.isNull()); + if (stats.signCount() != expected) { + std::cout << "################ Key before verify: " + << key + << "################ Key after verify: " + << key2; + } + Q_ASSERT(stats.signCount() == expected); + } + +private Q_SLOTS: + void testTofuNull() + { + if (!testSupported()) { + return; + } + TofuInfo tofu; + Q_ASSERT(tofu.isNull()); + Q_ASSERT(!tofu.description()); + Q_ASSERT(!tofu.signCount()); + Q_ASSERT(!tofu.signLast()); + Q_ASSERT(!tofu.signFirst()); + Q_ASSERT(tofu.validity() == TofuInfo::ValidityUnknown); + Q_ASSERT(tofu.policy() == TofuInfo::PolicyUnknown); + } + + void testTofuInfo() + { + if (!testSupported()) { + return; + } + auto *job = openpgp()->verifyOpaqueJob(true); + const QByteArray data1(testMsg1); + QByteArray plaintext; + + auto result = job->exec(data1, plaintext); + delete job; + + Q_ASSERT(!result.isNull()); + Q_ASSERT(!result.error()); + Q_ASSERT(!strcmp(plaintext.constData(), "Just GNU it!\n")); + + Q_ASSERT(result.numSignatures() == 1); + Signature sig = result.signatures()[0]; + /* TOFU is always marginal */ + Q_ASSERT(sig.validity() == Signature::Marginal); + + auto stats = sig.key().userID(0).tofuInfo(); + Q_ASSERT(!stats.isNull()); + Q_ASSERT(sig.key().primaryFingerprint()); + Q_ASSERT(sig.fingerprint()); + Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint())); + Q_ASSERT(stats.signFirst() == stats.signLast()); + Q_ASSERT(stats.signCount() == 1); + Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto); + Q_ASSERT(stats.validity() == TofuInfo::LittleHistory); + + testTofuCopy(stats, stats); + + /* Another verify */ + + job = openpgp()->verifyOpaqueJob(true); + result = job->exec(data1, plaintext); + delete job; + + Q_ASSERT(!result.isNull()); + Q_ASSERT(!result.error()); + + Q_ASSERT(result.numSignatures() == 1); + sig = result.signatures()[0]; + /* TOFU is always marginal */ + Q_ASSERT(sig.validity() == Signature::Marginal); + + stats = sig.key().userID(0).tofuInfo(); + Q_ASSERT(!stats.isNull()); + Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint())); + Q_ASSERT(stats.signFirst() == stats.signLast()); + Q_ASSERT(stats.signCount() == 1); + Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto); + Q_ASSERT(stats.validity() == TofuInfo::LittleHistory); + + /* Verify that another call yields the same result */ + job = openpgp()->verifyOpaqueJob(true); + result = job->exec(data1, plaintext); + delete job; + + Q_ASSERT(!result.isNull()); + Q_ASSERT(!result.error()); + + Q_ASSERT(result.numSignatures() == 1); + sig = result.signatures()[0]; + /* TOFU is always marginal */ + Q_ASSERT(sig.validity() == Signature::Marginal); + + stats = sig.key().userID(0).tofuInfo(); + Q_ASSERT(!stats.isNull()); + Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint())); + Q_ASSERT(stats.signFirst() == stats.signLast()); + Q_ASSERT(stats.signCount() == 1); + Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto); + Q_ASSERT(stats.validity() == TofuInfo::LittleHistory); + } + + void testTofuSignCount() + { + if (!testSupported()) { + return; + } + auto *job = openpgp()->keyListJob(false, false, false); + job->addMode(GpgME::WithTofu); + std::vector<GpgME::Key> keys; + GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"), + true, keys); + delete job; + Q_ASSERT(!keys.empty()); + Key key = keys[0]; + Q_ASSERT(!key.isNull()); + + /* As we sign & verify quickly here we need different + * messages to avoid having them treated as the same + * message if they were created within the same second. + * Alternatively we could use the same message and wait + * a second between each call. But this would slow down + * the testsuite. */ + signAndVerify(QStringLiteral("Hello"), key, 1); + key.update(); + signAndVerify(QStringLiteral("Hello2"), key, 2); + key.update(); + signAndVerify(QStringLiteral("Hello3"), key, 3); + key.update(); + signAndVerify(QStringLiteral("Hello4"), key, 4); + } + + void testTofuKeyList() + { + if (!testSupported()) { + return; + } + + /* First check that the key has no tofu info. */ + auto *job = openpgp()->keyListJob(false, false, false); + std::vector<GpgME::Key> keys; + auto result = job->exec(QStringList() << QStringLiteral("zulu@example.net"), + true, keys); + delete job; + Q_ASSERT(!keys.empty()); + auto key = keys[0]; + Q_ASSERT(!key.isNull()); + Q_ASSERT(key.userID(0).tofuInfo().isNull()); + auto keyCopy = key; + keyCopy.update(); + auto sigCnt = keyCopy.userID(0).tofuInfo().signCount(); + signAndVerify(QStringLiteral("Hello5"), keyCopy, + sigCnt + 1); + keyCopy.update(); + signAndVerify(QStringLiteral("Hello6"), keyCopy, + sigCnt + 2); + + /* Now another one but with tofu */ + job = openpgp()->keyListJob(false, false, false); + job->addMode(GpgME::WithTofu); + result = job->exec(QStringList() << QStringLiteral("zulu@example.net"), + true, keys); + delete job; + Q_ASSERT(!result.error()); + Q_ASSERT(!keys.empty()); + auto key2 = keys[0]; + Q_ASSERT(!key2.isNull()); + auto info = key2.userID(0).tofuInfo(); + Q_ASSERT(!info.isNull()); + Q_ASSERT(info.signCount()); + } + + void testTofuPolicy() + { + if (!testSupported()) { + return; + } + + /* First check that the key has no tofu info. */ + auto *job = openpgp()->keyListJob(false, false, false); + std::vector<GpgME::Key> keys; + job->addMode(GpgME::WithTofu); + auto result = job->exec(QStringList() << QStringLiteral("bravo@example.net"), + false, keys); + + if (keys.empty()) { + qDebug() << "bravo@example.net not found"; + qDebug() << "Error: " << result.error().asString(); + const auto homedir = QString::fromLocal8Bit(qgetenv("GNUPGHOME")); + qDebug() << "Homedir is: " << homedir; + QFileInfo fi(homedir + "/pubring.gpg"); + qDebug () << "pubring exists: " << fi.exists() << " readable? " + << fi.isReadable() << " size: " << fi.size(); + QFileInfo fi2(homedir + "/pubring.kbx"); + qDebug () << "keybox exists: " << fi2.exists() << " readable? " + << fi2.isReadable() << " size: " << fi2.size(); + + result = job->exec(QStringList(), false, keys); + foreach (const auto key, keys) { + qDebug() << "Key: " << key.userID(0).name() << " <" + << key.userID(0).email() + << ">\n fpr: " << key.primaryFingerprint(); + } + } + Q_ASSERT(!result.error()); + Q_ASSERT(!keys.empty()); + auto key = keys[0]; + Q_ASSERT(!key.isNull()); + Q_ASSERT(key.userID(0).tofuInfo().policy() != TofuInfo::PolicyBad); + auto *tofuJob = openpgp()->tofuPolicyJob(); + auto err = tofuJob->exec(key, TofuInfo::PolicyBad); + Q_ASSERT(!err); + result = job->exec(QStringList() << QStringLiteral("bravo@example.net"), + false, keys); + Q_ASSERT(!keys.empty()); + key = keys[0]; + Q_ASSERT(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyBad); + err = tofuJob->exec(key, TofuInfo::PolicyGood); + + result = job->exec(QStringList() << QStringLiteral("bravo@example.net"), + false, keys); + key = keys[0]; + Q_ASSERT(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyGood); + delete tofuJob; + delete job; + } + + void initTestCase() + { + QGpgMETest::initTestCase(); + const QString gpgHome = qgetenv("GNUPGHOME"); + qputenv("GNUPGHOME", mDir.path().toUtf8()); + Q_ASSERT(mDir.isValid()); + QFile conf(mDir.path() + QStringLiteral("/gpg.conf")); + Q_ASSERT(conf.open(QIODevice::WriteOnly)); + conf.write("trust-model tofu+pgp"); + conf.close(); + QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf")); + Q_ASSERT(agentConf.open(QIODevice::WriteOnly)); + agentConf.write("allow-loopback-pinentry"); + agentConf.close(); + Q_ASSERT(copyKeyrings(gpgHome, mDir.path())); + } +private: + QTemporaryDir mDir; + +}; + +QTEST_MAIN(TofuInfoTest) + +#include "t-tofuinfo.moc" diff --git a/lang/qt/tests/t-wkspublish.cpp b/lang/qt/tests/t-wkspublish.cpp new file mode 100644 index 0000000..17d3447 --- /dev/null +++ b/lang/qt/tests/t-wkspublish.cpp @@ -0,0 +1,278 @@ +/* t-wkspublish.cpp + + This file is part of qgpgme, the Qt API binding for gpgme + Copyright (c) 2016 Intevation GmbH + + QGpgME 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. + + QGpgME is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ +#include <QDebug> +#include <QTest> +#include <QSignalSpy> +#include <QTemporaryDir> +#include "wkspublishjob.h" +#include "keygenerationjob.h" +#include "keygenerationresult.h" +#include "importjob.h" +#include "importresult.h" +#include "protocol.h" +#include "engineinfo.h" + +#include "t-support.h" + +using namespace QGpgME; +using namespace GpgME; + +//#define DO_ONLINE_TESTS + +#define TEST_ADDRESS "testuser2@test.gnupg.org" + +static const char *testSecKey = +"-----BEGIN PGP PRIVATE KEY BLOCK-----\n" +"\n" +"lHgEV77hVhMJKyQDAwIIAQEHAgMEN3qKqBr9EecnfUnpw8RS8DHAjJqhwm2HAoEE\n" +"3yfQQ9w8uB/bKm5dqW4HML3JWRH8YoJaKSVrJY2D1FZUY+vHlgABAKDwEAB0HND8\n" +"5kbxiJmqKIuuNqCJ2jHgs9G0xk4GdKvZEdq0JlRlc3QgVXNlciAyIDx0ZXN0dXNl\n" +"cjJAdGVzdC5nbnVwZy5vcmc+iHkEExMIACEFAle+4VYCGwMFCwkIBwIGFQgJCgsC\n" +"BBYCAwECHgECF4AACgkQRVRoUEJO+6zgFQD7BF3pnS3w3A7J9y+Y3kyGfmscXFWJ\n" +"Kme1PAsAlVSm1y4A+weReMvWFYHJH257v94yhStmV8egGoybsNDttNAW53cbnHwE\n" +"V77hVhIJKyQDAwIIAQEHAgMEX+6cF0HEn4g3ztFvwHyr7uwXMVYUGL3lE3mjhnV3\n" +"SbY6Dmy3OeFVnEVkawHqSv+HobpQTeEqNoQHAoIiXFCRlgMBCAcAAP9FykiyDspm\n" +"T33XWRPD+LAOmaIU7CIhfv9+lVkeExlU1w+qiGEEGBMIAAkFAle+4VYCGwwACgkQ\n" +"RVRoUEJO+6xjhgD/ZJ/MwYZJPk/xPYhTP8+wF+tErVNA8w3pP9D69dgUPdcA/izZ\n" +"Pji6YetVhgsyaHc4PrKynsk5G6nM3KkAOehUQsX8\n" +"=S/Wa\n" +"-----END PGP PRIVATE KEY BLOCK-----\n"; + +static const char *testResponse = +"From key-submission@test.gnupg.org Thu Aug 25 12:15:54 2016\n" +"Return-Path: <webkey@g10code.com>\n" +"From: key-submission@test.gnupg.org\n" +"To: testuser2@test.gnupg.org\n" +"Subject: Confirm your key publication\n" +"X-Wks-Loop: webkey.g10code.com\n" +"MIME-Version: 1.0\n" +"Content-Type: multipart/encrypted; protocol=\"application/pgp-encrypted\";\n" +" boundary=\"=-=01-wbu5fr9nu6fix5tcojjo=-=\"\n" +"Date: Thu, 25 Aug 2016 12:15:54 +0000\n" +"Message-Id: <E1bctZa-0004LE-Fr@kerckhoffs.g10code.com>\n" +"Sender: <webkey@g10code.com>\n" +"X-Kolab-Scheduling-Message: FALSE\n" +"\n" +" \n" +"\n" +"--=-=01-wbu5fr9nu6fix5tcojjo=-=\n" +"Content-Type: application/pgp-encrypted\n" +"\n" +"Version: 1\n" +"\n" +"--=-=01-wbu5fr9nu6fix5tcojjo=-=\n" +"Content-Type: application/octet-stream\n" +"\n" +"-----BEGIN PGP MESSAGE-----\n" +"Version: GnuPG v2\n" +"\n" +"hH4D8pSp7hUsFUASAgMEg0w39E6d0TkFYxLbT6n3YcoKTT+Ur/c7Sn1ECyL7Rnuk\n" +"cmPO0adt3JxueK7Oz5COlk32SECFODdF3cQuDhkGxzC6Sfc4SfisdILmNhaT/MeW\n" +"8a+yE4skSK70absif4kw5XkvxXNxHeIHfAteP50jPJLSwEsBTEceb9cRMoP7s8w0\n" +"lYyi+RWQ7UKlKKywtcRCL4ow2H7spjx+a+3FzNOAoy7K0/thhLVRk8z+iuPi0/4n\n" +"Z2Ql60USLLUlfV2ZIpXdCd+5GjTJsnGhDos1pas5TZcOOAxO12Cg5TcqHISOaqa8\n" +"6BqxcKCU3NypIynOKHj375KArSs0WsEH8HWHyBBHB+NYtNpnTAuHNKxM+JtNxf+U\n" +"NfD2zptS6kyiHLw+4zjL5pEV7RHS2PBwWBDS6vhnyybNwckleya96U04iYiGRYGE\n" +"lUUR6Fl8H6x04dItFH1/jJA6Ppcu4FoYou04HADWCqJXPTgztjiW1/9QoCeXl5lm\n" +"CcOCcuw7lXp+qTejuns=\n" +"=SsWX\n" +"-----END PGP MESSAGE-----\n" +"\n" +"--=-=01-wbu5fr9nu6fix5tcojjo=-=--\n"; + + +class WKSPublishTest : public QGpgMETest +{ + Q_OBJECT + +Q_SIGNALS: + void asyncDone(); + +private Q_SLOTS: + void testUnsupported() + { + // First check if it is supported + auto job = openpgp()->wksPublishJob(); + connect(job, &WKSPublishJob::result, this, + [this] (Error err, QByteArray out, QByteArray errout, QString, Error) { + Q_ASSERT(err); + Q_EMIT asyncDone(); + }); + job->startCheck ("testuser1@localhost"); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } +#ifdef DO_ONLINE_TESTS +private Q_SLOTS: +#else +private: +#endif + void testWSKPublishSupport() + { + // First check if it is supported + auto job = openpgp()->wksPublishJob(); + connect(job, &WKSPublishJob::result, this, + [this] (Error err, QByteArray out, QByteArray errout, QString, Error) { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") { + std::cout << err; + Q_ASSERT(err); + } else { + Q_ASSERT(!err); + } + Q_EMIT asyncDone(); + }); + job->startCheck ("testuser1@test.gnupg.org"); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } + + void testWKSPublishErrors() { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") { + /* Not supported */ + return; + } + auto job = openpgp()->wksPublishJob(); + connect(job, &WKSPublishJob::result, this, + [this] (Error err, QByteArray out, QByteArray errout, QString, Error) { + Q_ASSERT(err); + Q_EMIT asyncDone(); + }); + job->startCreate("AB874F24E98EBB8487EE7B170F8E3D97FE7011B7", + QStringLiteral("Foo@bar.baz")); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + } + + void testWKSPublishCreate() { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") { + /* Not supported */ + return; + } + /* First generate a test key */ + const QString args = QStringLiteral("<GnupgKeyParms format=\"internal\">\n" + "%no-protection\n" + "%transient-key\n" + "key-type: ECDSA\n" + "key-curve: brainpoolP256r1\n" + "key-usage: sign\n" + "subkey-type: ECDH\n" + "subkey-curve: brainpoolP256r1\n" + "subkey-usage: encrypt\n" + "name-email: %1\n" + "name-real: Test User\n" + "</GnupgKeyParms>").arg(TEST_ADDRESS); + + auto keygenjob = openpgp()->keyGenerationJob(); + QByteArray fpr; + connect(keygenjob, &KeyGenerationJob::result, this, + [this, &fpr](KeyGenerationResult result, QByteArray pubkeyData, QString, Error) + { + Q_ASSERT(!result.error()); + fpr = QByteArray(result.fingerprint()); + Q_ASSERT(!fpr.isEmpty()); + Q_EMIT asyncDone(); + }); + keygenjob->start(args); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + + /* Then try to create a request. */ + auto job = openpgp()->wksPublishJob(); + connect(job, &WKSPublishJob::result, this, + [this] (Error err, QByteArray out, QByteArray errout, QString, Error) { + Q_ASSERT(!err); + Q_EMIT asyncDone(); + const QString outstr = QString(out); + Q_ASSERT(outstr.contains( + QStringLiteral("-----BEGIN PGP PUBLIC KEY BLOCK-----"))); + Q_ASSERT(outstr.contains( + QStringLiteral("Content-Type: application/pgp-keys"))); + Q_ASSERT(outstr.contains( + QStringLiteral("From: " TEST_ADDRESS))); + }); + job->startCreate(fpr.constData(), QLatin1String(TEST_ADDRESS)); + Q_ASSERT(spy.wait()); + } + + void testWKSPublishRecieve() { + if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") { + /* Not supported */ + return; + } + auto importjob = openpgp()->importJob(); + connect(importjob, &ImportJob::result, this, + [this](ImportResult result, QString, Error) + { + Q_ASSERT(!result.error()); + Q_ASSERT(!result.imports().empty()); + Q_ASSERT(result.numSecretKeysImported()); + Q_EMIT asyncDone(); + }); + importjob->start(QByteArray(testSecKey)); + QSignalSpy spy (this, SIGNAL(asyncDone())); + Q_ASSERT(spy.wait()); + + /* Get a response. */ + auto job = openpgp()->wksPublishJob(); + connect(job, &WKSPublishJob::result, this, + [this] (Error err, QByteArray out, QByteArray errout, QString, Error) { + Q_ASSERT(!err); + Q_EMIT asyncDone(); + const QString outstr = QString(out); + Q_ASSERT(outstr.contains( + QStringLiteral("-----BEGIN PGP MESSAGE-----"))); + Q_ASSERT(outstr.contains( + QStringLiteral("Content-Type: multipart/encrypted;"))); + Q_ASSERT(outstr.contains( + QStringLiteral("From: " TEST_ADDRESS))); + }); + job->startRecieve(QByteArray(testResponse)); + Q_ASSERT(spy.wait()); + } + + void initTestCase() + { + QGpgMETest::initTestCase(); + const QString gpgHome = qgetenv("GNUPGHOME"); + qputenv("GNUPGHOME", mDir.path().toUtf8()); + Q_ASSERT(mDir.isValid()); + QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf")); + Q_ASSERT(agentConf.open(QIODevice::WriteOnly)); + agentConf.write("allow-loopback-pinentry"); + agentConf.close(); + } +private: + QTemporaryDir mDir; +}; + +QTEST_MAIN(WKSPublishTest) + +#include "t-wkspublish.moc" |