diff --git a/CMakeLists.txt b/CMakeLists.txt index e4297addd..69db6b057 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,168 +1,181 @@ project(kdepimlibs) # where to look first for cmake modules. This line must be the first one or cmake will use the system's FindFoo.cmake set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") ############### Build Options ############### option(KDEPIM_ONLY_KLEO "Only build the libraries needed by Kleopatra." FALSE) ############### The kdepimlibs version (used e.g. in KdepimLibsConfig.cmake) ############### set(KDEPIMLIBS_VERSION_MAJOR 4) -set(KDEPIMLIBS_VERSION_MINOR 2) -set(KDEPIMLIBS_VERSION_PATCH 92) +set(KDEPIMLIBS_VERSION_MINOR 3) +set(KDEPIMLIBS_VERSION_PATCH 60) set(KDEPIMLIBS_VERSION ${KDEPIMLIBS_VERSION_MAJOR}.${KDEPIMLIBS_VERSION_MINOR}.${KDEPIMLIBS_VERSION_PATCH}) ############### search packages used by KDE ############### -find_package(KDE4 4.2.90 REQUIRED) # see SVN rev. 952875/954493 +find_package(KDE4 4.3.60 REQUIRED) include(KDE4Defaults) include(MacroLibrary) ############### Needed commands before building anything ############### add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES}) ############### Find the stuff we need ############### set(Boost_MINIMUM_VERSION "1.33.1") find_package(Boost) macro_log_feature(Boost_FOUND "boost" "Boost C++ Libraries" "http://www.boost.org" TRUE "" "Required by several critical KDEPIM apps.") #FindGpgme.cmake already handles the log message but we must ensure it is required. find_package(Gpgme REQUIRED) # configure macros if (GPGME_FOUND) include (gpgme++/ConfigureChecks.cmake) endif (GPGME_FOUND) if (NOT KDEPIM_ONLY_KLEO) #FindAkonadi.cmake is only there for compatibility reasons, but we don't want to use that. find_package(Akonadi 1.1.91 QUIET NO_MODULE) - macro_log_feature(Akonadi_FOUND "Akonadi" "Akonadi server (from kdesupport)" "http://pim.kde.org/akonadi" TRUE "1.1.91" "Akonadi is required to build KdepimLibs.") + macro_log_feature(Akonadi_FOUND "Akonadi" "Akonadi server (from kdesupport)" "http://pim.kde.org/akonadi" TRUE "1.1.95" "Akonadi is required to build KdepimLibs.") find_package(Sasl2) macro_log_feature(SASL2_FOUND "cyrus-sasl" "Cyrus SASL API" "http://asg.web.cmu.edu/sasl/sasl-library.html" TRUE "" "Required to support authentication of logins in the IMAP and Sieve kioslaves.") include (ConfigureChecks.cmake) + + set(SHARED_MIME_INFO_MINIMUM_VERSION "0.30") + find_package(SharedMimeInfo) + macro_log_feature(SHARED_MIME_INFO_FOUND "SMI" "SharedMimeInfo" "http://freedesktop.org/wiki/Software/shared-mime-info" TRUE "0.30" "SharedMimeInfo is required.") + endif (NOT KDEPIM_ONLY_KLEO) ############### Now, we add the KDEPIMLibs components ############### # These targets will always be built add_subdirectory(cmake) add_subdirectory(gpgme++) add_subdirectory(qgpgme) if (NOT KDEPIM_ONLY_KLEO) add_subdirectory(akonadi) add_subdirectory(kabc) add_subdirectory(kblog) add_subdirectory(kcal) add_subdirectory(kholidays) add_subdirectory(kimap) add_subdirectory(kioslave) add_subdirectory(kldap) add_subdirectory(kmime) add_subdirectory(kpimidentities) add_subdirectory(kpimutils) add_subdirectory(kpimtextedit) add_subdirectory(kresources) add_subdirectory(ktnef) add_subdirectory(kxmlrpcclient) add_subdirectory(mailtransport) add_subdirectory(microblog) add_subdirectory(outboxinterface) add_subdirectory(syndication) # Build the CamelCase headers add_subdirectory(includes) endif (NOT KDEPIM_ONLY_KLEO) # doc must be a subdir of kdepimlibs macro_optional_add_subdirectory(doc) # All done, let's display what we found... macro_display_feature_log() +############### Here we install some extra stuff ############### + +if (NOT KDEPIM_ONLY_KLEO) + install(FILES kdepimlibs-mime.xml DESTINATION ${XDG_MIME_INSTALL_DIR}) + update_xdg_mimetypes(${XDG_MIME_INSTALL_DIR}) +endif (NOT KDEPIM_ONLY_KLEO) + + # now create the KdepimLibsConfig.cmake file, which will be loaded by # kdelibs/cmake/modules/FindKdepimLibs.cmake and which has to contain all information # about the installed kdepimlibs anybody would like to have. Alex # we need the absolute directories where stuff will be installed too # but since the variables which contain the destinations can be relative # or absolute paths, we need this macro to make them all absoulte, Alex macro(MAKE_INSTALL_PATH_ABSOLUTE out in) if (IS_ABSOLUTE "${in}") # IS_ABSOLUTE is new since cmake 2.4.8 set(${out} "${in}") else (IS_ABSOLUTE "${in}") set(${out} "\${KDEPIMLIBS_INSTALL_DIR}/${in}") endif (IS_ABSOLUTE "${in}") endmacro(MAKE_INSTALL_PATH_ABSOLUTE out in) # all the following variables are put into KdepimLibsConfig.cmake, so # they are usable by projects using kdepimlibs. Alex make_install_path_absolute(KDEPIMLIBS_DATA_DIR ${DATA_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_DBUS_INTERFACES_DIR ${DBUS_INTERFACES_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_DBUS_SERVICES_DIR ${DBUS_SERVICES_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_INCLUDE_DIR ${INCLUDE_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_LIB_DIR ${LIB_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_BIN_DIR ${BIN_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_LIBEXEC_DIR ${LIBEXEC_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_SBIN_DIR ${SBIN_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_HTML_DIR ${HTML_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_CONFIG_DIR ${CONFIG_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_ICON_DIR ${ICON_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_KCFG_DIR ${KCFG_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_LOCALE_DIR ${LOCALE_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_MIME_DIR ${MIME_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_SOUND_DIR ${SOUND_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_TEMPLATES_DIR ${TEMPLATES_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_WALLPAPER_DIR ${WALLPAPER_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_KCONF_UPDATE_DIR ${KCONF_UPDATE_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_AUTOSTART_DIR ${AUTOSTART_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_XDG_APPS_DIR ${XDG_APPS_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_XDG_DIRECTORY_DIR ${XDG_DIRECTORY_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_SYSCONF_DIR ${SYSCONF_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_MAN_DIR ${MAN_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_INFO_DIR ${INFO_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_SERVICES_DIR ${SERVICES_INSTALL_DIR}) make_install_path_absolute(KDEPIMLIBS_SERVICETYPES_DIR ${SERVICETYPES_INSTALL_DIR}) # Used in configure_file() and install(EXPORT) set(KDEPIMLIBS_TARGET_PREFIX KDEPIMLibs__) # this file is installed and contains all necessary information about the installed kdepimlibs, it also loads the file with the exported targets configure_file(KdepimLibsConfig.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/KdepimLibsConfig.cmake" @ONLY) # this file will be installed too and will be used by cmake when searching for the Config.cmake file to check the version of kdepimlibs, Alex macro_write_basic_cmake_version_file(${CMAKE_CURRENT_BINARY_DIR}/KdepimLibsConfigVersion.cmake ${KDEPIMLIBS_VERSION_MAJOR} ${KDEPIMLIBS_VERSION_MINOR} ${KDEPIMLIBS_VERSION_PATCH}) set(_KdepimLibsConfig_INSTALL_DIR ${LIB_INSTALL_DIR}/KdepimLibs/cmake) # places where find_package() looks for FooConfig.cmake files: # CMake >= 2.6.0 looks in lib/Foo*/cmake/, CMake >= 2.6.3 also looks in # lib/cmake/Foo*/, which packagers prefer. So they can set the KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR # option to have kdepimlibs install its Config file there. Alex if(KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR) set(_KdepimLibsConfig_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/KdepimLibs) endif(KDE4_USE_COMMON_CMAKE_PACKAGE_CONFIG_DIR) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KdepimLibsConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/KdepimLibsConfig.cmake DESTINATION ${_KdepimLibsConfig_INSTALL_DIR} ) # Install the file with the exported targets, use ${KDEPIMLIBS_TARGET_PREFIX} as prefix for the names of these targets, Alex install(EXPORT kdepimlibsLibraryTargets NAMESPACE ${KDEPIMLIBS_TARGET_PREFIX} DESTINATION ${_KdepimLibsConfig_INSTALL_DIR} FILE KDEPimLibsLibraryTargetsWithPrefix.cmake ) # Install a KDEPimLibsDependencies.cmake so people using kdepimlibs 4.2 with kdelibs < 4.2 get a useful error message, Alex file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/KDEPimLibsDependencies.cmake "\n message(FATAL_ERROR \"For using this version of kdepimlibs (${KDEPIMLIBS_VERSION}) you need a newer version of kdelibs, please update.\")\n") install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KDEPimLibsDependencies.cmake DESTINATION ${DATA_INSTALL_DIR}/cmake/modules) diff --git a/akonadi/agentbase.cpp b/akonadi/agentbase.cpp index 3dcd123b1..3aeece8c2 100644 --- a/akonadi/agentbase.cpp +++ b/akonadi/agentbase.cpp @@ -1,603 +1,602 @@ /* Copyright (c) 2006 Till Adam Copyright (c) 2007 Volker Krause Copyright (c) 2007 Bruno Virlet Copyright (c) 2008 Kevin Krammer This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 "agentbase.h" #include "agentbase_p.h" #include "controladaptor.h" #include "statusadaptor.h" #include "monitor_p.h" #include "xdgbasedirs_p.h" #include "session.h" #include "session_p.h" #include "changerecorder.h" #include "itemfetchjob.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; static AgentBase *sAgentBase = 0; AgentBase::Observer::Observer() { } AgentBase::Observer::~Observer() { } void AgentBase::Observer::itemAdded( const Item &item, const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::itemChanged( const Item &item, const QSet &partIdentifiers ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); Q_UNUSED( partIdentifiers ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::itemRemoved( const Item &item ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( item ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); Q_UNUSED( parent ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionChanged( const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } void AgentBase::Observer::collectionRemoved( const Collection &collection ) { kDebug() << "sAgentBase=" << (void*) sAgentBase << "this=" << (void*) this; Q_UNUSED( collection ); if ( sAgentBase != 0 ) sAgentBase->d_ptr->changeProcessed(); } //@cond PRIVATE AgentBasePrivate::AgentBasePrivate( AgentBase *parent ) : q_ptr( parent ), mStatusCode( AgentBase::Idle ), mProgress( 0 ), mNeedsNetwork( false ), mOnline( false ), mSettings( 0 ), mObserver( 0 ) { } AgentBasePrivate::~AgentBasePrivate() { mMonitor->setConfig( 0 ); delete mSettings; } void AgentBasePrivate::init() { Q_Q( AgentBase ); /** * Create a default session for this process. */ SessionPrivate::createDefaultSession( mId.toLatin1() ); mTracer = new org::freedesktop::Akonadi::Tracer( QLatin1String( "org.freedesktop.Akonadi" ), QLatin1String( "/tracing" ), QDBusConnection::sessionBus(), q ); new ControlAdaptor( q ); new StatusAdaptor( q ); if ( !QDBusConnection::sessionBus().registerObject( QLatin1String( "/" ), q, QDBusConnection::ExportAdaptors ) ) q->error( QString::fromLatin1( "Unable to register object at dbus: %1" ).arg( QDBusConnection::sessionBus().lastError().message() ) ); mSettings = new QSettings( QString::fromLatin1( "%1/agent_config_%2" ).arg( XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) ), mId ), QSettings::IniFormat ); mMonitor = new ChangeRecorder( q ); mMonitor->ignoreSession( Session::defaultSession() ); mMonitor->itemFetchScope().setCacheOnly( true ); mMonitor->setConfig( mSettings ); mOnline = mSettings->value( QLatin1String( "Agent/Online" ), true ).toBool(); mName = mSettings->value( QLatin1String( "Agent/Name" ) ).toString(); - if (mName.isEmpty()) { + if ( mName.isEmpty() ) { mName = mSettings->value( QLatin1String( "Resource/Name" ) ).toString(); - if (!mName.isEmpty()) { + if ( !mName.isEmpty() ) { mSettings->remove( QLatin1String( "Resource/Name" ) ); mSettings->setValue( QLatin1String( "Agent/Name" ), mName ); } } - connect( mMonitor, SIGNAL( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ), SLOT( itemAdded( const Akonadi::Item&, const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( itemChanged( const Akonadi::Item&, const QSet& ) ), SLOT( itemChanged( const Akonadi::Item&, const QSet& ) ) ); - connect( mMonitor, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)), - SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) ); + connect( mMonitor, SIGNAL( itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& ) ), + SLOT( itemMoved( const Akonadi::Item&, const Akonadi::Collection&, const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( itemRemoved( const Akonadi::Item& ) ), SLOT( itemRemoved( const Akonadi::Item& ) ) ); - connect( mMonitor, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)), - SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) ); + connect( mMonitor, SIGNAL( collectionAdded( const Akonadi::Collection&, const Akonadi::Collection& ) ), + SLOT( collectionAdded( const Akonadi::Collection&, const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( collectionChanged( const Akonadi::Collection& ) ), SLOT( collectionChanged( const Akonadi::Collection& ) ) ); connect( mMonitor, SIGNAL( collectionRemoved( const Akonadi::Collection& ) ), SLOT( collectionRemoved( const Akonadi::Collection& ) ) ); - connect( q, SIGNAL( status( int, QString ) ), q, SLOT( slotStatus( int, QString ) ) ); + connect( q, SIGNAL( status( int, const QString& ) ), q, SLOT( slotStatus( int, const QString& ) ) ); connect( q, SIGNAL( percent( int ) ), q, SLOT( slotPercent( int ) ) ); - connect( q, SIGNAL( warning( QString ) ), q, SLOT( slotWarning( QString ) ) ); - connect( q, SIGNAL( error( QString ) ), q, SLOT( slotError( QString ) ) ); + connect( q, SIGNAL( warning( const QString& ) ), q, SLOT( slotWarning( const QString& ) ) ); + connect( q, SIGNAL( error( const QString& ) ), q, SLOT( slotError( const QString& ) ) ); // Use reference counting to allow agents to finish internal jobs when the // agent is stopped. KGlobal::ref(); KGlobal::setAllowQuit(true); QTimer::singleShot( 0, q, SLOT( delayedInit() ) ); } void AgentBasePrivate::delayedInit() { Q_Q( AgentBase ); if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Agent." ) + mId ) ) kFatal() << "Unable to register service at dbus:" << QDBusConnection::sessionBus().lastError().message(); q->setOnline( mOnline ); } void AgentBasePrivate::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemAdded( item, collection ); } void AgentBasePrivate::itemChanged( const Akonadi::Item &item, const QSet &partIdentifiers ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemChanged( item, partIdentifiers ); } void AgentBasePrivate::itemMoved( const Akonadi::Item &item, const Akonadi::Collection &source, const Akonadi::Collection &dest ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver ) { // inter-resource moves, requires we know which resources the source and destination are in though if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) { if ( source.resource() != dest.resource() ) { if ( source.resource() == q_ptr->identifier() ) // moved away from us mObserver->itemRemoved( item ); else if ( dest.resource() == q_ptr->identifier() ) // moved to us mObserver->itemAdded( item, dest ); else // not for us, not sure if we should get here at all changeProcessed(); return; } } // either incomplete information or intra-resource move // ### we cannot just call itemRemoved here as this will already trigger changeProcessed() // so, just itemAdded() is good enough as no resource can have implemented intra-resource moves anyway // without using Observer2 mObserver->itemAdded( item, dest ); // mObserver->itemRemoved( item ); } } void AgentBasePrivate::itemRemoved( const Akonadi::Item &item ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->itemRemoved( item ); } void AgentBasePrivate::collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionAdded( collection, parent ); } void AgentBasePrivate::collectionChanged( const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionChanged( collection ); } void AgentBasePrivate::collectionRemoved( const Akonadi::Collection &collection ) { kDebug() << "mObserver=" << (void*) mObserver << "this=" << (void*) this; if ( mObserver != 0 ) mObserver->collectionRemoved( collection ); } void AgentBasePrivate::changeProcessed() { mMonitor->changeProcessed(); QTimer::singleShot( 0, mMonitor, SLOT( replayNext() ) ); } void AgentBasePrivate::slotStatus( int status, const QString &message ) { mStatusMessage = message; mStatusCode = 0; switch ( status ) { case AgentBase::Idle: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultReadyMessage(); mStatusCode = 0; break; case AgentBase::Running: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultSyncingMessage(); mStatusCode = 1; break; case AgentBase::Broken: if ( mStatusMessage.isEmpty() ) mStatusMessage = defaultErrorMessage(); mStatusCode = 2; break; default: Q_ASSERT( !"Unknown status passed" ); break; } } void AgentBasePrivate::slotPercent( int progress ) { mProgress = progress; } void AgentBasePrivate::slotWarning( const QString& message ) { mTracer->warning( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message ); } void AgentBasePrivate::slotError( const QString& message ) { mTracer->error( QString::fromLatin1( "AgentBase(%1)" ).arg( mId ), message ); } void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat ) { Q_Q( AgentBase ); q->setOnline( stat == Solid::Networking::Connected ); } AgentBase::AgentBase( const QString & id ) : d_ptr( new AgentBasePrivate( this ) ) { sAgentBase = this; d_ptr->mId = id; d_ptr->init(); if ( KApplication::kApplication() ) KApplication::kApplication()->disableSessionManagement(); } AgentBase::AgentBase( AgentBasePrivate* d, const QString &id ) : d_ptr( d ) { sAgentBase = this; d_ptr->mId = id; d_ptr->init(); } AgentBase::~AgentBase() { delete d_ptr; } QString AgentBase::parseArguments( int argc, char **argv ) { QString identifier; if ( argc < 3 ) { kDebug( 5250 ) << "Not enough arguments passed..."; exit( 1 ); } for ( int i = 1; i < argc - 1; ++i ) { if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) ) identifier = QLatin1String( argv[ i + 1 ] ); } if ( identifier.isEmpty() ) { kDebug( 5250 ) << "Identifier argument missing"; exit( 1 ); } QByteArray catalog; char *p = strrchr( argv[0], '/' ); if ( p ) catalog = QByteArray( p + 1 ); else catalog = QByteArray( argv[0] ); KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog, ki18n("Akonadi Agent"),"0.1" , ki18n("Akonadi Agent") ); KCmdLineOptions options; options.add("identifier ", ki18n("Agent identifier")); KCmdLineArgs::addCmdLineOptions( options ); return identifier; } // @endcond int AgentBase::init( AgentBase *r ) { QApplication::setQuitOnLastWindowClosed( false ); KGlobal::locale()->insertCatalog( QLatin1String("libakonadi") ); int rv = kapp->exec(); delete r; return rv; } int AgentBase::status() const { Q_D( const AgentBase ); return d->mStatusCode; } QString AgentBase::statusMessage() const { Q_D( const AgentBase ); return d->mStatusMessage; } int AgentBase::progress() const { Q_D( const AgentBase ); return d->mProgress; } QString AgentBase::progressMessage() const { Q_D( const AgentBase ); return d->mProgressMessage; } bool AgentBase::isOnline() const { Q_D( const AgentBase ); return d->mOnline; } void AgentBase::setNeedsNetwork( bool needsNetwork ) { Q_D( AgentBase ); d->mNeedsNetwork = needsNetwork; if ( d->mNeedsNetwork ) { connect( Solid::Networking::notifier() , SIGNAL( statusChanged( Solid::Networking::Status ) ) , this, SLOT( slotNetworkStatusChange( Solid::Networking::Status ) ) ); } else { disconnect( Solid::Networking::notifier(), 0, 0, 0 ); setOnline( true ); } } void AgentBase::setOnline( bool state ) { Q_D( AgentBase ); d->mOnline = state; d->mSettings->setValue( QLatin1String( "Agent/Online" ), state ); doSetOnline( state ); emit onlineChanged( state ); } void AgentBase::doSetOnline( bool online ) { Q_UNUSED( online ); } void AgentBase::configure( WId windowId ) { Q_UNUSED( windowId ); } #ifdef Q_OS_WIN //krazy:exclude=cpp void AgentBase::configure( qlonglong windowId ) { configure( reinterpret_cast( windowId ) ); } #endif WId AgentBase::winIdForDialogs() const { bool registered = QDBusConnection::sessionBus().interface()->isServiceRegistered( QLatin1String("org.freedesktop.akonaditray") ); if ( !registered ) return 0; QDBusInterface dbus( QLatin1String("org.freedesktop.akonaditray"), QLatin1String("/Actions"), QLatin1String("org.freedesktop.Akonadi.Tray") ); QDBusMessage reply = dbus.call( QLatin1String("getWinId") ); if ( reply.type() == QDBusMessage::ErrorMessage ) return 0; WId winid = (WId)reply.arguments().at( 0 ).toLongLong(); return winid; } void AgentBase::quit() { Q_D( AgentBase ); aboutToQuit(); if ( d->mSettings ) { d->mMonitor->setConfig( 0 ); d->mSettings->sync(); } KGlobal::deref(); } void AgentBase::aboutToQuit() { } void AgentBase::cleanup() { Q_D( AgentBase ); // prevent the monitor from picking up deletion signals for our own data if we are a resource // and thus avoid that we kill our own data as last act before our own death d->mMonitor->blockSignals( true ); aboutToQuit(); const QString fileName = d->mSettings->fileName(); /* * First destroy the settings object... */ d->mMonitor->setConfig( 0 ); delete d->mSettings; d->mSettings = 0; /* * ... then remove the file from hd. */ QFile::remove( fileName ); /* * ... and also remove the agent configuration file if there is one. */ QString configFile = KStandardDirs::locateLocal( "config", KGlobal::config()->name() ); QFile::remove( configFile ); KGlobal::deref(); } void AgentBase::registerObserver( Observer *observer ) { kDebug() << "observer=" << (void*) observer << "this=" << (void*) this; d_ptr->mObserver = observer; } QString AgentBase::identifier() const { return d_ptr->mId; } void AgentBase::setAgentName( const QString &name ) { Q_D( AgentBase ); if ( name == d->mName ) return; // TODO: rename collection d->mName = name; if ( d->mName.isEmpty() || d->mName == d->mId ) { d->mSettings->remove( QLatin1String( "Resource/Name" ) ); d->mSettings->remove( QLatin1String( "Agent/Name" ) ); } else d->mSettings->setValue( QLatin1String( "Agent/Name" ), d->mName ); d->mSettings->sync(); emit agentNameChanged( d->mName ); } QString AgentBase::agentName() const { Q_D( const AgentBase ); if ( d->mName.isEmpty() ) return d->mId; else return d->mName; } void AgentBase::changeProcessed() { Q_D( AgentBase ); d->changeProcessed(); } ChangeRecorder * AgentBase::changeRecorder() const { return d_ptr->mMonitor; } void AgentBase::abort() { emit abortRequested(); } void AgentBase::reconfigure() { emit reloadConfiguration(); } #include "agentbase.moc" #include "agentbase_p.moc" diff --git a/akonadi/agentbase.h b/akonadi/agentbase.h index 37b3856db..fb6a94859 100644 --- a/akonadi/agentbase.h +++ b/akonadi/agentbase.h @@ -1,503 +1,509 @@ /* This file is part of akonadiresources. Copyright (c) 2006 Till Adam Copyright (c) 2007 Volker Krause Copyright (c) 2008 Kevin Krammer This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 AKONADI_AGENTBASE_H #define AKONADI_AGENTBASE_H #include "akonadi_export.h" #include #include class ControlAdaptor; class StatusAdaptor; namespace Akonadi { class AgentBasePrivate; class ChangeRecorder; class Collection; class Item; class Session; /** * @short The base class for all Akonadi agents and resources. * * This class is a base class for all Akonadi agents, which covers the real * agent processes and all resources. * * It provides: * - lifetime management * - change monitoring and recording * - configuration interface * - problem reporting * * @author Till Adam , Volker Krause */ class AKONADI_EXPORT AgentBase : public QObject, protected QDBusContext { Q_OBJECT public: /** * @short The interface for reacting on monitored or replayed changes. * * The Observer provides an interface to react on monitored or replayed changes. * * Since the this base class does only tell the change recorder that the change * has been processed, an AgentBase subclass which wants to actually process * the change needs to subclass Observer and reimplement the methods it is * interested in. * * Such an agent specific Observer implementation can either be done * stand-alone, i.e. as a separate object, or by inheriting both AgentBase * and AgentBase::Observer. * * The observer implementation then has registered with the agent, so it * can forward the incoming changes to the observer. * * @note In the multiple inheritance approach the init() method automatically * registers itself as the observer. * * Example for stand-alone observer: * @code * class ExampleAgent : public AgentBase * { * public: * ExampleAgent( const QString &id ); * * ~ExampleAgent(); * * private: * AgentBase::Observer *mObserver; * }; * * class ExampleObserver : public AgentBase::Observer * { * protected: * void itemChanged( const Item &item ); * }; * * ExampleAgent::ExampleAgent( const QString &id ) * : AgentBase( id ), mObserver( 0 ) * { * mObserver = new ExampleObserver(); * registerObserver( mObserver ); * } * * ExampleAgent::~ExampleAgent() * { * delete mObserver; * } * * void ExampleObserver::itemChanged( const Item &item ) * { * // do something with item * kDebug() << "Item id=" << item.id(); * * // let base implementation tell the change recorder that we * // have processed the change * AgentBase::Observer::itemChanged( item ); * } * @endcode * * Example for observer through multiple inheritance: * @code * class ExampleAgent : public AgentBase, public AgentBase::Observer * { * public: * ExampleAgent( const QString &id ); * * protected: * void itemChanged( const Item &item ); * }; * * ExampleAgent::ExampleAgent( const QString &id ) * : AgentBase( id ) * { * // no need to create or register observer since * // we are the observer and registration happens automatically * // in init() * } * * void ExampleAgent::itemChanged( const Item &item ) * { * // do something with item * kDebug() << "Item id=" << item.id(); * * // let base implementation tell the change recorder that we * // have processed the change * AgentBase::Observer::itemChanged( item ); * } * @endcode * * @author Kevin Krammer */ class AKONADI_EXPORT Observer // krazy:exclude=dpointer { public: /** * Creates an observer instance. */ Observer(); /** * Destroys the observer instance. */ virtual ~Observer(); /** * Reimplement to handle adding of new items. * @param item The newly added item. * @param collection The collection @p item got added to. */ virtual void itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection ); /** * Reimplement to handle changes to existing items. * @param item The changed item. * @param partIdentifiers The identifiers of the item parts that has been changed. */ virtual void itemChanged( const Akonadi::Item &item, const QSet &partIdentifiers ); /** * Reimplement to handle deletion of items. * @param item The deleted item. */ virtual void itemRemoved( const Akonadi::Item &item ); /** * Reimplement to handle adding of new collections. * @param collection The newly added collection. * @param parent The parent collection. */ virtual void collectionAdded( const Akonadi::Collection &collection, const Akonadi::Collection &parent ); /** * Reimplement to handle changes to existing collections. * @param collection The changed collection. */ virtual void collectionChanged( const Akonadi::Collection &collection ); /** * Reimplement to handle deletion of collections. * @param collection The deleted collection. */ virtual void collectionRemoved( const Akonadi::Collection &collection ); }; /** * This enum describes the different states the * agent can be in. */ enum Status { Idle = 0, ///< The agent does currently nothing. Running, ///< The agent is working on something. Broken ///< The agent encountered an error state. }; /** * Use this method in the main function of your agent * application to initialize your agent subclass. * This method also takes care of creating a KApplication * object and parsing command line arguments. * * @note In case the given class is also derived from AgentBase::Observer * it gets registered as its own observer (see AgentBase::Observer), e.g. * agentInstance->registerObserver( agentInstance ); * * @code * * class MyAgent : public AgentBase * { * ... * }; * * AKONADI_AGENT_MAIN( MyAgent ) * * @endcode */ template static int init( int argc, char **argv ) { const QString id = parseArguments( argc, argv ); KApplication app; T* r = new T( id ); // check if T also inherits AgentBase::Observer and // if it does, automatically register it on itself Observer *observer = dynamic_cast( r ); if ( observer != 0 ) r->registerObserver( observer ); return init( r ); } /** * This method returns the current status code of the agent. * * The following return values are possible: * * - 0 - Idle * - 1 - Running * - 2 - Broken */ virtual int status() const; /** * This method returns an i18n'ed description of the current status code. */ virtual QString statusMessage() const; /** * This method returns the current progress of the agent in percentage. */ virtual int progress() const; /** * This method returns an i18n'ed description of the current progress. */ virtual QString progressMessage() const; /** * This method is called whenever the agent shall show its configuration dialog * to the user. It will be automatically called when the agent is started for * the first time. * @param windowId The parent window id. */ virtual void configure( WId windowId ); /** * This method returns the windows id, which should be used for dialogs. */ WId winIdForDialogs() const; #ifdef Q_OS_WIN /** * Overload of @ref configure needed because WId cannot be automatically casted * to qlonglong on Windows. */ void configure( qlonglong windowId ); #endif /** * Returns the instance identifier of this agent. */ QString identifier() const; /** * This method is called when the agent is removed from * the system, so it can do some cleanup stuff. */ virtual void cleanup(); /** * Registers the given observer for reacting on monitored or recorded changes. * * @param observer The change handler to register. No ownership transfer, i.e. * the caller stays owner of the pointer and can reset * the registration by calling this method with @c 0 */ void registerObserver( Observer *observer ); /** * This method is used to set the name of the agent. + * + * @since 4.3 */ //FIXME_API: make sure location is renamed to this by agentbase void setAgentName( const QString &name ); /** * Returns the name of the agent. + * + * @since 4.3 */ QString agentName() const; Q_SIGNALS: /** * This signal is emitted whenever the name of the agent has changed. * * @param name The new name of the agent. + * + * @since 4.3 */ void agentNameChanged( const QString &name ); /** * This signal should be emitted whenever the status of the agent has been changed. * @param status The new Status code. * @param message A i18n'ed description of the new status. */ void status( int status, const QString &message = QString() ); /** * This signal should be emitted whenever the progress of an action in the agent * (e.g. data transfer, connection establishment to remote server etc.) has changed. * * @param progress The progress of the action in percent. */ void percent( int progress ); /** * This signal shall be used to report warnings. * * @param message The i18n'ed warning message. */ void warning( const QString& message ); /** * This signal shall be used to report errors. * * @param message The i18n'ed error message. */ void error( const QString& message ); /** * Emitted when another application has remotely asked the agent to abort * its current operation. * Connect to this signal if your agent supports abortion. After aborting * and cleaning up, agents should return to Idle status. * * @since 4.4 */ void abortRequested(); /** * Emitted if another application has changed the agent's configuration remotely * and called AgentInstance::reconfigure(). * * @since 4.2 */ void reloadConfiguration(); /** * Emitted when the online state changed. * @param state The online state. * @since 4.2 */ void onlineChanged( bool b ); protected: /** * Creates an agent base. * * @param id The instance id of the agent. */ AgentBase( const QString & id ); /** * Destroys the agent base. */ ~AgentBase(); /** * This method is called whenever the agent application is about to * quit. * * Reimplement this method to do session cleanup (e.g. disconnecting * from groupware server). */ virtual void aboutToQuit(); /** * Returns the Akonadi::ChangeRecorder object used for monitoring. * Use this to configure which parts you want to monitor. */ ChangeRecorder* changeRecorder() const; /** * Marks the current change as processes and replays the next change if change * recording is enabled (noop otherwise). This method is called * from the default implementation of the change notification slots. While not * required when not using change recording, it is nevertheless recommended * to call this method when done with processing a change notification. */ void changeProcessed(); /** * Returns whether the agent is currently online. */ bool isOnline() const; /** * Sets whether the agent needs network or not. * * @since 4.2 * @todo use this in combination with Solid::Networking::Notifier to change * the onLine status of the agent. */ void setNeedsNetwork( bool needsNetwork ); /** * Sets whether the agent shall be online or not. */ void setOnline( bool state ); protected: //@cond PRIVATE AgentBasePrivate *d_ptr; explicit AgentBase( AgentBasePrivate* d, const QString &id ); //@endcond /** * This method is called whenever the @p online status has changed. * Reimplement this method to react on online status changes. */ virtual void doSetOnline( bool online ); private: //@cond PRIVATE static QString parseArguments( int, char** ); static int init( AgentBase *r ); // D-Bus interface stuff void abort(); void reconfigure(); void quit(); // dbus agent interface friend class ::StatusAdaptor; friend class ::ControlAdaptor; Q_DECLARE_PRIVATE( AgentBase ) Q_PRIVATE_SLOT( d_func(), void delayedInit() ) Q_PRIVATE_SLOT( d_func(), void slotStatus( int, const QString& ) ) Q_PRIVATE_SLOT( d_func(), void slotPercent( int ) ) Q_PRIVATE_SLOT( d_func(), void slotWarning( const QString& ) ) Q_PRIVATE_SLOT( d_func(), void slotError( const QString& ) ) Q_PRIVATE_SLOT( d_func(), void slotNetworkStatusChange( Solid::Networking::Status ) ) //@endcond }; } #ifndef AKONADI_AGENT_MAIN /** * Convenience Macro for the most common main() function for Akonadi agents. */ #define AKONADI_AGENT_MAIN( agentClass ) \ int main( int argc, char **argv ) \ { \ return Akonadi::AgentBase::init( argc, argv ); \ } #endif #endif diff --git a/akonadi/collectiondeletejob.h b/akonadi/collectiondeletejob.h index 9850fa46e..ab06a264a 100644 --- a/akonadi/collectiondeletejob.h +++ b/akonadi/collectiondeletejob.h @@ -1,76 +1,76 @@ /* Copyright (c) 2006 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 AKONADI_COLLECTIONDELETEJOB_H #define AKONADI_COLLECTIONDELETEJOB_H #include namespace Akonadi { class Collection; class CollectionDeleteJobPrivate; /** * @short Job that deletes a collection in the Akonadi storage. * * This job deletes a collection and all its sub-collections as well as all associated content. * * @code * * Akonadi::Collection collection = ... * * Akonadi::CollectionDeleteJob *job = new Akonadi::CollectionDeleteJob( collection ); - * connect( job, SIGNAL(result(KJob*)), this, SLOT(deletionResult(KJob*)) ); + * connect( job, SIGNAL( result( KJob* ) ), this, SLOT( deletionResult( KJob* ) ) ); * * @endcode * * @author Volker Krause */ class AKONADI_EXPORT CollectionDeleteJob : public Job { Q_OBJECT public: /** * Creates a new collection delete job. The collection needs to either have a unique * identifier or a remote identifier set. Note that using a remote identifier only works * in a resource context (that is from within ResourceBase), as remote identifiers * are not guaranteed to be globally unique. * * @param collection The collection to delete. * @param parent The parent object. */ explicit CollectionDeleteJob( const Collection &collection, QObject *parent = 0 ); /** * Destroys the collection delete job. */ ~CollectionDeleteJob(); protected: virtual void doStart(); private: Q_DECLARE_PRIVATE( CollectionDeleteJob ) }; } #endif diff --git a/akonadi/collectionmodifyjob.h b/akonadi/collectionmodifyjob.h index d7f42823b..e05b75415 100644 --- a/akonadi/collectionmodifyjob.h +++ b/akonadi/collectionmodifyjob.h @@ -1,80 +1,80 @@ /* Copyright (c) 2006 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 AKONADI_COLLECTIONMODIFYJOB_H #define AKONADI_COLLECTIONMODIFYJOB_H #include "akonadi_export.h" #include namespace Akonadi { class CachePolicy; class Collection; class CollectionModifyJobPrivate; /** * @short Job that modifies a collection in the Akonadi storage. * * This job modifies the properties of an existing collection. * * @code * * Akonadi::Collection collection = ... * * Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( collection ); - * connect( job, SIGNAL(result(KJob*)), this, SLOT(modifyResult(KJob*)) ); + * connect( job, SIGNAL( result( KJob* ) ), this, SLOT( modifyResult( KJob* ) ) ); * * @endcode * * @author Volker Krause */ class AKONADI_EXPORT CollectionModifyJob : public Job { Q_OBJECT public: /** * Creates a new collection modify job for the given collection. The collection can be * identified either by its unique identifier or its remote identifier. Since the remote * identifier is not necessarily globally unique, identification by remote identifier only * works inside a resource context (that is from within ResourceBase) and is therefore * limited to one resource. * * @param collection The collection to modify. * @param parent The parent object. */ explicit CollectionModifyJob( const Collection &collection, QObject *parent = 0 ); /** * Destroys the collection modify job. */ ~CollectionModifyJob(); protected: virtual void doStart(); private: Q_DECLARE_PRIVATE( CollectionModifyJob ) }; } #endif diff --git a/akonadi/collectionmovejob.h b/akonadi/collectionmovejob.h index f81bacd10..979827cc0 100644 --- a/akonadi/collectionmovejob.h +++ b/akonadi/collectionmovejob.h @@ -1,60 +1,72 @@ /* Copyright (c) 2009 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 AKONADI_COLLECTIONMOVEJOB_H #define AKONADI_COLLECTIONMOVEJOB_H #include "akonadi_export.h" #include namespace Akonadi { class Collection; class CollectionMoveJobPrivate; /** * @short Job that moves a collection in the Akonadi storage to a new parent collection. * * This job moves an existing collection to a new parent collection. + * + * @code + * + * const Akonadi::Collection collection = ... + * const Akonadi::Collection newParent = ... + * + * Akonadi::CollectionMoveJob *job = new Akonadi::CollectionMoveJob( collection, newParent ); + * connect( job, SIGNAL( result( KJob* ) ), this, SLOT( moveResult( KJob* ) ) ); + * + * @endcode + * + * @author Volker Krause */ class AKONADI_EXPORT CollectionMoveJob : public Job { Q_OBJECT public: /** * Creates a new collection move job for the given collection and destination * * @param collection The collection to move. * @param destination The destination collection where @p collection should be moved to. * @param parent The parent object. */ CollectionMoveJob( const Collection &collection, const Collection &destination, QObject *parent = 0 ); protected: virtual void doStart(); private: Q_DECLARE_PRIVATE( CollectionMoveJob ) }; } #endif diff --git a/akonadi/resourcebase.cpp b/akonadi/resourcebase.cpp index be798b66e..8c4eccee6 100644 --- a/akonadi/resourcebase.cpp +++ b/akonadi/resourcebase.cpp @@ -1,604 +1,606 @@ /* Copyright (c) 2006 Till Adam Copyright (c) 2007 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 "resourcebase.h" #include "agentbase_p.h" #include "resourceadaptor.h" #include "collectiondeletejob.h" #include "collectionsync_p.h" #include "itemsync.h" #include "resourcescheduler_p.h" #include "tracerinterface.h" #include "xdgbasedirs_p.h" #include "changerecorder.h" #include "collectionfetchjob.h" #include "collectionmodifyjob.h" #include "itemfetchjob.h" #include "itemfetchscope.h" #include "itemmodifyjob.h" #include "itemmodifyjob_p.h" #include "session.h" #include "resourceselectjob_p.h" #include #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; class Akonadi::ResourceBasePrivate : public AgentBasePrivate { public: ResourceBasePrivate( ResourceBase *parent ) : AgentBasePrivate( parent ), scheduler( 0 ), mItemSyncer( 0 ), mCollectionSyncer( 0 ) { mStatusMessage = defaultReadyMessage(); } Q_DECLARE_PUBLIC( ResourceBase ) void delayedInit() { if ( !QDBusConnection::sessionBus().registerService( QLatin1String( "org.freedesktop.Akonadi.Resource." ) + mId ) ) kFatal() << "Unable to register service at D-Bus: " << QDBusConnection::sessionBus().lastError().message(); AgentBasePrivate::delayedInit(); } virtual void changeProcessed() { mMonitor->changeProcessed(); if ( !mMonitor->isEmpty() ) scheduler->scheduleChangeReplay(); scheduler->taskDone(); } void slotDeliveryDone( KJob* job ); void slotCollectionSyncDone( KJob *job ); void slotLocalListDone( KJob *job ); void slotSynchronizeCollection( const Collection &col ); void slotCollectionListDone( KJob *job ); void slotItemSyncDone( KJob *job ); void slotPercent( KJob* job, unsigned long percent ); void slotDeleteResourceCollection(); void slotDeleteResourceCollectionDone( KJob *job ); void slotCollectionDeletionDone( KJob *job ); // synchronize states Collection currentCollection; ResourceScheduler *scheduler; ItemSync *mItemSyncer; CollectionSync *mCollectionSyncer; }; ResourceBase::ResourceBase( const QString & id ) : AgentBase( new ResourceBasePrivate( this ), id ) { Q_D( ResourceBase ); new ResourceAdaptor( this ); d->scheduler = new ResourceScheduler( this ); d->mMonitor->setChangeRecordingEnabled( true ); - connect( d->mMonitor, SIGNAL(changesAdded()), - d->scheduler, SLOT(scheduleChangeReplay()) ); + connect( d->mMonitor, SIGNAL( changesAdded() ), + d->scheduler, SLOT( scheduleChangeReplay() ) ); d->mMonitor->setResourceMonitored( d->mId.toLatin1() ); - connect( d->scheduler, SIGNAL(executeFullSync()), - SLOT(retrieveCollections()) ); - connect( d->scheduler, SIGNAL(executeCollectionTreeSync()), - SLOT(retrieveCollections()) ); - connect( d->scheduler, SIGNAL(executeCollectionSync(Akonadi::Collection)), - SLOT(slotSynchronizeCollection(Akonadi::Collection)) ); - connect( d->scheduler, SIGNAL(executeItemFetch(Akonadi::Item,QSet)), - SLOT(retrieveItem(Akonadi::Item,QSet)) ); - connect( d->scheduler, SIGNAL(executeResourceCollectionDeletion()), - SLOT(slotDeleteResourceCollection()) ); - connect( d->scheduler, SIGNAL( status( int, QString ) ), - SIGNAL( status( int, QString ) ) ); - connect( d->scheduler, SIGNAL(executeChangeReplay()), - d->mMonitor, SLOT(replayNext()) ); - connect( d->scheduler, SIGNAL(fullSyncComplete()), SIGNAL(synchronized()) ); - connect( d->mMonitor, SIGNAL(nothingToReplay()), d->scheduler, SLOT(taskDone()) ); - connect( this, SIGNAL(synchronized()), d->scheduler, SLOT(taskDone()) ); - connect( this, SIGNAL(agentNameChanged(QString)), this, SIGNAL(nameChanged(QString))); + connect( d->scheduler, SIGNAL( executeFullSync() ), + SLOT( retrieveCollections() ) ); + connect( d->scheduler, SIGNAL( executeCollectionTreeSync() ), + SLOT( retrieveCollections() ) ); + connect( d->scheduler, SIGNAL( executeCollectionSync( const Akonadi::Collection& ) ), + SLOT( slotSynchronizeCollection( const Akonadi::Collection& ) ) ); + connect( d->scheduler, SIGNAL( executeItemFetch( const Akonadi::Item&, const QSet& ) ), + SLOT( retrieveItem( const Akonadi::Item&, const QSet& ) ) ); + connect( d->scheduler, SIGNAL( executeResourceCollectionDeletion() ), + SLOT( slotDeleteResourceCollection() ) ); + connect( d->scheduler, SIGNAL( status( int, const QString& ) ), + SIGNAL( status( int, const QString& ) ) ); + connect( d->scheduler, SIGNAL( executeChangeReplay() ), + d->mMonitor, SLOT( replayNext() ) ); + connect( d->scheduler, SIGNAL( fullSyncComplete() ), SIGNAL( synchronized() ) ); + connect( d->mMonitor, SIGNAL( nothingToReplay() ), d->scheduler, SLOT( taskDone() ) ); + connect( this, SIGNAL( synchronized() ), d->scheduler, SLOT( taskDone() ) ); + connect( this, SIGNAL( agentNameChanged( const QString& ) ), + this, SIGNAL( nameChanged( const QString& ) ) ); d->scheduler->setOnline( d->mOnline ); if ( !d->mMonitor->isEmpty() ) d->scheduler->scheduleChangeReplay(); new ResourceSelectJob( identifier() ); } ResourceBase::~ResourceBase() { } void ResourceBase::synchronize() { d_func()->scheduler->scheduleFullSync(); } void ResourceBase::setName( const QString &name ) { - AgentBase::setAgentName(name); + AgentBase::setAgentName( name ); } QString ResourceBase::name() const { - return AgentBase::agentName(); + return AgentBase::agentName(); } QString ResourceBase::parseArguments( int argc, char **argv ) { QString identifier; if ( argc < 3 ) { kDebug( 5250 ) << "Not enough arguments passed..."; exit( 1 ); } for ( int i = 1; i < argc - 1; ++i ) { if ( QLatin1String( argv[ i ] ) == QLatin1String( "--identifier" ) ) identifier = QLatin1String( argv[ i + 1 ] ); } if ( identifier.isEmpty() ) { kDebug( 5250 ) << "Identifier argument missing"; exit( 1 ); } QByteArray catalog; char *p = strrchr( argv[0], '/' ); if ( p ) catalog = QByteArray( p + 1 ); else catalog = QByteArray( argv[0] ); KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog, ki18nc("@title, application name", "Akonadi Resource"), "0.1", ki18nc("@title, application description", "Akonadi Resource") ); KCmdLineOptions options; - options.add("identifier ", - ki18nc("@label, commandline option", "Resource identifier")); + options.add( "identifier ", + ki18nc("@label, commandline option", "Resource identifier") ); KCmdLineArgs::addCmdLineOptions( options ); return identifier; } int ResourceBase::init( ResourceBase *r ) { QApplication::setQuitOnLastWindowClosed( false ); int rv = kapp->exec(); delete r; return rv; } void ResourceBase::itemRetrieved( const Item &item ) { Q_D( ResourceBase ); Q_ASSERT( d->scheduler->currentTask().type == ResourceScheduler::FetchItem ); if ( !item.isValid() ) { QDBusMessage reply( d->scheduler->currentTask().dbusMsg ); reply << false; QDBusConnection::sessionBus().send( reply ); d->scheduler->taskDone(); return; } Item i( item ); QSet requestedParts = d->scheduler->currentTask().itemParts; foreach ( const QByteArray &part, requestedParts ) { if ( !item.loadedPayloadParts().contains( part ) ) { kWarning( 5250 ) << "Item does not provide part" << part; } } ItemModifyJob *job = new ItemModifyJob( i ); // FIXME: remove once the item with which we call retrieveItem() has a revision number job->disableRevisionCheck(); - connect( job, SIGNAL(result(KJob*)), SLOT(slotDeliveryDone(KJob*)) ); + connect( job, SIGNAL( result( KJob* ) ), SLOT( slotDeliveryDone( KJob* ) ) ); } void ResourceBasePrivate::slotDeliveryDone(KJob * job) { Q_Q( ResourceBase ); Q_ASSERT( scheduler->currentTask().type == ResourceScheduler::FetchItem ); QDBusMessage reply( scheduler->currentTask().dbusMsg ); if ( job->error() ) { emit q->error( QLatin1String( "Error while creating item: " ) + job->errorString() ); reply << false; } else { reply << true; } QDBusConnection::sessionBus().send( reply ); scheduler->taskDone(); } void ResourceBasePrivate::slotDeleteResourceCollection() { Q_Q( ResourceBase ); CollectionFetchJob *job = new CollectionFetchJob( Collection::root(), CollectionFetchJob::FirstLevel ); job->setResource( q->identifier() ); - connect( job, SIGNAL(result(KJob*)), q, SLOT(slotDeleteResourceCollectionDone(KJob*)) ); + connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotDeleteResourceCollectionDone( KJob* ) ) ); } void ResourceBasePrivate::slotDeleteResourceCollectionDone( KJob *job ) { Q_Q( ResourceBase ); if ( job->error() ) { emit q->error( job->errorString() ); scheduler->taskDone(); } else { const CollectionFetchJob *fetchJob = static_cast( job ); if ( !fetchJob->collections().isEmpty() ) { CollectionDeleteJob *job = new CollectionDeleteJob( fetchJob->collections().first() ); connect( job, SIGNAL( result( KJob* ) ), q, SLOT( slotCollectionDeletionDone( KJob* ) ) ); } else { // there is no resource collection, so just ignore the request scheduler->taskDone(); } } } void ResourceBasePrivate::slotCollectionDeletionDone( KJob *job ) { Q_Q( ResourceBase ); if ( job->error() ) { emit q->error( job->errorString() ); } scheduler->taskDone(); } -void ResourceBase::changeCommitted(const Item& item) +void ResourceBase::changeCommitted( const Item& item ) { Q_D( ResourceBase ); ItemModifyJob *job = new ItemModifyJob( item ); job->d_func()->setClean(); job->disableRevisionCheck(); // TODO: remove, but where/how do we handle the error? job->ignorePayload(); // we only want to reset the dirty flag and update the remote id d->changeProcessed(); } void ResourceBase::changeCommitted( const Collection &collection ) { Q_D( ResourceBase ); CollectionModifyJob *job = new CollectionModifyJob( collection ); Q_UNUSED( job ); //TODO: error checking d->changeProcessed(); } bool ResourceBase::requestItemDelivery( qint64 uid, const QString & remoteId, const QString &mimeType, const QStringList &_parts ) { Q_D( ResourceBase ); if ( !isOnline() ) { emit error( i18nc( "@info", "Cannot fetch item in offline mode." ) ); return false; } setDelayedReply( true ); // FIXME: we need at least the revision number too Item item( uid ); item.setMimeType( mimeType ); item.setRemoteId( remoteId ); QSet parts; Q_FOREACH( const QString &str, _parts ) parts.insert( str.toLatin1() ); d->scheduler->scheduleItemFetch( item, parts, message().createReply() ); return true; } -void ResourceBase::collectionsRetrieved(const Collection::List & collections) +void ResourceBase::collectionsRetrieved( const Collection::List & collections ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree || d->scheduler->currentTask().type == ResourceScheduler::SyncAll, "ResourceBase::collectionsRetrieved()", "Calling collectionsRetrieved() although no collection retrieval is in progress" ); if ( !d->mCollectionSyncer ) { d->mCollectionSyncer = new CollectionSync( identifier() ); - connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) ); + connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) ); } d->mCollectionSyncer->setRemoteCollections( collections ); } -void ResourceBase::collectionsRetrievedIncremental(const Collection::List & changedCollections, const Collection::List & removedCollections) +void ResourceBase::collectionsRetrievedIncremental( const Collection::List & changedCollections, + const Collection::List & removedCollections ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree || d->scheduler->currentTask().type == ResourceScheduler::SyncAll, "ResourceBase::collectionsRetrievedIncremental()", "Calling collectionsRetrievedIncremental() although no collection retrieval is in progress" ); if ( !d->mCollectionSyncer ) { d->mCollectionSyncer = new CollectionSync( identifier() ); - connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) ); + connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) ); } d->mCollectionSyncer->setRemoteCollections( changedCollections, removedCollections ); } -void ResourceBase::setCollectionStreamingEnabled(bool enable) +void ResourceBase::setCollectionStreamingEnabled( bool enable ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree || d->scheduler->currentTask().type == ResourceScheduler::SyncAll, "ResourceBase::setCollectionStreamingEnabled()", "Calling setCollectionStreamingEnabled() although no collection retrieval is in progress" ); if ( !d->mCollectionSyncer ) { d->mCollectionSyncer = new CollectionSync( identifier() ); - connect( d->mCollectionSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mCollectionSyncer, SIGNAL(result(KJob*)), SLOT(slotCollectionSyncDone(KJob*)) ); + connect( d->mCollectionSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mCollectionSyncer, SIGNAL( result( KJob* ) ), SLOT( slotCollectionSyncDone( KJob* ) ) ); } d->mCollectionSyncer->setStreamingEnabled( enable ); } void ResourceBase::collectionsRetrievalDone() { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollectionTree || d->scheduler->currentTask().type == ResourceScheduler::SyncAll, "ResourceBase::collectionsRetrievalDone()", "Calling collectionsRetrievalDone() although no collection retrieval is in progress" ); // streaming enabled, so finalize the sync if ( d->mCollectionSyncer ) { d->mCollectionSyncer->retrievalDone(); } // user did the sync himself, we are done now else { d->scheduler->taskDone(); } } -void ResourceBasePrivate::slotCollectionSyncDone(KJob * job) +void ResourceBasePrivate::slotCollectionSyncDone( KJob * job ) { Q_Q( ResourceBase ); mCollectionSyncer = 0; if ( job->error() ) { emit q->error( job->errorString() ); } else { if ( scheduler->currentTask().type == ResourceScheduler::SyncAll ) { CollectionFetchJob *list = new CollectionFetchJob( Collection::root(), CollectionFetchJob::Recursive ); list->setResource( mId ); - q->connect( list, SIGNAL(result(KJob*)), q, SLOT(slotLocalListDone(KJob*)) ); + q->connect( list, SIGNAL( result( KJob* ) ), q, SLOT( slotLocalListDone( KJob* ) ) ); return; } } scheduler->taskDone(); } -void ResourceBasePrivate::slotLocalListDone(KJob * job) +void ResourceBasePrivate::slotLocalListDone( KJob * job ) { Q_Q( ResourceBase ); if ( job->error() ) { emit q->error( job->errorString() ); } else { Collection::List cols = static_cast( job )->collections(); foreach ( const Collection &col, cols ) { scheduler->scheduleSync( col ); } scheduler->scheduleFullSyncCompletion(); } scheduler->taskDone(); } void ResourceBasePrivate::slotSynchronizeCollection( const Collection &col ) { Q_Q( ResourceBase ); currentCollection = col; // check if this collection actually can contain anything QStringList contentTypes = currentCollection.contentMimeTypes(); contentTypes.removeAll( Collection::mimeType() ); if ( !contentTypes.isEmpty() ) { emit q->status( AgentBase::Running, i18nc( "@info:status", "Syncing collection '%1'", currentCollection.name() ) ); q->retrieveItems( currentCollection ); return; } scheduler->taskDone(); } void ResourceBase::itemsRetrievalDone() { Q_D( ResourceBase ); // streaming enabled, so finalize the sync if ( d->mItemSyncer ) { d->mItemSyncer->deliveryDone(); } // user did the sync himself, we are done now else { d->scheduler->taskDone(); } } void ResourceBase::clearCache() { Q_D( ResourceBase ); d->scheduler->scheduleResourceCollectionDeletion(); } Collection ResourceBase::currentCollection() const { Q_D( const ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection , "ResourceBase::currentCollection()", "Trying to access current collection although no item retrieval is in progress" ); return d->currentCollection; } Item ResourceBase::currentItem() const { Q_D( const ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::FetchItem , "ResourceBase::currentItem()", "Trying to access current item although no item retrieval is in progress" ); return d->scheduler->currentTask().item; } void ResourceBase::synchronizeCollectionTree() { d_func()->scheduler->scheduleCollectionTreeSync(); } void ResourceBase::cancelTask() { Q_D( ResourceBase ); switch ( d->scheduler->currentTask().type ) { case ResourceScheduler::FetchItem: itemRetrieved( Item() ); // sends the error reply and break; case ResourceScheduler::ChangeReplay: d->changeProcessed(); break; default: d->scheduler->taskDone(); } } void ResourceBase::cancelTask( const QString &msg ) { cancelTask(); emit error( msg ); } void ResourceBase::deferTask() { Q_D( ResourceBase ); d->scheduler->deferTask(); } void ResourceBase::doSetOnline( bool state ) { d_func()->scheduler->setOnline( state ); } -void ResourceBase::synchronizeCollection(qint64 collectionId ) +void ResourceBase::synchronizeCollection( qint64 collectionId ) { - CollectionFetchJob* job = new CollectionFetchJob( Collection(collectionId), CollectionFetchJob::Base ); + CollectionFetchJob* job = new CollectionFetchJob( Collection( collectionId ), CollectionFetchJob::Base ); job->setResource( identifier() ); - connect( job, SIGNAL(result(KJob*)), SLOT(slotCollectionListDone(KJob*)) ); + connect( job, SIGNAL( result( KJob* ) ), SLOT( slotCollectionListDone( KJob* ) ) ); } void ResourceBasePrivate::slotCollectionListDone( KJob *job ) { if ( !job->error() ) { Collection::List list = static_cast( job )->collections(); if ( !list.isEmpty() ) { Collection col = list.first(); scheduler->scheduleSync( col ); } } // TODO: error handling } void ResourceBase::setTotalItems( int amount ) { kDebug() << amount; Q_D( ResourceBase ); setItemStreamingEnabled( true ); d->mItemSyncer->setTotalItems( amount ); } void ResourceBase::setItemStreamingEnabled( bool enable ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection, "ResourceBase::setItemStreamingEnabled()", "Calling setItemStreamingEnabled() although no item retrieval is in progress" ); if ( !d->mItemSyncer ) { d->mItemSyncer = new ItemSync( currentCollection() ); - connect( d->mItemSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mItemSyncer, SIGNAL(result(KJob*)), SLOT(slotItemSyncDone(KJob*)) ); + connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) ); } d->mItemSyncer->setStreamingEnabled( enable ); } void ResourceBase::itemsRetrieved( const Item::List &items ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection, "ResourceBase::itemsRetrieved()", "Calling itemsRetrieved() although no item retrieval is in progress" ); if ( !d->mItemSyncer ) { d->mItemSyncer = new ItemSync( currentCollection() ); - connect( d->mItemSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mItemSyncer, SIGNAL(result(KJob*)), SLOT(slotItemSyncDone(KJob*)) ); + connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) ); } d->mItemSyncer->setFullSyncItems( items ); } -void ResourceBase::itemsRetrievedIncremental(const Item::List &changedItems, const Item::List &removedItems) +void ResourceBase::itemsRetrievedIncremental( const Item::List &changedItems, const Item::List &removedItems ) { Q_D( ResourceBase ); Q_ASSERT_X( d->scheduler->currentTask().type == ResourceScheduler::SyncCollection, "ResourceBase::itemsRetrievedIncremental()", "Calling itemsRetrievedIncremental() although no item retrieval is in progress" ); if ( !d->mItemSyncer ) { d->mItemSyncer = new ItemSync( currentCollection() ); - connect( d->mItemSyncer, SIGNAL(percent(KJob*,unsigned long)), SLOT(slotPercent(KJob*,unsigned long)) ); - connect( d->mItemSyncer, SIGNAL(result(KJob*)), SLOT(slotItemSyncDone(KJob*)) ); + connect( d->mItemSyncer, SIGNAL( percent( KJob*, unsigned long ) ), SLOT( slotPercent( KJob*, unsigned long ) ) ); + connect( d->mItemSyncer, SIGNAL( result( KJob* ) ), SLOT( slotItemSyncDone( KJob* ) ) ); } d->mItemSyncer->setIncrementalSyncItems( changedItems, removedItems ); } void ResourceBasePrivate::slotItemSyncDone( KJob *job ) { mItemSyncer = 0; Q_Q( ResourceBase ); if ( job->error() ) { emit q->error( job->errorString() ); } scheduler->taskDone(); } void ResourceBasePrivate::slotPercent( KJob *job, unsigned long percent ) { Q_Q( ResourceBase ); Q_UNUSED( job ); emit q->percent( percent ); } #include "resourcebase.moc" diff --git a/akonadi/tests/testrunner/CMakeLists.txt b/akonadi/tests/testrunner/CMakeLists.txt index e4ed024a6..4787a204b 100644 --- a/akonadi/tests/testrunner/CMakeLists.txt +++ b/akonadi/tests/testrunner/CMakeLists.txt @@ -1,46 +1,45 @@ project (akonaditest) include_directories( ${CMAKE_SOURCE_DIR}/kabc ${CMAKE_SOURCE_DIR}/kcal ${CMAKE_SOURCE_DIR}/akonadi ${CMAKE_BINARY_DIR}/kabc ${CMAKE_BINARY_DIR}/kcal ${CMAKE_BINARY_DIR}/akonadi ${CMAKE_CURRENT_SOURCE_DIR} ${Boost_INCLUDE_DIR} ${AKONADI_INCLUDE_DIR} ${KDE4_INCLUDES} ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" ) set(akonaditest_SRCS main.cpp setup.cpp config.cpp shellscript.cpp symbols.cpp testrunner.cpp ) kde4_add_executable(akonaditest NOGUI ${akonaditest_SRCS}) target_link_libraries(akonaditest akonadi-kde kabc kcal syndication ${KDE4_KDEUI_LIBS} ${Boost_LIBRARIES} ${KDE4_AKONADI_LIBS} ${KDE4_KABC_LIBS} ${KDE4_KCAL_LIBS} ${KDE4_SYNDICATION_LIBS} - ${KDE4_KDECORE_LIBS} - ${QT_QTCORE_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTDBUS_LIBRARY} + ${QT_QTNETWORK_LIBRARY} ) install(TARGETS akonaditest ${INSTALL_TARGETS_DEFAULT_ARGS}) diff --git a/akonadi/tests/testrunner/setup.cpp b/akonadi/tests/testrunner/setup.cpp index 5e9e6dd85..53b55f9c6 100644 --- a/akonadi/tests/testrunner/setup.cpp +++ b/akonadi/tests/testrunner/setup.cpp @@ -1,410 +1,418 @@ /* * Copyright (c) 2008 Igor Trindade Oliveira * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include "setup.h" #include "config.h" #include "symbols.h" #include #include #include +#include #include #include #include #include #include #include #include #include #include #include +#include #include #include #ifdef __APPLE__ #include #endif QMap SetupTest::environment() const { QMap env; foreach ( const QString& val, QProcess::systemEnvironment() ) { const int p = val.indexOf( QLatin1Char( '=' ) ); if ( p > 0 ) { env[ val.left( p ).toUpper() ] = val.mid( p + 1 ); } } return env; } bool SetupTest::clearEnvironment() { const QStringList keys = environment().keys(); foreach ( const QString& key, keys ) { if ( key != QLatin1String( "HOME" ) ) { // work around a bug in the Mac OS X 10.4.0 SDK #if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4) /* on OSX 10.4, unsetenv is a void, not a boolean */ unsetenv( key.toAscii() ); #else if ( !unsetenv( key.toAscii() ) ) { return false; } #endif } } return true; } int SetupTest::addDBusToEnvironment( QIODevice& io ) { QByteArray data = io.readLine(); int pid = -1; Symbols *symbol = Symbols::instance(); while ( data.size() ) { if ( data[ data.size() - 1 ] == '\n' ) { data.resize( data.size() - 1 ); } QString val( data ); const int p = val.indexOf( '=' ); if ( p > 0 ) { const QString name = val.left( p ).toUpper(); val = val.mid( p + 1 ); if ( name == QLatin1String( "DBUS_SESSION_BUS_PID" ) ) { pid = val.toInt(); setenv( name.toAscii(), val.toAscii(), 1 ); symbol->insertSymbol( name, val ); } else if ( name == QLatin1String( "DBUS_SESSION_BUS_ADDRESS" ) ) { setenv( name.toAscii(), val.toAscii(), 1 ); symbol->insertSymbol( name, val ); } } data = io.readLine(); } return pid; } int SetupTest::startDBusDaemon() { QProcess dbusprocess; QStringList dbusargs; dbusprocess.start( "/usr/bin/dbus-launch", dbusargs ); bool ok = dbusprocess.waitForStarted() && dbusprocess.waitForFinished(); if ( !ok ) { kDebug() << "error starting dbus-launch"; dbusprocess.kill(); return -1; } int dbuspid = addDBusToEnvironment( dbusprocess ); return dbuspid; } void SetupTest::stopDBusDaemon( int dbuspid ) { kDebug() << dbuspid; if ( dbuspid ) kill( dbuspid, 15 ); sleep( 1 ); if ( dbuspid ) kill( dbuspid, 9 ); } void SetupTest::registerWithInternalDBus( const QString &address ) { mInternalBus = new QDBusConnection( QDBusConnection::connectToBus( address, QLatin1String( "InternalBus" ) ) ); mInternalBus->registerService( QLatin1String( "org.kde.Akonadi.Testrunner" ) ); mInternalBus->registerObject( QLatin1String( "/MainApplication" ), KApplication::kApplication(), QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableProperties | QDBusConnection::ExportAdaptors ); mInternalBus->registerObject( QLatin1String( "/" ), this, QDBusConnection::ExportScriptableSlots ); QDBusConnectionInterface *busInterface = mInternalBus->interface(); connect( busInterface, SIGNAL( serviceOwnerChanged( QString, QString, QString ) ), this, SLOT( dbusNameOwnerChanged( QString, QString, QString ) ) ); } bool SetupTest::startAkonadiDaemon() { mAkonadiDaemonProcess->setProgram( QLatin1String( "akonadi_control" ) ); mAkonadiDaemonProcess->start(); const bool started = mAkonadiDaemonProcess->waitForStarted( 5000 ); kDebug() << mAkonadiDaemonProcess->pid(); return started; } bool SetupTest::stopAkonadiDaemon() { mAkonadiDaemonProcess->terminate(); const bool finished = mAkonadiDaemonProcess->waitForFinished( 5000 ); if ( !finished ) { kDebug() << "Problem finishing process."; } mAkonadiDaemonProcess->close(); return finished; } void SetupTest::setupAgents() { if ( mAgentsCreated ) return; mAgentsCreated = true; Config *config = Config::instance(); QDBusInterface agentDBus( QLatin1String( "org.freedesktop.Akonadi.Control" ), QLatin1String( "/AgentManager" ), QLatin1String( "org.freedesktop.Akonadi.AgentManager" ), *mInternalBus ); const QList > agents = config->agents(); typedef QPair StringBoolPair; foreach ( const StringBoolPair &agent, agents ) { kDebug() << "Creating agent" << agent.first << "..."; QDBusReply reply = agentDBus.call( QLatin1String( "createAgentInstance" ), agent.first ); if ( reply.isValid() && !reply.value().isEmpty() ) { mPendingAgents << reply.value(); mPendingResources << reply.value(); if ( agent.second ) { mPendingSyncs << reply.value(); } } else { kError() << "createAgentInstance call failed:" << reply.error(); } } if ( mPendingAgents.isEmpty() ) emit setupDone(); } void SetupTest::dbusNameOwnerChanged( const QString &name, const QString &oldOwner, const QString &newOwner ) { kDebug() << name << oldOwner << newOwner; // TODO: find out why it does not work properly when reacting on // org.freedesktop.Akonadi.Control if ( name == QLatin1String( "org.freedesktop.Akonadi" ) ) { if ( oldOwner.isEmpty() ) // startup setupAgents(); else if ( mShuttingDown ) // our own shutdown shutdownHarder(); return; } if ( name.startsWith( QLatin1String( "org.freedesktop.Akonadi.Agent." ) ) && oldOwner.isEmpty() ) { const QString identifier = name.mid( 30 ); if ( mPendingAgents.contains( identifier ) ) { kDebug() << "Agent" << identifier << "started."; mPendingAgents.removeAll( identifier ); if ( mPendingAgents.isEmpty() && mPendingResources.isEmpty() ) QTimer::singleShot( 5000, this, SLOT(synchronizeResources()) ); } } if ( name.startsWith( QLatin1String( "org.freedesktop.Akonadi.Resource." ) ) && oldOwner.isEmpty() ) { const QString identifier = name.mid( 33 ); if ( mPendingResources.contains( identifier ) ) { kDebug() << "Resource" << identifier << "registered."; mPendingResources.removeAll( identifier ); if ( mPendingAgents.isEmpty() && mPendingResources.isEmpty() ) QTimer::singleShot( 5000, this, SLOT(synchronizeResources()) ); } } } void SetupTest::synchronizeResources() { foreach ( const QString id, mPendingSyncs ) { QDBusInterface *iface = new QDBusInterface( QString::fromLatin1( "org.freedesktop.Akonadi.Resource.%1").arg( id ), "/", "org.freedesktop.Akonadi.Resource", *mInternalBus, this ); mSyncMapper->setMapping( iface, id ); connect( iface, SIGNAL(synchronized()), mSyncMapper, SLOT(map()) ); if ( mPendingSyncs.contains( id ) ) { kDebug() << "Synchronizing resource" << id << "..."; QDBusReply reply = iface->call( "synchronize" ); if ( !reply.isValid() ) kError() << "Syncing resource" << id << "failed: " << reply.error(); } } } void SetupTest::resourceSynchronized(const QString& agentId) { if ( mPendingSyncs.contains( agentId ) ) { kDebug() << "Agent" << agentId << "synchronized."; mPendingSyncs.removeAll( agentId ); if ( mPendingSyncs.isEmpty() ) emit setupDone(); } } void SetupTest::copyDirectory( const QString &src, const QString &dst ) { QDir srcDir( src ); srcDir.setFilter( QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot ); const QFileInfoList list = srcDir.entryInfoList(); for ( int i = 0; i < list.size(); ++i ) { if ( list.at( i ).isDir() ) { const QDir tmpDir( dst ); tmpDir.mkdir( list.at( i ).fileName() ); copyDirectory( list.at( i ).absoluteFilePath(), dst + QDir::separator() + list.at( i ).fileName() ); } else { QFile::copy( srcDir.absolutePath() + QDir::separator() + list.at( i ).fileName(), dst + QDir::separator() + list.at( i ).fileName() ); } } } void SetupTest::createTempEnvironment() { const QDir tmpDir( basePath() ); const QString testRunnerKdeHomeDir = QLatin1String( "kdehome" ); const QString testRunnerDataDir = QLatin1String( "data" ); const QString testRunnerConfigDir = QLatin1String( "config" ); tmpDir.mkdir( testRunnerKdeHomeDir ); tmpDir.mkdir( testRunnerConfigDir ); tmpDir.mkdir( testRunnerDataDir ); const Config *config = Config::instance(); copyDirectory( config->kdeHome(), basePath() + testRunnerKdeHomeDir ); copyDirectory( config->xdgConfigHome(), basePath() + testRunnerConfigDir ); copyDirectory( config->xdgDataHome(), basePath() + testRunnerDataDir ); + + // copy syscoca file from the host to increase startup speed + const QString sycoca = KStandardDirs::locateLocal( "cache", "ksycoca4" ); + const QString cacheDir = basePath() + testRunnerKdeHomeDir + QDir::separator() + "cache-" + QHostInfo::localHostName() + QDir::separator(); + QFile::copy( sycoca, cacheDir + "ksycoca4" ); + QFile::copy( sycoca + "stamp", cacheDir + "ksycoca4stamp" ); } void SetupTest::deleteDirectory( const QString &dirName ) { Q_ASSERT( dirName.startsWith( QDir::tempPath() ) ); // just to be sure we don't run amok anywhere QDir dir( dirName ); dir.setFilter( QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot ); const QFileInfoList list = dir.entryInfoList(); for ( int i = 0; i < list.size(); ++i ) { if ( list.at( i ).isDir() && !list.at( i ).isSymLink() ) { deleteDirectory( list.at( i ).absoluteFilePath() ); const QDir tmpDir( list.at( i ).absoluteDir() ); tmpDir.rmdir( list.at( i ).fileName() ); } else { QFile::remove( list.at( i ).absoluteFilePath() ); } } dir.cdUp(); dir.rmdir( dirName ); } void SetupTest::cleanTempEnvironment() { deleteDirectory( basePath() ); } SetupTest::SetupTest() : mShuttingDown( false ), mSyncMapper( new QSignalMapper( this ) ), mAgentsCreated( false ) { clearEnvironment(); cleanTempEnvironment(); createTempEnvironment(); setenv( "KDEHOME", qPrintable( basePath() + "kdehome" ), 1 ); setenv( "XDG_DATA_HOME", qPrintable( basePath() + "data" ), 1 ); setenv( "XDG_CONFIG_HOME", qPrintable( basePath() + "config" ), 1 ); Symbols *symbol = Symbols::instance(); symbol->insertSymbol( "KDEHOME", basePath() + QLatin1String( "kdehome" ) ); symbol->insertSymbol( "XDG_DATA_HOME", basePath() + QLatin1String( "data" ) ); symbol->insertSymbol( "XDG_CONFIG_HOME", basePath() + QLatin1String( "config" ) ); symbol->insertSymbol( "AKONADI_TESTRUNNER_PID", QString::number( QCoreApplication::instance()->applicationPid() ) ); mDBusDaemonPid = startDBusDaemon(); #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 2)) const QString dbusAddress = symbol->symbols()[ QLatin1String( "DBUS_SESSION_BUS_ADDRESS" ) ]; registerWithInternalDBus( dbusAddress ); #endif mAkonadiDaemonProcess = new KProcess( this ); connect( mSyncMapper, SIGNAL(mapped(QString)), SLOT(resourceSynchronized(QString)) ); } SetupTest::~SetupTest() { cleanTempEnvironment(); delete mAkonadiDaemonProcess; } void SetupTest::shutdown() { if ( mShuttingDown ) return; mShuttingDown = true; // check first if the Akonadi server is still running, otherwise D-Bus auto-launch will actually start it here if ( mInternalBus->interface()->isServiceRegistered( "org.freedesktop.Akonadi.Control" ) ) { kDebug() << "Shutting down Akonadi control..."; QDBusInterface controlIface( QLatin1String( "org.freedesktop.Akonadi.Control" ), QLatin1String( "/ControlManager" ), QLatin1String( "org.freedesktop.Akonadi.ControlManager" ), *mInternalBus ); QDBusReply reply = controlIface.call( "shutdown" ); if ( !reply.isValid() ) { kWarning() << "Failed to shutdown Akonadi control: " << reply.error().message(); shutdownHarder(); } else { // safety timeout QTimer::singleShot( 30 * 1000, this, SLOT( shutdownHarder() ) ); } // in case we indirectly started KDE processes, stop those before we kill their D-Bus if ( mInternalBus->interface()->isServiceRegistered( "org.kde.klauncher" ) ) { QDBusInterface klauncherIface( QLatin1String( "org.kde.klauncher" ), QLatin1String( "/" ), QLatin1String( "org.kde.KLauncher" ), *mInternalBus ); QDBusReply reply = klauncherIface.call( "terminate_kdeinit" ); if ( !reply.isValid() ) kDebug() << reply.error(); } } else { shutdownHarder(); } } void SetupTest::shutdownHarder() { kDebug(); mShuttingDown = false; stopAkonadiDaemon(); stopDBusDaemon( mDBusDaemonPid ); QCoreApplication::instance()->quit(); } QString SetupTest::basePath() const { const QString tempDir = QString::fromLatin1( "akonadi_testrunner-%1" ) .arg( QCoreApplication::instance()->applicationPid() ); if ( !QDir::temp().exists( tempDir ) ) QDir::temp().mkdir( tempDir ); return QDir::tempPath() + QDir::separator() + tempDir + QDir::separator(); } diff --git a/gpgme++/CMakeLists.txt b/gpgme++/CMakeLists.txt index cd8962144..8ea999b99 100644 --- a/gpgme++/CMakeLists.txt +++ b/gpgme++/CMakeLists.txt @@ -1,140 +1,147 @@ project( gpgmepp ) +if (MINGW) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mms-bitfields") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mms-bitfields") +endif (MINGW) + 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 + assuanresult.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.2.0 ) +set( _gpgmepp_version 2.3.1 ) set( _gpgmepp_soversion 2 ) set( GPGMEPP_INCLUDE ${INCLUDE_INSTALL_DIR} ${GPGME_INCLUDES} ${Boost_INCLUDE_DIR} ) if ( GPGME_VANILLA_FOUND ) kde4_add_library( gpgmepp SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp ${GPGME_VANILLA_LIBRARIES} ) set_target_properties( gpgmepp PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++ ) get_target_property( GPGMEPP_VANILLA_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} COMPONENT Devel) endif ( GPGME_VANILLA_FOUND ) if ( GPGME_GLIB_FOUND ) kde4_add_library( gpgmepp-glib SHARED ${gpgme_LIB_SRCS} context_glib.cpp ) target_link_libraries( gpgmepp-glib ${GPGME_GLIB_LIBRARIES} ) set_target_properties( gpgmepp-glib PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-glib DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_GLIB_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-glib EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_GLIB_FOUND ) if ( GPGME_QT_FOUND ) kde4_add_library( gpgmepp-qt SHARED ${gpgme_LIB_SRCS} context_qt.cpp ) target_link_libraries( gpgmepp-qt ${GPGME_QT_LIBRARIES} ) if(WIN32) target_link_libraries( gpgmepp-qt ${GPGME_VANILLA_LIBRARIES} ) endif(WIN32) set_target_properties( gpgmepp-qt PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-qt DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_QT_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-qt EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_QT_FOUND ) if ( GPGME_PTHREAD_FOUND ) kde4_add_library( gpgmepp-pthread SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp-pthread ${GPGME_PTHREAD_LIBRARIES} ) set_target_properties( gpgmepp-pthread PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-pthread DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_PTHREAD_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-pthread EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_PTHREAD_FOUND ) if ( GPGME_PTH_FOUND ) kde4_add_library( gpgmepp-pth SHARED ${gpgme_LIB_SRCS} context_vanilla.cpp ) target_link_libraries( gpgmepp-pth ${GPGME_PTH_LIBRARIES} ) set_target_properties( gpgmepp-pth PROPERTIES VERSION ${_gpgmepp_version} SOVERSION ${_gpgmepp_soversion} OUTPUT_NAME gpgme++-pth DEFINE_SYMBOL MAKE_GPGME___LIB ) get_target_property( GPGMEPP_PTH_LIBRARY gpgmepp LOCATION ) install(TARGETS gpgmepp-pth EXPORT kdepimlibsLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS} ) endif ( GPGME_PTH_FOUND ) include( CMakeExportBuildSettings ) # this writes way too much, but do we care? EXPORT_LIBRARY_DEPENDENCIES( ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppLibraryDepends.cmake ) ########### install files ############### configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GpgmeppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppConfig.cmake @ONLY ) if ( GPGME_FOUND ) add_subdirectory( interfaces ) install(FILES global.h error.h exception.h context.h key.h trustitem.h eventloopinteractor.h editinteractor.h data.h gpgmefw.h result.h + assuanresult.h keylistresult.h keygenerationresult.h importresult.h decryptionresult.h verificationresult.h signingresult.h encryptionresult.h notation.h engineinfo.h gpgsetexpirytimeeditinteractor.h gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h gpgadduserideditinteractor.h gpgme++_export.h DESTINATION ${INCLUDE_INSTALL_DIR}/gpgme++ COMPONENT Devel ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/GpgmeppLibraryDepends.cmake DESTINATION ${LIB_INSTALL_DIR}/gpgmepp ) endif ( GPGME_FOUND ) diff --git a/gpgme++/ConfigureChecks.cmake b/gpgme++/ConfigureChecks.cmake index f7a7bcfd8..74cae3415 100644 --- a/gpgme++/ConfigureChecks.cmake +++ b/gpgme++/ConfigureChecks.cmake @@ -1,335 +1,346 @@ # gpgme configure checks include(CheckFunctionExists) if ( GPGME_FOUND ) set(CMAKE_REQUIRED_INCLUDES ${GPGME_INCLUDES}) set(CMAKE_REQUIRED_LIBRARIES) foreach( _FLAVOUR VANILLA PTHREAD QT PTH GLIB ) if ( NOT CMAKE_REQUIRED_LIBRARIES ) if ( GPGME_${_FLAVOUR}_FOUND ) set(CMAKE_REQUIRED_LIBRARIES ${GPGME_VANILLA_LIBRARIES}) endif( GPGME_${_FLAVOUR}_FOUND ) endif( NOT CMAKE_REQUIRED_LIBRARIES ) endforeach( _FLAVOUR ) # check if gpgme has gpgme_data_{get,set}_file_name (new in 1.1.0) check_cxx_source_compiles (" #include int main() { gpgme_data_t data = 0; const char * filename = 0; const gpgme_error_t err = gpgme_data_set_file_name( data, filename ); char * filename2 = gpgme_data_get_file_name( data ); (void)filename2; (void)err; return 0; } " HAVE_GPGME_DATA_SET_FILE_NAME ) # check if gpgme has GPGME_INCLUDE_CERTS_DEFAULT check_cxx_source_compiles (" #include int main() { int i = GPGME_INCLUDE_CERTS_DEFAULT; return 0; } " HAVE_GPGME_INCLUDE_CERTS_DEFAULT ) # check if gpgme has GPGME_KEYLIST_MODE_SIG_NOTATIONS check_cxx_source_compiles (" #include int main() { gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_SIG_NOTATIONS; return 0; } " HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS ) # check if gpgme_key_sig_t has notations check_cxx_source_compiles (" #include int main() { gpgme_key_sig_t key_sig = 0; gpgme_sig_notation_t notation = key_sig->notations; return 0; } " HAVE_GPGME_KEY_SIG_NOTATIONS ) # check if gpgme has gpgme_key_t->is_qualified check_cxx_source_compiles (" #include void test(gpgme_key_t& key) { unsigned int iq; iq = key->is_qualified; } int main() { return 0; } " HAVE_GPGME_KEY_T_IS_QUALIFIED ) # check if gpgme has gpgme_sig_notation_t->critical check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; unsigned int cr1 = sig_notation->critical; unsigned int cr2 = GPGME_SIG_NOTATION_CRITICAL; return 0; } " HAVE_GPGME_SIG_NOTATION_CRITICAL ) # check if gpgme has gpgme_sig_notation_t->flags check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; gpgme_sig_notation_flags_t f = sig_notation->flags; return 0; } " HAVE_GPGME_SIG_NOTATION_FLAGS_T ) # check if gpgme has gpgme_sig_notation_t->human_readable check_cxx_source_compiles (" #include int main() { gpgme_sig_notation_t sig_notation = 0; unsigned int cr1 = sig_notation->human_readable; unsigned int cr2 = GPGME_SIG_NOTATION_HUMAN_READABLE; return 0; } " HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE ) # check if gpgme has gpgme_subkey_t->is_qualified check_cxx_source_compiles (" #include void test(gpgme_subkey_t& subkey) { unsigned int iq; iq = subkey->is_qualified; } int main() { return 0; } " HAVE_GPGME_SUBKEY_T_IS_QUALIFIED ) # check if gpgme has gpgme_engine_info_t->home_dir check_cxx_source_compiles (" #include int main() { gpgme_engine_info_t ei = 0; const char * hd = ei->home_dir; return 0; } " HAVE_GPGME_ENGINE_INFO_T_HOME_DIR ) #check if gpgme has gpgme_ctx_{get,set}_engine_info() check_cxx_source_compiles (" #include int main() { gpgme_ctx_t ctx = 0; const gpgme_engine_info_t ei = gpgme_ctx_get_engine_info( ctx ); const char * filename = 0; const char * home_dir = 0; const gpgme_error_t e = gpgme_ctx_set_engine_info( ctx, GPGME_PROTOCOL_OpenPGP, filename, home_dir ); return 0; } " HAVE_GPGME_CTX_GETSET_ENGINE_INFO ) # missing, but not needed yet (only for edit interaction) #+ GPGME_STATUS_SIG_SUBPACKET, #+ GPGME_STATUS_NEED_PASSPHRASE_PIN, #+ GPGME_STATUS_SC_OP_FAILURE, #+ GPGME_STATUS_SC_OP_SUCCESS, #+ GPGME_STATUS_CARDCTRL, #+ GPGME_STATUS_BACKUP_KEY_CREATED, #+ GPGME_STATUS_PKA_TRUST_BAD, #+ GPGME_STATUS_PKA_TRUST_GOOD, #+ #+ GPGME_STATUS_PLAINTEXT # check if gpgme has gpgme_sig_notation_{clear,add,get} check_cxx_source_compiles (" #include int main() { gpgme_ctx_t ctx = 0; const gpgme_sig_notation_t nota = gpgme_sig_notation_get( ctx ); const char * const name = 0; const char * const value = 0; const gpgme_sig_notation_flags_t flags = 0; const gpgme_error_t err = gpgme_sig_notation_add( ctx, name, value, flags ); gpgme_sig_notation_clear( ctx ); return 0; } " HAVE_GPGME_SIG_NOTATION_CLEARADDGET ) # check if gpgme has gpgme_decrypt_result_t->file_name check_cxx_source_compiles (" #include int main() { gpgme_decrypt_result_t res = 0; const char * const fn = res->file_name; (void)fn; } " HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME ) # check if gpgme has gpgme_recipient_t and gpgme_decrypt_result_t->recipients check_cxx_source_compiles (" #include int main() { gpgme_decrypt_result_t res = 0; gpgme_recipient_t r = res->recipients; const char * kid = r->keyid; r = r->next; const gpgme_pubkey_algo_t algo = r->pubkey_algo; const gpgme_error_t err = r->status; return 0; } " HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS ) # check if gpgme has gpgme_verify_result_t->file_name check_cxx_source_compiles (" #include int main() { gpgme_verify_result_t res = 0; const char * fn = res->file_name; (void)fn; return 0; } " HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME ) # check if gpgme has gpgme_signature_t->pka_{trust,address} check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; unsigned int pkat = sig->pka_trust; const char * pkaa = sig->pka_address; return 0; } " HAVE_GPGME_SIGNATURE_T_PKA_FIELDS ) # check if gpgme has gpgme_signature_t->{hash,pubkey}_algo check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; gpgme_pubkey_algo_t pk = sig->pubkey_algo; gpgme_hash_algo_t h = sig->hash_algo; return 0; } " HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS ) # check if gpgme has gpgme_signature_t->chain_model check_cxx_source_compiles (" #include int main() { gpgme_signature_t sig = 0; unsigned int cm = sig->chain_model; return 0; } " HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL ) # check if gpgme has gpgme_get_fdptr check_function_exists( "gpgme_get_fdptr" HAVE_GPGME_GET_FDPTR ) # check if gpgme has gpgme_op_getauditlog check_function_exists ("gpgme_op_getauditlog" HAVE_GPGME_OP_GETAUDITLOG ) # check if gpgme has GPGME_PROTOCOL_GPGCONF check_cxx_source_compiles (" #include int main() { gpgme_protocol_t proto = GPGME_PROTOCOL_GPGCONF; return 0; } " HAVE_GPGME_PROTOCOL_GPGCONF ) # check if gpgme has gpgme_cancel_async check_function_exists ("gpgme_cancel_async" HAVE_GPGME_CANCEL_ASYNC ) # check if gpg-error has GPG_ERR_NO_PASSPHRASE check_cxx_source_compiles (" #include int main() { gpg_error_t err = GPG_ERR_NO_PASSPHRASE; return 0; } " HAVE_GPG_ERR_NO_PASSPHRASE ) # check if gpg-error has GPG_ERR_ALREADY_SIGNED check_cxx_source_compiles (" #include int main() { gpg_error_t err = GPG_ERR_ALREADY_SIGNED; return 0; } " HAVE_GPG_ERR_ALREADY_SIGNED ) # check if gpgme has GPGME_ENCRYPT_NO_ENCRYPT_TO check_cxx_source_compiles (" #include int main() { gpgme_encrypt_flags_t f = GPGME_ENCRYPT_NO_ENCRYPT_TO; return 0; } " HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO ) # check if gpgme has gpgme_subkey_t->is_cardkey and ->card_number check_cxx_source_compiles (" #include int main() { gpgme_subkey_t sk = 0; const char * card_number = sk->card_number; const unsigned int is_cardkey = sk->is_cardkey; return 0; } " HAVE_GPGME_SUBKEY_T_IS_CARDKEY ) # check if gpgme has assuan protocol support check_cxx_source_compiles (" #include static gpgme_error_t data_cb(void *, const void *, size_t) { return 0; } static gpgme_error_t inquire_cb(void *, const char *, const char *, gpgme_data_t *) { return 0; } static gpgme_error_t status_cb(void *, const char *, const char *) { return 0; } int main() { const gpgme_protocol_t proto = GPGME_PROTOCOL_ASSUAN; gpgme_ctx_t ctx = 0; gpgme_assuan_data_cb_t d = data_cb; gpgme_assuan_inquire_cb_t i = inquire_cb; gpgme_assuan_status_cb_t s = status_cb; gpgme_assuan_result_t r = gpgme_op_assuan_result( ctx ); void * opaque = 0; gpgme_error_t err = gpgme_op_assuan_transact_start( ctx, \"FOO\", d, opaque, i, opaque, s, opaque ); err = gpgme_op_assuan_transact( ctx, \"FOO\", d, opaque, i, opaque, s, opaque ); return 0; } " HAVE_GPGME_ASSUAN_ENGINE ) check_cxx_source_compiles (" #include int main() { gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_EPHEMERAL; return 0; } " HAVE_GPGME_KEYLIST_MODE_EPHEMERAL ) +# check if gpgme has import-from-keyserver support +check_cxx_source_compiles (" + #include + int main() { + gpgme_ctx_t ctx = 0; + gpgme_key_t keys[2] = { 0, 0 }; + const gpgme_error_t err = gpgme_op_import_keys( ctx, keys ); + return err ? 1 : 0 ; + } +" HAVE_GPGME_OP_IMPORT_KEYS ) + set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_LIBRARIES) endif( GPGME_FOUND ) diff --git a/gpgme++/assuanresult.cpp b/gpgme++/assuanresult.cpp new file mode 100644 index 000000000..bc144d8e3 --- /dev/null +++ b/gpgme++/assuanresult.cpp @@ -0,0 +1,90 @@ +/* + assuanresult.cpp - wraps a gpgme assuan result + Copyright (C) 2009 Klarälvdalens Datakonsult AB + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include "result_p.h" + +#include + +#include + +using namespace GpgME; + +#ifdef HAVE_GPGME_ASSUAN_ENGINE +class AssuanResult::Private { +public: + explicit Private( const gpgme_assuan_result_t r ) { + if ( !r ) + return; + error = r->err; + } + + gpgme_error_t error; +}; +#endif + +AssuanResult::AssuanResult( gpgme_ctx_t ctx, int error ) + : Result( error ), d() +{ + init( ctx ); +} + +AssuanResult::AssuanResult( gpgme_ctx_t ctx, const Error & error ) + : Result( error ), d() +{ + init( ctx ); +} + +void AssuanResult::init( gpgme_ctx_t ctx ) { + (void)ctx; +#ifdef HAVE_GPGME_ASSUAN_ENGINE + if ( !ctx ) + return; + gpgme_assuan_result_t res = gpgme_op_assuan_result( ctx ); + if ( !res ) + return; + d.reset( new Private( res ) ); +#endif +} + +make_standard_stuff(AssuanResult) + +Error AssuanResult::assuanError() const { +#ifdef HAVE_GPGME_ASSUAN_ENGINE + if ( d ) + return Error( d->error ); +#endif + return Error(); +} + +std::ostream & GpgME::operator<<( std::ostream & os, const AssuanResult & result ) { + os << "GpgME::AssuanResult("; + if ( !result.isNull() ) { + os << "\n error: " << result.error() + << "\n assuanError: " << result.assuanError() + << "\n"; + } + return os << ')'; +} + diff --git a/gpgme++/assuanresult.h b/gpgme++/assuanresult.h new file mode 100644 index 000000000..dfe247db1 --- /dev/null +++ b/gpgme++/assuanresult.h @@ -0,0 +1,76 @@ +/* + assuanresult.h - wraps a gpgme assuan result + Copyright (C) 2009 Klarälvdalens Datakonsult AB + Author: Marc Mutz + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_ASSUANRESULT_H__ +#define __GPGMEPP_ASSUANRESULT_H__ + +#include +#include +#include + +#include + +#include + +#include +#include + +namespace GpgME { + + class Error; + + class GPGMEPP_EXPORT AssuanResult : public Result { + public: + AssuanResult(); + AssuanResult( gpgme_ctx_t ctx, int error ); + AssuanResult( gpgme_ctx_t ctx, const Error & error ); + explicit AssuanResult( const Error & err ); + + const AssuanResult & operator=( AssuanResult other ) { + swap( other ); + return *this; + } + + void swap( AssuanResult & other ) { + Result::swap( other ); + using std::swap; + swap( this->d, other.d ); + } + + bool isNull() const; + + Error assuanError() const; + + class Private; + private: + void init( gpgme_ctx_t ctx ); + boost::shared_ptr d; + }; + + GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, const AssuanResult & result ); + +} + +GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( AssuanResult ) + +#endif // __GPGMEPP_ASSUANRESULT_H__ diff --git a/gpgme++/config-gpgme++.h.cmake b/gpgme++/config-gpgme++.h.cmake index 9490138d0..95b0ff06c 100644 --- a/gpgme++/config-gpgme++.h.cmake +++ b/gpgme++/config-gpgme++.h.cmake @@ -1,88 +1,91 @@ /* Define to 1 if your gpgme has the gpgme_data_{set,get}_file_name functions */ #cmakedefine HAVE_GPGME_DATA_SET_FILE_NAME 1 /* Define to 1 if your gpgme has the GPGME_INCLUDE_CERTS_DEFAULT macro */ #cmakedefine HAVE_GPGME_INCLUDE_CERTS_DEFAULT 1 /* Define to 1 if your gpgme has the GPGME_KEYLIST_MODE_SIG_NOTATIONS macro */ #cmakedefine HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS /* Define to 1 if your gpgme's gpgme_key_sig_t has the notations member */ #cmakedefine HAVE_GPGME_KEY_SIG_NOTATIONS /* Define to 1 if your gpgme's gpgme_key_t has the is_qualified flag */ #cmakedefine HAVE_GPGME_KEY_T_IS_QUALIFIED 1 /* Define to 1 if your gpgme's gpgme_sig_notation_t has the critical flag */ #cmakedefine HAVE_GPGME_SIG_NOTATION_CRITICAL /* Define to 1 if your gpgme's gpgme_sig_notation_t has the flags member */ #cmakedefine HAVE_GPGME_SIG_NOTATION_FLAGS_T /* Define to 1 if your gpgme's gpgme_sig_notation_t has the human_readable flag */ #cmakedefine HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE /* Define to 1 if your gpgme's gpgme_subkey_t has the is_qualified flag */ #cmakedefine HAVE_GPGME_SUBKEY_T_IS_QUALIFIED 1 /* Define to 1 if your gpgme's gpgme_engine_info_t has the home_dir member */ #cmakedefine HAVE_GPGME_ENGINE_INFO_T_HOME_DIR 1 /* Define to 1 if your gpgme has the gpgme_ctx_{get,set}_engine_info() functions */ #cmakedefine HAVE_GPGME_CTX_GETSET_ENGINE_INFO 1 /* Define to 1 if your gpgme has the gpgme_sig_notation_{clear,add,get}() functions */ #cmakedefine HAVE_GPGME_SIG_NOTATION_CLEARADDGET 1 /* Define to 1 if your gpgme's gpgme_decrypt_result_t has the file_name member */ #cmakedefine HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME 1 /* Define to 1 if your gpgme's gpgme_decrypt_result_t has the recipients member */ #cmakedefine HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS 1 /* Define to 1 if your gpgme's gpgme_verify_result_t has the file_name member */ #cmakedefine HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME 1 /* Define to 1 if your gpgme's gpgme_signature_t has the pka_{trust,address} fields */ #cmakedefine HAVE_GPGME_SIGNATURE_T_PKA_FIELDS 1 /* Define to 1 if your gpgme's gpgme_signature_t has the {hash,pubkey}_algo fields */ #cmakedefine HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS 1 /* Define to 1 if your gpgme has gpgme_get_fdptr (it won't be in gpgme.h, though!) */ #cmakedefine HAVE_GPGME_GET_FDPTR 1 /* Define to 1 if your gpgme has the gpgme_op_getauditlog function */ #cmakedefine HAVE_GPGME_OP_GETAUDITLOG 1 /* Define to 1 if your gpgme has GPGME_PROTOCOL_GPGCONF */ #cmakedefine HAVE_GPGME_PROTOCOL_GPGCONF 1 /* Define to 1 if your gpgme has gpgme_cancel_async */ #cmakedefine HAVE_GPGME_CANCEL_ASYNC 1 /* Define to 1 if your gpg-error has GPG_ERR_NO_PASSPHRASE */ #cmakedefine HAVE_GPG_ERR_NO_PASSPHRASE 1 /* Define to 1 if your gpg-error has GPG_ERR_ALREADY_SIGNED */ #cmakedefine HAVE_GPG_ERR_ALREADY_SIGNED 1 #ifndef HAVE_GPG_ERR_NO_PASSPHRASE # define GPG_ERR_NO_PASSPHRASE GPG_ERR_INV_PASSPHRASE #endif #ifndef HAVE_GPG_ERR_ALREADY_SIGNED # define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1 #endif /* Define to 1 if your gpgme has GPGME_ENCRYPT_NO_ENCRYPT_TO */ #cmakedefine HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO 1 /* Define to 1 if your gpgme has gpgme_subkey_t->card_number and gpgme_subkey_t->is_cardkey */ #cmakedefine HAVE_GPGME_SUBKEY_T_IS_CARDKEY /* Define to 1 if your gpgme has ASSUAN protocol support (in the interface, not only in the implementation */ #cmakedefine HAVE_GPGME_ASSUAN_ENGINE /* Define to 1 if your gpgme has GPGME_KEYLIST_MODE_EPHEMERAL */ #cmakedefine HAVE_GPGME_KEYLIST_MODE_EPHEMERAL + +/* Define to 1 if your gpgme has gpgme_op_import_keys */ +#cmakedefine HAVE_GPGME_OP_IMPORT_KEYS diff --git a/gpgme++/context.cpp b/gpgme++/context.cpp index 41510f089..dabdd1f1d 100644 --- a/gpgme++/context.cpp +++ b/gpgme++/context.cpp @@ -1,1090 +1,1243 @@ /* 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 +#include + #include "callbacks.h" #include "data_p.h" #include "context_p.h" #include "util.h" #include +#include + #include #ifndef NDEBUG #include using std::cerr; using std::endl; #endif #include namespace GpgME { + void initializeLibrary() { + gpgme_check_version( 0 ); + } + 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 ), + lastAssuanInquireData( Data::null ), + lastAssuanTransaction(), lastEditInteractor(), lastCardEditInteractor() { } Context::Private::~Private() { if ( ctx ) gpgme_release( ctx ); ctx = 0; delete iocbs; } // // // Context attributes: // // Protocol Context::protocol() const { gpgme_protocol_t p = gpgme_get_protocol( d->ctx ); switch ( p ) { case GPGME_PROTOCOL_OpenPGP: return OpenPGP; case GPGME_PROTOCOL_CMS: return CMS; default: return UnknownProtocol; } } void Context::setArmor( bool useArmor ) { gpgme_set_armor( d->ctx, int( useArmor ) ); } bool Context::armor() const { return gpgme_get_armor( d->ctx ); } void Context::setTextMode( bool useTextMode ) { gpgme_set_textmode( d->ctx, int( useTextMode ) ); } bool Context::textMode() const { return gpgme_get_textmode( d->ctx ); } void Context::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) ); } + ImportResult Context::importKeys( const std::vector & kk ) { + d->lastop = Private::Import; + d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ); + bool shouldHaveResult = false; +#ifdef HAVE_GPGME_OP_IMPORT_KEYS + const boost::scoped_array keys( new gpgme_key_t[ kk.size() + 1 ] ); + gpgme_key_t * keys_it = &keys[0]; + for ( std::vector::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it ) + if ( it->impl() ) + *keys_it++ = it->impl(); + *keys_it++ = 0; + d->lasterr = gpgme_op_import_keys( d->ctx, keys.get() ); + shouldHaveResult = true; +#endif + if ( ( gpgme_err_code( d->lasterr ) == GPG_ERR_NOT_IMPLEMENTED || + gpgme_err_code( d->lasterr ) == GPG_ERR_NOT_SUPPORTED ) && + protocol() == CMS ) + { + // ok, try the workaround (export+import): + std::vector fprs; + for ( std::vector::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it ) { + if ( const char * fpr = it->primaryFingerprint() ) { + if ( *fpr ) + fprs.push_back( fpr ); + } else if ( const char * keyid = it->keyID() ) { + if ( *keyid ) + fprs.push_back( keyid ); + } + } + fprs.push_back( 0 ); + Data data; + Data::Private * const dp = data.impl(); + const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode( d->ctx ); + gpgme_set_keylist_mode( d->ctx, GPGME_KEYLIST_MODE_EXTERN ); + d->lasterr = gpgme_op_export_ext( d->ctx, &fprs[0], 0, dp ? dp->data : 0 ); + gpgme_set_keylist_mode( d->ctx, oldMode ); + if ( !d->lasterr ) { + data.seek( 0, SEEK_SET ); + d->lasterr = gpgme_op_import( d->ctx, dp ? dp->data : 0 ); + shouldHaveResult = true; + } + } + if ( shouldHaveResult ) + return ImportResult( d->ctx, Error(d->lasterr) ); + else + return ImportResult( Error( d->lasterr ) ); + } + Error Context::startKeyImport( const Data & data ) { d->lastop = Private::Import; const Data::Private * const dp = data.impl(); return Error( d->lasterr = gpgme_op_import_start( d->ctx, dp ? dp->data : 0 ) ); } + Error Context::startKeyImport( const std::vector & kk ) { + d->lastop = Private::Import; +#ifdef HAVE_GPGME_OP_IMPORT_KEYS + const boost::scoped_array keys( new gpgme_key_t[ kk.size() + 1 ] ); + gpgme_key_t * keys_it = &keys[0]; + for ( std::vector::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it ) + if ( it->impl() ) + *keys_it++ = it->impl(); + *keys_it++ = 0; + return Error( d->lasterr = gpgme_op_import_keys_start( d->ctx, keys.get() ) ); +#else + (void)kk; + return Error( d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ); +#endif + } + ImportResult Context::importResult() const { if ( d->lastop & Private::Import ) return ImportResult( d->ctx, Error(d->lasterr) ); else return ImportResult(); } Error Context::deleteKey( const Key & key, bool allowSecretKeyDeletion ) { d->lastop = Private::Delete; return Error( d->lasterr = gpgme_op_delete( d->ctx, key.impl(), int( allowSecretKeyDeletion ) ) ); } Error Context::startKeyDeletion( const Key & key, bool allowSecretKeyDeletion ) { d->lastop = Private::Delete; return Error( d->lasterr = gpgme_op_delete_start( d->ctx, key.impl(), int( allowSecretKeyDeletion ) ) ); } Error Context::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 ) ); } +#ifdef HAVE_GPGME_ASSUAN_ENGINE + static gpgme_error_t assuan_transaction_data_callback( void * opaque, const void * data, size_t datalen ) { + assert( opaque ); + AssuanTransaction * t = static_cast( opaque ); + return t->data( data, datalen ).encodedError(); + } + + static gpgme_error_t assuan_transaction_inquire_callback( void * opaque, const char * name, const char * args, gpgme_data_t * r_data ) { + assert( opaque ); + Context::Private * p = static_cast( opaque ); + AssuanTransaction * t = p->lastAssuanTransaction.get(); + assert( t ); + Error err; + if ( name ) + p->lastAssuanInquireData = t->inquire( name, args, err ); + else + p->lastAssuanInquireData = Data::null; + if ( !p->lastAssuanInquireData.isNull() ) + *r_data = p->lastAssuanInquireData.impl()->data; + return err.encodedError(); + } + + static gpgme_error_t assuan_transaction_status_callback( void * opaque, const char * status, const char * args ) { + assert( opaque ); + AssuanTransaction * t = static_cast( opaque ); + return t->status( status, args ).encodedError(); + } +#endif + + AssuanResult Context::assuanTransact( const char * command, std::auto_ptr transaction ) { + d->lastop = Private::AssuanTransact; + d->lastAssuanTransaction = transaction; +#ifdef HAVE_GPGME_ASSUAN_ENGINE + d->lasterr = gpgme_op_assuan_transact( d->ctx, command, + d->lastAssuanTransaction.get() ? assuan_transaction_data_callback : 0, + d->lastAssuanTransaction.get(), + d->lastAssuanTransaction.get() ? assuan_transaction_inquire_callback : 0, + d->lastAssuanTransaction.get() ? d : 0, // sic! + d->lastAssuanTransaction.get() ? assuan_transaction_status_callback : 0, + d->lastAssuanTransaction.get() ); +#else + (void)command; + d->lasterr = gpg_error( GPG_ERR_NOT_SUPPORTED ); +#endif + return AssuanResult( d->ctx, d->lasterr ); + } + + Error Context::startAssuanTransaction( const char * command, std::auto_ptr transaction ) { + d->lastop = Private::AssuanTransact; + d->lastAssuanTransaction = transaction; +#ifdef HAVE_GPGME_ASSUAN_ENGINE + return Error( d->lasterr = gpgme_op_assuan_transact_start( d->ctx, command, + d->lastAssuanTransaction.get() ? assuan_transaction_data_callback : 0, + d->lastAssuanTransaction.get(), + d->lastAssuanTransaction.get() ? assuan_transaction_inquire_callback : 0, + d->lastAssuanTransaction.get() ? d : 0, // sic! + d->lastAssuanTransaction.get() ? assuan_transaction_status_callback : 0, + d->lastAssuanTransaction.get() ) ); +#else + (void)command; + return Error( d->lasterr = gpg_error( GPG_ERR_NOT_SUPPORTED ) ); +#endif + } + + AssuanResult Context::assuanResult() const { + if ( d->lastop & Private::AssuanTransact ) + return AssuanResult( d->ctx, d->lasterr ); + else + return AssuanResult(); + } + + AssuanTransaction * Context::lastAssuanTransaction() const { + return d->lastAssuanTransaction.get(); + } + DecryptionResult Context::decrypt( const Data & cipherText, Data & plainText ) { d->lastop = Private::Decrypt; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); d->lasterr = gpgme_op_decrypt( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ); return DecryptionResult( d->ctx, Error(d->lasterr) ); } Error Context::startDecryption( const Data & cipherText, Data & plainText ) { d->lastop = Private::Decrypt; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); return Error( d->lasterr = gpgme_op_decrypt_start( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ) ); } DecryptionResult Context::decryptionResult() const { if ( d->lastop & Private::Decrypt ) return DecryptionResult( d->ctx, Error(d->lasterr) ); else return DecryptionResult(); } VerificationResult Context::verifyDetachedSignature( const Data & signature, const Data & signedText ) { d->lastop = Private::Verify; const Data::Private * const sdp = signature.impl(); const Data::Private * const tdp = signedText.impl(); d->lasterr = gpgme_op_verify( d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0 ); return VerificationResult( d->ctx, Error(d->lasterr) ); } VerificationResult Context::verifyOpaqueSignature( const Data & signedData, Data & plainText ) { d->lastop = Private::Verify; const Data::Private * const sdp = signedData.impl(); Data::Private * const pdp = plainText.impl(); d->lasterr = gpgme_op_verify( d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0 ); return VerificationResult( d->ctx, Error(d->lasterr) ); } Error Context::startDetachedSignatureVerification( const Data & signature, const Data & signedText ) { d->lastop = Private::Verify; const Data::Private * const sdp = signature.impl(); const Data::Private * const tdp = signedText.impl(); return Error( d->lasterr = gpgme_op_verify_start( d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0 ) ); } Error Context::startOpaqueSignatureVerification( const Data & signedData, Data & plainText ) { d->lastop = Private::Verify; const Data::Private * const sdp = signedData.impl(); Data::Private * const pdp = plainText.impl(); return Error( d->lasterr = gpgme_op_verify_start( d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0 ) ); } VerificationResult Context::verificationResult() const { if ( d->lastop & Private::Verify ) return VerificationResult( d->ctx, Error(d->lasterr) ); else return VerificationResult(); } std::pair Context::decryptAndVerify( const Data & cipherText, Data & plainText ) { d->lastop = Private::DecryptAndVerify; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); d->lasterr = gpgme_op_decrypt_verify( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ); return std::make_pair( DecryptionResult( d->ctx, Error(d->lasterr) ), VerificationResult( d->ctx, Error(d->lasterr) ) ); } Error Context::startCombinedDecryptionAndVerification( const Data & cipherText, Data & plainText ) { d->lastop = Private::DecryptAndVerify; const Data::Private * const cdp = cipherText.impl(); Data::Private * const pdp = plainText.impl(); return Error( d->lasterr = gpgme_op_decrypt_verify_start( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ) ); } #ifdef HAVE_GPGME_OP_GETAUDITLOG unsigned int to_auditlog_flags( unsigned int flags ) { unsigned int result = 0; if ( flags & Context::HtmlAuditLog ) result |= GPGME_AUDITLOG_HTML; if ( flags & Context::AuditLogWithHelp ) result |= GPGME_AUDITLOG_WITH_HELP; return result; } #endif // HAVE_GPGME_OP_GETAUDITLOG Error Context::startGetAuditLog( Data & output, unsigned int flags ) { d->lastop = Private::GetAuditLog; #ifdef HAVE_GPGME_OP_GETAUDITLOG Data::Private * const odp = output.impl(); return Error( d->lasterr = gpgme_op_getauditlog_start( d->ctx, odp ? odp->data : 0, to_auditlog_flags( flags ) ) ); #else (void)output; (void)flags; return Error( d->lasterr = makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } Error Context::getAuditLog( Data & output, unsigned int flags ) { d->lastop = Private::GetAuditLog; #ifdef HAVE_GPGME_OP_GETAUDITLOG Data::Private * const odp = output.impl(); return Error( d->lasterr = gpgme_op_getauditlog( d->ctx, odp ? odp->data : 0, to_auditlog_flags( flags ) ) ); #else (void)output; (void)flags; return Error( d->lasterr = makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } void Context::clearSigningKeys() { gpgme_signers_clear( d->ctx ); } Error Context::addSigningKey( const Key & key ) { return Error( d->lasterr = gpgme_signers_add( d->ctx, key.impl() ) ); } Key Context::signingKey( unsigned int idx ) const { gpgme_key_t key = gpgme_signers_enum( d->ctx, idx ); return Key( key, false ); } std::vector Context::signingKeys() const { std::vector result; gpgme_key_t key; for ( unsigned int i = 0 ; ( key = gpgme_signers_enum( d->ctx, i ) ) ; ++i ) result.push_back( Key( key, false ) ); return result; } void Context::clearSignatureNotations() { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET gpgme_sig_notation_clear( d->ctx ); #endif } GpgME::Error Context::addSignatureNotation( const char * name, const char * value, unsigned int flags ) { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET return Error( gpgme_sig_notation_add( d->ctx, name, value, add_to_gpgme_sig_notation_flags_t( 0, flags ) ) ); #else (void)name; (void)value; (void)flags; return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } GpgME::Error Context::addSignaturePolicyURL( const char * url, bool critical ) { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET return Error( gpgme_sig_notation_add( d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0 ) ); #else (void)url; (void)critical; return Error( makeError( GPG_ERR_NOT_IMPLEMENTED ) ); #endif } const char * Context::signaturePolicyURL() const { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( !n->name ) return n->value; #endif return 0; } Notation Context::signatureNotation( unsigned int idx ) const { #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( n->name ) if ( idx-- == 0 ) return Notation( n ); #endif return Notation(); } std::vector Context::signatureNotations() const { std::vector result; #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET for ( gpgme_sig_notation_t n = gpgme_sig_notation_get( d->ctx ) ; n ; n = n->next ) if ( n->name ) result.push_back( Notation( n ) ); #endif return result; } static gpgme_sig_mode_t sigmode2sigmode( SignatureMode mode ) { switch ( mode ) { default: case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL; case Detached: return GPGME_SIG_MODE_DETACH; case Clearsigned: return GPGME_SIG_MODE_CLEAR; } } SigningResult Context::sign( const Data & plainText, Data & signature, SignatureMode mode ) { d->lastop = Private::Sign; const Data::Private * const pdp = plainText.impl(); Data::Private * const sdp = signature.impl(); d->lasterr = gpgme_op_sign( d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode( mode ) ); return SigningResult( d->ctx, Error(d->lasterr) ); } Error Context::startSigning( const Data & plainText, Data & signature, SignatureMode mode ) { d->lastop = Private::Sign; const Data::Private * const pdp = plainText.impl(); Data::Private * const sdp = signature.impl(); return Error( d->lasterr = gpgme_op_sign_start( d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode( mode ) ) ); } SigningResult Context::signingResult() const { if ( d->lastop & Private::Sign ) return SigningResult( d->ctx, Error(d->lasterr) ); else return SigningResult(); } static gpgme_encrypt_flags_t encryptflags2encryptflags( Context::EncryptionFlags flags ) { unsigned int result = 0; if ( flags & Context::AlwaysTrust ) result |= GPGME_ENCRYPT_ALWAYS_TRUST; #ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO if ( flags & Context::NoEncryptTo ) result |= GPGME_ENCRYPT_NO_ENCRYPT_TO; #endif return static_cast( result ); } EncryptionResult Context::encrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::Encrypt; #ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO if ( flags & NoEncryptTo ) return EncryptionResult( Error( d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ) ); #endif const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return EncryptionResult( d->ctx, Error(d->lasterr) ); } Error Context::encryptSymmetrically( const Data & plainText, Data & cipherText ) { d->lastop = Private::Encrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); return Error( d->lasterr = gpgme_op_encrypt( d->ctx, 0, (gpgme_encrypt_flags_t)0, pdp ? pdp->data : 0, cdp ? cdp->data : 0 ) ); } Error Context::startEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::Encrypt; #ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO if ( flags & NoEncryptTo ) return Error( d->lasterr = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ); #endif const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_start( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return Error( d->lasterr ); } EncryptionResult Context::encryptionResult() const { if ( d->lastop & Private::Encrypt ) return EncryptionResult( d->ctx, Error(d->lasterr) ); else return EncryptionResult(); } std::pair Context::signAndEncrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::SignAndEncrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_sign( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return std::make_pair( SigningResult( d->ctx, Error(d->lasterr) ), EncryptionResult( d->ctx, Error(d->lasterr) ) ); } Error Context::startCombinedSigningAndEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { d->lastop = Private::SignAndEncrypt; const Data::Private * const pdp = plainText.impl(); Data::Private * const cdp = cipherText.impl(); gpgme_key_t * const keys = new gpgme_key_t[ recipients.size() + 1 ]; gpgme_key_t * keys_it = keys; for ( std::vector::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) if ( it->impl() ) *keys_it++ = it->impl(); *keys_it++ = 0; d->lasterr = gpgme_op_encrypt_sign_start( d->ctx, keys, encryptflags2encryptflags( flags ), pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); delete[] keys; return Error( d->lasterr ); } Error Context::cancelPendingOperation() { #ifdef HAVE_GPGME_CANCEL_ASYNC return Error( gpgme_cancel_async( d->ctx ) ); #else return Error( gpgme_cancel( d->ctx ) ); #endif } bool Context::poll() { gpgme_error_t e = GPG_ERR_NO_ERROR; const bool finished = gpgme_wait( d->ctx, &e, 0 ); if ( finished ) d->lasterr = e; return finished; } Error Context::wait() { gpgme_error_t e = GPG_ERR_NO_ERROR; gpgme_wait( d->ctx, &e, 1 ); return Error( d->lasterr = e ); } Error Context::lastError() const { return Error( d->lasterr ); } std::ostream & operator<<( std::ostream & os, Protocol proto ) { os << "GpgME::Protocol("; switch ( proto ) { case OpenPGP: os << "OpenPGP"; break; case CMS: os << "CMS"; break; default: case UnknownProtocol: os << "UnknownProtocol"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Engine eng ) { os << "GpgME::Engine("; switch ( eng ) { case GpgEngine: os << "GpgEngine"; break; case GpgSMEngine: os << "GpgSMEngine"; break; case GpgConfEngine: os << "GpgConfEngine"; break; case AssuanEngine: os << "AssuanEngine"; default: case UnknownEngine: os << "UnknownEngine"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::CertificateInclusion incl ) { os << "GpgME::Context::CertificateInclusion(" << static_cast( incl ); switch ( incl ) { case Context::DefaultCertificates: os << "(DefaultCertificates)"; break; case Context::AllCertificatesExceptRoot: os << "(AllCertificatesExceptRoot)"; break; case Context::AllCertificates: os << "(AllCertificates)"; break; case Context::NoCertificates: os << "(NoCertificates)"; break; case Context::OnlySenderCertificate: os << "(OnlySenderCertificate)"; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, KeyListMode mode ) { os << "GpgME::KeyListMode("; #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0) CHECK( Local ); CHECK( Extern ); CHECK( Signatures ); CHECK( Validate ); CHECK( Ephemeral ); #undef CHECK return os << ')'; } std::ostream & operator<<( std::ostream & os, SignatureMode mode ) { os << "GpgME::SignatureMode("; switch ( mode ) { #define CHECK( x ) case x: os << #x; break CHECK( NormalSignatureMode ); CHECK( Detached ); CHECK( Clearsigned ); #undef CHECK default: os << "???" "(" << static_cast( mode ) << ')'; break; } return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::EncryptionFlags flags ) { os << "GpgME::Context::EncryptionFlags("; #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) CHECK( AlwaysTrust ); #undef CHECK return os << ')'; } std::ostream & operator<<( std::ostream & os, Context::AuditLogFlags flags ) { os << "GpgME::Context::AuditLogFlags("; #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0) CHECK( HtmlAuditLog ); CHECK( AuditLogWithHelp ); #undef CHECK return os << ')'; } } // namespace GpgME GpgME::Error GpgME::setDefaultLocale( int cat, const char * val ) { return Error( gpgme_set_locale( 0, cat, val ) ); } GpgME::EngineInfo GpgME::engineInfo( GpgME::Protocol proto ) { gpgme_engine_info_t ei = 0; if ( gpgme_get_engine_info( &ei ) ) return EngineInfo(); const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; for ( gpgme_engine_info_t i = ei ; i ; i = i->next ) if ( i->protocol == p ) return EngineInfo( i ); return EngineInfo(); } GpgME::Error GpgME::checkEngine( GpgME::Protocol proto ) { const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; return Error( gpgme_engine_check_version( p ) ); } static gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast( 255 ); static gpgme_protocol_t engine2protocol( const GpgME::Engine engine ) { switch ( engine ) { case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP; case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS; case GpgME::GpgConfEngine: #ifdef HAVE_GPGME_PROTOCOL_GPGCONF return GPGME_PROTOCOL_GPGCONF; #else break; #endif case GpgME::AssuanEngine: #ifdef HAVE_GPGME_ASSUAN_ENGINE return GPGME_PROTOCOL_ASSUAN; #else break; #endif case GpgME::UnknownEngine: ; } return UNKNOWN_PROTOCOL; } GpgME::EngineInfo GpgME::engineInfo( GpgME::Engine engine ) { gpgme_engine_info_t ei = 0; if ( gpgme_get_engine_info( &ei ) ) return EngineInfo(); const gpgme_protocol_t p = engine2protocol( engine ); for ( gpgme_engine_info_t i = ei ; i ; i = i->next ) if ( i->protocol == p ) return EngineInfo( i ); return EngineInfo(); } GpgME::Error GpgME::checkEngine( GpgME::Engine engine ) { const gpgme_protocol_t p = engine2protocol( engine ); return Error( gpgme_engine_check_version( p ) ); } static const unsigned long supported_features = 0 | GpgME::ValidatingKeylistModeFeature | GpgME::CancelOperationFeature | GpgME::WrongKeyUsageFeature #ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT | GpgME::DefaultCertificateInclusionFeature #endif #ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO | GpgME::GetSetEngineInfoFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET | GpgME::ClearAddGetSignatureNotationsFeature #endif #ifdef HAVE_GPGME_DATA_SET_FILE_NAME | GpgME::SetDataFileNameFeeature #endif #ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS | GpgME::SignatureNotationsKeylistModeFeature #endif #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS | GpgME::KeySignatureNotationsFeature #endif #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED | GpgME::KeyIsQualifiedFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL | GpgME::SignatureNotationsCriticalFlagFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T | GpgME::SignatureNotationsFlagsFeature #endif #ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE | GpgME::SignatureNotationsHumanReadableFlagFeature #endif #ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED | GpgME::SubkeyIsQualifiedFeature #endif #ifdef HAVE_GPGME_ENGINE_INFO_T_HOME_DIR | GpgME::EngineInfoHomeDirFeature #endif #ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME | GpgME::DecryptionResultFileNameFeature #endif #ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS | GpgME::DecryptionResultRecipientsFeature #endif #ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME | GpgME::VerificationResultFileNameFeature #endif #ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS | GpgME::SignaturePkaFieldsFeature #endif #ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS | GpgME::SignatureAlgorithmFieldsFeature #endif #ifdef HAVE_GPGME_GET_FDPTR | GpgME::FdPointerFeature #endif #ifdef HAVE_GPGME_OP_GETAUDITLOG | GpgME::AuditLogFeature #endif #ifdef HAVE_GPGME_PROTOCOL_GPGCONF | GpgME::GpgConfEngineFeature #endif #ifdef HAVE_GPGME_CANCEL_ASYNC | GpgME::CancelOperationAsyncFeature #endif #ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO | GpgME::NoEncryptToEncryptionFlagFeature #endif #ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY | GpgME::CardKeyFeature #endif #ifdef HAVE_GPGME_ASSUAN_ENGINE | GpgME::AssuanEngineFeature #endif #ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL | GpgME::EphemeralKeylistModeFeature +#endif +#ifdef HAVE_GPGME_OP_IMPORT_KEYS + | GpgME::ImportFromKeyserverFeature #endif ; bool GpgME::hasFeature( unsigned long features ) { return features == ( features & supported_features ); } diff --git a/gpgme++/context.h b/gpgme++/context.h index 461bfefbd..0ec727c29 100644 --- a/gpgme++/context.h +++ b/gpgme++/context.h @@ -1,306 +1,320 @@ /* 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 AssuanTransaction; + class AssuanResult; 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 ); + ImportResult importKeys( const std::vector & keys ); GpgME::Error startKeyImport( const Data & data ); + GpgME::Error startKeyImport( const std::vector & keys ); 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(); + // + // Assuan Transactions + // + + AssuanResult assuanTransact( const char * command, std::auto_ptr transaction ); + GpgME::Error startAssuanTransaction( const char * command, std::auto_ptr transaction ); + AssuanResult assuanResult() const; + + AssuanTransaction * lastAssuanTransaction() const; + // // // 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, NoEncryptTo=2 }; EncryptionResult encrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); GpgME::Error encryptSymmetrically( const Data & plainText, Data & cipherText ); GpgME::Error startEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); EncryptionResult encryptionResult() const; // // Combined Signing and Encryption // std::pair signAndEncrypt( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); GpgME::Error startCombinedSigningAndEncryption( const std::vector & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ); // use encryptionResult() and signingResult() to retrieve the result objects... // // // Audit Log // // enum AuditLogFlags { HtmlAuditLog = 1, AuditLogWithHelp = 128 }; GpgME::Error startGetAuditLog( Data & output, unsigned int flags=0 ); GpgME::Error getAuditLog( Data & output, unsigned int flags=0 ); // // // Run Control // // bool poll(); GpgME::Error wait(); GpgME::Error lastError() const; GpgME::Error cancelPendingOperation(); class Private; const Private * impl() const { return d; } Private * impl() { return d; } private: Private * d; private: // disable... Context( const Context & ); const Context & operator=( const Context & ); }; GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Context::CertificateInclusion incl ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Context::EncryptionFlags flags ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Context::AuditLogFlags flags ); } // namespace GpgME #endif // __GPGMEPP_CONTEXT_H__ diff --git a/gpgme++/context_p.h b/gpgme++/context_p.h index beb89e682..c30bde2ed 100644 --- a/gpgme++/context_p.h +++ b/gpgme++/context_p.h @@ -1,73 +1,80 @@ /* context_p.h - wraps a gpgme context (private part) Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB This file is part of GPGME++. GPGME++ is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GPGME++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with GPGME++; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // -*- c++ -*- #ifndef __GPGMEPP_CONTEXT_P_H__ #define __GPGMEPP_CONTEXT_P_H__ #include +#include #include namespace GpgME { class Context::Private { public: enum Operation { None = 0, Encrypt = 0x001, Decrypt = 0x002, Sign = 0x004, Verify = 0x008, DecryptAndVerify = Decrypt|Verify, SignAndEncrypt = Sign|Encrypt, Import = 0x010, Export = 0x020, // no gpgme_export_result_t, but nevertheless... Delete = 0x040, // no gpgme_delete_result_t, but nevertheless... KeyGen = 0x080, KeyList = 0x100, TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless... Edit = 0x400, // no gpgme_edit_result_t, but nevertheless... CardEdit = 0x800, // no gpgme_card_edit_result_t, but nevertheless... - GetAuditLog = 0x1000 // no gpgme_getauditlog_result_t, but nevertheless... + GetAuditLog = 0x1000, // no gpgme_getauditlog_result_t, but nevertheless... + + AssuanTransact = 0x2000, + + EndMarker }; Private( gpgme_ctx_t c=0 ); ~Private(); gpgme_ctx_t ctx; gpgme_io_cbs * iocbs; Operation lastop; gpgme_error_t lasterr; + Data lastAssuanInquireData; + std::auto_ptr lastAssuanTransaction; std::auto_ptr lastEditInteractor, lastCardEditInteractor; }; } // namespace GpgME #endif // __GPGMEPP_CONTEXT_P_H__ diff --git a/gpgme++/global.h b/gpgme++/global.h index 22d0d35ca..ffeb46ffb 100644 --- a/gpgme++/global.h +++ b/gpgme++/global.h @@ -1,128 +1,130 @@ /* 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 { + GPGMEPP_EXPORT void initializeLibrary(); + enum Protocol { OpenPGP, CMS, UnknownProtocol }; enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine }; enum KeyListMode { Local = 0x1, Extern = 0x2, Signatures = 0x4, SignatureNotations = 0x8, Validate = 0x10, Ephemeral = 0x20 }; enum SignatureMode { NormalSignatureMode, Detached, Clearsigned }; GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Protocol proto ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, Engine eng ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, KeyListMode mode ); GPGMEPP_EXPORT std::ostream & operator<<( std::ostream & os, SignatureMode mode ); GPGMEPP_EXPORT Error setDefaultLocale( int category, const char * value ); GPGMEPP_EXPORT Context * wait( Error & e, bool hang=true ); typedef void (*IdleFunction)(void); GPGMEPP_EXPORT IdleFunction registerIdleFunction( IdleFunction idleFunction ); typedef void (*IOCallback)( void * data, int fd ); GPGMEPP_EXPORT EngineInfo engineInfo( Protocol proto ); GPGMEPP_EXPORT EngineInfo engineInfo( Engine engine ); GPGMEPP_EXPORT Error checkEngine( Protocol proto ); GPGMEPP_EXPORT Error checkEngine( Engine engine ); GPGMEPP_EXPORT GIOChannel * getGIOChannel( int fd ); GPGMEPP_EXPORT QIODevice * getQIODevice( int fd ); enum Feature { ValidatingKeylistModeFeature = 0x00000001, CancelOperationFeature = 0x00000002, WrongKeyUsageFeature = 0x00000004, DefaultCertificateInclusionFeature = 0x00000008, GetSetEngineInfoFeature = 0x00000010, EngineInfoHomeDirFeature = 0x00000020, NoEncryptToEncryptionFlagFeature = 0x00000040, EphemeralKeylistModeFeature = 0x00000080, SetDataFileNameFeeature = 0x00000100, VerificationResultFileNameFeature = 0x00000200, DecryptionResultFileNameFeature = 0x00000400, DecryptionResultRecipientsFeature = 0x00000800, AuditLogFeature = 0x00001000, GpgConfEngineFeature = 0x00002000, CancelOperationAsyncFeature = 0x00004000, AssuanEngineFeature = 0x00008000, ClearAddGetSignatureNotationsFeature = 0x00010000, SignatureNotationsKeylistModeFeature = 0x00020000, KeySignatureNotationsFeature = 0x00040000, SignatureNotationsFlagsFeature = 0x00080000, SignatureNotationsCriticalFlagFeature = 0x00100000, SignatureNotationsHumanReadableFlagFeature = 0x00200000, CardKeyFeature = 0x00400000, - // reserved + ImportFromKeyserverFeature = 0x00800000, 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++/interfaces/CMakeLists.txt b/gpgme++/interfaces/CMakeLists.txt index 03551c4d3..c004ce7af 100644 --- a/gpgme++/interfaces/CMakeLists.txt +++ b/gpgme++/interfaces/CMakeLists.txt @@ -1,3 +1,8 @@ -install( FILES dataprovider.h passphraseprovider.h progressprovider.h DESTINATION ${INCLUDE_INSTALL_DIR}/gpgme++/interfaces COMPONENT Devel) +install( FILES + dataprovider.h + passphraseprovider.h + progressprovider.h + assuantransaction.h + DESTINATION ${INCLUDE_INSTALL_DIR}/gpgme++/interfaces COMPONENT Devel) diff --git a/gpgme++/interfaces/assuantransaction.h b/gpgme++/interfaces/assuantransaction.h new file mode 100644 index 000000000..e4f93cbd0 --- /dev/null +++ b/gpgme++/interfaces/assuantransaction.h @@ -0,0 +1,45 @@ +/* + assuantransaction.h - Interface for ASSUAN transactions + Copyright (C) 2009 Klarälvdalens Datakonsult AB + Author: Marc Mutz + + This file is part of GPGME++. + + GPGME++ is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + GPGME++ is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with GPGME++; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ +#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ + +#include + +namespace GpgME { + + class Error; + class Data; + + class GPGMEPP_EXPORT AssuanTransaction { + public: + virtual ~AssuanTransaction() {} + + virtual Error data( const void * data, size_t datalen ) = 0; + virtual Data inquire( const char * name, const char * args, Error & err ) = 0; + virtual Error status( const char * status, const char * args ) = 0; + }; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ diff --git a/gpgme++/key.cpp b/gpgme++/key.cpp index 1e934a697..c2c4f22aa 100644 --- a/gpgme++/key.cpp +++ b/gpgme++/key.cpp @@ -1,678 +1,682 @@ /* key.cpp - wraps a gpgme key Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB This file is part of GPGME++. GPGME++ is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GPGME++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with GPGME++; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include "util.h" #include #include GpgME::Key::Null GpgME::Key::null; namespace GpgME { Key::Key() : key() {} Key::Key( const Null & ) : key() {} Key::Key( const shared_gpgme_key_t & k ) : key( k ) {} Key::Key( gpgme_key_t k, bool ref ) : key( k ? shared_gpgme_key_t( k, &gpgme_key_unref ) : shared_gpgme_key_t() ) { if ( ref && impl() ) gpgme_key_ref( impl() ); } UserID Key::userID( unsigned int index ) const { return UserID( key, index ); } Subkey Key::subkey( unsigned int index ) const { return Subkey( key, index ); } unsigned int Key::numUserIDs() const { if ( !key ) return 0; unsigned int count = 0; for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) ++count; return count; } unsigned int Key::numSubkeys() const { if ( !key ) return 0; unsigned int count = 0; for ( gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next ) ++count; return count; } std::vector Key::userIDs() const { if ( !key ) return std::vector(); std::vector v; v.reserve( numUserIDs() ); for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) v.push_back( UserID( key, uid ) ); return v; } std::vector Key::subkeys() const { if ( !key ) return std::vector(); std::vector v; v.reserve( numSubkeys() ); for ( gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next ) v.push_back( Subkey( key, subkey ) ); return v; } Key::OwnerTrust Key::ownerTrust() const { if ( !key ) return Unknown; switch ( key->owner_trust ) { default: case GPGME_VALIDITY_UNKNOWN: return Unknown; case GPGME_VALIDITY_UNDEFINED: return Undefined; case GPGME_VALIDITY_NEVER: return Never; case GPGME_VALIDITY_MARGINAL: return Marginal; case GPGME_VALIDITY_FULL: return Full; case GPGME_VALIDITY_ULTIMATE: return Ultimate; } } char Key::ownerTrustAsString() const { if ( !key ) return '?'; switch ( key->owner_trust ) { default: case GPGME_VALIDITY_UNKNOWN: return '?'; case GPGME_VALIDITY_UNDEFINED: return 'q'; case GPGME_VALIDITY_NEVER: return 'n'; case GPGME_VALIDITY_MARGINAL: return 'm'; case GPGME_VALIDITY_FULL: return 'f'; case GPGME_VALIDITY_ULTIMATE: return 'u'; } } Protocol Key::protocol() const { if ( !key ) return UnknownProtocol; switch ( key->protocol ) { case GPGME_PROTOCOL_CMS: return CMS; case GPGME_PROTOCOL_OpenPGP: return OpenPGP; default: return UnknownProtocol; } } const char * Key::protocolAsString() const { return key ? gpgme_get_protocol_name( key->protocol ) : 0 ; } bool Key::isRevoked() const { return key && key->revoked; } bool Key::isExpired() const { return key && key->expired; } bool Key::isDisabled() const { return key && key->disabled; } bool Key::isInvalid() const { return key && key->invalid; } bool Key::hasSecret() const { return key && key->secret; } bool Key::isRoot() const { return key && key->subkeys && key->subkeys->fpr && key->chain_id && strcasecmp( key->subkeys->fpr, key->chain_id ) == 0; } bool Key::canEncrypt() const { return key && key->can_encrypt; } bool Key::canSign() const { #ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN if ( key && key->protocol == GPGME_PROTOCOL_OpenPGP ) return true; #endif return key && key->can_sign; } bool Key::canCertify() const { return key && key->can_certify; } bool Key::canAuthenticate() const { return key && key->can_authenticate; } bool Key::isQualified() const { #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED return key && key->is_qualified; #else return false; #endif } const char * Key::issuerSerial() const { return key ? key->issuer_serial : 0 ; } const char * Key::issuerName() const { return key ? key->issuer_name : 0 ; } const char * Key::chainID() const { return key ? key->chain_id : 0 ; } const char * Key::keyID() const { return key && key->subkeys ? key->subkeys->keyid : 0 ; } const char * Key::shortKeyID() const { if ( !key || !key->subkeys || !key->subkeys->keyid ) return 0; const int len = strlen( key->subkeys->keyid ); if ( len > 8 ) return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation) else return key->subkeys->keyid ; } const char * Key::primaryFingerprint() const { - return key && key->subkeys ? key->subkeys->fpr : 0 ; + const char * fpr = key && key->subkeys ? key->subkeys->fpr : 0 ; + if ( fpr ) + return fpr; + else + return keyID(); } unsigned int Key::keyListMode() const { return key ? convert_from_gpgme_keylist_mode_t( key->keylist_mode ) : 0 ; } const Key & Key::mergeWith( const Key & other ) { // ### incomplete. Just merges has* and can*, nothing else atm // ### detach also missing if ( !this->primaryFingerprint() || !other.primaryFingerprint() || strcasecmp( this->primaryFingerprint(), other.primaryFingerprint() ) != 0 ) return *this; // only merge the Key object which describe the same key const gpgme_key_t me = impl(); const gpgme_key_t him = other.impl(); if ( !me || !him ) return *this; me->revoked |= him->revoked; me->expired |= him->expired; me->disabled |= him->disabled; me->invalid |= him->invalid; me->can_encrypt |= him->can_encrypt; me->can_sign |= him->can_sign; me->can_certify |= him->can_certify; me->secret |= him->secret; me->can_authenticate |= him->can_authenticate; #ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED me->is_qualified |= him->is_qualified; #endif me->keylist_mode |= him->keylist_mode; return *this; } // // // class Subkey // // gpgme_sub_key_t find_subkey( const shared_gpgme_key_t & key, unsigned int idx ) { if ( key ) for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx ) if ( idx == 0 ) return s; return 0; } gpgme_sub_key_t verify_subkey( const shared_gpgme_key_t & key, gpgme_sub_key_t subkey ) { if ( key ) for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next ) if ( s == subkey ) return subkey; return 0; } Subkey::Subkey() : key(), subkey( 0 ) {} Subkey::Subkey( const shared_gpgme_key_t & k, unsigned int idx ) : key( k ), subkey( find_subkey( k, idx ) ) { } Subkey::Subkey( const shared_gpgme_key_t & k, gpgme_sub_key_t sk ) : key( k ), subkey( verify_subkey( k, sk ) ) { } Key Subkey::parent() const { return Key( key ); } const char * Subkey::keyID() const { return subkey ? subkey->keyid : 0 ; } const char * Subkey::fingerprint() const { return subkey ? subkey->fpr : 0 ; } unsigned int Subkey::publicKeyAlgorithm() const { return subkey ? subkey->pubkey_algo : 0 ; } const char * Subkey::publicKeyAlgorithmAsString() const { return gpgme_pubkey_algo_name( subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0 ); } bool Subkey::canEncrypt() const { return subkey && subkey->can_encrypt; } bool Subkey::canSign() const { return subkey && subkey->can_sign; } bool Subkey::canCertify() const { return subkey && subkey->can_certify; } bool Subkey::canAuthenticate() const { return subkey && subkey->can_authenticate; } bool Subkey::isQualified() const { #ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED return subkey && subkey->is_qualified; #else return false; #endif } bool Subkey::isCardKey() const { #ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY return subkey && subkey->is_cardkey; #else return false; #endif } const char * Subkey::cardSerialNumber() const { #ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY return subkey ? subkey->card_number : 0 ; #else return 0; #endif } bool Subkey::isSecret() const { return subkey && subkey->secret; } unsigned int Subkey::length() const { return subkey ? subkey->length : 0 ; } time_t Subkey::creationTime() const { return static_cast( subkey ? subkey->timestamp : 0 ); } time_t Subkey::expirationTime() const { return static_cast( subkey ? subkey->expires : 0 ); } bool Subkey::neverExpires() const { return expirationTime() == time_t(0); } bool Subkey::isRevoked() const { return subkey && subkey->revoked; } bool Subkey::isInvalid() const { return subkey && subkey->invalid; } bool Subkey::isExpired() const { return subkey && subkey->expired; } bool Subkey::isDisabled() const { return subkey && subkey->disabled; } // // // class UserID // // gpgme_user_id_t find_uid( const shared_gpgme_key_t & key, unsigned int idx ) { if ( key ) for ( gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx ) if ( idx == 0 ) return u; return 0; } gpgme_user_id_t verify_uid( const shared_gpgme_key_t & key, gpgme_user_id_t uid ) { if ( key ) for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) if ( u == uid ) return uid; return 0; } UserID::UserID() : key(), uid( 0 ) {} UserID::UserID( const shared_gpgme_key_t & k, gpgme_user_id_t u ) : key( k ), uid( verify_uid( k, u ) ) { } UserID::UserID( const shared_gpgme_key_t & k, unsigned int idx ) : key( k ), uid( find_uid( k, idx ) ) { } Key UserID::parent() const { return Key( key ); } UserID::Signature UserID::signature( unsigned int index ) const { return Signature( key, uid, index ); } unsigned int UserID::numSignatures() const { if ( !uid ) return 0; unsigned int count = 0; for ( gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next ) ++count; return count; } std::vector UserID::signatures() const { if ( !uid ) return std::vector(); std::vector v; v.reserve( numSignatures() ); for ( gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next ) v.push_back( Signature( key, uid, sig ) ); return v; } const char * UserID::id() const { return uid ? uid->uid : 0 ; } const char * UserID::name() const { return uid ? uid->name : 0 ; } const char * UserID::email() const { return uid ? uid->email : 0 ; } const char * UserID::comment() const { return uid ? uid->comment : 0 ; } UserID::Validity UserID::validity() const { if ( !uid ) return Unknown; switch ( uid->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return Unknown; case GPGME_VALIDITY_UNDEFINED: return Undefined; case GPGME_VALIDITY_NEVER: return Never; case GPGME_VALIDITY_MARGINAL: return Marginal; case GPGME_VALIDITY_FULL: return Full; case GPGME_VALIDITY_ULTIMATE: return Ultimate; } } char UserID::validityAsString() const { if ( !uid ) return '?'; switch ( uid->validity ) { default: case GPGME_VALIDITY_UNKNOWN: return '?'; case GPGME_VALIDITY_UNDEFINED: return 'q'; case GPGME_VALIDITY_NEVER: return 'n'; case GPGME_VALIDITY_MARGINAL: return 'm'; case GPGME_VALIDITY_FULL: return 'f'; case GPGME_VALIDITY_ULTIMATE: return 'u'; } } bool UserID::isRevoked() const { return uid && uid->revoked; } bool UserID::isInvalid() const { return uid && uid->invalid; } // // // class Signature // // gpgme_key_sig_t find_signature( gpgme_user_id_t uid, unsigned int idx ) { if ( uid ) for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx ) if ( idx == 0 ) return s; return 0; } gpgme_key_sig_t verify_signature( gpgme_user_id_t uid, gpgme_key_sig_t sig ) { if ( uid ) for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next ) if ( s == sig ) return sig; return 0; } UserID::Signature::Signature() : key(), uid( 0 ), sig( 0 ) {} UserID::Signature::Signature( const shared_gpgme_key_t & k, gpgme_user_id_t u, unsigned int idx ) : key( k ), uid( verify_uid( k, u ) ), sig( find_signature( uid, idx ) ) { } UserID::Signature::Signature( const shared_gpgme_key_t & k, gpgme_user_id_t u, gpgme_key_sig_t s ) : key( k ), uid( verify_uid( k, u ) ), sig( verify_signature( uid, s ) ) { } UserID UserID::Signature::parent() const { return UserID( key, uid ); } const char * UserID::Signature::signerKeyID() const { return sig ? sig->keyid : 0 ; } const char * UserID::Signature::algorithmAsString() const { return gpgme_pubkey_algo_name( sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0 ); } unsigned int UserID::Signature::algorithm() const { return sig ? sig->pubkey_algo : 0 ; } time_t UserID::Signature::creationTime() const { return static_cast( sig ? sig->timestamp : 0 ); } time_t UserID::Signature::expirationTime() const { return static_cast( sig ? sig->expires : 0 ); } bool UserID::Signature::neverExpires() const { return expirationTime() == time_t(0); } bool UserID::Signature::isRevokation() const { return sig && sig->revoked; } bool UserID::Signature::isInvalid() const { return sig && sig->invalid; } bool UserID::Signature::isExpired() const { return sig && sig->expired; } bool UserID::Signature::isExportable() const { return sig && sig->exportable; } const char * UserID::Signature::signerUserID() const { return sig ? sig->uid : 0 ; } const char * UserID::Signature::signerName() const { return sig ? sig->name : 0 ; } const char * UserID::Signature::signerEmail() const { return sig ? sig->email : 0 ; } const char * UserID::Signature::signerComment() const { return sig ? sig->comment : 0 ; } unsigned int UserID::Signature::certClass() const { return sig ? sig->sig_class : 0 ; } UserID::Signature::Status UserID::Signature::status() const { if ( !sig ) return GeneralError; switch ( gpgme_err_code(sig->status) ) { case GPG_ERR_NO_ERROR: return NoError; case GPG_ERR_SIG_EXPIRED: return SigExpired; case GPG_ERR_KEY_EXPIRED: return KeyExpired; case GPG_ERR_BAD_SIGNATURE: return BadSignature; case GPG_ERR_NO_PUBKEY: return NoPublicKey; default: case GPG_ERR_GENERAL: return GeneralError; } } std::string UserID::Signature::statusAsString() const { if ( !sig ) return std::string(); char buf[ 1024 ]; gpgme_strerror_r( sig->status, buf, sizeof buf ); buf[ sizeof buf - 1 ] = '\0'; return std::string( buf ); } GpgME::Notation UserID::Signature::notation( unsigned int idx ) const { if ( !sig ) return GpgME::Notation(); #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) if ( idx-- == 0 ) return GpgME::Notation( nota ); #endif return GpgME::Notation(); } unsigned int UserID::Signature::numNotations() const { if ( !sig ) return 0; unsigned int count = 0; #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) ++count; // others are policy URLs... #endif return count; } std::vector UserID::Signature::notations() const { if ( !sig ) return std::vector(); std::vector v; #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS v.reserve( numNotations() ); for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( nota->name ) v.push_back( GpgME::Notation( nota ) ); #endif return v; } const char * UserID::Signature::policyURL() const { #ifdef HAVE_GPGME_KEY_SIG_NOTATIONS if ( !sig ) return 0; for ( gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next ) if ( !nota->name ) return nota->value; #endif return 0; } } // namespace GpgME diff --git a/kabc/plugins/dir/dir.desktop b/kabc/plugins/dir/dir.desktop index 75c57b057..0f9fdc51e 100644 --- a/kabc/plugins/dir/dir.desktop +++ b/kabc/plugins/dir/dir.desktop @@ -1,53 +1,55 @@ [Desktop Entry] Name=Folder Name[ca]=Carpeta Name[da]=Mappe Name[de]=Ordner Name[el]=Φάκελος Name[es]=Carpeta Name[et]=Kataloog Name[fr]=Dossier Name[ga]=Fillteán Name[gl]=Cartafol +Name[hu]=Mappa Name[it]=Cartella Name[km]=ថត Name[lv]=Mape Name[nb]=Mappe Name[nds]=Orner Name[nn]=Mappe Name[pt]=Pasta Name[pt_BR]=Pasta Name[sv]=Katalog Name[tr]=Dizin Name[uk]=Тека Name[x-test]=xxFolderxx Name[zh_CN]=文件夹 Name[zh_TW]=資料夾 Comment=Provides access to contacts, each stored in a single file, in a given folder. Supports standard VCard file and other formats depending on availability of plugins. Comment[ca]=Proporciona l'accés als contactes, cada un emmagatzemat en un fitxer individual, en una carpeta donada. Accepta els fitxers estàndard VCard i altres formats depenent de la disponibilitat dels connectors. Comment[da]=Giver adgang til kontakter, hver lagret i en enkelt fil, i en given mappe. Understøtter standard VCard-fil og andre formater afhængigt af tilgængeligheden af plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte, die in einzelnen Dateien in einem vorgegebenen Ordner gespeichert sind. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές, αποθηκευμένες σε ξεχωριστά αρχεία, σε ένα 
δοσμένο φάκελο. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos, cada uno almacenado en un archivo diferente, dentro de un directorio determinado. Soporta archivos VCard estándar y otros formatos dependiendo de la disponibilidad de los complementos Comment[et]=Võimaldab kasutada eraldi failidesse salvestatud kontakte määratud kataloogis. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[fr]=Fourni l'accès aux contacts stockés chacun dans un fichier dans le dossier indiqué. Le format VCard et d'autres formats sont pris en charge en fonction des modules externes disponibles Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha, gach ceann stóráilte i gcomhad aonair, i bhfillteán sonraithe. Tacaítear le comhaid v-Chárta agus le formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso aos contactos, cada un gardado nun ficheiro nun cartafol dado. Admite ficheiros vCard estándar e outros formatos, en función da dispoñibilidade de extensións. +Comment[hu]=Névjegyek elérését biztosítja. Minden névjegy külön fájlban található, egy adott mappában. Támogatja a standard vCard formátumot, és bővítmények segítségével más formátumok is kezelhetők. Comment[it]=Fornisce accesso a contatti, ciascuno dei quali memorizzato in un singolo file in una cartella data. Gestisce file in standard VCard e altri formati in base ai plugin disponibili. Comment[km]=ផ្ដល់​ការ​ចូលដំណើរការ​ទៅ​កាន់​ទំនាក់ទំនង ដែល​ទំនាក់ទំនង​នីមួយៗ​ត្រូវ​បានផ្ទុកនៅ​ក្នុង​ឯកសារ​តែ​មួយ នៅ​ក្នុង​ថត​ដែល​បានផ្ដល់​ឲ្យ ។ គាំទ្រ​ឯកសារ VCard និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​មាន ។ Comment[lv]=Nodrošina pieeju kontaktiem, kas katrs saglabāts individuālā failā norādītajā mapē. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter, lagret hver for seg i en enkelt fil, i en gitt mappe. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten praat, elkeen binnen een Datei binnen en angeven Orner. Ünnerstütt VCard-Dateien un anner Formaten na de verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar i ei viss mappe, der dei er lagra i kvar sine filer. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos, estando cada um guardado num único ficheiro de uma dada pasta. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos, cada um armazenado em um único arquivo, em uma pasta informada. Suporta o formato de arquivos VCard padrão e outros formatos, dependendo da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter, var och en lagrad i en enstaka fil, i en given katalog. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[uk]=Надає доступ до контактів, кожен з яких зберігається у окремому файлі у вказаній теці. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts, each stored in a single file, in a given folder. Supports standard VCard file and other formats depending on availability of plugins.xx Comment[zh_CN]=提供对被存储在指定目录下的单独一个文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取特定目錄下,個別儲存在單一檔案中的聯絡人的功能。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_directory Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=dir diff --git a/kabc/plugins/file/file.desktop b/kabc/plugins/file/file.desktop index 376233baf..d0892be23 100644 --- a/kabc/plugins/file/file.desktop +++ b/kabc/plugins/file/file.desktop @@ -1,71 +1,72 @@ [Desktop Entry] Name=File Name[be]=Файл Name[ca]=Fitxer Name[cs]=Soubor Name[da]=Fil Name[de]=Datei Name[el]=Αρχείο Name[es]=Archivo Name[et]=Fail Name[fr]=Fichier Name[ga]=Comhad Name[gl]=Ficheiro Name[hne]=फाइल Name[hu]=Fájl Name[ja]=ファイル Name[km]=ឯកសារ Name[lt]=Failas Name[lv]=Fails Name[nb]=Fil Name[nds]=Datei Name[nl]=Bestand Name[nn]=Fil Name[oc]=Fichièr Name[pa]=ਫਾਇਲ Name[pl]=Plik Name[pt]=Ficheiro Name[pt_BR]=Arquivo Name[ro]=Fișier Name[ru]=Файл Name[se]=Fiila Name[sk]=Súbor Name[sl]=Datoteka Name[sr]=Фајл Name[sr@latin]=Fajl Name[sv]=Fil Name[th]=แฟ้ม Name[tr]=Dosya Name[uk]=Файл Name[x-test]=xxFilexx Name[zh_CN]=文件 Name[zh_TW]=檔案 Comment=Provides access to contacts stored in a single local file. Supports standard VCard files and other formats depending on available plugins. Comment[ca]=Proporciona l'accés als contactes emmagatzemats en un fitxer individual. Accepta els fitxers estàndard VCard i altres formats, depenent dels connectors disponibles. Comment[da]=Giver adgang til kontakter, hver lagret i en enkelt fil. Understøtter standard VCard-fil og andre formater afhængigt af tilgængelige af plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte, die in einer einzigen Dateien lokal gespeichert sind. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές, αποθηκευμένες σε ένα τοπικό αρχείο. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos almacenados en un único archivo local. Soporta archivos VCard estándar y otros formatos dependiendo de la disponibilidad de los componentes. Comment[et]=Võimaldab kasutada kohalikku faili salvestatud kontakte. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[fr]=Fourni l'accès aux contacts stockés dans un seul fichier local. Le format VCard et d'autres formats sont pris en charge en fonction des modules externes disponibles. Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha, stóráilte i gcomhad aonair. Tacaítear le comhaid v-Chárta agus formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso a contactos gardados nun único ficheiro local. Admite ficheiros vCard estándar e outros formatos en función das extensións dispoñíbeis. +Comment[hu]=Névjegyek elérését biztosítja. Minden névjegy egy közös helyi fájlban található. Támogatja a standard vCard formátumot, és bővítmények segítségével más formátumok is kezelhetők. Comment[it]=Fornisce accesso a contatti memorizzati in un singolo file locale. Gestisce file in standard VCard e altri formati in base ai plugin disponibili. Comment[ja]=単一のローカルファイルに保存されている連絡先へのアクセスを提供します。標準の VCard ファイルと、利用可能なプラグインに応じたフォーマットをサポートします。 Comment[km]=ផ្ដល់​កា​រចូលដំណើរការ​ទៅ​ទំនាក់ទំនង​​នៅ​ក្នុង​ឯកសារ​មូលដ្ឋាន​តែ​មួយ ។ គាំទ្រ​ឯកសារ VCard ស្តង់ដារ និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​មាន ។ Comment[lv]=Nodrošina piekļuvi kontaktiem, kas glabājas vienā lokālā failā. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter, lagret i en enkelt lokal fil. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten praat, de in een enkel lokaal Datei wohrt warrt. Ünnerstütt VCard-Dateien un anner Formaten na de 'verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar lagra i ei einskild lokal fil. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos, estando todos guardados num único ficheiro local. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos armazenados em um único arquivo local. Suporta o formato de arquivos VCard padrão e outros formatos, dependendo da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter lagrade i en enda lokal fil. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[uk]=Надає доступ до контактів, які зберігаються у окремому локальному файлі. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts stored in a single local file. Supports standard VCard files and other formats depending on available plugins.xx Comment[zh_CN]=提供对被存储在单独的本地文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取儲存在單一檔案中的聯絡人的功能。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_file Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=file diff --git a/kabc/plugins/net/net.desktop b/kabc/plugins/net/net.desktop index 56b73203d..f7e0052cc 100644 --- a/kabc/plugins/net/net.desktop +++ b/kabc/plugins/net/net.desktop @@ -1,73 +1,74 @@ [Desktop Entry] Name=Network Name[be]=Сетка Name[ca]=Xarxa Name[cs]=Síť Name[da]=Netværk Name[de]=Netzwerk Name[el]=Δίκτυο Name[es]=Red Name[et]=Võrk Name[fr]=Réseau Name[ga]=Líonra Name[gl]=Rede Name[hne]=नेटवर्क Name[hu]=Hálózat Name[it]=Rete Name[ja]=ネットワーク Name[km]=បណ្តាញ Name[lt]=Tinklas Name[lv]=Tīkls Name[nb]=Nettverk Name[nds]=Nettwark Name[nl]=Netwerk Name[nn]=Nettverk Name[oc]=Ret Name[pa]=ਨੈੱਟਵਰਕ Name[pl]=Sieć Name[pt]=Rede Name[pt_BR]=Rede Name[ro]=Rețea Name[ru]=Сетевой файл Name[se]=Fierbmi Name[sk]=Sieť Name[sl]=Omrežje Name[sr]=Мрежа Name[sr@latin]=Mreža Name[sv]=Nätverk Name[th]=ระบบเครือข่าย Name[tr]=Ağ Name[uk]=Мережа Name[x-test]=xxNetworkxx Name[zh_CN]=网络 Name[zh_TW]=網路 Comment=Provides access to contacts in remote files using KDE's network framework KIO. Supports standard VCard files and other formats depending on available plugins. Comment[ca]=Proporciona l'accés als contactes en fitxers remots usant la infraestructura KIO de xarxa del KDE. Accepta els fitxers estàndard VCard i altres formats, depenent dels connectors disponibles. Comment[da]=Giver adgang til kontakter i eksterne filer med brug af KDE's netværks-framework KIO. Understøtter standard VCard-filer og andre formater afhængigt af tilgængelige plugins. Comment[de]=Ermöglicht Zugriff auf Kontakte in entfernten Dateien durch das KIO-Netzwerksystem von KDE. Unterstützt Standard-VCard-Dateien und andere Formate abhängig von den verfügbaren Modulen. Comment[el]=Προσφέρει πρόσβαση σε επαφές σε απομακρυσμένα αρχεία με τη χρήση του συστήματος KIO του KDE. Υποστηρίζει τυπικά αρχεία VCard και άλλες μορφές αρχείων ανάλογα με τη διαθεσιμότητα των πρόσθετων. Comment[es]=Provee acceso a los contactos en un archivo remoto utilizando la infraestructura de red KIO de KDE. Soporta archivos VCard estándar y otros formatos dependiendo en la disponibilidad de los complementos. Comment[et]=Võimaldab kasutada võrgufaile KDE võrguraamistiku KIO abil. Toetab standardseid VCard-faile ja teisi vorminguid sõltuvalt pluginate olemasolust. Comment[fr]=Fourni l'accès aux contacts stockés dans des fichiers distants en utilisant le mécanisme réseau KIO de KDE. Le format VCard et d'autres formats sont pris en charge en fonction des modules externes disponibles. Comment[ga]=Soláthraíonn sé seo rochtain ar theagmhálacha i gcianchomhaid tríd an gcreatlach líonra KIO atá cuid de KDE. Tacaítear le comhaid v-Chárta agus formáidí eile, ag brath ar na breiseáin atá ar fáil. Comment[gl]=Dá acceso a contactos gardados en ficheiros remotos mediante a infraestrutura de rede KIO, de KDE. Admite ficheiros vCard estándar e outros formatos en función das extensións dispoñíbeis. +Comment[hu]=Távoli fájlokban található névjegyek elérését biztosítja a KDE KIO keretrendszeren keresztül. Támogatja a standard vCard formátumot, és bővítmények segítségével más formátumok is kezelhetők. Comment[it]=Fornisce accesso a contatti su file remoti usando KIO, l'infrastruttura di rete di KDE. Gestisce file in standard VCard e altri formati in base ai plugin disponibili. Comment[ja]=KDE のネットワークフレームワーク KIO を使って、リモートファイルに保存されている連絡先へのアクセスを提供します。標準の VCard ファイルと、利用可能なプラグインに応じたフォーマットをサポートします。 Comment[km]=ផ្ដល់​កា​រចូលដំណើរការ​ទៅកាន់​ទំនាក់ទំនង​ក្នុង​​ឯកសារ​ពី​ចម្ងាយ ដោយ​ប្រើ KIO ​គ្រោងការណ៍​បណ្ដាញ​របស់ KDE ។ គាំទ្រ​ឯកសារ VCard ស្តង់ដារ និង​ទ្រង់ទ្រាយ​ផ្សេងៗ​ទៀត ដោយ​អាស្រ័យ​លើ​កម្មវិធី​ជំនួយ​ដែល​លមាន ។ Comment[lv]=Nodrošina piekļuvi kontaktiem attālinātos failus, izmantojot KDE tīklošanas ietvaru KIO. Atbalsta standarta VCard failus un citus formātus, atkarībā no pieejamajiem spraudņiem. Comment[nb]=Gir tilgang til kontakter i nettverksfiler, ved bruk av KDEs rammeverk KIO for nettverk. Støtter standard vCard og andre formater avhengig av tilgjengelige programtillegg. Comment[nds]=Stellt Togriep op Kontakten binnen feern Dateien praat, bruukt KDE sien Nettwark-Rahmenwark KIO. Ünnerstütt VCard-Dateien un anner Formaten na de verföögboren Modulen. Comment[nn]=Gjev tilgang til kontaktar i nettverksfiler ved å bruka KIO, nettverksrammeverket frå KDE. Standard vCard-filer er støtta, i tillegg til andre format, avhengig av kva programtillegg som er i bruk. Comment[pt]=Oferece o acesso aos contactos em ficheiros remotos, disponíveis através de um KIO da plataforma de rede do KDE. Suporta os ficheiros VCard normais, assim como outros formatos, dependendo da disponibilidade dos 'plugins'. Comment[pt_BR]=Fornece acesso aos contatos em arquivos remotos usando o KIO framework da rede do KDE. O suporte à arquivos VCard padrão e outros formatos dependem da disponibilidade de plug-ins. Comment[sv]=Ger tillgång till kontakter i fjärrfiler med användning av KDE:s I/O-ramverk. Stöder vCard-standardfiler och andra format, beroende på tillgängliga insticksprogram. Comment[tr]=KDE'nin ağ iskeleti KIO'yu kullanarak uzak dosyalardaki kişilere erişim sağlar. Mevcut eklentilere bağlı olarak standart VCard dosyalarını ve diğer dosya biçimleri destekler. Comment[uk]=Надає доступ до контактів, які зберігаються у віддалених файлах, за допомогою мережевих засобів KIO KDE. Підтримує стандартні файли VCard та файли у інших форматах, залежно від наявності відповідних додатків. Comment[x-test]=xxProvides access to contacts in remote files using KDE's network framework KIO. Supports standard VCard files and other formats depending on available plugins.xx Comment[zh_CN]=通过 KDE 的网络透明框架 KIO,提供对被存储在远程文件中的联系人的访问支持。支持标准 VCard 文件和其它插件所允许的格式。 Comment[zh_TW]=提供存取使用 KDE 網路架構 KIO 儲存在遠端檔案中的聯絡人。支援標準的 VCard 檔,以及外掛程式所提供的其它格式檔案。 X-KDE-Library=kabc_net Type=Service X-KDE-ServiceTypes=KResources/Plugin X-KDE-ResourceFamily=contact X-KDE-ResourceType=net diff --git a/kdepimlibs-mime.xml b/kdepimlibs-mime.xml new file mode 100644 index 000000000..4b78bdc05 --- /dev/null +++ b/kdepimlibs-mime.xml @@ -0,0 +1,20 @@ + + + + + + + E-Mail Distribution Lists + + diff --git a/kimap/acljobbase.h b/kimap/acljobbase.h index b491dd291..3bc1e1ac7 100644 --- a/kimap/acljobbase.h +++ b/kimap/acljobbase.h @@ -1,64 +1,64 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_ACLJOBBASE_H #define KIMAP_ACLJOBBASE_H #include "kimap_export.h" #include "acl.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class AclJobBasePrivate; /** @short Base class of Acl related jobs. It cannot be used directly, you must subclass it and reimplement at least the doStart() method. */ class KIMAP_EXPORT AclJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(AclJobBase) friend class SessionPrivate; public: AclJobBase( Session *session ); virtual ~AclJobBase(); enum AclModifier { Add = 0, Remove, Change }; void setMailBox( const QString &mailBox ); QString mailBox() const; protected: explicit AclJobBase( JobPrivate &dd ); }; } #endif diff --git a/kimap/appendjob.h b/kimap/appendjob.h index 27440b0b8..d1919bb2e 100644 --- a/kimap/appendjob.h +++ b/kimap/appendjob.h @@ -1,62 +1,62 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_APPENDJOB_H #define KIMAP_APPENDJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class AppendJobPrivate; class KIMAP_EXPORT AppendJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(AppendJob) friend class SessionPrivate; public: AppendJob( Session *session ); virtual ~AppendJob(); void setMailBox( const QString &mailBox ); QString mailBox() const; void setFlags( const QList &flags); QList flags() const; void setContent( const QByteArray &content ); QByteArray content() const; qint64 uid() const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/capabilitiesjob.h b/kimap/capabilitiesjob.h index 9ecf7ebda..8262f2f12 100644 --- a/kimap/capabilitiesjob.h +++ b/kimap/capabilitiesjob.h @@ -1,56 +1,56 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_CAPABILITIESJOB_H #define KIMAP_CAPABILITIESJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class CapabilitiesJobPrivate; class KIMAP_EXPORT CapabilitiesJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CapabilitiesJob) friend class SessionPrivate; public: CapabilitiesJob( Session *session ); virtual ~CapabilitiesJob(); QStringList capabilities() const; Q_SIGNALS: void capabilitiesReceived( const QStringList &capabilities ); protected: virtual void doStart(); virtual void handleResponse( const Message &response ); }; } #endif diff --git a/kimap/closejob.h b/kimap/closejob.h index 3392e83e6..6affb2bf8 100644 --- a/kimap/closejob.h +++ b/kimap/closejob.h @@ -1,50 +1,50 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_CLOSEJOB_H #define KIMAP_CLOSEJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class CloseJobPrivate; class KIMAP_EXPORT CloseJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CloseJob) friend class SessionPrivate; public: explicit CloseJob( Session *session ); virtual ~CloseJob(); protected: virtual void doStart(); }; } #endif diff --git a/kimap/copyjob.h b/kimap/copyjob.h index 9c37b54aa..608f9dd91 100644 --- a/kimap/copyjob.h +++ b/kimap/copyjob.h @@ -1,57 +1,57 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_COPYJOB_H #define KIMAP_COPYJOB_H #include "kimap_export.h" #include "job.h" #include "imapset.h" namespace KIMAP { class Session; -class Message; +struct Message; class CopyJobPrivate; class KIMAP_EXPORT CopyJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CopyJob) friend class SessionPrivate; public: explicit CopyJob( Session *session ); virtual ~CopyJob(); void setMailBox( const QString &mailBox ); QString mailBox() const; void setSequenceSet( const ImapSet &set ); ImapSet sequenceSet() const; protected: virtual void doStart(); }; } #endif diff --git a/kimap/createjob.h b/kimap/createjob.h index 14fe82ebf..d55d5888f 100644 --- a/kimap/createjob.h +++ b/kimap/createjob.h @@ -1,53 +1,53 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_CREATEJOB_H #define KIMAP_CREATEJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class CreateJobPrivate; class KIMAP_EXPORT CreateJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(CreateJob) friend class SessionPrivate; public: explicit CreateJob( Session *session ); virtual ~CreateJob(); void setMailBox( const QString &mailBox ); QString mailBox() const; protected: virtual void doStart(); }; } #endif diff --git a/kimap/deleteacljob.h b/kimap/deleteacljob.h index a0f93646e..6802ee8d5 100644 --- a/kimap/deleteacljob.h +++ b/kimap/deleteacljob.h @@ -1,55 +1,55 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_DELETEACLJOB_H #define KIMAP_DELETEACLJOB_H #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class DeleteAclJobPrivate; class KIMAP_EXPORT DeleteAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(DeleteAclJob) friend class SessionPrivate; public: explicit DeleteAclJob( Session *session ); virtual ~DeleteAclJob(); void setIdentifier( const QByteArray &identifier ); QByteArray identifier(); protected: virtual void doStart(); }; } #endif diff --git a/kimap/expungejob.h b/kimap/expungejob.h index 365cd6294..7f91eac83 100644 --- a/kimap/expungejob.h +++ b/kimap/expungejob.h @@ -1,51 +1,51 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_EXPUNGEJOB_H #define KIMAP_EXPUNGEJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class ExpungeJobPrivate; class KIMAP_EXPORT ExpungeJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(ExpungeJob) friend class SessionPrivate; public: explicit ExpungeJob( Session *session ); virtual ~ExpungeJob(); protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/fetchjob.h b/kimap/fetchjob.h index ffe592b06..4e60714d4 100644 --- a/kimap/fetchjob.h +++ b/kimap/fetchjob.h @@ -1,102 +1,102 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_FETCHJOB_H #define KIMAP_FETCHJOB_H #include "kimap_export.h" #include "imapset.h" #include "job.h" #include "kmime/kmime_content.h" #include "kmime/kmime_message.h" #include namespace KIMAP { class Session; -class Message; +struct Message; class FetchJobPrivate; typedef boost::shared_ptr ContentPtr; typedef QMap MessageParts; typedef boost::shared_ptr MessagePtr; typedef QList MessageFlags; class KIMAP_EXPORT FetchJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(FetchJob) friend class SessionPrivate; public: struct FetchScope { QList parts; // used only if mode == Headers or Content enum {Headers, Flags, Structure, Content} mode; }; explicit FetchJob( Session *session ); virtual ~FetchJob(); void setSequenceSet( const ImapSet &set ); ImapSet sequenceSet() const; void setUidBased(bool uidBased); bool isUidBased() const; void setScope( const FetchScope &scope ); FetchScope scope() const; QMap messages() const; QMap parts() const; QMap flags() const; QMap sizes() const; QMap uids() const; Q_SIGNALS: void headersReceived( const QString &mailBox, const QMap &uids, const QMap &sizes, const QMap &flags, const QMap &messages ); void messagesReceived( const QString &mailBox, const QMap &uids, const QMap &messages ); void partsReceived( const QString &mailBox, const QMap &uids, const QMap &parts ); protected: virtual void doStart(); virtual void handleResponse(const Message &response); private: Q_PRIVATE_SLOT( d_func(), void emitPendings() ) }; } #endif diff --git a/kimap/getacljob.h b/kimap/getacljob.h index b45dc41d5..aa8d90cee 100644 --- a/kimap/getacljob.h +++ b/kimap/getacljob.h @@ -1,59 +1,59 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_GETACLJOB_H #define KIMAP_GETACLJOB_H #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class GetAclJobPrivate; class KIMAP_EXPORT GetAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetAclJob) friend class SessionPrivate; public: explicit GetAclJob( Session *session ); virtual ~GetAclJob(); QList identifiers() const; bool hasRightEnabled(const QByteArray &identifier, Acl::Right right) const; Acl::Rights rights(const QByteArray &identifier) const; QMap allRights() const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/getmetadatajob.h b/kimap/getmetadatajob.h index 98586759a..72c82a5b2 100644 --- a/kimap/getmetadatajob.h +++ b/kimap/getmetadatajob.h @@ -1,97 +1,97 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_GETMETADATAJOB_H #define KIMAP_GETMETADATAJOB_H #include "kimap_export.h" #include "metadatajobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class GetMetaDataJobPrivate; class KIMAP_EXPORT GetMetaDataJob : public MetaDataJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetMetaDataJob) friend class SessionPrivate; public: explicit GetMetaDataJob( Session *session ); virtual ~GetMetaDataJob(); enum Depth { NoDepth = 0, OneLevel, AllLevels }; Q_DECLARE_FLAGS(Depths, Depth) /** * Add an entry, attribute pair to query, if the job is operating in Annotatemore mode, the attribute name is used.In Metadata mode the @param attribute is ignored. * @param entry the metadata entry name * @param attribute the attribute name, in Annotatemore mode */ void addEntry(const QByteArray &entry, const QByteArray &attribute = QByteArray()); /** * Only entry values that are less than or equal in octet size to the specified @param size limit are returned. In * Annotatemore mode, this setting is ignored. */ void setMaximumSize(qint64 size); /** * Default is NoDepth. In Annotatemore mode, this setting is ignored. * @param depth */ void setDepth(Depth depth); /** * Get the metadata. If used in Metadata mode, @param attribute is ignored. * @param mailBox * @param entry * @param attribute * @return */ QByteArray metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute = QByteArray()) const; /** * Get all the metadata for a given mailbox. * * @param mailBox * @return */ QMap > allMetaData(const QString &mailBox) const; protected: virtual void doStart(); virtual void handleResponse( const Message &response ); }; } #endif diff --git a/kimap/getquotajob.h b/kimap/getquotajob.h index 14f7bcb16..adb1cc294 100644 --- a/kimap/getquotajob.h +++ b/kimap/getquotajob.h @@ -1,53 +1,53 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_GETQUOTAJOB_H #define KIMAP_GETQUOTAJOB_H #include "quotajobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class GetQuotaJobPrivate; class KIMAP_EXPORT GetQuotaJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetQuotaJob) friend class SessionPrivate; public: explicit GetQuotaJob( Session *session ); virtual ~GetQuotaJob(); void setRoot(const QByteArray &root); QByteArray root() const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/getquotarootjob.h b/kimap/getquotarootjob.h index 5017ea7c8..7a9829255 100644 --- a/kimap/getquotarootjob.h +++ b/kimap/getquotarootjob.h @@ -1,59 +1,59 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_GETQUOTAROOTJOB_H #define KIMAP_GETQUOTAROOTJOB_H #include "quotajobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class GetQuotaRootJobPrivate; class KIMAP_EXPORT GetQuotaRootJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(GetQuotaRootJob) friend class SessionPrivate; public: explicit GetQuotaRootJob( Session *session ); virtual ~GetQuotaRootJob(); void setMailBox(const QString &mailBox); QString mailBox() const; QList roots() const; qint64 usage(const QByteArray &root, const QByteArray &resource) const; qint64 limit(const QByteArray &root, const QByteArray &resource) const; QMap allUsages(const QByteArray &root) const; QMap allLimits(const QByteArray &root) const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/job.h b/kimap/job.h index 1d855df43..cf3679016 100644 --- a/kimap/job.h +++ b/kimap/job.h @@ -1,67 +1,67 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_JOB_H #define KIMAP_JOB_H #include "kimap_export.h" #include namespace KIMAP { class Session; class SessionPrivate; class JobPrivate; -class Message; +struct Message; class KIMAP_EXPORT Job : public KJob { Q_OBJECT Q_DECLARE_PRIVATE(Job) friend class SessionPrivate; public: virtual ~Job(); virtual void start(); private: virtual void doStart() = 0; virtual void handleResponse(const Message &response); virtual void connectionLost(); protected: enum HandlerResponse { Handled = 0, NotHandled }; HandlerResponse handleErrorReplies(const Message &response); explicit Job( Session *session ); explicit Job( JobPrivate &dd ); JobPrivate *const d_ptr; }; } #endif diff --git a/kimap/listjob.h b/kimap/listjob.h index ffe7c5c30..99e694036 100644 --- a/kimap/listjob.h +++ b/kimap/listjob.h @@ -1,80 +1,80 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_LISTJOB_H #define KIMAP_LISTJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class ListJobPrivate; struct KIMAP_EXPORT MailBoxDescriptor { QString name; QChar separator; inline bool operator==(const MailBoxDescriptor &other) const { return other.name==name && other.separator==separator; } inline bool operator<(const MailBoxDescriptor &other) const { return other.name mailBoxes() const; QMap< MailBoxDescriptor, QList > flags() const; Q_SIGNALS: void mailBoxesReceived( const QList &descriptors, const QList< QList > &flags ); protected: virtual void doStart(); virtual void handleResponse(const Message &response); private: Q_PRIVATE_SLOT( d_func(), void emitPendings() ) }; } #endif diff --git a/kimap/listrightsjob.h b/kimap/listrightsjob.h index 9fd0753ac..cf19774b4 100644 --- a/kimap/listrightsjob.h +++ b/kimap/listrightsjob.h @@ -1,57 +1,57 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_LISTRIGHTSJOB_H #define KIMAP_LISTRIGHTSJOB_H #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class ListRightsJobPrivate; class KIMAP_EXPORT ListRightsJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(ListRightsJob) friend class SessionPrivate; public: explicit ListRightsJob( Session *session ); virtual ~ListRightsJob(); void setIdentifier( const QByteArray &identifier ); QByteArray identifier(); Acl::Rights defaultRights(); QList possibleRights(); protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/loginjob.h b/kimap/loginjob.h index 563c81267..c4cb1b1ad 100644 --- a/kimap/loginjob.h +++ b/kimap/loginjob.h @@ -1,98 +1,98 @@ /* Copyright (c) 2009 Kevin Ottens Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_LOGINJOB_H #define KIMAP_LOGINJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class LoginJobPrivate; class KIMAP_EXPORT LoginJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(LoginJob) friend class SessionPrivate; public: enum EncryptionMode { Unencrypted = 0, TlsV1, SslV2, SslV3, SslV3_1, AnySslVersion }; enum AuthenticationMode { ClearText = 0, Login, Plain, CramMD5, DigestMD5, NTLM, GSSAPI, Anonymous }; explicit LoginJob( Session *session ); virtual ~LoginJob(); QString userName() const; void setUserName( const QString &userName ); QString password() const; void setPassword( const QString &password ); /** * Set the encryption mode for the connection. In case an encryption mode is set, the caller * MUST check the encryptionMode() result after executing the job, to see if the connection is * encrypted or not (e.g handshaking failed). * @param mode the encryption mode, see EncryptionModes */ void setEncryptionMode(EncryptionMode mode); /** Get the encryption mode. @return the currently active encryption mode */ EncryptionMode encryptionMode(); void setAuthenticationMode(AuthenticationMode mode); protected: virtual void doStart(); virtual void handleResponse( const Message &response ); virtual void connectionLost(); private: Q_PRIVATE_SLOT( d_func(), void sslResponse(bool) ) }; } #endif diff --git a/kimap/metadatajobbase.h b/kimap/metadatajobbase.h index b42387479..edf7e06fa 100644 --- a/kimap/metadatajobbase.h +++ b/kimap/metadatajobbase.h @@ -1,74 +1,74 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_METADATAJOBBASE_H #define KIMAP_METADATAJOBBASE_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class MetaDataJobBasePrivate; /** @short Base class of Metadata/Annotatemore related jobs. It cannot be used directly, you must subclass it and reimplement at least the doStart() method. */ class KIMAP_EXPORT MetaDataJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(MetaDataJobBase) friend class SessionPrivate; public: explicit MetaDataJobBase( Session *session ); virtual ~MetaDataJobBase(); enum ServerCapability { Metadata = 0, //rfc5464 Annotatemore //compatibility with draft-daboo-imap-annotatemore-07 }; void setMailBox( const QString &mailBox ); QString mailBox() const; /** * Set what kind of annotation does the server support. The commands send out depend on the mode set here. * @param capability Metadata (RFC5464 mode) or Annotatemore (draft-daboo-imap-annotatemore-07 mode) */ void setServerCapability(const ServerCapability& capability); /** * Check the operating mode. * @return the annotation capability of the server, see ServerCapability */ ServerCapability serverCapability() const; protected: MetaDataJobBase( JobPrivate &dd ); }; } #endif diff --git a/kimap/myrightsjob.h b/kimap/myrightsjob.h index 19f8c9c3b..46d9594eb 100644 --- a/kimap/myrightsjob.h +++ b/kimap/myrightsjob.h @@ -1,56 +1,56 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_MYRIGHTSJOB_H #define KIMAP_MYRIGHTSJOB_H #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class MyRightsJobPrivate; class KIMAP_EXPORT MyRightsJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(MyRightsJob) friend class SessionPrivate; public: explicit MyRightsJob( Session *session ); virtual ~MyRightsJob(); bool hasRightEnabled(Acl::Right right); Acl::Rights rights(); protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/quotajobbase.h b/kimap/quotajobbase.h index 8ad05d985..a263b6c76 100644 --- a/kimap/quotajobbase.h +++ b/kimap/quotajobbase.h @@ -1,57 +1,57 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_QUOTAJOBBASE_H #define KIMAP_QUOTAJOBBASE_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class QuotaJobBasePrivate; /** @short Base class of Quota related jobs. It cannot be used directly, you must subclass it and reimplement at least the doStart() method. */ class KIMAP_EXPORT QuotaJobBase : public Job { Q_OBJECT Q_DECLARE_PRIVATE(QuotaJobBase) friend class SessionPrivate; public: explicit QuotaJobBase( Session *session ); virtual ~QuotaJobBase(); qint64 usage(const QByteArray& resource); qint64 limit(const QByteArray& resource); protected: QuotaJobBase( JobPrivate &dd ); }; } #endif diff --git a/kimap/searchjob.h b/kimap/searchjob.h index a8232621a..4f8d903e7 100644 --- a/kimap/searchjob.h +++ b/kimap/searchjob.h @@ -1,154 +1,154 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SEARCHJOB_H #define KIMAP_SEARCHJOB_H #include "kimap_export.h" #include "job.h" class QDate; namespace KIMAP { class Session; -class Message; +struct Message; class SearchJobPrivate; class KIMAP_EXPORT SearchJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SearchJob) friend class SessionPrivate; public: enum SearchLogic { And = 0, Or, Not }; enum SearchCriteria { All = 0, Answered, BCC, Before, Body, CC, Deleted, Draft, Flagged, From, Header, Keyword, Larger, New, Old, On, Recent, Seen, SentBefore, SentOn, SentSince, Since, Smaller, Subject, Text, To, Uid, Unanswered, Undeleted, Undraft, Unflagged, Unkeyword, Unseen }; explicit SearchJob( Session *session ); virtual ~SearchJob(); void setUidBased(bool uidBased); bool isUidBased() const; void setCharset( const QByteArray &charSet ); QByteArray charset() const; /** * Get the search result, as a list of sequence numbers or UIDs, based on the isUidBased status * @return the found items */ QList foundItems(); /** * Add a search criteria that doesn't have an argument. Passing a criteria that * should have an argument will be ignored. * @param criteria a criteria from SearchCriterias */ void addSearchCriteria( SearchCriteria criteria ); /** * Add a search criteria that has one or more space separate string arguments. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument the arguments */ void addSearchCriteria( SearchCriteria criteria, const QByteArray &argument ); /** * Add a search criteria that has an integer argument. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument a number argument */ void addSearchCriteria( SearchCriteria criteria, int argument ); /** * Add a search criteria that has a date as argument. * Passing a criteria that accepts a different type or argument or no * argument will be ignored. * @param criteria a criteria from SearchCriterias * @param argument a date */ void addSearchCriteria( SearchCriteria criteria, const QDate& argument ); /** * Add a custom criteria. No checks are done, the data is sent as it is * to the server. * @param searchCriteria free form search criteria. */ void addSearchCriteria( const QByteArray &searchCriteria ); /** * Set the logic combining the search criterias. * @param logic AND (the default), OR, NOT. See SearchLogics. */ void setSearchLogic(SearchLogic logic); protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/selectjob.h b/kimap/selectjob.h index 213d070de..c67d28c06 100644 --- a/kimap/selectjob.h +++ b/kimap/selectjob.h @@ -1,67 +1,67 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SELECTJOB_H #define KIMAP_SELECTJOB_H #include "kimap_export.h" #include "job.h" namespace KIMAP { class Session; -class Message; +struct Message; class SelectJobPrivate; class KIMAP_EXPORT SelectJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SelectJob) friend class SessionPrivate; public: explicit SelectJob( Session *session ); virtual ~SelectJob(); void setMailBox( const QString &mailBox ); QString mailBox() const; void setOpenReadOnly( bool readOnly ); bool isOpenReadOnly() const; QList flags() const; QList permanentFlags() const; int messageCount() const; int recentCount() const; int firstUnseenIndex() const; qint64 uidValidity() const; qint64 nextUid() const; protected: virtual void doStart(); virtual void handleResponse( const Message &response ); }; } #endif diff --git a/kimap/session.h b/kimap/session.h index 109c2d469..bad692bb6 100644 --- a/kimap/session.h +++ b/kimap/session.h @@ -1,76 +1,76 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SESSION_H #define KIMAP_SESSION_H #include "kimap_export.h" #include class KSslErrorUiData; namespace KIMAP { class SessionUiProxy; class SessionPrivate; class JobPrivate; -class Message; +struct Message; class KIMAP_EXPORT Session : public QObject { Q_OBJECT Q_ENUMS(State) friend class JobPrivate; public: enum State { Disconnected = 0, NotAuthenticated, Authenticated, Selected }; Session( const QString &hostName, quint16 port, QObject *parent=0 ); ~Session(); QString hostName() const; quint16 port() const; State state() const; /** * Sets an ui proxy that displays the error messages and waits for user feedback. * @param proxy the ui proxy object */ void setUiProxy(SessionUiProxy *proxy); private: Q_PRIVATE_SLOT( d, void doStartNext() ) Q_PRIVATE_SLOT( d, void jobDone( KJob* ) ) Q_PRIVATE_SLOT( d, void jobDestroyed( QObject* ) ) Q_PRIVATE_SLOT( d, void responseReceived( const KIMAP::Message& ) ) Q_PRIVATE_SLOT( d, void socketConnected() ) Q_PRIVATE_SLOT( d, void socketDisconnected() ) Q_PRIVATE_SLOT( d, void socketError() ) Q_PRIVATE_SLOT( d, void handleSslError( const KSslErrorUiData &errorData ) ) friend class SessionPrivate; SessionPrivate *const d; }; } #endif diff --git a/kimap/session_p.h b/kimap/session_p.h index 410c3ad6e..8cced20e8 100644 --- a/kimap/session_p.h +++ b/kimap/session_p.h @@ -1,96 +1,96 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SESSION_P_H #define KIMAP_SESSION_P_H #include "session.h" #include #include #include #include class KJob; namespace KIMAP { class Job; -class Message; +struct Message; class SessionThread; class SessionUiProxy; class SessionPrivate : public QObject { Q_OBJECT friend class Session; public: SessionPrivate( Session *session ); void addJob(Job *job); QByteArray sendCommand( const QByteArray &command, const QByteArray &args = QByteArray() ); void startSsl(const KTcpSocket::SslVersion &version); void sendData( const QByteArray &data ); QString selectedMailBox() const; void handleSslError( const KSslErrorUiData &errorData ); Q_SIGNALS: void encryptionNegotiationResult(bool); private: void reconnect(); void startNext(); void doStartNext(); void jobDone( KJob *job ); void jobDestroyed( QObject *job ); void responseReceived( const KIMAP::Message &response ); void socketConnected(); void socketDisconnected(); void socketError(); Session *const q; Session::State state; SessionThread *thread; SessionUiProxy *uiProxy; bool jobRunning; Job *currentJob; QQueue queue; QByteArray authTag; QByteArray selectTag; QByteArray closeTag; QByteArray currentMailBox; QByteArray upcomingMailBox; quint16 tagCount; }; } #endif diff --git a/kimap/sessionthread_p.h b/kimap/sessionthread_p.h index 375c29c99..97d5230a4 100644 --- a/kimap/sessionthread_p.h +++ b/kimap/sessionthread_p.h @@ -1,84 +1,84 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SESSIONTHREAD_P_H #define KIMAP_SESSIONTHREAD_P_H #include #include #include #include typedef KTcpSocket SessionSocket; namespace KIMAP { class ImapStreamParser; -class Message; +struct Message; class Session; class SessionThread : public QThread { Q_OBJECT public: explicit SessionThread( const QString &hostName, quint16 port, Session *parent ); ~SessionThread(); inline QString hostName() { return m_hostName; } inline quint16 port() { return m_port; } void sendData( const QByteArray &payload ); void run(); public slots: void closeSocket(); void reconnect(); void startSsl(const KTcpSocket::SslVersion &version); signals: void responseReceived(const KIMAP::Message &response); void encryptionNegotiationResult(bool); void sslError(const KSslErrorUiData&); private slots: void readMessage(); void writeDataQueue(); void sslConnected(); void sslErrorHandlerResponse(bool result); private: QString m_hostName; quint16 m_port; Session *m_session; SessionSocket *m_socket; ImapStreamParser *m_stream; QQueue m_dataQueue; QMutex m_mutex; bool m_encryptedMode; }; } #endif diff --git a/kimap/setacljob.h b/kimap/setacljob.h index 89d8b8b72..7edda81d4 100644 --- a/kimap/setacljob.h +++ b/kimap/setacljob.h @@ -1,56 +1,56 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SETACLJOB_H #define KIMAP_SETACLJOB_H #include "kimap_export.h" #include "acljobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class SetAclJobPrivate; class KIMAP_EXPORT SetAclJob : public AclJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetAclJob) friend class SessionPrivate; public: explicit SetAclJob( Session *session ); virtual ~SetAclJob(); void setRights(AclModifier modifier, Acl::Rights rights); void setIdentifier( const QByteArray &identifier ); QByteArray identifier(); protected: virtual void doStart(); }; } #endif diff --git a/kimap/setmetadatajob.h b/kimap/setmetadatajob.h index 3b6bd0d87..4302fcfb2 100644 --- a/kimap/setmetadatajob.h +++ b/kimap/setmetadatajob.h @@ -1,90 +1,90 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SETMETADATAJOB_H #define KIMAP_SETMETADATAJOB_H #include "kimap_export.h" #include "metadatajobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class SetMetaDataJobPrivate; class KIMAP_EXPORT SetMetaDataJob : public MetaDataJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetMetaDataJob) friend class SessionPrivate; public: explicit SetMetaDataJob( Session *session ); virtual ~SetMetaDataJob(); /** * Add a metadata to the mailbox. Depending on the supported standard by the server (setServerCapability), * the @param name can have a different meaning. * @param name the entry name if serverCapability() returns Metadata (RFC5464 mode), the attribute value name * if serverCapability() is Annotatemore (draft-daboo-imap-annotatemore-07 mode). * @param value the value of the entry/attribute */ void addMetaData(const QByteArray &name, const QByteArray &value); /** * Set the entry name for the metada, if the job is operating in Annotatemore mode. In Metadata mode, this setting is * ignored. * @param entry the metadata entry name */ void setEntry(const QByteArray &entry); enum MetaDataError { NoError = 0, TooMany = 1, TooBig = 2, NoPrivate = 4 }; // Q_DECLARE_WHATEVER_THAT_WAS missing Q_DECLARE_FLAGS(MetaDataErrors, MetaDataError) /** * The metadata errors recived from the server. * @return OR connected error codes, see MetaDataError */ MetaDataErrors metaDataErrors() const; /** * The maximum accepted metadata size. * @return the accepted metadata size, -1 means the limit is unknown. */ qint64 maxAcceptedSize(); protected: virtual void doStart(); virtual void handleResponse( const Message &response ); }; } Q_DECLARE_OPERATORS_FOR_FLAGS( KIMAP::SetMetaDataJob::MetaDataErrors ) #endif diff --git a/kimap/setquotajob.h b/kimap/setquotajob.h index 39d179a00..db16acbc7 100644 --- a/kimap/setquotajob.h +++ b/kimap/setquotajob.h @@ -1,61 +1,61 @@ /* Copyright (c) 2009 Andras Mantia This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_SETQUOTAJOB_H #define KIMAP_SETQUOTAJOB_H #include "quotajobbase.h" namespace KIMAP { class Session; -class Message; +struct Message; class SetQuotaJobPrivate; class KIMAP_EXPORT SetQuotaJob : public QuotaJobBase { Q_OBJECT Q_DECLARE_PRIVATE(SetQuotaJob) friend class SessionPrivate; public: explicit SetQuotaJob( Session *session ); virtual ~SetQuotaJob(); /** * Set a limit for a quota resource * @param resource quota resouce name * @param limit limit for the resouce */ // use qint64 for all the quota stuff void setQuota(const QByteArray& resource, qint64 limit); void setRoot(const QByteArray &root); QByteArray root() const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/kimap/storejob.h b/kimap/storejob.h index 0ea5d9c4f..7c41d905d 100644 --- a/kimap/storejob.h +++ b/kimap/storejob.h @@ -1,75 +1,75 @@ /* Copyright (c) 2009 Kevin Ottens This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 KIMAP_STOREJOB_H #define KIMAP_STOREJOB_H #include "kimap_export.h" #include "job.h" #include "imapset.h" namespace KIMAP { class Session; -class Message; +struct Message; class StoreJobPrivate; typedef QList MessageFlags; class KIMAP_EXPORT StoreJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(StoreJob) friend class SessionPrivate; public: enum StoreMode { SetFlags, AppendFlags, RemoveFlags }; explicit StoreJob( Session *session ); virtual ~StoreJob(); void setSequenceSet( const ImapSet &set ); ImapSet sequenceSet() const; void setUidBased( bool uidBased ); bool isUidBased() const; void setFlags( const MessageFlags &flags ); MessageFlags flags() const; void setMode( StoreMode mode ); StoreMode mode() const; QMap resultingFlags() const; protected: virtual void doStart(); virtual void handleResponse(const Message &response); }; } #endif diff --git a/mailtransport/transportmanager.cpp b/mailtransport/transportmanager.cpp index 57160af24..c5154d104 100644 --- a/mailtransport/transportmanager.cpp +++ b/mailtransport/transportmanager.cpp @@ -1,582 +1,608 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 "transportmanager.h" #include "mailtransport_defs.h" #include "transport.h" #include "transportconfigwidget.h" #include "transportjob.h" #include "transporttypeinfo.h" +#include "transportconfigdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace MailTransport; using namespace KWallet; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class TransportManager::Private { public: Private() {} ~Private() { delete config; qDeleteAll( transports ); } KConfig *config; QList transports; bool myOwnChange; bool appliedChange; KWallet::Wallet *wallet; bool walletOpenFailed; bool walletAsyncOpen; int defaultTransportId; bool isMainInstance; QList walletQueue; }; class StaticTransportManager : public TransportManager { public: StaticTransportManager() : TransportManager() {} }; StaticTransportManager *sSelf = 0; static void destroyStaticTransportManager() { delete sSelf; } TransportManager::TransportManager() : QObject(), d( new Private ) { KGlobal::locale()->insertCatalog( QLatin1String( "libmailtransport" ) ); qAddPostRoutine( destroyStaticTransportManager ); d->myOwnChange = false; d->appliedChange = false; d->wallet = 0; d->walletOpenFailed = false; d->walletAsyncOpen = false; d->defaultTransportId = -1; d->config = new KConfig( QLatin1String( "mailtransports" ) ); QDBusConnection::sessionBus().registerObject( DBUS_OBJECT_PATH, this, QDBusConnection::ExportScriptableSlots | QDBusConnection::ExportScriptableSignals ); QDBusConnection::sessionBus().connect( QString(), QString(), DBUS_INTERFACE_NAME, DBUS_CHANGE_SIGNAL, this, SLOT(slotTransportsChanged()) ); d->isMainInstance = QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); connect( QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), SLOT(dbusServiceOwnerChanged(QString,QString,QString)) ); } TransportManager::~TransportManager() { qRemovePostRoutine( destroyStaticTransportManager ); delete d; } TransportManager *TransportManager::self() { if ( !sSelf ) { sSelf = new StaticTransportManager; sSelf->readConfig(); } return sSelf; } Transport *TransportManager::transportById( int id, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->id() == id ) { return t; } } if ( def || ( id == 0 && d->defaultTransportId != id ) ) { return transportById( d->defaultTransportId, false ); } return 0; } Transport *TransportManager::transportByName( const QString &name, bool def ) const { foreach ( Transport *t, d->transports ) { if ( t->name() == name ) { return t; } } if ( def ) { return transportById( 0, false ); } return 0; } QList< Transport * > TransportManager::transports() const { return d->transports; } Transport *TransportManager::createTransport() const { int id = createId(); Transport *t = new Transport( QString::number( id ) ); t->setId( id ); return t; } void TransportManager::addTransport( Transport *transport ) { if ( d->transports.contains( transport ) ) { return; } d->transports.append( transport ); validateDefault(); emitChangesCommitted(); } void TransportManager::schedule( TransportJob *job ) { connect( job, SIGNAL(result(KJob*)), SLOT(jobResult(KJob*)) ); // check if the job is waiting for the wallet if ( !job->transport()->isComplete() ) { kDebug() << "job waits for wallet:" << job; d->walletQueue << job; loadPasswordsAsync(); return; } job->start(); } void TransportManager::createDefaultTransport() { KEMailSettings kes; Transport *t = createTransport(); t->setName( i18n( "Default Transport" ) ); t->setHost( kes.getSetting( KEMailSettings::OutServer ) ); if ( t->isValid() ) { t->writeConfig(); addTransport( t ); } else { kWarning() << "KEMailSettings does not contain a valid transport."; } } +bool TransportManager::checkTransport( QWidget *parent ) +{ + if ( !isEmpty() ) + return true; + + const int response = KMessageBox::messageBox( parent, + KMessageBox::WarningContinueCancel, + i18n("You must create an outgoing account before sending."), + i18n("Create Account Now?"), + KGuiItem( i18n("Create Account Now") ) ); + if ( response == KMessageBox::Continue ) { + Transport* transport = createTransport(); + TransportConfigDialog* dialog = new TransportConfigDialog( transport, parent ); + dialog->setAttribute( Qt::WA_DeleteOnClose ); + dialog->setWindowModality( Qt::WindowModal ); + if ( ( dialog->exec() == QDialog::Accepted ) && transport->isValid() ) { + addTransport( transport ); + return true; + } else { + delete transport; + } + } + return false; +} + TransportJob *TransportManager::createTransportJob( int transportId ) { Transport *t = transportById( transportId, false ); if ( !t ) { return 0; } return TransportTypeInfo::jobForTransport( t->clone(), this ); } TransportJob *TransportManager::createTransportJob( const QString &transport ) { bool ok = false; Transport *t = 0; int transportId = transport.toInt( &ok ); if ( ok ) { t = transportById( transportId ); } if ( !t ) { t = transportByName( transport, false ); } if ( t ) { return createTransportJob( t->id() ); } return 0; } bool TransportManager::isEmpty() const { return d->transports.isEmpty(); } QList TransportManager::transportIds() const { QList rv; foreach ( Transport *t, d->transports ) { rv << t->id(); } return rv; } QStringList TransportManager::transportNames() const { QStringList rv; foreach ( Transport *t, d->transports ) { rv << t->name(); } return rv; } QString TransportManager::defaultTransportName() const { Transport *t = transportById( d->defaultTransportId, false ); if ( t ) { return t->name(); } return QString(); } int TransportManager::defaultTransportId() const { return d->defaultTransportId; } void TransportManager::setDefaultTransport( int id ) { if ( id == d->defaultTransportId || !transportById( id, false ) ) { return; } d->defaultTransportId = id; writeConfig(); } void TransportManager::removeTransport( int id ) { Transport *t = transportById( id, false ); if ( !t ) { return; } emit transportRemoved( t->id(), t->name() ); d->transports.removeAll( t ); validateDefault(); QString group = t->currentGroup(); delete t; d->config->deleteGroup( group ); writeConfig(); } void TransportManager::readConfig() { QList oldTransports = d->transports; d->transports.clear(); QRegExp re( QLatin1String( "^Transport (.+)$" ) ); QStringList groups = d->config->groupList().filter( re ); foreach ( const QString &s, groups ) { re.indexIn( s ); Transport *t = 0; // see if we happen to have that one already foreach ( Transport *old, oldTransports ) { if ( old->currentGroup() == QLatin1String( "Transport " ) + re.cap( 1 ) ) { kDebug() << "reloading existing transport:" << s; t = old; t->readConfig(); oldTransports.removeAll( old ); break; } } if ( !t ) { t = new Transport( re.cap( 1 ) ); } if ( t->id() <= 0 ) { t->setId( createId() ); t->writeConfig(); } d->transports.append( t ); } qDeleteAll( oldTransports ); oldTransports.clear(); // read default transport KConfigGroup group( d->config, "General" ); d->defaultTransportId = group.readEntry( "default-transport", 0 ); if ( d->defaultTransportId == 0 ) { // migrated default transport contains the name instead QString name = group.readEntry( "default-transport", QString() ); if ( !name.isEmpty() ) { Transport *t = transportByName( name, false ); if ( t ) { d->defaultTransportId = t->id(); writeConfig(); } } } validateDefault(); migrateToWallet(); } void TransportManager::writeConfig() { KConfigGroup group( d->config, "General" ); group.writeEntry( "default-transport", d->defaultTransportId ); d->config->sync(); emitChangesCommitted(); } void TransportManager::emitChangesCommitted() { d->myOwnChange = true; // prevent us from reading our changes again d->appliedChange = false; // but we have to read them at least once emit transportsChanged(); emit changesCommitted(); } void TransportManager::slotTransportsChanged() { if ( d->myOwnChange && d->appliedChange ) { d->myOwnChange = false; d->appliedChange = false; return; } kDebug(); d->config->reparseConfiguration(); // FIXME: this deletes existing transport objects! readConfig(); d->appliedChange = true; // to prevent recursion emit transportsChanged(); } int TransportManager::createId() const { QList usedIds; foreach ( Transport *t, d->transports ) { usedIds << t->id(); } usedIds << 0; // 0 is default for unknown int newId; do { newId = KRandom::random(); } while ( usedIds.contains( newId ) ); return newId; } KWallet::Wallet * TransportManager::wallet() { if ( d->wallet && d->wallet->isOpen() ) { return d->wallet; } if ( !Wallet::isEnabled() || d->walletOpenFailed ) { return 0; } WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } delete d->wallet; d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window ); if ( !d->wallet ) { d->walletOpenFailed = true; return 0; } prepareWallet(); return d->wallet; } void TransportManager::prepareWallet() { if ( !d->wallet ) { return; } if ( !d->wallet->hasFolder( WALLET_FOLDER ) ) { d->wallet->createFolder( WALLET_FOLDER ); } d->wallet->setFolder( WALLET_FOLDER ); } void TransportManager::loadPasswords() { foreach ( Transport *t, d->transports ) { t->readPassword(); } // flush the wallet queue foreach ( TransportJob *job, d->walletQueue ) { job->start(); } d->walletQueue.clear(); emit passwordsChanged(); } void TransportManager::loadPasswordsAsync() { kDebug(); // check if there is anything to do at all bool found = false; foreach ( Transport *t, d->transports ) { if ( !t->isComplete() ) { found = true; break; } } if ( !found ) { return; } // async wallet opening if ( !d->wallet && !d->walletOpenFailed ) { WId window = 0; if ( qApp->activeWindow() ) { window = qApp->activeWindow()->winId(); } else if ( !QApplication::topLevelWidgets().isEmpty() ) { window = qApp->topLevelWidgets().first()->winId(); } d->wallet = Wallet::openWallet( Wallet::NetworkWallet(), window, Wallet::Asynchronous ); if ( d->wallet ) { connect( d->wallet, SIGNAL(walletOpened(bool)), SLOT(slotWalletOpened(bool)) ); d->walletAsyncOpen = true; } else { d->walletOpenFailed = true; loadPasswords(); } return; } if ( d->wallet && !d->walletAsyncOpen ) { loadPasswords(); } } void TransportManager::slotWalletOpened( bool success ) { kDebug(); d->walletAsyncOpen = false; if ( !success ) { d->walletOpenFailed = true; delete d->wallet; d->wallet = 0; } else { prepareWallet(); } loadPasswords(); } void TransportManager::validateDefault() { if ( !transportById( d->defaultTransportId, false ) ) { if ( isEmpty() ) { d->defaultTransportId = -1; } else { d->defaultTransportId = d->transports.first()->id(); writeConfig(); } } } void TransportManager::migrateToWallet() { // check if we tried this already static bool firstRun = true; if ( !firstRun ) { return; } firstRun = false; // check if we are the main instance if ( !d->isMainInstance ) { return; } // check if migration is needed QStringList names; foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { names << t->name(); } } if ( names.isEmpty() ) { return; } // ask user if he wants to migrate int result = KMessageBox::questionYesNoList( 0, i18n( "The following mail transports store their passwords in an " "unencrypted configuration file.\nFor security reasons, " "please consider migrating these passwords to KWallet, the " "KDE Wallet management tool,\nwhich stores sensitive data " "for you in a strongly encrypted file.\n" "Do you want to migrate your passwords to KWallet?" ), names, i18n( "Question" ), KGuiItem( i18n( "Migrate" ) ), KGuiItem( i18n( "Keep" ) ), QString::fromAscii( "WalletMigrate" ) ); if ( result != KMessageBox::Yes ) { return; } // perform migration foreach ( Transport *t, d->transports ) { if ( t->needsWalletMigration() ) { t->migrateToWallet(); } } } void TransportManager::dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ) { Q_UNUSED( oldOwner ); if ( service == DBUS_SERVICE_NAME && newOwner.isEmpty() ) { QDBusConnection::sessionBus().registerService( DBUS_SERVICE_NAME ); } } void TransportManager::jobResult( KJob *job ) { d->walletQueue.removeAll( static_cast( job ) ); } #include "transportmanager.moc" diff --git a/mailtransport/transportmanager.h b/mailtransport/transportmanager.h index 376efc4f2..64acdcc5e 100644 --- a/mailtransport/transportmanager.h +++ b/mailtransport/transportmanager.h @@ -1,255 +1,263 @@ /* Copyright (c) 2006 - 2007 Volker Krause This library 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. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; 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 MAILTRANSPORT_TRANSPORTMANAGER_H #define MAILTRANSPORT_TRANSPORTMANAGER_H #include #include #include class KJob; namespace KWallet { class Wallet; } namespace MailTransport { class Transport; class TransportConfigWidget; class TransportJob; /** Takes care of loading and storing mail transport settings and creating of transport jobs. */ class MAILTRANSPORT_EXPORT TransportManager : public QObject { Q_OBJECT Q_CLASSINFO( "D-Bus Interface", "org.kde.pim.TransportManager" ) friend class Transport; friend class Private; public: class Private; /** Destructor. */ virtual ~TransportManager(); /** Returns the TransportManager instance. */ static TransportManager *self(); /** Tries to load passwords asynchronously from KWallet if needed. The passwordsChanged() signal is emitted once the passwords have been loaded. Nothing happens if the passwords were already available. */ void loadPasswordsAsync(); /** Returns the Transport object with the given id. @param id The identifier of the Transport. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use. It might become invalid as soon as the event loop is entered again due to remote changes. If you need to store a Transport object, store the transport identifier instead. */ Transport *transportById( int id, bool def = true ) const; /** Returns the transport object with the given name. @param name The transport name. @param def if set to true, the default transport will be returned if the specified Transport object could not be found, 0 otherwise. @returns A Transport object for immediate use, see transportById() for limitations. */ Transport *transportByName( const QString &name, bool def = true ) const; /** Returns a list of all available transports. Note: The Transport objects become invalid as soon as a change occur, so they are only suitable for immediate use. */ QListtransports() const; /** Creates a new, empty Transport object. The object is owned by the caller. If you want to add the Transport permanently (eg. after configuring it) call addTransport(). */ Transport *createTransport() const; /** Adds the given transport. The object ownership is transferred to TransportMananger, ie. you must not delete @p transport. @param transport The Transport object to add. */ void addTransport( Transport *transport ); /** Creates a mail transport job for the given transport identifier. Returns 0 if the specified transport is invalid. @param transportId The transport identifier. */ TransportJob *createTransportJob( int transportId ); /** Creates a mail transport job for the given transport identifer, or transport name. Returns 0 if the specified transport is invalid. @param transport A string defining a mail transport. */ TransportJob *createTransportJob( const QString &transport ); /** Executes the given transport job. This is the preferred way to start transport jobs. It takes care of asynchronously loading passwords from KWallet if necessary. @param job The completely configured transport job to execute. */ void schedule( TransportJob *job ); /** Tries to create a transport based on KEMailSettings. If the data in KEMailSettings is incomplete, no transport is created. */ void createDefaultTransport(); + /** + Check for an existing transport, and show a configuration dialog if not. + Returns true if transport exists or user creates one. Otherwise false. + @param parent Parent widget of the dialog + @since 4.4 + */ + bool checkTransport( QWidget *parent ); + public Q_SLOTS: /** Returns true if there are no mail transports at all. */ Q_SCRIPTABLE bool isEmpty() const; /** Returns a list of transport identifiers. */ Q_SCRIPTABLE QList transportIds() const; /** Returns a list of transport names. */ Q_SCRIPTABLE QStringList transportNames() const; /** Returns the default transport name. */ Q_SCRIPTABLE QString defaultTransportName() const; /** Returns the default transport identifier. Invalid if there are no transports at all. */ Q_SCRIPTABLE int defaultTransportId() const; /** Sets the default transport. The change will be in effect immediately. @param id The identifier of the new default transport. */ Q_SCRIPTABLE void setDefaultTransport( int id ); /** Deletes the specified transport. @param id The identifier of the mail transport to remove. */ Q_SCRIPTABLE void removeTransport( int id ); Q_SIGNALS: /** Emitted when transport settings have changed (by this or any other TransportManager instance). */ Q_SCRIPTABLE void transportsChanged(); /** Internal signal to synchronize all TransportManager instances. This signal is emitted by the instance writing the changes. You probably want to use transportsChanged() instead. */ Q_SCRIPTABLE void changesCommitted(); /** Emitted when passwords have been loaded from the wallet. If you made a deep copy of a transport, you should call updatePasswordState() for the cloned transport to ensure its password is updated as well. */ void passwordsChanged(); /** Emitted when a transport is deleted. @param id The identifier of the deleted transport. @param name The name of the deleted transport. */ void transportRemoved( int id, const QString &name ); /** Emitted when a transport has been renamed. @param id The identifier of the renamed transport. @param oldName The old name. @param newName The new name. */ void transportRenamed( int id, const QString &oldName, const QString &newName ); protected: /** Returns a pointer to an open wallet if available, 0 otherwise. The wallet is opened synchronously if necessary. */ KWallet::Wallet *wallet(); /** Loads all passwords synchronously. */ void loadPasswords(); TransportManager(); private: void readConfig(); void writeConfig(); void emitChangesCommitted(); int createId() const; void prepareWallet(); void validateDefault(); void migrateToWallet(); private Q_SLOTS: void slotTransportsChanged(); void slotWalletOpened( bool success ); void dbusServiceOwnerChanged( const QString &service, const QString &oldOwner, const QString &newOwner ); void jobResult( KJob *job ); private: Private *const d; }; } #endif