diff --git a/gpgme++/CMakeLists.txt b/gpgme++/CMakeLists.txt index 7f34547dc..fa09c86e1 100644 --- a/gpgme++/CMakeLists.txt +++ b/gpgme++/CMakeLists.txt @@ -1,139 +1,139 @@ 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.0.2 ) +set( _gpgmepp_version 2.1.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 ${INSTALL_TARGETS_DEFAULT_ARGS} ) 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 ${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 ${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 ${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 ${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++/context.cpp b/gpgme++/context.cpp index 91ceff3cf..66be27b53 100644 --- a/gpgme++/context.cpp +++ b/gpgme++/context.cpp @@ -1,947 +1,1055 @@ /* 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; return static_cast( result ); } EncryptionResult Context::encrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::Encrypt; 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; 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; + 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 ); +#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; #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 ; bool GpgME::hasFeature( unsigned long features ) { return features == ( features & supported_features ); } diff --git a/gpgme++/context.h b/gpgme++/context.h index f4a26511d..cc1956216 100644 --- a/gpgme++/context.h +++ b/gpgme++/context.h @@ -1,301 +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 }; 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++/decryptionresult.cpp b/gpgme++/decryptionresult.cpp index c4dc4bcc0..cbf0c05c1 100644 --- a/gpgme++/decryptionresult.cpp +++ b/gpgme++/decryptionresult.cpp @@ -1,212 +1,239 @@ /* 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 #include #include "result_p.h" +#include "util.h" #include #include #include #include #include +#include #include class GpgME::DecryptionResult::Private { public: explicit Private( const _gpgme_op_decrypt_result & r ) : res( r ) { if ( res.unsupported_algorithm ) res.unsupported_algorithm = strdup( res.unsupported_algorithm ); #ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME if ( res.file_name ) res.file_name = strdup( res.file_name ); #endif #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS //FIXME: copying gpgme_recipient_t objects invalidates the keyid member, //thus we use _keyid for now (internal API) for ( gpgme_recipient_t r = res.recipients ; r ; r = r->next ) recipients.push_back( *r ); res.recipients = 0; #endif } ~Private() { if ( res.unsupported_algorithm ) std::free( res.unsupported_algorithm ); res.unsupported_algorithm = 0; #ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME if ( res.file_name ) std::free( res.file_name ); res.file_name = 0; #endif } _gpgme_op_decrypt_result res; #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS std::vector<_gpgme_recipient> recipients; #endif }; GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, int error ) : GpgME::Result( error ), d() { init( ctx ); } GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, const Error & error ) : GpgME::Result( error ), d() { init( ctx ); } void GpgME::DecryptionResult::init( gpgme_ctx_t ctx ) { if ( !ctx ) return; gpgme_decrypt_result_t res = gpgme_op_decrypt_result( ctx ); if ( !res ) return; d.reset( new Private( *res ) ); } make_standard_stuff(DecryptionResult) const char * GpgME::DecryptionResult::unsupportedAlgorithm() const { return d ? d->res.unsupported_algorithm : 0 ; } bool GpgME::DecryptionResult::isWrongKeyUsage() const { return d && d->res.wrong_key_usage; } const char * GpgME::DecryptionResult::fileName() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME return d ? d->res.file_name : 0 ; #else return 0; #endif } unsigned int GpgME::DecryptionResult::numRecipients() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS return d ? d->recipients.size() : 0 ; #else return 0; #endif } GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient( unsigned int idx ) const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( d && idx < d->recipients.size() ) return Recipient( &d->recipients[idx] ); #endif return Recipient(); } namespace { struct make_recipient { GpgME::DecryptionResult::Recipient operator()( _gpgme_recipient & t ) { return GpgME::DecryptionResult::Recipient( &t ); } }; } std::vector GpgME::DecryptionResult::recipients() const { std::vector result; #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( d ) { result.reserve( d->recipients.size() ); std::transform( d->recipients.begin(), d->recipients.end(), std::back_inserter( result ), make_recipient() ); } #endif return result; } #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient { public: Private( gpgme_recipient_t reci ) : _gpgme_recipient( *reci ) {} }; #endif GpgME::DecryptionResult::Recipient::Recipient() : d() { } GpgME::DecryptionResult::Recipient::Recipient( gpgme_recipient_t r ) : d() { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( r ) d.reset( new Private( r ) ); #endif } bool GpgME::DecryptionResult::Recipient::isNull() const { return !d; } const char * GpgME::DecryptionResult::Recipient::keyID() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS //_keyid is internal API, but the public keyid is invalid after copying (see above) if ( d ) return d->_keyid; #endif return 0; } const char * GpgME::DecryptionResult::Recipient::shortKeyID() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS //_keyid is internal API, but the public keyid is invalid after copying (see above) if ( d ) return d->_keyid + 8; #endif return 0; } unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( d ) return d->pubkey_algo; #endif return 0; } const char * GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( d ) return gpgme_pubkey_algo_name( d->pubkey_algo ); #endif return 0; } GpgME::Error GpgME::DecryptionResult::Recipient::status() const { #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS if ( d ) return Error( d->status ); #endif return Error(); } + +std::ostream & GpgME::operator<<( std::ostream & os, const DecryptionResult & result ) { + os << "GpgME::DecryptionResult("; + if ( !result.isNull() ) { + os << "\n error: " << result.error() + << "\n fileName: " << protect( result.fileName() ) + << "\n unsupportedAlgorithm: " << protect( result.unsupportedAlgorithm() ) + << "\n isWrongKeyUsage: " << result.isWrongKeyUsage() + << "\n recipients:\n"; + const std::vector recipients = result.recipients(); + std::copy( recipients.begin(), recipients.end(), + std::ostream_iterator( 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/gpgme++/decryptionresult.h b/gpgme++/decryptionresult.h index 80bf91515..0dd2246c2 100644 --- a/gpgme++/decryptionresult.h +++ b/gpgme++/decryptionresult.h @@ -1,112 +1,118 @@ /* 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 #include #include #include #include +#include +#include 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 recipients() const; private: class Private; void init( gpgme_ctx_t ctx ); boost::shared_ptr d; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const DecryptionResult & result ); + class GPGMEPP_EXPORT DecryptionResult::Recipient { public: Recipient(); explicit Recipient( gpgme_recipient_t reci ); const Recipient & operator=( Recipient other ) { swap( other ); return *this; } void swap( Recipient & other ) { using std::swap; swap( this->d, other.d ); } bool isNull() const; const char * keyID() const; const char * shortKeyID() const; unsigned int publicKeyAlgorithm() const; const char * publicKeyAlgorithmAsString() const; Error status() const; private: class Private; boost::shared_ptr 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/gpgme++/encryptionresult.cpp b/gpgme++/encryptionresult.cpp index 236f6fe7f..1a302dd78 100644 --- a/gpgme++/encryptionresult.cpp +++ b/gpgme++/encryptionresult.cpp @@ -1,122 +1,148 @@ /* 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 #include #include "result_p.h" +#include "util.h" #include #include #include +#include +#include +#include #include 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::iterator it = invalid.begin() ; it != invalid.end() ; ++it ) { std::free( (*it)->fpr ); delete *it; *it = 0; } } std::vector 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::EncryptionResult::invalidEncryptionKeys() const { if ( !d ) return std::vector(); std::vector result; result.reserve( d->invalid.size() ); for ( unsigned int i = 0 ; i < d->invalid.size() ; ++i ) result.push_back( InvalidRecipient( d, i ) ); return result; } GpgME::InvalidRecipient::InvalidRecipient( const boost::shared_ptr & 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 ir = result.invalidEncryptionKeys(); + std::copy( ir.begin(), ir.end(), + std::ostream_iterator( 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/gpgme++/encryptionresult.h b/gpgme++/encryptionresult.h index 8426a2d9c..bb5a08bd2 100644 --- a/gpgme++/encryptionresult.h +++ b/gpgme++/encryptionresult.h @@ -1,101 +1,106 @@ /* 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 #include #include #include #include +#include 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 invalidEncryptionKeys() const; class Private; private: void init( gpgme_ctx_t ctx ); boost::shared_ptr d; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const EncryptionResult & result ); + class GPGMEPP_EXPORT InvalidRecipient { friend class ::GpgME::EncryptionResult; InvalidRecipient( const boost::shared_ptr & parent, unsigned int index ); public: InvalidRecipient(); const InvalidRecipient & operator=( InvalidRecipient other ) { swap( other ); return *this; } void swap( InvalidRecipient & other ) { using std::swap; swap( this->d, other.d ); } bool isNull() const; const char * fingerprint() const; Error reason() const; private: boost::shared_ptr 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/gpgme++/error.h b/gpgme++/error.h index 18be86011..b71e6406b 100644 --- a/gpgme++/error.h +++ b/gpgme++/error.h @@ -1,60 +1,63 @@ /* 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 #include #include +#include namespace GpgME { class GPGMEPP_EXPORT Error { public: explicit Error( unsigned int e=0 ) : 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; } private: struct __safe_bool_dummy__ { void nonnull() {} }; typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); public: operator unspecified_bool_type() const { return mErr && !isCanceled() ? &__safe_bool_dummy__::nonnull : 0 ; } 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/gpgme++/global.h b/gpgme++/global.h index 4129aced6..f15679183 100644 --- a/gpgme++/global.h +++ b/gpgme++/global.h @@ -1,121 +1,127 @@ /* 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 KeyListMode { Local = 0x1, Extern = 0x2, Signatures = 0x4, SignatureNotations = 0x8, Validate = 0x10 }; 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 SetDataFileNameFeeature = 0x00000100, VerificationResultFileNameFeature = 0x00000200, DecryptionResultFileNameFeature = 0x00000400, DecryptionResultRecipientsFeature = 0x00000800, AuditLogFeature = 0x00001000, GpgConfEngineFeature = 0x00002000, CancelOperationAsyncFeature = 0x00004000, // reserved ClearAddGetSignatureNotationsFeature = 0x00010000, SignatureNotationsKeylistModeFeature = 0x00020000, KeySignatureNotationsFeature = 0x00040000, SignatureNotationsFlagsFeature = 0x00080000, SignatureNotationsCriticalFlagFeature = 0x00100000, SignatureNotationsHumanReadableFlagFeature = 0x00200000, // reserved // 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++/notation.h b/gpgme++/notation.h index cd2f9fc79..3c008a7d1 100644 --- a/gpgme++/notation.h +++ b/gpgme++/notation.h @@ -1,75 +1,80 @@ /* 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 #include #include #include +#include + namespace GpgME { class GPGMEPP_EXPORT Notation { friend class ::GpgME::Signature; Notation( const boost::shared_ptr & parent, unsigned int sindex, unsigned int nindex ); public: Notation(); explicit Notation( gpgme_sig_notation_t nota ); const Notation & operator=( Notation other ) { swap( other ); return *this; } void swap( Notation & other ) { using std::swap; swap( this->d, other.d ); } bool isNull() const; const char * name() const; const char * value() const; enum Flags { NoFlags = 0, HumanReadable = 1, Critical = 2 }; Flags flags() const; bool isHumanReadable() const; bool isCritical() const; private: class Private; boost::shared_ptr d; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const Notation & nota ); + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Notation::Flags flags ); + } GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Notation ) #endif // __GPGMEPP_NOTATION_H__ diff --git a/gpgme++/signingresult.cpp b/gpgme++/signingresult.cpp index fdda3e4e8..0f7f1dd77 100644 --- a/gpgme++/signingresult.cpp +++ b/gpgme++/signingresult.cpp @@ -1,197 +1,239 @@ /* 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 #include #include "result_p.h" +#include "util.h" #include #include #include +#include +#include +#include #include 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::iterator it = created.begin() ; it != created.end() ; ++it ) { std::free( (*it)->fpr ); delete *it; *it = 0; } for ( std::vector::iterator it = invalid.begin() ; it != invalid.end() ; ++it ) { std::free( (*it)->fpr ); delete *it; *it = 0; } } std::vector created; std::vector 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::SigningResult::createdSignatures() const { if ( !d ) return std::vector(); std::vector 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::SigningResult::invalidSigningKeys() const { if ( !d ) return std::vector(); std::vector result; result.reserve( d->invalid.size() ); for ( unsigned int i = 0 ; i < d->invalid.size() ; ++i ) result.push_back( InvalidSigningKey( d, i ) ); return result; } GpgME::InvalidSigningKey::InvalidSigningKey( const boost::shared_ptr & parent, unsigned int i ) : d( parent ), idx( i ) { } GpgME::InvalidSigningKey::InvalidSigningKey() : d(), idx( 0 ) {} bool GpgME::InvalidSigningKey::isNull() const { return !d || idx >= d->invalid.size() ; } const char * GpgME::InvalidSigningKey::fingerprint() const { return isNull() ? 0 : d->invalid[idx]->fpr ; } GpgME::Error GpgME::InvalidSigningKey::reason() const { return Error( isNull() ? 0 : d->invalid[idx]->reason ); } GpgME::CreatedSignature::CreatedSignature( const boost::shared_ptr & 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( 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 cs = result.createdSignatures(); + std::copy( cs.begin(), cs.end(), + std::ostream_iterator( os, "\n" ) ); + os << " invalidSigningKeys:\n"; + const std::vector isk = result.invalidSigningKeys(); + std::copy( isk.begin(), isk.end(), + std::ostream_iterator( 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/gpgme++/signingresult.h b/gpgme++/signingresult.h index 31cb2175e..fa59e1f8e 100644 --- a/gpgme++/signingresult.h +++ b/gpgme++/signingresult.h @@ -1,145 +1,152 @@ /* 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 #include #include #include #include +#include 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 createdSignatures() const; InvalidSigningKey invalidSigningKey( unsigned int index ) const; std::vector invalidSigningKeys() const; class Private; private: void init( gpgme_ctx_t ctx ); boost::shared_ptr d; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const SigningResult & result ); + class GPGMEPP_EXPORT InvalidSigningKey { friend class ::GpgME::SigningResult; InvalidSigningKey( const boost::shared_ptr & parent, unsigned int index ); public: InvalidSigningKey(); const InvalidSigningKey & operator=( InvalidSigningKey other ) { swap( other ); return *this; } void swap( InvalidSigningKey & other ) { using std::swap; swap( this->d, other.d ); swap( this->idx, other.idx ); } bool isNull() const; const char * fingerprint() const; Error reason() const; private: boost::shared_ptr d; unsigned int idx; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const InvalidSigningKey & key ); + class GPGMEPP_EXPORT CreatedSignature { friend class ::GpgME::SigningResult; CreatedSignature( const boost::shared_ptr & parent, unsigned int index ); public: CreatedSignature(); const CreatedSignature & operator=( CreatedSignature other ) { swap( other ); return *this; } void swap( CreatedSignature & other ) { using std::swap; swap( this->d, other.d ); swap( this->idx, other.idx ); } bool isNull() const; const char * fingerprint() const; time_t creationTime() const; SignatureMode mode() const; unsigned int publicKeyAlgorithm() const; const char * publicKeyAlgorithmAsString() const; unsigned int hashAlgorithm() const; const char * hashAlgorithmAsString() const; unsigned int signatureClass() const; private: boost::shared_ptr 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/gpgme++/util.h b/gpgme++/util.h index 67487e85c..71739f8ce 100644 --- a/gpgme++/util.h +++ b/gpgme++/util.h @@ -1,113 +1,117 @@ /* 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::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 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 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__ diff --git a/gpgme++/verificationresult.cpp b/gpgme++/verificationresult.cpp index 502509575..30a3471b9 100644 --- a/gpgme++/verificationresult.cpp +++ b/gpgme++/verificationresult.cpp @@ -1,410 +1,497 @@ /* 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 #include #include #include "result_p.h" #include "util.h" #include +#include #include +#include #include #include #include #include class GpgME::VerificationResult::Private { public: explicit Private( const gpgme_verify_result_t r ) { if ( !r ) return; #ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME if ( r->file_name ) file_name = r->file_name; #endif // copy recursively, using compiler-generated copy ctor. // We just need to handle the pointers in the structs: for ( gpgme_signature_t is = r->signatures ; is ; is = is->next ) { gpgme_signature_t scopy = new _gpgme_signature( *is ); if ( is->fpr ) scopy->fpr = strdup( is->fpr ); scopy->next = 0; sigs.push_back( scopy ); // copy notations: nota.push_back( std::vector() ); purls.push_back( 0 ); for ( gpgme_sig_notation_t in = is->notations ; in ; in = in->next ) { if ( !in->name ) { if ( in->value ) purls.back() = strdup( in->value ); // policy url continue; } #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T Nota n = { 0, 0, in->flags }; #else Nota n = { 0, 0 }; #endif n.name = strdup( in->name ); if ( in->value ) n.value = strdup( in->value ); nota.back().push_back( n ); } } } ~Private() { for ( std::vector::iterator it = sigs.begin() ; it != sigs.end() ; ++it ) { std::free( (*it)->fpr ); delete *it; *it = 0; } for ( std::vector< std::vector >::iterator it = nota.begin() ; it != nota.end() ; ++it ) for ( std::vector::iterator jt = it->begin() ; jt != it->end() ; ++jt ) { std::free( jt->name ); jt->name = 0; std::free( jt->value ); jt->value = 0; } std::for_each( purls.begin(), purls.end(), &std::free ); } struct Nota { char * name; char * value; #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T gpgme_sig_notation_flags_t flags; #endif }; std::vector sigs; std::vector< std::vector > nota; std::vector 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::VerificationResult::signatures() const { if ( !d ) return std::vector(); std::vector result; result.reserve( d->sigs.size() ); for ( unsigned int i = 0 ; i < d->sigs.size() ; ++i ) result.push_back( Signature( d, i ) ); return result; } GpgME::Signature::Signature( const boost::shared_ptr & parent, unsigned int i ) : d( parent ), idx( i ) { } GpgME::Signature::Signature() : d(), idx( 0 ) {} bool GpgME::Signature::isNull() const { return !d || idx >= d->sigs.size() ; } GpgME::Signature::Summary GpgME::Signature::summary() const { if ( isNull() ) return None; gpgme_sigsum_t sigsum = d->sigs[idx]->summary; unsigned int result = 0; if ( sigsum & GPGME_SIGSUM_VALID ) result |= Valid; if ( sigsum & GPGME_SIGSUM_GREEN ) result |= Green; if ( sigsum & GPGME_SIGSUM_RED ) result |= Red; if ( sigsum & GPGME_SIGSUM_KEY_REVOKED ) result |= KeyRevoked; if ( sigsum & GPGME_SIGSUM_KEY_EXPIRED ) result |= KeyExpired; if ( sigsum & GPGME_SIGSUM_SIG_EXPIRED ) result |= SigExpired; if ( sigsum & GPGME_SIGSUM_KEY_MISSING ) result |= KeyMissing; if ( sigsum & GPGME_SIGSUM_CRL_MISSING ) result |= CrlMissing; if ( sigsum & GPGME_SIGSUM_CRL_TOO_OLD ) result |= CrlTooOld; if ( sigsum & GPGME_SIGSUM_BAD_POLICY ) result |= BadPolicy; if ( sigsum & GPGME_SIGSUM_SYS_ERROR ) result |= SysError; return static_cast( 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( isNull() ? 0 : d->sigs[idx]->timestamp ); } time_t GpgME::Signature::expirationTime() const { return static_cast( isNull() ? 0 : d->sigs[idx]->exp_timestamp ); } bool GpgME::Signature::neverExpires() const { return expirationTime() == (time_t)0; } bool GpgME::Signature::isWrongKeyUsage() const { return !isNull() && d->sigs[idx]->wrong_key_usage; } bool GpgME::Signature::isVerifiedUsingChainModel() const { #ifdef HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL return !isNull() && d->sigs[idx]->chain_model; #else return false; #endif } GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const { #ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS if ( !isNull() ) return static_cast( d->sigs[idx]->pka_trust ); #endif return UnknownPKAStatus; } const char * GpgME::Signature::pkaAddress() const { #ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS if ( !isNull() ) return d->sigs[idx]->pka_address; #endif return 0; } GpgME::Signature::Validity GpgME::Signature::validity() const { if ( isNull() ) return Unknown; switch ( d->sigs[idx]->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return Unknown; case GPGME_VALIDITY_UNDEFINED: return Undefined; case GPGME_VALIDITY_NEVER: return Never; case GPGME_VALIDITY_MARGINAL: return Marginal; case GPGME_VALIDITY_FULL: return Full; case GPGME_VALIDITY_ULTIMATE: return Ultimate; } } char GpgME::Signature::validityAsString() const { if ( isNull() ) return '?'; switch ( d->sigs[idx]->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return '?'; case GPGME_VALIDITY_UNDEFINED: return 'q'; case GPGME_VALIDITY_NEVER: return 'n'; case GPGME_VALIDITY_MARGINAL: return 'm'; case GPGME_VALIDITY_FULL: return 'f'; case GPGME_VALIDITY_ULTIMATE: return 'u'; } } GpgME::Error GpgME::Signature::nonValidityReason() const { return Error( isNull() ? 0 : d->sigs[idx]->validity_reason ); } unsigned int GpgME::Signature::publicKeyAlgorithm() const { #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS if ( !isNull() ) return d->sigs[idx]->pubkey_algo; #endif return 0; } const char * GpgME::Signature::publicKeyAlgorithmAsString() const { #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS if ( !isNull() ) return gpgme_pubkey_algo_name( d->sigs[idx]->pubkey_algo ); #endif return 0; } unsigned int GpgME::Signature::hashAlgorithm() const { #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS if ( !isNull() ) return d->sigs[idx]->hash_algo; #endif return 0; } const char * GpgME::Signature::hashAlgorithmAsString() const { #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS if ( !isNull() ) return gpgme_hash_algo_name( d->sigs[idx]->hash_algo ); #endif return 0; } const char * GpgME::Signature::policyURL() const { return isNull() ? 0 : d->purls[idx] ; } GpgME::Notation GpgME::Signature::notation( unsigned int nidx ) const { return GpgME::Notation( d, idx, nidx ); } std::vector GpgME::Signature::notations() const { if ( isNull() ) return std::vector(); std::vector result; result.reserve( d->nota[idx].size() ); for ( unsigned int i = 0 ; i < d->nota[idx].size() ; ++i ) result.push_back( GpgME::Notation( d, idx, i ) ); return result; } class GpgME::Notation::Private { public: Private() : d(), sidx( 0 ), nidx( 0 ), nota( 0 ) {} Private( const boost::shared_ptr & priv, unsigned int sindex, unsigned int nindex ) : d( priv ), sidx( sindex ), nidx( nindex ), nota( 0 ) { } Private( gpgme_sig_notation_t n ) : d(), sidx( 0 ), nidx( 0 ), nota( n ? new _gpgme_sig_notation( *n ) : 0 ) { if ( nota && nota->name ) nota->name = strdup( nota->name ); if ( nota && nota->value ) nota->value = strdup( nota->value ); } Private( const Private & other ) : d( other.d ), sidx( other.sidx ), nidx( other.nidx ), nota( other.nota ) { if ( nota ) { nota->name = strdup( nota->name ); nota->value = strdup( nota->value ); } } ~Private() { if ( nota ) { std::free( nota->name ); nota->name = 0; std::free( nota->value ); nota->value = 0; delete nota; } } boost::shared_ptr d; unsigned int sidx, nidx; gpgme_sig_notation_t nota; }; GpgME::Notation::Notation( const boost::shared_ptr & parent, unsigned int sindex, unsigned int nindex ) : d( new Private( parent, sindex, nindex ) ) { } GpgME::Notation::Notation( gpgme_sig_notation_t nota ) : d( new Private( nota ) ) { } GpgME::Notation::Notation() : d() {} bool GpgME::Notation::isNull() const { if ( !d ) return true; if ( d->d ) return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ; return !d->nota; } const char * GpgME::Notation::name() const { return isNull() ? 0 : d->d ? d->d->nota[d->sidx][d->nidx].name : d->nota ? d->nota->name : 0 ; } const char * GpgME::Notation::value() const { return isNull() ? 0 : d->d ? d->d->nota[d->sidx][d->nidx].value : d->nota ? d->nota->value : 0 ; } GpgME::Notation::Flags GpgME::Notation::flags() const { return convert_from_gpgme_sig_notation_flags_t( #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T isNull() ? 0 : d->d ? d->d->nota[d->sidx][d->nidx].flags : d->nota ? d->nota->flags : 0 ); #else 0 ); #endif } bool GpgME::Notation::isHumanReadable() const { return flags() & HumanReadable; } bool GpgME::Notation::isCritical() const { return flags() & Critical; } + +std::ostream & GpgME::operator<<( std::ostream & os, const VerificationResult & result ) { + os << "GpgME::VerificationResult("; + if ( !result.isNull() ) { + os << "\n error: " << result.error() + << "\n fileName: " << protect( result.fileName() ) + << "\n signatures:\n"; + const std::vector sigs = result.signatures(); + std::copy( sigs.begin(), sigs.end(), + std::ostream_iterator( os, "\n" ) ); + } + return os << ')'; +} + +std::ostream & GpgME::operator<<( std::ostream & os, Signature::PKAStatus pkaStatus ) { +#define OUTPUT( x ) if ( !(pkaStatus & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0) + os << "GpgME::Signature::PKAStatus("; + OUTPUT( UnknownPKAStatus ); + OUTPUT( PKAVerificationFailed ); + OUTPUT( PKAVerificationSucceeded ); +#undef OUTPUT + return os << ')'; +} + +std::ostream & GpgME::operator<<( std::ostream & os, Signature::Summary summary ) { +#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0) + os << "GpgME::Signature::Summary("; + OUTPUT( Valid ); + OUTPUT( Green ); + OUTPUT( Red ); + OUTPUT( KeyRevoked ); + OUTPUT( KeyExpired ); + OUTPUT( SigExpired ); + OUTPUT( KeyMissing ); + OUTPUT( CrlMissing ); + OUTPUT( CrlTooOld ); + OUTPUT( BadPolicy ); + OUTPUT( SysError ); +#undef OUTPUT + return os << ')'; +} + +std::ostream & GpgME::operator<<( std::ostream & os, const Signature & sig ) { + os << "GpgME::Signature("; + if ( !sig.isNull() ) { + os << "\n Summary: " << sig.summary() + << "\n Fingerprint: " << protect( sig.fingerprint() ) + << "\n Status: " << sig.status() + << "\n creationTime: " << sig.creationTime() + << "\n expirationTime: " << sig.expirationTime() + << "\n isWrongKeyUsage: " << sig.isWrongKeyUsage() + << "\n isVerifiedUsingChainModel: " << sig.isVerifiedUsingChainModel() + << "\n pkaStatus: " << sig.pkaStatus() + << "\n pkaAddress: " << protect( sig.pkaAddress() ) + << "\n validity: " << sig.validityAsString() + << "\n nonValidityReason: " << sig.nonValidityReason() + << "\n publicKeyAlgorithm: " << protect( sig.publicKeyAlgorithmAsString() ) + << "\n hashAlgorithm: " << protect( sig.hashAlgorithmAsString() ) + << "\n policyURL: " << protect( sig.policyURL() ) + << "\n notations:\n"; + const std::vector nota = sig.notations(); + std::copy( nota.begin(), nota.end(), + std::ostream_iterator( 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 & nota ) { + 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/gpgme++/verificationresult.h b/gpgme++/verificationresult.h index 23f7509ef..a8dcea40f 100644 --- a/gpgme++/verificationresult.h +++ b/gpgme++/verificationresult.h @@ -1,157 +1,164 @@ /* 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 #include #include #include #include #include +#include namespace GpgME { class Error; class Signature; class Notation; class GPGMEPP_EXPORT VerificationResult : public Result { public: VerificationResult(); VerificationResult( gpgme_ctx_t ctx, int error ); VerificationResult( gpgme_ctx_t ctx, const Error & error ); explicit VerificationResult( const Error & err ); const VerificationResult & operator=( VerificationResult other ) { swap( other ); return *this; } void swap( VerificationResult & other ) { Result::swap( other ); using std::swap; swap( this->d, other.d ); } bool isNull() const; const char * fileName() const; unsigned int numSignatures() const; Signature signature( unsigned int index ) const; std::vector signatures() const; class Private; private: void init( gpgme_ctx_t ctx ); boost::shared_ptr d; }; + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const VerificationResult & result ); + class GPGMEPP_EXPORT Signature { friend class ::GpgME::VerificationResult; Signature( const boost::shared_ptr & parent, unsigned int index ); public: typedef GPGMEPP_DEPRECATED GpgME::Notation Notation; Signature(); const Signature & operator=( Signature other ) { swap( other ); return *this; } void swap( Signature & other ) { using std::swap; swap( this->d, other.d ); swap( this->idx, other.idx ); } bool isNull() const; enum Summary { None = 0x000, Valid = 0x001, Green = 0x002, Red = 0x004, KeyRevoked = 0x008, KeyExpired = 0x010, SigExpired = 0x020, KeyMissing = 0x040, CrlMissing = 0x080, CrlTooOld = 0x100, BadPolicy = 0x200, SysError = 0x400 }; Summary summary() const; const char * fingerprint() const; Error status() const; time_t creationTime() const; time_t expirationTime() const; bool neverExpires() const; GPGMEPP_DEPRECATED bool wrongKeyUsage() const { return isWrongKeyUsage(); } bool isWrongKeyUsage() const; bool isVerifiedUsingChainModel() const; enum PKAStatus { UnknownPKAStatus, PKAVerificationFailed, PKAVerificationSucceeded }; PKAStatus pkaStatus() const; const char * pkaAddress() const; enum Validity { Unknown, Undefined, Never, Marginal, Full, Ultimate }; Validity validity() const; char validityAsString() const; Error nonValidityReason() const; unsigned int publicKeyAlgorithm() const; const char * publicKeyAlgorithmAsString() const; unsigned int hashAlgorithm() const; const char * hashAlgorithmAsString() const; const char * policyURL() const; GpgME::Notation notation( unsigned int index ) const; std::vector notations() const; private: boost::shared_ptr 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__