From 761328989492db9bd603c2d7f1134d20e485d2f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Nicole?= Date: Tue, 27 Mar 2018 18:26:11 +0200 Subject: Add CalDAV support Summary: Notes: - Add a `webdavcommon` folder for WebDAV generic resource code - Move `davresource` to `carddaveresource` and make it use the WebDAV code - For now it tests the CalDAV resource directly on KolabNow (to be changed) - Only synchronization, not adding / changing / removing WebDAV collections or items (to be implemented) - Only events are currently supported (todo, freebusy, etc. are to be implemented but should be straightforward) Fixes T8224 Reviewers: cmollekopf Tags: #sink Maniphest Tasks: T8224 Differential Revision: https://phabricator.kde.org/D11741 --- examples/carddavresource/CMakeLists.txt | 11 ++ examples/carddavresource/carddavresource.cpp | 147 +++++++++++++++++++++++++++ examples/carddavresource/carddavresource.h | 63 ++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 examples/carddavresource/CMakeLists.txt create mode 100644 examples/carddavresource/carddavresource.cpp create mode 100644 examples/carddavresource/carddavresource.h (limited to 'examples/carddavresource') diff --git a/examples/carddavresource/CMakeLists.txt b/examples/carddavresource/CMakeLists.txt new file mode 100644 index 0000000..2c69d26 --- /dev/null +++ b/examples/carddavresource/CMakeLists.txt @@ -0,0 +1,11 @@ +project(sink_resource_carddav) + +add_definitions(-DQT_PLUGIN) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +find_package(KPimKDAV2 REQUIRED) + +add_library(${PROJECT_NAME} SHARED carddavresource.cpp) +target_link_libraries(${PROJECT_NAME} sink_webdav_common sink Qt5::Core Qt5::Network KPim::KDAV2) + +install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${SINK_RESOURCE_PLUGINS_PATH}) diff --git a/examples/carddavresource/carddavresource.cpp b/examples/carddavresource/carddavresource.cpp new file mode 100644 index 0000000..fc2b946 --- /dev/null +++ b/examples/carddavresource/carddavresource.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2015 Christian Mollekopf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "carddavresource.h" + +#include "../webdavcommon/webdav.h" + +#include "facade.h" +#include "resourceconfig.h" +#include "log.h" +#include "definitions.h" +#include "synchronizer.h" +#include "inspector.h" + +#include "facadefactory.h" +#include "adaptorfactoryregistry.h" + +#include "contactpreprocessor.h" + +//This is the resources entity type, and not the domain type +#define ENTITY_TYPE_CONTACT "contact" +#define ENTITY_TYPE_ADDRESSBOOK "addressbook" + +using namespace Sink; + +class ContactSynchronizer : public WebDavSynchronizer +{ +public: + ContactSynchronizer(const Sink::ResourceContext &resourceContext) + : WebDavSynchronizer(resourceContext, KDAV2::CardDav, + ApplicationDomain::getTypeName(), + ApplicationDomain::getTypeName()) + {} + QByteArray createAddressbook(const QString &addressbookName, const QString &addressbookPath, const QString &parentAddressbookRid) + { + SinkTrace() << "Creating addressbook: " << addressbookName << parentAddressbookRid; + const auto remoteId = addressbookPath.toUtf8(); + const auto bufferType = ENTITY_TYPE_ADDRESSBOOK; + Sink::ApplicationDomain::Addressbook addressbook; + addressbook.setName(addressbookName); + QHash mergeCriteria; + + if (!parentAddressbookRid.isEmpty()) { + addressbook.setParent(syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, parentAddressbookRid.toUtf8())); + } + createOrModify(bufferType, remoteId, addressbook, mergeCriteria); + return remoteId; + } + +protected: + void updateLocalCollections(KDAV2::DavCollection::List addressbookList) Q_DECL_OVERRIDE + { + const QByteArray bufferType = ENTITY_TYPE_ADDRESSBOOK; + SinkTrace() << "Found" << addressbookList.size() << "addressbooks"; + + for (const auto &f : addressbookList) { + const auto &rid = resourceID(f); + SinkLog() << "Found addressbook:" << rid << f.displayName(); + createAddressbook(f.displayName(), rid, ""); + } + } + + void updateLocalItem(KDAV2::DavItem remoteContact, const QByteArray &addressbookLocalId) Q_DECL_OVERRIDE + { + Sink::ApplicationDomain::Contact localContact; + + localContact.setVcard(remoteContact.data()); + localContact.setAddressbook(addressbookLocalId); + + QHash mergeCriteria; + createOrModify(ENTITY_TYPE_CONTACT, resourceID(remoteContact), localContact, mergeCriteria); + } + + QByteArray collectionLocalResourceID(const KDAV2::DavCollection &addressbook) Q_DECL_OVERRIDE + { + return syncStore().resolveRemoteId(ENTITY_TYPE_ADDRESSBOOK, resourceID(addressbook)); + } + + KAsync::Job replay(const ApplicationDomain::Contact &contact, Sink::Operation operation, const QByteArray &oldRemoteId, const QList &changedProperties) Q_DECL_OVERRIDE + { + return KAsync::null(); + } + + KAsync::Job replay(const ApplicationDomain::Addressbook &addressbook, Sink::Operation operation, const QByteArray &oldRemoteId, const QList &changedProperties) Q_DECL_OVERRIDE + { + return KAsync::null(); + } +}; + + +CardDavResource::CardDavResource(const Sink::ResourceContext &resourceContext) + : Sink::GenericResource(resourceContext) +{ + auto synchronizer = QSharedPointer::create(resourceContext); + setupSynchronizer(synchronizer); + + setupPreprocessors(ENTITY_TYPE_CONTACT, QVector() << new ContactPropertyExtractor); +} + + +CardDavResourceFactory::CardDavResourceFactory(QObject *parent) + : Sink::ResourceFactory(parent, + {Sink::ApplicationDomain::ResourceCapabilities::Contact::contact, + Sink::ApplicationDomain::ResourceCapabilities::Contact::addressbook, + Sink::ApplicationDomain::ResourceCapabilities::Contact::storage + } + ) +{ +} + +Sink::Resource *CardDavResourceFactory::createResource(const ResourceContext &context) +{ + return new CardDavResource(context); +} + +void CardDavResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory) +{ + factory.registerFacade>(name); + factory.registerFacade>(name); +} + +void CardDavResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry ®istry) +{ + registry.registerFactory>(name); + registry.registerFactory>(name); +} + +void CardDavResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier) +{ + CardDavResource::removeFromDisk(instanceIdentifier); +} diff --git a/examples/carddavresource/carddavresource.h b/examples/carddavresource/carddavresource.h new file mode 100644 index 0000000..3c0f707 --- /dev/null +++ b/examples/carddavresource/carddavresource.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 Christian Mollekopf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "common/genericresource.h" + +#include +#include + +#include + +class ContactAdaptorFactory; +class AddressbookAdaptorFactory; + +/** + * A CardDAV resource. + * + * Implementation details: + * The remoteid's have the following formats: + * files: full file path + * directories: full directory path + * + * The resource moves all messages from new to cur during sync and thus expectes all messages that are in the store to always reside in cur. + * The tmp directory is never directly used + */ +class CardDavResource : public Sink::GenericResource +{ +public: + CardDavResource(const Sink::ResourceContext &resourceContext); +}; + +class CardDavResourceFactory : public Sink::ResourceFactory +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "sink.carddav") + Q_INTERFACES(Sink::ResourceFactory) + +public: + CardDavResourceFactory(QObject *parent = 0); + + Sink::Resource *createResource(const Sink::ResourceContext &context) Q_DECL_OVERRIDE; + void registerFacades(const QByteArray &resourceName, Sink::FacadeFactory &factory) Q_DECL_OVERRIDE; + void registerAdaptorFactories(const QByteArray &resourceName, Sink::AdaptorFactoryRegistry ®istry) Q_DECL_OVERRIDE; + void removeDataFromDisk(const QByteArray &instanceIdentifier) Q_DECL_OVERRIDE; +}; + -- cgit v1.2.3