/*
* module-owncloud-backend.c
*
* This program 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 of the License, or (at your option) version 3.
*
* 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see
*
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include "owncloud-utils.h"
/* Standard GObject macros */
#define E_TYPE_OWNCLOUD_BACKEND \
(e_owncloud_backend_get_type ())
#define E_OWNCLOUD_BACKEND(obj) \
(G_TYPE_CHECK_INSTANCE_CAST \
((obj), E_TYPE_OWNCLOUD_BACKEND, EOwncloudBackend))
typedef struct _EOwncloudBackend EOwncloudBackend;
typedef struct _EOwncloudBackendClass EOwncloudBackendClass;
typedef struct _EOwncloudBackendFactory EOwncloudBackendFactory;
typedef struct _EOwncloudBackendFactoryClass EOwncloudBackendFactoryClass;
struct _EOwncloudBackend {
ECollectionBackend parent;
};
struct _EOwncloudBackendClass {
ECollectionBackendClass parent_class;
};
struct _EOwncloudBackendFactory {
ECollectionBackendFactory parent;
};
struct _EOwncloudBackendFactoryClass {
ECollectionBackendFactoryClass parent_class;
};
/* Module Entry Points */
void e_module_load (GTypeModule *type_module);
void e_module_unload (GTypeModule *type_module);
/* Forward Declarations */
GType e_owncloud_backend_get_type (void);
GType e_owncloud_backend_factory_get_type (void);
G_DEFINE_DYNAMIC_TYPE (
EOwncloudBackend,
e_owncloud_backend,
E_TYPE_COLLECTION_BACKEND)
G_DEFINE_DYNAMIC_TYPE (
EOwncloudBackendFactory,
e_owncloud_backend_factory,
E_TYPE_COLLECTION_BACKEND_FACTORY)
static void
owncloud_remove_unknown_sources_cb (gpointer resource_id,
gpointer uid,
gpointer user_data)
{
ESourceRegistryServer *server = user_data;
ESource *source;
source = e_source_registry_server_ref_source (server, uid);
if (source) {
e_source_registry_server_remove_source (server, source);
g_object_unref (source);
}
}
static void
owncloud_source_found_cb (ECollectionBackend *collection,
OwnCloudSourceType source_type,
SoupURI *uri,
const gchar *display_name,
const gchar *color,
gpointer user_data)
{
GHashTable *known_sources = user_data;
ESourceRegistryServer *server;
ESourceBackend *backend;
ESource *source = NULL;
const gchar *backend_name = NULL;
const gchar *provider = NULL;
const gchar *identity_prefix = NULL;
const gchar *source_uid;
gboolean is_new;
gchar *url;
gchar *identity;
g_return_if_fail (collection != NULL);
g_return_if_fail (uri != NULL);
g_return_if_fail (display_name != NULL);
g_return_if_fail (known_sources != NULL);
switch (source_type) {
case OwnCloud_Source_Contacts:
backend_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
provider = "webdav";
identity_prefix = "contacts";
break;
case OwnCloud_Source_Events:
backend_name = E_SOURCE_EXTENSION_CALENDAR;
provider = "caldav";
identity_prefix = "events";
break;
case OwnCloud_Source_Memos:
backend_name = E_SOURCE_EXTENSION_MEMO_LIST;
provider = "caldav";
identity_prefix = "memos";
break;
case OwnCloud_Source_Tasks:
backend_name = E_SOURCE_EXTENSION_TASK_LIST;
provider = "caldav";
identity_prefix = "tasks";
break;
}
g_return_if_fail (backend_name != NULL);
server = e_collection_backend_ref_server (collection);
url = soup_uri_to_string (uri, FALSE);
identity = g_strconcat (identity_prefix, "::", url, NULL);
source_uid = g_hash_table_lookup (known_sources, identity);
is_new = !source_uid;
if (is_new) {
ESource *master_source;
source = e_collection_backend_new_child (collection, identity);
g_warn_if_fail (source != NULL);
if (source) {
ESourceResource *resource;
ESourceWebdav *master_webdav, *child_webdav;
master_source = e_backend_get_source (E_BACKEND (collection));
master_webdav = e_source_get_extension (master_source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
child_webdav = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND);
resource = e_source_get_extension (source, E_SOURCE_EXTENSION_RESOURCE);
e_source_webdav_set_soup_uri (child_webdav, uri);
e_source_resource_set_identity (resource, identity);
/* inherit ssl trust options */
e_source_webdav_set_ssl_trust (child_webdav, e_source_webdav_get_ssl_trust (master_webdav));
}
} else {
source = e_source_registry_server_ref_source (server, source_uid);
g_warn_if_fail (source != NULL);
g_hash_table_remove (known_sources, identity);
}
g_free (identity);
g_free (url);
/* these properties are synchronized always */
if (source) {
backend = e_source_get_extension (source, backend_name);
e_source_backend_set_backend_name (backend, provider);
e_source_set_display_name (source, display_name);
if (source_type != OwnCloud_Source_Contacts && color)
e_source_selectable_set_color (E_SOURCE_SELECTABLE (backend), color);
if (is_new)
e_source_registry_server_add_source (server, source);
g_object_unref (source);
}
g_object_unref (server);
}
static void
owncloud_add_uid_to_hashtable (gpointer source,
gpointer known_sources)
{
ESourceResource *resource;
gchar *uid, *rid;
if (!e_source_has_extension (source, E_SOURCE_EXTENSION_RESOURCE))
return;
resource = e_source_get_extension (source, E_SOURCE_EXTENSION_RESOURCE);
uid = e_source_dup_uid (source);
if (!uid || !*uid) {
g_free (uid);
return;
}
rid = e_source_resource_dup_identity (resource);
if (!rid || !*rid) {
g_free (rid);
g_free (uid);
return;
}
g_hash_table_insert (known_sources, rid, uid);
}
static gpointer
owncloud_populate_thread (gpointer data)
{
ECollectionBackend *collection = data;
GHashTable *known_sources;
GList *sources;
g_return_val_if_fail (collection != NULL, NULL);
/* resource-id => source's UID */
known_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
sources = e_collection_backend_list_calendar_sources (collection);
g_list_foreach (sources, owncloud_add_uid_to_hashtable, known_sources);
g_list_free_full (sources, g_object_unref);
sources = e_collection_backend_list_contacts_sources (collection);
g_list_foreach (sources, owncloud_add_uid_to_hashtable, known_sources);
g_list_free_full (sources, g_object_unref);
if (owncloud_utils_search_server (collection, owncloud_source_found_cb, known_sources)) {
ESourceRegistryServer *server;
server = e_collection_backend_ref_server (collection);
g_hash_table_foreach (known_sources, owncloud_remove_unknown_sources_cb, server);
g_object_unref (server);
}
g_hash_table_destroy (known_sources);
g_object_unref (collection);
return NULL;
}
static void
owncloud_backend_populate (ECollectionBackend *collection)
{
GList *list, *liter;
ESourceRegistryServer *server;
GThread *thread;
/* Chain up to parent's populate() method. */
E_COLLECTION_BACKEND_CLASS (e_owncloud_backend_parent_class)->populate (collection);
server = e_collection_backend_ref_server (collection);
list = e_collection_backend_claim_all_resources (collection);
for (liter = list; liter; liter = g_list_next (liter)) {
ESource *source = liter->data;
if (e_source_has_extension (source, E_SOURCE_EXTENSION_RESOURCE)) {
ESourceResource *resource;
ESource *child;
resource = e_source_get_extension (source, E_SOURCE_EXTENSION_RESOURCE);
child = e_collection_backend_new_child (collection, e_source_resource_get_identity (resource));
if (child) {
e_source_registry_server_add_source (server, source);
g_object_unref (child);
}
}
}
g_list_free_full (list, g_object_unref);
g_object_unref (server);
thread = g_thread_new (NULL, owncloud_populate_thread, g_object_ref (collection));
g_thread_unref (thread);
}
static void
e_owncloud_backend_class_init (EOwncloudBackendClass *class)
{
ECollectionBackendClass *backend_class;
backend_class = E_COLLECTION_BACKEND_CLASS (class);
backend_class->populate = owncloud_backend_populate;
}
static void
e_owncloud_backend_class_finalize (EOwncloudBackendClass *class)
{
}
static void
e_owncloud_backend_init (EOwncloudBackend *backend)
{
}
static void
e_owncloud_backend_factory_class_init (EOwncloudBackendFactoryClass *class)
{
ECollectionBackendFactoryClass *factory_class;
factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class);
factory_class->factory_name = "owncloud";
factory_class->backend_type = E_TYPE_OWNCLOUD_BACKEND;
}
static void
e_owncloud_backend_factory_class_finalize (EOwncloudBackendFactoryClass *class)
{
}
static void
e_owncloud_backend_factory_init (EOwncloudBackendFactory *factory)
{
}
G_MODULE_EXPORT void
e_module_load (GTypeModule *type_module)
{
e_owncloud_backend_register_type (type_module);
e_owncloud_backend_factory_register_type (type_module);
}
G_MODULE_EXPORT void
e_module_unload (GTypeModule *type_module)
{
}