[evolution-ews] Implement "Subscribe to folder of other user" feature
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Implement "Subscribe to folder of other user" feature
- Date: Wed, 15 Aug 2012 07:09:05 +0000 (UTC)
commit 74437db8bec94a623d5bd9ba34c29f8c97187186
Author: Milan Crha <mcrha redhat com>
Date: Wed Aug 15 09:07:51 2012 +0200
Implement "Subscribe to folder of other user" feature
po/POTFILES.in | 2 +
src/camel/camel-ews-folder.c | 4 +
src/camel/camel-ews-store-summary.c | 68 ++-
src/camel/camel-ews-store-summary.h | 13 +-
src/camel/camel-ews-store.c | 407 +++++++++++-
src/camel/camel-ews-store.h | 8 +
src/camel/camel-ews-utils.c | 6 +-
src/camel/camel-ews-utils.h | 2 +-
src/collection/e-ews-backend.c | 137 +++--
src/configuration/Makefile.am | 2 +
src/configuration/e-ews-config-utils.c | 21 +-
src/configuration/e-ews-subscribe-foreign-folder.c | 716 ++++++++++++++++++++
src/configuration/e-ews-subscribe-foreign-folder.h | 34 +
src/server/e-ews-connection.c | 175 +++++-
src/server/e-ews-connection.h | 22 +
src/server/e-ews-folder.c | 370 ++++++++++-
src/server/e-ews-folder.h | 44 ++
src/server/e-source-ews-folder.c | 52 ++-
src/server/e-source-ews-folder.h | 4 +
19 files changed, 1992 insertions(+), 95 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ae9a67f..a87b6d5 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -14,6 +14,7 @@ src/collection/module-ews-backend.c
src/configuration/e-ews-config-utils.c
src/configuration/e-ews-edit-folder-permissions.c
src/configuration/e-ews-search-user.c
+src/configuration/e-ews-subscribe-foreign-folder.c
src/configuration/e-mail-config-ews-autodiscover.c
src/configuration/e-mail-config-ews-backend.c
src/configuration/e-mail-config-ews-gal.c
@@ -21,4 +22,5 @@ src/configuration/e-mail-config-ews-delegates-page.c
src/configuration/e-mail-config-ews-ooo-page.c
src/configuration/module-ews-configuration.error.xml
src/server/e-ews-connection.c
+src/server/e-ews-folder.c
src/utils/ews-camel-common.c
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index c0b6d75..dec71b4 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -1060,6 +1060,10 @@ ews_folder_count_notify_cb (CamelFolderSummary *folder_summary,
store_summary = ews_store->summary;
folder_id = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, camel_folder_get_full_name (folder));
+ /* this can happen on folder delete/unsubscribe, after folder summary clear */
+ if (!folder_id)
+ return;
+
if (g_strcmp0 (g_param_spec_get_name (param), "saved-count") == 0) {
count = camel_folder_summary_get_saved_count (folder_summary);
camel_ews_store_summary_set_folder_total (store_summary, folder_id, count);
diff --git a/src/camel/camel-ews-store-summary.c b/src/camel/camel-ews-store-summary.c
index 08e4dcc..0ebbbfd 100644
--- a/src/camel/camel-ews-store-summary.c
+++ b/src/camel/camel-ews-store-summary.c
@@ -105,6 +105,9 @@ load_id_fname_hash (CamelEwsStoreSummary *ews_summary)
{
GSList *folders, *l;
+ g_hash_table_remove_all (ews_summary->priv->fname_id_hash);
+ g_hash_table_remove_all (ews_summary->priv->id_fname_hash);
+
folders = camel_ews_store_summary_get_folders (ews_summary, NULL);
for (l = folders; l != NULL; l = g_slist_next (l)) {
@@ -189,10 +192,10 @@ camel_ews_store_summary_load (CamelEwsStoreSummary *ews_summary,
camel_ews_store_summary_clear (ews_summary);
g_key_file_set_integer (priv->key_file, STORE_GROUP_NAME, "Version", CURRENT_SUMMARY_VERSION);
- } else {
- load_id_fname_hash (ews_summary);
}
+ load_id_fname_hash (ews_summary);
+
S_UNLOCK (ews_summary);
return ret;
@@ -261,6 +264,16 @@ camel_ews_store_summary_remove (CamelEwsStoreSummary *ews_summary)
return (ret == 0);
}
+void
+camel_ews_store_summary_rebuild_hashes (CamelEwsStoreSummary *ews_summary)
+{
+ g_return_if_fail (CAMEL_IS_EWS_STORE_SUMMARY (ews_summary));
+
+ S_LOCK (ews_summary);
+ load_id_fname_hash (ews_summary);
+ S_UNLOCK (ews_summary);
+}
+
struct subfolder_match {
GSList *ids;
gchar *match;
@@ -355,7 +368,8 @@ camel_ews_store_summary_new_folder (CamelEwsStoreSummary *ews_summary,
const gchar *display_name,
EEwsFolderType folder_type,
guint64 folder_flags,
- guint64 total)
+ guint64 total,
+ gboolean foreign)
{
const gchar *folder_type_nick;
@@ -365,12 +379,14 @@ camel_ews_store_summary_new_folder (CamelEwsStoreSummary *ews_summary,
S_LOCK (ews_summary);
- g_key_file_set_string (
- ews_summary->priv->key_file,
- folder_id, "ParentFolderId", parent_fid);
- g_key_file_set_string (
- ews_summary->priv->key_file,
- folder_id, "ChangeKey", change_key);
+ if (parent_fid)
+ g_key_file_set_string (
+ ews_summary->priv->key_file,
+ folder_id, "ParentFolderId", parent_fid);
+ if (change_key)
+ g_key_file_set_string (
+ ews_summary->priv->key_file,
+ folder_id, "ChangeKey", change_key);
g_key_file_set_string (
ews_summary->priv->key_file,
folder_id, "DisplayName", display_name);
@@ -383,6 +399,9 @@ camel_ews_store_summary_new_folder (CamelEwsStoreSummary *ews_summary,
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);
ews_ss_hash_replace (ews_summary, g_strdup (folder_id), NULL, FALSE);
@@ -511,6 +530,21 @@ camel_ews_store_summary_set_folder_type (CamelEwsStoreSummary *ews_summary,
}
void
+camel_ews_store_summary_set_foreign (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ gboolean is_foreign)
+{
+ S_LOCK (ews_summary);
+
+ g_key_file_set_boolean (
+ ews_summary->priv->key_file,
+ folder_id, "Foreign", is_foreign);
+ 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)
@@ -697,6 +731,22 @@ camel_ews_store_summary_get_folder_type (CamelEwsStoreSummary *ews_summary,
return folder_type;
}
+gboolean
+camel_ews_store_summary_get_foreign (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, "Foreign", 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 7fdb63e..524b483 100644
--- a/src/camel/camel-ews-store-summary.h
+++ b/src/camel/camel-ews-store-summary.h
@@ -52,6 +52,8 @@ gboolean camel_ews_store_summary_save (CamelEwsStoreSummary *ews_summary,
GError **error);
gboolean camel_ews_store_summary_clear (CamelEwsStoreSummary *ews_summary);
gboolean camel_ews_store_summary_remove (CamelEwsStoreSummary *ews_summary);
+void camel_ews_store_summary_rebuild_hashes
+ (CamelEwsStoreSummary *ews_summary);
void camel_ews_store_summary_set_folder_name
(CamelEwsStoreSummary *ews_summary,
@@ -85,6 +87,10 @@ void camel_ews_store_summary_set_folder_type
(CamelEwsStoreSummary *ews_summary,
const gchar *folder_id,
EEwsFolderType folder_type);
+void camel_ews_store_summary_set_foreign
+ (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ gboolean is_foreign);
gchar * camel_ews_store_summary_get_folder_name
(CamelEwsStoreSummary *ews_summary,
@@ -122,6 +128,10 @@ EEwsFolderType camel_ews_store_summary_get_folder_type
(CamelEwsStoreSummary *ews_summary,
const gchar *folder_id,
GError **error);
+gboolean camel_ews_store_summary_get_foreign
+ (CamelEwsStoreSummary *ews_summary,
+ const gchar *folder_id,
+ GError **error);
GSList * camel_ews_store_summary_get_folders
(CamelEwsStoreSummary *ews_summary,
@@ -150,7 +160,8 @@ void camel_ews_store_summary_new_folder
const gchar *display_name,
EEwsFolderType folder_type,
guint64 folder_flags,
- guint64 total);
+ guint64 total,
+ gboolean foreign);
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 9ee158b..074b908 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -70,12 +70,15 @@ static gboolean ews_store_construct (CamelService *service, CamelSession *sessio
CamelProvider *provider, GError **error);
static void camel_ews_store_initable_init (GInitableIface *interface);
+static void camel_ews_subscribable_init (CamelSubscribableInterface *interface);
static GInitableIface *parent_initable_interface;
G_DEFINE_TYPE_WITH_CODE (
CamelEwsStore, camel_ews_store, CAMEL_TYPE_OFFLINE_STORE,
G_IMPLEMENT_INTERFACE (
- G_TYPE_INITABLE, camel_ews_store_initable_init))
+ G_TYPE_INITABLE, camel_ews_store_initable_init)
+ G_IMPLEMENT_INTERFACE (
+ CAMEL_TYPE_SUBSCRIBABLE, camel_ews_subscribable_init))
static void
ews_migrate_to_user_cache_dir (CamelService *service)
@@ -193,6 +196,265 @@ ews_store_construct (CamelService *service,
return TRUE;
}
+/* free returned pointer with g_free() */
+static gchar *
+ews_get_owenr_mailbox_name (CamelEwsStore *ews_store)
+{
+ const gchar *email;
+ gchar *mailbox_name = NULL, *username = NULL;
+ CamelEwsSettings *ews_settings;
+
+ g_return_val_if_fail (CAMEL_IS_EWS_STORE (ews_store), NULL);
+
+ ews_settings = CAMEL_EWS_SETTINGS (camel_service_ref_settings (CAMEL_SERVICE (ews_store)));
+ email = camel_ews_settings_get_email (ews_settings);
+
+ if (email && *email && camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
+ /* get username from the server */
+ EEwsConnection *conn;
+
+ conn = camel_ews_store_ref_connection (ews_store);
+ if (conn) {
+ GSList *mailboxes = NULL;
+ gboolean includes_last_item = FALSE;
+
+ if (e_ews_connection_resolve_names_sync (conn, G_PRIORITY_DEFAULT,
+ email, EWS_SEARCH_AD, NULL, FALSE, &mailboxes, NULL,
+ &includes_last_item, NULL, NULL)) {
+ GSList *iter;
+
+ for (iter = mailboxes; iter; iter = iter->next) {
+ EwsMailbox *mailbox = iter->data;
+
+ if (mailbox && mailbox->email && email &&
+ g_ascii_strcasecmp (email, mailbox->email) == 0) {
+ username = g_strdup (mailbox->name);
+ break;
+ }
+ }
+
+ g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free);
+ }
+
+ g_object_unref (conn);
+ }
+ }
+
+ /* Translators: The '%s' is replaced with user name, to whom the foreign mailbox belongs.
+ Example result: "Mailbox - John Smith"
+ */
+ mailbox_name = g_strdup_printf (C_("ForeignFolder", "Mailbox - %s"), username ? username : (email ? email : C_("ForeignFolder", "Owner")));
+
+ g_object_unref (ews_settings);
+ g_free (username);
+
+ return mailbox_name;
+}
+
+void
+camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
+{
+ gchar *inbox_id, *inbox_parent_id;
+ gboolean needs_foreign = FALSE, has_foreign = FALSE;
+ GSList *folders, *iter;
+ GHashTable *children_count;
+ GHashTableIter tab_iter;
+ gpointer key, value;
+
+ g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
+
+ folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL);
+ if (!folders)
+ return;
+
+ children_count = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (iter = folders; iter; iter = iter->next) {
+ const gchar *fid = iter->data;
+ GError *error = NULL;
+
+ if (!fid)
+ continue;
+
+ if (g_str_has_prefix (fid, "ForeignMailbox::") &&
+ !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) {
+ gchar *pfid;
+
+ needs_foreign = TRUE;
+
+ pfid = camel_ews_store_summary_get_parent_folder_id (ews_store->summary, fid, NULL);
+ if (pfid && g_str_has_prefix (pfid, "ForeignMailbox::")) {
+ 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);
+ }
+
+ inbox_id = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_INBOX);
+ g_return_if_fail (inbox_id != NULL);
+
+ inbox_parent_id = camel_ews_store_summary_get_parent_folder_id (ews_store->summary, inbox_id, NULL);
+ g_free (inbox_id);
+
+ g_return_if_fail (inbox_parent_id != NULL);
+
+ g_hash_table_iter_init (&tab_iter, children_count);
+ while (g_hash_table_iter_next (&tab_iter, &key, &value)) {
+ gint count = GPOINTER_TO_INT (value);
+
+ if (!count) {
+ CamelFolderInfo *fi;
+
+ fi = camel_ews_utils_build_folder_info (ews_store, key);
+ camel_ews_store_summary_remove_folder (ews_store->summary, key, NULL);
+
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_store_folder_deleted (CAMEL_STORE (ews_store), fi);
+ camel_folder_info_free (fi);
+ }
+ }
+
+ g_hash_table_destroy (children_count);
+
+ if (needs_foreign && !has_foreign) {
+ camel_ews_store_summary_new_folder (ews_store->summary,
+ EWS_FOREIGN_FOLDER_ROOT_ID, NULL, NULL,
+ EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME,
+ E_EWS_FOLDER_TYPE_MAILBOX,
+ CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
+ 0, FALSE);
+ } else if (has_foreign && !needs_foreign) {
+ CamelFolderInfo *fi;
+
+ fi = camel_ews_utils_build_folder_info (ews_store, EWS_FOREIGN_FOLDER_ROOT_ID);
+ camel_ews_store_summary_remove_folder (ews_store->summary, EWS_FOREIGN_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);
+ }
+
+ if (!camel_ews_store_summary_has_folder (ews_store->summary, inbox_parent_id)) {
+ /* all standard mail folders should be renamed */
+ GHashTable *old_names, *new_names;
+ CamelStore *store;
+ gchar *mailbox_name;
+
+ store = CAMEL_STORE (ews_store);
+ old_names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+ new_names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+ for (iter = folders; iter; iter = iter->next) {
+ const gchar *fid = iter->data;
+ GError *error = NULL;
+
+ if (!fid)
+ continue;
+
+ if (g_str_equal (fid, EWS_FOREIGN_FOLDER_ROOT_ID) ||
+ g_str_equal (fid, inbox_parent_id)) {
+ /* these are not needed for rename */
+ } else if (!camel_ews_store_summary_get_foreign (ews_store->summary, fid, &error) || error) {
+ gchar *full_name = camel_ews_store_summary_get_folder_full_name (
+ ews_store->summary, fid, NULL);
+
+ if (full_name)
+ g_hash_table_insert (old_names, (gpointer) fid, full_name);
+ }
+
+ g_clear_error (&error);
+ }
+
+ mailbox_name = ews_get_owenr_mailbox_name (ews_store);
+ camel_ews_store_summary_new_folder (ews_store->summary,
+ inbox_parent_id, NULL, NULL,
+ mailbox_name, E_EWS_FOLDER_TYPE_MAILBOX,
+ CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
+ 0, FALSE);
+
+ g_free (mailbox_name);
+
+ g_hash_table_iter_init (&tab_iter, old_names);
+ while (g_hash_table_iter_next (&tab_iter, &key, &value)) {
+ const gchar *fid = key;
+ gchar *full_name = camel_ews_store_summary_get_folder_full_name (
+ ews_store->summary, fid, NULL);
+
+ if (g_strcmp0 (full_name, value) != 0) {
+ g_hash_table_insert (new_names, (gpointer) fid, full_name);
+ }
+
+ g_free (full_name);
+ }
+
+ g_hash_table_iter_init (&tab_iter, new_names);
+ while (g_hash_table_iter_next (&tab_iter, &key, &value)) {
+ /* just rename folders.db folders, as this might
+ be done before any ask for folder structure */
+ camel_db_rename_folder (store->cdb_w, g_hash_table_lookup (old_names, key), value, NULL);
+ }
+
+ g_hash_table_destroy (old_names);
+ g_hash_table_destroy (new_names);
+ }
+
+ camel_ews_store_summary_rebuild_hashes (ews_store->summary);
+ camel_ews_store_summary_save (ews_store->summary, NULL);
+
+ g_free (inbox_parent_id);
+ g_slist_free_full (folders, g_free);
+}
+
+void
+camel_ews_store_ensure_unique_path (CamelEwsStore *ews_store,
+ gchar **ppath)
+{
+ gboolean done;
+ guint counter = 0;
+ gchar *base_path = NULL;
+
+ g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
+ 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 void
ews_update_folder_hierarchy (CamelEwsStore *ews_store,
gchar *sync_state,
@@ -202,6 +464,8 @@ ews_update_folder_hierarchy (CamelEwsStore *ews_store,
GSList *folders_updated)
{
ews_utils_sync_folders (ews_store, folders_created, folders_deleted, folders_updated);
+ camel_ews_store_ensure_virtual_folders (ews_store);
+
camel_ews_store_summary_store_string_val (ews_store->summary, "sync_state", sync_state);
camel_ews_store_summary_save (ews_store->summary, NULL);
@@ -612,11 +876,11 @@ ews_folder_hierarchy_ready_cb (GObject *obj,
g_mutex_unlock (priv->get_finfo_lock);
goto exit;
}
+ g_mutex_lock (priv->get_finfo_lock);
ews_update_folder_hierarchy (
ews_store, sync_state, includes_last_folder,
folders_created, folders_deleted, folders_updated);
- g_mutex_lock (priv->get_finfo_lock);
ews_store->priv->last_refresh_time = time (NULL);
g_mutex_unlock (priv->get_finfo_lock);
@@ -672,12 +936,21 @@ 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;
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))) {
+ camel_ews_store_ensure_virtual_folders (ews_store);
g_mutex_unlock (priv->get_finfo_lock);
goto offline;
}
@@ -794,11 +1067,12 @@ ews_create_folder_sync (CamelStore *store,
fid, folder_id->change_key,
folder_name,
E_EWS_FOLDER_TYPE_MAILBOX,
- 0, 0);
+ 0, 0, FALSE);
fi = camel_ews_utils_build_folder_info (ews_store, folder_id->id);
e_ews_folder_id_free (folder_id);
camel_store_folder_created (store, fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
g_free (full_name);
g_free (fid);
@@ -815,7 +1089,6 @@ ews_delete_folder_sync (CamelStore *store,
CamelEwsStoreSummary *ews_summary = ews_store->summary;
gchar *fid;
CamelFolderInfo *fi = NULL;
- EEwsConnection *connection;
gboolean success;
GError *local_error = NULL;
@@ -833,15 +1106,23 @@ ews_delete_folder_sync (CamelStore *store,
return FALSE;
}
- connection = camel_ews_store_ref_connection (ews_store);
+ if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL)) {
+ /* do not delete foreign folders,
+ just remove them from local store */
+ success = TRUE;
+ } else {
+ EEwsConnection *connection;
- success = e_ews_connection_delete_folder_sync (
- connection,
- EWS_PRIORITY_MEDIUM,
- fid, FALSE, "HardDelete",
- cancellable, &local_error);
+ connection = camel_ews_store_ref_connection (ews_store);
- g_object_unref (connection);
+ success = e_ews_connection_delete_folder_sync (
+ connection,
+ EWS_PRIORITY_MEDIUM,
+ fid, FALSE, "HardDelete",
+ cancellable, &local_error);
+
+ g_object_unref (connection);
+ }
if (!success) {
camel_ews_store_maybe_disconnect (ews_store, local_error);
@@ -853,11 +1134,15 @@ ews_delete_folder_sync (CamelStore *store,
fi = camel_ews_utils_build_folder_info (ews_store, fid);
camel_ews_store_summary_remove_folder (ews_summary, fid, error);
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
camel_store_folder_deleted (store, fi);
camel_folder_info_free (fi);
g_free (fid);
+ camel_ews_store_ensure_virtual_folders (ews_store);
+ camel_ews_store_summary_save (ews_store->summary, NULL);
+
return TRUE;
}
@@ -1184,6 +1469,98 @@ ews_can_refresh_folder (CamelStore *store,
can_refresh_folder (store, info, error);
}
+static gboolean
+ews_store_folder_is_subscribed (CamelSubscribable *subscribable,
+ const gchar *folder_name)
+{
+ CamelEwsStore *ews_store = CAMEL_EWS_STORE (subscribable);
+ gchar *fid;
+ gboolean truth = FALSE;
+ GError *error = NULL;
+
+ fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, folder_name);
+ if (!fid)
+ return FALSE;
+
+ if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, &error) && !error) {
+ truth = TRUE;
+ }
+
+ g_clear_error (&error);
+ g_free (fid);
+
+ return truth;
+}
+
+static gboolean
+ews_store_subscribe_folder_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelEwsStore *ews_store = CAMEL_EWS_STORE (subscribable);
+
+ if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot subscribe EWS folders in offline mode"));
+ return FALSE;
+ }
+
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Folder '%s' not found"), folder_name);
+
+ return TRUE;
+}
+
+static gboolean
+ews_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelEwsStore *ews_store = CAMEL_EWS_STORE (subscribable);
+ gboolean res = TRUE;
+ gchar *fid;
+
+ if (!camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
+ g_set_error_literal (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot unsubscribe EWS folders in offline mode"));
+ return FALSE;
+ }
+
+ fid = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, folder_name);
+ 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)) {
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR, CAMEL_SERVICE_ERROR_UNAVAILABLE,
+ _("Cannot subscribe EWS folder '%s'"), folder_name);
+ res = FALSE;
+ } else {
+ CamelFolderInfo *fi;
+
+ fi = camel_ews_utils_build_folder_info (ews_store, fid);
+ camel_ews_store_summary_remove_folder (ews_store->summary, fid, error);
+
+ 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_summary_save (ews_store->summary, NULL);
+ }
+
+ g_free (fid);
+
+ return res;
+}
+
gboolean
camel_ews_store_connected (CamelEwsStore *ews_store,
GError **error)
@@ -1296,6 +1673,14 @@ camel_ews_store_class_init (CamelEwsStoreClass *class)
}
static void
+camel_ews_subscribable_init (CamelSubscribableInterface *interface)
+{
+ interface->folder_is_subscribed = ews_store_folder_is_subscribed;
+ interface->subscribe_folder_sync = ews_store_subscribe_folder_sync;
+ interface->unsubscribe_folder_sync = ews_store_unsubscribe_folder_sync;
+}
+
+static void
camel_ews_store_init (CamelEwsStore *ews_store)
{
ews_store->priv =
diff --git a/src/camel/camel-ews-store.h b/src/camel/camel-ews-store.h
index 37b2bf3..d4115a3 100644
--- a/src/camel/camel-ews-store.h
+++ b/src/camel/camel-ews-store.h
@@ -51,6 +51,9 @@
#define EWS_PARAM_FILTER_INBOX (1 << 0)
+#define EWS_FOREIGN_FOLDER_ROOT_ID "ForeignRoot"
+#define EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME _("Foreign Folders")
+
G_BEGIN_DECLS
typedef struct _CamelEwsStore CamelEwsStore;
@@ -79,6 +82,11 @@ gboolean camel_ews_store_connected (CamelEwsStore *store,
void camel_ews_store_maybe_disconnect
(CamelEwsStore *store,
const GError *error);
+void camel_ews_store_ensure_virtual_folders
+ (CamelEwsStore *ews_store);
+void camel_ews_store_ensure_unique_path
+ (CamelEwsStore *ews_store,
+ gchar **ppath);
G_END_DECLS
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index e1e5cc8..c783c8b 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -339,6 +339,8 @@ sync_deleted_folders (CamelEwsStore *store,
fi = camel_ews_utils_build_folder_info (store, fid);
camel_ews_store_summary_remove_folder (ews_summary, fid, &error);
+
+ camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (store), fi);
camel_store_folder_deleted ((CamelStore *) store, fi);
g_clear_error (&error);
@@ -476,7 +478,8 @@ add_folder_to_summary (CamelEwsStore *store,
camel_ews_store_summary_new_folder (
ews_summary, fid->id,
pfid->id, fid->change_key,
- dname, ftype, 0, total);
+ dname, ftype, 0, total,
+ e_ews_folder_get_foreign (folder));
camel_ews_store_summary_set_folder_unread (ews_summary, fid->id, unread);
}
@@ -508,6 +511,7 @@ sync_created_folders (CamelEwsStore *ews_store,
if (ftype == E_EWS_FOLDER_TYPE_MAILBOX) {
fi = camel_ews_utils_build_folder_info (ews_store, fid->id);
camel_store_folder_created ((CamelStore *) ews_store, fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
camel_folder_info_free (fi);
}
}
diff --git a/src/camel/camel-ews-utils.h b/src/camel/camel-ews-utils.h
index 6916fa7..5ee80c3 100644
--- a/src/camel/camel-ews-utils.h
+++ b/src/camel/camel-ews-utils.h
@@ -83,7 +83,7 @@ void ews_utils_sync_folders (CamelEwsStore *ews_store,
CamelFolderInfo *
camel_ews_utils_build_folder_info (CamelEwsStore *store,
- const gchar *fname);
+ const gchar *fid);
void camel_ews_utils_sync_deleted_items (CamelEwsFolder *ews_folder,
GSList *items_deleted);
diff --git a/src/collection/e-ews-backend.c b/src/collection/e-ews-backend.c
index f7d0824..907c46f 100644
--- a/src/collection/e-ews-backend.c
+++ b/src/collection/e-ews-backend.c
@@ -656,7 +656,7 @@ ews_backend_create_resource_sync (ECollectionBackend *backend,
GCancellable *cancellable,
GError **error)
{
- EEwsConnection *connection;
+ EEwsConnection *connection = NULL;
EwsFolderId *out_folder_id = NULL;
EEwsFolderType folder_type = E_EWS_FOLDER_TYPE_UNKNOWN;
const gchar *extension_name;
@@ -664,68 +664,80 @@ ews_backend_create_resource_sync (ECollectionBackend *backend,
gchar *folder_name;
gboolean success = FALSE;
- connection = e_ews_backend_ref_connection_sync (
- E_EWS_BACKEND (backend), cancellable, error);
- if (connection == NULL)
- return FALSE;
-
- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+ extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
if (e_source_has_extension (source, extension_name)) {
- folder_type = E_EWS_FOLDER_TYPE_CONTACTS;
- parent_folder_id = "contacts";
- }
+ ESourceEwsFolder *extension;
- extension_name = E_SOURCE_EXTENSION_CALENDAR;
- if (e_source_has_extension (source, extension_name)) {
- folder_type = E_EWS_FOLDER_TYPE_CALENDAR;
- parent_folder_id = "calendar";
+ /* foreign folders are just added */
+ extension = e_source_get_extension (source, extension_name);
+ if (e_source_ews_folder_get_foreign (extension))
+ success = TRUE;
}
- extension_name = E_SOURCE_EXTENSION_TASK_LIST;
- if (e_source_has_extension (source, extension_name)) {
- folder_type = E_EWS_FOLDER_TYPE_TASKS;
- parent_folder_id = "tasks";
- }
+ if (!success) {
+ connection = e_ews_backend_ref_connection_sync (
+ E_EWS_BACKEND (backend), cancellable, error);
+ if (connection == NULL)
+ return FALSE;
- /* FIXME No support for memo lists. */
+ extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+ if (e_source_has_extension (source, extension_name)) {
+ folder_type = E_EWS_FOLDER_TYPE_CONTACTS;
+ parent_folder_id = "contacts";
+ }
- if (parent_folder_id == NULL) {
- g_set_error (
- error, G_IO_ERROR,
- G_IO_ERROR_INVALID_ARGUMENT,
- _("Could not determine a suitable folder "
- "class for a new folder named '%s'"),
- e_source_get_display_name (source));
- goto exit;
- }
+ extension_name = E_SOURCE_EXTENSION_CALENDAR;
+ if (e_source_has_extension (source, extension_name)) {
+ folder_type = E_EWS_FOLDER_TYPE_CALENDAR;
+ parent_folder_id = "calendar";
+ }
- folder_name = e_source_dup_display_name (source);
+ extension_name = E_SOURCE_EXTENSION_TASK_LIST;
+ if (e_source_has_extension (source, extension_name)) {
+ folder_type = E_EWS_FOLDER_TYPE_TASKS;
+ parent_folder_id = "tasks";
+ }
- success = e_ews_connection_create_folder_sync (
- connection, EWS_PRIORITY_MEDIUM,
- parent_folder_id, TRUE,
- folder_name, folder_type,
- &out_folder_id, cancellable, error);
+ /* FIXME No support for memo lists. */
- g_free (folder_name);
+ if (parent_folder_id == NULL) {
+ g_set_error (
+ error, G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Could not determine a suitable folder "
+ "class for a new folder named '%s'"),
+ e_source_get_display_name (source));
+ goto exit;
+ }
- /* Sanity check */
- g_warn_if_fail (
- (success && out_folder_id != NULL) ||
- (!success && out_folder_id == NULL));
+ folder_name = e_source_dup_display_name (source);
- if (out_folder_id != NULL) {
- ESourceEwsFolder *extension;
- const gchar *extension_name;
+ success = e_ews_connection_create_folder_sync (
+ connection, EWS_PRIORITY_MEDIUM,
+ parent_folder_id, TRUE,
+ folder_name, folder_type,
+ &out_folder_id, cancellable, error);
- extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
- extension = e_source_get_extension (source, extension_name);
- e_source_ews_folder_set_id (
- extension, out_folder_id->id);
- e_source_ews_folder_set_change_key (
- extension, out_folder_id->change_key);
+ g_free (folder_name);
+
+ /* Sanity check */
+ g_warn_if_fail (
+ (success && out_folder_id != NULL) ||
+ (!success && out_folder_id == NULL));
+
+ if (out_folder_id != NULL) {
+ ESourceEwsFolder *extension;
+ const gchar *extension_name;
- e_ews_folder_id_free (out_folder_id);
+ extension_name = E_SOURCE_EXTENSION_EWS_FOLDER;
+ extension = e_source_get_extension (source, extension_name);
+ e_source_ews_folder_set_id (
+ extension, out_folder_id->id);
+ e_source_ews_folder_set_change_key (
+ extension, out_folder_id->change_key);
+
+ e_ews_folder_id_free (out_folder_id);
+ }
}
if (success) {
@@ -755,8 +767,9 @@ ews_backend_create_resource_sync (ECollectionBackend *backend,
g_object_unref (server);
}
-exit:
- g_object_unref (connection);
+ exit:
+ if (connection)
+ g_object_unref (connection);
return success;
}
@@ -770,7 +783,6 @@ ews_backend_delete_resource_sync (ECollectionBackend *backend,
EEwsConnection *connection;
ESourceEwsFolder *extension;
const gchar *extension_name;
- gchar *folder_id;
gboolean success = FALSE;
connection = e_ews_backend_ref_connection_sync (
@@ -789,11 +801,22 @@ ews_backend_delete_resource_sync (ECollectionBackend *backend,
goto exit;
}
extension = e_source_get_extension (source, extension_name);
- folder_id = e_source_ews_folder_dup_id (extension);
- success = e_ews_connection_delete_folder_sync (
- connection, EWS_PRIORITY_MEDIUM, folder_id,
- FALSE, "HardDelete", cancellable, error);
+ if (e_source_ews_folder_get_foreign (extension)) {
+ /* do not delete foreign folders,
+ just remove them from local store */
+ success = TRUE;
+ } else {
+ gchar *folder_id;
+
+ folder_id = e_source_ews_folder_dup_id (extension);
+
+ success = e_ews_connection_delete_folder_sync (
+ connection, EWS_PRIORITY_MEDIUM, folder_id,
+ FALSE, "HardDelete", cancellable, error);
+
+ g_free (folder_id);
+ }
if (success) {
ESourceRegistryServer *server;
diff --git a/src/configuration/Makefile.am b/src/configuration/Makefile.am
index 9c059ae..ad5f142 100644
--- a/src/configuration/Makefile.am
+++ b/src/configuration/Makefile.am
@@ -38,6 +38,8 @@ module_ews_configuration_la_SOURCES = \
e-ews-edit-folder-permissions.h \
e-ews-search-user.c \
e-ews-search-user.h \
+ e-ews-subscribe-foreign-folder.c \
+ e-ews-subscribe-foreign-folder.h \
$(NULL)
module_ews_configuration_la_LIBADD = \
diff --git a/src/configuration/e-ews-config-utils.c b/src/configuration/e-ews-config-utils.c
index 4bcd550..17bead9 100644
--- a/src/configuration/e-ews-config-utils.c
+++ b/src/configuration/e-ews-config-utils.c
@@ -47,6 +47,7 @@
#include "e-ews-config-utils.h"
#include "e-ews-search-user.h"
+#include "e-ews-subscribe-foreign-folder.h"
struct RunWithFeedbackData
{
@@ -107,8 +108,11 @@ run_with_feedback_idle (gpointer user_data)
}
if (!was_cancelled) {
- if (rfd->error)
+ if (rfd->error) {
+ g_dbus_error_strip_remote_error (rfd->error);
+
e_notice (rfd->parent, GTK_MESSAGE_ERROR, "%s", rfd->error->message);
+ }
}
free_run_with_feedback_data (rfd);
@@ -458,7 +462,6 @@ get_ews_store_from_folder_tree (EShellView *shell_view,
return found;
}
-#if 0
static void
action_subscribe_foreign_folder_cb (GtkAction *action,
EShellView *shell_view)
@@ -479,9 +482,7 @@ action_subscribe_foreign_folder_cb (GtkAction *action,
g_object_unref (session);
g_object_unref (store);
- g_free (profile);
}
-#endif
static void
action_folder_permissions_mail_cb (GtkAction *action,
@@ -580,17 +581,15 @@ ews_ui_enable_actions (GtkActionGroup *action_group,
}
}
-#if 0
static GtkActionEntry mail_account_context_entries[] = {
{ "mail-ews-subscribe-foreign-folder",
NULL,
N_("Subscribe to folder of other user..."),
NULL,
- NULL, / * XXX Add a tooltip! * /
+ NULL, /* XXX Add a tooltip! */
G_CALLBACK (action_subscribe_foreign_folder_cb) }
};
-#endif
static GtkActionEntry mail_folder_context_entries[] = {
{ "mail-ews-folder-permissions",
@@ -604,7 +603,7 @@ static GtkActionEntry mail_folder_context_entries[] = {
static const gchar *ews_ui_mail_def =
"<popup name=\"mail-folder-popup\">\n"
" <placeholder name=\"mail-folder-popup-actions\">\n"
- /*" <menuitem action=\"mail-ews-subscribe-foreign-folder\"/>\n"*/
+ " <menuitem action=\"mail-ews-subscribe-foreign-folder\"/>\n"
" <menuitem action=\"mail-ews-folder-permissions\"/>\n"
" </placeholder>\n"
"</popup>\n";
@@ -659,7 +658,7 @@ ews_ui_update_actions_mail_cb (EShellView *shell_view,
g_object_unref (session);
}
- /* ews_ui_enable_actions (action_group, mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), account_node, online); */
+ ews_ui_enable_actions (action_group, mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), account_node, online);
ews_ui_enable_actions (action_group, mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), folder_node, online);
}
@@ -679,8 +678,8 @@ ews_ui_init_mail (GtkUIManager *ui_manager,
action_group = e_shell_window_get_action_group (shell_window, "mail");
/* Add actions to the "mail" action group. */
- /*e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
- mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), shell_view);*/
+ e_action_group_add_actions_localized (action_group, GETTEXT_PACKAGE,
+ mail_account_context_entries, G_N_ELEMENTS (mail_account_context_entries), shell_view);
e_action_group_add_actions_localized (
action_group, GETTEXT_PACKAGE,
mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), shell_view);
diff --git a/src/configuration/e-ews-subscribe-foreign-folder.c b/src/configuration/e-ews-subscribe-foreign-folder.c
new file mode 100644
index 0000000..ab2bdda
--- /dev/null
+++ b/src/configuration/e-ews-subscribe-foreign-folder.c
@@ -0,0 +1,716 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libedataserverui/libedataserverui.h>
+#include <libemail-engine/e-mail-session.h>
+
+#include "camel/camel-ews-store.h"
+#include "camel/camel-ews-store-summary.h"
+#include "camel/camel-ews-utils.h"
+
+#include "e-ews-config-utils.h"
+#include "e-ews-search-user.h"
+#include "e-ews-subscribe-foreign-folder.h"
+
+#define STR_USER_NAME_SELECTOR_ENTRY "e-ews-name-selector-entry"
+#define STR_FOLDER_NAME_COMBO "e-ews-folder-name-combo"
+#define STR_EWS_CAMEL_SESSION "e-ews-camel-session"
+#define STR_EWS_CAMEL_STORE "e-ews-camel-store"
+#define STR_EWS_DIRECT_EMAIL "e-ews-direct-email"
+
+static void
+announce_new_folder (CamelEwsStore *ews_store,
+ const gchar *fid)
+{
+ CamelFolderInfo *fi;
+
+ g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
+ g_return_if_fail (fid != NULL);
+ g_return_if_fail (camel_ews_store_summary_has_folder (ews_store->summary, fid));
+
+ fi = camel_ews_utils_build_folder_info (ews_store, fid);
+ camel_store_folder_created (CAMEL_STORE (ews_store), fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (ews_store), fi);
+ camel_folder_info_free (fi);
+}
+
+static gboolean
+add_foreign_folder_to_camel (CamelEwsStore *ews_store,
+ const gchar *foreign_email,
+ EEwsFolder *folder,
+ const gchar *display_username,
+ const gchar *display_foldername,
+ GError **perror)
+{
+ gchar *foreign_mailbox_id;
+ gchar *mailbox, *fullname;
+ const EwsFolderId *fid, *parent_fid;
+
+ g_return_val_if_fail (ews_store != NULL, FALSE);
+ g_return_val_if_fail (ews_store->summary != NULL, FALSE);
+ g_return_val_if_fail (foreign_email != NULL, FALSE);
+ g_return_val_if_fail (folder != NULL, FALSE);
+ g_return_val_if_fail (display_username != NULL, FALSE);
+ g_return_val_if_fail (display_foldername != NULL, FALSE);
+
+ fid = e_ews_folder_get_id (folder);
+ parent_fid = e_ews_folder_get_parent_id (folder);
+
+ g_return_val_if_fail (fid != NULL, FALSE);
+ g_return_val_if_fail (parent_fid != NULL, FALSE);
+ g_return_val_if_fail (g_strcmp0 (fid->id, parent_fid->id) != 0, FALSE);
+
+ if (camel_ews_store_summary_has_folder (ews_store->summary, fid->id)) {
+ gchar *full_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, fid->id, NULL);
+
+ g_propagate_error (perror,
+ g_error_new (EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDEREXISTS,
+ _("Cannot add folder, folder already exists as '%s'"), full_name));
+
+ g_free (full_name);
+
+ return FALSE;
+ }
+
+ /* Translators: The '%s' is replaced with user name, to whom the foreign mailbox belongs.
+ Example result: "Mailbox - John Smith"
+ */
+ mailbox = g_strdup_printf (C_("ForeignFolder", "Mailbox - %s"), display_username);
+
+ foreign_mailbox_id = g_strdup_printf ("ForeignMailbox::%s", foreign_email);
+ if (!camel_ews_store_summary_has_folder (ews_store->summary, foreign_mailbox_id)) {
+ camel_ews_store_summary_new_folder (ews_store->summary,
+ foreign_mailbox_id, EWS_FOREIGN_FOLDER_ROOT_ID, NULL,
+ mailbox, E_EWS_FOLDER_TYPE_MAILBOX,
+ CAMEL_FOLDER_SYSTEM | CAMEL_FOLDER_NOSELECT,
+ 0, FALSE);
+ }
+
+ if (camel_ews_store_summary_has_folder (ews_store->summary, parent_fid->id)) {
+ camel_ews_store_summary_new_folder (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);
+ } else {
+ const gchar *displayname;
+
+ fullname = g_strdup_printf ("%s/%s/%s", EWS_FOREIGN_FOLDER_ROOT_DISPLAY_NAME, mailbox, display_foldername);
+
+ /* make sure the path is unique */
+ camel_ews_store_ensure_unique_path (ews_store, &fullname);
+
+ displayname = strrchr (fullname, '/');
+ displayname++;
+
+ camel_ews_store_summary_new_folder (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);
+
+ g_free (fullname);
+ }
+
+ camel_ews_store_ensure_virtual_folders (ews_store);
+
+ announce_new_folder (ews_store, EWS_FOREIGN_FOLDER_ROOT_ID);
+ announce_new_folder (ews_store, foreign_mailbox_id);
+ announce_new_folder (ews_store, fid->id);
+
+ g_free (foreign_mailbox_id);
+ g_free (mailbox);
+
+ return TRUE;
+}
+
+static void
+enable_ok_button_by_data (GObject *dialog)
+{
+ GtkEntry *entry;
+ GtkComboBoxText *combo;
+ const gchar *entry_text;
+ gchar *combo_text;
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ g_return_if_fail (entry != NULL);
+
+ combo = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
+ g_return_if_fail (combo != NULL);
+
+ entry_text = gtk_entry_get_text (entry);
+ combo_text = gtk_combo_box_text_get_active_text (combo);
+
+ gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK,
+ entry_text && *entry_text && *entry_text != ' ' && *entry_text != ',' &&
+ combo_text && *combo_text);
+
+ g_free (combo_text);
+}
+
+static void
+name_entry_changed_cb (GObject *dialog)
+{
+ GtkEntry *entry;
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ g_return_if_fail (entry != NULL);
+
+ g_object_set_data (G_OBJECT (entry), STR_EWS_DIRECT_EMAIL, NULL);
+
+ enable_ok_button_by_data (dialog);
+}
+
+static void
+folder_name_combo_changed_cb (GObject *dialog)
+{
+ enable_ok_button_by_data (dialog);
+}
+
+struct EEwsCheckForeignFolderData
+{
+ GtkWidget *dialog;
+ gchar *email;
+ gchar *direct_email;
+ gchar *user_displayname;
+ gchar *orig_foldername;
+ gchar *use_foldername;
+ EEwsFolder *folder;
+};
+
+static void
+e_ews_check_foreign_folder_data_free (gpointer ptr)
+{
+ struct EEwsCheckForeignFolderData *cffd = ptr;
+
+ if (!cffd)
+ return;
+
+ g_free (cffd->email);
+ g_free (cffd->direct_email);
+ g_free (cffd->user_displayname);
+ g_free (cffd->orig_foldername);
+ g_free (cffd->use_foldername);
+
+ /* folder tells whether successfully finished,
+ then the dialog can be destroyed */
+ if (cffd->folder && cffd->dialog)
+ gtk_widget_destroy (cffd->dialog);
+
+ if (cffd->folder)
+ g_object_unref (cffd->folder);
+
+ g_free (cffd);
+}
+
+static void
+check_foreign_folder_thread (GObject *with_object,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EEwsCheckForeignFolderData *cffd = user_data;
+ GError *local_error = NULL;
+ EEwsConnection *conn;
+ EwsFolderId fid;
+ EEwsFolder *folder = NULL;
+
+ g_return_if_fail (with_object != NULL);
+ g_return_if_fail (CAMEL_IS_EWS_STORE (with_object));
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (cffd->email != NULL);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror))
+ return;
+
+ conn = camel_ews_store_ref_connection (CAMEL_EWS_STORE (with_object));
+ if (!conn) {
+ g_set_error_literal (
+ perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_NORESPONSE,
+ _("Cannot test foreign folder availability while in offline mode"));
+ return;
+ }
+
+ if (cffd->direct_email && *cffd->direct_email) {
+ g_return_if_fail (cffd->user_displayname == NULL);
+
+ cffd->user_displayname = cffd->email;
+ cffd->email = g_strdup (cffd->direct_email);
+ } else {
+ GSList *mailboxes = NULL;
+ EwsMailbox *mailbox = NULL;
+ gboolean includes_last_item = FALSE;
+
+ if (!e_ews_connection_resolve_names_sync (conn, G_PRIORITY_DEFAULT,
+ cffd->email, EWS_SEARCH_AD, NULL, FALSE,
+ &mailboxes, NULL, &includes_last_item,
+ cancellable, perror)) {
+ g_object_unref (conn);
+ return;
+ }
+
+ if (!mailboxes) {
+ g_set_error (
+ perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_MAILRECIPIENTNOTFOUND,
+ _("User '%s' was not found on the server"), cffd->email);
+ g_object_unref (conn);
+ return;
+ }
+
+ /* is there only one result? */
+ if (mailboxes->next == NULL) {
+ mailbox = mailboxes->data;
+ } else {
+ GSList *iter;
+
+ for (iter = mailboxes; iter; iter = iter->next) {
+ EwsMailbox *mb = iter->data;
+
+ if (!mb)
+ continue;
+
+ if (mb->name && g_utf8_collate (mb->name, cffd->email) == 0) {
+ mailbox = mb;
+ break;
+ }
+ }
+ }
+
+ if (mailbox) {
+ g_free (cffd->user_displayname);
+ cffd->user_displayname = g_strdup (mailbox->name);
+ g_free (cffd->email);
+ cffd->email = g_strdup (mailbox->email);
+ }
+
+ g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free);
+
+ if (!mailbox) {
+ g_set_error (
+ perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND,
+ _("User name '%s' is ambiguous, specify it more precisely, please"), cffd->email);
+ g_object_unref (conn);
+ return;
+ }
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ g_object_unref (conn);
+ return;
+ }
+
+ fid.id = (gchar *) (cffd->use_foldername ? cffd->use_foldername : cffd->orig_foldername);
+ fid.change_key = NULL;
+ fid.is_distinguished_id = cffd->use_foldername != NULL;
+
+ if (!e_ews_connection_get_folder_info_sync (conn, G_PRIORITY_DEFAULT,
+ cffd->email, &fid, &folder, cancellable, &local_error)) {
+ if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND) ||
+ g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND)) {
+ g_clear_error (&local_error);
+ local_error = g_error_new (EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND,
+ _("Folder '%s' not found. Either it does not exist or you do not have permission to access it."),
+ cffd->orig_foldername);
+ }
+
+ g_propagate_error (perror, local_error);
+ g_object_unref (conn);
+ return;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ g_object_unref (folder);
+ g_object_unref (conn);
+ return;
+ }
+
+ if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_UNKNOWN) {
+ g_propagate_error (perror, g_error_new_literal (EWS_CONNECTION_ERROR,
+ EWS_CONNECTION_ERROR_FOLDERNOTFOUND, _("Cannot add folder, cannot determine folder's type")));
+ g_object_unref (folder);
+ g_object_unref (conn);
+ return;
+ }
+
+ e_ews_folder_set_foreign (folder, TRUE);
+
+ cffd->folder = folder;
+ g_object_unref (conn);
+}
+
+static void
+check_foreign_folder_idle (GObject *with_object,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ struct EEwsCheckForeignFolderData *cffd = user_data;
+ gchar *folder_name;
+ const gchar *base_username, *base_foldername;
+ CamelSettings *settings;
+ CamelEwsSettings *ews_settings;
+ CamelEwsStore *ews_store;
+ ESourceRegistry *registry = NULL;
+ CamelSession *session;
+ EEwsFolderType folder_type;
+
+ g_return_if_fail (with_object != NULL);
+ g_return_if_fail (CAMEL_IS_EWS_STORE (with_object));
+ g_return_if_fail (user_data != NULL);
+ g_return_if_fail (cffd->email != NULL);
+
+ if (!cffd->folder)
+ return;
+
+ folder_type = e_ews_folder_get_folder_type (cffd->folder);
+ base_username = cffd->user_displayname ? cffd->user_displayname : cffd->email;
+ base_foldername = e_ews_folder_get_name (cffd->folder) ? e_ews_folder_get_name (cffd->folder) : cffd->orig_foldername;
+
+ /* Translators: This is used to name foreign folder.
+ The first '%s' is replaced with user name to whom the folder belongs,
+ the second '%s' is replaced with folder name.
+ Example result: "John Smith - Calendar"
+ */
+ folder_name = g_strdup_printf (C_("ForeignFolder", "%s - %s"), base_username, base_foldername);
+ if (folder_type != E_EWS_FOLDER_TYPE_MAILBOX)
+ e_ews_folder_set_name (cffd->folder, folder_name);
+
+ ews_store = CAMEL_EWS_STORE (with_object);
+ 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));
+
+ if ((folder_type == E_EWS_FOLDER_TYPE_MAILBOX &&
+ !add_foreign_folder_to_camel (ews_store,
+ cffd->email,
+ cffd->folder,
+ base_username,
+ base_foldername,
+ perror)) ||
+ (folder_type != E_EWS_FOLDER_TYPE_MAILBOX && !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)),
+ cffd->folder,
+ TRUE,
+ 0,
+ cancellable,
+ perror))
+ ) {
+ /* to not destroy the dialog on error */
+ g_object_unref (cffd->folder);
+ cffd->folder = NULL;
+ }
+
+ g_free (folder_name);
+ g_object_unref (settings);
+}
+
+static void
+subscribe_foreign_response_cb (GObject *dialog,
+ gint response_id)
+{
+ struct EEwsCheckForeignFolderData *cffd;
+ ENameSelectorEntry *entry;
+ GtkComboBoxText *combo_text;
+ EDestinationStore *dest_store;
+ CamelStore *cstore;
+ gchar *description;
+ const gchar *username;
+ gchar *orig_foldername, *use_foldername = NULL, *show_foldername = NULL;
+
+ if (response_id != GTK_RESPONSE_OK) {
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return;
+ }
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ combo_text = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
+ cstore = g_object_get_data (dialog, STR_EWS_CAMEL_STORE);
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (cstore != NULL);
+
+ username = NULL;
+ dest_store = e_name_selector_entry_peek_destination_store (entry);
+ if (dest_store && e_destination_store_get_destination_count (dest_store) > 0) {
+ EDestination *dest;
+ GList *dests = e_destination_store_list_destinations (dest_store);
+
+ g_return_if_fail (dests != NULL);
+
+ /* pick the first, there is no option to limit to only one destination */
+ dest = dests->data;
+ if (dest) {
+ username = e_destination_get_email (dest);
+ if (!username || !*username)
+ username = e_destination_get_name (dest);
+ }
+
+ g_list_free (dests);
+ }
+
+ if (!username || !*username)
+ username = gtk_entry_get_text (GTK_ENTRY (entry));
+
+ orig_foldername = gtk_combo_box_text_get_active_text (combo_text);
+ if (!orig_foldername)
+ orig_foldername = g_strdup ("");
+
+ /* convert well-known names to their non-localized form */
+ if (g_strcmp0 (orig_foldername, _("Inbox")) == 0) {
+ use_foldername = g_strdup ("inbox");
+ } else if (g_strcmp0 (orig_foldername, _("Contacts")) == 0) {
+ use_foldername = g_strdup ("contacts");
+ } else if (g_strcmp0 (orig_foldername, _("Calendar")) == 0) {
+ use_foldername = g_strdup ("calendar");
+ } else if (g_strcmp0 (orig_foldername, _("Memos")) == 0) {
+ use_foldername = g_strdup ("notes");
+ } else if (g_strcmp0 (orig_foldername, _("Tasks")) == 0) {
+ use_foldername = g_strdup ("tasks");
+ } else if (strlen (orig_foldername) > 13) {
+ /* if its a folder ID, then show only first 10 letters of it */
+ show_foldername = g_strdup_printf ("%.10s...", orig_foldername);
+ }
+
+ cffd = g_new0 (struct EEwsCheckForeignFolderData, 1);
+ cffd->dialog = GTK_WIDGET (dialog);
+ cffd->email = g_strdup (username ? username : "");
+ cffd->direct_email = g_strdup (g_object_get_data (G_OBJECT (entry), STR_EWS_DIRECT_EMAIL));
+ cffd->orig_foldername = orig_foldername;
+ cffd->use_foldername = use_foldername;
+ cffd->folder = NULL;
+
+ description = g_strdup_printf (_("Testing availability of folder '%s' of user '%s', please wait..."),
+ show_foldername ? show_foldername : cffd->orig_foldername, cffd->email);
+
+ e_ews_config_utils_run_in_thread_with_feedback (
+ GTK_WINDOW (dialog),
+ G_OBJECT (cstore),
+ description,
+ check_foreign_folder_thread,
+ check_foreign_folder_idle,
+ cffd,
+ e_ews_check_foreign_folder_data_free);
+
+ g_free (description);
+ g_free (show_foldername);
+}
+
+static void
+pick_gal_user_clicked_cb (GtkButton *button,
+ GObject *dialog)
+{
+ GtkEntry *entry;
+ CamelEwsStore *ews_store;
+ EEwsConnection *conn;
+ gchar *text, *display_name = NULL, *email = NULL;
+
+ g_return_if_fail (dialog != NULL);
+
+ entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
+ ews_store = g_object_get_data (dialog, STR_EWS_CAMEL_STORE);
+
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (ews_store != NULL);
+
+ text = g_strstrip (g_strdup (gtk_entry_get_text (entry)));
+ conn = camel_ews_store_ref_connection (ews_store);
+
+ if (e_ews_search_user_modal (GTK_WINDOW (dialog),
+ conn,
+ text,
+ &display_name,
+ &email)) {
+ if (display_name && email && *email) {
+ gtk_entry_set_text (entry, display_name);
+ g_object_set_data_full (G_OBJECT (entry), STR_EWS_DIRECT_EMAIL, g_strdup (email), g_free);
+ }
+ }
+
+ g_free (text);
+ g_free (display_name);
+ g_free (email);
+ g_object_unref (conn);
+}
+
+/* Opens dialog to subscribe to folders of other
+ users in the given store */
+void
+e_ews_subscribe_foreign_folder (GtkWindow *parent,
+ CamelSession *session,
+ CamelStore *store)
+{
+ PangoAttrList *attrs;
+ ENameSelector *name_selector;
+ ENameSelectorModel *name_selector_model;
+ ENameSelectorDialog *name_selector_dialog;
+ GObject *dialog;
+ GtkWidget *content;
+ GtkWidget *label, *widget, *entry;
+ GtkGrid *grid;
+ GtkComboBoxText *combo_text;
+ gint row;
+
+ g_return_if_fail (session != NULL);
+ g_return_if_fail (store != NULL);
+ g_return_if_fail (CAMEL_IS_EWS_STORE (store));
+
+ dialog = G_OBJECT (gtk_dialog_new_with_buttons (
+ _("Subscribe to folder of other EWS user..."),
+ parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ NULL));
+
+ g_signal_connect (dialog, "response", G_CALLBACK (subscribe_foreign_response_cb), NULL);
+
+ content = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+
+ grid = GTK_GRID (gtk_grid_new ());
+ gtk_grid_set_row_homogeneous (grid, FALSE);
+ gtk_grid_set_row_spacing (grid, 6);
+ gtk_grid_set_column_homogeneous (grid, FALSE);
+ gtk_grid_set_column_spacing (grid, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (grid), 12);
+ gtk_container_add (GTK_CONTAINER (content), GTK_WIDGET (grid));
+
+ row = 0;
+
+ label = gtk_label_new (_("Account:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ NULL);
+
+ attrs = pango_attr_list_new ();
+ pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD));
+ widget = gtk_label_new (camel_service_get_display_name (CAMEL_SERVICE (store)));
+ g_object_set (G_OBJECT (widget),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ "use-underline", FALSE,
+ "attributes", attrs,
+ "xalign", 0.0,
+ "halign", GTK_ALIGN_START,
+ NULL);
+ pango_attr_list_unref (attrs);
+
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, widget, 1, row, 2, 1);
+
+ row++;
+
+ name_selector = e_name_selector_new (e_mail_session_get_registry (E_MAIL_SESSION (session)));
+ name_selector_model = e_name_selector_peek_model (name_selector);
+ e_name_selector_model_add_section (name_selector_model, "User", _("User"), NULL);
+ name_selector_dialog = e_name_selector_peek_dialog (name_selector);
+ g_signal_connect (name_selector_dialog, "response", G_CALLBACK (gtk_widget_hide), name_selector);
+ e_name_selector_load_books (name_selector);
+
+ g_object_set_data_full (dialog, "e-ews-name-selector", name_selector, g_object_unref);
+
+ label = gtk_label_new_with_mnemonic (_("_User:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ NULL);
+
+ entry = GTK_WIDGET (e_name_selector_peek_section_entry (name_selector, "User"));
+ g_object_set (G_OBJECT (entry),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ NULL);
+
+ widget = gtk_button_new_with_mnemonic (_("C_hoose..."));
+ g_object_set (G_OBJECT (entry),
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ NULL);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry);
+ g_signal_connect (widget, "clicked", G_CALLBACK (pick_gal_user_clicked_cb), dialog);
+
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, entry, 1, row, 1, 1);
+ gtk_grid_attach (grid, widget, 2, row, 1, 1);
+
+ row++;
+
+ label = gtk_label_new_with_mnemonic (_("_Folder name:"));
+ g_object_set (G_OBJECT (label),
+ "hexpand", FALSE,
+ "vexpand", FALSE,
+ "xalign", 0.0,
+ NULL);
+
+ widget = GTK_WIDGET (g_object_new (gtk_combo_box_text_get_type (),
+ "has-entry", TRUE,
+ "entry-text-column", 0,
+ "hexpand", TRUE,
+ "vexpand", FALSE,
+ NULL));
+
+ combo_text = GTK_COMBO_BOX_TEXT (widget);
+ gtk_combo_box_text_append_text (combo_text, _("Inbox"));
+ gtk_combo_box_text_append_text (combo_text, _("Contacts"));
+ gtk_combo_box_text_append_text (combo_text, _("Calendar"));
+ gtk_combo_box_text_append_text (combo_text, _("Memos"));
+ gtk_combo_box_text_append_text (combo_text, _("Tasks"));
+ gtk_combo_box_set_active (GTK_COMBO_BOX (combo_text), 0);
+
+ gtk_label_set_mnemonic_widget (GTK_LABEL (label), widget);
+ gtk_grid_attach (grid, label, 0, row, 1, 1);
+ gtk_grid_attach (grid, widget, 1, row, 2, 1);
+
+ /* remember widgets for later use */
+ g_object_set_data (dialog, STR_USER_NAME_SELECTOR_ENTRY, entry);
+ g_object_set_data (dialog, STR_FOLDER_NAME_COMBO, widget);
+
+ g_object_set_data_full (dialog, STR_EWS_CAMEL_SESSION, g_object_ref (session), g_object_unref);
+ g_object_set_data_full (dialog, STR_EWS_CAMEL_STORE, g_object_ref (store), g_object_unref);
+
+ g_signal_connect_swapped (entry, "changed", G_CALLBACK (name_entry_changed_cb), dialog);
+ g_signal_connect_swapped (combo_text, "changed", G_CALLBACK (folder_name_combo_changed_cb), dialog);
+
+ name_entry_changed_cb (dialog);
+
+ gtk_widget_show_all (content);
+ gtk_widget_show (GTK_WIDGET (dialog));
+}
diff --git a/src/configuration/e-ews-subscribe-foreign-folder.h b/src/configuration/e-ews-subscribe-foreign-folder.h
new file mode 100644
index 0000000..04a7956
--- /dev/null
+++ b/src/configuration/e-ews-subscribe-foreign-folder.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Authors:
+ * Milan Crha <mcrha redhat com>
+ *
+ * Copyright (C) 2012 Red Hat, Inc. (www.redhat.com)
+ *
+ */
+
+#ifndef E_EWS_SUBSCRIBE_FOREIGN_FOLDER_H
+#define E_EWS_SUBSCRIBE_FOREIGN_FOLDER_H
+
+#include <gtk/gtk.h>
+#include <camel/camel.h>
+
+void e_ews_subscribe_foreign_folder (GtkWindow *parent,
+ CamelSession *session,
+ CamelStore *store);
+
+#endif /* E_EWS_SUBSCRIBE_FOREIGN_FOLDER_H */
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index 3099c57..a3c5739 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -3101,8 +3101,11 @@ ews_append_folder_ids_to_msg (ESoapMessage *msg,
if (fid->change_key)
e_soap_message_add_attribute (msg, "ChangeKey", fid->change_key, NULL, NULL);
- if (fid->is_distinguished_id && email)
- e_ews_message_write_string_parameter (msg, "Mailbox", NULL, email);
+ if (fid->is_distinguished_id && email) {
+ e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
+ e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, email);
+ e_soap_message_end_element (msg);
+ }
e_soap_message_end_element (msg);
}
@@ -7323,3 +7326,171 @@ e_ews_connection_get_password_expiration_sync (EEwsConnection *cnc,
return success;
}
+
+static void
+get_folder_info_response_cb (ESoapResponse *response,
+ GSimpleAsyncResult *simple)
+{
+ EwsAsyncData *async_data;
+ ESoapParameter *param;
+ ESoapParameter *subparam;
+ GError *error = NULL;
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ param = e_soap_response_get_first_parameter_by_name (
+ response, "ResponseMessages", &error);
+
+ /* Sanity check */
+ g_return_if_fail (
+ (param != NULL && error == NULL) ||
+ (param == NULL && error != NULL));
+
+ if (error != NULL) {
+ g_simple_async_result_take_error (simple, error);
+ return;
+ }
+
+ subparam = e_soap_parameter_get_first_child (param);
+
+ while (subparam != NULL) {
+ const gchar *name = (const gchar *) subparam->name;
+
+ if (!ews_get_response_status (subparam, &error)) {
+ g_simple_async_result_take_error (simple, error);
+ return;
+ }
+
+ if (CHECK_ELEMENT (name, "GetFolderResponseMessage")) {
+ ESoapParameter *node;
+
+ node = e_soap_parameter_get_first_child_by_name (subparam, "Folders");
+ if (node) {
+ EEwsFolder *folder = e_ews_folder_new_from_soap_parameter (node);
+
+ if (folder)
+ async_data->items = g_slist_prepend (NULL, folder);
+ }
+
+ break;
+ }
+
+ subparam = e_soap_parameter_get_next_child (subparam);
+ }
+}
+
+void
+e_ews_connection_get_folder_info (EEwsConnection *cnc,
+ gint pri,
+ const gchar *mail_id,
+ const EwsFolderId *folder_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ESoapMessage *msg;
+ GSimpleAsyncResult *simple;
+ EwsAsyncData *async_data;
+ GSList *folder_ids;
+
+ g_return_if_fail (cnc != NULL);
+ g_return_if_fail (folder_id != NULL);
+
+ msg = e_ews_message_new_with_header (cnc->priv->uri, "GetFolder", NULL, NULL, 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:ParentFolderId");
+ e_soap_message_end_element (msg); /* AdditionalProperties */
+ e_soap_message_end_element (msg); /* FolderShape */
+
+ folder_ids = g_slist_append (NULL, (gpointer) folder_id);
+ e_soap_message_start_element (msg, "FolderIds", "messages", NULL);
+ ews_append_folder_ids_to_msg (msg, mail_id, folder_ids);
+ e_soap_message_end_element (msg);
+ g_slist_free (folder_ids);
+
+ e_ews_message_write_footer (msg);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (cnc), callback, user_data,
+ e_ews_connection_get_folder_info);
+
+ async_data = g_new0 (EwsAsyncData, 1);
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_data, (GDestroyNotify) async_data_free);
+
+ e_ews_connection_queue_request (
+ cnc, msg, get_folder_info_response_cb,
+ pri, cancellable, simple);
+
+ g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_get_folder_info_finish (EEwsConnection *cnc,
+ GAsyncResult *result,
+ EEwsFolder **folder,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ EwsAsyncData *async_data;
+
+ g_return_val_if_fail (cnc != NULL, FALSE);
+ g_return_val_if_fail (folder != NULL, FALSE);
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (cnc), e_ews_connection_get_folder_info),
+ FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (!async_data->items)
+ return FALSE;
+
+ *folder = async_data->items ? async_data->items->data : NULL;
+
+ g_slist_free (async_data->items);
+ async_data->items = NULL;
+
+ return TRUE;
+}
+
+gboolean
+e_ews_connection_get_folder_info_sync (EEwsConnection *cnc,
+ gint pri,
+ const gchar *mail_id,
+ const EwsFolderId *folder_id,
+ EEwsFolder **folder,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (folder_id != NULL, FALSE);
+ g_return_val_if_fail (folder != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_ews_connection_get_folder_info (
+ cnc, pri, mail_id, folder_id, cancellable,
+ e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_ews_connection_get_folder_info_finish (
+ cnc, result, folder, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index 269f710..923bd30 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -931,6 +931,28 @@ gboolean e_ews_connection_get_password_expiration_sync
GCancellable *cancellable,
GError **error);
+void e_ews_connection_get_folder_info
+ (EEwsConnection *cnc,
+ gint pri,
+ const gchar *mail_id,
+ const EwsFolderId *folder_id,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_ews_connection_get_folder_info_finish
+ (EEwsConnection *cnc,
+ GAsyncResult *result,
+ EEwsFolder **folder,
+ GError **error);
+gboolean e_ews_connection_get_folder_info_sync
+ (EEwsConnection *cnc,
+ gint pri,
+ const gchar *mail_id,
+ const EwsFolderId *folder_id,
+ EEwsFolder **folder,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif
diff --git a/src/server/e-ews-folder.c b/src/server/e-ews-folder.c
index 7872549..77440d3 100644
--- a/src/server/e-ews-folder.c
+++ b/src/server/e-ews-folder.c
@@ -23,9 +23,14 @@
#include <config.h>
#endif
#include <string.h>
+#include <glib/gi18n-lib.h>
+
#include "e-ews-folder.h"
#include "e-ews-message.h"
#include "e-ews-enumtypes.h"
+#include "ews-errors.h"
+#include "e-source-ews-folder.h"
+#include "camel-ews-settings.h"
G_DEFINE_TYPE (EEwsFolder, e_ews_folder, G_TYPE_OBJECT)
@@ -38,6 +43,7 @@ struct _EEwsFolderPrivate {
guint32 unread;
guint32 total;
guint32 child_count;
+ gboolean foreign;
};
static GObjectClass *parent_class = NULL;
@@ -110,6 +116,7 @@ e_ews_folder_init (EEwsFolder *folder)
folder->priv = priv;
priv->folder_type = E_EWS_FOLDER_TYPE_MAILBOX;
+ priv->foreign = FALSE;
}
/* FIXME pick it from folder_type and make it set folder_type */
@@ -372,7 +379,6 @@ e_ews_folder_get_unread_count (EEwsFolder *folder)
g_return_val_if_fail (E_IS_EWS_FOLDER (folder), -1);
return folder->priv->unread;
-
}
guint32
@@ -381,5 +387,367 @@ e_ews_folder_get_child_count (EEwsFolder *folder)
g_return_val_if_fail (E_IS_EWS_FOLDER (folder), -1);
return folder->priv->child_count;
+}
+
+gboolean
+e_ews_folder_get_foreign (EEwsFolder *folder)
+{
+ g_return_val_if_fail (E_IS_EWS_FOLDER (folder), FALSE);
+
+ return folder->priv->foreign;
+}
+
+void
+e_ews_folder_set_foreign (EEwsFolder *folder,
+ gboolean is_foreign)
+{
+ g_return_if_fail (E_IS_EWS_FOLDER (folder));
+
+ folder->priv->foreign = is_foreign;
+}
+
+gchar *
+e_ews_folder_utils_pick_color_spec (gint move_by,
+ gboolean around_middle)
+{
+ static gint color_mover = 0;
+ static gint color_indexer = -1;
+ const guint32 colors[] = {
+ 0x1464ae, /* dark blue */
+ 0x14ae64, /* dark green */
+ 0xae1464, /* dark red */
+ 0
+ };
+ guint32 color;
+
+ if (move_by <= 0)
+ move_by = 1;
+
+ while (move_by > 0) {
+ move_by--;
+
+ color_indexer++;
+ if (colors[color_indexer] == 0) {
+ color_mover += 1;
+ color_indexer = 0;
+ }
+ }
+
+ color = colors[color_indexer];
+ color = (color & ~(0xFF << (color_indexer * 8))) |
+ (((((color >> (color_indexer * 8)) & 0xFF) + (0x33 * color_mover)) % 0xFF) << (color_indexer * 8));
+
+ if (around_middle) {
+ gint rr, gg, bb, diff;
+
+ rr = (0xFF0000 & color) >> 16;
+ gg = (0x00FF00 & color) >> 8;
+ bb = (0x0000FF & color);
+
+ diff = 0x80 - rr;
+ if (diff < 0x80 - gg)
+ diff = 0x80 - gg;
+ if (diff < 0x80 - bb)
+ diff = 0x80 - bb;
+
+ rr = rr + diff < 0 ? 0 : rr + diff > 0xCC ? 0xCC : rr + diff;
+ gg = gg + diff < 0 ? 0 : gg + diff > 0xCC ? 0xCC : gg + diff;
+ bb = bb + diff < 0 ? 0 : bb + diff > 0xCC ? 0xCC : bb + diff;
+
+ color = (rr << 16) + (gg << 8) + bb;
+ }
+
+ return g_strdup_printf ("#%06x", color);
+}
+
+gboolean
+e_ews_folder_utils_populate_esource (ESource *source,
+ const GList *sources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ EEwsFolder *folder,
+ gboolean offline_sync,
+ gint color_seed,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ ESource *master_source;
+ gboolean res = FALSE;
+
+ master_source = e_ews_folder_utils_get_master_source (sources, master_hosturl, master_username);
+
+ if (master_source) {
+ ESourceBackend *backend_ext;
+ EEwsFolderType folder_type;
+ const EwsFolderId *folder_id = e_ews_folder_get_id (folder);
+
+ g_return_val_if_fail (folder_id != NULL, FALSE);
+
+ folder_type = e_ews_folder_get_folder_type (folder);
+
+ e_source_set_parent (source, e_source_get_uid (master_source));
+ e_source_set_display_name (source, e_ews_folder_get_name (folder));
+
+ switch (folder_type) {
+ 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:
+ backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_MEMO_LIST);
+ break;*/
+ case E_EWS_FOLDER_TYPE_TASKS:
+ backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_TASK_LIST);
+ break;
+ case E_EWS_FOLDER_TYPE_CONTACTS:
+ backend_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK);
+ break;
+ default:
+ backend_ext = NULL;
+ break;
+ }
+
+ if (backend_ext) {
+ ESourceEwsFolder *folder_ext;
+ ESourceOffline *offline_ext;
+
+ e_source_backend_set_backend_name (backend_ext , "ews");
+
+ folder_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_EWS_FOLDER);
+ 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));
+
+ offline_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_OFFLINE);
+ e_source_offline_set_stay_synchronized (offline_ext, offline_sync);
+
+ /* set also color for calendar-like sources */
+ if (folder_type != E_EWS_FOLDER_TYPE_CONTACTS) {
+ gchar *color_str;
+
+ color_str = e_ews_folder_utils_pick_color_spec (1 + g_list_length ((GList *) sources),
+ folder_type != E_EWS_FOLDER_TYPE_CALENDAR);
+ e_source_selectable_set_color (E_SOURCE_SELECTABLE (backend_ext), color_str);
+ g_free (color_str);
+ }
+
+ res = TRUE;
+ } else {
+ g_propagate_error (perror, g_error_new_literal (EWS_CONNECTION_ERROR,
+ EWS_CONNECTION_ERROR_NORESPONSE, _("Cannot add folder, unsupported folder type")));
+ }
+ } else {
+ g_propagate_error (perror, g_error_new_literal (EWS_CONNECTION_ERROR,
+ EWS_CONNECTION_ERROR_NORESPONSE, _("Cannot add folder, master source not found")));
+ }
+
+ return res;
+}
+
+gboolean
+e_ews_folder_utils_add_as_esource (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ EEwsFolder *folder,
+ gboolean offline_sync,
+ gint color_seed,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ ESourceRegistry *registry;
+ GList *sources;
+ ESource *source, *old_source;
+ const EwsFolderId *fid;
+ gboolean res = FALSE;
+
+ registry = pregistry;
+ if (!registry) {
+ registry = e_source_registry_new_sync (cancellable, perror);
+ if (!registry)
+ return FALSE;
+ }
+
+ sources = e_source_registry_list_sources (registry, NULL);
+ source = e_source_new (NULL, NULL, NULL);
+ fid = e_ews_folder_get_id (folder);
+
+ old_source = e_ews_folder_utils_get_source_for_folder (sources, master_hosturl, master_username, fid->id);
+ if (old_source) {
+ res = FALSE;
+
+ g_propagate_error (perror,
+ g_error_new (EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDEREXISTS,
+ _("Cannot add folder, folder already exists as '%s'"), e_source_get_display_name (old_source)));
+ } else if (e_ews_folder_utils_populate_esource (
+ source,
+ sources,
+ master_hosturl,
+ master_username,
+ folder,
+ offline_sync,
+ color_seed,
+ cancellable,
+ perror)) {
+ res = e_source_registry_commit_source_sync (registry, source, cancellable, perror);
+ }
+ g_object_unref (source);
+
+ g_list_free_full (sources, g_object_unref);
+ if (!pregistry)
+ g_object_unref (registry);
+
+ return res;
+}
+
+gboolean
+e_ews_folder_utils_remove_as_esource (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ ESourceRegistry *registry;
+ ESource *source;
+ GList *sources;
+ gboolean res = TRUE;
+
+ registry = pregistry;
+ if (!registry) {
+ registry = e_source_registry_new_sync (cancellable, perror);
+ if (!registry)
+ return FALSE;
+ }
+
+ 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);
+
+ g_list_free_full (sources, g_object_unref);
+ if (!pregistry)
+ g_object_unref (registry);
+
+ return res;
+}
+
+gboolean
+e_ews_folder_utils_is_subscribed_as_esource (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id)
+{
+ return e_ews_folder_utils_get_source_for_folder (esources, master_hosturl, master_username, folder_id) != NULL;
+}
+
+static gboolean
+is_for_account (ESource *source,
+ const gchar *master_hosturl,
+ const gchar *master_username)
+{
+ ESourceCamel *camel_extension;
+ ESourceAuthentication *auth_extension;
+ CamelEwsSettings *settings;
+ const gchar *extension_name;
+
+ if (!source)
+ return FALSE;
+
+ if (!master_hosturl && !master_username)
+ return TRUE;
+
+ extension_name = e_source_camel_get_extension_name ("ews");
+ if (!e_source_has_extension (source, extension_name))
+ return FALSE;
+
+ camel_extension = e_source_get_extension (source, extension_name);
+ settings = CAMEL_EWS_SETTINGS (e_source_camel_get_settings (camel_extension));
+
+ if (!settings || g_strcmp0 (camel_ews_settings_get_hosturl (settings), master_hosturl) != 0)
+ return FALSE;
+
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ if (!e_source_has_extension (source, extension_name))
+ return FALSE;
+
+ auth_extension = e_source_get_extension (source, extension_name);
+ return g_strcmp0 (e_source_authentication_get_user (auth_extension), master_username) == 0;
+}
+
+/* filters @esources thus the resulting list will contain ESource-s only for @profile;
+ free returned list with g_list_free_full (list, g_object_unref); */
+GList *
+e_ews_folder_utils_filter_sources_for_account (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username)
+{
+ GList *found = NULL;
+ const GList *iter;
+ ESource *master_source;
+
+ master_source = e_ews_folder_utils_get_master_source (esources, master_hosturl, master_username);
+ if (!master_source)
+ return NULL;
+
+ for (iter = esources; iter; iter = iter->next) {
+ ESource *source = iter->data;
+
+ if (is_for_account (source, master_hosturl, master_username) ||
+ g_strcmp0 (e_source_get_uid (master_source), e_source_get_parent (source)) == 0)
+ found = g_list_prepend (found, g_object_ref (source));
+ }
+
+ return g_list_reverse (found);
+}
+
+/* returns (not-reffed) member of @esources, which is for @profile and @folder_id */
+ESource *
+e_ews_folder_utils_get_source_for_folder (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id)
+{
+ ESource *master_source;
+ const GList *iter;
+
+ master_source = e_ews_folder_utils_get_master_source (esources, master_hosturl, master_username);
+ if (!master_source)
+ return NULL;
+
+ for (iter = esources; iter; iter = iter->next) {
+ ESource *source = iter->data;
+
+ if ((is_for_account (source, master_hosturl, master_username) ||
+ g_strcmp0 (e_source_get_uid (master_source), e_source_get_parent (source)) == 0) &&
+ e_source_has_extension (source, E_SOURCE_EXTENSION_EWS_FOLDER)) {
+ ESourceEwsFolder *folder_ext = e_source_get_extension (source, E_SOURCE_EXTENSION_EWS_FOLDER);
+
+ g_return_val_if_fail (folder_ext != NULL, NULL);
+
+ if (g_strcmp0 (e_source_ews_folder_get_id (folder_ext), folder_id) == 0)
+ return source;
+ }
+ }
+
+ return NULL;
+}
+
+/* returns (not-reffed) member of @esources, which is master (with no parent) source for @profile */
+ESource *
+e_ews_folder_utils_get_master_source (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username)
+{
+ const GList *iter;
+
+ for (iter = esources; iter; iter = iter->next) {
+ ESource *source = iter->data;
+
+ if (!e_source_get_parent (source) &&
+ is_for_account (source, master_hosturl, master_username))
+ return source;
+ }
+ return NULL;
}
diff --git a/src/server/e-ews-folder.h b/src/server/e-ews-folder.h
index a721e53..2cec0c4 100644
--- a/src/server/e-ews-folder.h
+++ b/src/server/e-ews-folder.h
@@ -22,6 +22,8 @@
#ifndef E_EWS_FOLDER_H
#define E_EWS_FOLDER_H
+#include <libedataserver/libedataserver.h>
+
#include "e-ews-enums.h"
#include "e-soap-message.h"
@@ -70,12 +72,54 @@ gboolean e_ews_folder_get_is_writable (EEwsFolder *folder);
void e_ews_folder_set_is_writable (EEwsFolder *folder, gboolean writable);
EEwsFolderType e_ews_folder_get_folder_type (EEwsFolder *folder);
void e_ews_folder_set_folder_type (EEwsFolder *folder, EEwsFolderType folder_type);
+gboolean e_ews_folder_get_foreign (EEwsFolder *folder);
+void e_ews_folder_set_foreign (EEwsFolder *folder, gboolean is_foreign);
EwsFolderId * e_ews_folder_id_new (const gchar *id,
const gchar *change_key,
gboolean is_distinguished_id);
void e_ews_folder_id_free (EwsFolderId *fid);
+gchar * e_ews_folder_utils_pick_color_spec (gint move_by,
+ gboolean around_middle);
+gboolean e_ews_folder_utils_populate_esource (ESource *source,
+ const GList *sources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ EEwsFolder *folder,
+ gboolean offline_sync,
+ gint color_seed,
+ GCancellable *cancellable,
+ GError **perror);
+gboolean e_ews_folder_utils_add_as_esource (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ EEwsFolder *folder,
+ gboolean offline_sync,
+ gint color_seed,
+ GCancellable *cancellable,
+ GError **perror);
+gboolean e_ews_folder_utils_remove_as_esource (ESourceRegistry *pregistry,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id,
+ GCancellable *cancellable,
+ GError **perror);
+gboolean e_ews_folder_utils_is_subscribed_as_esource (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id);
+GList * e_ews_folder_utils_filter_sources_for_account (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username);
+ESource * e_ews_folder_utils_get_source_for_folder (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username,
+ const gchar *folder_id);
+ESource * e_ews_folder_utils_get_master_source (const GList *esources,
+ const gchar *master_hosturl,
+ const gchar *master_username);
+
G_END_DECLS
#endif
diff --git a/src/server/e-source-ews-folder.c b/src/server/e-source-ews-folder.c
index dcdc6b5..eef7306 100644
--- a/src/server/e-source-ews-folder.c
+++ b/src/server/e-source-ews-folder.c
@@ -26,12 +26,14 @@ struct _ESourceEwsFolderPrivate {
GMutex *property_lock;
gchar *change_key;
gchar *id;
+ gboolean foreign;
};
enum {
PROP_0,
PROP_CHANGE_KEY,
- PROP_ID
+ PROP_ID,
+ PROP_FOREIGN
};
G_DEFINE_DYNAMIC_TYPE (
@@ -57,6 +59,12 @@ source_ews_folder_set_property (GObject *object,
E_SOURCE_EWS_FOLDER (object),
g_value_get_string (value));
return;
+
+ case PROP_FOREIGN:
+ e_source_ews_folder_set_foreign (
+ E_SOURCE_EWS_FOLDER (object),
+ g_value_get_boolean (value));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -82,6 +90,13 @@ source_ews_folder_get_property (GObject *object,
e_source_ews_folder_dup_id (
E_SOURCE_EWS_FOLDER (object)));
return;
+
+ case PROP_FOREIGN:
+ g_value_set_boolean (
+ value,
+ e_source_ews_folder_get_foreign (
+ E_SOURCE_EWS_FOLDER (object)));
+ return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -145,6 +160,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_FOREIGN,
+ g_param_spec_boolean (
+ "foreign",
+ "Foreign",
+ "The folder is a foreign folder, aka belongs to other user",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS |
+ E_SOURCE_PARAM_SETTING));
}
static void
@@ -278,3 +306,25 @@ e_source_ews_folder_dup_folder_id (ESourceEwsFolder *extension)
return folder_id;
}
+
+gboolean
+e_source_ews_folder_get_foreign (ESourceEwsFolder *extension)
+{
+ g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), FALSE);
+
+ return extension->priv->foreign;
+}
+
+void
+e_source_ews_folder_set_foreign (ESourceEwsFolder *extension,
+ gboolean is_foreign)
+{
+ g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
+
+ if ((extension->priv->foreign ? 1 : 0) == (is_foreign ? 1 : 0))
+ return;
+
+ extension->priv->foreign = is_foreign;
+
+ g_object_notify (G_OBJECT (extension), "foreign");
+}
diff --git a/src/server/e-source-ews-folder.h b/src/server/e-source-ews-folder.h
index f6202bd..e15b7a9 100644
--- a/src/server/e-source-ews-folder.h
+++ b/src/server/e-source-ews-folder.h
@@ -76,6 +76,10 @@ void e_source_ews_folder_set_id (ESourceEwsFolder *extension,
EwsFolderId * e_source_ews_folder_dup_folder_id
(ESourceEwsFolder *extension);
+gboolean e_source_ews_folder_get_foreign (ESourceEwsFolder *extension);
+void e_source_ews_folder_set_foreign (ESourceEwsFolder *extension,
+ gboolean is_foreign);
+
G_END_DECLS
#endif /* E_SOURCE_EWS_FOLDER_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]