[evolution-ews] Bug #656377 - Support for public folders
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #656377 - Support for public folders
- Date: Thu, 17 Jan 2013 11:11:51 +0000 (UTC)
commit 2a61b5b2b155d50a5a9b6bbee1d96bbbd5411675
Author: Milan Crha <mcrha redhat com>
Date: Thu Jan 17 12:11:07 2013 +0100
Bug #656377 - Support for public folders
src/camel/camel-ews-folder.c | 22 +-
src/camel/camel-ews-store-summary.c | 45 ++-
src/camel/camel-ews-store-summary.h | 11 +-
src/camel/camel-ews-store.c | 709 ++++++++++++++++++--
src/camel/camel-ews-store.h | 2 +
src/camel/camel-ews-utils.c | 42 +-
src/collection/e-ews-backend.c | 21 +-
src/configuration/e-ews-subscribe-foreign-folder.c | 9 +-
src/server/e-ews-connection.c | 4 +
src/server/e-ews-folder.c | 54 ++-
src/server/e-ews-folder.h | 18 +-
src/server/e-source-ews-folder.c | 52 ++-
src/server/e-source-ews-folder.h | 3 +
13 files changed, 896 insertions(+), 96 deletions(-)
---
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index 26489a2..0eeb54b 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -1003,6 +1003,7 @@ ews_synchronize_sync (CamelFolder *folder,
gint mi_list_len = 0;
gboolean success = TRUE;
gint i;
+ GError *local_error = NULL;
ews_store = (CamelEwsStore *) camel_folder_get_parent_store (folder);
@@ -1056,28 +1057,39 @@ ews_synchronize_sync (CamelFolder *folder,
}
if (mi_list_len == EWS_MAX_FETCH_COUNT) {
- success = ews_sync_mi_flags (folder, mi_list, cancellable, error);
+ success = ews_sync_mi_flags (folder, mi_list, cancellable, &local_error);
mi_list = NULL;
mi_list_len = 0;
}
}
- if (mi_list_len)
- success = ews_sync_mi_flags (folder, mi_list, cancellable, error);
+ if (mi_list_len && success) {
+ success = ews_sync_mi_flags (folder, mi_list, cancellable, &local_error);
+ if (local_error && g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ACCESSDENIED)) {
+ /* if cannot save flags, then it can be a public or
+ a foreign folder with no write access;
+ the flags will be saved locally, at least */
+ g_clear_error (&local_error);
+ success = TRUE;
+ }
+ }
if (deleted_uids && success)
- success = ews_delete_messages (folder, deleted_uids, ews_folder_is_of_type (folder, CAMEL_FOLDER_TYPE_TRASH), cancellable, error);
+ success = ews_delete_messages (folder, deleted_uids, ews_folder_is_of_type (folder, CAMEL_FOLDER_TYPE_TRASH), cancellable, &local_error);
else
g_slist_free_full (deleted_uids, (GDestroyNotify) camel_pstring_free);
if (junk_uids && success)
- success = ews_move_to_junk_folder (folder, junk_uids, cancellable, error);
+ success = ews_move_to_junk_folder (folder, junk_uids, cancellable, &local_error);
else
g_slist_free_full (junk_uids, (GDestroyNotify) camel_pstring_free);
camel_folder_summary_save_to_db (folder->summary, NULL);
camel_folder_summary_free_array (uids);
+ if (local_error)
+ g_propagate_error (error, local_error);
+
return success;
}
diff --git a/src/camel/camel-ews-store-summary.c b/src/camel/camel-ews-store-summary.c
index 45549ef..f0c8edd 100644
--- a/src/camel/camel-ews-store-summary.c
+++ b/src/camel/camel-ews-store-summary.c
@@ -386,7 +386,8 @@ camel_ews_store_summary_new_folder (CamelEwsStoreSummary *ews_summary,
EEwsFolderType folder_type,
guint64 folder_flags,
guint64 total,
- gboolean foreign)
+ gboolean foreign,
+ gboolean public_folder)
{
const gchar *folder_type_nick;
@@ -410,15 +411,19 @@ camel_ews_store_summary_new_folder (CamelEwsStoreSummary *ews_summary,
g_key_file_set_string (
ews_summary->priv->key_file,
folder_id, "FolderType", folder_type_nick);
- g_key_file_set_uint64 (
- ews_summary->priv->key_file,
- folder_id, "Flags", folder_flags);
+ if (folder_flags)
+ g_key_file_set_uint64 (
+ ews_summary->priv->key_file,
+ folder_id, "Flags", folder_flags);
g_key_file_set_uint64 (
ews_summary->priv->key_file,
folder_id, "Total", total);
g_key_file_set_boolean (
ews_summary->priv->key_file,
folder_id, "Foreign", foreign);
+ g_key_file_set_boolean (
+ ews_summary->priv->key_file,
+ folder_id, "Public", public_folder);
ews_ss_hash_replace (ews_summary, g_strdup (folder_id), NULL, FALSE);
@@ -577,6 +582,21 @@ camel_ews_store_summary_set_foreign_subfolders (CamelEwsStoreSummary *ews_summar
}
void
+camel_ews_store_summary_set_public (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ gboolean is_public)
+{
+ S_LOCK (ews_summary);
+
+ g_key_file_set_boolean (
+ ews_summary->priv->key_file,
+ folder_id, "Public", is_public);
+ ews_summary->priv->dirty = TRUE;
+
+ S_UNLOCK (ews_summary);
+}
+
+void
camel_ews_store_summary_store_string_val (CamelEwsStoreSummary *ews_summary,
const gchar *key,
const gchar *value)
@@ -797,6 +817,23 @@ camel_ews_store_summary_get_foreign_subfolders (CamelEwsStoreSummary *ews_summar
return ret;
}
+gboolean
+camel_ews_store_summary_get_public (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ GError **error)
+{
+ gboolean ret;
+
+ S_LOCK (ews_summary);
+
+ ret = g_key_file_get_boolean (
+ ews_summary->priv->key_file, folder_id, "Public", error);
+
+ S_UNLOCK (ews_summary);
+
+ return ret;
+}
+
gchar *
camel_ews_store_summary_get_string_val (CamelEwsStoreSummary *ews_summary,
const gchar *key,
diff --git a/src/camel/camel-ews-store-summary.h b/src/camel/camel-ews-store-summary.h
index a1231dc..54770fb 100644
--- a/src/camel/camel-ews-store-summary.h
+++ b/src/camel/camel-ews-store-summary.h
@@ -97,6 +97,10 @@ void camel_ews_store_summary_set_foreign_subfolders
(CamelEwsStoreSummary *ews_summary,
const gchar *folder_id,
gboolean foreign_subfolders);
+void camel_ews_store_summary_set_public
+ (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ gboolean is_public);
gchar * camel_ews_store_summary_get_folder_name
(CamelEwsStoreSummary *ews_summary,
@@ -142,6 +146,10 @@ gboolean camel_ews_store_summary_get_foreign_subfolders
(CamelEwsStoreSummary *ews_summary,
const gchar *folder_id,
GError **error);
+gboolean camel_ews_store_summary_get_public
+ (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ GError **error);
GSList * camel_ews_store_summary_get_folders
(CamelEwsStoreSummary *ews_summary,
@@ -174,7 +182,8 @@ void camel_ews_store_summary_new_folder
EEwsFolderType folder_type,
guint64 folder_flags,
guint64 total,
- gboolean foreign);
+ gboolean foreign,
+ gboolean public_folder);
gchar * camel_ews_store_summary_get_folder_id_from_name
(CamelEwsStoreSummary *ews_summary,
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index f05eb84..67f97f3 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -39,6 +39,7 @@
#include <glib/gstdio.h>
#include <libemail-engine/e-mail-folder-utils.h>
+#include <libemail-engine/e-mail-session.h>
#include "server/camel-ews-settings.h"
#include "server/e-ews-item-change.h"
@@ -68,6 +69,7 @@ struct _CamelEwsStorePrivate {
GMutex get_finfo_lock;
EEwsConnection *connection;
GMutex connection_lock;
+ GSList *public_folders; /* EEwsFolder * objects */
};
static gboolean ews_store_construct (CamelService *service, CamelSession *session,
@@ -200,10 +202,42 @@ ews_store_construct (CamelService *service,
return TRUE;
}
+/* returns NULL when it's safe to use the default "Public Folders" name; otherwise g_free() it */
+static gchar *
+ews_store_get_public_folders_name (CamelEwsStore *ews_store)
+{
+ gchar *use_name = NULL;
+ gchar *tmp_fid;
+ gint counter = 0;
+
+ tmp_fid = camel_ews_store_summary_get_folder_id_from_name (
+ ews_store->summary, EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME);
+ while (tmp_fid) {
+ counter++;
+
+ g_free (tmp_fid);
+ g_free (use_name);
+
+ /* Translators: This composes a "Public Folders" folder name for case when
+ * user has such in his store already. The %s is replaced with "Public Folders",
+ * the %d with counter, thus it composes name like "Public Folders_1"
+ */
+ use_name = g_strdup_printf (
+ C_("PublicFolders", "%s_%d"),
+ EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME, counter);
+
+ tmp_fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, use_name);
+ }
+
+ return use_name;
+}
+
void
camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
{
gboolean needs_foreign = FALSE, has_foreign = FALSE;
+ gboolean needs_public = FALSE, has_public = FALSE;
+ CamelFolderInfo *fi;
GSList *folders, *iter;
GHashTable *children_count;
GHashTableIter tab_iter;
@@ -228,6 +262,10 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
!g_hash_table_contains (children_count, fid))
g_hash_table_insert (children_count, (gpointer) fid, GINT_TO_POINTER (0));
+ if (g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID) &&
+ !g_hash_table_contains (children_count, fid))
+ g_hash_table_insert (children_count, (gpointer) fid, GINT_TO_POINTER (0));
+
if (!has_foreign && g_str_equal (fid, EWS_FOREIGN_FOLDER_ROOT_ID))
has_foreign = TRUE;
else if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, &error) && !error) {
@@ -244,6 +282,32 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
}
g_clear_error (&error);
+
+ if (!has_public && g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID))
+ has_public = TRUE;
+ else if (camel_ews_store_summary_get_public (ews_store->summary, fid, &error) && !error) {
+ EEwsFolderType ftype;
+ gchar *pfid;
+
+ ftype = camel_ews_store_summary_get_folder_type (ews_store->summary, fid, &error);
+ if (ftype == E_EWS_FOLDER_TYPE_MAILBOX && !error) {
+ guint64 fflags;
+
+ fflags = camel_ews_store_summary_get_folder_flags (ews_store->summary, fid, &error);
+ if ((fflags & CAMEL_FOLDER_SUBSCRIBED) != 0 && !error) {
+ needs_public = TRUE;
+
+ pfid = camel_ews_store_summary_get_parent_folder_id (ews_store->summary, fid, NULL);
+ if (pfid && g_str_equal (pfid, EWS_PUBLIC_FOLDER_ROOT_ID)) {
+ gint count = GPOINTER_TO_INT (g_hash_table_lookup (children_count, pfid));
+
+ g_hash_table_insert (children_count, (gpointer) pfid, GINT_TO_POINTER (count + 1));
+ }
+ }
+ }
+ }
+
+ g_clear_error (&error);
}
g_hash_table_iter_init (&tab_iter, children_count);
@@ -253,6 +317,12 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
if (!count) {
CamelFolderInfo *fi;
+ if (has_foreign && g_str_equal (key, EWS_FOREIGN_FOLDER_ROOT_ID))
+ has_foreign = FALSE;
+
+ if (has_public && g_str_equal (key, EWS_PUBLIC_FOLDER_ROOT_ID))
+ has_public = FALSE;
+
fi = camel_ews_utils_build_folder_info (ews_store, key);
camel_ews_store_summary_remove_folder (ews_store->summary, key, NULL);
@@ -294,9 +364,14 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
use_name ? use_name : EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME,
E_EWS_FOLDER_TYPE_MAILBOX,
CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
- 0, FALSE);
+ 0, FALSE, FALSE);
g_free (use_name);
+
+ fi = camel_ews_utils_build_folder_info (ews_store, EWS_FOREIGN_FOLDER_ROOT_ID);
+ camel_store_folder_created (CAMEL_STORE (ews_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_folder_info_free (fi);
} else if (has_foreign && !needs_foreign) {
CamelFolderInfo *fi;
@@ -308,6 +383,36 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
camel_folder_info_free (fi);
}
+ if (needs_public && !has_public) {
+ gchar *use_name;
+
+ use_name = ews_store_get_public_folders_name (ews_store);
+
+ camel_ews_store_summary_new_folder (
+ ews_store->summary,
+ EWS_PUBLIC_FOLDER_ROOT_ID, NULL, NULL,
+ use_name ? use_name : EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME,
+ E_EWS_FOLDER_TYPE_MAILBOX,
+ CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
+ 0, FALSE, FALSE);
+
+ g_free (use_name);
+
+ fi = camel_ews_utils_build_folder_info (ews_store, EWS_PUBLIC_FOLDER_ROOT_ID);
+ camel_store_folder_created (CAMEL_STORE (ews_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_folder_info_free (fi);
+ } else if (has_public && !needs_public) {
+ CamelFolderInfo *fi;
+
+ fi = camel_ews_utils_build_folder_info (ews_store, EWS_PUBLIC_FOLDER_ROOT_ID);
+ camel_ews_store_summary_remove_folder (ews_store->summary, EWS_PUBLIC_FOLDER_ROOT_ID, NULL);
+
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
+ camel_folder_info_free (fi);
+ }
+
camel_ews_store_summary_rebuild_hashes (ews_store->summary);
camel_ews_store_summary_save (ews_store->summary, NULL);
@@ -641,7 +746,7 @@ ews_store_update_foreign_subfolders (CamelSession *session,
ews_store->summary,
folder_id->id, parent_fid ? parent_fid->id : euf->folder_id, folder_id->change_key,
e_ews_folder_get_name (folder), E_EWS_FOLDER_TYPE_MAILBOX,
- CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE);
+ CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE, FALSE);
fi = camel_ews_utils_build_folder_info (ews_store, folder_id->id);
camel_store_folder_created (CAMEL_STORE (ews_store), fi);
@@ -1068,42 +1173,198 @@ ews_get_folder_sync (CamelStore *store,
return folder;
}
+static gchar *
+get_public_folder_full_name (EEwsFolder *folder,
+ GHashTable *folders_by_id)
+{
+ const EwsFolderId *parent_fid;
+ GString *full_name;
+
+ g_return_val_if_fail (folder != NULL, NULL);
+ g_return_val_if_fail (folders_by_id != NULL, NULL);
+
+ full_name = g_string_new (e_ews_folder_get_name (folder));
+ while (folder) {
+ parent_fid = e_ews_folder_get_parent_id (folder);
+ if (!parent_fid || !parent_fid->id)
+ break;
+
+ folder = g_hash_table_lookup (folders_by_id, parent_fid->id);
+ if (folder) {
+ g_string_prepend (full_name, "/");
+ g_string_prepend (full_name, e_ews_folder_get_name (folder));
+ }
+ }
+
+ g_string_prepend (full_name, "/");
+ g_string_prepend (full_name, EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME);
+
+ return g_string_free (full_name, FALSE);
+}
+
static CamelFolderInfo *
folder_info_from_store_summary (CamelEwsStore *store,
const gchar *top,
guint32 flags,
+ GCancellable *cancellable,
GError **error)
{
CamelEwsStoreSummary *ews_summary;
- GSList *folders, *l;
- GPtrArray *folder_infos;
- CamelFolderInfo *root_fi = NULL;
+ GPtrArray *folder_infos = NULL;
+ CamelFolderInfo *root_fi = NULL, *fi;
- ews_summary = store->summary;
- folders = camel_ews_store_summary_get_folders (ews_summary, top);
+ /* search in public folders */
+ if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) != 0) {
+ GHashTable *folders_by_id;
+ GSList *fiter;
+ GList *esources = NULL;
+ gchar *hosturl = NULL, *username = NULL;
- if (!folders)
- return NULL;
+ g_mutex_lock (&store->priv->get_finfo_lock);
- folder_infos = g_ptr_array_new ();
+ if (!store->priv->public_folders) {
+ g_mutex_unlock (&store->priv->get_finfo_lock);
+ return NULL;
+ }
- for (l = folders; l != NULL; l = g_slist_next (l)) {
- CamelFolderInfo *fi;
- EEwsFolderType ftype;
+ folder_infos = g_ptr_array_new ();
+ folders_by_id = g_hash_table_new (g_str_hash, g_str_equal);
- ftype = camel_ews_store_summary_get_folder_type (ews_summary, l->data, NULL);
- if (ftype != E_EWS_FOLDER_TYPE_MAILBOX)
- continue;
+ for (fiter = store->priv->public_folders; fiter != NULL; fiter = g_slist_next (fiter)) {
+ EEwsFolder *folder = fiter->data;
+ const EwsFolderId *fid;
+
+ if (!folder)
+ continue;
+
+ fid = e_ews_folder_get_id (folder);
+ if (!fid || !fid->id)
+ continue;
+
+ g_hash_table_insert (folders_by_id, fid->id, folder);
+ }
+
+ fi = camel_folder_info_new ();
+ fi->full_name = g_strdup (EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME);
+ fi->display_name = g_strdup (fi->full_name);
+ fi->flags = CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT;
+ fi->unread = 0;
+ fi->total = 0;
- fi = camel_ews_utils_build_folder_info (store, l->data);
g_ptr_array_add (folder_infos, fi);
+
+ for (fiter = store->priv->public_folders; fiter != NULL; fiter = g_slist_next (fiter)) {
+ EEwsFolder *folder = fiter->data;
+ const EwsFolderId *fid;
+
+ if (!folder)
+ continue;
+
+ fid = e_ews_folder_get_id (folder);
+ if (!fid || !fid->id)
+ continue;
+
+ fi = camel_folder_info_new ();
+ fi->full_name = get_public_folder_full_name (folder, folders_by_id);
+ fi->display_name = g_strdup (e_ews_folder_get_name (folder));
+ fi->flags = 0;
+ fi->unread = 0;
+ fi->total = 0;
+
+ switch (e_ews_folder_get_folder_type (folder)) {
+ case E_EWS_FOLDER_TYPE_CALENDAR:
+ fi->flags |= CAMEL_FOLDER_TYPE_EVENTS;
+ break;
+ case E_EWS_FOLDER_TYPE_CONTACTS:
+ fi->flags |= CAMEL_FOLDER_TYPE_CONTACTS;
+ break;
+ case E_EWS_FOLDER_TYPE_TASKS:
+ fi->flags |= CAMEL_FOLDER_TYPE_TASKS;
+ break;
+ case E_EWS_FOLDER_TYPE_MEMOS:
+ fi->flags |= CAMEL_FOLDER_TYPE_MEMOS;
+ break;
+ default:
+ break;
+ }
+
+ if (camel_ews_store_summary_has_folder (store->summary, fid->id)) {
+ guint64 fflags = camel_ews_store_summary_get_folder_flags (store->summary, fid->id, NULL);
+
+ if ((fflags & CAMEL_FOLDER_SUBSCRIBED) != 0)
+ fi->flags |= CAMEL_FOLDER_SUBSCRIBED;
+ }
+
+ if (!(fi->flags & CAMEL_FOLDER_SUBSCRIBED) &&
+ e_ews_folder_get_folder_type (folder) != E_EWS_FOLDER_TYPE_MAILBOX) {
+ if (!hosturl && !username && !esources) {
+ CamelSession *session;
+ CamelSettings *settings;
+ CamelEwsSettings *ews_settings;
+ ESourceRegistry *registry = NULL;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (store));
+ ews_settings = CAMEL_EWS_SETTINGS (settings);
+ session = camel_service_get_session (CAMEL_SERVICE (store));
+ if (E_IS_MAIL_SESSION (session))
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+ hosturl = camel_ews_settings_dup_hosturl (ews_settings);
+ username = camel_network_settings_dup_user (CAMEL_NETWORK_SETTINGS (ews_settings));
+ esources = e_ews_folder_utils_get_esources (registry, hosturl, username, cancellable, NULL);
+
+ g_object_unref (settings);
+ }
+
+ if (e_ews_folder_utils_is_subscribed_as_esource (esources, hosturl, username, fid->id))
+ fi->flags |= CAMEL_FOLDER_SUBSCRIBED;
+ }
+
+ g_ptr_array_add (folder_infos, fi);
+ }
+
+ g_list_free_full (esources, g_object_unref);
+ g_hash_table_destroy (folders_by_id);
+ g_free (hosturl);
+ g_free (username);
+ g_mutex_unlock (&store->priv->get_finfo_lock);
+
+ /* search in regular/subscribed folders */
+ } else {
+ GSList *folders, *fiter;
+
+ ews_summary = store->summary;
+ folders = camel_ews_store_summary_get_folders (ews_summary, top);
+ if (!folders)
+ return NULL;
+
+ folder_infos = g_ptr_array_new ();
+
+ for (fiter = folders; fiter != NULL; fiter = g_slist_next (fiter)) {
+ EEwsFolderType ftype;
+ const gchar *fid = fiter->data;
+
+ ftype = camel_ews_store_summary_get_folder_type (ews_summary, fid, NULL);
+ if (ftype != E_EWS_FOLDER_TYPE_MAILBOX)
+ continue;
+
+ if (camel_ews_store_summary_get_public (ews_summary, fid, NULL)) {
+ guint64 fflags;
+
+ fflags = camel_ews_store_summary_get_folder_flags (ews_summary, fid, NULL);
+ if (!(fflags & CAMEL_FOLDER_SUBSCRIBED))
+ continue;
+ }
+
+ fi = camel_ews_utils_build_folder_info (store, fid);
+ g_ptr_array_add (folder_infos, fi);
+ }
+
+ g_slist_free_full (folders, g_free);
}
root_fi = camel_folder_info_build (folder_infos, top, '/', TRUE);
-
g_ptr_array_free (folder_infos, TRUE);
- g_slist_foreach (folders, (GFunc) g_free, NULL);
- g_slist_free (folders);
return root_fi;
}
@@ -1197,18 +1458,97 @@ ews_get_folder_info_sync (CamelStore *store,
gboolean success;
GError *local_error = NULL;
- if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) != 0) {
- g_set_error_literal (
- error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
- _("Cannot list folders available for subscription of Exchange Web Services account, "
- "use 'Subscribe to folder of other user' context menu option above the account node "
- "in the folder tree instead."));
- return NULL;
- }
-
ews_store = (CamelEwsStore *) store;
priv = ews_store->priv;
+ if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) != 0) {
+ gboolean includes_last_folder = TRUE;
+ GSList *folders = NULL, *to_check = NULL;
+ EwsFolderId *folder_id;
+
+ if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot list EWS public folders in offline mode"));
+ return NULL;
+ }
+
+ g_mutex_lock (&priv->get_finfo_lock);
+
+ g_slist_free_full (priv->public_folders, g_object_unref);
+ priv->public_folders = NULL;
+
+ connection = camel_ews_store_ref_connection (ews_store);
+ folder_id = e_ews_folder_id_new ("publicfoldersroot", NULL, TRUE);
+ to_check = g_slist_append (to_check, folder_id);
+
+ while (!local_error && !g_cancellable_is_cancelled (cancellable) && to_check) {
+ folder_id = to_check->data;
+ to_check = g_slist_remove (to_check, folder_id);
+
+ while (e_ews_connection_find_folder_sync (connection, EWS_PRIORITY_MEDIUM, folder_id, &includes_last_folder, &folders,
+ cancellable, &local_error) && !local_error &&
+ !g_cancellable_is_cancelled (cancellable)) {
+ GSList *fiter;
+
+ if (!folders)
+ break;
+
+ for (fiter = folders; fiter != NULL; fiter = fiter->next) {
+ EEwsFolder *folder = fiter->data;
+
+ if (e_ews_folder_get_child_count (folder) > 0) {
+ const EwsFolderId *fid = e_ews_folder_get_id (folder);
+
+ if (fid)
+ to_check = g_slist_prepend (to_check,
+ e_ews_folder_id_new (fid->id, fid->change_key, fid->is_distinguished_id));
+ }
+
+ if (!e_ews_folder_get_parent_id (folder)) {
+ if (!folder_id->is_distinguished_id) {
+ e_ews_folder_set_parent_id (folder,
+ e_ews_folder_id_new (folder_id->id, folder_id->change_key, folder_id->is_distinguished_id));
+ } else {
+ e_ews_folder_set_parent_id (folder, e_ews_folder_id_new (EWS_PUBLIC_FOLDER_ROOT_ID, NULL, FALSE));
+ }
+ }
+ }
+
+ priv->public_folders = g_slist_concat (priv->public_folders, folders);
+ folders = NULL;
+
+ if (includes_last_folder)
+ break;
+ }
+
+ e_ews_folder_id_free (folder_id);
+ }
+
+ g_mutex_unlock (&priv->get_finfo_lock);
+
+ g_object_unref (connection);
+ g_slist_free_full (to_check, (GDestroyNotify) e_ews_folder_id_free);
+
+ camel_ews_store_ensure_virtual_folders (ews_store);
+
+ if (local_error) {
+ camel_ews_store_maybe_disconnect (ews_store, local_error);
+ g_propagate_error (error, local_error);
+
+ return NULL;
+ }
+
+ if (!priv->public_folders) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot find any EWS public folders"));
+ return NULL;
+ }
+
+ goto offline;
+ }
+
g_mutex_lock (&priv->get_finfo_lock);
if (!(camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store))
&& camel_service_connect_sync ((CamelService *) store, cancellable, error))) {
@@ -1276,7 +1616,7 @@ ews_get_folder_info_sync (CamelStore *store,
g_mutex_unlock (&priv->get_finfo_lock);
offline:
- fi = folder_info_from_store_summary ( (CamelEwsStore *) store, top, flags, error);
+ fi = folder_info_from_store_summary (ews_store, top, flags, cancellable, error);
return fi;
}
@@ -1336,6 +1676,16 @@ ews_create_folder_sync (CamelStore *store,
parent_name);
return NULL;
}
+
+ if (g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID)) {
+ g_free (fid);
+
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ _("Cannot create folder under '%s', it is used for public folders only"),
+ parent_name);
+ return NULL;
+ }
}
if (!camel_ews_store_connected (ews_store, cancellable, error)) {
@@ -1371,7 +1721,7 @@ ews_create_folder_sync (CamelStore *store,
fid, folder_id->change_key,
folder_name,
E_EWS_FOLDER_TYPE_MAILBOX,
- 0, 0, FALSE);
+ 0, 0, FALSE, FALSE);
fi = camel_ews_utils_build_folder_info (ews_store, folder_id->id);
e_ews_folder_id_free (folder_id);
@@ -1415,14 +1765,25 @@ ews_delete_folder_sync (CamelStore *store,
return FALSE;
}
+ if (g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID)) {
+ g_free (fid);
+
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ _("Cannot remove folder '%s', it is used for public folders only"),
+ folder_name);
+ return FALSE;
+ }
+
if (!camel_ews_store_connected (ews_store, cancellable, error)) {
g_free (fid);
return FALSE;
}
- if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL)) {
- /* do not delete foreign folders,
- * just remove them from local store */
+ if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL) ||
+ camel_ews_store_summary_get_public (ews_store->summary, fid, NULL)) {
+ /* do not delete foreign or public folders,
+ * only remove them from local store */
success = TRUE;
} else {
EEwsConnection *connection;
@@ -1797,13 +2158,121 @@ ews_store_folder_is_subscribed (CamelSubscribable *subscribable,
if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, &error) && !error) {
truth = TRUE;
}
+ g_clear_error (&error);
+ if (!truth && camel_ews_store_summary_get_public (ews_store->summary, fid, &error) && !error) {
+ truth = TRUE;
+ }
g_clear_error (&error);
+
g_free (fid);
return truth;
}
+/* caller should hold ews_store->priv->get_finfo_lock already */
+static EEwsFolder *
+ews_store_find_public_folder (CamelEwsStore *ews_store,
+ const gchar *folder_name)
+{
+ EEwsFolder *folder = NULL;
+ GSList *piter;
+ gchar **folders;
+ gint ii;
+
+ g_return_val_if_fail (CAMEL_IS_EWS_STORE (ews_store), NULL);
+ g_return_val_if_fail (folder_name != NULL, NULL);
+
+ folders = g_strsplit (folder_name, "/", -1);
+ if (!folders || !folders[0] || g_strcmp0 (folders[0], EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME) != 0) {
+ g_strfreev (folders);
+ return NULL;
+ }
+
+ /* they are stored in public_folders from top level to bottom level */
+ piter = ews_store->priv->public_folders;
+ for (ii = 1; folders[ii] && piter; ii++) {
+ const gchar *fname = folders[ii];
+
+ while (piter) {
+ EEwsFolder *subf = piter->data;
+ const EwsFolderId *parent_id;
+
+ if (!subf) {
+ piter = NULL;
+ break;
+ }
+
+ if (g_strcmp0 (e_ews_folder_get_name (subf), fname) == 0) {
+ parent_id = e_ews_folder_get_parent_id (subf);
+ if (!folder && (!parent_id || g_strcmp0 (parent_id->id, EWS_PUBLIC_FOLDER_ROOT_ID) == 0)) {
+ folder = subf;
+ break;
+ } else if (parent_id && folder) {
+ const EwsFolderId *fid = e_ews_folder_get_id (folder);
+
+ if (fid && g_strcmp0 (fid->id, parent_id->id) == 0) {
+ folder = subf;
+ break;
+ }
+ }
+ }
+
+ piter = piter->next;
+ }
+ }
+
+ if (!piter || folders[ii])
+ folder = NULL;
+
+ g_strfreev (folders);
+
+ return folder;
+}
+
+/* ppath contains proposed path, this only makes sure that it's a unique path */
+static void
+ews_store_ensure_unique_path (CamelEwsStore *ews_store,
+ gchar **ppath)
+{
+ gboolean done;
+ guint counter = 0;
+ gchar *base_path = NULL;
+
+ g_return_if_fail (ews_store != NULL);
+ g_return_if_fail (ews_store->summary != NULL);
+ g_return_if_fail (ppath != NULL);
+ g_return_if_fail (*ppath != NULL);
+
+ done = FALSE;
+ while (!done) {
+ gchar *fid;
+
+ done = TRUE;
+
+ fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, *ppath);
+ if (fid) {
+ g_free (fid);
+
+ done = FALSE;
+ counter++;
+ if (!counter) {
+ g_debug ("%s: Counter overflow", G_STRFUNC);
+ break;
+ }
+
+ if (!base_path)
+ base_path = *ppath;
+ else
+ g_free (*ppath);
+
+ *ppath = g_strdup_printf ("%s_%u", base_path, counter);
+ }
+ }
+
+ g_free (base_path);
+}
+
static gboolean
ews_store_subscribe_folder_sync (CamelSubscribable *subscribable,
const gchar *folder_name,
@@ -1811,6 +2280,10 @@ ews_store_subscribe_folder_sync (CamelSubscribable *subscribable,
GError **error)
{
CamelEwsStore *ews_store = CAMEL_EWS_STORE (subscribable);
+ EEwsFolder *folder;
+ const EwsFolderId *fid;
+ gboolean res = TRUE;
+ gchar *tmp;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
g_set_error_literal (
@@ -1819,9 +2292,102 @@ ews_store_subscribe_folder_sync (CamelSubscribable *subscribable,
return FALSE;
}
- /* it does nothing currently */
+ /* can subscribe only public folders,
+ thus skip anything known */
+ tmp = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, folder_name);
+ if (tmp) {
+ g_free (tmp);
+ return TRUE;
+ }
- return TRUE;
+ g_mutex_lock (&ews_store->priv->get_finfo_lock);
+ if (!ews_store->priv->public_folders) {
+ g_mutex_unlock (&ews_store->priv->get_finfo_lock);
+
+ g_set_error (
+ error, CAMEL_STORE_ERROR, CAMEL_STORE_ERROR_NO_FOLDER,
+ _("Cannot subscribe folder '%s', no public folder available"), folder_name);
+ return FALSE;
+ }
+
+ folder = ews_store_find_public_folder (ews_store, folder_name);
+ if (!folder) {
+ g_mutex_unlock (&ews_store->priv->get_finfo_lock);
+
+ g_set_error (
+ error, CAMEL_STORE_ERROR, CAMEL_STORE_ERROR_NO_FOLDER,
+ _("Cannot subscribe folder '%s', folder not found"), folder_name);
+ return FALSE;
+ }
+
+ fid = e_ews_folder_get_id (folder);
+
+ g_return_val_if_fail (fid != NULL, FALSE);
+
+ if (camel_ews_store_summary_has_folder (ews_store->summary, EWS_PUBLIC_FOLDER_ROOT_ID)) {
+ gchar *parent_name = camel_ews_store_summary_get_folder_name (ews_store->summary, EWS_PUBLIC_FOLDER_ROOT_ID, NULL);
+
+ g_return_val_if_fail (parent_name != NULL, FALSE);
+
+ tmp = g_strconcat (parent_name, "/", e_ews_folder_get_name (folder), NULL);
+ g_free (parent_name);
+ } else {
+ tmp = g_strconcat (EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME, "/", e_ews_folder_get_name (folder), NULL);
+ }
+
+ if (e_ews_folder_get_folder_type (folder) != E_EWS_FOLDER_TYPE_MAILBOX) {
+ CamelSession *session;
+ CamelSettings *settings;
+ CamelEwsSettings *ews_settings;
+ ESourceRegistry *registry = NULL;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (ews_store));
+ ews_settings = CAMEL_EWS_SETTINGS (settings);
+ session = camel_service_get_session (CAMEL_SERVICE (ews_store));
+ if (E_IS_MAIL_SESSION (session))
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+ res = e_ews_folder_utils_add_as_esource (registry,
+ camel_ews_settings_get_hosturl (ews_settings),
+ camel_network_settings_get_user (CAMEL_NETWORK_SETTINGS (ews_settings)),
+ folder,
+ E_EWS_ESOURCE_FLAG_OFFLINE_SYNC | E_EWS_ESOURCE_FLAG_PUBLIC_FOLDER,
+ 0,
+ cancellable,
+ error);
+
+ g_object_unref (settings);
+ }
+
+ if (res) {
+ ews_store_ensure_unique_path (ews_store, &tmp);
+
+ camel_ews_store_summary_new_folder (ews_store->summary, fid->id, EWS_PUBLIC_FOLDER_ROOT_ID,
+ NULL,
+ strrchr (tmp, '/') + 1,
+ e_ews_folder_get_folder_type (folder),
+ CAMEL_FOLDER_SUBSCRIBED,
+ e_ews_folder_get_total_count (folder),
+ FALSE, TRUE);
+
+ if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_MAILBOX) {
+ CamelFolderInfo *fi;
+
+ camel_ews_store_ensure_virtual_folders (ews_store);
+
+ fi = camel_ews_utils_build_folder_info (ews_store, fid->id);
+ camel_store_folder_created (CAMEL_STORE (ews_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_folder_info_free (fi);
+ }
+ }
+
+ camel_ews_store_summary_save (ews_store->summary, NULL);
+
+ g_free (tmp);
+ g_mutex_unlock (&ews_store->priv->get_finfo_lock);
+
+ return res;
}
static gboolean
@@ -1831,8 +2397,11 @@ ews_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
GError **error)
{
CamelEwsStore *ews_store = CAMEL_EWS_STORE (subscribable);
+ EEwsFolderType folder_type;
+ EEwsFolder *folder;
+ gboolean is_public;
gboolean res = TRUE;
- gchar *fid;
+ gchar *fid = NULL;
if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
g_set_error_literal (
@@ -1841,19 +2410,35 @@ ews_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
return FALSE;
}
- fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, folder_name);
+ folder = ews_store_find_public_folder (ews_store, folder_name);
+ if (folder) {
+ const EwsFolderId *folder_id = e_ews_folder_get_id (folder);
+
+ if (folder_id) {
+ fid = g_strdup (folder_id->id);
+ folder_type = e_ews_folder_get_folder_type (folder);
+ }
+ }
+
+ if (!fid) {
+ fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, folder_name);
+ if (fid)
+ folder_type = camel_ews_store_summary_get_folder_type (ews_store->summary, fid, NULL);
+ }
+
if (!fid) {
/* no such folder in the cache, might be unsubscribed already */
return TRUE;
}
- if (!camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL)) {
+ is_public = camel_ews_store_summary_get_public (ews_store->summary, fid, NULL);
+ if (!is_public && !camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL)) {
/* nothing to do for regular folders */
res = TRUE;
} else {
CamelFolderInfo *fi;
- if (camel_ews_store_summary_get_foreign_subfolders (ews_store->summary, fid, NULL)) {
+ if (!is_public && camel_ews_store_summary_get_foreign_subfolders (ews_store->summary, fid, NULL)) {
/* when subscribed with subfolders, then unsubscribe with subfolders as well */
GSList *local_folders = NULL, *ii;
gchar *full_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, fid, NULL);
@@ -1884,14 +2469,41 @@ ews_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
g_slist_free_full (local_folders, g_free);
}
- fi = camel_ews_utils_build_folder_info (ews_store, fid);
- camel_ews_store_summary_remove_folder (ews_store->summary, fid, error);
+ if (folder_type != E_EWS_FOLDER_TYPE_MAILBOX) {
+ CamelSession *session;
+ CamelSettings *settings;
+ CamelEwsSettings *ews_settings;
+ ESourceRegistry *registry = NULL;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (ews_store));
+ ews_settings = CAMEL_EWS_SETTINGS (settings);
+ session = camel_service_get_session (CAMEL_SERVICE (ews_store));
+ if (E_IS_MAIL_SESSION (session))
+ registry = e_mail_session_get_registry (E_MAIL_SESSION (session));
+
+ res = e_ews_folder_utils_remove_as_esource (registry,
+ camel_ews_settings_get_hosturl (ews_settings),
+ camel_network_settings_get_user (CAMEL_NETWORK_SETTINGS (ews_settings)),
+ fid,
+ cancellable,
+ error);
+
+ g_object_unref (settings);
+ }
- camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
- camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
- camel_folder_info_free (fi);
+ if (res) {
+ fi = camel_ews_utils_build_folder_info (ews_store, fid);
+ camel_ews_store_summary_remove_folder (ews_store->summary, fid, error);
+
+ if (folder_type == E_EWS_FOLDER_TYPE_MAILBOX) {
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
+ camel_folder_info_free (fi);
+
+ camel_ews_store_ensure_virtual_folders (ews_store);
+ }
+ }
- camel_ews_store_ensure_virtual_folders (ews_store);
camel_ews_store_summary_save (ews_store->summary, NULL);
}
@@ -1959,6 +2571,11 @@ ews_store_dispose (GObject *object)
ews_store->priv->connection = NULL;
}
+ if (ews_store->priv->public_folders) {
+ g_slist_free_full (ews_store->priv->public_folders, g_object_unref);
+ ews_store->priv->public_folders = NULL;
+ }
+
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (camel_ews_store_parent_class)->dispose (object);
}
diff --git a/src/camel/camel-ews-store.h b/src/camel/camel-ews-store.h
index 60f5288..0420f47 100644
--- a/src/camel/camel-ews-store.h
+++ b/src/camel/camel-ews-store.h
@@ -53,6 +53,8 @@
#define EWS_FOREIGN_FOLDER_ROOT_ID "ForeignRoot"
#define EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME _("Foreign Folders")
+#define EWS_PUBLIC_FOLDER_ROOT_ID "PublicRoot"
+#define EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME _("Public Folders")
G_BEGIN_DECLS
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index c58d593..5035337 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -48,6 +48,14 @@ camel_ews_utils_build_folder_info (CamelEwsStore *store,
fi = camel_folder_info_new ();
fi->full_name = camel_ews_store_summary_get_folder_full_name (
ews_summary, fid, NULL);
+
+ if (!fi->full_name) {
+ camel_folder_info_free (fi);
+ g_warn_if_reached ();
+
+ return NULL;
+ }
+
fi->display_name = camel_ews_store_summary_get_folder_name (
ews_summary, fid, NULL);
fi->flags = camel_ews_store_summary_get_folder_flags (
@@ -57,6 +65,25 @@ camel_ews_utils_build_folder_info (CamelEwsStore *store,
fi->total = camel_ews_store_summary_get_folder_total (
ews_summary, fid, NULL);
+ if (!(fi->flags & CAMEL_FOLDER_TYPE_MASK)) {
+ switch (camel_ews_store_summary_get_folder_type (ews_summary, fid, NULL)) {
+ case E_EWS_FOLDER_TYPE_CALENDAR:
+ fi->flags |= CAMEL_FOLDER_TYPE_EVENTS;
+ break;
+ case E_EWS_FOLDER_TYPE_CONTACTS:
+ fi->flags |= CAMEL_FOLDER_TYPE_CONTACTS;
+ break;
+ case E_EWS_FOLDER_TYPE_TASKS:
+ fi->flags |= CAMEL_FOLDER_TYPE_TASKS;
+ break;
+ case E_EWS_FOLDER_TYPE_MEMOS:
+ fi->flags |= CAMEL_FOLDER_TYPE_MEMOS;
+ break;
+ default:
+ break;
+ }
+ }
+
return fi;
}
@@ -81,12 +108,12 @@ sync_deleted_folders (CamelEwsStore *store,
if (ftype == E_EWS_FOLDER_TYPE_MAILBOX) {
fi = camel_ews_utils_build_folder_info (store, fid);
- camel_ews_store_summary_remove_folder (
- ews_summary, fid, &error);
+ camel_ews_store_summary_remove_folder (ews_summary, fid, &error);
- camel_subscribable_folder_unsubscribed (
- CAMEL_SUBSCRIBABLE (store), fi);
- camel_store_folder_deleted (CAMEL_STORE (store), fi);
+ if ((fi->flags & CAMEL_FOLDER_SUBSCRIBED) != 0) {
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (store), fi);
+ camel_store_folder_deleted (CAMEL_STORE (store), fi);
+ }
g_clear_error (&error);
}
@@ -227,9 +254,10 @@ add_folder_to_summary (CamelEwsStore *store,
camel_ews_store_summary_new_folder (
ews_summary, fid->id,
- pfid->id, fid->change_key,
+ pfid ? pfid->id : NULL, fid->change_key,
dname, ftype, 0, total,
- e_ews_folder_get_foreign (folder));
+ e_ews_folder_get_foreign (folder),
+ FALSE);
camel_ews_store_summary_set_folder_unread (
ews_summary, fid->id, unread);
}
diff --git a/src/collection/e-ews-backend.c b/src/collection/e-ews-backend.c
index e709d4d..db72aae 100644
--- a/src/collection/e-ews-backend.c
+++ b/src/collection/e-ews-backend.c
@@ -514,9 +514,10 @@ add_remote_sources (EEwsBackend *backend)
if (!e_source_has_extension (source, extension_name))
continue;
- /* foreign folders are just added */
+ /* foreign or public folders are just added */
extension = e_source_get_extension (source, extension_name);
- if (e_source_ews_folder_get_foreign (extension)) {
+ if (e_source_ews_folder_get_foreign (extension) ||
+ e_source_ews_folder_get_public (extension)) {
e_server_side_source_set_writable (
E_SERVER_SIDE_SOURCE (source), TRUE);
e_server_side_source_set_remote_deletable (
@@ -752,9 +753,10 @@ ews_backend_create_resource_sync (ECollectionBackend *backend,
if (e_source_has_extension (source, extension_name)) {
ESourceEwsFolder *extension;
- /* foreign folders are just added */
+ /* foreign and public folders are just added */
extension = e_source_get_extension (source, extension_name);
- if (e_source_ews_folder_get_foreign (extension))
+ if (e_source_ews_folder_get_foreign (extension) ||
+ e_source_ews_folder_get_public (extension))
success = TRUE;
}
@@ -841,10 +843,8 @@ ews_backend_create_resource_sync (ECollectionBackend *backend,
E_SERVER_SIDE_SOURCE (source), cache_dir);
/* Set permissions for clients. */
- e_server_side_source_set_writable (
- E_SERVER_SIDE_SOURCE (source), TRUE);
- e_server_side_source_set_remote_deletable (
- E_SERVER_SIDE_SOURCE (source), TRUE);
+ e_server_side_source_set_writable (E_SERVER_SIDE_SOURCE (source), TRUE);
+ e_server_side_source_set_remote_deletable (E_SERVER_SIDE_SOURCE (source), TRUE);
server = e_collection_backend_ref_server (backend);
e_source_registry_server_add_source (server, source);
@@ -886,8 +886,9 @@ ews_backend_delete_resource_sync (ECollectionBackend *backend,
}
extension = e_source_get_extension (source, extension_name);
- if (e_source_ews_folder_get_foreign (extension)) {
- /* do not delete foreign folders,
+ if (e_source_ews_folder_get_foreign (extension) ||
+ e_source_ews_folder_get_public (extension)) {
+ /* do not delete foreign or public folders,
* just remove them from local store */
success = TRUE;
} else {
diff --git a/src/configuration/e-ews-subscribe-foreign-folder.c b/src/configuration/e-ews-subscribe-foreign-folder.c
index 80c86fb..8562165 100644
--- a/src/configuration/e-ews-subscribe-foreign-folder.c
+++ b/src/configuration/e-ews-subscribe-foreign-folder.c
@@ -113,7 +113,7 @@ add_foreign_folder_to_camel (CamelEwsStore *ews_store,
foreign_mailbox_id, EWS_FOREIGN_FOLDER_ROOT_ID, NULL,
mailbox, E_EWS_FOLDER_TYPE_MAILBOX,
CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
- 0, FALSE);
+ 0, FALSE, FALSE);
}
if (camel_ews_store_summary_has_folder (ews_store->summary, parent_fid->id)) {
@@ -121,7 +121,7 @@ add_foreign_folder_to_camel (CamelEwsStore *ews_store,
ews_store->summary,
fid->id, parent_fid->id, fid->change_key,
display_foldername, E_EWS_FOLDER_TYPE_MAILBOX,
- CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE);
+ CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE, FALSE);
} else {
const gchar *displayname;
@@ -137,7 +137,7 @@ add_foreign_folder_to_camel (CamelEwsStore *ews_store,
ews_store->summary,
fid->id, foreign_mailbox_id, fid->change_key,
displayname, E_EWS_FOLDER_TYPE_MAILBOX,
- CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE);
+ CAMEL_FOLDER_SUBSCRIBED, e_ews_folder_get_total_count (folder), TRUE, FALSE);
g_free (fullname);
}
@@ -438,8 +438,7 @@ check_foreign_folder_idle (GObject *with_object,
camel_ews_settings_get_hosturl (ews_settings),
camel_network_settings_get_user (CAMEL_NETWORK_SETTINGS (ews_settings)),
cffd->folder,
- cffd->include_subfolders,
- TRUE,
+ (cffd->include_subfolders ? E_EWS_ESOURCE_FLAG_INCLUDE_SUBFOLDERS : 0) | E_EWS_ESOURCE_FLAG_OFFLINE_SYNC,
0,
cancellable,
perror))
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 7e60170..fe5abf1 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -7714,6 +7714,10 @@ e_ews_connection_find_folder (EEwsConnection *cnc,
msg = e_ews_message_new_with_header (cnc->priv->uri, cnc->priv->impersonate_user, "FindFolder", "Traversal", "Shallow", EWS_EXCHANGE_2007_SP1);
e_soap_message_start_element (msg, "FolderShape", "messages", NULL);
e_ews_message_write_string_parameter (msg, "BaseShape", NULL, "Default");
+ e_soap_message_start_element (msg, "AdditionalProperties", NULL, NULL);
+ e_ews_message_write_string_parameter_with_attribute (msg, "FieldURI", NULL, NULL, "FieldURI", "folder:FolderClass");
+ e_ews_message_write_string_parameter_with_attribute (msg, "FieldURI", NULL, NULL, "FieldURI", "folder:ChildFolderCount");
+ e_soap_message_end_element (msg); /* AdditionalProperties */
e_soap_message_end_element (msg);
e_soap_message_start_element (msg, "ParentFolderIds", "messages", NULL);
diff --git a/src/server/e-ews-folder.c b/src/server/e-ews-folder.c
index f789171..9a86e74 100644
--- a/src/server/e-ews-folder.c
+++ b/src/server/e-ews-folder.c
@@ -472,8 +472,7 @@ e_ews_folder_utils_populate_esource (ESource *source,
const gchar *master_hosturl,
const gchar *master_username,
EEwsFolder *folder,
- gboolean include_subfolders,
- gboolean offline_sync,
+ EEwsESourceFlags flags,
gint color_seed,
GCancellable *cancellable,
GError **perror)
@@ -499,10 +498,9 @@ e_ews_folder_utils_populate_esource (ESource *source,
case E_EWS_FOLDER_TYPE_CALENDAR:
backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_CALENDAR);
break;
- /*case E_EWS_FOLDER_TYPE_JOURNAL:
- case E_EWS_FOLDER_TYPE_MEMO:
+ case E_EWS_FOLDER_TYPE_MEMOS:
backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MEMO_LIST);
- break;*/
+ break;
case E_EWS_FOLDER_TYPE_TASKS:
backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
break;
@@ -524,10 +522,11 @@ e_ews_folder_utils_populate_esource (ESource *source,
e_source_ews_folder_set_id (folder_ext, folder_id->id);
e_source_ews_folder_set_change_key (folder_ext, NULL);
e_source_ews_folder_set_foreign (folder_ext, e_ews_folder_get_foreign (folder));
- e_source_ews_folder_set_foreign_subfolders (folder_ext, include_subfolders);
+ e_source_ews_folder_set_foreign_subfolders (folder_ext, (flags & E_EWS_ESOURCE_FLAG_INCLUDE_SUBFOLDERS) != 0);
+ e_source_ews_folder_set_public (folder_ext, (flags & E_EWS_ESOURCE_FLAG_PUBLIC_FOLDER) != 0);
offline_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE);
- e_source_offline_set_stay_synchronized (offline_ext, offline_sync);
+ e_source_offline_set_stay_synchronized (offline_ext, (flags & E_EWS_ESOURCE_FLAG_OFFLINE_SYNC) != 0);
/* set also color for calendar-like sources */
if (folder_type != E_EWS_FOLDER_TYPE_CONTACTS) {
@@ -560,8 +559,7 @@ e_ews_folder_utils_add_as_esource (ESourceRegistry *pregistry,
const gchar *master_hosturl,
const gchar *master_username,
EEwsFolder *folder,
- gboolean include_subfolders,
- gboolean offline_sync,
+ EEwsESourceFlags flags,
gint color_seed,
GCancellable *cancellable,
GError **perror)
@@ -597,8 +595,7 @@ e_ews_folder_utils_add_as_esource (ESourceRegistry *pregistry,
master_hosturl,
master_username,
folder,
- include_subfolders,
- offline_sync,
+ flags,
color_seed,
cancellable,
perror)) {
@@ -636,8 +633,12 @@ e_ews_folder_utils_remove_as_esource (ESourceRegistry *pregistry,
sources = e_source_registry_list_sources (registry, NULL);
source = e_ews_folder_utils_get_source_for_folder (sources, master_hosturl, master_username, folder_id);
- if (source)
- res = e_source_remove_sync (source, cancellable, perror);
+ if (source) {
+ if (e_source_get_removable (source))
+ res = e_source_remove_sync (source, cancellable, perror);
+ else
+ res = e_source_remote_delete_sync (source, cancellable, perror);
+ }
g_list_free_full (sources, g_object_unref);
if (!pregistry)
@@ -646,6 +647,33 @@ e_ews_folder_utils_remove_as_esource (ESourceRegistry *pregistry,
return res;
}
+GList *
+e_ews_folder_utils_get_esources (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ ESourceRegistry *registry;
+ GList *all_sources, *esources = NULL;
+
+ registry = pregistry;
+ if (!registry) {
+ registry = e_source_registry_new_sync (cancellable, perror);
+ if (!registry)
+ return NULL;
+ }
+
+ all_sources = e_source_registry_list_sources (registry, NULL);
+ esources = e_ews_folder_utils_filter_sources_for_account (all_sources, master_hosturl, master_username);
+
+ g_list_free_full (all_sources, g_object_unref);
+ if (!pregistry)
+ g_object_unref (registry);
+
+ return esources;
+}
+
gboolean
e_ews_folder_utils_is_subscribed_as_esource (const GList *esources,
const gchar *master_hosturl,
diff --git a/src/server/e-ews-folder.h b/src/server/e-ews-folder.h
index 53d6fca..f410b32 100644
--- a/src/server/e-ews-folder.h
+++ b/src/server/e-ews-folder.h
@@ -80,6 +80,13 @@ EwsFolderId * e_ews_folder_id_new (const gchar *id,
gboolean is_distinguished_id);
void e_ews_folder_id_free (EwsFolderId *fid);
+typedef enum {
+ E_EWS_ESOURCE_FLAG_NONE = 0,
+ E_EWS_ESOURCE_FLAG_INCLUDE_SUBFOLDERS = 1 << 0,
+ E_EWS_ESOURCE_FLAG_OFFLINE_SYNC = 1 << 1,
+ E_EWS_ESOURCE_FLAG_PUBLIC_FOLDER = 1 << 2
+} EEwsESourceFlags;
+
gchar * e_ews_folder_utils_pick_color_spec (gint move_by,
gboolean around_middle);
gboolean e_ews_folder_utils_populate_esource (ESource *source,
@@ -87,8 +94,7 @@ gboolean e_ews_folder_utils_populate_esource (ESource *source,
const gchar *master_hosturl,
const gchar *master_username,
EEwsFolder *folder,
- gboolean include_subfolders,
- gboolean offline_sync,
+ EEwsESourceFlags flags,
gint color_seed,
GCancellable *cancellable,
GError **perror);
@@ -96,8 +102,7 @@ gboolean e_ews_folder_utils_add_as_esource (ESourceRegistry *pregistry,
const gchar *master_hosturl,
const gchar *master_username,
EEwsFolder *folder,
- gboolean include_subfolders,
- gboolean offline_sync,
+ EEwsESourceFlags flags,
gint color_seed,
GCancellable *cancellable,
GError **perror);
@@ -107,6 +112,11 @@ gboolean e_ews_folder_utils_remove_as_esource (ESourceRegistry *pregistry,
const gchar *folder_id,
GCancellable *cancellable,
GError **perror);
+GList * e_ews_folder_utils_get_esources (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ GCancellable *cancellable,
+ GError **perror);
gboolean e_ews_folder_utils_is_subscribed_as_esource (const GList *esources,
const gchar *master_hosturl,
const gchar *master_username,
diff --git a/src/server/e-source-ews-folder.c b/src/server/e-source-ews-folder.c
index 4eb6961..8404760 100644
--- a/src/server/e-source-ews-folder.c
+++ b/src/server/e-source-ews-folder.c
@@ -32,6 +32,7 @@ struct _ESourceEwsFolderPrivate {
gchar *id;
gboolean foreign;
gboolean foreign_subfolders;
+ gboolean is_public;
};
enum {
@@ -39,7 +40,8 @@ enum {
PROP_CHANGE_KEY,
PROP_ID,
PROP_FOREIGN,
- PROP_FOREIGN_SUBFOLDERS
+ PROP_FOREIGN_SUBFOLDERS,
+ PROP_PUBLIC
};
G_DEFINE_DYNAMIC_TYPE (
@@ -77,6 +79,12 @@ source_ews_folder_set_property (GObject *object,
E_SOURCE_EWS_FOLDER (object),
g_value_get_boolean (value));
return;
+
+ case PROP_PUBLIC:
+ e_source_ews_folder_set_public (
+ E_SOURCE_EWS_FOLDER (object),
+ g_value_get_boolean (value));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -116,6 +124,13 @@ source_ews_folder_get_property (GObject *object,
e_source_ews_folder_get_foreign_subfolders (
E_SOURCE_EWS_FOLDER (object)));
return;
+
+ case PROP_PUBLIC:
+ g_value_set_boolean (
+ value,
+ e_source_ews_folder_get_public (
+ E_SOURCE_EWS_FOLDER (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -205,6 +220,19 @@ e_source_ews_folder_class_init (ESourceEwsFolderClass *class)
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS |
E_SOURCE_PARAM_SETTING));
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PUBLIC,
+ g_param_spec_boolean (
+ "public",
+ "Public",
+ "The folder is a public folder, part of Public Folders",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
}
static void
@@ -383,3 +411,25 @@ e_source_ews_folder_set_foreign_subfolders (ESourceEwsFolder *extension,
g_object_notify (G_OBJECT (extension), "foreign-subfolders");
}
+
+gboolean
+e_source_ews_folder_get_public (ESourceEwsFolder *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), FALSE);
+
+ return extension->priv->is_public;
+}
+
+void
+e_source_ews_folder_set_public (ESourceEwsFolder *extension,
+ gboolean is_public)
+{
+ g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
+
+ if ((extension->priv->is_public ? 1 : 0) == (is_public ? 1 : 0))
+ return;
+
+ extension->priv->is_public = is_public;
+
+ g_object_notify (G_OBJECT (extension), "public");
+}
diff --git a/src/server/e-source-ews-folder.h b/src/server/e-source-ews-folder.h
index ad0f284..c0637d8 100644
--- a/src/server/e-source-ews-folder.h
+++ b/src/server/e-source-ews-folder.h
@@ -84,6 +84,9 @@ gboolean e_source_ews_folder_get_foreign_subfolders
void e_source_ews_folder_set_foreign_subfolders
(ESourceEwsFolder *extension,
gboolean foreign_subfolders);
+gboolean e_source_ews_folder_get_public (ESourceEwsFolder *extension);
+void e_source_ews_folder_set_public (ESourceEwsFolder *extension,
+ gboolean is_public);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]