[evolution-mapi] Derive from EBookMetaBackend and ECalMetaBackend
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Derive from EBookMetaBackend and ECalMetaBackend
- Date: Mon, 29 May 2017 17:03:11 +0000 (UTC)
commit 8041b56dad48a4de55b5386ef25381b4256544a6
Author: Milan Crha <mcrha redhat com>
Date: Mon May 29 19:02:03 2017 +0200
Derive from EBookMetaBackend and ECalMetaBackend
src/addressbook/e-book-backend-mapi-contacts.c | 1088 +-------
src/addressbook/e-book-backend-mapi-contacts.h | 9 +-
src/addressbook/e-book-backend-mapi-gal.c | 322 +--
src/addressbook/e-book-backend-mapi-gal.h | 10 +-
src/addressbook/e-book-backend-mapi.c | 2129 +++++--------
src/addressbook/e-book-backend-mapi.h | 103 +-
src/calendar/e-cal-backend-mapi.c | 3900 +++++++-----------------
src/calendar/e-cal-backend-mapi.h | 4 +-
src/libexchangemapi/CMakeLists.txt | 2 -
src/libexchangemapi/e-mapi-cal-utils.c | 57 +-
src/libexchangemapi/e-mapi-cal-utils.h | 1 -
src/libexchangemapi/e-mapi-mail-utils.c | 2 +-
src/libexchangemapi/e-mapi-operation-queue.c | 337 --
src/libexchangemapi/e-mapi-operation-queue.h | 72 -
src/libexchangemapi/e-mapi-utils.c | 2 +-
15 files changed, 1897 insertions(+), 6141 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-mapi-contacts.c b/src/addressbook/e-book-backend-mapi-contacts.c
index b1a07f6..8f5a443 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.c
+++ b/src/addressbook/e-book-backend-mapi-contacts.c
@@ -23,1104 +23,30 @@
#include "evolution-mapi-config.h"
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n-lib.h>
-
-#include <sys/time.h>
-
-#include <libedataserver/libedataserver.h>
-#include <libedata-book/libedata-book.h>
-#include <libebook/libebook.h>
-#include <camel/camel.h>
-
#include "e-book-backend-mapi-contacts.h"
-#include "e-source-mapi-folder.h"
G_DEFINE_TYPE (EBookBackendMAPIContacts, e_book_backend_mapi_contacts, E_TYPE_BOOK_BACKEND_MAPI)
struct _EBookBackendMAPIContactsPrivate
{
- mapi_id_t fid;
- gboolean is_public_folder;
- gchar *foreign_username; /* NULL, if not a foreign folder */
+ gint32 unused;
};
-static gboolean
-ebbm_contacts_open_folder (EBookBackendMAPIContacts *ebmac,
- EMapiConnection *conn,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
-{
- gboolean res;
-
- g_return_val_if_fail (ebmac != NULL, FALSE);
- g_return_val_if_fail (ebmac->priv != NULL, FALSE);
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (obj_folder != NULL, FALSE);
-
- if (ebmac->priv->foreign_username)
- res = e_mapi_connection_open_foreign_folder (conn, ebmac->priv->foreign_username,
ebmac->priv->fid, obj_folder, cancellable, perror);
- else if (ebmac->priv->is_public_folder)
- res = e_mapi_connection_open_public_folder (conn, ebmac->priv->fid, obj_folder, cancellable,
perror);
- else
- res = e_mapi_connection_open_personal_folder (conn, ebmac->priv->fid, obj_folder,
cancellable, perror);
-
- return res;
-}
-
-typedef struct {
- EContact *contact;
- EBookBackendSqliteDB *db;
-} EMapiCreateitemData;
-
-static gboolean
-ebbm_contact_to_object (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- EMapiObject **pobject, /* out */
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- EMapiCreateitemData *mcd = user_data;
- const gchar *uid = NULL;
- EContact *old_contact = NULL;
- gboolean res;
- GError *error = NULL;
-
- g_return_val_if_fail (mcd != NULL, FALSE);
- g_return_val_if_fail (mcd->contact != NULL, FALSE);
- g_return_val_if_fail (mcd->db != NULL, FALSE);
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (mem_ctx != NULL, FALSE);
- g_return_val_if_fail (pobject != NULL, FALSE);
-
- uid = e_contact_get_const (mcd->contact, E_CONTACT_UID);
- if (uid)
- old_contact = e_book_backend_sqlitedb_get_contact (mcd->db, EMA_EBB_CACHE_FOLDERID, uid,
NULL, NULL, &error);
-
- if (error) {
- old_contact = NULL;
- g_clear_error (&error);
- }
-
- res = e_mapi_book_utils_contact_to_object (mcd->contact, old_contact, pobject, mem_ctx, cancellable,
perror);
-
- if (old_contact)
- g_object_unref (old_contact);
-
- return res;
-}
-
-struct TransferContactData
-{
- EBookBackendMAPI *ebma;
- EContact *contact; /* out */
-};
-
-static gboolean
-transfer_contact_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct TransferContactData *tc = user_data;
-
- g_return_val_if_fail (tc != NULL, FALSE);
- g_return_val_if_fail (tc->ebma != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
-
- tc->contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uid
(tc->ebma));
- if (tc->contact)
- return e_book_backend_mapi_notify_contact_update (tc->ebma, NULL, tc->contact, obj_index,
obj_total, FALSE, NULL);
-
- return TRUE;
-}
-
-static gboolean
-gather_contact_mids_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- const ListObjectsData *object_data,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- GSList **pmids = user_data;
- mapi_id_t *pmid;
-
- g_return_val_if_fail (object_data != NULL, FALSE);
- g_return_val_if_fail (pmids != NULL, FALSE);
-
- pmid = g_new0 (mapi_id_t, 1);
- *pmid = object_data->mid;
-
- *pmids = g_slist_prepend (*pmids, pmid);
-
- return TRUE;
-}
-
-struct TransferContactsData
-{
- EBookBackendMAPI *ebma;
- EDataBookView *book_view;
- gpointer notify_contact_data;
- GSList **cards;
-};
-
-static gboolean
-transfer_contacts_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct TransferContactsData *tcd = user_data;
- EContact *contact;
-
- g_return_val_if_fail (tcd != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (tcd->ebma != NULL, FALSE);
-
- contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uid
(tcd->ebma));
- if (contact) {
- if (tcd->cards)
- *tcd->cards = g_slist_prepend (*tcd->cards, e_vcard_to_string (E_VCARD (contact),
EVC_FORMAT_VCARD_30));
-
- if (!e_book_backend_mapi_notify_contact_update (tcd->ebma, tcd->book_view, contact,
obj_index, obj_total, FALSE, tcd->notify_contact_data)) {
- g_object_unref (contact);
- return FALSE;
- }
-
- g_object_unref (contact);
- } else {
- g_debug ("%s: [%d/%d] Failed to transform to contact", G_STRFUNC, obj_index, obj_total);
- }
-
- return TRUE;
-}
-
-static gboolean
-gather_known_uids_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- const ListObjectsData *object_data,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct ListKnownUidsData *lku = user_data;
- gchar *suid;
-
- g_return_val_if_fail (lku != NULL, FALSE);
- g_return_val_if_fail (lku->uid_to_rev != NULL, FALSE);
-
- suid = e_mapi_util_mapi_id_to_string (object_data->mid);
- if (suid) {
- g_hash_table_insert (lku->uid_to_rev, suid, e_mapi_book_utils_timet_to_string
(object_data->last_modified));
- if (lku->latest_last_modify < object_data->last_modified)
- lku->latest_last_modify = object_data->last_modified;
- }
-
- return TRUE;
-}
-
-static void
-ebbmc_server_notification_cb (EMapiConnection *conn,
- guint event_mask,
- gpointer event_data,
- gpointer user_data)
-{
- EBookBackendMAPI *ebma = user_data;
- EBookBackendMAPIContactsPrivate *priv;
- mapi_id_t update_folder1 = 0, update_folder2 = 0;
-
- g_return_if_fail (ebma != NULL);
-
- switch (event_mask) {
- case fnevNewMail:
- case fnevNewMail | fnevMbit: {
- struct NewMailNotification *newmail = event_data;
-
- if (newmail)
- update_folder1 = newmail->FID;
- } break;
- case fnevObjectCreated:
- case fnevMbit | fnevObjectCreated: {
- struct MessageCreatedNotification *msgcreated = event_data;
-
- if (msgcreated)
- update_folder1 = msgcreated->FID;
- } break;
- case fnevObjectModified:
- case fnevMbit | fnevObjectModified: {
- struct MessageModifiedNotification *msgmodified = event_data;
-
- if (msgmodified)
- update_folder1 = msgmodified->FID;
- } break;
- case fnevObjectDeleted:
- case fnevMbit | fnevObjectDeleted: {
- struct MessageDeletedNotification *msgdeleted = event_data;
-
- if (msgdeleted)
- update_folder1 = msgdeleted->FID;
- } break;
- case fnevObjectMoved:
- case fnevMbit | fnevObjectMoved: {
- struct MessageMoveCopyNotification *msgmoved = event_data;
-
- if (msgmoved) {
- update_folder1 = msgmoved->OldFID;
- update_folder2 = msgmoved->FID;
- }
- } break;
- case fnevObjectCopied:
- case fnevMbit | fnevObjectCopied: {
- struct MessageMoveCopyNotification *msgcopied = event_data;
-
- if (msgcopied) {
- update_folder1 = msgcopied->OldFID;
- update_folder2 = msgcopied->FID;
- }
- } break;
- default:
- break;
- }
-
- priv = ((EBookBackendMAPIContacts *) ebma)->priv;
- if ((priv->fid == update_folder1 || priv->fid == update_folder2) &&
- e_book_backend_mapi_is_marked_for_offline (ebma))
- e_book_backend_mapi_refresh_cache (ebma);
-}
-
-static void
-ebbm_contacts_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean only_if_exists, GError
**perror)
-{
- ESource *source = e_backend_get_source (E_BACKEND (ebma));
- ESourceMapiFolder *ext_mapi_folder;
- EBookBackendMAPIContactsPrivate *priv = ((EBookBackendMAPIContacts *) ebma)->priv;
- GError *err = NULL;
-
- if (e_book_backend_is_opened (E_BOOK_BACKEND (ebma))) {
- if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open)
- E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma,
cancellable, only_if_exists, perror);
- return;
- }
-
- ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
-
- priv->fid = e_source_mapi_folder_get_id (ext_mapi_folder);
- priv->is_public_folder = e_source_mapi_folder_is_public (ext_mapi_folder);
- priv->foreign_username = e_source_mapi_folder_dup_foreign_username (ext_mapi_folder);
-
- if (priv->foreign_username && !*priv->foreign_username) {
- g_free (priv->foreign_username);
- priv->foreign_username = NULL;
- }
-
- /* Chain up to parent's op_load_source() method. */
- if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open)
- E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma,
cancellable, only_if_exists, &err);
-
- if (err)
- g_propagate_error (perror, err);
-}
-
static void
-ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_online)
+e_book_backend_mapi_contacts_init (EBookBackendMAPIContacts *bbmcontacts)
{
- ESource *source;
- ESourceMapiFolder *ext_mapi_folder;
-
- e_book_backend_set_writable (E_BOOK_BACKEND (ebma), is_online);
-
- if (!is_online)
- return;
-
- source = e_backend_get_source (E_BACKEND (ebma));
- ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
-
- if (e_source_mapi_folder_get_server_notification (ext_mapi_folder)) {
- EMapiConnection *conn;
- mapi_object_t obj_folder;
- gboolean status;
- GError *mapi_error = NULL;
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, NULL, NULL);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
- return;
- }
-
- status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder,
NULL, &mapi_error);
-
- if (status) {
- e_mapi_connection_enable_notifications (conn, &obj_folder,
- fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved
| fnevObjectCopied,
- NULL, &mapi_error);
+ bbmcontacts->priv = G_TYPE_INSTANCE_GET_PRIVATE (bbmcontacts, E_TYPE_BOOK_BACKEND_MAPI_CONTACTS,
EBookBackendMAPIContactsPrivate);
- e_mapi_connection_close_folder (conn, &obj_folder, NULL, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- g_clear_error (&mapi_error);
-
- g_signal_connect (conn, "server-notification", G_CALLBACK (ebbmc_server_notification_cb),
ebma);
-
- e_book_backend_mapi_unlock_connection (ebma);
- }
-}
-
-static void
-ebbm_contacts_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError **error)
-{
- EBookBackendMAPIContactsPrivate *priv;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = E_BOOK_BACKEND_MAPI_CONTACTS (ebma)->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_remove)
- E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_remove (ebma,
cancellable, &mapi_error);
-
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
- g_error_free (mapi_error);
- return;
- }
-
- if (!priv->is_public_folder && !priv->foreign_username) {
- EMapiConnection *conn;
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error,
E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL);
- g_clear_error (&mapi_error);
- } else {
- mapi_object_t *obj_store = NULL;
-
- if (e_mapi_connection_peek_store (conn, priv->foreign_username ? FALSE :
priv->is_public_folder, priv->foreign_username, &obj_store, cancellable, &mapi_error))
- e_mapi_connection_remove_folder (conn, obj_store, priv->fid, cancellable,
&mapi_error);
-
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR,
_("Failed to remove public folder"));
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- g_error_free (mapi_error);
- }
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
- }
-}
-
-static void
-ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards,
GSList **added_contacts, GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- EMapiCreateitemData mcd;
- GError *mapi_error = NULL;
- mapi_id_t mid = 0;
- mapi_object_t obj_folder;
- gboolean status;
- gchar *id;
- EContact *contact;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (vcards != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (added_contacts != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- if (vcards->next) {
- g_propagate_error (error, EDB_ERROR_EX (NOT_SUPPORTED, _("The backend does not support bulk
additions")));
- return;
- }
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- contact = e_contact_new_from_vcard (vcards->data);
- if (!contact) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- e_book_backend_mapi_unlock_connection (ebma);
- return;
- }
-
- e_book_backend_mapi_get_db (ebma, &mcd.db);
- mcd.contact = contact;
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
- ebbm_contact_to_object, &mcd,
- &mid, cancellable, &mapi_error);
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mid) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
create item on a server"));
-
- if (mapi_error)
- g_error_free (mapi_error);
-
- g_object_unref (contact);
- return;
- }
-
- id = e_mapi_util_mapi_id_to_string (mid);
-
- /* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/
- e_contact_set (contact, E_CONTACT_UID, id);
- e_contact_set (contact, E_CONTACT_BOOK_UID, e_book_backend_mapi_get_book_uid (ebma));
-
- g_free (id);
-
- *added_contacts = g_slist_append (NULL, contact);
-}
-
-static void
-ebbm_contacts_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *id_list,
GSList **removed_ids, GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- GError *mapi_error = NULL;
- GSList *to_remove;
- const GSList *l;
- mapi_object_t obj_folder;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (id_list != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (removed_ids != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- to_remove = NULL;
- for (l = id_list; l; l = l->next) {
- const gchar *uid = l->data;
- mapi_id_t *pmid = g_new0 (mapi_id_t, 1);
-
- if (e_mapi_util_mapi_id_from_string (uid, pmid)) {
- to_remove = g_slist_prepend (to_remove, pmid);
-
- *removed_ids = g_slist_prepend (*removed_ids, g_strdup (uid));
- } else {
- g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, uid);
- g_free (pmid);
- }
- }
-
- if (ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error)) {
- e_mapi_connection_remove_items (conn, &obj_folder, to_remove, cancellable, &mapi_error);
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
-
- g_error_free (mapi_error);
-
- g_slist_foreach (*removed_ids, (GFunc) g_free, NULL);
- g_slist_free (*removed_ids);
- *removed_ids = NULL;
- }
-
- g_slist_foreach (to_remove, (GFunc) g_free, NULL);
- g_slist_free (to_remove);
-}
-
-static void
-ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards,
GSList **modified_contacts, GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- EMapiCreateitemData mcd;
- EContact *contact;
- GError *mapi_error = NULL;
- mapi_id_t mid;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (vcards != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (modified_contacts != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- if (vcards->next != NULL) {
- g_propagate_error (error, EDB_ERROR_EX (NOT_SUPPORTED, _("The backend does not support bulk
modifications")));
- return;
- }
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- contact = e_contact_new_from_vcard (vcards->data);
- if (!contact) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- e_book_backend_mapi_unlock_connection (ebma);
- return;
- }
-
- e_book_backend_mapi_get_db (ebma, &mcd.db);
- mcd.contact = contact;
-
- if (e_mapi_util_mapi_id_from_string (e_contact_get_const (contact, E_CONTACT_UID), &mid)) {
- mapi_object_t obj_folder;
- gboolean status;
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- status = e_mapi_connection_modify_object (conn, &obj_folder, mid,
- ebbm_contact_to_object, &mcd,
- cancellable, &mapi_error);
-
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- if (!status) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed
to modify item on a server"));
- if (mapi_error)
- g_error_free (mapi_error);
-
- g_object_unref (contact);
- } else {
- *modified_contacts = g_slist_append (NULL, contact);
- }
- } else {
- g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, (const gchar *) e_contact_get_const
(contact, E_CONTACT_UID));
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_contacts_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *id, gchar
**vcard, GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- mapi_id_t mid;
- mapi_object_t obj_folder;
- struct TransferContactData tc = { 0 };
- gboolean status, has_obj_folder;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (id != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (vcard != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_get_contact)
- E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_get_contact (ebma,
cancellable, id, vcard, &mapi_error);
-
- if (mapi_error) {
- g_propagate_error (error, mapi_error);
- return;
- }
-
- /* found in a cache */
- if (*vcard)
- return;
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
- has_obj_folder = status;
-
- if (status) {
- status = e_mapi_util_mapi_id_from_string (id, &mid);
- if (!status) {
- g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, id);
- }
- }
-
- if (status) {
- tc.ebma = ebma;
- tc.contact = NULL;
-
- e_mapi_connection_transfer_object (conn, &obj_folder, mid, transfer_contact_cb, &tc,
cancellable, &mapi_error);
- }
-
- if (has_obj_folder)
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
-
- if (tc.contact) {
- *vcard = e_vcard_to_string (E_VCARD (tc.contact), EVC_FORMAT_VCARD_30);
- g_object_unref (tc.contact);
- } else {
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- if (!mapi_error || mapi_error->code == MAPI_E_NOT_FOUND) {
- g_propagate_error (error, EDB_ERROR (CONTACT_NOT_FOUND));
- } else {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,
NULL);
- }
-
- if (mapi_error)
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_contacts_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *query,
GSList **vCards, GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- GError *mapi_error = NULL;
- gboolean status;
- mapi_object_t obj_folder;
- GSList *mids = NULL;
- struct TransferContactsData tcd = { 0 };
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (query != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (vCards != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_get_contact_list)
- E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_get_contact_list
(ebma, cancellable, query, vCards, &mapi_error);
-
- if (mapi_error) {
- g_propagate_error (error, mapi_error);
- return;
- }
-
- /* found some in cache, thus use them */
- if (*vCards)
- return;
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- tcd.ebma = ebma;
- tcd.cards = vCards;
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- status = e_mapi_connection_list_objects (conn, &obj_folder,
- e_mapi_book_utils_build_sexp_restriction, (gpointer)
query,
- gather_contact_mids_cb, &mids,
- cancellable, &mapi_error);
-
- if (mids)
- status = e_mapi_connection_transfer_objects (conn, &obj_folder, mids,
transfer_contacts_cb, &tcd, cancellable, &mapi_error);
-
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
-
- g_slist_free_full (mids, g_free);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- if (!status) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
fetch items from a server"));
- if (mapi_error)
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static gchar *
-ebbm_contacts_get_status_message (EBookBackendMAPI *ebma, gint index, gint total)
-{
- if (index <= 0)
- return NULL;
-
- if (total <= 0)
- return g_strdup_printf (
- /* Translators : This is used to cache the downloaded contacts from a server.
- %d is an index of the contact. */
- _("Caching contact %d"), index);
-
- return g_strdup_printf (
- /* Translators : This is used to cache the downloaded contacts from a server.
- The first %d is an index of the contact,
- the second %d is total count of conacts on the server. */
- _("Caching contact %d/%d"), index, total);
-}
-
-static void
-ebbm_contacts_get_contacts_count (EBookBackendMAPI *ebma,
- guint32 *obj_total,
- GCancellable *cancellable,
- GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EMapiConnection *conn;
- gboolean status;
- mapi_object_t obj_folder;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (obj_total != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- struct FolderBasicPropertiesData fbp = { 0 };
-
- status = e_mapi_connection_get_folder_properties (conn, &obj_folder, NULL, NULL,
- e_mapi_utils_get_folder_basic_properties_cb, &fbp,
- cancellable, &mapi_error);
- if (status)
- *obj_total = fbp.obj_total;
-
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
count server contacts"));
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_contacts_list_known_uids (EBookBackendMAPI *ebma,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- struct ListKnownUidsData *lku,
- GCancellable *cancellable,
- GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EMapiConnection *conn;
- gboolean status;
- mapi_object_t obj_folder;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (lku != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (lku->uid_to_rev != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (ebmac->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- status = e_mapi_connection_list_objects (conn, &obj_folder, build_rs_cb, build_rs_cb_data,
- gather_known_uids_cb, lku,
- cancellable, &mapi_error);
-
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to list
items from a server"));
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_contacts_transfer_contacts (EBookBackendMAPI *ebma,
- const GSList *uids,
- EDataBookView *book_view,
- gpointer notify_contact_data,
- GCancellable *cancellable,
- GError **error)
-{
- EBookBackendMAPIContacts *ebmac;
- EBookBackendMAPIContactsPrivate *priv;
- EMapiConnection *conn;
- struct TransferContactsData tcd = { 0 };
- mapi_object_t obj_folder;
- gboolean status;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma),
E_DATA_BOOK_STATUS_INVALID_ARG);
-
- ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma);
- e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- priv = ebmac->priv;
- e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- tcd.ebma = ebma;
- tcd.book_view = book_view;
- tcd.notify_contact_data = notify_contact_data;
-
- status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error);
-
- if (status) {
- GSList *mids = NULL;
- const GSList *iter;
-
- for (iter = uids; iter; iter = iter->next) {
- const gchar *uid_str = iter->data;
- mapi_id_t mid, *pmid;
-
- if (!uid_str || !e_mapi_util_mapi_id_from_string (uid_str, &mid))
- continue;
-
- pmid = g_new0 (mapi_id_t, 1);
- *pmid = mid;
-
- mids = g_slist_prepend (mids, pmid);
- }
-
- if (mids)
- status = e_mapi_connection_transfer_objects (conn, &obj_folder, mids,
transfer_contacts_cb, &tcd, cancellable, &mapi_error);
-
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
-
- g_slist_free_full (mids, g_free);
- }
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- if (!status) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
transfer contacts from a server"));
-
- if (mapi_error)
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-e_book_backend_mapi_contacts_init (EBookBackendMAPIContacts *backend)
-{
- backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, E_TYPE_BOOK_BACKEND_MAPI_CONTACTS,
EBookBackendMAPIContactsPrivate);
-
- backend->priv->foreign_username = NULL;
-}
-
-static void
-ebbm_contacts_finalize (GObject *object)
-{
- EBookBackendMAPIContactsPrivate *priv;
-
- priv = E_BOOK_BACKEND_MAPI_CONTACTS (object)->priv;
-
- g_free (priv->foreign_username);
- priv->foreign_username = NULL;
-
- G_OBJECT_CLASS (e_book_backend_mapi_contacts_parent_class)->finalize (object);
+ e_book_backend_mapi_set_is_gal (E_BOOK_BACKEND_MAPI (bbmcontacts), FALSE);
}
static void
e_book_backend_mapi_contacts_class_init (EBookBackendMAPIContactsClass *klass)
{
- EBookBackendMAPIClass *parent_class;
- GObjectClass *object_class;
+ EBookMetaBackendClass *meta_backend_class;
g_type_class_add_private (klass, sizeof (EBookBackendMAPIContactsPrivate));
- object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ebbm_contacts_finalize;
-
- parent_class = E_BOOK_BACKEND_MAPI_CLASS (klass);
-
- /* Set the virtual methods. */
- parent_class->op_open = ebbm_contacts_open;
- parent_class->op_remove = ebbm_contacts_remove;
- parent_class->op_create_contacts = ebbm_contacts_create_contacts;
- parent_class->op_remove_contacts = ebbm_contacts_remove_contacts;
- parent_class->op_modify_contacts = ebbm_contacts_modify_contacts;
- parent_class->op_get_contact = ebbm_contacts_get_contact;
- parent_class->op_get_contact_list = ebbm_contacts_get_contact_list;
-
- parent_class->op_connection_status_changed = ebbm_contacts_connection_status_changed;
- parent_class->op_get_status_message = ebbm_contacts_get_status_message;
- parent_class->op_get_contacts_count = ebbm_contacts_get_contacts_count;
- parent_class->op_list_known_uids = ebbm_contacts_list_known_uids;
- parent_class->op_transfer_contacts = ebbm_contacts_transfer_contacts;
-}
-
-EBookBackend *
-e_book_backend_mapi_contacts_new (void)
-{
- return g_object_new (E_TYPE_BOOK_BACKEND_MAPI_CONTACTS, NULL);
+ meta_backend_class = E_BOOK_META_BACKEND_CLASS (klass);
+ meta_backend_class->backend_factory_type_name = "EBookBackendMapiContactsFactory";
}
diff --git a/src/addressbook/e-book-backend-mapi-contacts.h b/src/addressbook/e-book-backend-mapi-contacts.h
index c09723c..1cc4769 100644
--- a/src/addressbook/e-book-backend-mapi-contacts.h
+++ b/src/addressbook/e-book-backend-mapi-contacts.h
@@ -21,8 +21,8 @@
*
*/
-#ifndef __E_BOOK_BACKEND_MAPI_CONTACTS_H__
-#define __E_BOOK_BACKEND_MAPI_CONTACTS_H__
+#ifndef E_BOOK_BACKEND_MAPI_CONTACTS_H
+#define E_BOOK_BACKEND_MAPI_CONTACTS_H
#include "e-book-backend-mapi.h"
@@ -39,7 +39,7 @@ typedef struct _EBookBackendMAPIContactsPrivate EBookBackendMAPIContactsPrivate;
typedef struct
{
- EBookBackendMAPI parent_object;
+ EBookBackendMAPI parent_object;
EBookBackendMAPIContactsPrivate *priv;
} EBookBackendMAPIContacts;
@@ -48,9 +48,8 @@ typedef struct
EBookBackendMAPIClass parent_class;
} EBookBackendMAPIContactsClass;
-EBookBackend *e_book_backend_mapi_contacts_new (void);
GType e_book_backend_mapi_contacts_get_type (void);
G_END_DECLS
-#endif /* __E_BOOK_BACKEND_MAPI_CONTACTS_H__ */
+#endif /* E_BOOK_BACKEND_MAPI_CONTACTS_H */
diff --git a/src/addressbook/e-book-backend-mapi-gal.c b/src/addressbook/e-book-backend-mapi-gal.c
index e189599..5204cf2 100644
--- a/src/addressbook/e-book-backend-mapi-gal.c
+++ b/src/addressbook/e-book-backend-mapi-gal.c
@@ -1,5 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
+ *
* 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
@@ -16,341 +19,34 @@
*
* Authors:
* Bharath Acharya <abharath novell com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
#include "evolution-mapi-config.h"
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib/gi18n-lib.h>
-
-#include <sys/time.h>
-
-#include <libedataserver/libedataserver.h>
-#include <libedata-book/libedata-book.h>
-#include <libebook/libebook.h>
-
#include "e-book-backend-mapi-gal.h"
-#include "e-source-mapi-folder.h"
-
-/* default value for "partial-count", upper bound of objects to download during partial search */
-#define DEFAULT_PARTIAL_COUNT 50
G_DEFINE_TYPE (EBookBackendMAPIGAL, e_book_backend_mapi_gal, E_TYPE_BOOK_BACKEND_MAPI)
struct _EBookBackendMAPIGALPrivate
{
- /* nothing to store locally at the moment,
- but keep it ready for any later need */
-
gint32 unused;
};
-struct TransferGalData
-{
- EBookBackendMAPI *ebma;
- EDataBookView *book_view;
- gpointer notify_contact_data;
-};
-
-static gboolean
-transfer_gal_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct TransferGalData *tg = user_data;
- EContact *contact;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (tg != NULL, FALSE);
-
- contact = e_mapi_book_utils_contact_from_object (conn, object, e_book_backend_mapi_get_book_uid
(tg->ebma));
- if (!contact) {
- /* this is GAL, just ignore them */
- return TRUE;
- }
-
- if (!e_book_backend_mapi_notify_contact_update (tg->ebma, tg->book_view, contact, obj_index,
obj_total, FALSE, tg->notify_contact_data)) {
- g_object_unref (contact);
- return FALSE;
- }
-
- g_object_unref (contact);
-
- return TRUE;
-}
-
-static gboolean
-list_gal_uids_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- const ListObjectsData *object_data,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- gchar *uid;
- struct ListKnownUidsData *lku = user_data;
-
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (object_data != NULL, FALSE);
- g_return_val_if_fail (lku != NULL, FALSE);
-
- uid = e_mapi_util_mapi_id_to_string (object_data->mid);
- if (uid) {
- if (lku->latest_last_modify < object_data->last_modified)
- lku->latest_last_modify = object_data->last_modified;
-
- g_hash_table_insert (lku->uid_to_rev, uid, e_mapi_book_utils_timet_to_string
(object_data->last_modified));
- }
-
- return TRUE;
-}
-
-static void
-ebbm_gal_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards, GSList
**added_contacts, GError **error)
-{
- g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
-}
-
-static void
-ebbm_gal_remove_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *ids, GSList
**removed_ids, GError **error)
-{
- g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
-}
-
static void
-ebbm_gal_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards, GSList
**modified_contacts, GError **error)
-{
- g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
-}
-
-static gchar *
-ebbm_gal_get_status_message (EBookBackendMAPI *ebma, gint index, gint total)
+e_book_backend_mapi_gal_init (EBookBackendMAPIGAL *bbmgal)
{
- if (index <= 0)
- return NULL;
-
- if (total <= 0)
- return g_strdup_printf (
- /* Translators : This is used to cache the downloaded contacts from GAL.
- %d is an index of the GAL entry. */
- _("Caching GAL contact %d"), index);
+ bbmgal->priv = G_TYPE_INSTANCE_GET_PRIVATE (bbmgal, E_TYPE_BOOK_BACKEND_MAPI_GAL,
EBookBackendMAPIGALPrivate);
- return g_strdup_printf (
- /* Translators : This is used to cache the downloaded contacts from GAL.
- The first %d is an index of the GAL entry,
- the second %d is total count of entries in GAL. */
- _("Caching GAL contact %d/%d"), index, total);
-}
-
-static void
-ebbm_gal_transfer_contacts (EBookBackendMAPI *ebma,
- const GSList *uids,
- EDataBookView *book_view,
- gpointer notify_contact_data,
- GCancellable *cancellable,
- GError **error)
-{
- GError *mapi_error = NULL;
- struct TransferGalData tg = { 0 };
- EMapiConnection *conn;
- ESource *source;
- ESourceMapiFolder *ext_mapi_folder;
- GSList *get_mids = NULL;
- const GSList *iter;
- gint partial_count = -1;
- gboolean status;
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- source = e_backend_get_source (E_BACKEND (ebma));
- ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
-
- if (ext_mapi_folder &&
- !e_book_backend_mapi_is_marked_for_offline (ebma) &&
- e_source_mapi_folder_get_allow_partial (ext_mapi_folder)) {
- partial_count = e_source_mapi_folder_get_partial_count (ext_mapi_folder);
-
- if (partial_count <= 0)
- partial_count = DEFAULT_PARTIAL_COUNT;
- }
-
- for (iter = uids; iter && (partial_count == -1 || partial_count > 0); iter = iter->next) {
- mapi_id_t *pmid, mid;
-
- if (e_mapi_util_mapi_id_from_string (iter->data, &mid)) {
- pmid = g_new0 (mapi_id_t, 1);
- *pmid = mid;
-
- get_mids = g_slist_prepend (get_mids, pmid);
-
- if (partial_count > 0)
- partial_count--;
- }
- }
-
- tg.ebma = ebma;
- tg.book_view = book_view;
- tg.notify_contact_data = notify_contact_data;
-
- status = e_mapi_connection_transfer_gal_objects (conn, get_mids, NULL, NULL, transfer_gal_cb, &tg,
cancellable, &mapi_error);
-
- if (mapi_error) {
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
-
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
fetch GAL entries"));
- g_error_free (mapi_error);
- } else if (!status) {
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Cancelled");
- }
-
- g_slist_free_full (get_mids, g_free);
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_gal_get_contacts_count (EBookBackendMAPI *ebma,
- guint32 *obj_total,
- GCancellable *cancellable,
- GError **error)
-{
- EMapiConnection *conn;
- GError *mapi_error = NULL;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (obj_total != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- if (!e_mapi_connection_count_gal_objects (conn, obj_total, cancellable, &mapi_error))
- *obj_total = -1;
-
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- if (mapi_error) {
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
- g_clear_error (&mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-ebbm_gal_list_known_uids (EBookBackendMAPI *ebma,
- BuildRestrictionsCB build_rs_cb,
- gpointer build_rs_cb_data,
- struct ListKnownUidsData *lku,
- GCancellable *cancellable,
- GError **error)
-{
- EMapiConnection *conn;
- GError *mapi_error = NULL;
-
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (lku != NULL);
- g_return_if_fail (lku->uid_to_rev != NULL);
-
- e_book_backend_mapi_lock_connection (ebma);
-
- conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error);
- if (!conn) {
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (!mapi_error)
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- else
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
NULL);
- g_clear_error (&mapi_error);
-
- return;
- }
-
- e_mapi_connection_list_gal_objects (conn, build_rs_cb, build_rs_cb_data, list_gal_uids_cb, lku,
cancellable, &mapi_error);
-
- if (mapi_error) {
- e_book_backend_mapi_maybe_disconnect (ebma, mapi_error);
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
fetch GAL entries"));
- g_error_free (mapi_error);
- }
-
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static void
-e_book_backend_mapi_gal_init (EBookBackendMAPIGAL *backend)
-{
- backend->priv = G_TYPE_INSTANCE_GET_PRIVATE (backend, E_TYPE_BOOK_BACKEND_MAPI_GAL,
EBookBackendMAPIGALPrivate);
+ e_book_backend_mapi_set_is_gal (E_BOOK_BACKEND_MAPI (bbmgal), TRUE);
}
static void
e_book_backend_mapi_gal_class_init (EBookBackendMAPIGALClass *klass)
{
- EBookBackendMAPIClass *parent_class;
+ EBookMetaBackendClass *meta_backend_class;
g_type_class_add_private (klass, sizeof (EBookBackendMAPIGALPrivate));
- parent_class = E_BOOK_BACKEND_MAPI_CLASS (klass);
-
- /* Set the virtual methods. */
- parent_class->op_create_contacts = ebbm_gal_create_contacts;
- parent_class->op_remove_contacts = ebbm_gal_remove_contacts;
- parent_class->op_modify_contacts = ebbm_gal_modify_contacts;
-
- parent_class->op_get_status_message = ebbm_gal_get_status_message;
- parent_class->op_get_contacts_count = ebbm_gal_get_contacts_count;
- parent_class->op_list_known_uids = ebbm_gal_list_known_uids;
- parent_class->op_transfer_contacts = ebbm_gal_transfer_contacts;
-}
-
-/**
- * e_book_backend_mapi_gal_new:
- */
-EBookBackend *
-e_book_backend_mapi_gal_new (void)
-{
- EBookBackendMAPIGAL *backend;
-
- backend = g_object_new (E_TYPE_BOOK_BACKEND_MAPI_GAL, NULL);
-
- return E_BOOK_BACKEND (backend);
+ meta_backend_class = E_BOOK_META_BACKEND_CLASS (klass);
+ meta_backend_class->backend_factory_type_name = "EBookBackendMapiGalFactory";
}
diff --git a/src/addressbook/e-book-backend-mapi-gal.h b/src/addressbook/e-book-backend-mapi-gal.h
index e9f1e82..fdec7dc 100644
--- a/src/addressbook/e-book-backend-mapi-gal.h
+++ b/src/addressbook/e-book-backend-mapi-gal.h
@@ -21,8 +21,8 @@
*
*/
-#ifndef __E_BOOK_BACKEND_MAPI_GAL_H__
-#define __E_BOOK_BACKEND_MAPI_GAL_H__
+#ifndef E_BOOK_BACKEND_MAPI_GAL_H
+#define E_BOOK_BACKEND_MAPI_GAL_H
#include "e-book-backend-mapi.h"
@@ -37,7 +37,7 @@ G_BEGIN_DECLS
typedef struct _EBookBackendMAPIGALPrivate EBookBackendMAPIGALPrivate;
typedef struct {
- EBookBackendMAPI parent_object;
+ EBookBackendMAPI parent_object;
EBookBackendMAPIGALPrivate *priv;
} EBookBackendMAPIGAL;
@@ -45,10 +45,8 @@ typedef struct {
EBookBackendMAPIClass parent_class;
} EBookBackendMAPIGALClass;
-EBookBackend *e_book_backend_mapi_gal_new (void);
GType e_book_backend_mapi_gal_get_type (void);
G_END_DECLS
-#endif /* __E_BOOK_BACKEND_MAPI_GAL_H__ */
-
+#endif /* E_BOOK_BACKEND_MAPI_GAL_H */
diff --git a/src/addressbook/e-book-backend-mapi.c b/src/addressbook/e-book-backend-mapi.c
index 355bae8..22bdd32 100644
--- a/src/addressbook/e-book-backend-mapi.c
+++ b/src/addressbook/e-book-backend-mapi.c
@@ -1,5 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
+ *
* 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
@@ -16,9 +19,6 @@
*
* Authors:
* Srinivasa Ragavan <sragavan novell com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
#include "evolution-mapi-config.h"
@@ -33,41 +33,85 @@
#include <libedataserver/libedataserver.h>
#include <camel/camel.h>
-#include <e-mapi-operation-queue.h>
-
#include "e-mapi-utils.h"
#include "e-mapi-defs.h"
+#include "e-source-mapi-folder.h"
#include "e-book-backend-mapi.h"
-G_DEFINE_TYPE (EBookBackendMAPI, e_book_backend_mapi, E_TYPE_BOOK_BACKEND)
+/* default value for "partial-count", upper bound of objects to download during partial search */
+#define DEFAULT_PARTIAL_COUNT 50
+
+#define EDB_ERROR(_code) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
+#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
struct _EBookBackendMAPIPrivate
{
- EMapiOperationQueue *op_queue;
-
GRecMutex conn_lock;
EMapiConnection *conn;
- gchar *book_uid;
- GThread *update_cache_thread;
- GCancellable *update_cache;
- time_t last_update_cache;
+ gboolean is_gal;
+};
- EBookBackendSqliteDB *db;
+G_DEFINE_TYPE (EBookBackendMAPI, e_book_backend_mapi, E_TYPE_BOOK_META_BACKEND)
- glong last_db_commit_time; /* when committed changes to db */
+static void
+ebb_mapi_error_to_edb_error (GError **perror,
+ const GError *mapi_error,
+ EDataBookStatus code,
+ const gchar *context)
+{
+ gchar *err_msg = NULL;
- guint32 last_server_contact_count;
- time_t last_modify_time;
- gboolean server_dirty;
+ if (!perror)
+ return;
- GHashTable *running_views; /* EDataBookView => GCancellable */
- GMutex running_views_lock;
-};
+ if (g_error_matches (mapi_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ g_propagate_error (perror, g_error_copy (mapi_error));
+ return;
+ }
+
+ if (code == E_DATA_BOOK_STATUS_OTHER_ERROR && mapi_error && mapi_error->domain == E_MAPI_ERROR) {
+ /* Change error to more accurate only with OTHER_ERROR */
+ switch (mapi_error->code) {
+ case MAPI_E_PASSWORD_CHANGE_REQUIRED:
+ case MAPI_E_PASSWORD_EXPIRED:
+ code = E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED;
+ break;
+ case ecRpcFailed:
+ code = E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (context)
+ err_msg = g_strconcat (context, mapi_error ? ": " : NULL, mapi_error ? mapi_error->message :
NULL, NULL);
+
+ g_propagate_error (perror, e_data_book_create_error (code, err_msg ? err_msg : mapi_error ?
mapi_error->message : _("Unknown error")));
+
+ g_free (err_msg);
+}
+
+static void
+ebb_mapi_lock_connection (EBookBackendMAPI *bbmapi)
+{
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi));
+
+ g_rec_mutex_lock (&bbmapi->priv->conn_lock);
+}
+
+static void
+ebb_mapi_unlock_connection (EBookBackendMAPI *bbmapi)
+{
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi));
+
+ g_rec_mutex_unlock (&bbmapi->priv->conn_lock);
+}
static CamelMapiSettings *
-ebbm_get_collection_settings (EBookBackendMAPI *ebbm)
+ebb_mapi_get_collection_settings (EBookBackendMAPI *ebbm)
{
ESource *source;
ESource *collection;
@@ -95,1217 +139,922 @@ ebbm_get_collection_settings (EBookBackendMAPI *ebbm)
return CAMEL_MAPI_SETTINGS (settings);
}
-static glong
-get_current_time_ms (void)
+static gboolean
+ebb_mapi_contacts_open_folder (EBookBackendMAPI *bbmapi,
+ mapi_object_t *out_obj_folder,
+ GCancellable *cancellable,
+ GError **error)
{
- GTimeVal tv;
-
- g_get_current_time (&tv);
+ ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
+ mapi_id_t fid;
+ gchar *foreign_username;
+ gboolean success;
- return tv.tv_sec * 1000 + tv.tv_usec / 1000;
-}
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
+ g_return_val_if_fail (bbmapi->priv->conn != NULL, FALSE);
+ g_return_val_if_fail (out_obj_folder != NULL, FALSE);
-static EDataBookView *
-ebbm_pick_book_view (EBookBackendMAPI *ebma)
-{
- EDataBookView *pick = NULL;
- GList *list;
+ source = e_backend_get_source (E_BACKEND (bbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- list = e_book_backend_list_views (E_BOOK_BACKEND (ebma));
+ fid = e_source_mapi_folder_get_id (ext_mapi_folder);
+ foreign_username = e_source_mapi_folder_dup_foreign_username (ext_mapi_folder);
- if (list != NULL) {
- /* Note we return a new reference. */
- pick = g_object_ref (list->data);
- }
+ if (foreign_username && *foreign_username)
+ success = e_mapi_connection_open_foreign_folder (bbmapi->priv->conn, foreign_username, fid,
out_obj_folder, cancellable, error);
+ else if (e_source_mapi_folder_is_public (ext_mapi_folder))
+ success = e_mapi_connection_open_public_folder (bbmapi->priv->conn, fid, out_obj_folder,
cancellable, error);
+ else
+ success = e_mapi_connection_open_personal_folder (bbmapi->priv->conn, fid, out_obj_folder,
cancellable, error);
- g_list_free_full (list, g_object_unref);
+ g_free (foreign_username);
- return pick;
+ return success;
}
static void
-complete_views (EBookBackendMAPI *ebma)
+ebb_mapi_maybe_disconnect (EBookBackendMAPI *bbmapi,
+ const GError *mapi_error)
{
- GList *list, *link;
-
- list = e_book_backend_list_views (E_BOOK_BACKEND (ebma));
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- EDataBookView *view = E_DATA_BOOK_VIEW (link->data);
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi));
- if (e_book_backend_mapi_book_view_is_running (ebma, view))
- e_book_backend_mapi_update_view_by_cache (ebma, view, NULL);
+ /* no error or already disconnected */
+ if (!mapi_error || !bbmapi->priv->conn)
+ return;
- e_data_book_view_notify_complete (view, NULL);
+ if (g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed) ||
+ g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
+ e_mapi_connection_disconnect (bbmapi->priv->conn,
+ !g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed),
+ NULL, NULL);
+ g_clear_object (&bbmapi->priv->conn);
}
-
- g_list_free_full (list, g_object_unref);
}
-static void
-ebbm_notify_connection_status (EBookBackendMAPI *ebma, gboolean is_online)
+static gboolean
+ebb_mapi_is_marked_for_offline (EBookBackendMAPI *bbmapi)
{
- EBookBackendMAPIClass *ebmac;
+ ESource *source;
+ ESourceOffline *offline_extension;
+
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
+ source = e_backend_get_source (E_BACKEND (bbmapi));
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
- g_return_if_fail (ebmac != NULL);
+ offline_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE);
- if (ebmac->op_connection_status_changed)
- ebmac->op_connection_status_changed (ebma, is_online);
+ return e_source_offline_get_stay_synchronized (offline_extension);
}
static void
-ebbm_transfer_contacts (EBookBackendMAPI *ebma,
- const GSList *uids,
- EDataBookView *book_view,
- GCancellable *cancellable,
- GError **error)
+ebb_mapi_server_notification_cb (EMapiConnection *conn,
+ guint event_mask,
+ gpointer event_data,
+ gpointer user_data)
{
- EBookBackendMAPIClass *ebmac;
- glong last_notification = 0;
-
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (ebma->priv != NULL);
- g_return_if_fail (ebma->priv->conn != NULL);
-
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
- g_return_if_fail (ebmac != NULL);
- g_return_if_fail (ebmac->op_transfer_contacts != NULL);
+ EBookBackendMAPI *bbmapi = user_data;
+ mapi_id_t update_folder1 = 0, update_folder2 = 0;
+
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi));
+
+ switch (event_mask) {
+ case fnevNewMail:
+ case fnevNewMail | fnevMbit: {
+ struct NewMailNotification *newmail = event_data;
+
+ if (newmail)
+ update_folder1 = newmail->FID;
+ } break;
+ case fnevObjectCreated:
+ case fnevMbit | fnevObjectCreated: {
+ struct MessageCreatedNotification *msgcreated = event_data;
+
+ if (msgcreated)
+ update_folder1 = msgcreated->FID;
+ } break;
+ case fnevObjectModified:
+ case fnevMbit | fnevObjectModified: {
+ struct MessageModifiedNotification *msgmodified = event_data;
+
+ if (msgmodified)
+ update_folder1 = msgmodified->FID;
+ } break;
+ case fnevObjectDeleted:
+ case fnevMbit | fnevObjectDeleted: {
+ struct MessageDeletedNotification *msgdeleted = event_data;
+
+ if (msgdeleted)
+ update_folder1 = msgdeleted->FID;
+ } break;
+ case fnevObjectMoved:
+ case fnevMbit | fnevObjectMoved: {
+ struct MessageMoveCopyNotification *msgmoved = event_data;
+
+ if (msgmoved) {
+ update_folder1 = msgmoved->OldFID;
+ update_folder2 = msgmoved->FID;
+ }
+ } break;
+ case fnevObjectCopied:
+ case fnevMbit | fnevObjectCopied: {
+ struct MessageMoveCopyNotification *msgcopied = event_data;
+
+ if (msgcopied) {
+ update_folder1 = msgcopied->OldFID;
+ update_folder2 = msgcopied->FID;
+ }
+ } break;
+ default:
+ break;
+ }
- e_book_backend_sqlitedb_lock_updates (ebma->priv->db, NULL);
- ebma->priv->last_db_commit_time = get_current_time_ms ();
+ if (update_folder1 || update_folder2) {
+ ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
- ebmac->op_transfer_contacts (ebma, uids, book_view, &last_notification, cancellable, error);
+ source = e_backend_get_source (E_BACKEND (bbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- e_book_backend_sqlitedb_unlock_updates (ebma->priv->db, TRUE, NULL);
+ if (update_folder1 == e_source_mapi_folder_get_id (ext_mapi_folder) ||
+ update_folder2 == e_source_mapi_folder_get_id (ext_mapi_folder)) {
+ e_book_meta_backend_schedule_refresh (E_BOOK_META_BACKEND (bbmapi));
+ }
+ }
}
static gboolean
-unref_backend_idle_cb (gpointer data)
+ebb_mapi_connect_sync (EBookMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendMAPI *ebma = data;
-
- g_return_val_if_fail (ebma != NULL, FALSE);
-
- g_object_unref (ebma);
-
- return FALSE;
-}
-
-static gpointer
-ebbm_update_cache_cb (gpointer data)
-{
- EBookBackendMAPI *ebma = (EBookBackendMAPI *) data;
- EBookBackendMAPIPrivate *priv;
- EBookBackendMAPIClass *ebmac;
- guint32 server_stored_contacts = 0;
- time_t restr_tt = 0;
- gboolean partial_update = FALSE;
- GCancellable *cancellable;
- GError *error = NULL;
+ EBookBackendMAPI *bbmapi;
+ EMapiConnection *old_conn;
+ CamelMapiSettings *settings;
+ ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
+ GError *mapi_error = NULL;
- g_return_val_if_fail (ebma != NULL, NULL);
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), NULL);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_auth_result != NULL, FALSE);
- priv = ebma->priv;
- g_return_val_if_fail (priv != NULL, NULL);
- g_return_val_if_fail (priv->db != NULL, NULL);
- g_return_val_if_fail (priv->conn != NULL, NULL);
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
- g_return_val_if_fail (ebmac != NULL, NULL);
+ ebb_mapi_lock_connection (bbmapi);
- cancellable = priv->update_cache;
- g_cancellable_reset (cancellable);
+ if (bbmapi->priv->conn &&
+ e_mapi_connection_connected (bbmapi->priv->conn)) {
+ ebb_mapi_unlock_connection (bbmapi);
+ return TRUE;
+ }
- do {
- GHashTable *local_known_uids, *server_known_uids;
+ settings = ebb_mapi_get_collection_settings (bbmapi);
+ source = e_backend_get_source (E_BACKEND (bbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- priv->server_dirty = FALSE;
+ old_conn = bbmapi->priv->conn;
- local_known_uids = e_book_backend_sqlitedb_get_uids_and_rev (priv->db,
EMA_EBB_CACHE_FOLDERID, &error);
- server_known_uids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ bbmapi->priv->conn = e_mapi_connection_new (
+ e_book_backend_get_registry (E_BOOK_BACKEND (bbmapi)),
+ camel_mapi_settings_get_profile (settings),
+ credentials, cancellable, &mapi_error);
- if (!error && !g_cancellable_is_cancelled (cancellable) && ebmac->op_get_contacts_count) {
- ebmac->op_get_contacts_count (ebma, &server_stored_contacts, cancellable, &error);
- }
+ if (!bbmapi->priv->conn) {
+ bbmapi->priv->conn = e_mapi_connection_find (camel_mapi_settings_get_profile (settings));
+ if (bbmapi->priv->conn && !e_mapi_connection_connected (bbmapi->priv->conn))
+ e_mapi_connection_reconnect (bbmapi->priv->conn, credentials, cancellable,
&mapi_error);
+ }
- if (!error && !g_cancellable_is_cancelled (cancellable) && ebmac->op_list_known_uids) {
- struct ListKnownUidsData lku;
+ if (old_conn)
+ g_signal_handlers_disconnect_by_func (old_conn, G_CALLBACK (ebb_mapi_server_notification_cb),
bbmapi);
- restr_tt = priv->last_modify_time && server_stored_contacts == g_hash_table_size
(local_known_uids) ? priv->last_modify_time + 1 : 0;
- partial_update = restr_tt > 0;
+ g_clear_object (&old_conn);
- lku.uid_to_rev = server_known_uids;
- lku.latest_last_modify = priv->last_modify_time;
+ if (!bbmapi->priv->conn || mapi_error) {
+ gboolean is_network_error = mapi_error && mapi_error->domain != E_MAPI_ERROR;
- ebmac->op_list_known_uids (ebma, partial_update ?
e_mapi_utils_build_last_modify_restriction : NULL, &restr_tt, &lku, cancellable, &error);
+ g_clear_object (&bbmapi->priv->conn);
+ ebb_mapi_unlock_connection (bbmapi);
- restr_tt = lku.latest_last_modify;
- }
+ if (is_network_error)
+ ebb_mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, NULL);
- if (!error && !g_cancellable_is_cancelled (cancellable) && ebmac->op_transfer_contacts &&
local_known_uids) {
- GSList *uids = NULL;
- GHashTableIter iter;
- gpointer key, value;
+ g_clear_error (&mapi_error);
- g_hash_table_iter_init (&iter, server_known_uids);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- const gchar *uid = key, *rev = value, *local_rev;
+ *out_auth_result = is_network_error ? E_SOURCE_AUTHENTICATION_ERROR :
E_SOURCE_AUTHENTICATION_REJECTED;
- local_rev = g_hash_table_lookup (local_known_uids, uid);
- if (g_strcmp0 (local_rev, rev) != 0) {
- uids = g_slist_prepend (uids, (gpointer) uid);
- }
+ return FALSE;
+ }
- g_hash_table_remove (local_known_uids, uid);
- }
+ if (!e_book_backend_mapi_get_is_gal (bbmapi) &&
+ e_source_mapi_folder_get_server_notification (ext_mapi_folder)) {
+ mapi_object_t obj_folder;
+ GError *mapi_error = NULL;
- if (uids)
- ebbm_transfer_contacts (ebma, uids, NULL, cancellable, &error);
+ g_signal_connect (bbmapi->priv->conn, "server-notification", G_CALLBACK
(ebb_mapi_server_notification_cb), bbmapi);
- if (!error && !g_cancellable_is_cancelled (cancellable) && !partial_update) {
- e_book_backend_sqlitedb_lock_updates (priv->db, NULL);
+ if (ebb_mapi_contacts_open_folder (bbmapi, &obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_enable_notifications (bbmapi->priv->conn, &obj_folder,
+ fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved
| fnevObjectCopied,
+ cancellable, &mapi_error);
- g_hash_table_iter_init (&iter, local_known_uids);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- const gchar *uid = key;
+ e_mapi_connection_close_folder (bbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
+ }
- if (!uid)
- continue;
+ if (mapi_error) {
+ ebb_mapi_maybe_disconnect (bbmapi, mapi_error);
+ g_clear_error (&mapi_error);
+ }
+ }
- e_book_backend_mapi_notify_contact_removed (ebma, uid);
- }
+ ebb_mapi_unlock_connection (bbmapi);
- e_book_backend_sqlitedb_unlock_updates (priv->db, TRUE, NULL);
- }
+ *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
- priv->last_server_contact_count = server_stored_contacts;
- priv->last_modify_time = restr_tt;
+ return TRUE;
+}
- /* has borrowed data from server_known_uids */
- g_slist_free (uids);
- }
+static gboolean
+ebb_mapi_disconnect_sync (EBookMetaBackend *meta_backend,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookBackendMAPI *bbmapi;
+ gboolean success = TRUE;
- priv->last_update_cache = time(NULL);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
- g_hash_table_destroy (server_known_uids);
- if (local_known_uids)
- g_hash_table_destroy (local_known_uids);
- } while (!error && priv->server_dirty && !g_cancellable_is_cancelled (cancellable));
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- g_clear_error (&error);
+ ebb_mapi_lock_connection (bbmapi);
- complete_views (ebma);
+ if (bbmapi->priv->conn) {
+ g_signal_handlers_disconnect_by_func (bbmapi->priv->conn, G_CALLBACK
(ebb_mapi_server_notification_cb), bbmapi);
- /* indicate the thread is not running */
- g_cancellable_cancel (priv->update_cache);
+ success = e_mapi_connection_disconnect (bbmapi->priv->conn, FALSE, cancellable, error);
+ g_clear_object (&bbmapi->priv->conn);
+ }
- /* May unref it out of the thread, in case it's the last reference to it */
- g_idle_add (unref_backend_idle_cb, ebma);
+ ebb_mapi_unlock_connection (bbmapi);
- return NULL;
+ return success;
}
-static void
-ebbm_maybe_invoke_cache_update (EBookBackendMAPI *ebma)
-{
- EBookBackendMAPIPrivate *priv;
-
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (ebma->priv != NULL);
+typedef struct _LoadMultipleData {
+ gboolean is_gal;
+ gchar *book_uid;
+ GSList **out_contacts; /* EContact * */
+} LoadMultipleData;
- priv = ebma->priv;
+static gboolean
+transfer_contacts_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ LoadMultipleData *lmd = user_data;
+ EContact *contact;
- if (priv->update_cache_thread) {
- if (!g_cancellable_is_cancelled (priv->update_cache))
- return;
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (lmd != NULL, FALSE);
- g_thread_join (priv->update_cache_thread);
- priv->update_cache_thread = NULL;
+ contact = e_mapi_book_utils_contact_from_object (conn, object, lmd->book_uid);
+ if (!contact) {
+ /* being it GAL, just ignore failures */
+ return lmd->is_gal;
}
- /* do not update more often than each 10 minutes */
- if (time (NULL) - priv->last_update_cache >= 60 * 10) {
- g_object_ref (ebma);
+ *lmd->out_contacts = g_slist_prepend (*lmd->out_contacts, contact);
- g_cancellable_reset (priv->update_cache);
- priv->server_dirty = FALSE;
- priv->update_cache_thread = g_thread_new (NULL, ebbm_update_cache_cb, ebma);
- if (!priv->update_cache_thread)
- g_object_unref (ebma);
- }
+ return TRUE;
}
-static ESourceAuthenticationResult
-ebbm_connect_user (EBookBackendMAPI *ebma,
- const ENamedParameters *credentials,
- gboolean update_connection_status,
- GCancellable *cancellable,
- GError **error)
+static gboolean
+ebb_mapi_load_multiple_sync (EBookBackendMAPI *bbmapi,
+ const GSList *uids, /* gchar * */
+ GSList **out_contacts, /* EContact * */
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendMAPIPrivate *priv = ebma->priv;
- EMapiConnection *old_conn;
- CamelMapiSettings *settings;
+ LoadMultipleData lmd;
+ const gchar *error_text;
+ gint partial_count = -1;
+ GSList *mids = NULL, *link;
ESource *source;
+ gboolean success;
GError *mapi_error = NULL;
- settings = ebbm_get_collection_settings (ebma);
- source = e_backend_get_source (E_BACKEND (ebma));
-
- if (!e_backend_get_online (E_BACKEND (ebma))) {
- ebbm_notify_connection_status (ebma, FALSE);
- } else {
- if (priv->update_cache_thread) {
- g_cancellable_cancel (priv->update_cache);
- g_thread_join (priv->update_cache_thread);
- priv->update_cache_thread = NULL;
- }
-
- e_book_backend_mapi_lock_connection (ebma);
- if (update_connection_status)
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
- if (update_connection_status)
- e_source_set_connection_status (source,
E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- e_book_backend_mapi_unlock_connection (ebma);
- return E_SOURCE_AUTHENTICATION_ERROR;
- }
-
- old_conn = priv->conn;
- priv->conn = NULL;
-
- priv->conn = e_mapi_connection_new (
- e_book_backend_get_registry (E_BOOK_BACKEND (ebma)),
- camel_mapi_settings_get_profile (settings),
- credentials, cancellable, &mapi_error);
- if (!priv->conn) {
- priv->conn = e_mapi_connection_find (camel_mapi_settings_get_profile (settings));
- if (priv->conn && !e_mapi_connection_connected (priv->conn))
- e_mapi_connection_reconnect (priv->conn, credentials, cancellable,
&mapi_error);
- }
-
- if (old_conn)
- g_object_unref (old_conn);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
+ g_return_val_if_fail (uids != NULL, FALSE);
+ g_return_val_if_fail (out_contacts != NULL, FALSE);
- if (!priv->conn || mapi_error) {
- gboolean is_network_error = mapi_error && mapi_error->domain != E_MAPI_ERROR;
+ source = e_backend_get_source (E_BACKEND (bbmapi));
- if (priv->conn) {
- g_object_unref (priv->conn);
- priv->conn = NULL;
- }
-
- if (is_network_error)
- mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR,
NULL);
- if (update_connection_status)
- e_source_set_connection_status (source,
E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- e_book_backend_mapi_unlock_connection (ebma);
-
- if (mapi_error)
- g_error_free (mapi_error);
-
- ebbm_notify_connection_status (ebma, FALSE);
+ if (e_book_backend_mapi_get_is_gal (bbmapi) &&
+ !ebb_mapi_is_marked_for_offline (bbmapi)) {
+ ESourceMapiFolder *ext_mapi_folder;
- return is_network_error ? E_SOURCE_AUTHENTICATION_ERROR :
E_SOURCE_AUTHENTICATION_REJECTED;
- }
-
- if (update_connection_status)
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
- e_book_backend_mapi_unlock_connection (ebma);
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
+ if (e_source_mapi_folder_get_allow_partial (ext_mapi_folder)) {
+ partial_count = e_source_mapi_folder_get_partial_count (ext_mapi_folder);
- ebbm_notify_connection_status (ebma, TRUE);
-
- if (!g_cancellable_is_cancelled (cancellable) && e_book_backend_mapi_is_marked_for_offline
(ebma)) {
- ebbm_maybe_invoke_cache_update (ebma);
+ if (partial_count <= 0)
+ partial_count = DEFAULT_PARTIAL_COUNT;
}
}
- return E_SOURCE_AUTHENTICATION_ACCEPTED;
-}
+ for (link = (GSList *) uids; link && (partial_count == -1 || partial_count > 0); link = g_slist_next
(link)) {
+ mapi_id_t *pmid, mid;
-/* connection lock should be already held when calling this function */
-gboolean
-e_book_backend_mapi_ensure_connected (EBookBackendMAPI *ebma,
- GCancellable *cancellable,
- GError **error)
-{
- CamelMapiSettings *settings;
- GError *local_error = NULL;
+ if (e_mapi_util_mapi_id_from_string (link->data, &mid)) {
+ pmid = g_new0 (mapi_id_t, 1);
+ *pmid = mid;
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
+ mids = g_slist_prepend (mids, pmid);
- if (ebma->priv->conn && e_mapi_connection_connected (ebma->priv->conn))
- return TRUE;
-
- settings = ebbm_get_collection_settings (ebma);
-
- if (!camel_mapi_settings_get_kerberos (settings) ||
- ebbm_connect_user (ebma, NULL, TRUE, cancellable, &local_error) !=
E_SOURCE_AUTHENTICATION_ACCEPTED) {
- e_backend_credentials_required_sync (E_BACKEND (ebma),
- E_SOURCE_CREDENTIALS_REASON_REQUIRED, NULL, 0, NULL,
- cancellable, &local_error);
+ if (partial_count > 0)
+ partial_count--;
+ }
}
- if (!local_error)
- return TRUE;
-
- g_propagate_error (error, local_error);
-
- return FALSE;
-}
-
-/* connection lock should be already held when calling this function */
-void
-e_book_backend_mapi_maybe_disconnect (EBookBackendMAPI *ebma,
- const GError *mapi_error)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
-
- /* no error or already disconnected */
- if (!mapi_error || !ebma->priv->conn)
- return;
+ lmd.is_gal = e_book_backend_mapi_get_is_gal (bbmapi);
+ lmd.book_uid = e_source_dup_uid (source);
+ lmd.out_contacts = out_contacts;
- if (g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed) ||
- g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
- e_mapi_connection_disconnect (ebma->priv->conn,
- !g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed),
- NULL, NULL);
- g_object_unref (ebma->priv->conn);
- ebma->priv->conn = NULL;
- }
-}
+ ebb_mapi_lock_connection (bbmapi);
-static void
-ebbm_open (EBookBackendMAPI *ebma,
- GCancellable *cancellable,
- gboolean only_if_exists,
- GError **perror)
-{
- EBookBackendMAPIPrivate *priv = ebma->priv;
- ESource *source = e_backend_get_source (E_BACKEND (ebma));
- const gchar *cache_dir;
- GError *error = NULL;
+ if (e_book_backend_mapi_get_is_gal (bbmapi)) {
+ error_text = _("Failed to fetch GAL entries");
- if (e_book_backend_is_opened (E_BOOK_BACKEND (ebma)))
- return;
+ success = e_mapi_connection_transfer_gal_objects (bbmapi->priv->conn, mids, NULL, NULL,
transfer_contacts_cb, &lmd, cancellable, &mapi_error);
+ } else {
+ mapi_object_t obj_folder;
- if (priv->book_uid)
- g_free (priv->book_uid);
- priv->book_uid = e_source_dup_uid (source);
+ error_text = _("Failed to transfer contacts from a server");
- cache_dir = e_book_backend_get_cache_dir (E_BOOK_BACKEND (ebma));
+ success = ebb_mapi_contacts_open_folder (bbmapi, &obj_folder, cancellable, &mapi_error);
- if (priv->db)
- g_object_unref (priv->db);
- priv->db = e_book_backend_sqlitedb_new (cache_dir,
- EMA_EBB_CACHE_PROFILEID,
- EMA_EBB_CACHE_FOLDERID,
- EMA_EBB_CACHE_FOLDERID,
- TRUE, &error);
+ if (success) {
+ success = e_mapi_connection_transfer_objects (bbmapi->priv->conn, &obj_folder, mids,
transfer_contacts_cb, &lmd, cancellable, &mapi_error);
- if (error) {
- g_propagate_error (perror, error);
- return;
+ e_mapi_connection_close_folder (bbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
+ }
}
- e_book_backend_set_writable (E_BOOK_BACKEND (ebma), FALSE);
-
- ebbm_notify_connection_status (ebma, e_backend_get_online (E_BACKEND (ebma)));
+ if (mapi_error) {
+ ebb_mapi_maybe_disconnect (bbmapi, mapi_error);
+ ebb_mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, error_text);
+ g_error_free (mapi_error);
- /* Either we are in Online mode or this is marked for offline */
- if (!e_backend_get_online (E_BACKEND (ebma)) &&
- !e_book_backend_mapi_is_marked_for_offline (ebma)) {
- g_propagate_error (perror, EDB_ERROR (OFFLINE_UNAVAILABLE));
- return;
- }
-
- /* Once aunthentication in address book works this can be removed */
- if (!e_backend_get_online (E_BACKEND (ebma))) {
- e_backend_set_online (E_BACKEND (ebma), FALSE);
- return;
+ success = FALSE;
}
- e_backend_set_online (E_BACKEND (ebma), TRUE);
+ ebb_mapi_unlock_connection (bbmapi);
- e_book_backend_mapi_ensure_connected (ebma, cancellable, &error);
+ g_slist_free_full (mids, g_free);
+ g_free (lmd.book_uid);
- if (error)
- g_propagate_error (perror, error);
+ return success;
}
-static ESourceAuthenticationResult
-ebbm_authenticate_sync (EBackend *backend,
- const ENamedParameters *credentials,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GCancellable *cancellable,
- GError **error)
-{
- return ebbm_connect_user (E_BOOK_BACKEND_MAPI (backend), credentials, FALSE, cancellable, error);
-}
-
-static void
-ebbm_remove (EBookBackendMAPI *ebma, GCancellable *cancellable, GError **error)
+static gboolean
+ebb_mapi_preload_infos_sync (EBookBackendMAPI *bbmapi,
+ GSList *created_objects,
+ GSList *modified_objects,
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendMAPIPrivate *priv;
-
- e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), E_DATA_BOOK_STATUS_INVALID_ARG);
- e_mapi_return_data_book_error_if_fail (ebma->priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG);
+ GHashTable *infos;
+ GSList *uids = NULL, *link;
+ gboolean success = TRUE;
- priv = ebma->priv;
-
- if (!priv->book_uid)
- return;
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
- e_book_backend_mapi_lock_connection (ebma);
+ infos = g_hash_table_new (g_str_hash, g_str_equal);
- if (!priv->db) {
- const gchar *cache_dir = e_book_backend_get_cache_dir (E_BOOK_BACKEND (ebma));
+ for (link = created_objects; link; link = g_slist_next (link)) {
+ EBookMetaBackendInfo *nfo = link->data;
- /* pity, but it's required to be removed completely */
- priv->db = e_book_backend_sqlitedb_new (cache_dir,
- EMA_EBB_CACHE_PROFILEID,
- EMA_EBB_CACHE_FOLDERID,
- EMA_EBB_CACHE_FOLDERID,
- TRUE, NULL);
+ if (nfo && nfo->uid) {
+ uids = g_slist_prepend (uids, nfo->uid);
+ g_hash_table_insert (infos, nfo->uid, nfo);
+ }
}
- if (priv->db) {
- e_book_backend_sqlitedb_remove (priv->db, NULL);
- g_object_unref (priv->db);
- priv->db = NULL;
- }
+ for (link = modified_objects; link; link = g_slist_next (link)) {
+ EBookMetaBackendInfo *nfo = link->data;
- e_book_backend_mapi_unlock_connection (ebma);
-}
-
-static gchar *
-ebbm_get_backend_property (EBookBackend *backend,
- const gchar *prop_name)
-{
- EBookBackendMAPI *ebma;
-
- g_return_val_if_fail (prop_name != NULL, NULL);
-
- ebma = E_BOOK_BACKEND_MAPI (backend);
-
- if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
- if (e_book_backend_mapi_is_marked_for_offline (ebma))
- return g_strdup ("net,bulk-removes,contact-lists,do-initial-query");
- else
- return g_strdup ("net,bulk-removes,contact-lists");
- } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
- return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
- } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
- GSList *fields;
- gchar *prop_value;
-
- fields = e_mapi_book_utils_get_supported_contact_fields ();
- prop_value = e_data_book_string_slist_to_comma_string (fields);
- g_slist_free (fields);
-
- return prop_value;
+ if (nfo && nfo->uid) {
+ uids = g_slist_prepend (uids, nfo->uid);
+ g_hash_table_insert (infos, nfo->uid, nfo);
+ }
}
- /* Chain up to parent's get_backend_property() method. */
- return E_BOOK_BACKEND_CLASS (e_book_backend_mapi_parent_class)->
- get_backend_property (backend, prop_name);
-}
-
-static void
-ebbm_notify_online_cb (EBookBackend *backend, GParamSpec *pspec)
-{
- EBookBackendMAPI *ebma = E_BOOK_BACKEND_MAPI (backend);
- EBookBackendMAPIPrivate *priv = ebma->priv;
- gboolean online;
+ uids = g_slist_reverse (uids);
+ if (uids) {
+ GSList *contacts = NULL;
- online = e_backend_get_online (E_BACKEND (backend));
+ success = ebb_mapi_load_multiple_sync (bbmapi, uids, &contacts, cancellable, error);
+ if (success) {
+ for (link = contacts; link; link = g_slist_next (link)) {
+ EContact *contact = link->data;
- if (e_book_backend_is_opened (backend)) {
- e_book_backend_mapi_lock_connection (ebma);
+ if (contact) {
+ EBookMetaBackendInfo *nfo = g_hash_table_lookup (infos,
e_contact_get_const (contact, E_CONTACT_UID));
- if (!online) {
- e_book_backend_set_writable (backend, FALSE);
- ebbm_notify_connection_status (ebma, FALSE);
-
- if (priv->conn) {
- e_mapi_utils_unref_in_thread (G_OBJECT (priv->conn));
- priv->conn = NULL;
+ if (nfo && !nfo->object)
+ nfo->object = e_vcard_to_string (E_VCARD (contact),
EVC_FORMAT_VCARD_30);
+ }
}
- } else {
- ebbm_notify_connection_status (ebma, TRUE);
}
- e_book_backend_mapi_unlock_connection (ebma);
+ g_slist_free_full (contacts, g_object_unref);
}
-}
-
-static void
-ebbm_get_contact (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *id, gchar **vcard, GError
**error)
-{
- EBookBackendMAPIPrivate *priv;
- gchar *contact;
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (vcard != NULL);
+ g_hash_table_destroy (infos);
+ g_slist_free (uids);
- priv = ebma->priv;
- g_return_if_fail (priv != NULL);
-
- if (!priv->db) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- return;
- }
-
- contact = e_book_backend_sqlitedb_get_vcard_string (priv->db,
- EMA_EBB_CACHE_FOLDERID,
- id, NULL, NULL, error);
- if (contact)
- *vcard = contact;
- else
- g_propagate_error (error, EDB_ERROR (CONTACT_NOT_FOUND));
+ return success;
}
-static void
-ebbm_get_contact_list (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *query, GSList
**vCards, GError **error)
+static gboolean
+ebb_mapi_get_changes_sync (EBookMetaBackend *meta_backend,
+ const gchar *last_sync_tag,
+ gboolean is_repeat,
+ gchar **out_new_sync_tag,
+ gboolean *out_repeat,
+ GSList **out_created_objects,
+ GSList **out_modified_objects,
+ GSList **out_removed_objects,
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendMAPIPrivate *priv;
- GSList *hits, *l;
- GError *err = NULL;
-
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (query != NULL);
- g_return_if_fail (vCards != NULL);
+ EBookBackendMAPI *bbmapi;
- priv = ebma->priv;
- g_return_if_fail (priv != NULL);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_created_objects != NULL, FALSE);
+ g_return_val_if_fail (out_modified_objects != NULL, FALSE);
- if (!priv->db) {
- g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE));
- return;
+ /* Chain up to parent's method */
+ if (!E_BOOK_META_BACKEND_CLASS (e_book_backend_mapi_parent_class)->get_changes_sync (meta_backend,
+ last_sync_tag, is_repeat, out_new_sync_tag, out_repeat, out_created_objects,
+ out_modified_objects, out_removed_objects, cancellable, error)) {
+ return FALSE;
}
- hits = e_book_backend_sqlitedb_search (priv->db, EMA_EBB_CACHE_FOLDERID,
- query, NULL, NULL, NULL, &err);
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- for (l = hits; !err && l; l = l->next) {
- EbSdbSearchData *sdata = (EbSdbSearchData *) l->data;
- gchar *vcard = sdata->vcard;
+ /* Preload some of the contacts in chunk, to speed-up things;
+ ignore errors, to not break whole update process. */
+ ebb_mapi_preload_infos_sync (bbmapi, *out_created_objects, *out_modified_objects, cancellable, NULL);
- if (!err && vcard)
- *vCards = g_slist_prepend (*vCards, g_strdup (vcard));
-
- e_book_backend_sqlitedb_search_data_free (sdata);
- }
-
- if (err)
- g_propagate_error (error, err);
-
- g_slist_free (hits);
+ return TRUE;
}
-struct BookViewThreadData
-{
- EBookBackendMAPI *ebma;
- EDataBookView *book_view;
- GCancellable *cancellable;
-};
-
-static gpointer
-ebbm_book_view_thread (gpointer data)
+static gboolean
+ebb_mapi_list_existing_uids_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ const ListObjectsData *object_data,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- struct BookViewThreadData *bvtd = data;
- EBookBackendMAPIPrivate *priv;
- EBookBackendMAPIClass *ebmac;
- GError *error = NULL;
-
- g_return_val_if_fail (bvtd != NULL, NULL);
- g_return_val_if_fail (bvtd->ebma != NULL, NULL);
- g_return_val_if_fail (bvtd->book_view != NULL, NULL);
-
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (bvtd->ebma);
- g_return_val_if_fail (ebmac != NULL, NULL);
-
- priv = bvtd->ebma->priv;
-
- e_data_book_view_notify_progress (bvtd->book_view, -1, _("Searching"));
-
- if (!error && priv && priv->conn && (!priv->update_cache_thread || g_cancellable_is_cancelled
(priv->update_cache))
- && e_book_backend_mapi_book_view_is_running (bvtd->ebma, bvtd->book_view)) {
- EBookBackendMAPIClass *ebmac;
+ GSList **out_existing_objects = user_data;
+ gchar *uid;
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (bvtd->ebma);
- if (ebmac && ebmac->op_book_view_thread)
- ebmac->op_book_view_thread (bvtd->ebma, bvtd->book_view, priv->update_cache, &error);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (object_data != NULL, FALSE);
+ g_return_val_if_fail (out_existing_objects != NULL, FALSE);
- if (e_book_backend_mapi_is_marked_for_offline (bvtd->ebma)) {
- e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
+ uid = e_mapi_util_mapi_id_to_string (object_data->mid);
+ if (uid) {
+ gchar *rev;
- ebbm_maybe_invoke_cache_update (bvtd->ebma);
+ rev = e_mapi_book_utils_timet_to_string (object_data->last_modified);
- e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view, &error);
- } else if (ebmac && ebmac->op_list_known_uids && ebmac->op_transfer_contacts) {
- EBookBackendSExp *sexp;
- const gchar *query;
+ *out_existing_objects = g_slist_prepend (*out_existing_objects,
+ e_book_meta_backend_info_new (uid, rev, NULL, NULL));
- sexp = e_data_book_view_get_sexp (bvtd->book_view);
- query = e_book_backend_sexp_text (sexp);
+ g_free (uid);
+ g_free (rev);
+ }
- /* search only if not searching for everything */
- if (query && *query && g_ascii_strcasecmp (query, "(contains
\"x-evolution-any-field\" \"\")") != 0) {
- struct ListKnownUidsData lku = { 0 };
- GHashTable *local_known_uids, *server_known_uids;
+ return TRUE;
+}
- e_book_backend_mapi_update_view_by_cache (bvtd->ebma, bvtd->book_view,
&error);
+static gboolean
+ebb_mapi_list_existing_with_restrictions_sync (EBookMetaBackend *meta_backend,
+ BuildRestrictionsCB build_rs_cb,
+ gpointer build_rs_cb_data,
+ gchar **out_new_sync_tag,
+ GSList **out_existing_objects, /* EBookMetaBackendInfo * */
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookBackendMAPI *bbmapi;
+ const gchar *error_text;
+ gboolean success;
+ GError *mapi_error = NULL;
- local_known_uids = e_book_backend_sqlitedb_get_uids_and_rev (priv->db,
EMA_EBB_CACHE_FOLDERID, &error);
- server_known_uids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
g_free);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_existing_objects, FALSE);
- lku.uid_to_rev = server_known_uids;
- lku.latest_last_modify = 0;
+ *out_existing_objects = NULL;
- ebmac->op_list_known_uids (bvtd->ebma,
e_mapi_book_utils_build_sexp_restriction, (gpointer) query, &lku, bvtd->cancellable, &error);
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- if (!g_cancellable_is_cancelled (bvtd->cancellable)) {
- GSList *uids = NULL;
- GHashTableIter iter;
- gpointer key, value;
+ ebb_mapi_lock_connection (bbmapi);
- g_hash_table_iter_init (&iter, server_known_uids);
- while (g_hash_table_iter_next (&iter, &key, &value)) {
- const gchar *uid = key, *rev = value, *local_rev;
+ if (e_book_backend_mapi_get_is_gal (bbmapi)) {
+ error_text = _("Failed to fetch GAL entries");
- local_rev = g_hash_table_lookup (local_known_uids, uid);
- if (g_strcmp0 (local_rev, rev) != 0) {
- uids = g_slist_prepend (uids, (gpointer) uid);
- }
+ success = e_mapi_connection_list_gal_objects (bbmapi->priv->conn, NULL, NULL,
+ ebb_mapi_list_existing_uids_cb, out_existing_objects, cancellable, &mapi_error);
+ } else {
+ mapi_object_t obj_folder;
- g_hash_table_remove (local_known_uids, uid);
- }
+ error_text = _("Failed to list items from a server");
- if (uids) {
- ebbm_transfer_contacts (bvtd->ebma, uids, NULL,
bvtd->cancellable, &error);
- e_book_backend_mapi_update_view_by_cache (bvtd->ebma,
bvtd->book_view, &error);
- }
+ success = ebb_mapi_contacts_open_folder (bbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ success = e_mapi_connection_list_objects (bbmapi->priv->conn, &obj_folder, NULL, NULL,
+ ebb_mapi_list_existing_uids_cb, out_existing_objects, cancellable,
&mapi_error);
- /* has borrowed data from server_known_uids */
- g_slist_free (uids);
- }
-
- g_hash_table_destroy (server_known_uids);
- if (local_known_uids)
- g_hash_table_destroy (local_known_uids);
- }
+ e_mapi_connection_close_folder (bbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
}
}
- if (error && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_clear_error (&error);
+ if (mapi_error) {
+ ebb_mapi_maybe_disconnect (bbmapi, mapi_error);
+ ebb_mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, error_text);
+ g_error_free (mapi_error);
- /* do not stop book view when filling cache */
- if (e_book_backend_mapi_book_view_is_running (bvtd->ebma, bvtd->book_view)
- && (!priv->update_cache_thread || g_cancellable_is_cancelled (priv->update_cache)))
- e_data_book_view_notify_complete (bvtd->book_view, error);
-
- if (error)
- g_error_free (error);
+ success = FALSE;
+ }
- if (bvtd->cancellable)
- g_object_unref (bvtd->cancellable);
- g_object_unref (bvtd->book_view);
- /* May unref it out of the thread, in case it's the last reference to it */
- g_idle_add (unref_backend_idle_cb, bvtd->ebma);
- g_free (bvtd);
+ ebb_mapi_unlock_connection (bbmapi);
- return NULL;
+ return success;
}
-/* Async OP functions, data structures and so on */
-
-typedef enum {
- OP_OPEN,
-
- OP_CREATE_CONTACTS,
- OP_REMOVE_CONTACTS,
- OP_MODIFY_CONTACTS,
- OP_GET_CONTACT,
- OP_GET_CONTACT_LIST,
- OP_START_BOOK_VIEW,
- OP_STOP_BOOK_VIEW
-} OperationType;
-
-typedef struct {
- OperationType ot;
-
- EDataBook *book;
- guint32 opid;
- GCancellable *cancellable;
-} OperationBase;
-typedef struct {
- OperationBase base;
-
- gboolean only_if_exists;
-} OperationOpen;
-
-typedef struct {
- OperationBase base;
-
- gchar *str;
-} OperationStr;
-
-typedef struct {
- OperationBase base;
-
- GSList *str_slist;
-} OperationStrSlist;
-
-typedef struct {
- OperationBase base;
+static gboolean
+ebb_mapi_list_existing_sync (EBookMetaBackend *meta_backend,
+ gchar **out_new_sync_tag,
+ GSList **out_existing_objects,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
- EDataBookView *book_view;
-} OperationBookView;
+ return ebb_mapi_list_existing_with_restrictions_sync (meta_backend, NULL, NULL,
+ out_new_sync_tag, out_existing_objects, cancellable, error);
+}
-static void
-ebbm_operation_cb (OperationBase *op, gboolean cancelled, EBookBackend *backend)
+static gboolean
+ebb_mapi_load_contact_sync (EBookMetaBackend *meta_backend,
+ const gchar *uid,
+ const gchar *extra,
+ EContact **out_contact,
+ gchar **out_extra,
+ GCancellable *cancellable,
+ GError **error)
{
- EBookBackendMAPI *ebma;
- EBookBackendMAPIClass *ebmac;
- GError *error = NULL;
+ EBookBackendMAPI *bbmapi;
+ GSList *uids, *contacts = NULL;
+ gboolean success;
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND (backend));
- g_return_if_fail (op != NULL);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (out_contact != NULL, FALSE);
- ebma = E_BOOK_BACKEND_MAPI (backend);
- g_return_if_fail (ebma != NULL);
+ *out_contact = NULL;
- ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
- g_return_if_fail (ebmac != NULL);
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- cancelled = cancelled || (op->cancellable && g_cancellable_is_cancelled (op->cancellable));
+ uids = g_slist_prepend (NULL, (gpointer) uid);
- switch (op->ot) {
- case OP_OPEN: {
- OperationOpen *opo = (OperationOpen *) op;
+ success = ebb_mapi_load_multiple_sync (bbmapi, uids, &contacts, cancellable, error);
- if (!cancelled) {
- if (ebmac->op_open)
- ebmac->op_open (ebma, op->cancellable, opo->only_if_exists, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ ebb_mapi_unlock_connection (bbmapi);
- e_data_book_respond_open (op->book, op->opid, error);
- }
- } break;
- case OP_CREATE_CONTACTS: {
- OperationStrSlist *ops = (OperationStrSlist *) op;
+ if (success && contacts) {
+ *out_contact = g_object_ref (contacts->data);
+ }
- if (!cancelled) {
- GSList *added_contacts = NULL;
+ g_slist_free_full (contacts, g_object_unref);
+ g_slist_free (uids);
- if (ebmac->op_create_contacts)
- ebmac->op_create_contacts (ebma, op->cancellable, ops->str_slist,
&added_contacts, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ return success;
+}
- if (added_contacts && !error) {
- const GSList *l;
+typedef struct _SaveContactData {
+ EBookBackendMAPI *bbmapi;
+ EContact *contact;
+} SaveContactData;
- e_book_backend_sqlitedb_lock_updates (ebma->priv->db, NULL);
+static gboolean
+ebb_mapi_create_object_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ EMapiObject **pobject, /* out */
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SaveContactData *scd = user_data;
+ const gchar *uid = NULL;
+ EContact *old_contact = NULL;
+ gboolean success;
+
+ g_return_val_if_fail (scd != NULL, FALSE);
+ g_return_val_if_fail (scd->bbmapi != NULL, FALSE);
+ g_return_val_if_fail (scd->contact != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (mem_ctx != NULL, FALSE);
+ g_return_val_if_fail (pobject != NULL, FALSE);
+
+ uid = e_contact_get_const (scd->contact, E_CONTACT_UID);
+ if (uid) {
+ EBookCache *book_cache;
+
+ book_cache = e_book_meta_backend_ref_cache (E_BOOK_META_BACKEND (scd->bbmapi));
+ if (book_cache &&
+ !e_book_cache_get_contact (book_cache, uid, FALSE, &old_contact, cancellable, NULL)) {
+ old_contact = NULL;
+ }
- for (l = added_contacts; l; l = l->next) {
- e_book_backend_mapi_notify_contact_update (ebma, NULL, E_CONTACT
(l->data), -1, -1, TRUE, NULL);
- }
+ g_clear_object (&book_cache);
+ }
- e_book_backend_sqlitedb_unlock_updates (ebma->priv->db, TRUE, NULL);
- }
+ success = e_mapi_book_utils_contact_to_object (scd->contact, old_contact, pobject, mem_ctx,
cancellable, error);
- e_data_book_respond_create_contacts (op->book, op->opid, error, added_contacts);
+ g_clear_object (&old_contact);
- g_slist_free_full (added_contacts, g_object_unref);
- }
+ return success;
+}
- g_slist_free_full (ops->str_slist, g_free);
- } break;
- case OP_REMOVE_CONTACTS: {
- OperationStrSlist *ops = (OperationStrSlist *) op;
+static gboolean
+ebb_mapi_save_contact_sync (EBookMetaBackend *meta_backend,
+ gboolean overwrite_existing,
+ EConflictResolution conflict_resolution,
+ /* const */ EContact *contact,
+ const gchar *extra,
+ gchar **out_new_uid,
+ gchar **out_new_extra,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookBackendMAPI *bbmapi;
+ mapi_object_t obj_folder;
+ mapi_id_t mid = 0;
+ gboolean success;
+ GError *mapi_error = NULL;
- if (!cancelled) {
- GSList *removed_ids = NULL;
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
+ g_return_val_if_fail (out_new_uid != NULL, FALSE);
- if (ebmac->op_remove_contacts)
- ebmac->op_remove_contacts (ebma, op->cancellable, ops->str_slist,
&removed_ids, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ *out_new_uid = NULL;
- if (!error) {
- GSList *r;
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- e_book_backend_sqlitedb_lock_updates (ebma->priv->db, NULL);
+ if (e_book_backend_mapi_get_is_gal (bbmapi)) {
+ g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
+ return FALSE;
+ }
- for (r = removed_ids; r; r = r->next) {
- const gchar *uid = r->data;
+ ebb_mapi_lock_connection (bbmapi);
- if (uid)
- e_book_backend_mapi_notify_contact_removed (ebma, uid);
- }
+ success = ebb_mapi_contacts_open_folder (bbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ SaveContactData scd;
- e_book_backend_sqlitedb_unlock_updates (ebma->priv->db, TRUE, NULL);
- }
+ scd.bbmapi = bbmapi;
+ scd.contact = contact;
- e_data_book_respond_remove_contacts (op->book, op->opid, error, removed_ids);
+ if (overwrite_existing) {
+ success = e_mapi_util_mapi_id_from_string (e_contact_get_const (contact,
E_CONTACT_UID), &mid) &&
+ e_mapi_connection_modify_object (bbmapi->priv->conn, &obj_folder, mid,
+ ebb_mapi_create_object_cb, &scd, cancellable, &mapi_error);
- g_slist_foreach (removed_ids, (GFunc) g_free, NULL);
- g_slist_free (removed_ids);
+ } else {
+ success = e_mapi_connection_create_object (bbmapi->priv->conn, &obj_folder,
E_MAPI_CREATE_FLAG_NONE,
+ ebb_mapi_create_object_cb, &scd, &mid, cancellable, &mapi_error);
}
- g_slist_free_full (ops->str_slist, g_free);
- } break;
- case OP_MODIFY_CONTACTS: {
- OperationStrSlist *ops = (OperationStrSlist *) op;
-
- if (!cancelled) {
- GSList *modified_contacts = NULL;
-
- if (ebmac->op_modify_contacts)
- ebmac->op_modify_contacts (ebma, op->cancellable, ops->str_slist,
&modified_contacts, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ e_mapi_connection_close_folder (bbmapi->priv->conn, &obj_folder, cancellable, &mapi_error);
+ }
- if (modified_contacts && !error) {
- const GSList *l;
+ if (mapi_error || !mid) {
+ ebb_mapi_maybe_disconnect (bbmapi, mapi_error);
+ ebb_mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR,
+ overwrite_existing ? _("Failed to modify item on a server") : _("Failed to create
item on a server"));
+ g_clear_error (&mapi_error);
- e_book_backend_sqlitedb_lock_updates (ebma->priv->db, NULL);
+ success = FALSE;
+ }
- for (l = modified_contacts; l; l = l->next) {
- e_book_backend_mapi_notify_contact_update (ebma, NULL, E_CONTACT
(l->data), -1, -1, TRUE, NULL);
- }
+ ebb_mapi_unlock_connection (bbmapi);
- e_book_backend_sqlitedb_unlock_updates (ebma->priv->db, TRUE, NULL);
- }
+ if (success)
+ *out_new_uid = e_mapi_util_mapi_id_to_string (mid);
- e_data_book_respond_modify_contacts (op->book, op->opid, error, modified_contacts);
+ return success;
+}
- g_slist_free_full (modified_contacts, g_object_unref);
- }
+static gboolean
+ebb_mapi_remove_contact_sync (EBookMetaBackend *meta_backend,
+ EConflictResolution conflict_resolution,
+ const gchar *uid,
+ const gchar *extra,
+ const gchar *object,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookBackendMAPI *bbmapi;
+ mapi_id_t mid = 0;
+ gboolean success = TRUE;
+ GError *mapi_error = NULL;
- g_slist_free_full (ops->str_slist, g_free);
- } break;
- case OP_GET_CONTACT: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *id = ops->str;
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
- if (!cancelled) {
- gchar *vcard = NULL;
+ bbmapi = E_BOOK_BACKEND_MAPI (meta_backend);
- if (ebmac->op_get_contact)
- ebmac->op_get_contact (ebma, op->cancellable, id, &vcard, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ if (e_book_backend_mapi_get_is_gal (bbmapi)) {
+ g_propagate_error (error, EDB_ERROR (PERMISSION_DENIED));
+ return FALSE;
+ }
- e_data_book_respond_get_contact (op->book, op->opid, error, vcard);
+ if (e_mapi_util_mapi_id_from_string (uid, &mid)) {
+ mapi_object_t obj_folder;
- g_free (vcard);
- }
+ ebb_mapi_lock_connection (bbmapi);
- g_free (ops->str);
- } break;
- case OP_GET_CONTACT_LIST: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *query = ops->str;
+ success = ebb_mapi_contacts_open_folder (bbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ GSList *mids;
- if (!cancelled) {
- GSList *vCards = NULL;
+ mids = g_slist_prepend (NULL, &mid);
- if (ebmac->op_get_contact_list)
- ebmac->op_get_contact_list (ebma, op->cancellable, query, &vCards, &error);
- else
- error = EDB_ERROR (NOT_SUPPORTED);
+ success = e_mapi_connection_remove_items (bbmapi->priv->conn, &obj_folder, mids,
cancellable, &mapi_error);
- e_data_book_respond_get_contact_list (op->book, op->opid, error, vCards);
+ e_mapi_connection_close_folder (bbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
- g_slist_foreach (vCards, (GFunc) g_free, NULL);
- g_slist_free (vCards);
+ g_slist_free (mids);
}
- g_free (ops->str);
- } break;
- case OP_START_BOOK_VIEW: {
- OperationBookView *opbv = (OperationBookView *) op;
+ ebb_mapi_unlock_connection (bbmapi);
+ }
- if (!cancelled && e_book_backend_mapi_book_view_is_running (ebma, opbv->book_view)) {
- GThread *thread;
- GError *err = NULL;
- struct BookViewThreadData *bvtd = g_new0 (struct BookViewThreadData, 1);
+ if (mapi_error || !mid) {
+ ebb_mapi_maybe_disconnect (bbmapi, mapi_error);
+ ebb_mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to
remove item from a server"));
+ g_clear_error (&mapi_error);
- g_mutex_lock (&ebma->priv->running_views_lock);
+ success = FALSE;
+ }
- bvtd->ebma = g_object_ref (ebma);
- bvtd->book_view = g_object_ref (opbv->book_view);
- bvtd->cancellable = g_hash_table_lookup (ebma->priv->running_views, bvtd->book_view);
+ return success;
+}
- if (bvtd->cancellable)
- g_object_ref (bvtd->cancellable);
+static gboolean
+ebb_mapi_update_cache_for_expression (EBookBackendMAPI *bbmapi,
+ const gchar *expr,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EBookMetaBackend *meta_backend;
+ GSList *found_infos = NULL;
+ gboolean success = TRUE;
- g_mutex_unlock (&ebma->priv->running_views_lock);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
- thread = g_thread_try_new (NULL, ebbm_book_view_thread, bvtd, &err);
+ meta_backend = E_BOOK_META_BACKEND (bbmapi);
- if (err) {
- error = EDB_ERROR_EX (OTHER_ERROR, err->message);
- e_data_book_view_notify_complete (opbv->book_view, error);
- g_error_free (error);
- g_error_free (err);
- }
+ ebb_mapi_lock_connection (bbmapi);
- if (thread)
- g_thread_unref (thread);
- }
+ /* Search only if not searching for everything */
+ if (expr && *expr && g_ascii_strcasecmp (expr, "(contains \"x-evolution-any-field\" \"\")") != 0) {
+ success = e_book_meta_backend_ensure_connected_sync (meta_backend, cancellable, error) &&
+ ebb_mapi_list_existing_with_restrictions_sync (meta_backend,
+ e_mapi_book_utils_build_sexp_restriction, (gpointer) expr,
+ NULL, &found_infos, cancellable, error);
+
+ if (success) {
+ GSList *created_objects = NULL, *modified_objects = NULL;
- g_object_unref (opbv->book_view);
- } break;
- case OP_STOP_BOOK_VIEW: {
- OperationBookView *opbv = (OperationBookView *) op;
+ success = e_book_meta_backend_split_changes_sync (meta_backend, found_infos,
&created_objects,
+ &modified_objects, NULL, cancellable, error);
+ if (success)
+ success = ebb_mapi_preload_infos_sync (bbmapi, created_objects,
modified_objects, cancellable, error);
+ if (success)
+ success = e_book_meta_backend_process_changes_sync (meta_backend,
created_objects,
+ modified_objects, NULL, cancellable, error);
- if (!cancelled) {
- e_data_book_view_notify_complete (opbv->book_view, NULL);
+ g_slist_free_full (created_objects, e_book_meta_backend_info_free);
+ g_slist_free_full (modified_objects, e_book_meta_backend_info_free);
}
- g_object_unref (opbv->book_view);
- } break;
+ g_slist_free_full (found_infos, e_book_meta_backend_info_free);
}
- if (op->cancellable)
- g_object_unref (op->cancellable);
- if (op->book)
- g_object_unref (op->book);
- g_free (op);
+ ebb_mapi_unlock_connection (bbmapi);
- /* for cases when this is the last reference */
- e_mapi_utils_unref_in_thread (G_OBJECT (backend));
+ return success;
}
-static void
-str_op_abstract (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const
gchar *str, OperationType ot)
-{
- OperationStr *op;
- EBookBackendMAPI *ebbm;
- EBookBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
-
- ebbm = E_BOOK_BACKEND_MAPI (backend);
- priv = ebbm->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (ebbm);
- if (book)
- g_object_ref (book);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationStr, 1);
- op->base.ot = ot;
- op->base.book = book;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->str = g_strdup (str);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-str_slist_op_abstract (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable,
const GSList *str_slist, OperationType ot)
+static gboolean
+ebb_mapi_search_sync (EBookMetaBackend *meta_backend,
+ const gchar *expr,
+ gboolean meta_contact,
+ GSList **out_contacts,
+ GCancellable *cancellable,
+ GError **error)
{
- OperationStrSlist *op;
- EBookBackendMAPI *ebbm;
- EBookBackendMAPIPrivate *priv;
- GSList *l;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
- g_return_if_fail (str_slist != NULL);
-
- ebbm = E_BOOK_BACKEND_MAPI (backend);
- priv = ebbm->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (ebbm);
- if (book)
- g_object_ref (book);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationStrSlist, 1);
- op->base.ot = ot;
- op->base.book = book;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->str_slist = g_slist_copy ((GSList *) str_slist);
-
- for (l = op->str_slist; l; l = l->next) {
- l->data = g_strdup (l->data);
- }
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
+ /* Ignore errors, just try its best */
+ ebb_mapi_update_cache_for_expression (E_BOOK_BACKEND_MAPI (meta_backend), expr, cancellable, NULL);
-#define STR_OP_DEF(_func, _ot) \
-static void \
-_func (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const gchar *str)
\
-{ \
- str_op_abstract (backend, book, opid, cancellable, str, _ot); \
+ /* Chain up to parent's method */
+ return E_BOOK_META_BACKEND_CLASS (e_book_backend_mapi_parent_class)->search_sync (meta_backend, expr,
meta_contact,
+ out_contacts, cancellable, error);
}
-#define STR_SLIST_OP_DEF(_func, _ot) \
-static void \
-_func (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList
*str_slist) \
-{ \
- str_slist_op_abstract (backend, book, opid, cancellable, str_slist, _ot); \
-}
+static gboolean
+ebb_mapi_search_uids_sync (EBookMetaBackend *meta_backend,
+ const gchar *expr,
+ GSList **out_uids,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (meta_backend), FALSE);
-STR_SLIST_OP_DEF (ebbm_op_create_contacts, OP_CREATE_CONTACTS)
-STR_SLIST_OP_DEF (ebbm_op_modify_contacts, OP_MODIFY_CONTACTS)
-STR_SLIST_OP_DEF (ebbm_op_remove_contacts, OP_REMOVE_CONTACTS)
-STR_OP_DEF (ebbm_op_get_contact, OP_GET_CONTACT)
-STR_OP_DEF (ebbm_op_get_contact_list, OP_GET_CONTACT_LIST)
+ /* Ignore errors, just try its best */
+ ebb_mapi_update_cache_for_expression (E_BOOK_BACKEND_MAPI (meta_backend), expr, cancellable, NULL);
-static void
-ebbm_op_open (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, gboolean
only_if_exists)
-{
- OperationOpen *op;
- EBookBackendMAPI *ebbm;
- EBookBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
-
- ebbm = E_BOOK_BACKEND_MAPI (backend);
- priv = ebbm->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (ebbm);
- if (book)
- g_object_ref (book);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationOpen, 1);
- op->base.ot = OP_OPEN;
- op->base.book = book;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->only_if_exists = only_if_exists;
-
- e_mapi_operation_queue_push (priv->op_queue, op);
+ /* Chain up to parent's method */
+ return E_BOOK_META_BACKEND_CLASS (e_book_backend_mapi_parent_class)->search_uids_sync (meta_backend,
expr,
+ out_uids, cancellable, error);
}
-static void
-ebbm_op_start_view (EBookBackend *backend, EDataBookView *book_view)
+static gchar *
+ebb_mapi_get_backend_property (EBookBackend *backend,
+ const gchar *prop_name)
{
- OperationBookView *op;
- EBookBackendMAPI *ebbm;
- EBookBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
- g_return_if_fail (book_view != NULL);
-
- ebbm = E_BOOK_BACKEND_MAPI (backend);
- priv = ebbm->priv;
- g_return_if_fail (priv != NULL);
+ EBookBackendMAPI *bbmapi;
- g_object_ref (ebbm);
+ g_return_val_if_fail (prop_name != NULL, NULL);
- op = g_new0 (OperationBookView, 1);
- op->base.ot = OP_START_BOOK_VIEW;
- op->base.book = NULL;
- op->base.opid = 0;
- op->book_view = g_object_ref (book_view);
+ bbmapi = E_BOOK_BACKEND_MAPI (backend);
- g_mutex_lock (&priv->running_views_lock);
- g_hash_table_insert (priv->running_views, book_view, g_cancellable_new ());
- g_mutex_unlock (&priv->running_views_lock);
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ return g_strjoin (",",
+ "net",
+ "contact-lists",
+ e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (backend)),
+ ebb_mapi_is_marked_for_offline (bbmapi) ? "do-initial-query" : NULL,
+ NULL);
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+ return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
+ } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+ GSList *fields;
+ gchar *prop_value;
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
+ fields = e_mapi_book_utils_get_supported_contact_fields ();
+ prop_value = e_data_book_string_slist_to_comma_string (fields);
+ g_slist_free (fields);
-static void
-ebbm_op_stop_view (EBookBackend *backend, EDataBookView *book_view)
-{
- OperationBookView *op;
- EBookBackendMAPI *ebbm;
- EBookBackendMAPIPrivate *priv;
- GCancellable *cancellable;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (backend));
- g_return_if_fail (book_view != NULL);
-
- ebbm = E_BOOK_BACKEND_MAPI (backend);
- priv = ebbm->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (ebbm);
-
- op = g_new0 (OperationBookView, 1);
- op->base.ot = OP_STOP_BOOK_VIEW;
- op->base.book = NULL;
- op->base.opid = 0;
- op->book_view = g_object_ref (book_view);
-
- g_mutex_lock (&priv->running_views_lock);
- cancellable = g_hash_table_lookup (priv->running_views, book_view);
- if (cancellable)
- g_cancellable_cancel (cancellable);
- g_hash_table_remove (priv->running_views, book_view);
- g_mutex_unlock (&priv->running_views_lock);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
+ return prop_value;
+ }
-static void
-e_book_backend_mapi_init (EBookBackendMAPI *ebma)
-{
- ebma->priv = G_TYPE_INSTANCE_GET_PRIVATE (ebma, E_TYPE_BOOK_BACKEND_MAPI, EBookBackendMAPIPrivate);
-
- ebma->priv->op_queue = e_mapi_operation_queue_new ((EMapiOperationQueueFunc) ebbm_operation_cb, ebma);
- ebma->priv->running_views = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
g_object_unref);
- g_mutex_init (&ebma->priv->running_views_lock);
- g_rec_mutex_init (&ebma->priv->conn_lock);
-
- ebma->priv->update_cache = g_cancellable_new ();
- ebma->priv->update_cache_thread = NULL;
- ebma->priv->last_update_cache = 0;
- ebma->priv->last_server_contact_count = 0;
- ebma->priv->last_modify_time = 0;
- ebma->priv->server_dirty = FALSE;
- ebma->priv->last_db_commit_time = 0;
-
- g_signal_connect (
- ebma, "notify::online",
- G_CALLBACK (ebbm_notify_online_cb), NULL);
+ /* Chain up to parent's method */
+ return E_BOOK_BACKEND_CLASS (e_book_backend_mapi_parent_class)->get_backend_property (backend,
prop_name);
}
static gboolean
-ebbm_get_destination_address (EBackend *backend,
- gchar **host,
- guint16 *port)
+ebb_mapi_get_destination_address (EBackend *backend,
+ gchar **host,
+ guint16 *port)
{
ESourceRegistry *registry;
ESource *source;
gboolean result = FALSE;
- g_return_val_if_fail (port != NULL, FALSE);
g_return_val_if_fail (host != NULL, FALSE);
+ g_return_val_if_fail (port != NULL, FALSE);
registry = e_book_backend_get_registry (E_BOOK_BACKEND (backend));
source = e_backend_get_source (backend);
@@ -1340,403 +1089,97 @@ ebbm_get_destination_address (EBackend *backend,
}
static void
-ebbm_constructed (GObject *object)
+ebb_mapi_constructed (GObject *object)
{
+ EBookBackendMAPI *bbmapi = E_BOOK_BACKEND_MAPI (object);
+
+ /* Chaing up to parent's method */
G_OBJECT_CLASS (e_book_backend_mapi_parent_class)->constructed (object);
/* Reset the connectable, it steals data from Authentication extension,
where is written no address */
e_backend_set_connectable (E_BACKEND (object), NULL);
-}
-
-static void
-ebbm_dispose (GObject *object)
-{
- EBookBackendMAPI *ebma = E_BOOK_BACKEND_MAPI (object);
- EBookBackendMAPIPrivate *priv = ebma->priv;
-
- if (priv) {
- if (priv->update_cache_thread) {
- g_cancellable_cancel (priv->update_cache);
- g_thread_join (priv->update_cache_thread);
- priv->update_cache_thread = NULL;
- }
-
- #define FREE(x) if (x) { g_free (x); x = NULL; }
- #define UNREF(x) if (x) { g_object_unref (x); x = NULL; }
-
- e_book_backend_mapi_lock_connection (ebma);
- UNREF (priv->conn);
- e_book_backend_mapi_unlock_connection (ebma);
- UNREF (priv->op_queue);
- UNREF (priv->db);
- UNREF (priv->update_cache);
-
- FREE (priv->book_uid);
-
- g_hash_table_destroy (priv->running_views);
- g_mutex_clear (&priv->running_views_lock);
- g_rec_mutex_clear (&priv->conn_lock);
- #undef UNREF
- #undef FREE
-
- ebma->priv = NULL;
- }
-
- /* Chain up to parent's dispose() method. */
- if (G_OBJECT_CLASS (e_book_backend_mapi_parent_class)->dispose)
- G_OBJECT_CLASS (e_book_backend_mapi_parent_class)->dispose (object);
+ e_book_backend_set_writable (E_BOOK_BACKEND (bbmapi), !e_book_backend_mapi_get_is_gal (bbmapi));
}
static void
-e_book_backend_mapi_class_init (EBookBackendMAPIClass *klass)
+ebb_mapi_dispose (GObject *object)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- EBackendClass *backend_class = E_BACKEND_CLASS (klass);
- EBookBackendClass *book_backend_class = E_BOOK_BACKEND_CLASS (klass);
+ EBookBackendMAPI *bbmapi = E_BOOK_BACKEND_MAPI (object);
- g_type_class_add_private (klass, sizeof (EBookBackendMAPIPrivate));
+ g_clear_object (&bbmapi->priv->conn);
- object_class->constructed = ebbm_constructed;
- object_class->dispose = ebbm_dispose;
-
- backend_class->get_destination_address = ebbm_get_destination_address;
- backend_class->authenticate_sync = ebbm_authenticate_sync;
-
- book_backend_class->open = ebbm_op_open;
- book_backend_class->create_contacts = ebbm_op_create_contacts;
- book_backend_class->remove_contacts = ebbm_op_remove_contacts;
- book_backend_class->modify_contacts = ebbm_op_modify_contacts;
- book_backend_class->get_contact = ebbm_op_get_contact;
- book_backend_class->get_contact_list = ebbm_op_get_contact_list;
- book_backend_class->start_view = ebbm_op_start_view;
- book_backend_class->stop_view = ebbm_op_stop_view;
- book_backend_class->get_backend_property= ebbm_get_backend_property;
-
- klass->op_open = ebbm_open;
- klass->op_remove = ebbm_remove;
- klass->op_get_contact = ebbm_get_contact;
- klass->op_get_contact_list = ebbm_get_contact_list;
-
- klass->op_connection_status_changed = NULL;
- klass->op_get_status_message = NULL;
- klass->op_book_view_thread = NULL;
- klass->op_get_contacts_count = NULL;
- klass->op_list_known_uids = NULL;
- klass->op_transfer_contacts = NULL;
+ /* Chain up to parent's method */
+ G_OBJECT_CLASS (e_book_backend_mapi_parent_class)->dispose (object);
}
-const gchar *
-e_book_backend_mapi_get_book_uid (EBookBackendMAPI *ebma)
-{
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), NULL);
- g_return_val_if_fail (ebma->priv != NULL, NULL);
-
- return ebma->priv->book_uid;
-}
-
-void
-e_book_backend_mapi_lock_connection (EBookBackendMAPI *ebma)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (ebma->priv != NULL);
-
- g_rec_mutex_lock (&ebma->priv->conn_lock);
-}
-
-void
-e_book_backend_mapi_unlock_connection (EBookBackendMAPI *ebma)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (ebma->priv != NULL);
-
- g_rec_mutex_unlock (&ebma->priv->conn_lock);
-}
-
-EMapiConnection *
-e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma,
- GCancellable *cancellable,
- GError **perror)
+static void
+ebb_mapi_finalize (GObject *object)
{
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), NULL);
- g_return_val_if_fail (ebma->priv != NULL, NULL);
-
- if (ebma->priv->conn)
- return ebma->priv->conn;
-
- if (!e_backend_get_online (E_BACKEND (ebma)))
- return NULL;
-
- if (!e_book_backend_mapi_ensure_connected (ebma, cancellable, perror))
- return NULL;
+ EBookBackendMAPI *bbmapi = E_BOOK_BACKEND_MAPI (object);
- return ebma->priv->conn;
-}
-
-void
-e_book_backend_mapi_get_db (EBookBackendMAPI *ebma, EBookBackendSqliteDB **db)
-{
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (ebma->priv != NULL);
+ g_rec_mutex_clear (&bbmapi->priv->conn_lock);
- if (db)
- *db = ebma->priv->db;
+ /* Chain up to parent's method */
+ G_OBJECT_CLASS (e_book_backend_mapi_parent_class)->finalize (object);
}
-gboolean
-e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma, EDataBookView *book_view)
+static void
+e_book_backend_mapi_class_init (EBookBackendMAPIClass *klass)
{
- gboolean res;
-
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
- g_return_val_if_fail (ebma->priv != NULL, FALSE);
+ GObjectClass *object_class;
+ EBackendClass *backend_class;
+ EBookBackendClass *book_backend_class;
+ EBookMetaBackendClass *meta_backend_class;
- g_mutex_lock (&ebma->priv->running_views_lock);
- res = g_hash_table_lookup (ebma->priv->running_views, book_view) != NULL;
- g_mutex_unlock (&ebma->priv->running_views_lock);
+ g_type_class_add_private (klass, sizeof (EBookBackendMAPIPrivate));
- return res;
+ meta_backend_class = E_BOOK_META_BACKEND_CLASS (klass);
+ meta_backend_class->backend_module_filename = "libebookbackendmapi.so";
+ meta_backend_class->connect_sync = ebb_mapi_connect_sync;
+ meta_backend_class->disconnect_sync = ebb_mapi_disconnect_sync;
+ meta_backend_class->get_changes_sync = ebb_mapi_get_changes_sync;
+ meta_backend_class->list_existing_sync = ebb_mapi_list_existing_sync;
+ meta_backend_class->load_contact_sync = ebb_mapi_load_contact_sync;
+ meta_backend_class->save_contact_sync = ebb_mapi_save_contact_sync;
+ meta_backend_class->remove_contact_sync = ebb_mapi_remove_contact_sync;
+ meta_backend_class->search_sync = ebb_mapi_search_sync;
+ meta_backend_class->search_uids_sync = ebb_mapi_search_uids_sync;
+
+ book_backend_class = E_BOOK_BACKEND_CLASS (klass);
+ book_backend_class->get_backend_property = ebb_mapi_get_backend_property;
+
+ backend_class = E_BACKEND_CLASS (klass);
+ backend_class->get_destination_address = ebb_mapi_get_destination_address;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = ebb_mapi_constructed;
+ object_class->dispose = ebb_mapi_dispose;
+ object_class->finalize = ebb_mapi_finalize;
}
-gboolean
-e_book_backend_mapi_is_marked_for_offline (EBookBackendMAPI *ebma)
+static void
+e_book_backend_mapi_init (EBookBackendMAPI *bbmapi)
{
- ESource *source;
- ESourceOffline *offline_extension;
-
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
- g_return_val_if_fail (ebma->priv != NULL, FALSE);
+ bbmapi->priv = G_TYPE_INSTANCE_GET_PRIVATE (bbmapi, E_TYPE_BOOK_BACKEND_MAPI,
EBookBackendMAPIPrivate);
- source = e_backend_get_source (E_BACKEND (ebma));
-
- offline_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE);
-
- return e_source_offline_get_stay_synchronized (offline_extension);
+ g_rec_mutex_init (&bbmapi->priv->conn_lock);
}
void
-e_book_backend_mapi_update_view_by_cache (EBookBackendMAPI *ebma, EDataBookView *book_view, GError **error)
+e_book_backend_mapi_set_is_gal (EBookBackendMAPI *bbmapi,
+ gboolean is_gal)
{
- gint i = 0;
- const gchar *query = NULL;
- EBookBackendSExp *sexp;
- EBookBackendSqliteDB *db = NULL;
- GSList *hits, *l;
-
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (book_view != NULL);
- g_return_if_fail (E_IS_DATA_BOOK_VIEW (book_view));
-
- sexp = e_data_book_view_get_sexp (book_view);
- query = e_book_backend_sexp_text (sexp);
-
- e_book_backend_mapi_get_db (ebma, &db);
-
- g_return_if_fail (db != NULL);
-
- hits = e_book_backend_sqlitedb_search (db, EMA_EBB_CACHE_FOLDERID,
- query, NULL, NULL, NULL, error);
+ g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi));
- for (l = hits; (!error || !*error) && l; l = l->next) {
- EbSdbSearchData *sdata = (EbSdbSearchData *) l->data;
- gchar *vcard = sdata->vcard;
-
- if (((i++) % 10) == 0 && !e_book_backend_mapi_book_view_is_running (ebma, book_view))
- break;
-
- if (vcard) {
- EContact *contact = e_contact_new_from_vcard (vcard);
- e_data_book_view_notify_update (book_view, contact);
- g_object_unref (contact);
- }
- }
-
- if (hits) {
- g_slist_foreach (hits, (GFunc) e_book_backend_sqlitedb_search_data_free, NULL);
- g_slist_free (hits);
- }
+ bbmapi->priv->is_gal = is_gal;
}
-/* called from op_transfer_contacts - book_view and notify_contact_data are taken from there;
- notify_contact_data is a pointer to glong last_notification, if not NULL;
- returns whether can continue with fetching */
gboolean
-e_book_backend_mapi_notify_contact_update (EBookBackendMAPI *ebma,
- EDataBookView *pbook_view,
- EContact *contact,
- gint index,
- gint total,
- gboolean cache_is_locked,
- gpointer notify_contact_data)
-{
- EBookBackendMAPIPrivate *priv;
- glong *last_notification = notify_contact_data;
- EDataBookView *book_view = pbook_view;
- glong current_time;
- GError *error = NULL;
-
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), FALSE);
- g_return_val_if_fail (ebma->priv, FALSE);
- g_return_val_if_fail (contact != NULL, FALSE);
-
- priv = ebma->priv;
- g_return_val_if_fail (priv != NULL, FALSE);
-
- current_time = get_current_time_ms ();
-
- /* report progres to any book_view, if not passed in;
- it can happen when cache is filling and the book view started later */
- if (!book_view)
- book_view = ebbm_pick_book_view (ebma);
- else
- g_object_ref (book_view);
-
- if (book_view) {
- if (!e_book_backend_mapi_book_view_is_running (ebma, book_view)) {
- g_object_unref (book_view);
- return FALSE;
- }
-
- if (index > 0 && last_notification && current_time - *last_notification > 333) {
- gchar *status_msg = NULL;
- EBookBackendMAPIClass *ebmac = E_BOOK_BACKEND_MAPI_GET_CLASS (ebma);
-
- if (ebmac->op_get_status_message)
- status_msg = ebmac->op_get_status_message (ebma, index, total);
-
- if (status_msg)
- e_data_book_view_notify_progress (book_view, -1, status_msg);
-
- g_free (status_msg);
-
- *last_notification = current_time;
- }
-
- g_object_unref (book_view);
- }
-
- if (!pbook_view && g_cancellable_is_cancelled (priv->update_cache))
- return FALSE;
-
- e_book_backend_sqlitedb_new_contact (priv->db,
- EMA_EBB_CACHE_FOLDERID, contact,
- TRUE, &error);
-
- /* commit not often than each minute, also to not lose data already transferred */
- if (cache_is_locked && current_time - priv->last_db_commit_time >= 60000) {
- e_book_backend_sqlitedb_unlock_updates (priv->db, TRUE, NULL);
- e_book_backend_sqlitedb_lock_updates (priv->db, NULL);
-
- priv->last_db_commit_time = current_time;
- }
-
- if (!error) {
- e_book_backend_notify_update (E_BOOK_BACKEND (ebma), contact);
- return TRUE;
- }
-
- g_error_free (error);
-
- return FALSE;
-}
-
-void
-e_book_backend_mapi_notify_contact_removed (EBookBackendMAPI *ebma, const gchar *uid)
-{
- EBookBackendMAPIPrivate *priv;
- GError *error = NULL;
- gboolean ret;
-
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (ebma->priv);
- g_return_if_fail (uid != NULL);
-
- priv = ebma->priv;
- g_return_if_fail (priv != NULL);
-
- ret = e_book_backend_sqlitedb_remove_contact (priv->db,
- EMA_EBB_CACHE_FOLDERID,
- uid, &error);
- if (ret && !error)
- e_book_backend_notify_remove (E_BOOK_BACKEND (ebma), uid);
-
- if (error)
- g_error_free (error);
-}
-
-void
-e_book_backend_mapi_cache_set (EBookBackendMAPI *ebma, const gchar *key, const gchar *value)
+e_book_backend_mapi_get_is_gal (EBookBackendMAPI *bbmapi)
{
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
- g_return_if_fail (ebma->priv != NULL);
- g_return_if_fail (ebma->priv->db != NULL);
- g_return_if_fail (key != NULL);
+ g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (bbmapi), FALSE);
- e_book_backend_sqlitedb_set_key_value (ebma->priv->db, EMA_EBB_CACHE_FOLDERID, key, value, NULL);
-}
-
-gchar *
-e_book_backend_mapi_cache_get (EBookBackendMAPI *ebma, const gchar *key)
-{
- g_return_val_if_fail (ebma != NULL, NULL);
- g_return_val_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma), NULL);
- g_return_val_if_fail (ebma->priv != NULL, NULL);
- g_return_val_if_fail (ebma->priv->db != NULL, NULL);
- g_return_val_if_fail (key != NULL, NULL);
-
- return e_book_backend_sqlitedb_get_key_value (ebma->priv->db, EMA_EBB_CACHE_FOLDERID, key, NULL);
-}
-
-void
-e_book_backend_mapi_refresh_cache (EBookBackendMAPI *ebma)
-{
- g_return_if_fail (ebma != NULL);
- g_return_if_fail (E_IS_BOOK_BACKEND_MAPI (ebma));
-
- ebma->priv->last_update_cache = 0;
- ebma->priv->last_modify_time = 0;
- ebma->priv->server_dirty = TRUE;
-
- ebbm_maybe_invoke_cache_update (ebma);
-}
-
-/* utility functions/macros */
-
-void
-mapi_error_to_edb_error (GError **perror, const GError *mapi_error, EDataBookStatus code, const gchar
*context)
-{
- gchar *err_msg = NULL;
-
- if (!perror)
- return;
-
- if (g_error_matches (mapi_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- g_propagate_error (perror, g_error_copy (mapi_error));
- return;
- }
-
- if (code == E_DATA_BOOK_STATUS_OTHER_ERROR && mapi_error && mapi_error->domain == E_MAPI_ERROR) {
- /* Change error to more accurate only with OTHER_ERROR */
- switch (mapi_error->code) {
- case MAPI_E_PASSWORD_CHANGE_REQUIRED:
- case MAPI_E_PASSWORD_EXPIRED:
- code = E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED;
- break;
- case ecRpcFailed:
- code = E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE;
- break;
- default:
- break;
- }
- }
-
- if (context)
- err_msg = g_strconcat (context, mapi_error ? ": " : NULL, mapi_error ? mapi_error->message :
NULL, NULL);
-
- g_propagate_error (perror, e_data_book_create_error (code, err_msg ? err_msg : mapi_error ?
mapi_error->message : _("Unknown error")));
-
- g_free (err_msg);
+ return bbmapi->priv->is_gal;
}
diff --git a/src/addressbook/e-book-backend-mapi.h b/src/addressbook/e-book-backend-mapi.h
index 5751e32..b5848d8 100644
--- a/src/addressbook/e-book-backend-mapi.h
+++ b/src/addressbook/e-book-backend-mapi.h
@@ -18,8 +18,8 @@
*
*/
-#ifndef __E_BOOK_BACKEND_MAPI_H__
-#define __E_BOOK_BACKEND_MAPI_H__
+#ifndef E_BOOK_BACKEND_MAPI_H
+#define E_BOOK_BACKEND_MAPI_H
#include <glib.h>
#include <gio/gio.h>
@@ -44,106 +44,21 @@ typedef struct _EBookBackendMAPIPrivate EBookBackendMAPIPrivate;
typedef struct
{
- EBookBackend parent_object;
+ EBookMetaBackend parent_object;
EBookBackendMAPIPrivate *priv;
} EBookBackendMAPI;
-struct ListKnownUidsData
-{
- GHashTable *uid_to_rev;
- time_t latest_last_modify;
-};
-
typedef struct
{
- EBookBackendClass parent_class;
-
- void (*op_open) (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean only_if_exists, GError
**error);
- void (*op_remove) (EBookBackendMAPI *ebma, GCancellable *cancellable, GError **error);
-
- void (*op_create_contacts) (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards,
GSList **added_contacts, GError **error);
- void (*op_remove_contacts) (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *id_list,
GSList **removed_ids, GError **error);
- void (*op_modify_contacts) (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards,
GSList **modified_contacts, GError **error);
- void (*op_get_contact) (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *id, gchar
**vcard, GError **error);
- void (*op_get_contact_list) (EBookBackendMAPI *ebma, GCancellable *cancellable, const gchar *query,
GSList **vCards, GError **error);
-
- /* called when online state changes on the backend */
- void (*op_connection_status_changed) (EBookBackendMAPI *ebma, gboolean is_online);
-
- /* returns a status message for a progress of fetching entries "index/total";
- returned string is freed by g_free() */
- gchar * (*op_get_status_message) (EBookBackendMAPI *ebma, gint index, gint total);
-
- /* function called for each new book_view, in a separate thread;
- this function is optional, contacts from cache are always processed
- before this function call */
- void (*op_book_view_thread) (EBookBackendMAPI *ebma, EDataBookView *book_view, GCancellable
*cancellable, GError **error);
-
- /* gets current count of contacts in the folder corresponding to the backend */
- void (*op_get_contacts_count) (EBookBackendMAPI *ebma, guint32 *obj_total, GCancellable *cancellable,
GError **error);
-
- /* function to fetch list of known uids (strings) on the server;
- it's used to synchronize local cache with available items;
- uids has the uid key, as a newly allocated string;
- value is a revision (REV) field value as newly allocated string */
- void (*op_list_known_uids) (EBookBackendMAPI *ebma, BuildRestrictionsCB build_rs_cb, gpointer
build_rs_cb_data, struct ListKnownUidsData *lku, GCancellable *cancellable, GError **error);
-
- /* function called to populate cache or similar operations;
- book_view can be NULL, call e_book_backend_mapi_notify_contact_update for each
- transferred contact with this book_view and notify_contact_data */
- void (*op_transfer_contacts) (EBookBackendMAPI *ebma, const GSList *uids, EDataBookView *book_view,
gpointer notify_contact_data, GCancellable *cancellable, GError **error);
+ EBookMetaBackendClass parent_class;
} EBookBackendMAPIClass;
-GType e_book_backend_mapi_get_type (void);
-
-const gchar * e_book_backend_mapi_get_book_uid (EBookBackendMAPI *ebma);
-void e_book_backend_mapi_lock_connection (EBookBackendMAPI *ebma);
-void e_book_backend_mapi_unlock_connection (EBookBackendMAPI *ebma);
-EMapiConnection * e_book_backend_mapi_get_connection (EBookBackendMAPI *ebma,
- GCancellable *cancellable,
- GError **perror);
-gboolean e_book_backend_mapi_ensure_connected (EBookBackendMAPI *ebma,
- GCancellable *cancellable,
- GError **error);
-void e_book_backend_mapi_maybe_disconnect (EBookBackendMAPI *ebma,
- const GError *mapi_error);
-void e_book_backend_mapi_get_db (EBookBackendMAPI *ebma,
- EBookBackendSqliteDB **db);
-gboolean e_book_backend_mapi_book_view_is_running (EBookBackendMAPI *ebma,
- EDataBookView *book_view);
-void e_book_backend_mapi_update_view_by_cache (EBookBackendMAPI *ebma,
- EDataBookView *book_view,
- GError **error);
-gboolean e_book_backend_mapi_is_marked_for_offline (EBookBackendMAPI *ebma);
-gboolean e_book_backend_mapi_notify_contact_update (EBookBackendMAPI *ebma,
- EDataBookView *book_view,
- EContact *contact,
- gint index,
- gint total,
- gboolean cache_is_locked,
- gpointer notify_contact_data);
-void e_book_backend_mapi_notify_contact_removed (EBookBackendMAPI *ebma,
- const gchar *uid);
-void e_book_backend_mapi_cache_set (EBookBackendMAPI *ebma,
- const gchar *key,
- const gchar *value);
-gchar * e_book_backend_mapi_cache_get (EBookBackendMAPI *ebma,
- const gchar *key);
-void e_book_backend_mapi_refresh_cache (EBookBackendMAPI *ebma);
-
-/* utility functions/macros */
-
-#define EDB_ERROR(_code) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
-#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
-
-void mapi_error_to_edb_error (GError **perror, const GError *mapi_error, EDataBookStatus code, const gchar
*context);
+GType e_book_backend_mapi_get_type (void);
-/* The EBookBackendSqliteDB functions allow for a single all-caches database,
- * which is a feature we do not use, and instead have per-folder databases.
- * Therefore we have a couple arbitrary constants... */
-#define EMA_EBB_CACHE_PROFILEID "EMA_PROFILE"
-#define EMA_EBB_CACHE_FOLDERID "EMA_FOLDER"
+void e_book_backend_mapi_set_is_gal (EBookBackendMAPI *bbmapi,
+ gboolean is_gal);
+gboolean e_book_backend_mapi_get_is_gal (EBookBackendMAPI *bbmapi);
G_END_DECLS
-#endif /* __E_BOOK_BACKEND_MAPI_H__ */
+#endif /* E_BOOK_BACKEND_MAPI_H */
diff --git a/src/calendar/e-cal-backend-mapi.c b/src/calendar/e-cal-backend-mapi.c
index d3142b1..aced948 100644
--- a/src/calendar/e-cal-backend-mapi.c
+++ b/src/calendar/e-cal-backend-mapi.c
@@ -1,5 +1,8 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com)
+ *
* 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
@@ -16,9 +19,6 @@
*
* Authors:
* Suman Manjunath <msuman novell com>
- *
- * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
- *
*/
#include "evolution-mapi-config.h"
@@ -31,11 +31,10 @@
#include <libedata-cal/libedata-cal.h>
#include <libedataserver/libedataserver.h>
-#include <e-mapi-connection.h>
-#include <e-mapi-cal-utils.h>
-#include <e-mapi-utils.h>
-#include <e-mapi-operation-queue.h>
-#include <e-source-mapi-folder.h>
+#include "e-mapi-connection.h"
+#include "e-mapi-cal-utils.h"
+#include "e-mapi-utils.h"
+#include "e-source-mapi-folder.h"
#include "e-cal-backend-mapi.h"
@@ -54,107 +53,21 @@
#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
-G_DEFINE_TYPE (ECalBackendMAPI, e_cal_backend_mapi, E_TYPE_CAL_BACKEND)
-
-typedef struct {
- GCond cond;
- GMutex mutex;
- gboolean exit;
-} SyncDelta;
+G_DEFINE_TYPE (ECalBackendMAPI, e_cal_backend_mapi, E_TYPE_CAL_META_BACKEND)
-/* Private part of the CalBackendMAPI structure */
struct _ECalBackendMAPIPrivate {
- EMapiOperationQueue *op_queue;
-
- mapi_id_t fid;
- gboolean is_public_folder;
- gchar *foreign_username;
+ GRecMutex conn_lock;
EMapiConnection *conn;
-
- /* A mutex to control access to the private structure */
- GMutex mutex;
- ECalBackendStore *store;
- gboolean read_only;
- gchar *uri;
- GMutex updating_mutex;
- GMutex is_updating_mutex;
- gboolean is_updating;
-
- /* timeout handler for syncing sendoptions */
- guint sendoptions_sync_timeout;
-
- /* used exclusively for delta fetching */
- guint timeout_id;
- GThread *dthread;
- SyncDelta *dlock;
-
- time_t last_refresh;
- gint last_obj_total;
- GCancellable *cancellable;
};
-static CamelMapiSettings *
-ecbm_get_collection_settings (ECalBackendMAPI *ecbm)
-{
- ESource *source;
- ESource *collection;
- ESourceCamel *extension;
- ESourceRegistry *registry;
- CamelSettings *settings;
- const gchar *extension_name;
-
- source = e_backend_get_source (E_BACKEND (ecbm));
- registry = e_cal_backend_get_registry (E_CAL_BACKEND (ecbm));
-
- extension_name = e_source_camel_get_extension_name ("mapi");
- e_source_camel_generate_subtype ("mapi", CAMEL_TYPE_MAPI_SETTINGS);
-
- /* The collection settings live in our parent data source. */
- collection = e_source_registry_find_extension (
- registry, source, extension_name);
- g_return_val_if_fail (collection != NULL, NULL);
-
- extension = e_source_get_extension (collection, extension_name);
- settings = e_source_camel_get_settings (extension);
-
- g_object_unref (collection);
-
- return CAMEL_MAPI_SETTINGS (settings);
-}
-
-static gboolean
-ecbm_open_folder (ECalBackendMAPI *ecbm,
- EMapiConnection *conn,
- mapi_object_t *obj_folder,
- GCancellable *cancellable,
- GError **perror)
-{
- gboolean res;
-
- g_return_val_if_fail (ecbm != NULL, FALSE);
- g_return_val_if_fail (ecbm->priv != NULL, FALSE);
- g_return_val_if_fail (conn != NULL, FALSE);
- g_return_val_if_fail (obj_folder != NULL, FALSE);
-
- if (ecbm->priv->foreign_username)
- res = e_mapi_connection_open_foreign_folder (conn, ecbm->priv->foreign_username,
ecbm->priv->fid, obj_folder, cancellable, perror);
- else if (ecbm->priv->is_public_folder)
- res = e_mapi_connection_open_public_folder (conn, ecbm->priv->fid, obj_folder, cancellable,
perror);
- else
- res = e_mapi_connection_open_personal_folder (conn, ecbm->priv->fid, obj_folder, cancellable,
perror);
-
- return res;
-}
-
-static EMapiConnection *e_cal_backend_mapi_get_connection (ECalBackendMAPI *cbma, GCancellable
*cancellable, GError **perror);
-static void e_cal_backend_mapi_maybe_disconnect (ECalBackendMAPI *cbma, const GError
*mapi_error);
-
-#define CACHE_REFRESH_INTERVAL 600000
-
-static GMutex auth_mutex;
+static gchar * ecb_mapi_dup_component_revision_cb (ECalCache *cal_cache,
+ icalcomponent *icalcomp);
static void
-mapi_error_to_edc_error (GError **perror, const GError *mapi_error, EDataCalCallStatus code, const gchar
*context)
+ecb_mapi_error_to_edc_error (GError **perror,
+ const GError *mapi_error,
+ EDataCalCallStatus code,
+ const gchar *context)
{
gchar *err_msg = NULL;
@@ -189,917 +102,498 @@ mapi_error_to_edc_error (GError **perror, const GError *mapi_error, EDataCalCall
g_free (err_msg);
}
-/* **** UTILITY FUNCTIONS **** */
-
static void
-get_comp_mid (icalcomponent *icalcomp, mapi_id_t *mid)
+ecb_mapi_lock_connection (ECalBackendMAPI *cbmapi)
{
- gchar *x_mid;
-
- g_return_if_fail (icalcomp != NULL);
- g_return_if_fail (mid != NULL);
-
- x_mid = e_mapi_cal_utils_get_icomp_x_prop (icalcomp, "X-EVOLUTION-MAPI-MID");
- if (x_mid) {
- e_mapi_util_mapi_id_from_string (x_mid, mid);
- g_free (x_mid);
- } else {
- e_mapi_util_mapi_id_from_string (icalcomponent_get_uid (icalcomp), mid);
- }
-}
-
-static ESource *
-ecbm_find_identity_source (ECalBackendMAPI *cbmapi)
-{
- ESourceRegistry *registry;
- GList *all_sources, *my_sources, *iter;
- CamelMapiSettings *settings;
- ESource *res = NULL;
-
- g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), NULL);
-
- settings = ecbm_get_collection_settings (cbmapi);
- g_return_val_if_fail (settings != NULL, NULL);
-
- registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbmapi));
- all_sources = e_source_registry_list_sources (registry, NULL);
- my_sources = e_mapi_utils_filter_sources_for_profile (all_sources,
- camel_mapi_settings_get_profile (settings));
- g_list_free_full (all_sources, g_object_unref);
-
- for (iter = my_sources; iter; iter = iter->next) {
- ESource *source = iter->data;
-
- if (!source)
- continue;
-
- if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_IDENTITY)) {
- res = g_object_ref (source);
- break;
- }
- }
-
- g_list_free_full (my_sources, g_object_unref);
-
- return res;
-}
-
-static const gchar *
-ecbm_get_owner_name (ECalBackendMAPI *cbmapi)
-{
- ESource *identity_source;
- ESourceMailIdentity *identity_ext;
- const gchar *res = NULL;
-
- identity_source = ecbm_find_identity_source (cbmapi);
- if (!identity_source)
- return NULL;
-
- identity_ext = e_source_get_extension (identity_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
- if (identity_ext)
- res = e_source_mail_identity_get_name (identity_ext);
-
- g_object_unref (identity_source);
-
- return res;
-}
-
-static const gchar *
-ecbm_get_owner_email (ECalBackendMAPI *cbmapi)
-{
- ESource *identity_source;
- ESourceMailIdentity *identity_ext;
- const gchar *res = NULL;
-
- identity_source = ecbm_find_identity_source (cbmapi);
- if (!identity_source)
- return NULL;
-
- identity_ext = e_source_get_extension (identity_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
- if (identity_ext)
- res = e_source_mail_identity_get_address (identity_ext);
-
- g_object_unref (identity_source);
+ g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi));
- return res;
+ g_rec_mutex_lock (&cbmapi->priv->conn_lock);
}
-static const gchar *
-ecbm_get_user_name (ECalBackendMAPI *cbmapi)
+static void
+ecb_mapi_unlock_connection (ECalBackendMAPI *cbmapi)
{
- return ecbm_get_owner_name (cbmapi);
-}
+ g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi));
-static const gchar *
-ecbm_get_user_email (ECalBackendMAPI *cbmapi)
-{
- return ecbm_get_owner_email (cbmapi);
+ g_rec_mutex_unlock (&cbmapi->priv->conn_lock);
}
-static gchar *
-ecbm_get_backend_property (ECalBackend *backend,
- const gchar *prop_name)
+static CamelMapiSettings *
+ecb_mapi_get_collection_settings (ECalBackendMAPI *cbmapi)
{
- g_return_val_if_fail (prop_name != NULL, NULL);
-
- if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
- return g_strjoin (
- ",",
- CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT,
- CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS,
- CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
- CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS,
- CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY,
- CAL_STATIC_CAPABILITY_REMOVE_ALARMS,
- CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
- CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
- CAL_STATIC_CAPABILITY_CREATE_MESSAGES,
- CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK,
- CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR,
- CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING,
- CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED,
- CAL_STATIC_CAPABILITY_NO_MEMO_START_DATE,
- CAL_STATIC_CAPABILITY_TASK_DATE_ONLY,
- NULL);
- } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
- ECalBackendMAPI *cbmapi;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
-
- return g_strdup (ecbm_get_user_email (cbmapi));
- } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
- /* We don't support email alarms. This should not have been called. */
- return NULL;
- } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
- ECalComponent *comp;
- gchar *prop_value;
+ ESource *source;
+ ESource *collection;
+ ESourceCamel *extension;
+ ESourceRegistry *registry;
+ CamelSettings *settings;
+ const gchar *extension_name;
- comp = e_cal_component_new ();
+ source = e_backend_get_source (E_BACKEND (cbmapi));
+ registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbmapi));
- switch (e_cal_backend_get_kind (E_CAL_BACKEND (backend))) {
- case ICAL_VEVENT_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
- break;
- case ICAL_VTODO_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
- break;
- case ICAL_VJOURNAL_COMPONENT:
- e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
- break;
- default:
- g_object_unref (comp);
- return NULL;
- }
+ extension_name = e_source_camel_get_extension_name ("mapi");
+ e_source_camel_generate_subtype ("mapi", CAMEL_TYPE_MAPI_SETTINGS);
- prop_value = e_cal_component_get_as_string (comp);
+ /* The collection settings live in our parent data source. */
+ collection = e_source_registry_find_extension (registry, source, extension_name);
+ g_return_val_if_fail (collection != NULL, NULL);
- g_object_unref (comp);
+ extension = e_source_get_extension (collection, extension_name);
+ settings = e_source_camel_get_settings (extension);
- return prop_value;
- }
+ g_object_unref (collection);
- /* Chain up to parent's get_backend_property() method. */
- return E_CAL_BACKEND_CLASS (e_cal_backend_mapi_parent_class)->
- get_backend_property (backend, prop_name);
+ return CAMEL_MAPI_SETTINGS (settings);
}
-static void
-ecbm_refresh (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, GError **perror)
+static gboolean
+ecb_mapi_open_folder (ECalBackendMAPI *cbmapi,
+ mapi_object_t *out_obj_folder,
+ GCancellable *cancellable,
+ GError **error)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+ ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
+ mapi_id_t fid;
+ gchar *foreign_username;
+ gboolean success;
- if (priv && priv->dlock)
- g_cond_signal (&priv->dlock->cond);
-}
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), FALSE);
+ g_return_val_if_fail (cbmapi->priv->conn != NULL, FALSE);
+ g_return_val_if_fail (out_obj_folder != NULL, FALSE);
-#if 0
-static const gchar *
-get_element_type (icalcomponent_kind kind)
-{
+ source = e_backend_get_source (E_BACKEND (cbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- const gchar *type = "";
+ fid = e_source_mapi_folder_get_id (ext_mapi_folder);
+ foreign_username = e_source_mapi_folder_dup_foreign_username (ext_mapi_folder);
- if (kind == ICAL_VEVENT_COMPONENT)
- type = "Appointment";
- else if (kind == ICAL_VTODO_COMPONENT)
- type = "Task";
- else if (kind == ICAL_VJOURNAL_COMPONENT)
- type = "Note";
+ if (foreign_username && *foreign_username)
+ success = e_mapi_connection_open_foreign_folder (cbmapi->priv->conn, foreign_username, fid,
out_obj_folder, cancellable, error);
+ else if (e_source_mapi_folder_is_public (ext_mapi_folder))
+ success = e_mapi_connection_open_public_folder (cbmapi->priv->conn, fid, out_obj_folder,
cancellable, error);
+ else
+ success = e_mapi_connection_open_personal_folder (cbmapi->priv->conn, fid, out_obj_folder,
cancellable, error);
- return type;
+ g_free (foreign_username);
+ return success;
}
-#endif
static void
-notify_view_progress (ECalBackendMAPI *cbmapi, guint index, guint total)
+ecb_mapi_maybe_disconnect (ECalBackendMAPI *cbmapi,
+ const GError *mapi_error)
{
- GList *list, *link;
- gchar *progress_string;
- gint percent = -1;
-
- if (total > 0)
- percent = index * 100 / total;
-
- if (percent > 100)
- percent = 99;
-
- /* To translators: This message is displayed on the status bar when calendar/tasks/memo items are
being fetched from the server. */
- progress_string = g_strdup_printf (_("Loading items in folder %s"),
- e_source_get_display_name (e_backend_get_source (E_BACKEND (cbmapi))));
-
- list = e_cal_backend_list_views (E_CAL_BACKEND (cbmapi));
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- EDataCalView *view = E_DATA_CAL_VIEW (link->data);
-
- if (e_data_cal_view_is_completed (view))
- continue;
+ g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi));
- if (e_data_cal_view_is_stopped (view))
- continue;
+ /* no error or already disconnected */
+ if (!mapi_error || !cbmapi->priv->conn)
+ return;
- e_data_cal_view_notify_progress (view, percent, progress_string);
+ if (g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed) ||
+ g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
+ e_mapi_connection_disconnect (cbmapi->priv->conn,
+ !g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed),
+ NULL, NULL);
+ g_clear_object (&cbmapi->priv->conn);
}
-
- g_list_free_full (list, g_object_unref);
-
- g_free (progress_string);
}
static void
-notify_view_completed (ECalBackendMAPI *cbmapi)
+ecb_mapi_get_comp_mid (icalcomponent *icalcomp,
+ mapi_id_t *mid)
{
- GList *list, *link;
-
- list = e_cal_backend_list_views (E_CAL_BACKEND (cbmapi));
-
- for (link = list; link != NULL; link = g_list_next (link)) {
- EDataCalView *view = E_DATA_CAL_VIEW (link->data);
-
- if (e_data_cal_view_is_completed (view))
- continue;
+ gchar *x_mid;
- if (e_data_cal_view_is_stopped (view))
- continue;
+ g_return_if_fail (icalcomp != NULL);
+ g_return_if_fail (mid != NULL);
- e_data_cal_view_notify_complete (view, NULL);
+ x_mid = e_mapi_cal_utils_get_icomp_x_prop (icalcomp, "X-EVOLUTION-MAPI-MID");
+ if (x_mid) {
+ e_mapi_util_mapi_id_from_string (x_mid, mid);
+ g_free (x_mid);
+ } else {
+ e_mapi_util_mapi_id_from_string (icalcomponent_get_uid (icalcomp), mid);
}
-
- g_list_free_full (list, g_object_unref);
}
-static icaltimezone *
-resolve_tzid (const char *tzid, gpointer user_data)
-{
- ETimezoneCache *timezone_cache;
-
- timezone_cache = E_TIMEZONE_CACHE (user_data);
-
- return e_timezone_cache_get_timezone (timezone_cache, tzid);
-}
-
-static void
-put_component_to_store (ECalBackendMAPI *cbmapi,
- ECalComponent *comp)
-{
- time_t time_start, time_end;
- ECalBackendMAPIPrivate *priv;
-
- priv = cbmapi->priv;
-
- e_cal_util_get_component_occur_times (comp, &time_start, &time_end,
- resolve_tzid, cbmapi, icaltimezone_get_utc_timezone (),
- e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi)));
-
- e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);
-}
-
-#define notify_error(_mmapi_backend, _merror, _mformat) \
- G_STMT_START { \
- notify_error_ex (_mmapi_backend, \
- &(_merror), \
- _mformat, \
- (_merror) ? (_merror)->message : _("Unknown error")); \
- } G_STMT_END
-
-static void notify_error_ex (ECalBackendMAPI *mapi_backend, GError **perror, const gchar *format, ...)
G_GNUC_PRINTF (3, 4);
-
-static void
-notify_error_ex (ECalBackendMAPI *mapi_backend, GError **perror, const gchar *format, ...)
+static gboolean
+ecb_mapi_capture_req_props (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- gchar *msg;
- va_list args;
+ struct cal_cbdata *cbdata = user_data;
+ const uint32_t *ui32;
- g_return_if_fail (mapi_backend != NULL);
- g_return_if_fail (format != NULL);
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (cbdata != NULL, FALSE);
- if (perror && (
- g_error_matches (*perror, G_IO_ERROR, G_IO_ERROR_CANCELLED) ||
- g_error_matches (*perror, E_MAPI_ERROR, MAPI_E_USER_CANCEL)))
- return;
+ ui32 = e_mapi_util_find_array_propval (&object->properties, PidTagOwnerAppointmentId);
+ if (ui32)
+ cbdata->appt_id = *ui32;
+ ui32 = e_mapi_util_find_array_propval (&object->properties, PidLidAppointmentSequence);
+ if (ui32)
+ cbdata->appt_seq = *ui32;
- va_start (args, format);
- msg = g_strdup_vprintf (format, args);
- va_end (args);
+ cbdata->cleanglobalid = e_mapi_util_copy_sbinary_short (e_mapi_util_find_array_propval
(&object->properties, PidLidCleanGlobalObjectId));
+ cbdata->globalid = e_mapi_util_copy_sbinary_short (e_mapi_util_find_array_propval
(&object->properties, PidLidGlobalObjectId));
- e_cal_backend_notify_error (E_CAL_BACKEND (mapi_backend), msg);
- g_free (msg);
+ cbdata->username = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingName));
+ cbdata->useridtype = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingAddressType));
+ cbdata->userid = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingEmailAddress));
- if (perror)
- e_cal_backend_mapi_maybe_disconnect (mapi_backend, *perror);
- g_clear_error (perror);
-}
+ cbdata->ownername = g_strdup (e_mapi_util_find_array_propval (&object->properties, PidTagSenderName));
+ cbdata->owneridtype = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSenderAddressType));
+ cbdata->ownerid = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSenderEmailAddress));
-static void
-free_component_slist (gpointer ptr)
-{
- g_slist_free_full (ptr, g_object_unref);
+ return TRUE;
}
-static void
-drop_removed_comps_cb (gpointer pmid, gpointer slist, gpointer pcbmapi)
+static gboolean
+ecb_mapi_list_for_one_mid_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ const ListObjectsData *object_data,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- ECalBackendMAPI *cbmapi = pcbmapi;
- ECalBackend *backend;
- GSList *iter;
-
- g_return_if_fail (pcbmapi != NULL);
-
- backend = E_CAL_BACKEND (cbmapi);
- g_return_if_fail (backend != NULL);
-
- for (iter = slist; iter; iter = iter->next) {
- ECalComponent *comp = iter->data;
- ECalComponentId *id;
-
- if (!comp) {
- g_debug ("%s: NULL component in list", G_STRFUNC);
- continue;
- }
+ mapi_id_t *pmid = user_data;
- id = e_cal_component_get_id (comp);
- if (!id) {
- g_debug ("%s: Failed to get component's ID", G_STRFUNC);
- continue;
- }
+ g_return_val_if_fail (pmid != NULL, FALSE);
+ g_return_val_if_fail (object_data != NULL, FALSE);
- if (e_cal_backend_store_remove_component (cbmapi->priv->store, id->uid, id->rid)) {
- e_cal_backend_notify_component_removed (backend, id, comp, NULL);
- }
+ *pmid = object_data->mid;
- e_cal_component_free_id (id);
- }
+ return TRUE;
}
-struct ListCalendarObjectsData
-{
- GSList *changed_mids; /* newly allocated mapi_id_t *; these will be fetched again */
- GHashTable *known_comps; /* reffed ECalComponent-s from the cache; those left will be removed;
- key is 'mapi_id_t *', the mid;
- value is GSList of the component and its detached instances
- */
- time_t latest_modified;
-};
-
static gboolean
-list_calendar_objects_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- const ListObjectsData *object_data,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
+ecb_mapi_build_global_id_restriction (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct mapi_SRestriction **restrictions,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- struct ListCalendarObjectsData *lco = user_data;
- GSList *slist;
- gboolean need_update = FALSE;
-
- g_return_val_if_fail (object_data != NULL, FALSE);
- g_return_val_if_fail (lco != NULL, FALSE);
+ ECalComponent *comp = user_data;
+ struct SBinary_short sb;
+ struct SPropValue sprop;
+ struct mapi_SRestriction *restriction;
+ gchar *propval;
- if (object_data->msg_class &&
- g_ascii_strcasecmp (object_data->msg_class, "IPM.Note") == 0) {
- return TRUE;
- }
+ g_return_val_if_fail (restrictions != NULL, FALSE);
+ g_return_val_if_fail (comp != NULL, FALSE);
- if (lco->latest_modified < object_data->last_modified)
- lco->latest_modified = object_data->last_modified;
+ restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (restriction != NULL, FALSE);
- slist = g_hash_table_lookup (lco->known_comps, &object_data->mid);
- if (!slist) {
- /* it's a new component on the server */
- need_update = TRUE;
- } else {
- /* known component, which might change */
- ECalComponent *comp = slist->data;
- struct icaltimetype *last_mod = NULL;
+ restriction->rt = RES_PROPERTY;
+ restriction->res.resProperty.relop = RELOP_EQ;
+ restriction->res.resProperty.ulPropTag = PidLidGlobalObjectId;
- /* pretty bad, but do not avoid fetching of other objects */
- g_return_val_if_fail (comp != NULL, TRUE);
+ propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp),
"X-EVOLUTION-MAPI-GLOBALID");
+ if (propval && *propval) {
+ gsize len = 0;
- e_cal_component_get_last_modified (comp, &last_mod);
+ sb.lpb = g_base64_decode (propval, &len);
+ sb.cb = len;
+ } else {
+ struct icaltimetype ical_creation_time = { 0 };
+ struct FILETIME creation_time = { 0 };
+ const gchar *uid;
- if (!last_mod ||
- icaltime_compare (icaltime_from_timet_with_zone (object_data->last_modified, 0,
icaltimezone_get_utc_timezone ()), *last_mod) != 0) {
- need_update = TRUE;
- }
+ uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (comp));
- if (last_mod)
- e_cal_component_free_icaltimetype (last_mod);
+ e_cal_component_get_dtstamp (comp, &ical_creation_time);
- g_hash_table_remove (lco->known_comps, &object_data->mid);
+ e_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
+ e_mapi_cal_util_generate_globalobjectid (FALSE, uid, NULL, ical_creation_time.year ?
&creation_time : NULL, &sb);
}
+ g_free (propval);
- if (need_update) {
- mapi_id_t *pmid;
-
- pmid = g_new0 (mapi_id_t, 1);
- *pmid = object_data->mid;
+ set_SPropValue_proptag (&sprop, PidLidGlobalObjectId, &sb);
+ cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
- lco->changed_mids = g_slist_prepend (lco->changed_mids, pmid);
- }
+ *restrictions = restriction;
return TRUE;
}
static gboolean
-transfer_calendar_objects_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- ECalBackendMAPI *cbmapi = user_data;
- ECalBackend *backend;
- ECalComponent *comp;
- const mapi_id_t *pmid;
- gchar *use_uid;
- GSList *comps = NULL, *iter;
-
- g_return_val_if_fail (cbmapi != NULL, FALSE);
- g_return_val_if_fail (object != NULL, FALSE);
-
- backend = E_CAL_BACKEND (cbmapi);
- g_return_val_if_fail (backend != NULL, FALSE);
-
- pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
- if (pmid)
- use_uid = e_mapi_util_mapi_id_to_string (*pmid);
- else
- use_uid = e_util_generate_uid ();
-
- comp = e_mapi_cal_util_object_to_comp (conn, object,
- e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi)), FALSE,
- e_cal_backend_get_cache_dir (E_CAL_BACKEND (cbmapi)),
- use_uid, &comps);
-
- g_free (use_uid);
-
- if (comp)
- comps = g_slist_prepend (comps, comp);
-
- for (iter = comps; iter; iter = iter->next) {
- ECalComponentId *id;
- ECalComponent *old_comp;
-
- comp = iter->data;
- if (!comp)
- continue;
-
- e_cal_component_commit_sequence (comp);
-
- id = e_cal_component_get_id (comp);
- if (!id) {
- g_debug ("%s: Failed to get component's ID", G_STRFUNC);
- continue;
- }
+ecb_mapi_build_global_id_or_mid_restriction_from_uid (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ struct mapi_SRestriction **restrictions,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ const gchar *uid = user_data;
+ struct SPropValue sprop;
+ struct mapi_SRestriction *restriction;
+ mapi_id_t mid = 0;
- old_comp = e_cal_backend_store_get_component (cbmapi->priv->store, id->uid, id->rid);
- if (old_comp) {
- mapi_id_t old_mid, new_mid;
+ g_return_val_if_fail (restrictions != NULL, FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
- get_comp_mid (e_cal_component_get_icalcomponent (old_comp), &old_mid);
- get_comp_mid (e_cal_component_get_icalcomponent (comp), &new_mid);
+ restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
+ g_return_val_if_fail (restriction != NULL, FALSE);
- if (new_mid && old_mid && new_mid != old_mid) {
- use_uid = e_mapi_util_mapi_id_to_string (new_mid);
- e_cal_component_set_uid (comp, use_uid);
- g_free (use_uid);
+ restriction->rt = RES_PROPERTY;
+ restriction->res.resProperty.relop = RELOP_EQ;
- e_cal_component_free_id (id);
- id = e_cal_component_get_id (comp);
- if (!id) {
- g_debug ("%s: Failed to re-get component's ID", G_STRFUNC);
- continue;
- }
+ if (e_mapi_util_mapi_id_from_string (uid, &mid) && mid) {
+ restriction->res.resProperty.ulPropTag = PidTagMid;
- old_comp = e_cal_backend_store_get_component (cbmapi->priv->store, id->uid,
id->rid);
- }
- }
+ set_SPropValue_proptag (&sprop, PidTagMid, &mid);
+ cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
+ } else {
+ struct SBinary_short sb;
+ gsize len = 0;
- put_component_to_store (cbmapi, comp);
+ sb.lpb = g_base64_decode (uid, &len);
+ sb.cb = len;
- if (old_comp) {
- e_cal_backend_notify_component_modified (backend, old_comp, comp);
- g_object_unref (old_comp);
- } else {
- e_cal_backend_notify_component_created (E_CAL_BACKEND (cbmapi), comp);
- }
+ restriction->res.resProperty.ulPropTag = PidLidGlobalObjectId;
- e_cal_component_free_id (id);
+ set_SPropValue_proptag (&sprop, PidLidGlobalObjectId, &sb);
+ cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
}
- g_slist_free_full (comps, g_object_unref);
-
- notify_view_progress (cbmapi, obj_index, obj_total);
+ *restrictions = restriction;
return TRUE;
}
+/* should call free_server_data() before done with cbdata */
static void
-copy_to_known_comps (gpointer key, gpointer value, gpointer user_data)
-{
- mapi_id_t *pmid = key, *pmidcopy;
- GSList *comps = value;
- GHashTable *known_comps = user_data;
-
- g_return_if_fail (pmid != NULL);
- g_return_if_fail (known_comps != NULL);
-
- pmidcopy = g_new0 (mapi_id_t, 1);
- *pmidcopy = *pmid;
-
- /* stealing 'comps' pointer here */
- g_hash_table_insert (known_comps, pmidcopy, comps);
-}
-
-static gboolean
-update_local_cache (ECalBackendMAPI *cbmapi, GCancellable *cancellable)
+ecb_mapi_get_server_data (ECalBackendMAPI *cbmapi,
+ ECalComponent *comp,
+ struct cal_cbdata *cbdata,
+ GCancellable *cancellable)
{
- ECalBackendMAPIPrivate *priv;
EMapiConnection *conn;
- struct ListCalendarObjectsData lco;
- GSList *iter, *components;
+ icalcomponent *icalcomp;
+ mapi_id_t mid;
mapi_object_t obj_folder;
- gboolean success = FALSE;
GError *mapi_error = NULL;
- GHashTable *comps_by_mids;
- gboolean partial_update;
- struct FolderBasicPropertiesData fbp;
-
- priv = cbmapi->priv;
- if (!e_backend_get_online (E_BACKEND (cbmapi)))
- return FALSE;
-
- g_mutex_lock (&priv->is_updating_mutex);
- priv->is_updating = TRUE;
- g_mutex_unlock (&priv->is_updating_mutex);
-
- g_mutex_lock (&priv->updating_mutex);
-
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
- if (!conn) {
- g_clear_error (&mapi_error);
- goto cleanup;
- }
- g_object_ref (conn);
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+ ecb_mapi_get_comp_mid (icalcomp, &mid);
- success = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
- if (!success) {
- notify_error (cbmapi, mapi_error, _("Failed to open folder: %s"));
+ conn = cbmapi->priv->conn;
+ if (!conn)
goto cleanup;
- }
- success = e_mapi_connection_get_folder_properties (conn, &obj_folder, NULL, NULL,
- e_mapi_utils_get_folder_basic_properties_cb, &fbp,
- cancellable, &mapi_error);
- if (!success) {
- notify_error (cbmapi, mapi_error, _("Failed to get folder properties: %s"));
- e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
+ if (!ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error))
goto cleanup;
- }
-
- comps_by_mids = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, NULL);
-
- components = e_cal_backend_store_get_components (priv->store);
- for (iter = components; iter; iter = iter->next) {
- ECalComponent *comp = iter->data;
- mapi_id_t mid, *pmid;
- GSList *comps;
-
- if (!comp)
- continue;
-
- get_comp_mid (e_cal_component_get_icalcomponent (comp), &mid);
-
- pmid = g_new0 (mapi_id_t, 1);
- *pmid = mid;
-
- comps = g_slist_prepend (g_hash_table_lookup (comps_by_mids, pmid), comp);
- g_hash_table_insert (comps_by_mids, pmid, comps);
- }
- /* doesn't call unref, because the hash table holds the components */
- g_slist_free (components);
-
- lco.changed_mids = NULL;
- lco.known_comps = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, free_component_slist);
- lco.latest_modified = priv->last_refresh;
-
- g_hash_table_foreach (comps_by_mids, copy_to_known_comps, lco.known_comps);
- g_hash_table_destroy (comps_by_mids);
- comps_by_mids = NULL;
-
- partial_update = priv->last_refresh > 0 && fbp.obj_total == priv->last_obj_total;
- success = e_mapi_connection_list_objects (conn, &obj_folder,
- partial_update ? e_mapi_utils_build_last_modify_restriction : NULL, &priv->last_refresh,
- list_calendar_objects_cb, &lco,
- cancellable, &mapi_error);
- if (!success) {
- notify_error (cbmapi, mapi_error, _("Failed to list objects: %s"));
-
- e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
-
- g_slist_free_full (lco.changed_mids, g_free);
- g_hash_table_destroy (lco.known_comps);
-
- goto cleanup;
- }
-
- e_cal_backend_store_freeze_changes (priv->store);
-
- if (!partial_update)
- g_hash_table_foreach (lco.known_comps, drop_removed_comps_cb, cbmapi);
- g_hash_table_destroy (lco.known_comps);
- lco.known_comps = NULL;
-
- if (lco.changed_mids) {
- success = e_mapi_connection_transfer_objects (conn, &obj_folder,
- lco.changed_mids,
- transfer_calendar_objects_cb, cbmapi,
- cancellable, &mapi_error);
-
- e_cal_backend_store_thaw_changes (priv->store);
-
- if (!success) {
- notify_error (cbmapi, mapi_error, _("Failed to transfer objects: %s"));
-
- e_mapi_connection_close_folder (conn, &obj_folder, NULL, NULL);
-
- g_slist_free_full (lco.changed_mids, g_free);
+ if (!e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecb_mapi_capture_req_props, cbdata,
cancellable, &mapi_error)) {
+ if (!g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
+ g_clear_error (&mapi_error);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
goto cleanup;
}
- g_slist_free_full (lco.changed_mids, g_free);
- } else {
- e_cal_backend_store_thaw_changes (priv->store);
+ /* try to find by global-id, if not found by MID */
+ g_clear_error (&mapi_error);
}
- priv->last_obj_total = fbp.obj_total;
- priv->last_refresh = lco.latest_modified;
-
- success = e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- if (!success) {
- notify_error (cbmapi, mapi_error, _("Failed to close folder: %s"));
-
- goto cleanup;
+ if (e_mapi_connection_list_objects (conn, &obj_folder,
+ ecb_mapi_build_global_id_restriction, comp,
+ ecb_mapi_list_for_one_mid_cb, &mid,
+ cancellable, &mapi_error)) {
+ e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecb_mapi_capture_req_props,
cbdata, cancellable, &mapi_error);
}
- cleanup:
- if (conn)
- g_object_unref (conn);
- g_mutex_unlock (&priv->updating_mutex);
-
- g_mutex_lock (&priv->is_updating_mutex);
- priv->is_updating = FALSE;
- g_mutex_unlock (&priv->is_updating_mutex);
-
- notify_view_completed (cbmapi);
+ e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- return success;
+ cleanup:
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ g_clear_error (&mapi_error);
}
+/* frees data members allocated in get_server_data(), not the cbdata itself */
static void
-ecbm_get_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const
gchar *rid, gchar **object, GError **error)
+ecb_mapi_free_server_data (struct cal_cbdata *cbdata)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- cbmapi = (ECalBackendMAPI *)(backend);
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (object != NULL, InvalidArg);
-
- priv = cbmapi->priv;
-
- g_mutex_lock (&priv->mutex);
-
- if (rid && *rid) {
- ECalComponent *comp;
-
- /* search the object in the cache */
- comp = e_cal_backend_store_get_component (priv->store, uid, rid);
-
- if (!comp) {
- /* the object is not in the backend store, double check that it's
- * also not on the server to prevent for a race condition where we
- * might otherwise mistakenly generate a new UID */
- g_mutex_unlock (&priv->mutex);
- update_local_cache (cbmapi, cancellable);
- g_mutex_lock (&priv->mutex);
- comp = e_cal_backend_store_get_component (priv->store, uid, rid);
- }
-
- if (comp) {
- g_mutex_unlock (&priv->mutex);
-
- *object = e_cal_component_get_as_string (comp);
+ if (!cbdata)
+ return;
- g_object_unref (comp);
- } else {
- g_mutex_unlock (&priv->mutex);
- }
- } else {
- *object = e_cal_backend_store_get_components_by_uid_as_ical_string (priv->store, uid);
- if (!*object && e_backend_get_online (E_BACKEND (backend))) {
- /* the object is not in the backend store, double check that it's
- * also not on the server to prevent for a race condition where we
- * might otherwise mistakenly generate a new UID */
- g_mutex_unlock (&priv->mutex);
- update_local_cache (cbmapi, cancellable);
- g_mutex_lock (&priv->mutex);
-
- *object = e_cal_backend_store_get_components_by_uid_as_ical_string (priv->store, uid);
- }
+ #define do_free(_func, _val) _func (_val); _val = NULL
- g_mutex_unlock (&priv->mutex);
- }
+ do_free (e_mapi_util_free_sbinary_short, cbdata->cleanglobalid);
+ do_free (e_mapi_util_free_sbinary_short, cbdata->globalid);
+ do_free (g_free, cbdata->username);
+ do_free (g_free, cbdata->useridtype);
+ do_free (g_free, cbdata->userid);
+ do_free (g_free, cbdata->ownername);
+ do_free (g_free, cbdata->owneridtype);
+ do_free (g_free, cbdata->ownerid);
- if (!*object)
- g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+ #undef do_free
}
-static void
-ecbm_get_object_list (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *sexp,
GSList **objects, GError **perror)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- GSList *components, *l;
- ECalBackendSExp *cbsexp;
- gboolean search_needed = TRUE;
- time_t occur_start = -1, occur_end = -1;
- gboolean prunning_by_time;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+#define free_and_dupe_str(_des, _new) G_STMT_START { \
+ g_free (_des); \
+ _des = g_strdup (_new); \
+ } G_STMT_END
- g_mutex_lock (&priv->mutex);
+static ESource *
+ecb_mapi_find_identity_source (ECalBackendMAPI *cbmapi)
+{
+ ESourceRegistry *registry;
+ GList *all_sources, *my_sources, *iter;
+ CamelMapiSettings *settings;
+ ESource *res = NULL;
- if (g_str_equal (sexp, "#t"))
- search_needed = FALSE;
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), NULL);
- cbsexp = e_cal_backend_sexp_new (sexp);
+ settings = ecb_mapi_get_collection_settings (cbmapi);
+ g_return_val_if_fail (settings != NULL, NULL);
- if (!cbsexp) {
- g_mutex_unlock (&priv->mutex);
- g_propagate_error (perror, EDC_ERROR (InvalidQuery));
- return;
- }
+ registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbmapi));
+ all_sources = e_source_registry_list_sources (registry, NULL);
+ my_sources = e_mapi_utils_filter_sources_for_profile (all_sources,
+ camel_mapi_settings_get_profile (settings));
+ g_list_free_full (all_sources, g_object_unref);
- *objects = NULL;
- prunning_by_time = e_cal_backend_sexp_evaluate_occur_times(cbsexp, &occur_start, &occur_end);
+ for (iter = my_sources; iter; iter = iter->next) {
+ ESource *source = iter->data;
- components = prunning_by_time ?
- e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
- : e_cal_backend_store_get_components (priv->store);
+ if (!source)
+ continue;
- for (l = components; l != NULL; l = l->next) {
- ECalComponent *comp = E_CAL_COMPONENT (l->data);
- if (e_cal_backend_get_kind (E_CAL_BACKEND (backend)) ==
- icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
- if ((!search_needed) ||
- (e_cal_backend_sexp_match_comp (cbsexp, comp, E_TIMEZONE_CACHE
(backend)))) {
- *objects = g_slist_append (*objects, e_cal_component_get_as_string (comp));
- }
+ if (e_source_has_extension (source, E_SOURCE_EXTENSION_MAIL_IDENTITY)) {
+ res = g_object_ref (source);
+ break;
}
}
- g_slist_free_full (components, g_object_unref);
- g_object_unref (cbsexp);
- g_mutex_unlock (&priv->mutex);
-}
+ g_list_free_full (my_sources, g_object_unref);
-static void
-ecbm_get_attachment_uris (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid,
const gchar *rid, GSList **list, GError **perror)
-{
- /* TODO implement the function */
- g_propagate_error (perror, EDC_ERROR (NotSupported));
+ return res;
}
-static guint
-get_cache_refresh_interval (void)
+static const gchar *
+ecb_mapi_get_owner_name (ECalBackendMAPI *cbmapi)
{
- guint time_interval;
- const gchar *time_interval_string = NULL;
-
- time_interval = CACHE_REFRESH_INTERVAL;
- time_interval_string = g_getenv ("GETQM_TIME_INTERVAL");
- if (time_interval_string) {
- time_interval = g_ascii_strtod (time_interval_string, NULL);
- time_interval *= (60*1000);
- }
+ ESource *identity_source;
+ ESourceMailIdentity *identity_ext;
+ const gchar *res = NULL;
+
+ identity_source = ecb_mapi_find_identity_source (cbmapi);
+ if (!identity_source)
+ return NULL;
+
+ identity_ext = e_source_get_extension (identity_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+ if (identity_ext)
+ res = e_source_mail_identity_get_name (identity_ext);
+
+ g_object_unref (identity_source);
- return time_interval;
+ return res;
}
-static gpointer
-delta_thread (gpointer data)
+static const gchar *
+ecb_mapi_get_owner_email (ECalBackendMAPI *cbmapi)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- GCancellable *cancellable;
- gint64 end_time;
-
- cbmapi = (ECalBackendMAPI *)(data);
- g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), NULL);
+ ESource *identity_source;
+ ESourceMailIdentity *identity_ext;
+ const gchar *res = NULL;
- priv = cbmapi->priv;
- cancellable = g_object_ref (priv->cancellable);
+ identity_source = ecb_mapi_find_identity_source (cbmapi);
+ if (!identity_source)
+ return NULL;
- while (!g_cancellable_is_cancelled (cancellable)) {
- update_local_cache (cbmapi, cancellable);
+ identity_ext = e_source_get_extension (identity_source, E_SOURCE_EXTENSION_MAIL_IDENTITY);
+ if (identity_ext)
+ res = e_source_mail_identity_get_address (identity_ext);
- g_mutex_lock (&priv->dlock->mutex);
+ g_object_unref (identity_source);
- if (priv->dlock->exit)
- break;
+ return res;
+}
- end_time = g_get_monotonic_time () + get_cache_refresh_interval () * G_TIME_SPAN_SECOND;
- g_cond_wait_until (&priv->dlock->cond, &priv->dlock->mutex, end_time);
+static gboolean
+ecb_mapi_modifier_is_organizer (ECalBackendMAPI *cbmapi,
+ ECalComponent *comp)
+{
+ ECalComponentOrganizer org;
+ const gchar *ownerid, *orgid;
- if (priv->dlock->exit)
- break;
+ if (!e_cal_component_has_organizer (comp))
+ return TRUE;
- g_mutex_unlock (&priv->dlock->mutex);
- }
+ e_cal_component_get_organizer (comp, &org);
+ if (!g_ascii_strncasecmp (org.value, "mailto:", 7))
+ orgid = (org.value) + 7;
+ else
+ orgid = org.value;
- g_object_unref (cancellable);
- g_mutex_unlock (&priv->dlock->mutex);
- priv->dthread = NULL;
+ ownerid = ecb_mapi_get_owner_email (cbmapi);
- return NULL;
+ return g_ascii_strcasecmp (orgid, ownerid) == 0;
}
-static void
-run_delta_thread (ECalBackendMAPI *cbmapi)
+static OlResponseStatus
+ecb_mapi_find_my_response (ECalBackendMAPI *cbmapi,
+ ECalComponent *comp)
{
- ECalBackendMAPIPrivate *priv;
- GError *error = NULL;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
+ icalproperty *attendee;
+ gchar *att = NULL;
+ OlResponseStatus val = olResponseTentative;
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi));
+ att = g_strdup_printf ("MAILTO:%s", ecb_mapi_get_owner_email (cbmapi));
- priv = cbmapi->priv;
+ for (attendee = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
+ attendee;
+ attendee = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY)) {
+ const gchar *value = icalproperty_get_attendee (attendee);
+ if (!g_ascii_strcasecmp (value, att)) {
+ icalparameter *param = icalproperty_get_first_parameter (attendee,
ICAL_PARTSTAT_PARAMETER);
- /* If the thread is already running just return back */
- if (priv->dthread) {
- g_cond_signal (&priv->dlock->cond);
- return;
- }
+ switch (icalparameter_get_partstat (param)) {
+ case ICAL_PARTSTAT_ACCEPTED:
+ val = olResponseAccepted;
+ break;
+ case ICAL_PARTSTAT_TENTATIVE:
+ val = olResponseTentative;
+ break;
+ case ICAL_PARTSTAT_DECLINED:
+ val = olResponseDeclined;
+ break;
+ default:
+ val = olResponseTentative;
+ break;
+ }
- if (!priv->dlock) {
- priv->dlock = g_new0 (SyncDelta, 1);
- g_mutex_init (&priv->dlock->mutex);
- g_cond_init (&priv->dlock->cond);
+ break;
+ }
}
- priv->dlock->exit = FALSE;
- priv->dthread = g_thread_try_new (NULL, (GThreadFunc) delta_thread, cbmapi, &error);
- if (!priv->dthread) {
- g_warning (G_STRLOC ": %s", error ? error->message : "Unknown error");
- g_clear_error (&error);
- }
+ g_free (att);
+
+ return val;
}
static void
-ecbm_server_notification_cb (EMapiConnection *conn,
- guint event_mask,
- gpointer event_data,
- gpointer user_data)
+ecb_mapi_server_notification_cb (EMapiConnection *conn,
+ guint event_mask,
+ gpointer event_data,
+ gpointer user_data)
{
ECalBackendMAPI *cbmapi = user_data;
- ECalBackendMAPIPrivate *priv;
mapi_id_t update_folder1 = 0, update_folder2 = 0;
- g_return_if_fail (cbmapi != NULL);
+ g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi));
switch (event_mask) {
case fnevNewMail:
@@ -1152,924 +646,815 @@ ecbm_server_notification_cb (EMapiConnection *conn,
break;
}
- priv = cbmapi->priv;
- if (priv->fid == update_folder1 || priv->fid == update_folder2)
- run_delta_thread (cbmapi);
+ if (update_folder1 || update_folder2) {
+ ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
+
+ source = e_backend_get_source (E_BACKEND (cbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
+
+ if (update_folder1 == e_source_mapi_folder_get_id (ext_mapi_folder) ||
+ update_folder2 == e_source_mapi_folder_get_id (ext_mapi_folder)) {
+ e_cal_meta_backend_schedule_refresh (E_CAL_META_BACKEND (cbmapi));
+ }
+ }
}
-static ESourceAuthenticationResult
-ecbm_connect_user (ECalBackend *backend,
- const ENamedParameters *credentials,
- gboolean update_connection_status,
- GCancellable *cancellable,
- GError **perror)
+static gboolean
+ecb_mapi_connect_sync (ECalMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
{
ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- CamelMapiSettings *settings;
EMapiConnection *old_conn;
+ CamelMapiSettings *settings;
ESource *source;
+ ESourceMapiFolder *ext_mapi_folder;
GError *mapi_error = NULL;
- g_mutex_lock (&auth_mutex);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_auth_result != NULL, FALSE);
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
+
+ ecb_mapi_lock_connection (cbmapi);
+
+ if (cbmapi->priv->conn &&
+ e_mapi_connection_connected (cbmapi->priv->conn)) {
+ ecb_mapi_unlock_connection (cbmapi);
+ return TRUE;
+ }
- old_conn = priv->conn;
- settings = ecbm_get_collection_settings (cbmapi);
+ settings = ecb_mapi_get_collection_settings (cbmapi);
source = e_backend_get_source (E_BACKEND (cbmapi));
+ ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- if (update_connection_status)
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
-
- priv->conn = e_mapi_connection_new (
- e_cal_backend_get_registry (backend),
- camel_mapi_settings_get_profile (settings), credentials, cancellable, &mapi_error);
- if (!priv->conn) {
- priv->conn = e_mapi_connection_find (camel_mapi_settings_get_profile (settings));
- if (priv->conn
- && !e_mapi_connection_connected (priv->conn)) {
- e_mapi_connection_reconnect (priv->conn, credentials, cancellable, &mapi_error);
- }
+ old_conn = cbmapi->priv->conn;
+
+ cbmapi->priv->conn = e_mapi_connection_new (
+ e_cal_backend_get_registry (E_CAL_BACKEND (cbmapi)),
+ camel_mapi_settings_get_profile (settings),
+ credentials, cancellable, &mapi_error);
+
+ if (!cbmapi->priv->conn) {
+ cbmapi->priv->conn = e_mapi_connection_find (camel_mapi_settings_get_profile (settings));
+ if (cbmapi->priv->conn && !e_mapi_connection_connected (cbmapi->priv->conn))
+ e_mapi_connection_reconnect (cbmapi->priv->conn, credentials, cancellable,
&mapi_error);
}
if (old_conn)
- g_object_unref (old_conn);
+ g_signal_handlers_disconnect_by_func (old_conn, G_CALLBACK (ecb_mapi_server_notification_cb),
cbmapi);
- if (priv->conn && e_mapi_connection_connected (priv->conn)) {
- /* Success */
- ESourceMapiFolder *ext_mapi_folder;
+ g_clear_object (&old_conn);
- if (update_connection_status)
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+ if (!cbmapi->priv->conn || mapi_error) {
+ gboolean is_network_error = mapi_error && mapi_error->domain != E_MAPI_ERROR;
- ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER);
- if (ext_mapi_folder && e_source_mapi_folder_get_server_notification (ext_mapi_folder)) {
- mapi_object_t obj_folder;
- gboolean status;
+ g_clear_object (&cbmapi->priv->conn);
+ ecb_mapi_unlock_connection (cbmapi);
- status = ecbm_open_folder (cbmapi, priv->conn, &obj_folder, NULL, NULL);
- if (status) {
- e_mapi_connection_enable_notifications (priv->conn, &obj_folder,
- fnevObjectCreated | fnevObjectModified | fnevObjectDeleted |
fnevObjectMoved | fnevObjectCopied,
- NULL, NULL);
+ if (is_network_error)
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError, NULL);
- e_mapi_connection_close_folder (priv->conn, &obj_folder, NULL, NULL);
- }
+ g_clear_error (&mapi_error);
- g_signal_connect (priv->conn, "server-notification", G_CALLBACK
(ecbm_server_notification_cb), cbmapi);
- }
- } else {
- gboolean is_network_error = mapi_error && mapi_error->domain != E_MAPI_ERROR;
+ *out_auth_result = is_network_error ? E_SOURCE_AUTHENTICATION_ERROR :
E_SOURCE_AUTHENTICATION_REJECTED;
- if (is_network_error) {
- if (update_connection_status)
- e_source_set_connection_status (source,
E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- mapi_error_to_edc_error (perror, mapi_error, OtherError, NULL);
- } else if (update_connection_status) {
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- }
- if (mapi_error)
- g_error_free (mapi_error);
- g_mutex_unlock (&auth_mutex);
- return is_network_error ? E_SOURCE_AUTHENTICATION_ERROR : E_SOURCE_AUTHENTICATION_REJECTED;
+ return FALSE;
}
- if (mapi_error) {
- /* do not set error when authentication was rejected */
- g_error_free (mapi_error);
- g_mutex_unlock (&auth_mutex);
- return E_SOURCE_AUTHENTICATION_REJECTED;
- }
+ if (e_source_mapi_folder_get_server_notification (ext_mapi_folder)) {
+ mapi_object_t obj_folder;
+ GError *mapi_error = NULL;
- g_mutex_unlock (&auth_mutex);
+ g_signal_connect (cbmapi->priv->conn, "server-notification", G_CALLBACK
(ecb_mapi_server_notification_cb), cbmapi);
- if (!priv->fid) {
- g_propagate_error (perror, EDC_ERROR_EX (OtherError, "No folder ID set"));
- return E_SOURCE_AUTHENTICATION_ERROR;
- }
+ if (ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error)) {
+ e_mapi_connection_enable_notifications (cbmapi->priv->conn, &obj_folder,
+ fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved
| fnevObjectCopied,
+ cancellable, &mapi_error);
+
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
+ }
- if (!priv->conn || !e_mapi_connection_connected (priv->conn)) {
- /* do not set error when authentication was rejected */
- return E_SOURCE_AUTHENTICATION_REJECTED;
+ if (mapi_error) {
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ g_clear_error (&mapi_error);
+ }
}
- /* We have established a connection */
- if (priv->store && priv->fid) {
- e_backend_set_online (E_BACKEND (cbmapi), TRUE);
+ ecb_mapi_unlock_connection (cbmapi);
- run_delta_thread (cbmapi);
- }
+ *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
- return E_SOURCE_AUTHENTICATION_ACCEPTED;
+ return TRUE;
}
static gboolean
-e_cal_backend_mapi_ensure_connected (ECalBackendMAPI *cbma,
- GCancellable *cancellable,
- GError **perror)
+ecb_mapi_disconnect_sync (ECalMetaBackend *meta_backend,
+ GCancellable *cancellable,
+ GError **error)
{
- CamelMapiSettings *settings;
- GError *local_error = NULL;
+ ECalBackendMAPI *cbmapi;
+ gboolean success = TRUE;
- g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbma), FALSE);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
- if (cbma->priv->conn && e_mapi_connection_connected (cbma->priv->conn))
- return TRUE;
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
- settings = ecbm_get_collection_settings (cbma);
+ ecb_mapi_lock_connection (cbmapi);
- if (!camel_mapi_settings_get_kerberos (settings) ||
- ecbm_connect_user (E_CAL_BACKEND (cbma), NULL, TRUE, cancellable, &local_error) !=
E_SOURCE_AUTHENTICATION_ACCEPTED) {
- e_backend_credentials_required_sync (E_BACKEND (cbma),
- E_SOURCE_CREDENTIALS_REASON_REQUIRED, NULL, 0, NULL,
- cancellable, &local_error);
- }
+ if (cbmapi->priv->conn) {
+ g_signal_handlers_disconnect_by_func (cbmapi->priv->conn, G_CALLBACK
(ecb_mapi_server_notification_cb), cbmapi);
- if (!local_error)
- return TRUE;
+ success = e_mapi_connection_disconnect (cbmapi->priv->conn, FALSE, cancellable, error);
+ g_clear_object (&cbmapi->priv->conn);
+ }
- g_propagate_error (perror, local_error);
+ ecb_mapi_unlock_connection (cbmapi);
- return FALSE;
+ return success;
}
-static void
-e_cal_backend_mapi_maybe_disconnect (ECalBackendMAPI *cbma,
- const GError *mapi_error)
+typedef struct _LoadMultipleData {
+ ECalMetaBackend *meta_backend;
+ icalcomponent_kind kind;
+ GSList **out_components; /* icalcomponent * */
+} LoadMultipleData;
+
+static gboolean
+transfer_calendar_objects_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ /* const */ EMapiObject *object,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (cbma));
+ LoadMultipleData *lmd = user_data;
+ ECalComponent *comp;
+ const mapi_id_t *pmid;
+ gchar *use_uid;
+ GSList *instances = NULL;
- /* no error or already disconnected */
- if (!mapi_error || !cbma->priv->conn)
- return;
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (object != NULL, FALSE);
+ g_return_val_if_fail (lmd != NULL, FALSE);
- if (g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed) ||
- g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_CALL_FAILED)) {
- e_mapi_connection_disconnect (cbma->priv->conn,
- !g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed),
- NULL, NULL);
- g_object_unref (cbma->priv->conn);
- cbma->priv->conn = NULL;
- }
-}
+ pmid = e_mapi_util_find_array_propval (&object->properties, PidTagMid);
+ if (pmid)
+ use_uid = e_mapi_util_mapi_id_to_string (*pmid);
+ else
+ use_uid = e_util_generate_uid ();
-static EMapiConnection *
-e_cal_backend_mapi_get_connection (ECalBackendMAPI *cbma,
- GCancellable *cancellable,
- GError **perror)
-{
- g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbma), NULL);
- g_return_val_if_fail (cbma->priv != NULL, NULL);
+ comp = e_mapi_cal_util_object_to_comp (conn, object,
+ lmd->kind, FALSE, use_uid, &instances);
- if (cbma->priv->conn)
- return cbma->priv->conn;
+ g_free (use_uid);
- if (!e_backend_get_online (E_BACKEND (cbma)))
- return NULL;
+ if (comp)
+ instances = g_slist_prepend (instances, comp);
- if (!e_cal_backend_mapi_ensure_connected (cbma, cancellable, perror))
- return NULL;
+ if (instances) {
+ icalcomponent *icomp;
- return cbma->priv->conn;
+ icomp = e_cal_meta_backend_merge_instances (lmd->meta_backend, instances, FALSE);
+ if (icomp)
+ *lmd->out_components = g_slist_prepend (*lmd->out_components, icomp);
+ }
+
+ g_slist_free_full (instances, g_object_unref);
+
+ return TRUE;
}
-static void
-ecbm_open (ECalBackend *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- gboolean only_if_exists,
- GError **perror)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- ESource *esource;
- ESourceMapiFolder *ext_mapi_folder;
- guint64 fid;
- const gchar *cache_dir;
- GError *error = NULL;
+static gboolean
+ecb_mapi_load_multiple_sync (ECalBackendMAPI *cbmapi,
+ const GSList *uids, /* gchar * */
+ GSList **out_components, /* icalcomponent * */
+ GCancellable *cancellable,
+ GError **error)
+{
+ LoadMultipleData lmd;
+ GSList *mids = NULL, *link;
+ mapi_object_t obj_folder;
+ gboolean success;
+ GError *mapi_error = NULL;
- if (e_cal_backend_is_opened (backend))
- return /* Success */;
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), FALSE);
+ g_return_val_if_fail (uids != NULL, FALSE);
+ g_return_val_if_fail (out_components != NULL, FALSE);
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+ for (link = (GSList *) uids; link; link = g_slist_next (link)) {
+ mapi_id_t *pmid, mid;
- esource = e_backend_get_source (E_BACKEND (cbmapi));
- ext_mapi_folder = e_source_get_extension (esource, E_SOURCE_EXTENSION_MAPI_FOLDER);
- fid = e_source_mapi_folder_get_id (ext_mapi_folder);
- if (!fid) {
- g_propagate_error (perror, EDC_ERROR_EX (OtherError, "No folder ID set"));
- return;
+ if (e_mapi_util_mapi_id_from_string (link->data, &mid)) {
+ pmid = g_new0 (mapi_id_t, 1);
+ *pmid = mid;
+
+ mids = g_slist_prepend (mids, pmid);
+ }
}
- g_mutex_lock (&priv->mutex);
+ ecb_mapi_lock_connection (cbmapi);
+
+ lmd.meta_backend = E_CAL_META_BACKEND (cbmapi);
+ lmd.kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi));
+ lmd.out_components = out_components;
+
+ success = ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error);
- cbmapi->priv->read_only = FALSE;
+ if (success) {
+ success = e_mapi_connection_transfer_objects (cbmapi->priv->conn, &obj_folder, mids,
+ transfer_calendar_objects_cb, &lmd, cancellable, &mapi_error);
- if (priv->store) {
- g_object_unref (priv->store);
- priv->store = NULL;
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable, &mapi_error);
}
- /* Always create cache here */
- cache_dir = e_cal_backend_get_cache_dir (backend);
- priv->store = e_cal_backend_store_new (cache_dir, E_TIMEZONE_CACHE (backend));
+ if (mapi_error) {
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to transfer objects
from a server"));
+ g_error_free (mapi_error);
- if (!priv->store) {
- g_mutex_unlock (&priv->mutex);
- g_propagate_error (perror, EDC_ERROR_EX (OtherError, _("Could not create cache file")));
- return;
+ success = FALSE;
}
- e_cal_backend_store_load (priv->store);
+ ecb_mapi_unlock_connection (cbmapi);
- g_free (priv->foreign_username);
+ g_slist_free_full (mids, g_free);
- priv->fid = fid;
- priv->is_public_folder = e_source_mapi_folder_is_public (ext_mapi_folder);
- priv->foreign_username = e_source_mapi_folder_dup_foreign_username (ext_mapi_folder);
+ return success;
+}
- if (priv->foreign_username && !*priv->foreign_username) {
- g_free (priv->foreign_username);
- priv->foreign_username = NULL;
- }
+static gboolean
+ecb_mapi_preload_infos_sync (ECalBackendMAPI *cbmapi,
+ GSList *created_objects,
+ GSList *modified_objects,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GHashTable *infos;
+ GSList *uids = NULL, *link;
+ gboolean success = TRUE;
- /* Not for remote */
- if (!e_backend_get_online (E_BACKEND (backend))) {
- ESourceOffline *offline_extension;
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), FALSE);
- cbmapi->priv->read_only = TRUE;
+ infos = g_hash_table_new (g_str_hash, g_str_equal);
- offline_extension = e_source_get_extension (esource, E_SOURCE_EXTENSION_OFFLINE);
+ for (link = created_objects; link; link = g_slist_next (link)) {
+ ECalMetaBackendInfo *nfo = link->data;
- if (!e_source_offline_get_stay_synchronized (offline_extension)) {
- g_mutex_unlock (&priv->mutex);
- g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
- return;
+ if (nfo && nfo->extra) {
+ uids = g_slist_prepend (uids, nfo->extra);
+ g_hash_table_insert (infos, nfo->extra, nfo);
+ } else if (nfo && nfo->uid) {
+ uids = g_slist_prepend (uids, nfo->uid);
+ g_hash_table_insert (infos, nfo->uid, nfo);
}
-
- g_mutex_unlock (&priv->mutex);
- e_backend_set_online (E_BACKEND (backend), FALSE);
- e_cal_backend_set_writable (backend, !priv->read_only);
- return /* Success */;
}
- g_mutex_unlock (&priv->mutex);
+ for (link = modified_objects; link; link = g_slist_next (link)) {
+ ECalMetaBackendInfo *nfo = link->data;
- e_backend_set_online (E_BACKEND (backend), TRUE);
- e_cal_backend_set_writable (backend, !priv->read_only);
+ if (nfo && nfo->extra) {
+ uids = g_slist_prepend (uids, nfo->extra);
+ g_hash_table_insert (infos, nfo->extra, nfo);
+ } else if (nfo && nfo->uid) {
+ uids = g_slist_prepend (uids, nfo->uid);
+ g_hash_table_insert (infos, nfo->uid, nfo);
+ }
+ }
- e_cal_backend_mapi_ensure_connected (cbmapi, cancellable, &error);
+ uids = g_slist_reverse (uids);
+ if (uids) {
+ GSList *components = NULL;
- if (error)
- g_propagate_error (perror, error);
-}
+ success = ecb_mapi_load_multiple_sync (cbmapi, uids, &components, cancellable, error);
+ if (success) {
+ for (link = components; link; link = g_slist_next (link)) {
+ icalcomponent *icomp = link->data;
+ if (icomp) {
+ ECalMetaBackendInfo *nfo;
+ const gchar *uid = NULL;
+ gchar *xmid = NULL;
-static ESourceAuthenticationResult
-ecbm_authenticate_sync (EBackend *backend,
- const ENamedParameters *credentials,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GCancellable *cancellable,
- GError **error)
-{
- return ecbm_connect_user (E_CAL_BACKEND (backend), credentials, FALSE, cancellable, error);
-}
+ if (icalcomponent_isa (icomp) == ICAL_VCALENDAR_COMPONENT) {
+ icalcomponent *subcomp;
+ icalcomponent_kind kind;
-static gboolean
-ecbm_capture_req_props (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- /* const */ EMapiObject *object,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- struct cal_cbdata *cbdata = user_data;
- const uint32_t *ui32;
+ kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi));
- g_return_val_if_fail (object != NULL, FALSE);
- g_return_val_if_fail (cbdata != NULL, FALSE);
+ for (subcomp = icalcomponent_get_first_component (icomp,
kind);
+ subcomp && !uid;
+ subcomp = icalcomponent_get_next_component (icomp,
kind)) {
+ uid = icalcomponent_get_uid (subcomp);
+ xmid = e_mapi_cal_utils_get_icomp_x_prop (subcomp,
"X-EVOLUTION-MAPI-MID");
+ }
+ } else {
+ uid = icalcomponent_get_uid (icomp);
+ xmid = e_mapi_cal_utils_get_icomp_x_prop (icomp,
"X-EVOLUTION-MAPI-MID");
+ }
- ui32 = e_mapi_util_find_array_propval (&object->properties, PidTagOwnerAppointmentId);
- if (ui32)
- cbdata->appt_id = *ui32;
- ui32 = e_mapi_util_find_array_propval (&object->properties, PidLidAppointmentSequence);
- if (ui32)
- cbdata->appt_seq = *ui32;
+ nfo = uid ? g_hash_table_lookup (infos, uid) : NULL;
+ if (!nfo && xmid)
+ nfo = g_hash_table_lookup (infos, xmid);
- cbdata->cleanglobalid = e_mapi_util_copy_sbinary_short (e_mapi_util_find_array_propval
(&object->properties, PidLidCleanGlobalObjectId));
- cbdata->globalid = e_mapi_util_copy_sbinary_short (e_mapi_util_find_array_propval
(&object->properties, PidLidGlobalObjectId));
+ if (nfo && !nfo->object)
+ nfo->object = icalcomponent_as_ical_string_r (icomp);
- cbdata->username = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingName));
- cbdata->useridtype = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingAddressType));
- cbdata->userid = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSentRepresentingEmailAddress));
+ g_free (xmid);
+ }
+ }
+ }
- cbdata->ownername = g_strdup (e_mapi_util_find_array_propval (&object->properties, PidTagSenderName));
- cbdata->owneridtype = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSenderAddressType));
- cbdata->ownerid = g_strdup (e_mapi_util_find_array_propval (&object->properties,
PidTagSenderEmailAddress));
+ g_slist_free_full (components, (GDestroyNotify) icalcomponent_free);
+ }
- return TRUE;
+ g_hash_table_destroy (infos);
+ g_slist_free (uids);
+
+ return success;
}
static gboolean
-ecbm_list_for_one_mid_cb (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- const ListObjectsData *object_data,
- guint32 obj_index,
- guint32 obj_total,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
+ecb_mapi_get_changes_sync (ECalMetaBackend *meta_backend,
+ const gchar *last_sync_tag,
+ gboolean is_repeat,
+ gchar **out_new_sync_tag,
+ gboolean *out_repeat,
+ GSList **out_created_objects,
+ GSList **out_modified_objects,
+ GSList **out_removed_objects,
+ GCancellable *cancellable,
+ GError **error)
{
- mapi_id_t *pmid = user_data;
+ ECalBackendMAPI *cbmapi;
- g_return_val_if_fail (pmid != NULL, FALSE);
- g_return_val_if_fail (object_data != NULL, FALSE);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_created_objects != NULL, FALSE);
+ g_return_val_if_fail (out_modified_objects != NULL, FALSE);
- *pmid = object_data->mid;
+ /* Chain up to parent's method */
+ if (!E_CAL_META_BACKEND_CLASS (e_cal_backend_mapi_parent_class)->get_changes_sync (meta_backend,
+ last_sync_tag, is_repeat, out_new_sync_tag, out_repeat, out_created_objects,
+ out_modified_objects, out_removed_objects, cancellable, error)) {
+ return FALSE;
+ }
+
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
+
+ /* Preload some of the components in chunk, to speed-up things;
+ ignore errors, to not break whole update process. */
+ ecb_mapi_preload_infos_sync (cbmapi, *out_created_objects, *out_modified_objects, cancellable, NULL);
return TRUE;
}
static gboolean
-ecbm_build_global_id_restriction (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- struct mapi_SRestriction **restrictions,
- gpointer user_data,
- GCancellable *cancellable,
- GError **perror)
-{
- ECalComponent *comp = user_data;
- struct SBinary_short sb;
- struct SPropValue sprop;
- struct mapi_SRestriction *restriction;
- gchar *propval;
-
- g_return_val_if_fail (restrictions != NULL, FALSE);
- g_return_val_if_fail (comp != NULL, FALSE);
+ecb_mapi_list_existing_uids_cb (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ const ListObjectsData *object_data,
+ guint32 obj_index,
+ guint32 obj_total,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ GSList **out_existing_objects = user_data;
+ gchar *uid;
- restriction = talloc_zero (mem_ctx, struct mapi_SRestriction);
- g_return_val_if_fail (restriction != NULL, FALSE);
+ g_return_val_if_fail (conn != NULL, FALSE);
+ g_return_val_if_fail (object_data != NULL, FALSE);
+ g_return_val_if_fail (out_existing_objects != NULL, FALSE);
- restriction->rt = RES_PROPERTY;
- restriction->res.resProperty.relop = RELOP_EQ;
- restriction->res.resProperty.ulPropTag = PidLidGlobalObjectId;
+ uid = e_mapi_util_mapi_id_to_string (object_data->mid);
+ if (uid) {
+ struct icaltimetype itt;
+ gchar *rev;
- propval = e_mapi_cal_utils_get_icomp_x_prop (e_cal_component_get_icalcomponent (comp),
"X-EVOLUTION-MAPI-GLOBALID");
- if (propval && *propval) {
- gsize len = 0;
+ itt = icaltime_from_timet_with_zone (object_data->last_modified, 0,
icaltimezone_get_utc_timezone ());
+ rev = icaltime_as_ical_string_r (itt);
- sb.lpb = g_base64_decode (propval, &len);
- sb.cb = len;
- } else {
- struct icaltimetype ical_creation_time = { 0 };
- struct FILETIME creation_time = { 0 };
- const gchar *uid;
+ *out_existing_objects = g_slist_prepend (*out_existing_objects,
+ e_cal_meta_backend_info_new (uid, rev, NULL, uid));
- uid = icalcomponent_get_uid (e_cal_component_get_icalcomponent (comp));
+ g_free (uid);
+ g_free (rev);
+ }
- e_cal_component_get_dtstamp (comp, &ical_creation_time);
+ return TRUE;
+}
- e_mapi_util_time_t_to_filetime (icaltime_as_timet (ical_creation_time), &creation_time);
- e_mapi_cal_util_generate_globalobjectid (FALSE, uid, NULL, ical_creation_time.year ?
&creation_time : NULL, &sb);
- }
- g_free (propval);
+static gboolean
+ecb_mapi_populate_mid_to_gid_cb (ECalCache *cal_cache,
+ const gchar *uid,
+ const gchar *rid,
+ const gchar *revision,
+ const gchar *object,
+ const gchar *extra,
+ EOfflineState offline_state,
+ gpointer user_data)
+{
+ GHashTable *mid_to_gid = user_data;
- set_SPropValue_proptag (&sprop, PidLidGlobalObjectId, &sb);
- cast_mapi_SPropValue (mem_ctx, &(restriction->res.resProperty.lpProp), &sprop);
+ g_return_val_if_fail (mid_to_gid != NULL, FALSE);
- *restrictions = restriction;
+ if (uid && *uid && extra && *extra && g_strcmp0 (uid, extra) != 0)
+ g_hash_table_insert (mid_to_gid, g_strdup (extra), g_strdup (uid));
return TRUE;
}
-/* should call free_server_data() before done with cbdata */
-static void
-get_server_data (ECalBackendMAPI *cbmapi,
- ECalComponent *comp,
- struct cal_cbdata *cbdata,
- GCancellable *cancellable)
+static gboolean
+ecb_mapi_list_existing_sync (ECalMetaBackend *meta_backend,
+ gchar **out_new_sync_tag,
+ GSList **out_existing_objects,
+ GCancellable *cancellable,
+ GError **error)
{
- EMapiConnection *conn;
- icalcomponent *icalcomp;
- mapi_id_t mid;
+ ECalBackendMAPI *cbmapi;
mapi_object_t obj_folder;
+ gboolean success;
GError *mapi_error = NULL;
- icalcomp = e_cal_component_get_icalcomponent (comp);
- get_comp_mid (icalcomp, &mid);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (out_existing_objects, FALSE);
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
- if (!conn)
- goto cleanup;
+ *out_existing_objects = NULL;
- if (!ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error))
- goto cleanup;
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
- if (!e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecbm_capture_req_props, cbdata,
cancellable, &mapi_error)) {
- if (!g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND)) {
- g_clear_error (&mapi_error);
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- goto cleanup;
- }
+ ecb_mapi_lock_connection (cbmapi);
- /* try to find by global-id, if not found by MID */
- g_clear_error (&mapi_error);
+ success = ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ success = e_mapi_connection_list_objects (cbmapi->priv->conn, &obj_folder, NULL, NULL,
+ ecb_mapi_list_existing_uids_cb, out_existing_objects, cancellable, &mapi_error);
+
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable, &mapi_error);
}
- if (e_mapi_connection_list_objects (conn, &obj_folder,
- ecbm_build_global_id_restriction, comp,
- ecbm_list_for_one_mid_cb, &mid,
- cancellable, &mapi_error)) {
- e_mapi_connection_transfer_object (conn, &obj_folder, mid, ecbm_capture_req_props, cbdata,
cancellable, &mapi_error);
+ if (mapi_error) {
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to list items from a
server"));
+ g_error_free (mapi_error);
+
+ success = FALSE;
}
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
+ ecb_mapi_unlock_connection (cbmapi);
- cleanup:
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- g_clear_error (&mapi_error);
-}
+ /* Components with GlobalId has UID the GlobalId, all other have MessageID,
+ but here the 'nfo->uid' is MessageID */
+ if (success) {
+ ECalCache *cal_cache;
-/* frees data members allocated in get_server_data(), not the cbdata itself */
-static void
-free_server_data (struct cal_cbdata *cbdata)
-{
- if (!cbdata)
- return;
+ cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
+ if (cal_cache) {
+ GHashTable *mid_to_gid;
- #define do_free(_func, _val) _func (_val); _val = NULL
+ mid_to_gid = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- do_free (e_mapi_util_free_sbinary_short, cbdata->cleanglobalid);
- do_free (e_mapi_util_free_sbinary_short, cbdata->globalid);
- do_free (g_free, cbdata->username);
- do_free (g_free, cbdata->useridtype);
- do_free (g_free, cbdata->userid);
- do_free (g_free, cbdata->ownername);
- do_free (g_free, cbdata->owneridtype);
- do_free (g_free, cbdata->ownerid);
+ if (e_cal_cache_search_with_callback (cal_cache, NULL,
ecb_mapi_populate_mid_to_gid_cb, mid_to_gid, cancellable, NULL) &&
+ g_hash_table_size (mid_to_gid) > 0) {
+ GSList *link;
- #undef do_free
-}
+ for (link = *out_existing_objects; link; link = g_slist_next (link)) {
+ ECalMetaBackendInfo *nfo = link->data;
-#define free_and_dupe_str(_des, _new) G_STMT_START { \
- g_free (_des); \
- _des = g_strdup (_new); \
- } G_STMT_END
+ if (nfo && nfo->uid) {
+ const gchar *gid = g_hash_table_lookup (mid_to_gid, nfo->uid);
-static void
-ecbm_create_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
gchar **uid, ECalComponent **new_ecalcomp, GError **error)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- EMapiConnection *conn;
- icalcomponent_kind kind;
- icalcomponent *icalcomp;
- ECalComponent *comp;
- mapi_id_t mid = 0;
- gchar *tmp = NULL;
- struct icaltimetype current;
- GError *mapi_error = NULL;
+ if (gid && *gid) {
+ g_free (nfo->uid);
+ nfo->uid = g_strdup (gid);
+ }
+ }
+ }
+ }
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+ g_hash_table_destroy (mid_to_gid);
+ g_object_unref (cal_cache);
+ }
+ }
- kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
+ return success;
+}
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
- e_mapi_return_data_cal_error_if_fail (new_ecalcomp != NULL, InvalidArg);
+static gboolean
+ecb_mapi_load_component_sync (ECalMetaBackend *meta_backend,
+ const gchar *uid,
+ const gchar *extra,
+ icalcomponent **out_component,
+ gchar **out_extra,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ECalBackendMAPI *cbmapi;
+ GSList *uids, *components = NULL;
+ gboolean success;
+ GError *local_error = NULL;
- if (!e_backend_get_online (E_BACKEND (backend))) {
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- return;
- }
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (out_component != NULL, FALSE);
- /* check the component for validity */
- icalcomp = icalparser_parse_string (calobj);
- if (!icalcomp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
+ *out_component = NULL;
- if (kind != icalcomponent_isa (icalcomp)) {
- icalcomponent_free (icalcomp);
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
- comp = e_cal_component_new ();
- e_cal_component_set_icalcomponent (comp, icalcomp);
+ uids = g_slist_prepend (NULL, (gpointer) uid);
- current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
- e_cal_component_set_created (comp, ¤t);
- e_cal_component_set_last_modified (comp, ¤t);
+ ecb_mapi_lock_connection (cbmapi);
- /* Check if object exists */
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
- if (conn) {
- struct cal_cbdata cbdata = { 0 };
- gboolean status;
+ success = ecb_mapi_load_multiple_sync (cbmapi, uids, &components, cancellable, &local_error);
+ if (!success) {
mapi_object_t obj_folder;
- gboolean has_attendees = e_cal_component_has_attendees (comp);
+ mapi_id_t mid = 0;
- cbdata.kind = kind;
- cbdata.username = g_strdup (ecbm_get_user_name (cbmapi));
- cbdata.useridtype = (gchar *) "SMTP";
- cbdata.userid = g_strdup (ecbm_get_user_email (cbmapi));
- cbdata.ownername = g_strdup (ecbm_get_owner_name (cbmapi));
- cbdata.owneridtype = (gchar *) "SMTP";
- cbdata.ownerid = g_strdup (ecbm_get_owner_email (cbmapi));
- cbdata.get_timezone = (icaltimezone * (*)(gpointer data, const gchar *tzid))
e_timezone_cache_get_timezone;
- cbdata.get_tz_data = cbmapi;
+ /* Not downloaded in the local cache yet, try to find it. */
+ if (ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, NULL)) {
+ if (e_mapi_connection_list_objects (cbmapi->priv->conn, &obj_folder,
+ ecb_mapi_build_global_id_or_mid_restriction_from_uid, (gpointer) uid,
+ ecb_mapi_list_for_one_mid_cb, &mid, cancellable, NULL) && mid) {
+ LoadMultipleData lmd;
- /* Create an appointment */
- cbdata.comp = comp;
- cbdata.is_modify = FALSE;
- cbdata.msgflags = MSGFLAG_READ;
- cbdata.meeting_type = has_attendees ? MEETING_OBJECT : NOT_A_MEETING;
- cbdata.resp = has_attendees ? olResponseOrganized : olResponseNone;
- cbdata.appt_id = e_mapi_cal_util_get_new_appt_id (conn, priv->fid);
- cbdata.appt_seq = 0;
- cbdata.globalid = NULL;
- cbdata.cleanglobalid = NULL;
-
- status = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
- if (status) {
- e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE,
- e_mapi_cal_utils_comp_to_object, &cbdata,
- &mid, cancellable, &mapi_error);
+ lmd.meta_backend = E_CAL_META_BACKEND (cbmapi);
+ lmd.kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbmapi));
+ lmd.out_components = &components;
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error);
- }
+ success = e_mapi_connection_transfer_object (cbmapi->priv->conn, &obj_folder,
mid,
+ transfer_calendar_objects_cb, &lmd, cancellable, NULL);
- g_free (cbdata.username);
- g_free (cbdata.userid);
- g_free (cbdata.ownername);
- g_free (cbdata.ownerid);
+ if (success)
+ g_clear_error (&local_error);
+ }
- if (!mid) {
- g_object_unref (comp);
- mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to create item on a
server"));
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- if (mapi_error)
- g_error_free (mapi_error);
- return;
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable, NULL);
}
-
- tmp = e_mapi_util_mapi_id_to_string (mid);
- e_cal_component_set_uid (comp, tmp);
- if (uid)
- *uid = tmp;
- else
- g_free (tmp);
-
- e_cal_component_commit_sequence (comp);
- put_component_to_store (cbmapi, comp);
- *new_ecalcomp = e_cal_component_clone (comp);
- e_cal_backend_notify_component_created (E_CAL_BACKEND (cbmapi), *new_ecalcomp);
- } else {
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- if (!mapi_error)
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- else
- mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
- g_clear_error (&mapi_error);
- g_object_unref (comp);
- return;
}
- run_delta_thread (cbmapi);
-
- g_object_unref (comp);
-}
-
-static gboolean
-modifier_is_organizer (ECalBackendMAPI *cbmapi, ECalComponent *comp)
-{
- ECalComponentOrganizer org;
- const gchar *ownerid, *orgid;
-
- if (!e_cal_component_has_organizer(comp))
- return TRUE;
-
- e_cal_component_get_organizer (comp, &org);
- if (!g_ascii_strncasecmp (org.value, "mailto:", 7))
- orgid = (org.value) + 7;
- else
- orgid = org.value;
- ownerid = ecbm_get_owner_email (cbmapi);
-
- return (!g_ascii_strcasecmp(orgid, ownerid) ? TRUE : FALSE);
-}
+ ecb_mapi_unlock_connection (cbmapi);
-static OlResponseStatus
-get_trackstatus_from_partstat (icalparameter_partstat partstat)
-{
- switch (partstat) {
- case ICAL_PARTSTAT_ACCEPTED : return olResponseAccepted;
- case ICAL_PARTSTAT_TENTATIVE : return olResponseTentative;
- case ICAL_PARTSTAT_DECLINED : return olResponseDeclined;
- default : return olResponseTentative;
+ if (success && components) {
+ *out_component = components->data;
+ g_slist_free (components);
+ } else {
+ g_slist_free_full (components, (GDestroyNotify) icalcomponent_free);
}
-}
-static OlResponseStatus
-find_my_response (ECalBackendMAPI *cbmapi, ECalComponent *comp)
-{
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (comp);
- icalproperty *attendee;
- gchar *att = NULL;
- OlResponseStatus val = olResponseTentative;
+ if (local_error)
+ g_propagate_error (error, local_error);
- att = g_strdup_printf ("MAILTO:%s", ecbm_get_owner_email (cbmapi));
- attendee = icalcomponent_get_first_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
- while (attendee) {
- const gchar *value = icalproperty_get_attendee (attendee);
- if (!g_ascii_strcasecmp (value, att)) {
- icalparameter *param = icalproperty_get_first_parameter (attendee,
ICAL_PARTSTAT_PARAMETER);
- val = get_trackstatus_from_partstat (icalparameter_get_partstat(param));
- break;
- }
- attendee = icalcomponent_get_next_property (icalcomp, ICAL_ATTENDEE_PROPERTY);
- }
- g_free (att);
+ g_slist_free (uids);
- return val;
+ return success;
}
-static void
-ecbm_modify_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
ECalObjModType mod, ECalComponent **old_ecalcomp, ECalComponent **new_ecalcomp, GError **error)
+static gboolean
+ecb_mapi_save_component_sync (ECalMetaBackend *meta_backend,
+ gboolean overwrite_existing,
+ EConflictResolution conflict_resolution,
+ const GSList *instances,
+ const gchar *extra,
+ gchar **out_new_uid,
+ gchar **out_new_extra,
+ GCancellable *cancellable,
+ GError **error)
{
ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- EMapiConnection *conn;
- icalcomponent_kind kind;
- icalcomponent *icalcomp;
- ECalComponent *comp, *cache_comp = NULL;
- gboolean status;
- mapi_id_t mid;
- const gchar *uid = NULL, *rid = NULL;
- struct cal_cbdata cbdata = { 0 };
- gboolean no_increment = FALSE;
- icalproperty *prop;
- struct icaltimetype current;
+ ECalComponent *comp;
+ icalcomponent *icomp;
+ gboolean no_increment;
+ mapi_object_t obj_folder;
+ mapi_id_t mid = 0;
+ gboolean success;
GError *mapi_error = NULL;
- *old_ecalcomp = *new_ecalcomp = NULL;
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
-
- kind = e_cal_backend_get_kind (backend);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (instances != NULL, FALSE);
+ g_return_val_if_fail (out_new_uid != NULL, FALSE);
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
+ *out_new_uid = NULL;
- if (!e_backend_get_online (E_BACKEND (backend))) {
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- return;
+ if (instances->next ||
+ e_cal_component_is_instance (instances->data)) {
+ g_propagate_error (error, EDC_ERROR_EX (OtherError,
+ _("Support for modifying single instances of a recurring appointment is not yet
implemented. No change was made to the appointment on the server.")));
+ return FALSE;
}
- /* check the component for validity */
- icalcomp = icalparser_parse_string (calobj);
- if (!icalcomp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
- if (mod != E_CAL_OBJ_MOD_ALL && e_cal_util_component_is_instance (icalcomp)) {
- icalcomponent_free (icalcomp);
- g_propagate_error (error, EDC_ERROR_EX (OtherError, _("Support for modifying single instances
of a recurring appointment is not yet implemented. No change was made to the appointment on the server.")));
- return;
- }
+ icomp = icalcomponent_new_clone (e_cal_component_get_icalcomponent (instances->data));
+ no_increment = e_cal_util_remove_x_property (icomp, "X-EVOLUTION-IS-REPLY");
- prop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
- while (prop) {
- const gchar *name = icalproperty_get_x_name (prop);
- if (!g_ascii_strcasecmp (name, "X-EVOLUTION-IS-REPLY")) {
- no_increment = TRUE;
- icalcomponent_remove_property (icalcomp, prop);
- }
- prop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
+ comp = e_cal_component_new_from_icalcomponent (icomp);
+ if (!comp) {
+ g_propagate_error (error, EDC_ERROR (InvalidObject));
+ return FALSE;
}
- comp = e_cal_component_new ();
- e_cal_component_set_icalcomponent (comp, icalcomp);
-
- current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
- e_cal_component_set_last_modified (comp, ¤t);
+ ecb_mapi_lock_connection (cbmapi);
- e_cal_component_get_uid (comp, &uid);
- /* rid = e_cal_component_get_recurid_as_string (comp); */
-
- cbdata.kind = kind;
- cbdata.get_timezone = (icaltimezone * (*)(gpointer data, const gchar *tzid))
e_timezone_cache_get_timezone;
- cbdata.get_tz_data = cbmapi;
-
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
-
- if (conn) {
+ success = ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ struct cal_cbdata cbdata = { 0 };
gboolean has_attendees = e_cal_component_has_attendees (comp);
- mapi_object_t obj_folder;
- /* when online, send the item to the server */
- /* check if the object exists */
- cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid);
- if (!cache_comp) {
- update_local_cache (cbmapi, cancellable);
- cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid);
- }
+ cbdata.kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
+ cbdata.comp = comp;
+ cbdata.is_modify = overwrite_existing;
+ cbdata.msgflags = MSGFLAG_READ;
+ cbdata.get_timezone = (icaltimezone * (*)(gpointer data, const gchar *tzid))
e_timezone_cache_get_timezone;
+ cbdata.get_tz_data = cbmapi;
- if (!cache_comp) {
- g_message ("CRITICAL : Could not find the object in cache");
- g_object_unref (comp);
- g_propagate_error (error, EDC_ERROR (ObjectNotFound));
- return;
- }
+ if (overwrite_existing) {
+ ecb_mapi_get_comp_mid (icomp, &mid);
+
+ ecb_mapi_get_server_data (cbmapi, comp, &cbdata, cancellable);
+ if (ecb_mapi_modifier_is_organizer (cbmapi, comp)) {
+ cbdata.meeting_type = has_attendees ? MEETING_OBJECT : NOT_A_MEETING;
+ cbdata.resp = has_attendees ? olResponseOrganized : olResponseNone;
+ if (!no_increment)
+ cbdata.appt_seq += 1;
+ free_and_dupe_str (cbdata.username, ecb_mapi_get_owner_name (cbmapi));
+ free_and_dupe_str (cbdata.useridtype, "SMTP");
+ free_and_dupe_str (cbdata.userid, ecb_mapi_get_owner_email (cbmapi));
+ free_and_dupe_str (cbdata.ownername, ecb_mapi_get_owner_name (cbmapi));
+ free_and_dupe_str (cbdata.owneridtype, "SMTP");
+ free_and_dupe_str (cbdata.ownerid, ecb_mapi_get_owner_email (cbmapi));
+ } else {
+ cbdata.resp = has_attendees ? ecb_mapi_find_my_response (cbmapi, comp) :
olResponseNone;
+ cbdata.meeting_type = has_attendees ? MEETING_OBJECT_RCVD : NOT_A_MEETING;
+ }
- get_comp_mid (e_cal_component_get_icalcomponent (cache_comp), &mid);
+ success = e_mapi_connection_modify_object (cbmapi->priv->conn, &obj_folder, mid,
+ e_mapi_cal_utils_comp_to_object, &cbdata, cancellable, &mapi_error);
- cbdata.comp = comp;
- cbdata.msgflags = MSGFLAG_READ;
- cbdata.is_modify = TRUE;
+ ecb_mapi_free_server_data (&cbdata);
+ } else {
+ cbdata.username = g_strdup (ecb_mapi_get_owner_name (cbmapi));
+ cbdata.useridtype = (gchar *) "SMTP";
+ cbdata.userid = g_strdup (ecb_mapi_get_owner_email (cbmapi));
+ cbdata.ownername = g_strdup (ecb_mapi_get_owner_name (cbmapi));
+ cbdata.owneridtype = (gchar *) "SMTP";
+ cbdata.ownerid = g_strdup (ecb_mapi_get_owner_email (cbmapi));
- get_server_data (cbmapi, comp, &cbdata, cancellable);
- if (modifier_is_organizer(cbmapi, comp)) {
cbdata.meeting_type = has_attendees ? MEETING_OBJECT : NOT_A_MEETING;
cbdata.resp = has_attendees ? olResponseOrganized : olResponseNone;
- if (!no_increment)
- cbdata.appt_seq += 1;
- free_and_dupe_str (cbdata.username, ecbm_get_user_name (cbmapi));
- free_and_dupe_str (cbdata.useridtype, "SMTP");
- free_and_dupe_str (cbdata.userid, ecbm_get_user_email (cbmapi));
- free_and_dupe_str (cbdata.ownername, ecbm_get_owner_name (cbmapi));
- free_and_dupe_str (cbdata.owneridtype, "SMTP");
- free_and_dupe_str (cbdata.ownerid, ecbm_get_owner_email (cbmapi));
- } else {
- cbdata.resp = has_attendees ? find_my_response(cbmapi, comp) : olResponseNone;
- cbdata.meeting_type = has_attendees ? MEETING_OBJECT_RCVD : NOT_A_MEETING;
- }
-
- status = ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &mapi_error);
- if (status) {
- status = e_mapi_connection_modify_object (conn, &obj_folder, mid,
- e_mapi_cal_utils_comp_to_object, &cbdata,
- cancellable, &mapi_error);
+ cbdata.appt_id = e_mapi_cal_util_get_new_appt_id (cbmapi->priv->conn,
mapi_object_get_id (&obj_folder));
+ cbdata.appt_seq = 0;
+ cbdata.globalid = NULL;
+ cbdata.cleanglobalid = NULL;
- status = e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error)
&& status;
+ success = e_mapi_connection_create_object (cbmapi->priv->conn, &obj_folder,
E_MAPI_CREATE_FLAG_NONE,
+ e_mapi_cal_utils_comp_to_object, &cbdata, &mid, cancellable, &mapi_error);
}
- free_server_data (&cbdata);
- if (!status) {
- g_object_unref (comp);
- g_object_unref (cache_comp);
+ g_free (cbdata.username);
+ g_free (cbdata.userid);
+ g_free (cbdata.ownername);
+ g_free (cbdata.ownerid);
- mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to modify item on a
server"));
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- if (mapi_error)
- g_error_free (mapi_error);
- return;
- }
- } else {
- g_object_unref (comp);
- g_object_unref (cache_comp);
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- if (!mapi_error)
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- else
- mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable, &mapi_error);
+ }
+
+ if (mapi_error || !mid) {
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError,
+ overwrite_existing ? _("Failed to modify item on a server") : _("Failed to create
item on a server"));
g_clear_error (&mapi_error);
- return;
+
+ success = FALSE;
}
- *old_ecalcomp = e_cal_component_clone (cache_comp);
- *new_ecalcomp = e_cal_component_clone (comp);
+ ecb_mapi_unlock_connection (cbmapi);
- put_component_to_store (cbmapi, comp);
- e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbmapi), *old_ecalcomp, *new_ecalcomp);
+ if (success)
+ *out_new_uid = e_mapi_util_mapi_id_to_string (mid);
g_object_unref (comp);
- g_object_unref (cache_comp);
+
+ return success;
}
-static void
-ecbm_remove_object (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable,
- const gchar *uid, const gchar *rid, ECalObjModType mod,
- ECalComponent **old_ecalcomp, ECalComponent **new_ecalcomp, GError **error)
+static gboolean
+ecb_mapi_remove_component_sync (ECalMetaBackend *meta_backend,
+ EConflictResolution conflict_resolution,
+ const gchar *uid,
+ const gchar *extra,
+ const gchar *object,
+ GCancellable *cancellable,
+ GError **error)
{
ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- EMapiConnection *conn;
- icalcomponent *icalcomp;
- gchar *calobj = NULL;
- mapi_id_t mid;
- GError *err = NULL, *mapi_error = NULL;
-
- *old_ecalcomp = *new_ecalcomp = NULL;
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
+ mapi_id_t mid = 0;
+ gboolean success = TRUE;
+ GError *mapi_error = NULL;
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_MAPI (meta_backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
- if (!e_backend_get_online (E_BACKEND (backend))) {
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- return;
- }
+ cbmapi = E_CAL_BACKEND_MAPI (meta_backend);
- /* when online, modify/delete the item from the server */
- /* check if the object exists */
- /* FIXME: we may have detached instances which need to be removed */
- ecbm_get_object (backend, cal, NULL, uid, NULL, &calobj, &err);
- if (err) {
- g_propagate_error (error, err);
- return;
- }
+ if (object) {
+ icalcomponent *icomp;
- /* check the component for validity */
- icalcomp = icalparser_parse_string (calobj);
- if (!icalcomp) {
- g_free (calobj);
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
+ icomp = icalcomponent_new_from_string (object);
+ if (icomp) {
+ ecb_mapi_get_comp_mid (icomp, &mid);
+ icalcomponent_free (icomp);
+ }
}
- get_comp_mid (icalcomp, &mid);
-
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
-
- if (mod == E_CAL_OBJ_MOD_THIS && rid && *rid) {
- gchar *new_calobj = NULL;
- struct icaltimetype time_rid;
-
- /*remove a single instance of a recurring event and modify */
- time_rid = icaltime_from_string (rid);
- e_cal_util_remove_instances (icalcomp, time_rid, mod);
- new_calobj = icalcomponent_as_ical_string_r (icalcomp);
- ecbm_modify_object (backend, cal, cancellable, new_calobj, E_CAL_OBJ_MOD_ALL, old_ecalcomp,
new_ecalcomp, &err);
- g_free (new_calobj);
- } else if (conn) {
+ if (mid || e_mapi_util_mapi_id_from_string (uid, &mid)) {
mapi_object_t obj_folder;
- GSList *list=NULL, *l, *comp_list = e_cal_backend_store_get_components_by_uid (priv->store,
uid);
- GError *ri_error = NULL;
- mapi_id_t *pmid = g_new (mapi_id_t, 1);
- *pmid = mid;
- list = g_slist_prepend (list, pmid);
+ ecb_mapi_lock_connection (cbmapi);
- if (ecbm_open_folder (cbmapi, conn, &obj_folder, cancellable, &ri_error)) {
- if (e_mapi_connection_remove_items (conn, &obj_folder, list, cancellable, &ri_error))
{
- for (l = comp_list; l; l = l->next) {
- ECalComponent *comp = E_CAL_COMPONENT (l->data);
- ECalComponentId *id = e_cal_component_get_id (comp);
+ success = ecb_mapi_open_folder (cbmapi, &obj_folder, cancellable, &mapi_error);
+ if (success) {
+ GSList *mids;
- e_cal_backend_store_remove_component (priv->store, id->uid, id->rid);
- e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbmapi), id,
comp, NULL);
- e_cal_component_free_id (id);
+ mids = g_slist_prepend (NULL, &mid);
- g_object_unref (comp);
- }
- }
+ success = e_mapi_connection_remove_items (cbmapi->priv->conn, &obj_folder, mids,
cancellable, &mapi_error);
- e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &ri_error);
+ e_mapi_connection_close_folder (cbmapi->priv->conn, &obj_folder, cancellable,
&mapi_error);
- *old_ecalcomp = e_cal_component_new_from_icalcomponent (icalparser_parse_string
(calobj));
- *new_ecalcomp = NULL;
- err = NULL; /* Success */
- } else {
- e_cal_backend_mapi_maybe_disconnect (cbmapi, ri_error);
- mapi_error_to_edc_error (&err, ri_error, OtherError, _("Cannot remove items from a
server"));
+ g_slist_free (mids);
}
- g_slist_free_full (list, g_free);
- g_slist_free (comp_list);
- } else {
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
- if (!mapi_error)
- g_propagate_error (&err, EDC_ERROR (RepositoryOffline));
- else
- mapi_error_to_edc_error (&err, mapi_error, RepositoryOffline, NULL);
- g_clear_error (&mapi_error);
+ ecb_mapi_unlock_connection (cbmapi);
}
- g_free (calobj);
+ if (mapi_error || !mid) {
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to remove item from a
server"));
+ g_clear_error (&mapi_error);
+
+ success = FALSE;
+ }
- if (err)
- g_propagate_error (error, err);
+ return success;
}
-static void
-ecbm_discard_alarm (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *uid, const
gchar *rid, const gchar *auid, GError **perror)
+static gchar *
+ecb_mapi_get_backend_property (ECalBackend *backend,
+ const gchar *prop_name)
{
- g_propagate_error (perror, EDC_ERROR (NotSupported));
+ ECalBackendMAPI *cbmapi;
+
+ g_return_val_if_fail (prop_name != NULL, NULL);
+
+ cbmapi = E_CAL_BACKEND_MAPI (backend);
+
+ if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+ return g_strjoin (
+ ",",
+ CAL_STATIC_CAPABILITY_NO_ALARM_REPEAT,
+ CAL_STATIC_CAPABILITY_NO_AUDIO_ALARMS,
+ CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
+ CAL_STATIC_CAPABILITY_NO_PROCEDURE_ALARMS,
+ CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY,
+ CAL_STATIC_CAPABILITY_REMOVE_ALARMS,
+ CAL_STATIC_CAPABILITY_NO_THISANDFUTURE,
+ CAL_STATIC_CAPABILITY_NO_THISANDPRIOR,
+ CAL_STATIC_CAPABILITY_CREATE_MESSAGES,
+ CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK,
+ CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR,
+ CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING,
+ CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED,
+ CAL_STATIC_CAPABILITY_NO_MEMO_START_DATE,
+ CAL_STATIC_CAPABILITY_TASK_DATE_ONLY,
+ e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (backend)),
+ NULL);
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
+ return g_strdup (ecb_mapi_get_owner_email (cbmapi));
+ } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
+ /* We don't support email alarms. This should not have been called. */
+ return NULL;
+ }
+
+ /* Chain up to parent's method */
+ return E_CAL_BACKEND_CLASS (e_cal_backend_mapi_parent_class)->get_backend_property (backend,
prop_name);
}
static void
-ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
GSList **users, gchar **modified_calobj, GError **error)
+ecb_mapi_send_objects_sync (ECalBackendSync *sync_backend,
+ EDataCal *cal,
+ GCancellable *cancellable,
+ const gchar *calobj,
+ GSList **users,
+ gchar **modified_calobj,
+ GError **error)
{
ECalBackendMAPI *cbmapi;
EMapiConnection *conn;
@@ -2077,26 +1462,32 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
icalcomponent *icalcomp;
GError *mapi_error = NULL;
- cbmapi = E_CAL_BACKEND_MAPI (backend);
+ e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (sync_backend), InvalidArg);
+ e_mapi_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
- kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
+ cbmapi = E_CAL_BACKEND_MAPI (sync_backend);
+ kind = e_cal_backend_get_kind (E_CAL_BACKEND (sync_backend));
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
+ ecb_mapi_lock_connection (cbmapi);
+
+ if (!e_cal_meta_backend_ensure_connected_sync (E_CAL_META_BACKEND (cbmapi), cancellable, &mapi_error)
||
+ !cbmapi->priv->conn) {
+ ecb_mapi_unlock_connection (cbmapi);
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
- if (!conn) {
if (!mapi_error)
g_propagate_error (error, EDC_ERROR (RepositoryOffline));
else
- mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
+ ecb_mapi_error_to_edc_error (error, mapi_error, RepositoryOffline, NULL);
g_clear_error (&mapi_error);
return;
}
+ conn = cbmapi->priv->conn;
+
/* check the component for validity */
icalcomp = icalparser_parse_string (calobj);
if (!icalcomp) {
+ ecb_mapi_unlock_connection (cbmapi);
g_propagate_error (error, EDC_ERROR (InvalidObject));
return;
}
@@ -2106,8 +1497,11 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
icalproperty_method method = icalcomponent_get_method (icalcomp);
- icalcomponent *subcomp = icalcomponent_get_first_component (icalcomp, kind);
- while (subcomp) {
+ icalcomponent *subcomp;
+
+ for (subcomp = icalcomponent_get_first_component (icalcomp, kind);
+ subcomp;
+ subcomp = icalcomponent_get_next_component (icalcomp, kind)) {
ECalComponent *comp = e_cal_component_new ();
struct cal_cbdata cbdata = { 0 };
mapi_id_t mid = 0;
@@ -2127,32 +1521,32 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
cbdata.msgflags = MSGFLAG_READ | MSGFLAG_SUBMIT | MSGFLAG_UNSENT;
switch (method) {
- case ICAL_METHOD_REQUEST :
+ case ICAL_METHOD_REQUEST:
cbdata.meeting_type = MEETING_REQUEST;
cbdata.resp = olResponseNotResponded;
break;
- case ICAL_METHOD_CANCEL :
+ case ICAL_METHOD_CANCEL:
cbdata.meeting_type = MEETING_CANCEL;
cbdata.resp = olResponseNotResponded;
break;
case ICAL_METHOD_REPLY:
- case ICAL_METHOD_RESPONSE :
+ case ICAL_METHOD_RESPONSE:
cbdata.meeting_type = MEETING_RESPONSE;
- cbdata.resp = find_my_response (cbmapi, comp);
+ cbdata.resp = ecb_mapi_find_my_response (cbmapi, comp);
break;
- default :
+ default:
cbdata.meeting_type = NOT_A_MEETING;
cbdata.resp = olResponseNone;
break;
}
- get_server_data (cbmapi, comp, &cbdata, cancellable);
- free_and_dupe_str (cbdata.username, ecbm_get_user_name (cbmapi));
+ ecb_mapi_get_server_data (cbmapi, comp, &cbdata, cancellable);
+ free_and_dupe_str (cbdata.username, ecb_mapi_get_owner_name (cbmapi));
free_and_dupe_str (cbdata.useridtype, "SMTP");
- free_and_dupe_str (cbdata.userid, ecbm_get_user_email (cbmapi));
- free_and_dupe_str (cbdata.ownername, ecbm_get_owner_name (cbmapi));
+ free_and_dupe_str (cbdata.userid, ecb_mapi_get_owner_email (cbmapi));
+ free_and_dupe_str (cbdata.ownername, ecb_mapi_get_owner_name (cbmapi));
free_and_dupe_str (cbdata.owneridtype, "SMTP");
- free_and_dupe_str (cbdata.ownerid, ecbm_get_owner_email (cbmapi));
+ free_and_dupe_str (cbdata.ownerid, ecb_mapi_get_owner_email (cbmapi));
cbdata.get_timezone = (icaltimezone * (*)(gpointer data, const gchar *tzid))
e_timezone_cache_get_timezone;
cbdata.get_tz_data = cbmapi;
@@ -2221,1174 +1615,42 @@ ecbm_send_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellabl
cbdata.globalid = NULL;
cbdata.cleanglobalid = NULL;
- free_server_data (&cbdata);
+ ecb_mapi_free_server_data (&cbdata);
g_free (globalid.lpb);
g_free (cleanglobalid.lpb);
if (!mid) {
+ ecb_mapi_unlock_connection (cbmapi);
g_object_unref (comp);
- mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to create
item on a server"));
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
+ ecb_mapi_error_to_edc_error (error, mapi_error, OtherError, _("Failed to
create item on a server"));
+ ecb_mapi_maybe_disconnect (cbmapi, mapi_error);
if (mapi_error)
g_error_free (mapi_error);
return;
}
g_object_unref (comp);
-
- subcomp = icalcomponent_get_next_component (icalcomp,
- e_cal_backend_get_kind (E_CAL_BACKEND
(backend)));
}
}
+ ecb_mapi_unlock_connection (cbmapi);
+
*modified_calobj = g_strdup (calobj);
icalcomponent_free (icalcomp);
}
-static void
-ecbm_receive_objects (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *calobj,
GError **error)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- icalcomponent_kind kind;
- icalcomponent *icalcomp;
- GError *err = NULL;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
-
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (calobj != NULL, InvalidArg);
-
- if (!e_backend_get_online (E_BACKEND (backend))) {
- g_propagate_error (error, EDC_ERROR (RepositoryOffline));
- return;
- }
-
- /* check the component for validity */
- icalcomp = icalparser_parse_string (calobj);
- if (!icalcomp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- if (icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT) {
- gboolean stop = FALSE;
- icalproperty_method method = icalcomponent_get_method (icalcomp);
- icalcomponent *subcomp = icalcomponent_get_first_component (icalcomp, kind);
- while (subcomp && !stop) {
- ECalComponent *comp = e_cal_component_new ();
- ECalObjModType mod;
- gchar *rid = NULL;
- const gchar *uid;
- gchar *comp_str;
- ECalComponent *old_ecalcomp = NULL, *new_ecalcomp = NULL;
-
- e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
- mod = e_cal_component_is_instance (comp) ? E_CAL_OBJ_MOD_THIS : E_CAL_OBJ_MOD_ALL;
-
- e_cal_component_get_uid (comp, &uid);
- rid = e_cal_component_get_recurid_as_string (comp);
-
- switch (method) {
- case ICAL_METHOD_REQUEST :
- comp_str = NULL;
- ecbm_get_object (backend, cal, NULL, uid, NULL, &comp_str, &err);
- if (err) {
- g_clear_error (&err);
- comp_str = e_cal_component_get_as_string (comp);
- ecbm_create_object (backend, cal, cancellable, comp_str, NULL,
&new_ecalcomp, &err);
- } else {
- g_free (comp_str);
- comp_str = e_cal_component_get_as_string (comp);
- ecbm_modify_object (backend, cal, cancellable, comp_str, mod,
&old_ecalcomp, &new_ecalcomp, &err);
- }
- g_free (comp_str);
-
- if (err)
- stop = TRUE;
- break;
- case ICAL_METHOD_CANCEL :
- ecbm_remove_object (backend, cal, cancellable, uid, rid, E_CAL_OBJ_MOD_THIS,
&old_ecalcomp, &new_ecalcomp, &err);
- if (err)
- stop = TRUE;
- break;
- case ICAL_METHOD_REPLY : {
- ECalComponent *cache_comp;
-
- g_mutex_lock (&priv->mutex);
- cache_comp = e_cal_backend_store_get_component (priv->store, uid, NULL);
- g_mutex_unlock (&priv->mutex);
- if (cache_comp) {
- gboolean any_changed = FALSE;
- GSList *reply_attendees = NULL, *ri, *cache_attendees = NULL, *ci;
-
- e_cal_component_get_attendee_list (comp, &reply_attendees);
- e_cal_component_get_attendee_list (cache_comp, &cache_attendees);
-
- for (ri = reply_attendees; ri; ri = ri->next) {
- ECalComponentAttendee *ra = ri->data;
-
- if (!ra || !ra->value || !*ra->value)
- continue;
-
- for (ci = cache_attendees; ci; ci = ci->next) {
- ECalComponentAttendee *ca = ci->data;
-
- if (!ca || !ca->value || !*ca->value ||
g_ascii_strcasecmp (ra->value, ca->value) != 0)
- continue;
-
- if (ca->status == ra->status)
- continue;
-
- ca->status = ra->status;
- any_changed = TRUE;
- }
- }
-
- if (any_changed) {
- old_ecalcomp = NULL;
- new_ecalcomp = NULL;
-
- e_cal_component_set_attendee_list (cache_comp,
cache_attendees);
-
- comp_str = e_cal_component_get_as_string (cache_comp);
- ecbm_modify_object (backend, cal, cancellable, comp_str, mod,
&old_ecalcomp, &new_ecalcomp, &err);
-
- g_free (comp_str);
- }
-
- e_cal_component_free_attendee_list (reply_attendees);
- e_cal_component_free_attendee_list (cache_attendees);
-
- if (err)
- stop = TRUE;
-
- g_object_unref (cache_comp);
- }
- } break;
- default :
- break;
- }
-
- g_free (rid);
- g_object_unref (comp);
-
- if (old_ecalcomp)
- g_object_unref (old_ecalcomp);
- if (new_ecalcomp)
- g_object_unref (new_ecalcomp);
-
- subcomp = icalcomponent_get_next_component (icalcomp,
- e_cal_backend_get_kind (E_CAL_BACKEND
(backend)));
- }
- }
-
- if (err)
- g_propagate_error (error, err);
-}
-
-static void
-ecbm_get_timezone (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzid, gchar
**object, GError **error)
-{
- ETimezoneCache *timezone_cache;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- icaltimezone *zone = NULL;
-
- cbmapi = (ECalBackendMAPI *) backend;
- timezone_cache = E_TIMEZONE_CACHE (backend);
-
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (tzid != NULL, InvalidArg);
-
- priv = cbmapi->priv;
- e_mapi_return_data_cal_error_if_fail (priv != NULL, InvalidArg);
-
- zone = e_timezone_cache_get_timezone (timezone_cache, tzid);
-
- if (!zone) {
- g_propagate_error (error, e_data_cal_create_error (ObjectNotFound, NULL));
- } else {
- icalcomponent *icalcomp;
-
- icalcomp = icaltimezone_get_component (zone);
-
- if (!icalcomp) {
- g_propagate_error (error, e_data_cal_create_error (InvalidObject, NULL));
- } else {
- *object = icalcomponent_as_ical_string_r (icalcomp);
- }
- }
-}
-
-static void
-ecbm_add_timezone (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj,
GError **error)
-{
- ECalBackendMAPI *cbmapi;
- ETimezoneCache *timezone_cache;
- icalcomponent *tz_comp;
-
- cbmapi = (ECalBackendMAPI *) backend;
- timezone_cache = E_TIMEZONE_CACHE (backend);
-
- e_mapi_return_data_cal_error_if_fail (E_IS_CAL_BACKEND_MAPI (cbmapi), InvalidArg);
- e_mapi_return_data_cal_error_if_fail (tzobj != NULL, InvalidArg);
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
-
- if (icalcomponent_isa (tz_comp) == ICAL_VTIMEZONE_COMPONENT) {
- icaltimezone *zone;
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
- e_timezone_cache_add_timezone (timezone_cache, zone);
- icaltimezone_free (zone, 1);
- }
-}
-
-static void
-ecbm_get_free_busy (ECalBackend *backend, EDataCal *cal, GCancellable *cancellable, const GSList *users,
time_t start, time_t end, GSList **freebusy, GError **perror)
-{
- ECalBackendMAPI *cbmapi;
- EMapiConnection *conn;
- GError *mapi_error = NULL;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
-
- conn = e_cal_backend_mapi_get_connection (cbmapi, cancellable, &mapi_error);
-
- if (!conn) {
- if (!mapi_error)
- g_propagate_error (perror, EDC_ERROR (RepositoryOffline));
- else
- mapi_error_to_edc_error (perror, mapi_error, RepositoryOffline, NULL);
- g_clear_error (&mapi_error);
- return;
- }
-
- if (!e_mapi_cal_utils_get_free_busy_data (conn, users, start, end, freebusy, cancellable,
&mapi_error)) {
- mapi_error_to_edc_error (perror, mapi_error, OtherError, _("Failed to get Free/Busy data"));
- e_cal_backend_mapi_maybe_disconnect (cbmapi, mapi_error);
-
- if (mapi_error)
- g_error_free (mapi_error);
- }
-}
-
-/***** BACKEND CLASS FUNCTIONS *****/
-
-static void
-ecbm_start_view (ECalBackend *backend, EDataCalView *view)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- GSList *components, *l;
- ECalBackendSExp *cbsexp;
- const gchar *sexp;
- gboolean search_needed = TRUE;
- time_t occur_start = -1, occur_end = -1;
- gboolean prunning_by_time;
- GError *err = NULL;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
-
- g_mutex_lock (&priv->mutex);
-
- cbsexp = e_data_cal_view_get_sexp (view);
-
- if (!cbsexp) {
- g_mutex_unlock (&priv->mutex);
-
- err = EDC_ERROR (InvalidQuery);
- e_data_cal_view_notify_complete (view, err);
- g_error_free (err);
-
- return;
- }
-
- sexp = e_cal_backend_sexp_text (cbsexp);
- if (!sexp || g_str_equal (sexp, "#t"))
- search_needed = FALSE;
-
- prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (cbsexp, &occur_start, &occur_end);
-
- components = prunning_by_time ?
- e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
- : e_cal_backend_store_get_components (priv->store);
-
- for (l = components; l != NULL; l = l->next) {
- ECalComponent *comp = E_CAL_COMPONENT (l->data);
- if (e_cal_backend_get_kind (E_CAL_BACKEND (backend)) ==
- icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
- if ((!search_needed) ||
- (e_cal_backend_sexp_match_comp (cbsexp, comp, E_TIMEZONE_CACHE
(backend)))) {
- e_data_cal_view_notify_components_added_1 (view, comp);
- }
- }
- }
-
- g_slist_free_full (components, g_object_unref);
- g_mutex_unlock (&priv->mutex);
-
- g_mutex_lock (&priv->is_updating_mutex);
- if (!priv->is_updating)
- e_data_cal_view_notify_complete (view, NULL /* Success */);
- g_mutex_unlock (&priv->is_updating_mutex);
-}
-
-static void
-ecbm_notify_online_cb (ECalBackend *backend, GParamSpec *pspec)
-{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
- gboolean online;
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
-
- online = e_backend_get_online (E_BACKEND (backend));
-
- g_mutex_lock (&priv->mutex);
-
- if (online) {
- priv->read_only = FALSE;
- } else {
- priv->read_only = TRUE;
-
- e_mapi_utils_unref_in_thread (G_OBJECT (priv->conn));
- priv->conn = NULL;
- }
-
- e_cal_backend_set_writable (backend, !priv->read_only);
- g_mutex_unlock (&priv->mutex);
-}
-
-/* Async OP functions, data structures and so on */
-
-typedef enum {
- OP_OPEN,
- OP_REFRESH,
- OP_CREATE_OBJECTS,
- OP_MODIFY_OBJECTS,
- OP_REMOVE_OBJECTS,
- OP_DISCARD_ALARM,
- OP_RECEIVE_OBJECTS,
- OP_SEND_OBJECTS,
- OP_GET_OBJECT,
- OP_GET_ATTACHMENT_URIS,
- OP_GET_OBJECT_LIST,
- OP_GET_TIMEZONE,
- OP_ADD_TIMEZONE,
- OP_GET_FREE_BUSY,
- OP_START_VIEW
-} OperationType;
-
-typedef struct {
- OperationType ot;
-
- EDataCal *cal;
- guint32 opid;
- GCancellable *cancellable;
-} OperationBase;
-
-typedef struct {
- OperationBase base;
-
- gboolean only_if_exists;
-} OperationOpen;
-
-typedef struct {
- OperationBase base;
-
- GSList *calobjs;
-} OperationCreate;
-
-typedef struct {
- OperationBase base;
-
- GSList *calobjs;
- ECalObjModType mod;
-} OperationModify;
-
-typedef struct {
- OperationBase base;
-
- GSList *ids;
- ECalObjModType mod;
-} OperationRemove;
-
-typedef struct {
- OperationBase base;
-
- gchar *str;
-} OperationStr;
-
-typedef struct {
- OperationBase base;
-
- gchar *str1;
- gchar *str2;
-} OperationStr2;
-
-typedef struct {
- OperationBase base;
-
- gchar *uid;
- gchar *rid;
- gchar *auid;
-} OperationDiscardAlarm;
-
-typedef struct {
- OperationBase base;
-
- GSList *users;
- time_t start;
- time_t end;
-} OperationGetFreeBusy;
-
-typedef struct {
- OperationBase base;
-
- EDataCalView *view;
-} OperationStartView;
-
-static void
-ecbm_operation_cb (OperationBase *op, gboolean cancelled, ECalBackend *backend)
-{
- GError *error = NULL;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND (backend));
- g_return_if_fail (op != NULL);
-
- cancelled = cancelled || (op->cancellable && g_cancellable_is_cancelled (op->cancellable));
-
- switch (op->ot) {
- case OP_OPEN: {
- OperationOpen *opo = (OperationOpen *) op;
-
- if (!cancelled) {
- ecbm_open (backend, op->cal, op->cancellable, opo->only_if_exists, &error);
-
- e_data_cal_respond_open (op->cal, op->opid, error);
- }
- } break;
- case OP_REFRESH: {
- if (!cancelled) {
- ecbm_refresh (backend, op->cal, op->cancellable, &error);
-
- e_data_cal_respond_refresh (op->cal, op->opid, error);
- }
- } break;
- case OP_CREATE_OBJECTS: {
- OperationCreate *opc = (OperationCreate *) op;
-
- if (!cancelled) {
- GSList *iter;
- GSList *uids = NULL;
- GSList *new_components = NULL;
-
- for (iter = opc->calobjs; iter && !g_cancellable_is_cancelled (op->cancellable) &&
!error; iter = iter->next) {
- const gchar *calobj = iter->data;
- gchar *uid = NULL;
- ECalComponent *new_ecalcomp = NULL;
-
- ecbm_create_object (backend, op->cal, op->cancellable, calobj, &uid,
&new_ecalcomp, &error);
-
- if (!error) {
- uids = g_slist_prepend (uids, uid);
- new_components = g_slist_prepend (new_components, new_ecalcomp);
- }
- }
-
- uids = g_slist_reverse (uids);
- new_components = g_slist_reverse (new_components);
-
- e_data_cal_respond_create_objects (op->cal, op->opid, error, uids, new_components);
-
- /* free memory */
- g_slist_free_full (uids, g_free);
- e_util_free_nullable_object_slist (new_components);
- }
-
- g_slist_free_full (opc->calobjs, g_free);
- } break;
- case OP_MODIFY_OBJECTS: {
- OperationModify *opm = (OperationModify *) op;
-
- if (!cancelled) {
- GSList *iter;
- GSList *new_components = NULL;
- GSList *old_components = NULL;
-
- for (iter = opm->calobjs; iter && !g_cancellable_is_cancelled (op->cancellable) &&
!error; iter = iter->next) {
- const gchar *calobj = iter->data;
- ECalComponent *old_ecalcomp = NULL, *new_ecalcomp = NULL;
-
- ecbm_modify_object (backend, op->cal, op->cancellable, calobj, opm->mod,
&old_ecalcomp, &new_ecalcomp, &error);
-
- if (!error) {
- if (!new_ecalcomp)
- new_ecalcomp = e_cal_component_new_from_icalcomponent
(icalparser_parse_string (calobj));
-
- old_components = g_slist_prepend (old_components, old_ecalcomp);
- new_components = g_slist_prepend (new_components, new_ecalcomp);
- }
- }
-
- old_components = g_slist_reverse (old_components);
- new_components = g_slist_reverse (new_components);
-
- e_data_cal_respond_modify_objects (op->cal, op->opid, error, old_components,
new_components);
-
- e_util_free_nullable_object_slist (old_components);
- e_util_free_nullable_object_slist (new_components);
- }
-
- g_slist_free_full (opm->calobjs, g_free);
- } break;
- case OP_REMOVE_OBJECTS: {
- OperationRemove *opr = (OperationRemove *) op;
-
- if (!cancelled) {
- GSList *iter;
- GSList *ids = NULL;
- GSList *new_components = NULL;
- GSList *old_components = NULL;
-
- for (iter = opr->ids; iter && !g_cancellable_is_cancelled (op->cancellable) &&
!error; iter = iter->next) {
- const ECalComponentId *ecid = iter->data;
- ECalComponent *old_ecalcomp = NULL, *new_ecalcomp = NULL;
-
- if (!ecid)
- continue;
-
- ecbm_remove_object (backend, op->cal, op->cancellable, ecid->uid, ecid->rid,
opr->mod, &old_ecalcomp, &new_ecalcomp, &error);
-
- if (!error) {
- ECalComponentId *id = g_new0 (ECalComponentId, 1);
- id->uid = g_strdup (ecid->uid);
-
- if (opr->mod == E_CAL_OBJ_MOD_THIS)
- id->rid = g_strdup (ecid->rid);
-
- ids = g_slist_prepend (ids, id);
- }
- }
-
- ids = g_slist_reverse (ids);
- old_components = g_slist_reverse (old_components);
- new_components = g_slist_reverse (new_components);
-
- e_data_cal_respond_remove_objects (op->cal, op->opid, error, ids, old_components,
new_components);
-
- g_slist_free_full (ids, (GDestroyNotify) e_cal_component_free_id);
- e_util_free_nullable_object_slist (old_components);
- e_util_free_nullable_object_slist (new_components);
- }
-
- g_slist_free_full (opr->ids, (GDestroyNotify) e_cal_component_free_id);
- } break;
- case OP_DISCARD_ALARM: {
- OperationDiscardAlarm *opda = (OperationDiscardAlarm *) op;
-
- if (!cancelled) {
- ecbm_discard_alarm (backend, op->cal, op->cancellable, opda->uid, opda->rid,
opda->auid, &error);
-
- e_data_cal_respond_discard_alarm (op->cal, op->opid, error);
- }
-
- g_free (opda->uid);
- g_free (opda->rid);
- g_free (opda->auid);
- } break;
- case OP_RECEIVE_OBJECTS: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *calobj = ops->str;
-
- if (!cancelled) {
- ecbm_receive_objects (backend, op->cal, op->cancellable, calobj, &error);
-
- e_data_cal_respond_receive_objects (op->cal, op->opid, error);
- }
-
- g_free (ops->str);
- } break;
- case OP_SEND_OBJECTS: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *calobj = ops->str;
-
- if (!cancelled) {
- GSList *users = NULL;
- gchar *modified_calobj = NULL;
-
- ecbm_send_objects (backend, op->cal, op->cancellable, calobj, &users,
&modified_calobj, &error);
-
- e_data_cal_respond_send_objects (op->cal, op->opid, error, users, modified_calobj);
-
- g_slist_foreach (users, (GFunc) g_free, NULL);
- g_slist_free (users);
- g_free (modified_calobj);
- }
-
- g_free (ops->str);
- } break;
- case OP_GET_OBJECT: {
- OperationStr2 *ops2 = (OperationStr2 *) op;
- const gchar *uid = ops2->str1, *rid = ops2->str2;
-
- if (!cancelled) {
- gchar *object = NULL;
-
- ecbm_get_object (backend, op->cal, op->cancellable, uid, rid, &object, &error);
-
- e_data_cal_respond_get_object (op->cal, op->opid, error, object);
-
- g_free (object);
- }
-
- g_free (ops2->str1);
- g_free (ops2->str2);
- } break;
- case OP_GET_ATTACHMENT_URIS: {
- OperationStr2 *ops2 = (OperationStr2 *) op;
- const gchar *uid = ops2->str1, *rid = ops2->str2;
-
- if (!cancelled) {
- GSList *list = NULL;
-
- ecbm_get_attachment_uris (backend, op->cal, op->cancellable, uid, rid, &list, &error);
-
- e_data_cal_respond_get_attachment_uris (op->cal, op->opid, error, list);
-
- g_slist_foreach (list, (GFunc) g_free, NULL);
- g_free (list);
- }
-
- g_free (ops2->str1);
- g_free (ops2->str2);
- } break;
- case OP_GET_OBJECT_LIST: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *sexp = ops->str;
-
- if (!cancelled) {
- GSList *objects = NULL;
-
- ecbm_get_object_list (backend, op->cal, op->cancellable, sexp, &objects, &error);
-
- e_data_cal_respond_get_object_list (op->cal, op->opid, error, objects);
-
- g_slist_foreach (objects, (GFunc) g_free, NULL);
- g_slist_free (objects);
- }
-
- g_free (ops->str);
- } break;
- case OP_GET_TIMEZONE: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *tzid = ops->str;
-
- if (!cancelled) {
- gchar *object = NULL;
-
- ecbm_get_timezone (backend, op->cal, op->cancellable, tzid, &object, &error);
-
- if (!object && tzid) {
- /* fallback if tzid contains only the location of timezone */
- gint i, slashes = 0;
-
- for (i = 0; tzid [i]; i++) {
- if (tzid [i] == '/')
- slashes++;
- }
-
- if (slashes == 1) {
- icalcomponent *icalcomp = NULL, *free_comp = NULL;
-
- icaltimezone *zone = icaltimezone_get_builtin_timezone (tzid);
- if (!zone) {
- /* Try fetching the timezone from zone directory. There are
some timezones like MST, US/Pacific etc. which do not appear in
- zone.tab, so they will not be available in the libical
builtin timezone */
- icalcomp = free_comp = icaltzutil_fetch_timezone (tzid);
- }
-
- if (zone)
- icalcomp = icaltimezone_get_component (zone);
-
- if (icalcomp) {
- icalcomponent *clone = icalcomponent_new_clone (icalcomp);
- icalproperty *prop;
-
- prop = icalcomponent_get_first_property (clone,
ICAL_TZID_PROPERTY);
- if (prop) {
- /* change tzid to our, because the component has the
buildin tzid */
- icalproperty_set_tzid (prop, tzid);
-
- object = icalcomponent_as_ical_string_r (clone);
- g_clear_error (&error);
- }
- icalcomponent_free (clone);
- }
-
- if (free_comp)
- icalcomponent_free (free_comp);
- }
-
- /* also cache this timezone to backend */
- if (object)
- ecbm_add_timezone (backend, op->cal, op->cancellable, object, NULL);
- }
-
- e_data_cal_respond_get_timezone (op->cal, op->opid, error, object);
-
- g_free (object);
- }
-
- g_free (ops->str);
- } break;
- case OP_ADD_TIMEZONE: {
- OperationStr *ops = (OperationStr *) op;
- const gchar *tzobj = ops->str;
-
- if (!cancelled) {
- ecbm_add_timezone (backend, op->cal, op->cancellable, tzobj, &error);
-
- e_data_cal_respond_add_timezone (op->cal, op->opid, error);
- }
-
- g_free (ops->str);
- } break;
- case OP_GET_FREE_BUSY: {
- OperationGetFreeBusy *opgfb = (OperationGetFreeBusy *) op;
-
- if (!cancelled) {
- GSList *freebusy = NULL;
-
- ecbm_get_free_busy (backend, op->cal, op->cancellable, opgfb->users, opgfb->start,
opgfb->end, &freebusy, &error);
-
- if (freebusy)
- e_data_cal_report_free_busy_data (op->cal, freebusy);
- e_data_cal_respond_get_free_busy (op->cal, op->opid, error, freebusy);
-
- g_slist_foreach (freebusy, (GFunc) g_free, NULL);
- g_slist_free (freebusy);
- }
-
- g_slist_foreach (opgfb->users, (GFunc) g_free, NULL);
- g_slist_free (opgfb->users);
- } break;
- case OP_START_VIEW: {
- OperationStartView *opsv = (OperationStartView *) op;
-
- if (!cancelled) {
- ecbm_start_view (backend, opsv->view);
- /* do not notify here, is should start its own thread */
- }
-
- g_object_unref (opsv->view);
- } break;
- }
-
- if (op->cancellable)
- g_object_unref (op->cancellable);
- if (op->cal)
- g_object_unref (op->cal);
- g_free (op);
-
- /* for cases when this is the last reference */
- e_mapi_utils_unref_in_thread (G_OBJECT (backend));
-}
-
-static GSList *
-copy_string_slist (const GSList *lst)
-{
- GSList *res, *l;
-
- res = g_slist_copy ((GSList *) lst);
- for (l = res; l; l = l->next) {
- l->data = g_strdup (l->data);
- }
-
- return res;
-}
-
-static void
-base_op_abstract (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable,
OperationType ot)
-{
- OperationBase *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationBase, 1);
- op->ot = ot;
- op->cal = cal;
- op->opid = opid;
- op->cancellable = cancellable;
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-str_op_abstract (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar
*str, OperationType ot)
-{
- OperationStr *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationStr, 1);
- op->base.ot = ot;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->str = g_strdup (str);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-str2_op_abstract (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar
*str1, const gchar *str2, OperationType ot)
-{
- OperationStr2 *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationStr2, 1);
- op->base.ot = ot;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->str1 = g_strdup (str1);
- op->str2 = g_strdup (str2);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-#define BASE_OP_DEF(_func, _ot)
\
-static void \
-_func (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable) \
-{ \
- base_op_abstract (backend, cal, opid, cancellable, _ot); \
-}
-
-#define STR_OP_DEF(_func, _ot) \
-static void \
-_func (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable * cancellable, const gchar *str)
\
-{ \
- str_op_abstract (backend, cal, opid, cancellable, str, _ot); \
-}
-
-#define STR2_OP_DEF(_func, _ot) \
-static void \
-_func (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *str1,
const gchar *str2) \
-{ \
- str2_op_abstract (backend, cal, opid, cancellable, str1, str2, _ot); \
-}
-
-static void
-ecbm_op_open (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, gboolean
only_if_exists)
-{
- OperationOpen *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationOpen, 1);
- op->base.ot = OP_OPEN;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->only_if_exists = only_if_exists;
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-BASE_OP_DEF (ecbm_op_refresh, OP_REFRESH)
-
-static void
-ecbm_op_create_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *calobjs)
-{
- OperationCreate *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationCreate, 1);
- op->base.ot = OP_CREATE_OBJECTS;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->calobjs = g_slist_copy_deep ((GSList *) calobjs, (GCopyFunc) g_strdup, NULL);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-ecbm_op_modify_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *calobjs,
- ECalObjModType mod)
-{
- OperationModify *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationModify, 1);
- op->base.ot = OP_MODIFY_OBJECTS;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->calobjs = g_slist_copy_deep ((GSList *) calobjs, (GCopyFunc) g_strdup, NULL);
- op->mod = mod;
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-ecbm_op_remove_objects (ECalBackend *backend,
- EDataCal *cal,
- guint32 opid,
- GCancellable *cancellable,
- const GSList *ids,
- ECalObjModType mod)
-{
- OperationRemove *op;
- GSList *iter;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationRemove, 1);
- op->base.ot = OP_REMOVE_OBJECTS;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->ids = g_slist_copy ((GSList *) ids);
- op->mod = mod;
-
- for (iter = op->ids; iter; iter = iter->next) {
- ECalComponentId *srcid = iter->data, *desid;
-
- if (!srcid)
- continue;
-
- desid = g_new0 (ECalComponentId, 1);
- desid->uid = g_strdup (srcid->uid);
- desid->rid = g_strdup (srcid->rid);
-
- iter->data = desid;
- }
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-ecbm_op_discard_alarm (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const
gchar *uid, const gchar *rid, const gchar *auid)
-{
- OperationDiscardAlarm *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationDiscardAlarm, 1);
- op->base.ot = OP_DISCARD_ALARM;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->uid = g_strdup (uid);
- op->rid = g_strdup (rid);
- op->auid = g_strdup (auid);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-STR_OP_DEF (ecbm_op_receive_objects, OP_RECEIVE_OBJECTS)
-STR_OP_DEF (ecbm_op_send_objects, OP_SEND_OBJECTS)
-STR2_OP_DEF (ecbm_op_get_object, OP_GET_OBJECT)
-STR_OP_DEF (ecbm_op_get_object_list, OP_GET_OBJECT_LIST)
-STR2_OP_DEF (ecbm_op_get_attachment_uris, OP_GET_ATTACHMENT_URIS)
-STR_OP_DEF (ecbm_op_get_timezone, OP_GET_TIMEZONE)
-STR_OP_DEF (ecbm_op_add_timezone, OP_ADD_TIMEZONE)
-
-static void
-ecbm_op_start_view (ECalBackend *backend, EDataCalView *view)
-{
- OperationStartView *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
-
- op = g_new0 (OperationStartView, 1);
- op->base.ot = OP_START_VIEW;
- op->view = g_object_ref (view);
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
-static void
-ecbm_op_get_free_busy (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const
GSList *users, time_t start, time_t end)
-{
- OperationGetFreeBusy *op;
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (backend != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (backend));
-
- cbmapi = E_CAL_BACKEND_MAPI (backend);
- priv = cbmapi->priv;
- g_return_if_fail (priv != NULL);
-
- g_object_ref (cbmapi);
- if (cal)
- g_object_ref (cal);
- if (cancellable)
- g_object_ref (cancellable);
-
- op = g_new0 (OperationGetFreeBusy, 1);
- op->base.ot = OP_GET_FREE_BUSY;
- op->base.cal = cal;
- op->base.opid = opid;
- op->base.cancellable = cancellable;
- op->users = copy_string_slist (users);
- op->start = start;
- op->end = end;
-
- e_mapi_operation_queue_push (priv->op_queue, op);
-}
-
static gboolean
-ecbm_get_destination_address (EBackend *backend,
- gchar **host,
- guint16 *port)
+ecb_mapi_get_destination_address (EBackend *backend,
+ gchar **host,
+ guint16 *port)
{
ESourceRegistry *registry;
ESource *source;
gboolean result = FALSE;
- g_return_val_if_fail (port != NULL, FALSE);
g_return_val_if_fail (host != NULL, FALSE);
+ g_return_val_if_fail (port != NULL, FALSE);
registry = e_cal_backend_get_registry (E_CAL_BACKEND (backend));
source = e_backend_get_source (backend);
@@ -3422,172 +1684,108 @@ ecbm_get_destination_address (EBackend *backend,
return result;
}
-static void
-ecbm_constructed (GObject *object)
-{
- G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->constructed (object);
-
- /* Reset the connectable, it steals data from Authentication extension,
- where is written no address */
- e_backend_set_connectable (E_BACKEND (object), NULL);
-}
-
-static void
-ecbm_dispose (GObject *object)
+static gchar *
+ecb_mapi_dup_component_revision_cb (ECalCache *cal_cache,
+ icalcomponent *icalcomp)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (object));
+ icalproperty *prop;
+ struct icaltimetype itt;
- cbmapi = E_CAL_BACKEND_MAPI (object);
- priv = cbmapi->priv;
+ g_return_val_if_fail (icalcomp != NULL, NULL);
- if (priv && priv->op_queue)
- e_mapi_operation_queue_cancel_all (priv->op_queue);
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_LASTMODIFIED_PROPERTY);
+ if (!prop)
+ return NULL;
- if (priv && priv->cancellable) {
- g_cancellable_cancel (priv->cancellable);
- g_object_unref (priv->cancellable);
- priv->cancellable = NULL;
- }
+ itt = icalproperty_get_lastmodified (prop);
- if (G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->dispose)
- (* G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->dispose) (object);
+ return icaltime_as_ical_string_r (itt);
}
static void
-ecbm_finalize (GObject *object)
+ecb_mapi_constructed (GObject *object)
{
- ECalBackendMAPI *cbmapi;
- ECalBackendMAPIPrivate *priv;
+ ECalBackendMAPI *cbmapi = E_CAL_BACKEND_MAPI (object);
+ ECalCache *cal_cache;
- g_return_if_fail (object != NULL);
- g_return_if_fail (E_IS_CAL_BACKEND_MAPI (object));
-
- cbmapi = E_CAL_BACKEND_MAPI (object);
- priv = cbmapi->priv;
-
- /* Clean up */
- if (priv->timeout_id) {
- g_source_remove (priv->timeout_id);
- priv->timeout_id = 0;
- }
-
- if (priv->dlock) {
- g_mutex_lock (&priv->dlock->mutex);
- priv->dlock->exit = TRUE;
- g_mutex_unlock (&priv->dlock->mutex);
+ /* Chaing up to parent's method */
+ G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->constructed (object);
- g_cond_signal (&priv->dlock->cond);
+ /* Reset the connectable, it steals data from Authentication extension,
+ where is written no address */
+ e_backend_set_connectable (E_BACKEND (object), NULL);
- if (priv->dthread)
- g_thread_join (priv->dthread);
+ e_cal_backend_set_writable (E_CAL_BACKEND (cbmapi), TRUE);
- g_mutex_clear (&priv->dlock->mutex);
- g_cond_clear (&priv->dlock->cond);
- g_free (priv->dlock);
- priv->dthread = NULL;
- }
+ cal_cache = e_cal_meta_backend_ref_cache (E_CAL_META_BACKEND (cbmapi));
- if (priv->op_queue) {
- g_object_unref (priv->op_queue);
- priv->op_queue = NULL;
- }
+ g_signal_connect (cal_cache, "dup-component-revision",
+ G_CALLBACK (ecb_mapi_dup_component_revision_cb), NULL);
- g_mutex_clear (&priv->mutex);
- g_mutex_clear (&priv->updating_mutex);
- g_mutex_clear (&priv->is_updating_mutex);
+ g_clear_object (&cal_cache);
+}
- if (priv->store) {
- g_object_unref (priv->store);
- priv->store = NULL;
- }
+static void
+ecb_mapi_dispose (GObject *object)
+{
+ ECalBackendMAPI *cbmapi = E_CAL_BACKEND_MAPI (object);
- if (priv->sendoptions_sync_timeout) {
- g_source_remove (priv->sendoptions_sync_timeout);
- priv->sendoptions_sync_timeout = 0;
- }
+ g_clear_object (&cbmapi->priv->conn);
- if (priv->foreign_username) {
- g_free (priv->foreign_username);
- priv->foreign_username = NULL;
- }
+ /* Chain up to parent's method */
+ G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->dispose (object);
+}
- if (priv->conn) {
- g_object_unref (priv->conn);
- priv->conn = NULL;
- }
+static void
+ecb_mapi_finalize (GObject *object)
+{
+ ECalBackendMAPI *cbmapi = E_CAL_BACKEND_MAPI (object);
- g_free (priv);
- cbmapi->priv = NULL;
+ g_rec_mutex_clear (&cbmapi->priv->conn_lock);
- if (G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->finalize)
- (* G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->finalize) (object);
+ /* Chain up to parent's method */
+ G_OBJECT_CLASS (e_cal_backend_mapi_parent_class)->finalize (object);
}
-/* MAPI CLASS INIT */
static void
-e_cal_backend_mapi_class_init (ECalBackendMAPIClass *class)
+e_cal_backend_mapi_class_init (ECalBackendMAPIClass *klass)
{
GObjectClass *object_class;
EBackendClass *backend_class;
ECalBackendClass *cal_backend_class;
+ ECalBackendSyncClass *sync_backend_class;
+ ECalMetaBackendClass *meta_backend_class;
- object_class = G_OBJECT_CLASS (class);
- backend_class = E_BACKEND_CLASS (class);
- cal_backend_class = E_CAL_BACKEND_CLASS (class);
-
- object_class->constructed = ecbm_constructed;
- object_class->dispose = ecbm_dispose;
- object_class->finalize = ecbm_finalize;
-
- backend_class->get_destination_address = ecbm_get_destination_address;
- backend_class->authenticate_sync = ecbm_authenticate_sync;
-
- /* functions done asynchronously */
- cal_backend_class->get_backend_property = ecbm_get_backend_property;
- cal_backend_class->open = ecbm_op_open;
- cal_backend_class->refresh = ecbm_op_refresh;
- cal_backend_class->get_object = ecbm_op_get_object;
- cal_backend_class->get_object_list = ecbm_op_get_object_list;
- cal_backend_class->get_attachment_uris = ecbm_op_get_attachment_uris;
- cal_backend_class->create_objects = ecbm_op_create_objects;
- cal_backend_class->modify_objects = ecbm_op_modify_objects;
- cal_backend_class->remove_objects = ecbm_op_remove_objects;
- cal_backend_class->discard_alarm = ecbm_op_discard_alarm;
- cal_backend_class->receive_objects = ecbm_op_receive_objects;
- cal_backend_class->send_objects = ecbm_op_send_objects;
- cal_backend_class->get_timezone = ecbm_op_get_timezone;
- cal_backend_class->add_timezone = ecbm_op_add_timezone;
- cal_backend_class->get_free_busy = ecbm_op_get_free_busy;
- cal_backend_class->start_view = ecbm_op_start_view;
-}
+ g_type_class_add_private (klass, sizeof (ECalBackendMAPIPrivate));
-static void
-e_cal_backend_mapi_init (ECalBackendMAPI *cbmapi)
-{
- ECalBackendMAPIPrivate *priv;
+ meta_backend_class = E_CAL_META_BACKEND_CLASS (klass);
+ meta_backend_class->connect_sync = ecb_mapi_connect_sync;
+ meta_backend_class->disconnect_sync = ecb_mapi_disconnect_sync;
+ meta_backend_class->get_changes_sync = ecb_mapi_get_changes_sync;
+ meta_backend_class->list_existing_sync = ecb_mapi_list_existing_sync;
+ meta_backend_class->load_component_sync = ecb_mapi_load_component_sync;
+ meta_backend_class->save_component_sync = ecb_mapi_save_component_sync;
+ meta_backend_class->remove_component_sync = ecb_mapi_remove_component_sync;
- priv = g_new0 (ECalBackendMAPIPrivate, 1);
+ cal_backend_class = E_CAL_BACKEND_CLASS (klass);
+ cal_backend_class->get_backend_property = ecb_mapi_get_backend_property;
- priv->timeout_id = 0;
- priv->sendoptions_sync_timeout = 0;
+ sync_backend_class = E_CAL_BACKEND_SYNC_CLASS (klass);
+ sync_backend_class->send_objects_sync = ecb_mapi_send_objects_sync;
- /* create the mutex for thread safety */
- g_mutex_init (&priv->mutex);
- g_mutex_init (&priv->updating_mutex);
- g_mutex_init (&priv->is_updating_mutex);
- priv->is_updating = FALSE;
- priv->op_queue = e_mapi_operation_queue_new ((EMapiOperationQueueFunc) ecbm_operation_cb, cbmapi);
- priv->last_refresh = -1;
- priv->last_obj_total = -1;
- priv->cancellable = g_cancellable_new ();
+ backend_class = E_BACKEND_CLASS (klass);
+ backend_class->get_destination_address = ecb_mapi_get_destination_address;
- cbmapi->priv = priv;
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->constructed = ecb_mapi_constructed;
+ object_class->dispose = ecb_mapi_dispose;
+ object_class->finalize = ecb_mapi_finalize;
+}
+
+static void
+e_cal_backend_mapi_init (ECalBackendMAPI *cbmapi)
+{
+ cbmapi->priv = G_TYPE_INSTANCE_GET_PRIVATE (cbmapi, E_TYPE_CAL_BACKEND_MAPI, ECalBackendMAPIPrivate);
- g_signal_connect (
- cbmapi, "notify::online",
- G_CALLBACK (ecbm_notify_online_cb), NULL);
+ g_rec_mutex_init (&cbmapi->priv->conn_lock);
}
diff --git a/src/calendar/e-cal-backend-mapi.h b/src/calendar/e-cal-backend-mapi.h
index dc8689f..d0aab71 100644
--- a/src/calendar/e-cal-backend-mapi.h
+++ b/src/calendar/e-cal-backend-mapi.h
@@ -41,14 +41,14 @@ typedef struct _ECalBackendMAPIClass ECalBackendMAPIClass;
typedef struct _ECalBackendMAPIPrivate ECalBackendMAPIPrivate;
struct _ECalBackendMAPI {
- ECalBackend backend;
+ ECalMetaBackend parent_object;
/* Private data */
ECalBackendMAPIPrivate *priv;
};
struct _ECalBackendMAPIClass {
- ECalBackendClass parent_class;
+ ECalMetaBackendClass parent_class;
};
GType e_cal_backend_mapi_get_type(void);
diff --git a/src/libexchangemapi/CMakeLists.txt b/src/libexchangemapi/CMakeLists.txt
index d214c43..58a3a25 100644
--- a/src/libexchangemapi/CMakeLists.txt
+++ b/src/libexchangemapi/CMakeLists.txt
@@ -27,8 +27,6 @@ set(SOURCES
e-mapi-cal-recur-utils.h
e-mapi-mail-utils.c
e-mapi-mail-utils.h
- e-mapi-operation-queue.c
- e-mapi-operation-queue.h
e-source-mapi-folder.c
e-source-mapi-folder.h
)
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index 2b1bb53..475e065 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -760,28 +760,27 @@ populate_ical_attendees (EMapiConnection *conn,
static void
set_attachments_to_comp (EMapiConnection *conn,
EMapiAttachment *attachments,
- ECalComponent *comp,
- const gchar *local_store_path)
+ ECalComponent *comp)
{
- GSList *comp_attach_list = NULL;
EMapiAttachment *attach;
- const gchar *uid;
+ icalcomponent *icalcomp;
g_return_if_fail (comp != NULL);
- g_return_if_fail (local_store_path != NULL);
if (!attachments)
return;
- e_cal_component_get_uid (comp, &uid);
+ icalcomp = e_cal_component_get_icalcomponent (comp);
+ g_return_if_fail (icalcomp != NULL);
for (attach = attachments; attach; attach = attach->next) {
uint64_t data_cb = 0;
const uint8_t *data_lpb = NULL;
const gchar *filename;
- const uint32_t *ui32;
- gchar *path, *attach_uri;
- GError *error = NULL;
+ icalattach *new_attach;
+ icalparameter *param;
+ gchar *base64;
+ icalproperty *prop;
if (!e_mapi_attachment_get_bin_prop (attach, PidTagAttachDataBinary, &data_cb, &data_lpb)) {
g_debug ("%s: Skipping calendar attachment without data", G_STRFUNC);
@@ -792,31 +791,28 @@ set_attachments_to_comp (EMapiConnection *conn,
if (!filename || !*filename)
filename = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachFilename);
- ui32 = e_mapi_util_find_array_propval (&attach->properties, PidTagAttachNumber);
- path = e_filename_mkdir_encoded (local_store_path, uid, filename, ui32 ? *ui32 : 0);
+ base64 = g_base64_encode ((const guchar *) data_lpb, data_cb);
+ new_attach = icalattach_new_from_data (base64, NULL, NULL);
+ g_free (base64);
- attach_uri = g_filename_to_uri (path, NULL, &error);
- if (!attach_uri) {
- g_debug ("%s: Could not get attach_uri from '%s': %s", G_STRFUNC, path, error ?
error->message : "Unknown error");
- g_clear_error (&error);
- g_free (path);
- continue;
- }
+ prop = icalproperty_new_attach (new_attach);
+ icalattach_unref (new_attach);
- if (!g_file_set_contents (path, (const gchar *) data_lpb, data_cb, &error)) {
- g_debug ("%s: Failed to write attachment content to '%s': %s", G_STRFUNC, path, error
? error->message : "Unknown error");
- g_free (attach_uri);
- g_clear_error (&error);
- } else {
- comp_attach_list = g_slist_append (comp_attach_list, attach_uri);
+ param = icalparameter_new_value (ICAL_VALUE_BINARY);
+ icalproperty_add_parameter (prop, param);
+
+ param = icalparameter_new_encoding (ICAL_ENCODING_BASE64);
+ icalproperty_add_parameter (prop, param);
+
+ if (filename && *filename) {
+ param = icalparameter_new_filename (filename);
+ icalproperty_add_parameter (prop, param);
}
- g_free (path);
+ icalcomponent_add_property (icalcomp, prop);
}
- e_cal_component_set_attachment_list (comp, comp_attach_list);
-
- g_slist_free_full (comp_attach_list, g_free);
+ e_cal_component_rescan (comp);
}
ECalComponent *
@@ -824,7 +820,6 @@ e_mapi_cal_util_object_to_comp (EMapiConnection *conn,
EMapiObject *object,
icalcomponent_kind kind,
gboolean is_reply,
- const gchar *local_store_uri,
const gchar *use_uid,
GSList **detached_components)
{
@@ -867,8 +862,6 @@ e_mapi_cal_util_object_to_comp (EMapiConnection *conn,
}
utc_zone = icaltimezone_get_utc_timezone ();
- if (!local_store_uri)
- local_store_uri = g_get_tmp_dir ();
str = e_mapi_util_find_array_propval (&object->properties, PidTagSubject);
str = str ? str : e_mapi_util_find_array_propval (&object->properties, PidTagNormalizedSubject);
@@ -1291,7 +1284,7 @@ e_mapi_cal_util_object_to_comp (EMapiConnection *conn,
icalcomponent_add_property (ical_comp, prop);
}
- set_attachments_to_comp (conn, object->attachments, comp, local_store_uri);
+ set_attachments_to_comp (conn, object->attachments, comp);
e_cal_component_rescan (comp);
diff --git a/src/libexchangemapi/e-mapi-cal-utils.h b/src/libexchangemapi/e-mapi-cal-utils.h
index 2c173fe..1af3db6 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.h
+++ b/src/libexchangemapi/e-mapi-cal-utils.h
@@ -95,7 +95,6 @@ ECalComponent * e_mapi_cal_util_object_to_comp (EMapiConnection
*conn,
EMapiObject *object,
icalcomponent_kind kind,
gboolean is_reply,
- const gchar *local_store_uri,
const gchar *use_uid,
GSList **detached_components);
diff --git a/src/libexchangemapi/e-mapi-mail-utils.c b/src/libexchangemapi/e-mapi-mail-utils.c
index db9b232..961f3e7 100644
--- a/src/libexchangemapi/e-mapi-mail-utils.c
+++ b/src/libexchangemapi/e-mapi-mail-utils.c
@@ -358,7 +358,7 @@ build_ical_string (EMapiConnection *conn,
else
use_uid = e_util_generate_uid ();
- comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY,
NULL, use_uid, &detached_components);
+ comp = e_mapi_cal_util_object_to_comp (conn, object, ical_kind, ical_method == ICAL_METHOD_REPLY,
use_uid, &detached_components);
g_free (use_uid);
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index 092cf79..859dad9 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -183,7 +183,7 @@ e_mapi_util_mapi_id_from_string (const gchar *str, mapi_id_t *id)
{
gint n = 0;
- if (str && *str)
+ if (str && *str && strlen (str) <= 16)
n = sscanf (str, "%016" G_GINT64_MODIFIER "X", id);
return (n == 1);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]