diff --git a/gpgme++/CMakeLists.txt b/gpgme++/CMakeLists.txt index cd555665e..cd8962144 100644 --- a/gpgme++/CMakeLists.txt +++ b/gpgme++/CMakeLists.txt @@ -1,140 +1,140 @@ project( gpgmepp ) include_directories( ${GPGME_INCLUDES} ${Boost_INCLUDE_DIR} ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-gpgme++.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-gpgme++.h ) ## gpgme comes in three flavours on each of the platforms: ## Windows: gpgme, gpgme-glib, gpgme-qt ## Unix: gpgme, gpgme-pthread, gpgme-pth ## We're building corresponding gpgme++ flavours set(gpgme_LIB_SRCS 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 ) -set( _gpgmepp_version 2.1.0 ) +set( _gpgmepp_version 2.2.0 ) set( _gpgmepp_soversion 2 ) set( GPGMEPP_INCLUDE ${INCLUDE_INSTALL_DIR} ${GPGME_INCLUDES} ${Boost_INCLUDE_DIR} ) if ( GPGME_VANILLA_FOUND ) kde4_add_library( gpgmepp SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp ${GPGME_VANILLA_LIBRARIES} ) set_target_properties( gpgmepp PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++ ) get_target_property( GPGMEPP_VANILLA_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} COMPONENT Devel) endif ( GPGME_VANILLA_FOUND ) if ( GPGME_GLIB_FOUND ) kde4_add_library( gpgmepp-glib SHARED ${gpgme_LIB_SRCS} context_glib.cpp ) target_link_libraries( gpgmepp-glib ${GPGME_GLIB_LIBRARIES} ) set_target_properties( gpgmepp-glib PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-glib DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_GLIB_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-glib EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_GLIB_FOUND ) if ( GPGME_QT_FOUND ) kde4_add_library( gpgmepp-qt SHARED ${gpgme_LIB_SRCS} context_qt.cpp ) target_link_libraries( gpgmepp-qt ${GPGME_QT_LIBRARIES} ) if(WIN32) target_link_libraries( gpgmepp-qt ${GPGME_VANILLA_LIBRARIES} ) endif(WIN32) set_target_properties( gpgmepp-qt PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-qt DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_QT_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-qt EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_QT_FOUND ) if ( GPGME_PTHREAD_FOUND ) kde4_add_library( gpgmepp-pthread SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp-pthread ${GPGME_PTHREAD_LIBRARIES} ) set_target_properties( gpgmepp-pthread PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-pthread DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_PTHREAD_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-pthread EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_PTHREAD_FOUND ) if ( GPGME_PTH_FOUND ) kde4_add_library( gpgmepp-pth SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp-pth ${GPGME_PTH_LIBRARIES} ) set_target_properties( gpgmepp-pth PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-pth DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_PTH_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-pth EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_PTH_FOUND ) include( CMakeExportBuildSettings ) # this writes way too much, but do we care? EXPORT_LIBRARY_DEPENDENCIES( ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppLibraryDepends.cmake ) ########### install files ############### configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GpgmeppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppConfig.cmake @ONLY ) if ( GPGME_FOUND ) add_subdirectory( interfaces ) install(FILES global.h error.h exception.h context.h key.h trustitem.h eventloopinteractor.h editinteractor.h data.h gpgmefw.h result.h keylistresult.h keygenerationresult.h importresult.h decryptionresult.h verificationresult.h signingresult.h encryptionresult.h notation.h engineinfo.h gpgsetexpirytimeeditinteractor.h gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h gpgadduserideditinteractor.h gpgme++_export.h DESTINATION ${INCLUDE_INSTALL_DIR}/gpgme++ COMPONENT Devel ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppLibraryDepends.cmake DESTINATION ${LIB_INSTALL_DIR}/gpgmepp ) endif ( GPGME_FOUND ) diff --git a/gpgme++/ConfigureChecks.cmake b/gpgme++/ConfigureChecks.cmake index dc43e8fd0..f7a7bcfd8 100644 --- a/gpgme++/ConfigureChecks.cmake +++ b/gpgme++/ConfigureChecks.cmake @@ -1,285 +1,335 @@ # gpgme configure checks include(CheckFunctionExists) if ( GPGME_FOUND ) set(CMAKE_REQUIRED_INCLUDES ${GPGME_INCLUDES}) set(CMAKE_REQUIRED_LIBRARIES) foreach( _FLAVOUR VANILLA PTHREAD QT PTH GLIB ) if ( NOT CMAKE_REQUIRED_LIBRARIES ) if ( GPGME_${_FLAVOUR}_FOUND ) set(CMAKE_REQUIRED_LIBRARIES ${GPGME_VANILLA_LIBRARIES}) endif( GPGME_${_FLAVOUR}_FOUND ) endif( NOT CMAKE_REQUIRED_LIBRARIES ) endforeach( _FLAVOUR ) # check if gpgme has gpgme_data_{get,set}_file_name (new in 1.1.0) check_cxx_source_compiles (" #include int main() { gpgme_data_t data = 0; const char * filename = 0; const gpgme_error_t err = gpgme_data_set_file_name( data, filename ); char * filename2 = gpgme_data_get_file_name( data ); (void)filename2; (void)err; return 0; } " HAVE_GPGME_DATA_SET_FILE_NAME ) # check if gpgme has GPGME_INCLUDE_CERTS_DEFAULT check_cxx_source_compiles (" #include int main() { int i = GPGME_INCLUDE_CERTS_DEFAULT; return 0; } " HAVE_GPGME_INCLUDE_CERTS_DEFAULT ) # check if gpgme has GPGME_KEYLIST_MODE_SIG_NOTATIONS check_cxx_source_compiles (" #include int main() { gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_SIG_NOTATIONS; return 0; } " HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS ) # check if gpgme_key_sig_t has notations check_cxx_source_compiles (" #include int main() { gpgme_key_sig_t key_sig = 0; gpgme_sig_notation_t notation = key_sig->notations; return 0; } " HAVE_GPGME_KEY_SIG_NOTATIONS ) # check if gpgme has gpgme_key_t->is_qualified check_cxx_source_compiles (" #include void test(gpgme_key_t& key) { unsigned int iq; iq = key->is_qualified; } int main() { return 0; } " HAVE_GPGME_KEY_T_IS_QUALIFIED ) # check if gpgme has gpgme_sig_notation_t->critical check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; unsigned int cr1 = sig_notation->critical; unsigned int cr2 = GPGME_SIG_NOTATION_CRITICAL; return 0; } " HAVE_GPGME_SIG_NOTATION_CRITICAL ) # check if gpgme has gpgme_sig_notation_t->flags check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; gpgme_sig_notation_flags_t f = sig_notation->flags; return 0; } " HAVE_GPGME_SIG_NOTATION_FLAGS_T ) # check if gpgme has gpgme_sig_notation_t->human_readable check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; unsigned int cr1 = sig_notation->human_readable; unsigned int cr2 = GPGME_SIG_NOTATION_HUMAN_READABLE; return 0; } " HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE ) # check if gpgme has gpgme_subkey_t->is_qualified check_cxx_source_compiles (" #include void test(gpgme_subkey_t& subkey) { unsigned int iq; iq = subkey->is_qualified; } int main() { return 0; } " HAVE_GPGME_SUBKEY_T_IS_QUALIFIED ) # check if gpgme has gpgme_engine_info_t->home_dir check_cxx_source_compiles (" #include int main() { gpgme_engine_info_t ei = 0; const char * hd = ei->home_dir; return 0; } " HAVE_GPGME_ENGINE_INFO_T_HOME_DIR ) #check if gpgme has gpgme_ctx_{get,set}_engine_info() check_cxx_source_compiles (" #include int main() { gpgme_ctx_t ctx = 0; const gpgme_engine_info_t ei = gpgme_ctx_get_engine_info( ctx ); const char * filename = 0; const char * home_dir = 0; const gpgme_error_t e = gpgme_ctx_set_engine_info( ctx, GPGME_PROTOCOL_OpenPGP, filename, home_dir ); return 0; } " HAVE_GPGME_CTX_GETSET_ENGINE_INFO ) # missing, but not needed yet (only for edit interaction) #+ GPGME_STATUS_SIG_SUBPACKET, #+ GPGME_STATUS_NEED_PASSPHRASE_PIN, #+ GPGME_STATUS_SC_OP_FAILURE, #+ GPGME_STATUS_SC_OP_SUCCESS, #+ GPGME_STATUS_CARDCTRL, #+ GPGME_STATUS_BACKUP_KEY_CREATED, #+ GPGME_STATUS_PKA_TRUST_BAD, #+ GPGME_STATUS_PKA_TRUST_GOOD, #+ #+ GPGME_STATUS_PLAINTEXT # check if gpgme has gpgme_sig_notation_{clear,add,get} check_cxx_source_compiles (" #include int main() { gpgme_ctx_t ctx = 0; const gpgme_sig_notation_t nota = gpgme_sig_notation_get( ctx ); const char * const name = 0; const char * const value = 0; const gpgme_sig_notation_flags_t flags = 0; const gpgme_error_t err = gpgme_sig_notation_add( ctx, name, value, flags ); gpgme_sig_notation_clear( ctx ); return 0; } " HAVE_GPGME_SIG_NOTATION_CLEARADDGET ) # check if gpgme has gpgme_decrypt_result_t->file_name check_cxx_source_compiles (" #include int main() { gpgme_decrypt_result_t res = 0; const char * const fn = res->file_name; (void)fn; } " HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME ) # check if gpgme has gpgme_recipient_t and gpgme_decrypt_result_t->recipients check_cxx_source_compiles (" #include int main() { gpgme_decrypt_result_t res = 0; gpgme_recipient_t r = res->recipients; const char * kid = r->keyid; r = r->next; const gpgme_pubkey_algo_t algo = r->pubkey_algo; const gpgme_error_t err = r->status; return 0; } " HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS ) # check if gpgme has gpgme_verify_result_t->file_name check_cxx_source_compiles (" #include int main() { gpgme_verify_result_t res = 0; const char * fn = res->file_name; (void)fn; return 0; } " HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME ) # check if gpgme has gpgme_signature_t->pka_{trust,address} check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; unsigned int pkat = sig->pka_trust; const char * pkaa = sig->pka_address; return 0; } " HAVE_GPGME_SIGNATURE_T_PKA_FIELDS ) # check if gpgme has gpgme_signature_t->{hash,pubkey}_algo check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; gpgme_pubkey_algo_t pk = sig->pubkey_algo; gpgme_hash_algo_t h = sig->hash_algo; return 0; } " HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS ) # check if gpgme has gpgme_signature_t->chain_model check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; unsigned int cm = sig->chain_model; return 0; } " HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL ) # check if gpgme has gpgme_get_fdptr check_function_exists( "gpgme_get_fdptr" HAVE_GPGME_GET_FDPTR ) # check if gpgme has gpgme_op_getauditlog check_function_exists ("gpgme_op_getauditlog" HAVE_GPGME_OP_GETAUDITLOG ) # check if gpgme has GPGME_PROTOCOL_GPGCONF check_cxx_source_compiles (" #include int main() { gpgme_protocol_t proto = GPGME_PROTOCOL_GPGCONF; return 0; } " HAVE_GPGME_PROTOCOL_GPGCONF ) # check if gpgme has gpgme_cancel_async check_function_exists ("gpgme_cancel_async" HAVE_GPGME_CANCEL_ASYNC ) # check if gpg-error has GPG_ERR_NO_PASSPHRASE check_cxx_source_compiles (" #include int main() { gpg_error_t err = GPG_ERR_NO_PASSPHRASE; return 0; } " HAVE_GPG_ERR_NO_PASSPHRASE ) # check if gpg-error has GPG_ERR_ALREADY_SIGNED check_cxx_source_compiles (" #include int main() { gpg_error_t err = GPG_ERR_ALREADY_SIGNED; return 0; } " HAVE_GPG_ERR_ALREADY_SIGNED ) +# check if gpgme has GPGME_ENCRYPT_NO_ENCRYPT_TO +check_cxx_source_compiles (" + #include + int main() { + gpgme_encrypt_flags_t f = GPGME_ENCRYPT_NO_ENCRYPT_TO; + return 0; + } +" HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO ) + +# check if gpgme has gpgme_subkey_t->is_cardkey and ->card_number +check_cxx_source_compiles (" + #include + int main() { + gpgme_subkey_t sk = 0; + const char * card_number = sk->card_number; + const unsigned int is_cardkey = sk->is_cardkey; + return 0; + } +" HAVE_GPGME_SUBKEY_T_IS_CARDKEY ) + +# check if gpgme has assuan protocol support +check_cxx_source_compiles (" + #include + + static gpgme_error_t data_cb(void *, const void *, size_t) { return 0; } + static gpgme_error_t inquire_cb(void *, const char *, const char *, gpgme_data_t *) { return 0; } + static gpgme_error_t status_cb(void *, const char *, const char *) { return 0; } + + int main() { + const gpgme_protocol_t proto = GPGME_PROTOCOL_ASSUAN; + gpgme_ctx_t ctx = 0; + gpgme_assuan_data_cb_t d = data_cb; + gpgme_assuan_inquire_cb_t i = inquire_cb; + gpgme_assuan_status_cb_t s = status_cb; + gpgme_assuan_result_t r = gpgme_op_assuan_result( ctx ); + void * opaque = 0; + gpgme_error_t err = gpgme_op_assuan_transact_start( ctx, \"FOO\", d, opaque, i, opaque, s, opaque ); + err = gpgme_op_assuan_transact( ctx, \"FOO\", d, opaque, i, opaque, s, opaque ); + return 0; + } +" HAVE_GPGME_ASSUAN_ENGINE ) + +check_cxx_source_compiles (" + #include + int main() { + gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_EPHEMERAL; + return 0; + } +" HAVE_GPGME_KEYLIST_MODE_EPHEMERAL ) + set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) endif( GPGME_FOUND ) diff --git a/gpgme++/config-gpgme++.h.cmake b/gpgme++/config-gpgme++.h.cmake index 3077da757..9490138d0 100644 --- a/gpgme++/config-gpgme++.h.cmake +++ b/gpgme++/config-gpgme++.h.cmake @@ -1,76 +1,88 @@ /* Define to 1 if your gpgme has the gpgme_data_{set,get}_file_name functions */ #cmakedefine HAVE_GPGME_DATA_SET_FILE_NAME 1 /* Define to 1 if your gpgme has the GPGME_INCLUDE_CERTS_DEFAULT macro */ #cmakedefine HAVE_GPGME_INCLUDE_CERTS_DEFAULT 1 /* Define to 1 if your gpgme has the GPGME_KEYLIST_MODE_SIG_NOTATIONS macro */ #cmakedefine HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS /* Define to 1 if your gpgme's gpgme_key_sig_t has the notations member */ #cmakedefine HAVE_GPGME_KEY_SIG_NOTATIONS /* Define to 1 if your gpgme's gpgme_key_t has the is_qualified flag */ #cmakedefine HAVE_GPGME_KEY_T_IS_QUALIFIED 1 /* Define to 1 if your gpgme's gpgme_sig_notation_t has the critical flag */ #cmakedefine HAVE_GPGME_SIG_NOTATION_CRITICAL /* Define to 1 if your gpgme's gpgme_sig_notation_t has the flags member */ #cmakedefine HAVE_GPGME_SIG_NOTATION_FLAGS_T /* Define to 1 if your gpgme's gpgme_sig_notation_t has the human_readable flag */ #cmakedefine HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE /* Define to 1 if your gpgme's gpgme_subkey_t has the is_qualified flag */ #cmakedefine HAVE_GPGME_SUBKEY_T_IS_QUALIFIED 1 /* Define to 1 if your gpgme's gpgme_engine_info_t has the home_dir member */ #cmakedefine HAVE_GPGME_ENGINE_INFO_T_HOME_DIR 1 /* Define to 1 if your gpgme has the gpgme_ctx_{get,set}_engine_info() functions */ #cmakedefine HAVE_GPGME_CTX_GETSET_ENGINE_INFO 1 /* Define to 1 if your gpgme has the gpgme_sig_notation_{clear,add,get}() functions */ #cmakedefine HAVE_GPGME_SIG_NOTATION_CLEARADDGET 1 /* Define to 1 if your gpgme's gpgme_decrypt_result_t has the file_name member */ #cmakedefine HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME 1 /* Define to 1 if your gpgme's gpgme_decrypt_result_t has the recipients member */ #cmakedefine HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS 1 /* Define to 1 if your gpgme's gpgme_verify_result_t has the file_name member */ #cmakedefine HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME 1 /* Define to 1 if your gpgme's gpgme_signature_t has the pka_{trust,address} fields */ #cmakedefine HAVE_GPGME_SIGNATURE_T_PKA_FIELDS 1 /* Define to 1 if your gpgme's gpgme_signature_t has the {hash,pubkey}_algo fields */ #cmakedefine HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS 1 /* Define to 1 if your gpgme has gpgme_get_fdptr (it won't be in gpgme.h, though!) */ #cmakedefine HAVE_GPGME_GET_FDPTR 1 /* Define to 1 if your gpgme has the gpgme_op_getauditlog function */ #cmakedefine HAVE_GPGME_OP_GETAUDITLOG 1 /* Define to 1 if your gpgme has GPGME_PROTOCOL_GPGCONF */ #cmakedefine HAVE_GPGME_PROTOCOL_GPGCONF 1 /* Define to 1 if your gpgme has gpgme_cancel_async */ #cmakedefine HAVE_GPGME_CANCEL_ASYNC 1 /* Define to 1 if your gpg-error has GPG_ERR_NO_PASSPHRASE */ #cmakedefine HAVE_GPG_ERR_NO_PASSPHRASE 1 /* Define to 1 if your gpg-error has GPG_ERR_ALREADY_SIGNED */ #cmakedefine HAVE_GPG_ERR_ALREADY_SIGNED 1 #ifndef HAVE_GPG_ERR_NO_PASSPHRASE # define GPG_ERR_NO_PASSPHRASE GPG_ERR_INV_PASSPHRASE #endif #ifndef HAVE_GPG_ERR_ALREADY_SIGNED # define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1 #endif + +/* Define to 1 if your gpgme has GPGME_ENCRYPT_NO_ENCRYPT_TO */ +#cmakedefine HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO 1 + +/* Define to 1 if your gpgme has gpgme_subkey_t->card_number and gpgme_subkey_t->is_cardkey */ +#cmakedefine HAVE_GPGME_SUBKEY_T_IS_CARDKEY + +/* Define to 1 if your gpgme has ASSUAN protocol support (in the interface, not only in the implementation */ +#cmakedefine HAVE_GPGME_ASSUAN_ENGINE + +/* Define to 1 if your gpgme has GPGME_KEYLIST_MODE_EPHEMERAL */ +#cmakedefine HAVE_GPGME_KEYLIST_MODE_EPHEMERAL diff --git a/gpgme++/context.cpp b/gpgme++/context.cpp index 66be27b53..41510f089 100644 --- a/gpgme++/context.cpp +++ b/gpgme++/context.cpp @@ -1,1055 +1,1090 @@ /* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include "callbacks.h" #include "data_p.h" #include "context_p.h" #include "util.h" #include #include #ifndef NDEBUG #include using std::cerr; using std::endl; #endif #include namespace GpgME { static inline gpgme_error_t makeError( gpg_err_code_t code ) { return gpg_err_make( (gpg_err_source_t)22, code ); } 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( 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; } 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; d = 0; } Context * Context::createForProtocol( Protocol proto ) { gpgme_ctx_t ctx = 0; if ( gpgme_new ( &ctx ) != 0 ) return 0; switch ( proto ) { case OpenPGP: if ( gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP ) != 0 ) { gpgme_release( ctx ); return 0; } break; case CMS: if ( gpgme_set_protocol( ctx, GPGME_PROTOCOL_CMS ) != 0 ) { gpgme_release( ctx ); return 0; } break; default: return 0; } return new Context( ctx ); } // // // Context::Private // // Context::Private::Private( gpgme_ctx_t c ) : ctx( c ), iocbs( 0 ), lastop( None ), lasterr( GPG_ERR_NO_ERROR ), 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::setIncludeCertificates( int which ) { if ( which == DefaultCertificates ) { #ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT which = GPGME_INCLUDE_CERTS_DEFAULT; #else which = 1; #endif } gpgme_set_include_certs( d->ctx, which ); } int Context::includeCertificates() const { return gpgme_get_include_certs( d->ctx ); } void Context::setKeyListMode( unsigned int mode ) { gpgme_set_keylist_mode( d->ctx, add_to_gpgme_keylist_mode_t( 0, mode ) ); } void Context::addKeyListMode( unsigned int mode ) { const unsigned int cur = gpgme_get_keylist_mode( d->ctx ); gpgme_set_keylist_mode( d->ctx, add_to_gpgme_keylist_mode_t( cur, mode ) ); } unsigned int Context::keyListMode() const { return convert_from_gpgme_keylist_mode_t( gpgme_get_keylist_mode( d->ctx ) ); } void Context::setProgressProvider( ProgressProvider * provider ) { gpgme_set_progress_cb( d->ctx, provider ? &progress_callback : 0, provider ); } ProgressProvider * Context::progressProvider() const { void * pp = 0; gpgme_progress_cb_t pcb = &progress_callback; gpgme_get_progress_cb( d->ctx, &pcb, &pp ); return static_cast( 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( pp ); } void Context::setManagedByEventLoopInteractor( bool manage ) { if ( !EventLoopInteractor::instance() ) { #ifndef NDEBUG cerr << "Context::setManagedByEventLoopInteractor(): " "You must create an instance of EventLoopInteractor " "before using anything that needs one." << endl; #endif return; } if ( manage ) EventLoopInteractor::instance()->manage( this ); else EventLoopInteractor::instance()->unmanage( this ); } bool Context::managedByEventLoopInteractor() const { return d->iocbs != 0; } void Context::installIOCallbacks( gpgme_io_cbs * iocbs ) { if ( !iocbs ) { uninstallIOCallbacks(); return; } gpgme_set_io_cbs( d->ctx, iocbs ); delete d->iocbs; d->iocbs = iocbs; } void Context::uninstallIOCallbacks() { static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 }; // io.add == 0 means disable io callbacks: gpgme_set_io_cbs( d->ctx, &noiocbs ); delete d->iocbs; d->iocbs = 0; } Error Context::setLocale( int cat, const char * val ) { return Error( d->lasterr = gpgme_set_locale( d->ctx, cat, val ) ); } EngineInfo Context::engineInfo() const { #ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO return EngineInfo( gpgme_ctx_get_engine_info( d->ctx ) ); #else return EngineInfo(); #endif } Error Context::setEngineFileName( const char * filename ) { #ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO const char * const home_dir = engineInfo().homeDirectory(); return Error( gpgme_ctx_set_engine_info( d->ctx, gpgme_get_protocol( d->ctx ), filename, home_dir ) ); #else return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } Error Context::setEngineHomeDirectory( const char * home_dir ) { #ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO const char * const filename = engineInfo().fileName(); return Error( gpgme_ctx_set_engine_info( d->ctx, gpgme_get_protocol( d->ctx ), filename, home_dir ) ); #else return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } // // // Key Management // // Error Context::startKeyListing( const char * pattern, bool secretOnly ) { d->lastop = Private::KeyList; return Error( d->lasterr = gpgme_op_keylist_start( d->ctx, pattern, int( secretOnly ) ) ); } Error Context::startKeyListing( const char * patterns[], bool secretOnly ) { d->lastop = Private::KeyList; #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN if ( !patterns || !patterns[0] || !patterns[1] ) // max. one pattern -> use the non-ext version return startKeyListing( patterns ? patterns[0] : 0, secretOnly ); #endif return Error( d->lasterr = gpgme_op_keylist_ext_start( d->ctx, patterns, int( secretOnly ), 0 ) ); } Key Context::nextKey( GpgME::Error & e ) { d->lastop = Private::KeyList; gpgme_key_t key; e = Error( d->lasterr = gpgme_op_keylist_next( d->ctx, &key ) ); return Key( key, false ); } KeyListResult Context::endKeyListing() { d->lasterr = gpgme_op_keylist_end( d->ctx ); return keyListResult(); } KeyListResult Context::keyListResult() const { return KeyListResult( d->ctx, Error(d->lasterr) ); } Key Context::key( const char * fingerprint, GpgME::Error & e , bool secret /*, bool forceUpdate*/ ) { d->lastop = Private::KeyList; gpgme_key_t key; e = Error( d->lasterr = gpgme_get_key( d->ctx, fingerprint, &key, int( secret )/*, int( forceUpdate )*/ ) ); return Key( key, false ); } KeyGenerationResult Context::generateKey( const char * parameters, Data & pubKey ) { d->lastop = Private::KeyGen; Data::Private * const dp = pubKey.impl(); d->lasterr = gpgme_op_genkey( d->ctx, parameters, dp ? dp->data : 0, 0 ); return KeyGenerationResult( d->ctx, Error(d->lasterr) ); } Error Context::startKeyGeneration( const char * parameters, Data & pubKey ) { d->lastop = Private::KeyGen; Data::Private * const dp = pubKey.impl(); return Error( d->lasterr = gpgme_op_genkey_start( d->ctx, parameters, dp ? dp->data : 0, 0 ) ); } KeyGenerationResult Context::keyGenerationResult() const { if ( d->lastop & Private::KeyGen ) return KeyGenerationResult( d->ctx, Error(d->lasterr) ); else return KeyGenerationResult(); } Error Context::exportPublicKeys( const char * pattern, Data & keyData ) { d->lastop = Private::Export; Data::Private * const dp = keyData.impl(); return Error( d->lasterr = gpgme_op_export( d->ctx, pattern, 0, dp ? dp->data : 0 ) ); } Error Context::exportPublicKeys( const char * patterns[], Data & keyData ) { d->lastop = Private::Export; #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN if ( !patterns || !patterns[0] || !patterns[1] ) // max. one pattern -> use the non-ext version return exportPublicKeys( patterns ? patterns[0] : 0, keyData ); #endif Data::Private * const dp = keyData.impl(); return Error( d->lasterr = gpgme_op_export_ext( d->ctx, patterns, 0, dp ? dp->data : 0 ) ); } Error Context::startPublicKeyExport( const char * pattern, Data & keyData ) { d->lastop = Private::Export; Data::Private * const dp = keyData.impl(); return Error( d->lasterr = gpgme_op_export_start( d->ctx, pattern, 0, dp ? dp->data : 0 ) ); } Error Context::startPublicKeyExport( const char * patterns[], Data & keyData ) { d->lastop = Private::Export; #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN if ( !patterns || !patterns[0] || !patterns[1] ) // max. one pattern -> use the non-ext version return startPublicKeyExport( patterns ? patterns[0] : 0, keyData ); #endif Data::Private * const dp = keyData.impl(); return Error( d->lasterr = gpgme_op_export_ext_start( d->ctx, patterns, 0, dp ? dp->data : 0 ) ); } ImportResult Context::importKeys( const Data & data ) { d->lastop = Private::Import; const Data::Private * const dp = data.impl(); d->lasterr = gpgme_op_import( d->ctx, dp ? dp->data : 0 ); return ImportResult( d->ctx, Error(d->lasterr) ); } 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 ) ); } 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::edit( const Key & key, std::auto_ptr func, Data & data ) { d->lastop = Private::Edit; d->lastEditInteractor = func; Data::Private * const dp = data.impl(); return Error( d->lasterr = gpgme_op_edit( d->ctx, key.impl(), d->lastEditInteractor.get() ? edit_interactor_callback : 0, d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0, dp ? dp->data : 0 ) ); } Error Context::startEditing( const Key & key, std::auto_ptr func, Data & data ) { d->lastop = Private::Edit; d->lastEditInteractor = func; Data::Private * const dp = data.impl(); return Error( d->lasterr = gpgme_op_edit_start( d->ctx, key.impl(), d->lastEditInteractor.get() ? edit_interactor_callback : 0, d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0, dp ? dp->data : 0 ) ); } EditInteractor * Context::lastEditInteractor() const { return d->lastEditInteractor.get(); } Error Context::cardEdit( const Key & key, std::auto_ptr func, Data & data ) { d->lastop = Private::CardEdit; d->lastCardEditInteractor = func; Data::Private * const dp = data.impl(); return Error( d->lasterr = gpgme_op_card_edit( d->ctx, key.impl(), d->lastCardEditInteractor.get() ? edit_interactor_callback : 0, d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0, dp ? dp->data : 0 ) ); } Error Context::startCardEditing( const Key & key, std::auto_ptr func, Data & data ) { d->lastop = Private::CardEdit; d->lastCardEditInteractor = func; Data::Private * const dp = data.impl(); return Error( d->lasterr = gpgme_op_card_edit_start( d->ctx, key.impl(), d->lastCardEditInteractor.get() ? edit_interactor_callback : 0, d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0, dp ? dp->data : 0 ) ); } EditInteractor * Context::lastCardEditInteractor() const { return d->lastCardEditInteractor.get(); } 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 ) ); } 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 Context::decryptAndVerify( const Data & cipherText, Data & plainText ) { d->lastop = Private::DecryptAndVerify; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); d->lasterr = gpgme_op_decrypt_verify( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ); return std::make_pair( DecryptionResult( d->ctx, Error(d->lasterr) ), VerificationResult( d->ctx, Error(d->lasterr) ) ); } Error Context::startCombinedDecryptionAndVerification( const Data & cipherText, Data & plainText ) { d->lastop = Private::DecryptAndVerify; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); return Error( d->lasterr = gpgme_op_decrypt_verify_start( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ) ); } #ifdef HAVE_GPGME_OP_GETAUDITLOG unsigned int to_auditlog_flags( unsigned int flags ) { unsigned int result = 0; if ( flags & Context::HtmlAuditLog ) result |= GPGME_AUDITLOG_HTML; if ( flags & Context::AuditLogWithHelp ) result |= GPGME_AUDITLOG_WITH_HELP; return result; } #endif // HAVE_GPGME_OP_GETAUDITLOG Error Context::startGetAuditLog( Data & output, unsigned int flags ) { d->lastop = Private::GetAuditLog; #ifdef HAVE_GPGME_OP_GETAUDITLOG Data::Private * const odp = output.impl(); return Error( d->lasterr = gpgme_op_getauditlog_start( d->ctx, odp ? odp->data : 0, to_auditlog_flags( flags ) ) ); #else (void)output; (void)flags; return Error( d->lasterr = makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } Error Context::getAuditLog( Data & output, unsigned int flags ) { d->lastop = Private::GetAuditLog; #ifdef HAVE_GPGME_OP_GETAUDITLOG Data::Private * const odp = output.impl(); return Error( d->lasterr = gpgme_op_getauditlog( d->ctx, odp ? odp->data : 0, to_auditlog_flags( flags ) ) ); #else (void)output; (void)flags; return Error( d->lasterr = makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } void Context::clearSigningKeys() { gpgme_signers_clear( d->ctx ); } Error Context::addSigningKey( const Key & key ) { return Error( d->lasterr = gpgme_signers_add( d->ctx, key.impl() ) ); } Key Context::signingKey( unsigned int idx ) const { gpgme_key_t key = gpgme_signers_enum( d->ctx, idx ); return Key( key, false ); } std::vector Context::signingKeys() const { std::vector result; gpgme_key_t key; for ( unsigned int i = 0 ; ( key = gpgme_signers_enum( d->ctx, i ) ) ; ++i ) result.push_back( Key( key, false ) ); return result; } void Context::clearSignatureNotations() { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET gpgme_sig_notation_clear( d->ctx ); #endif } GpgME::Error Context::addSignatureNotation( const char * name, const char * value, unsigned int flags ) { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET return Error( gpgme_sig_notation_add( d->ctx, name, value, add_to_gpgme_sig_notation_flags_t( 0, flags ) ) ); #else (void)name; (void)value; (void)flags; return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } GpgME::Error Context::addSignaturePolicyURL( const char * url, bool critical ) { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET return Error( gpgme_sig_notation_add( d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0 ) ); #else (void)url; (void)critical; return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } const char * Context::signaturePolicyURL() const { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( !n->name ) return n->value; #endif return 0; } Notation Context::signatureNotation( unsigned int idx ) const { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( n->name ) if ( idx-- == 0 ) return Notation( n ); #endif return Notation(); } std::vector Context::signatureNotations() const { std::vector result; #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( n->name ) result.push_back( Notation( n ) ); #endif return result; } static gpgme_sig_mode_t sigmode2sigmode( SignatureMode mode ) { switch ( mode ) { default: case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL; case Detached: return GPGME_SIG_MODE_DETACH; case Clearsigned: return GPGME_SIG_MODE_CLEAR; } } SigningResult Context::sign( const Data & plainText, Data & signature, SignatureMode mode ) { d->lastop = Private::Sign; const Data::Private * const pdp = plainText.impl(); Data::Private * const sdp = signature.impl(); d->lasterr = gpgme_op_sign( d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode( mode ) ); return SigningResult( d->ctx, Error(d->lasterr) ); } Error Context::startSigning( const Data & plainText, Data & signature, SignatureMode mode ) { d->lastop = Private::Sign; const Data::Private * const pdp = plainText.impl(); Data::Private * const sdp = signature.impl(); return Error( d->lasterr = gpgme_op_sign_start( d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode( mode ) ) ); } SigningResult Context::signingResult() const { if ( d->lastop & Private::Sign ) return SigningResult( d->ctx, Error(d->lasterr) ); else return SigningResult(); } static gpgme_encrypt_flags_t encryptflags2encryptflags( Context::EncryptionFlags flags ) { unsigned int result = 0; if ( flags & Context::AlwaysTrust ) result |= GPGME_ENCRYPT_ALWAYS_TRUST; +#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO + if ( flags & Context::NoEncryptTo ) + result |= GPGME_ENCRYPT_NO_ENCRYPT_TO; +#endif return static_cast( result ); } EncryptionResult Context::encrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::Encrypt; +#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO + if ( flags & NoEncryptTo ) + return EncryptionResult( Error( d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ) ); +#endif const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return EncryptionResult( d->ctx, Error(d->lasterr) ); } Error Context::encryptSymmetrically( const Data & plainText, Data & cipherText ) { d->lastop = Private::Encrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); return Error( d->lasterr = gpgme_op_encrypt( d->ctx, 0, (gpgme_encrypt_flags_t)0, pdp ? pdp->data : 0, cdp ? cdp->data : 0 ) ); } Error Context::startEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::Encrypt; +#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO + if ( flags & NoEncryptTo ) + return Error( d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ); +#endif const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_start( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return Error( d->lasterr ); } EncryptionResult Context::encryptionResult() const { if ( d->lastop & Private::Encrypt ) return EncryptionResult( d->ctx, Error(d->lasterr) ); else return EncryptionResult(); } std::pair Context::signAndEncrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::SignAndEncrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_sign( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return std::make_pair( SigningResult( d->ctx, Error(d->lasterr) ), EncryptionResult( d->ctx, Error(d->lasterr) ) ); } Error Context::startCombinedSigningAndEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::SignAndEncrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_sign_start( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return Error( d->lasterr ); } Error Context::cancelPendingOperation() { #ifdef HAVE_GPGME_CANCEL_ASYNC return Error( gpgme_cancel_async( d->ctx ) ); #else return Error( gpgme_cancel( d->ctx ) ); #endif } bool Context::poll() { gpgme_error_t e = GPG_ERR_NO_ERROR; const bool finished = gpgme_wait( d->ctx, &e, 0 ); if ( finished ) d->lasterr = e; return finished; } Error Context::wait() { gpgme_error_t e = GPG_ERR_NO_ERROR; gpgme_wait( d->ctx, &e, 1 ); return Error( d->lasterr = e ); } Error Context::lastError() const { return Error( d->lasterr ); } std::ostream & operator<<( std::ostream & os, Protocol proto ) { os << "GpgME::Protocol("; switch ( proto ) { case OpenPGP: os << "OpenPGP"; break; case CMS: os << "CMS"; break; default: case UnknownProtocol: os << "UnknownProtocol"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Engine eng ) { os << "GpgME::Engine("; switch ( eng ) { case GpgEngine: os << "GpgEngine"; break; case GpgSMEngine: os << "GpgSMEngine"; break; case GpgConfEngine: os << "GpgConfEngine"; break; + case AssuanEngine: + os << "AssuanEngine"; default: case UnknownEngine: os << "UnknownEngine"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::CertificateInclusion incl ) { os << "GpgME::Context::CertificateInclusion(" << static_cast( incl ); switch ( incl ) { case Context::DefaultCertificates: os << "(DefaultCertificates)"; break; case Context::AllCertificatesExceptRoot: os << "(AllCertificatesExceptRoot)"; break; case Context::AllCertificates: os << "(AllCertificates)"; break; case Context::NoCertificates: os << "(NoCertificates)"; break; case Context::OnlySenderCertificate: os << "(OnlySenderCertificate)"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, KeyListMode mode ) { os << "GpgME::KeyListMode("; #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0) CHECK( Local ); CHECK( Extern ); CHECK( Signatures ); CHECK( Validate ); + CHECK( Ephemeral ); #undef CHECK return os << ')'; } std::ostream & operator<<( std::ostream & os, SignatureMode mode ) { os << "GpgME::SignatureMode("; switch ( mode ) { #define CHECK( x ) case x: os << #x; break CHECK( NormalSignatureMode ); CHECK( Detached ); CHECK( Clearsigned ); #undef CHECK default: os << "???" "(" << static_cast( mode ) << ')'; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::EncryptionFlags flags ) { os << "GpgME::Context::EncryptionFlags("; #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) CHECK( AlwaysTrust ); #undef CHECK return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::AuditLogFlags flags ) { os << "GpgME::Context::AuditLogFlags("; #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) CHECK( HtmlAuditLog ); CHECK( AuditLogWithHelp ); #undef CHECK return os << ')'; } } // namespace GpgME GpgME::Error GpgME::setDefaultLocale( int cat, const char * val ) { return Error( gpgme_set_locale( 0, cat, val ) ); } GpgME::EngineInfo GpgME::engineInfo( GpgME::Protocol proto ) { gpgme_engine_info_t ei = 0; if ( gpgme_get_engine_info( &ei ) ) return EngineInfo(); const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; for ( gpgme_engine_info_t i = ei ; i ; i = i->next ) if ( i->protocol == p ) return EngineInfo( i ); return EngineInfo(); } GpgME::Error GpgME::checkEngine( GpgME::Protocol proto ) { const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; return Error( gpgme_engine_check_version( p ) ); } static gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast( 255 ); static gpgme_protocol_t engine2protocol( const GpgME::Engine engine ) { switch ( engine ) { case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP; case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS; case GpgME::GpgConfEngine: #ifdef HAVE_GPGME_PROTOCOL_GPGCONF return GPGME_PROTOCOL_GPGCONF; +#else + break; +#endif + case GpgME::AssuanEngine: +#ifdef HAVE_GPGME_ASSUAN_ENGINE + return GPGME_PROTOCOL_ASSUAN; +#else + break; #endif case GpgME::UnknownEngine: ; } return UNKNOWN_PROTOCOL; } GpgME::EngineInfo GpgME::engineInfo( GpgME::Engine engine ) { gpgme_engine_info_t ei = 0; if ( gpgme_get_engine_info( &ei ) ) return EngineInfo(); const gpgme_protocol_t p = engine2protocol( engine ); for ( gpgme_engine_info_t i = ei ; i ; i = i->next ) if ( i->protocol == p ) return EngineInfo( i ); return EngineInfo(); } GpgME::Error GpgME::checkEngine( GpgME::Engine engine ) { const gpgme_protocol_t p = engine2protocol( engine ); return Error( gpgme_engine_check_version( p ) ); } static const unsigned long supported_features = 0 | GpgME::ValidatingKeylistModeFeature | GpgME::CancelOperationFeature | GpgME::WrongKeyUsageFeature #ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT | GpgME::DefaultCertificateInclusionFeature #endif #ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO | GpgME::GetSetEngineInfoFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET | GpgME::ClearAddGetSignatureNotationsFeature #endif #ifdef HAVE_GPGME_DATA_SET_FILE_NAME | GpgME::SetDataFileNameFeeature #endif #ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS | GpgME::SignatureNotationsKeylistModeFeature #endif #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS | GpgME::KeySignatureNotationsFeature #endif #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED | GpgME::KeyIsQualifiedFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL | GpgME::SignatureNotationsCriticalFlagFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T | GpgME::SignatureNotationsFlagsFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE | GpgME::SignatureNotationsHumanReadableFlagFeature #endif #ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED | GpgME::SubkeyIsQualifiedFeature #endif #ifdef HAVE_GPGME_ENGINE_INFO_T_HOME_DIR | GpgME::EngineInfoHomeDirFeature #endif #ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME | GpgME::DecryptionResultFileNameFeature #endif #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS | GpgME::DecryptionResultRecipientsFeature #endif #ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME | GpgME::VerificationResultFileNameFeature #endif #ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS | GpgME::SignaturePkaFieldsFeature #endif #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS | GpgME::SignatureAlgorithmFieldsFeature #endif #ifdef HAVE_GPGME_GET_FDPTR | GpgME::FdPointerFeature #endif #ifdef HAVE_GPGME_OP_GETAUDITLOG | GpgME::AuditLogFeature #endif #ifdef HAVE_GPGME_PROTOCOL_GPGCONF | GpgME::GpgConfEngineFeature #endif #ifdef HAVE_GPGME_CANCEL_ASYNC | GpgME::CancelOperationAsyncFeature +#endif +#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO + | GpgME::NoEncryptToEncryptionFlagFeature +#endif +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + | GpgME::CardKeyFeature +#endif +#ifdef HAVE_GPGME_ASSUAN_ENGINE + | GpgME::AssuanEngineFeature +#endif +#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL + | GpgME::EphemeralKeylistModeFeature #endif ; bool GpgME::hasFeature( unsigned long features ) { return features == ( features & supported_features ); } diff --git a/gpgme++/context.h b/gpgme++/context.h index cc1956216..461bfefbd 100644 --- a/gpgme++/context.h +++ b/gpgme++/context.h @@ -1,306 +1,306 @@ /* 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 #include #include // for Signature::Notation #include #include #include #include namespace GpgME { class Key; class Data; class TrustItem; class ProgressProvider; class PassphraseProvider; class EventLoopInteractor; class EditInteractor; class KeyListResult; class KeyGenerationResult; class ImportResult; class DecryptionResult; class VerificationResult; class SigningResult; class EncryptionResult; class EngineInfo; class GPGMEPP_EXPORT Context { explicit Context( gpgme_ctx_t ); public: //using GpgME::Protocol; // // Creation and destruction: // static Context * createForProtocol( Protocol proto ); virtual ~Context(); // // Context Attributes // Protocol protocol() const; void setArmor( bool useArmor ); bool armor() const; void setTextMode( bool useTextMode ); bool textMode() const; enum CertificateInclusion { DefaultCertificates = -256, AllCertificatesExceptRoot = -2, AllCertificates = -1, NoCertificates = 0, OnlySenderCertificate = 1 }; void setIncludeCertificates( int which ); int includeCertificates() const; //using GpgME::KeyListMode; void setKeyListMode( unsigned int keyListMode ); void addKeyListMode( unsigned int keyListMode ); unsigned int keyListMode() const; void setPassphraseProvider( PassphraseProvider * provider ); PassphraseProvider * passphraseProvider() const; void setProgressProvider( ProgressProvider * provider ); ProgressProvider * progressProvider() const; void setManagedByEventLoopInteractor( bool managed ); bool managedByEventLoopInteractor() const; GpgME::Error setLocale( int category, const char * value ); EngineInfo engineInfo() const; GpgME::Error setEngineFileName( const char * filename ); GpgME::Error setEngineHomeDirectory( const char * filename ); private: friend class ::GpgME::EventLoopInteractor; void installIOCallbacks( gpgme_io_cbs * iocbs ); void uninstallIOCallbacks(); public: // // // Key Management // // // // Key Listing // GpgME::Error startKeyListing( const char * pattern=0, bool secretOnly=false ); GpgME::Error startKeyListing( const char * patterns[], bool secretOnly=false ); Key nextKey( GpgME::Error & e ); KeyListResult endKeyListing(); KeyListResult keyListResult() const; Key key( const char * fingerprint, GpgME::Error & e, bool secret=false ); // // Key Generation // KeyGenerationResult generateKey( const char * parameters, Data & pubKey ); GpgME::Error startKeyGeneration( const char * parameters, Data & pubkey ); KeyGenerationResult keyGenerationResult() const; // // Key Export // GpgME::Error exportPublicKeys( const char * pattern, Data & keyData ); GpgME::Error exportPublicKeys( const char * pattern[], Data & keyData ); GpgME::Error startPublicKeyExport( const char * pattern, Data & keyData ); GpgME::Error startPublicKeyExport( const char * pattern[], Data & keyData ); // // Key Import // ImportResult importKeys( const Data & data ); GpgME::Error startKeyImport( const Data & data ); ImportResult importResult() const; // // Key Deletion // GpgME::Error deleteKey( const Key & key, bool allowSecretKeyDeletion=false ); GpgME::Error startKeyDeletion( const Key & key, bool allowSecretKeyDeletion=false ); // // Key Editing // GpgME::Error edit( const Key & key, std::auto_ptr function, Data & out ); GpgME::Error startEditing( const Key & key, std::auto_ptr function, Data & out ); EditInteractor * lastEditInteractor() const; // // SmartCard Editing // GpgME::Error cardEdit( const Key & key, std::auto_ptr function, Data & out ); GpgME::Error startCardEditing( const Key & key, std::auto_ptr function, Data & out ); EditInteractor * lastCardEditInteractor() const; // // Trust Item Management // GpgME::Error startTrustItemListing( const char * pattern, int maxLevel ); TrustItem nextTrustItem( GpgME::Error & e ); GpgME::Error endTrustItemListing(); // // // Crypto Operations // // // // Decryption // DecryptionResult decrypt( const Data & cipherText, Data & plainText ); GpgME::Error startDecryption( const Data & cipherText, Data & plainText ); DecryptionResult decryptionResult() const; // // Signature Verification // VerificationResult verifyDetachedSignature( const Data & signature, const Data & signedText ); VerificationResult verifyOpaqueSignature( const Data & signedData, Data & plainText ); GpgME::Error startDetachedSignatureVerification( const Data & signature, const Data & signedText ); GpgME::Error startOpaqueSignatureVerification( const Data & signedData, Data & plainText ); VerificationResult verificationResult() const; // // Combined Decryption and Signature Verification // std::pair 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 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 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 }; + enum EncryptionFlags { None=0, AlwaysTrust=1, NoEncryptTo=2 }; EncryptionResult encrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); GpgME::Error encryptSymmetrically( const Data & plainText, Data & cipherText ); GpgME::Error startEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); EncryptionResult encryptionResult() const; // // Combined Signing and Encryption // std::pair signAndEncrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); GpgME::Error startCombinedSigningAndEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); // use encryptionResult() and signingResult() to retrieve the result objects... // // // Audit Log // // enum AuditLogFlags { HtmlAuditLog = 1, AuditLogWithHelp = 128 }; GpgME::Error startGetAuditLog( Data & output, unsigned int flags=0 ); GpgME::Error getAuditLog( Data & output, unsigned int flags=0 ); // // // Run Control // // bool poll(); GpgME::Error wait(); GpgME::Error lastError() const; GpgME::Error cancelPendingOperation(); class Private; const Private * impl() const { return d; } Private * impl() { return d; } private: Private * 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/gpgme++/global.h b/gpgme++/global.h index f15679183..22d0d35ca 100644 --- a/gpgme++/global.h +++ b/gpgme++/global.h @@ -1,127 +1,128 @@ /* 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 #include #include namespace GpgME { class Error; class EngineInfo; class Context; } struct _GIOChannel; typedef struct _GIOChannel GIOChannel; class QIODevice; namespace GpgME { enum Protocol { OpenPGP, CMS, UnknownProtocol }; - enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine }; + enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine }; enum KeyListMode { Local = 0x1, Extern = 0x2, Signatures = 0x4, SignatureNotations = 0x8, - Validate = 0x10 + Validate = 0x10, + Ephemeral = 0x20 }; enum SignatureMode { NormalSignatureMode, Detached, Clearsigned }; GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Protocol proto ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Engine eng ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, KeyListMode mode ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, SignatureMode mode ); GPGMEPP_EXPORT Error setDefaultLocale( int category, const char * value ); GPGMEPP_EXPORT Context * wait( Error & e, bool hang=true ); typedef void (*IdleFunction)(void); GPGMEPP_EXPORT IdleFunction registerIdleFunction( IdleFunction idleFunction ); typedef void (*IOCallback)( void * data, int fd ); GPGMEPP_EXPORT EngineInfo engineInfo( Protocol proto ); GPGMEPP_EXPORT EngineInfo engineInfo( Engine engine ); GPGMEPP_EXPORT Error checkEngine( Protocol proto ); GPGMEPP_EXPORT Error checkEngine( Engine engine ); GPGMEPP_EXPORT GIOChannel * getGIOChannel( int fd ); GPGMEPP_EXPORT QIODevice * getQIODevice( int fd ); enum Feature { ValidatingKeylistModeFeature = 0x00000001, CancelOperationFeature = 0x00000002, WrongKeyUsageFeature = 0x00000004, DefaultCertificateInclusionFeature = 0x00000008, GetSetEngineInfoFeature = 0x00000010, EngineInfoHomeDirFeature = 0x00000020, - // reserved - // reserved + NoEncryptToEncryptionFlagFeature = 0x00000040, + EphemeralKeylistModeFeature = 0x00000080, SetDataFileNameFeeature = 0x00000100, VerificationResultFileNameFeature = 0x00000200, DecryptionResultFileNameFeature = 0x00000400, DecryptionResultRecipientsFeature = 0x00000800, AuditLogFeature = 0x00001000, GpgConfEngineFeature = 0x00002000, CancelOperationAsyncFeature = 0x00004000, - // reserved + AssuanEngineFeature = 0x00008000, ClearAddGetSignatureNotationsFeature = 0x00010000, SignatureNotationsKeylistModeFeature = 0x00020000, KeySignatureNotationsFeature = 0x00040000, SignatureNotationsFlagsFeature = 0x00080000, SignatureNotationsCriticalFlagFeature = 0x00100000, SignatureNotationsHumanReadableFlagFeature = 0x00200000, - // reserved + CardKeyFeature = 0x00400000, // reserved KeyIsQualifiedFeature = 0x01000200, SubkeyIsQualifiedFeature = 0x02000000, SignaturePkaFieldsFeature = 0x04000000, SignatureAlgorithmFieldsFeature = 0x08000000, FdPointerFeature = 0x10000000, // reserved // reserved // unusable (max value) FeatureMaxValue = 0x80000000 }; GPGMEPP_EXPORT bool hasFeature( unsigned long feature ); } // namespace GpgME #endif // __GPGMEPP_GLOBAL_H__ diff --git a/gpgme++/key.cpp b/gpgme++/key.cpp index ab6f7c611..1e934a697 100644 --- a/gpgme++/key.cpp +++ b/gpgme++/key.cpp @@ -1,662 +1,678 @@ /* 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 #include #include "util.h" #include #include 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 Key::userIDs() const { if ( !key ) return std::vector(); std::vector 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 Key::subkeys() const { if ( !key ) return std::vector(); std::vector 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 key && key->can_sign; } bool Key::canCertify() const { return key && key->can_certify; } bool Key::canAuthenticate() const { return key && key->can_authenticate; } bool Key::isQualified() const { #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED return key && key->is_qualified; #else return false; #endif } const char * Key::issuerSerial() const { return key ? key->issuer_serial : 0 ; } const char * Key::issuerName() const { return key ? key->issuer_name : 0 ; } const char * Key::chainID() const { return key ? key->chain_id : 0 ; } const char * Key::keyID() const { return key && key->subkeys ? key->subkeys->keyid : 0 ; } const char * Key::shortKeyID() const { if ( !key || !key->subkeys || !key->subkeys->keyid ) return 0; const int len = strlen( key->subkeys->keyid ); if ( len > 8 ) return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation) else return key->subkeys->keyid ; } const char * Key::primaryFingerprint() const { return key && key->subkeys ? key->subkeys->fpr : 0 ; } unsigned int Key::keyListMode() const { return key ? convert_from_gpgme_keylist_mode_t( key->keylist_mode ) : 0 ; } const Key & Key::mergeWith( const Key & other ) { // ### incomplete. Just merges has* and can*, nothing else atm // ### detach also missing if ( !this->primaryFingerprint() || !other.primaryFingerprint() || strcasecmp( this->primaryFingerprint(), other.primaryFingerprint() ) != 0 ) return *this; // only merge the Key object which describe the same key const gpgme_key_t me = impl(); const gpgme_key_t him = other.impl(); if ( !me || !him ) return *this; me->revoked |= him->revoked; me->expired |= him->expired; me->disabled |= him->disabled; me->invalid |= him->invalid; me->can_encrypt |= him->can_encrypt; me->can_sign |= him->can_sign; me->can_certify |= him->can_certify; me->secret |= him->secret; me->can_authenticate |= him->can_authenticate; #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED me->is_qualified |= him->is_qualified; #endif me->keylist_mode |= him->keylist_mode; return *this; } // // // class Subkey // // gpgme_sub_key_t find_subkey( const shared_gpgme_key_t & key, unsigned int idx ) { if ( key ) for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx ) if ( idx == 0 ) return s; return 0; } gpgme_sub_key_t verify_subkey( const shared_gpgme_key_t & key, gpgme_sub_key_t subkey ) { if ( key ) for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next ) if ( s == subkey ) return subkey; return 0; } Subkey::Subkey() : key(), subkey( 0 ) {} Subkey::Subkey( const shared_gpgme_key_t & k, unsigned int idx ) : key( k ), subkey( find_subkey( k, idx ) ) { } Subkey::Subkey( const shared_gpgme_key_t & k, gpgme_sub_key_t sk ) : key( k ), subkey( verify_subkey( k, sk ) ) { } Key Subkey::parent() const { return Key( key ); } const char * Subkey::keyID() const { return subkey ? subkey->keyid : 0 ; } const char * Subkey::fingerprint() const { return subkey ? subkey->fpr : 0 ; } unsigned int Subkey::publicKeyAlgorithm() const { return subkey ? subkey->pubkey_algo : 0 ; } const char * Subkey::publicKeyAlgorithmAsString() const { return gpgme_pubkey_algo_name( subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0 ); } bool Subkey::canEncrypt() const { return subkey && subkey->can_encrypt; } bool Subkey::canSign() const { return subkey && subkey->can_sign; } bool Subkey::canCertify() const { return subkey && subkey->can_certify; } bool Subkey::canAuthenticate() const { return subkey && subkey->can_authenticate; } bool Subkey::isQualified() const { #ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED return subkey && subkey->is_qualified; #else return false; #endif } + bool Subkey::isCardKey() const { +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + return subkey && subkey->is_cardkey; +#else + return false; +#endif + } + + const char * Subkey::cardSerialNumber() const { +#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY + return subkey ? subkey->card_number : 0 ; +#else + return 0; +#endif + } + bool Subkey::isSecret() const { return subkey && subkey->secret; } unsigned int Subkey::length() const { return subkey ? subkey->length : 0 ; } time_t Subkey::creationTime() const { return static_cast( subkey ? subkey->timestamp : 0 ); } time_t Subkey::expirationTime() const { return static_cast( 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::signatures() const { if ( !uid ) return std::vector(); std::vector v; v.reserve( numSignatures() ); for ( gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next ) v.push_back( Signature( key, uid, sig ) ); return v; } const char * UserID::id() const { return uid ? uid->uid : 0 ; } const char * UserID::name() const { return uid ? uid->name : 0 ; } const char * UserID::email() const { return uid ? uid->email : 0 ; } const char * UserID::comment() const { return uid ? uid->comment : 0 ; } UserID::Validity UserID::validity() const { if ( !uid ) return Unknown; switch ( uid->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return Unknown; case GPGME_VALIDITY_UNDEFINED: return Undefined; case GPGME_VALIDITY_NEVER: return Never; case GPGME_VALIDITY_MARGINAL: return Marginal; case GPGME_VALIDITY_FULL: return Full; case GPGME_VALIDITY_ULTIMATE: return Ultimate; } } char UserID::validityAsString() const { if ( !uid ) return '?'; switch ( uid->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return '?'; case GPGME_VALIDITY_UNDEFINED: return 'q'; case GPGME_VALIDITY_NEVER: return 'n'; case GPGME_VALIDITY_MARGINAL: return 'm'; case GPGME_VALIDITY_FULL: return 'f'; case GPGME_VALIDITY_ULTIMATE: return 'u'; } } bool UserID::isRevoked() const { return uid && uid->revoked; } bool UserID::isInvalid() const { return uid && uid->invalid; } // // // class Signature // // gpgme_key_sig_t find_signature( gpgme_user_id_t uid, unsigned int idx ) { if ( uid ) for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx ) if ( idx == 0 ) return s; return 0; } gpgme_key_sig_t verify_signature( gpgme_user_id_t uid, gpgme_key_sig_t sig ) { if ( uid ) for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next ) if ( s == sig ) return sig; return 0; } UserID::Signature::Signature() : key(), uid( 0 ), sig( 0 ) {} UserID::Signature::Signature( const shared_gpgme_key_t & k, gpgme_user_id_t u, unsigned int idx ) : key( k ), uid( verify_uid( k, u ) ), sig( find_signature( uid, idx ) ) { } UserID::Signature::Signature( const shared_gpgme_key_t & k, gpgme_user_id_t u, gpgme_key_sig_t s ) : key( k ), uid( verify_uid( k, u ) ), sig( verify_signature( uid, s ) ) { } UserID UserID::Signature::parent() const { return UserID( key, uid ); } const char * UserID::Signature::signerKeyID() const { return sig ? sig->keyid : 0 ; } const char * UserID::Signature::algorithmAsString() const { return gpgme_pubkey_algo_name( sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0 ); } unsigned int UserID::Signature::algorithm() const { return sig ? sig->pubkey_algo : 0 ; } time_t UserID::Signature::creationTime() const { return static_cast( sig ? sig->timestamp : 0 ); } time_t UserID::Signature::expirationTime() const { return static_cast( sig ? sig->expires : 0 ); } bool UserID::Signature::neverExpires() const { return expirationTime() == time_t(0); } bool UserID::Signature::isRevokation() const { return sig && sig->revoked; } bool UserID::Signature::isInvalid() const { return sig && sig->invalid; } bool UserID::Signature::isExpired() const { return sig && sig->expired; } bool UserID::Signature::isExportable() const { return sig && sig->exportable; } const char * UserID::Signature::signerUserID() const { return sig ? sig->uid : 0 ; } const char * UserID::Signature::signerName() const { return sig ? sig->name : 0 ; } const char * UserID::Signature::signerEmail() const { return sig ? sig->email : 0 ; } const char * UserID::Signature::signerComment() const { return sig ? sig->comment : 0 ; } unsigned int UserID::Signature::certClass() const { return sig ? sig->sig_class : 0 ; } UserID::Signature::Status UserID::Signature::status() const { if ( !sig ) return GeneralError; switch ( gpgme_err_code(sig->status) ) { case GPG_ERR_NO_ERROR: return NoError; case GPG_ERR_SIG_EXPIRED: return SigExpired; case GPG_ERR_KEY_EXPIRED: return KeyExpired; case GPG_ERR_BAD_SIGNATURE: return BadSignature; case GPG_ERR_NO_PUBKEY: return NoPublicKey; default: case GPG_ERR_GENERAL: return GeneralError; } } std::string UserID::Signature::statusAsString() const { if ( !sig ) return std::string(); char buf[ 1024 ]; gpgme_strerror_r( sig->status, buf, sizeof buf ); buf[ sizeof buf - 1 ] = '\0'; return std::string( buf ); } GpgME::Notation UserID::Signature::notation( unsigned int idx ) const { if ( !sig ) return GpgME::Notation(); #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) if ( idx-- == 0 ) return GpgME::Notation( nota ); #endif return GpgME::Notation(); } unsigned int UserID::Signature::numNotations() const { if ( !sig ) return 0; unsigned int count = 0; #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) ++count; // others are policy URLs... #endif return count; } std::vector UserID::Signature::notations() const { if ( !sig ) return std::vector(); std::vector v; #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS v.reserve( numNotations() ); for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) v.push_back( GpgME::Notation( nota ) ); #endif return v; } const char * UserID::Signature::policyURL() const { #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS if ( !sig ) return 0; for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( !nota->name ) return nota->value; #endif return 0; } } // namespace GpgME diff --git a/gpgme++/key.h b/gpgme++/key.h index 9bf70a3ec..261d55a32 100644 --- a/gpgme++/key.h +++ b/gpgme++/key.h @@ -1,310 +1,313 @@ /* 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 #include #include #include #include #include #include #include #include namespace GpgME { class Context; class Subkey; class UserID; typedef boost::shared_ptr< boost::remove_pointer::type > shared_gpgme_key_t; // // class Key // class GPGMEPP_EXPORT Key { friend class ::GpgME::Context; struct Null {}; public: Key(); /* implicit */ Key( const Null & ); Key( const shared_gpgme_key_t & key ); Key( gpgme_key_t key, bool acquireRef ); static 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 userIDs() const; std::vector subkeys() const; bool isRevoked() const; bool isExpired() const; bool isDisabled() const; bool isInvalid() const; bool canEncrypt() const; bool canSign() const; bool canCertify() const; bool canAuthenticate() const; bool isQualified() const; bool hasSecret() const; GPGMEPP_DEPRECATED bool isSecret() const { return hasSecret(); } /*! @return true if this is a X.509 root certificate (currently equivalent to something like strcmp( chainID(), subkey(0).fingerprint() ) == 0 ) */ bool isRoot() const; enum OwnerTrust { Unknown=0, Undefined=1, Never=2, Marginal=3, Full=4, Ultimate=5 }; OwnerTrust ownerTrust() const; char ownerTrustAsString() const; Protocol protocol() const; const char * protocolAsString() const; const char * issuerSerial() const; const char * issuerName() const; const char * chainID() const; const char * keyID() const; const char * shortKeyID() const; const char * primaryFingerprint() const; unsigned int keyListMode() const; private: gpgme_key_t impl() const { return key.get(); } shared_gpgme_key_t key; }; // // class Subkey // class GPGMEPP_EXPORT Subkey { public: Subkey(); Subkey( const shared_gpgme_key_t & key, gpgme_sub_key_t subkey ); Subkey( const shared_gpgme_key_t & key, unsigned int idx ); const Subkey & operator=( Subkey other ) { swap( other ); return *this; } void swap( Subkey & other ) { using std::swap; swap( this->key, other.key ); swap( this->subkey, other.subkey ); } bool isNull() const { return !key || !subkey; } Key parent() const; const char * keyID() const; const char * fingerprint() const; time_t creationTime() const; time_t expirationTime() const; bool neverExpires() const; bool isRevoked() const; bool isExpired() const; bool isInvalid() const; bool isDisabled() const; bool canEncrypt() const; bool canSign() const; bool canCertify() const; bool canAuthenticate() const; bool isQualified() const; + bool isCardKey() const; bool isSecret() const; unsigned int publicKeyAlgorithm() const; const char * publicKeyAlgorithmAsString() const; unsigned int length() const; + const char * cardSerialNumber() const; + private: shared_gpgme_key_t key; gpgme_sub_key_t subkey; }; // // class UserID // class GPGMEPP_EXPORT UserID { public: class Signature; UserID(); UserID( const shared_gpgme_key_t & key, gpgme_user_id_t uid ); UserID( const shared_gpgme_key_t & key, unsigned int idx ); const UserID & operator=( UserID other ) { swap( other ); return *this; } void swap( UserID & other ) { using std::swap; swap( this->key, other.key ); swap( this->uid, other.uid ); } bool isNull() const { return !key || !uid; } Key parent() const; unsigned int numSignatures() const; Signature signature( unsigned int index ) const; std::vector signatures() const; const char * id() const; const char * name() const; const char * email() const; const char * comment() const; enum Validity { Unknown=0, Undefined=1, Never=2, Marginal=3, Full=4, Ultimate=5 }; Validity validity() const; char validityAsString() const; bool isRevoked() const; bool isInvalid() const; private: shared_gpgme_key_t key; gpgme_user_id_t uid; }; // // class UserID::Signature // class GPGMEPP_EXPORT UserID::Signature { public: typedef GPGMEPP_DEPRECATED GpgME::Notation Notation; Signature(); Signature( const shared_gpgme_key_t & key, gpgme_user_id_t uid, gpgme_key_sig_t sig ); Signature( const shared_gpgme_key_t & key, gpgme_user_id_t uid, unsigned int idx ); const Signature & operator=( Signature other ) { swap( other ); return *this; } void swap( Signature & other ) { using std::swap; swap( this->key, other.key ); swap( this->uid, other.uid ); swap( this->sig, other.sig ); } bool isNull() const { return !sig || !uid || !key ; } UserID parent() const; const char * signerKeyID() const; const char * algorithmAsString() const; unsigned int algorithm() const; time_t creationTime() const; time_t expirationTime() const; bool neverExpires() const; bool isRevokation() const; bool isInvalid() const; bool isExpired() const; bool isExportable() const; const char * signerUserID() const; const char * signerName() const; const char * signerEmail() const; const char * signerComment() const; unsigned int certClass() const; enum Status { NoError = 0, SigExpired, KeyExpired, BadSignature, NoPublicKey, GeneralError }; Status status() const; std::string statusAsString() const; const char * policyURL() const; unsigned int numNotations() const; GpgME::Notation notation( unsigned int idx ) const; std::vector notations() const; private: shared_gpgme_key_t key; gpgme_user_id_t uid; gpgme_key_sig_t sig; }; } // namespace GpgME GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Key ) GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Subkey ) GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( UserID ) GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( UserID::Signature ) #endif // __GPGMEPP_KEY_H__ diff --git a/gpgme++/util.h b/gpgme++/util.h index 71739f8ce..29c01e4f0 100644 --- a/gpgme++/util.h +++ b/gpgme++/util.h @@ -1,117 +1,130 @@ /* 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 #include #include #ifndef NDEBUG #include #endif static inline const char * protect( const char * s ) { return s ? s : "" ; } static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t( unsigned int oldmode, unsigned int newmodes ) { if ( newmodes & GpgME::Local ) oldmode |= GPGME_KEYLIST_MODE_LOCAL; if ( newmodes & GpgME::Extern ) oldmode |= GPGME_KEYLIST_MODE_EXTERN; if ( newmodes & GpgME::Signatures ) oldmode |= GPGME_KEYLIST_MODE_SIGS; if ( newmodes & GpgME::SignatureNotations ) { #ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS; #elif !defined(NDEBUG) std::cerr << "GpgME: ignoring SignatureNotations keylist flag (gpgme too old)." << std::endl; +#endif + } + if ( newmodes & GpgME::Ephemeral ) { +#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL + oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL; +#elif !defined(NDEBUG) + std::cerr << "GpgME: ignoring Ephemeral keylist flag (gpgme too old)." << std::endl; #endif } if ( newmodes & GpgME::Validate ) oldmode |= GPGME_KEYLIST_MODE_VALIDATE; #ifndef NDEBUG if ( newmodes & ~(GpgME::Local|GpgME::Extern|GpgME::Signatures|GpgME::SignatureNotations|GpgME::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( oldmode ); } static inline unsigned int convert_from_gpgme_keylist_mode_t( unsigned int mode ) { unsigned int result = 0; if ( mode & GPGME_KEYLIST_MODE_LOCAL ) result |= GpgME::Local; if ( mode & GPGME_KEYLIST_MODE_EXTERN ) result |= GpgME::Extern; if ( mode & GPGME_KEYLIST_MODE_SIGS ) result |= GpgME::Signatures; #ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS if ( mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS ) result |= GpgME::SignatureNotations; +#endif +#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL + if ( mode & GPGME_KEYLIST_MODE_EPHEMERAL ) result |= GpgME::Ephemeral; #endif if ( mode & GPGME_KEYLIST_MODE_VALIDATE ) result |= GpgME::Validate; #ifndef NDEBUG if ( mode & ~(GPGME_KEYLIST_MODE_LOCAL| GPGME_KEYLIST_MODE_EXTERN| #ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS GPGME_KEYLIST_MODE_SIG_NOTATIONS| +#endif +#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL + GPGME_KEYLIST_MODE_EPHEMERAL| #endif GPGME_KEYLIST_MODE_VALIDATE| GPGME_KEYLIST_MODE_SIGS) ) std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl; #endif // NDEBUG return result; } static inline GpgME::Notation::Flags convert_from_gpgme_sig_notation_flags_t( unsigned int flags ) { #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T unsigned int result = 0; #ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE if ( flags & GPGME_SIG_NOTATION_HUMAN_READABLE ) result |= GpgME::Notation::HumanReadable ; #endif #ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL if ( flags & GPGME_SIG_NOTATION_CRITICAL ) result |= GpgME::Notation::Critical ; #endif return static_cast( result ); #else return GpgME::Notation::NoFlags; #endif } #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t( unsigned int oldflags, unsigned int newflags ) { unsigned int result = oldflags; if ( newflags & GpgME::Notation::HumanReadable ) { #ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE result |= GPGME_SIG_NOTATION_HUMAN_READABLE; #elif !defined(NDEBUG) std::cerr << "GpgME::Context: ignoring HumanReadable signature notation flag (gpgme too old)" << std::endl; #endif } if ( newflags & GpgME::Notation::Critical ) { #ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL result |= GPGME_SIG_NOTATION_CRITICAL; #elif !defined(NDEBUG) std::cerr << "GpgME::Context: ignoring Critical signature notation flag (gpgme too old)" << std::endl; #endif } return static_cast( result ); } #endif #endif // __GPGMEPP_UTIL_H__