[evolution-mapi] Bug 788373 - Option to subscribe to other user's folder with subfolders
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-mapi] Bug 788373 - Option to subscribe to other user's folder with subfolders
- Date: Mon, 4 Dec 2017 11:05:40 +0000 (UTC)
commit a04109196cef5209e04a1ec2bb9d517ed05c1867
Author: Milan Crha <mcrha redhat com>
Date: Mon Dec 4 12:04:27 2017 +0100
Bug 788373 - Option to subscribe to other user's folder with subfolders
src/camel/camel-mapi-store-summary.h | 3 +-
src/camel/camel-mapi-store.c | 474 ++++++++++++++++++--
.../e-mapi-subscribe-foreign-folder.c | 23 +-
src/libexchangemapi/e-mapi-connection.c | 138 ++++--
src/libexchangemapi/e-mapi-connection.h | 10 +
5 files changed, 580 insertions(+), 68 deletions(-)
---
diff --git a/src/camel/camel-mapi-store-summary.h b/src/camel/camel-mapi-store-summary.h
index d0d2090..5f59ce1 100644
--- a/src/camel/camel-mapi-store-summary.h
+++ b/src/camel/camel-mapi-store-summary.h
@@ -58,7 +58,8 @@ enum CamelMapiStoreFolderFlags {
CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC = 1 << 1,
CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN = 1 << 2,
CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL = 1 << 3,
- CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL = 1 << 4 /* real public folder; the unreal is that under
Favorites */
+ CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL = 1 << 4, /* real public folder; the unreal is that under
Favorites */
+ CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS = 1 << 5
};
enum {
diff --git a/src/camel/camel-mapi-store.c b/src/camel/camel-mapi-store.c
index 5dbeb16..24d696b 100644
--- a/src/camel/camel-mapi-store.c
+++ b/src/camel/camel-mapi-store.c
@@ -328,7 +328,6 @@ mapi_convert_to_folder_info (CamelMapiStore *store,
gchar *name;
gchar *parent, *id = NULL;
mapi_id_t mapi_id_folder;
-
const gchar *par_name = NULL;
CamelFolderInfo *fi;
@@ -610,6 +609,10 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
camel_store_folder_created (CAMEL_STORE (store), info);
camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (store),
info);
}
+ } else if (e_mapi_folder_get_id (folder) != msi->folder_id ||
+ e_mapi_folder_get_parent_id (folder) != msi->parent_id) {
+ msi->folder_id = e_mapi_folder_get_id (folder);
+ msi->parent_id = e_mapi_folder_get_parent_id (folder);
}
msi->info.flags = info->flags;
@@ -634,6 +637,10 @@ mapi_folders_sync (CamelMapiStore *store, guint32 flags, GCancellable *cancellab
if (msi)
camel_store_summary_info_ref (store->summary, (CamelStoreInfo *) msi);
+ } else if (e_mapi_folder_get_id (folder) != msi->folder_id ||
+ e_mapi_folder_get_parent_id (folder) != msi->parent_id) {
+ msi->folder_id = e_mapi_folder_get_id (folder);
+ msi->parent_id = e_mapi_folder_get_parent_id (folder);
}
if (msi == NULL)
@@ -896,17 +903,14 @@ mapi_forget_folder (CamelMapiStore *mapi_store, const gchar *folder_name, GError
folder_dir = g_build_filename (storage_path, folder_name, NULL);
g_free (storage_path);
- if (g_access(folder_dir, F_OK) != 0) {
- g_free(folder_dir);
- return TRUE;
- }
-
- state_file = g_build_filename (folder_dir, "cmeta", NULL);
- g_unlink (state_file);
- g_free (state_file);
+ if (g_access (folder_dir, F_OK) == 0) {
+ state_file = g_build_filename (folder_dir, "cmeta", NULL);
+ g_unlink (state_file);
+ g_free (state_file);
- g_rmdir (folder_dir);
- g_free (folder_dir);
+ g_rmdir (folder_dir);
+ g_free (folder_dir);
+ }
camel_store_summary_remove_path (mapi_store->summary, folder_name);
camel_store_summary_save (mapi_store->summary);
@@ -1422,7 +1426,7 @@ mapi_store_delete_folder_sync (CamelStore *store,
if (!msi ||
(msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 ||
(msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
- /* do nore remove foreign or public folders, just unsubscribe from them,
+ /* do not remove foreign or public folders, just unsubscribe from them,
even when there are folder delete permissons on the folder
*/
status = TRUE;
@@ -1889,10 +1893,17 @@ mapi_store_subscribe_folder_sync (CamelSubscribable *subscribable,
}
static gboolean
-mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
- const gchar *folder_name,
- GCancellable *cancellable,
- GError **error)
+mapi_store_unsubscribe_subfolders (CamelMapiStore *mapi_store,
+ mapi_id_t parent_id,
+ GCancellable *cancellable,
+ GError **error);
+
+static gboolean
+mapi_store_unsubscribe_folder_internal_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ gboolean check_foreign_subfolders,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean res = TRUE;
CamelFolderInfo *fi;
@@ -1924,11 +1935,24 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
camel_subscribable_folder_unsubscribed (subscribable, fi);
camel_folder_info_free (fi);
- if ((msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 &&
- (msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL) == 0) {
- /* remove calls also free on 'si2' */
- camel_store_summary_remove (mapi_store->summary, si2);
- camel_store_summary_touch (mapi_store->summary);
+ if (((msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 &&
+ (msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL) == 0) ||
+ (msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0) {
+ if (check_foreign_subfolders &&
+ (msi2->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 &&
+ (msi2->mapi_folder_flags &
CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS) != 0) {
+ res = mapi_store_unsubscribe_subfolders (mapi_store, msi2->folder_id,
cancellable, error);
+ }
+
+ if (res) {
+ res = mapi_forget_folder (mapi_store, folder_name, error);
+
+ /* remove calls also free on 'si2' */
+ camel_store_summary_remove (mapi_store->summary, si2);
+ camel_store_summary_touch (mapi_store->summary);
+ } else {
+ camel_store_summary_info_unref (mapi_store->summary, si2);
+ }
} else {
camel_store_summary_info_unref (mapi_store->summary, si2);
}
@@ -1951,11 +1975,22 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
g_object_unref (settings);
}
- if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 &&
- (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL) == 0) {
- /* remove calls also free on 'si' */
- camel_store_summary_remove (mapi_store->summary, si);
- camel_store_summary_touch (mapi_store->summary);
+ if (res && (((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC) != 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_PUBLIC_REAL) == 0) ||
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0)) {
+ if (check_foreign_subfolders &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS) != 0) {
+ res = mapi_store_unsubscribe_subfolders (mapi_store, msi->folder_id, cancellable,
error);
+ }
+
+ if (res) {
+ /* remove calls also free on 'si' */
+ camel_store_summary_remove (mapi_store->summary, si);
+ camel_store_summary_touch (mapi_store->summary);
+ } else {
+ camel_store_summary_info_unref (mapi_store->summary, si);
+ }
} else {
camel_store_summary_info_unref (mapi_store->summary, si);
}
@@ -1965,6 +2000,73 @@ mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
return res;
}
+static gboolean
+mapi_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return mapi_store_unsubscribe_folder_internal_sync (subscribable, folder_name, TRUE, cancellable,
error);
+}
+
+/* This can be particularly slow (with many folders) */
+static GSList * /* (transfer container) (element-type CamelMapiStoreInfo *) */
+mapi_store_gather_subfolders (GPtrArray *array, /* CamelMapiStoreInfo * */
+ mapi_id_t parent_id)
+{
+ GSList *subfolders = NULL;
+ guint ii;
+
+ if (!array)
+ return NULL;
+
+ for (ii = 0; ii < array->len; ii++) {
+ CamelMapiStoreInfo *msi = g_ptr_array_index (array, ii);
+
+ if (msi && msi->parent_id == parent_id) {
+ GSList *subsub;
+
+ subfolders = g_slist_prepend (subfolders, msi);
+
+ subsub = mapi_store_gather_subfolders (array, msi->folder_id);
+ if (subsub)
+ subfolders = g_slist_concat (subfolders, subsub);
+ }
+ }
+
+ return subfolders;
+}
+
+static gboolean
+mapi_store_unsubscribe_subfolders (CamelMapiStore *mapi_store,
+ mapi_id_t parent_id,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GPtrArray *array;
+ GSList *subfolders, *link;
+ gboolean res = TRUE;
+
+ array = camel_store_summary_array (mapi_store->summary);
+ subfolders = mapi_store_gather_subfolders (array, parent_id);
+
+ for (link = subfolders; link && res; link = g_slist_next (link)) {
+ CamelMapiStoreInfo *msi = link->data;
+
+ if (!msi || !(msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN))
+ continue;
+
+ res = mapi_store_unsubscribe_folder_internal_sync (CAMEL_SUBSCRIBABLE (mapi_store),
+ camel_store_info_path (mapi_store->summary, (CamelStoreInfo *) msi),
+ FALSE, cancellable, error);
+ }
+
+ camel_store_summary_array_free (mapi_store->summary, array);
+ g_slist_free (subfolders);
+
+ return res;
+}
+
static void
mapi_migrate_to_user_cache_dir (CamelService *service)
{
@@ -2589,6 +2691,290 @@ camel_mapi_store_server_notification_cb (EMapiConnection *conn,
schedule_folder_list_update (mapi_store);
}
+static gboolean
+camel_mapi_add_foreign_folder (CamelMapiStore *mapi_store,
+ CamelMapiStoreInfo *owner_msi,
+ EMapiFolder *mapi_folder,
+ CamelFolderInfo *fi,
+ GError **error)
+{
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_MAPI_STORE (mapi_store), FALSE);
+ g_return_val_if_fail (owner_msi != NULL, FALSE);
+ g_return_val_if_fail (mapi_folder != NULL, FALSE);
+ g_return_val_if_fail (fi != NULL, FALSE);
+
+ success = camel_mapi_store_summary_add_from_full (mapi_store->summary, fi->full_name,
+ e_mapi_folder_get_id (mapi_folder), e_mapi_folder_get_parent_id (mapi_folder),
+ CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_FOLDER_NOCHILDREN | CAMEL_FOLDER_SUBSCRIBED,
+ CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+ owner_msi->foreign_username) != NULL;
+
+ if (success) {
+ CamelStoreInfo *parent_si;
+
+ parent_si = camel_mapi_store_summary_get_folder_id (mapi_store->summary,
e_mapi_folder_get_parent_id (mapi_folder));
+ if (parent_si) {
+ CamelMapiStoreInfo *parent_msi = (CamelMapiStoreInfo *) parent_si;
+
+ parent_msi->camel_folder_flags = parent_msi->camel_folder_flags &
(~CAMEL_FOLDER_NOCHILDREN);
+
+ camel_store_summary_info_unref (mapi_store->summary, parent_si);
+ }
+
+ owner_msi->camel_folder_flags = owner_msi->camel_folder_flags & (~CAMEL_FOLDER_NOCHILDREN);
+
+ camel_store_summary_touch (mapi_store->summary);
+
+ camel_mapi_store_announce_subscribed_folder (mapi_store, fi->full_name);
+ } else {
+ g_set_error (error, E_MAPI_ERROR, MAPI_E_INVALID_PARAMETER,
+ _("Cannot add folder “%s”, failed to add to store’s summary"), fi->full_name);
+ }
+
+ return success;
+}
+
+static gboolean
+mapi_store_unsubscribe_with_subfolders (CamelMapiStore *mapi_store,
+ CamelMapiStoreInfo *parent_msi,
+ GPtrArray *array, /* CamelMapiStoreInfo * */
+ GHashTable *processed_fids, /* gchar * ~> NULL */
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSList *subfolders, *link;
+ gboolean success = TRUE;
+
+ g_return_val_if_fail (CAMEL_IS_MAPI_STORE (mapi_store), FALSE);
+ g_return_val_if_fail (parent_msi != NULL, FALSE);
+
+ if (!array)
+ return TRUE;
+
+ subfolders = mapi_store_gather_subfolders (array, parent_msi->folder_id);
+ subfolders = g_slist_prepend (subfolders, parent_msi);
+
+ for (link = subfolders; link && success; link = g_slist_next (link)) {
+ CamelMapiStoreInfo *msi = link->data;
+
+ if (msi) {
+ g_hash_table_insert (processed_fids, e_mapi_util_mapi_id_to_string (msi->folder_id),
NULL);
+
+ success = mapi_store_unsubscribe_folder_internal_sync (CAMEL_SUBSCRIBABLE
(mapi_store),
+ camel_store_info_path (mapi_store->summary, (CamelStoreInfo *) msi),
+ FALSE, cancellable, error);
+ }
+ }
+
+ g_slist_free (subfolders);
+
+ return success;
+}
+
+static gboolean
+mapi_store_merge_with_subfolders (CamelMapiStore *mapi_store,
+ GSList *mapi_folders, /* EMapiFolder * */
+ CamelMapiStoreInfo *parent_msi,
+ GPtrArray *array, /* CamelMapiStoreInfo * */
+ GHashTable *processed_fids, /* gchar * ~> NULL */
+ GCancellable *cancellable,
+ GError **error)
+{
+ GSList *subfolders, *link;
+ GHashTable *existing;
+ gboolean success = TRUE;
+
+ g_return_val_if_fail (CAMEL_IS_MAPI_STORE (mapi_store), FALSE);
+ g_return_val_if_fail (parent_msi != NULL, FALSE);
+
+ if (!array)
+ return TRUE;
+
+ existing = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ subfolders = mapi_store_gather_subfolders (array, parent_msi->folder_id);
+
+ for (link = subfolders; link; link = g_slist_next (link)) {
+ CamelMapiStoreInfo *msi = link->data;
+
+ if (msi) {
+ g_hash_table_insert (processed_fids, e_mapi_util_mapi_id_to_string (msi->folder_id),
NULL);
+ g_hash_table_insert (existing, e_mapi_util_mapi_id_to_string (msi->folder_id), msi);
+ }
+ }
+
+ for (link = mapi_folders; link && success; link = g_slist_next (link)) {
+ EMapiFolder *mapi_folder = link->data;
+ CamelMapiStoreInfo *msi;
+ CamelFolderInfo *fi;
+ gchar *fid;
+
+ if (!mapi_folder)
+ continue;
+
+ fi = mapi_convert_to_folder_info (mapi_store, mapi_folder, NULL);
+ if (!fi)
+ continue;
+
+ fid = e_mapi_util_mapi_id_to_string (mapi_folder->folder_id);
+ if (!fid) {
+ camel_folder_info_free (fi);
+ continue;
+ }
+
+ msi = g_hash_table_lookup (existing, fid);
+
+ if (msi) {
+ const gchar *path;
+
+ path = camel_store_info_path (mapi_store->summary, (CamelStoreInfo *) msi);
+
+ if (g_strcmp0 (fi->full_name, path) != 0) {
+ mapi_rename_folder_infos (mapi_store, path, fi->full_name);
+
+ g_hash_table_remove (mapi_store->priv->name_hash, path);
+ g_hash_table_remove (mapi_store->priv->id_hash, fid);
+
+ mapi_update_folder_hash_tables (mapi_store, fi->full_name, fid, NULL);
+
+ camel_store_info_set_string (mapi_store->summary, (CamelStoreInfo *) msi,
CAMEL_STORE_INFO_PATH, fi->full_name);
+ camel_store_summary_touch (mapi_store->summary);
+ }
+
+ g_hash_table_remove (existing, fid);
+ } else {
+ if (e_mapi_folder_get_type (mapi_folder) == E_MAPI_FOLDER_TYPE_MAIL) {
+ success = camel_mapi_add_foreign_folder (mapi_store, parent_msi, mapi_folder,
fi, error);
+ } else {
+ CamelSettings *settings;
+ gchar *profile;
+
+ settings = camel_service_ref_settings (CAMEL_SERVICE (mapi_store));
+ profile = camel_mapi_settings_dup_profile (CAMEL_MAPI_SETTINGS (settings));
+
+ g_object_unref (settings);
+
+ success = e_mapi_folder_add_as_esource (NULL, e_mapi_folder_get_type
(mapi_folder),
+ profile,
+ TRUE /* camel_offline_settings_get_stay_synchronized
(CAMEL_OFFLINE_SETTINGS (mapi_settings)) */,
+ E_MAPI_FOLDER_CATEGORY_FOREIGN,
+ parent_msi->foreign_username,
+ e_mapi_folder_get_name (mapi_folder),
+ e_mapi_folder_get_id (mapi_folder),
+ 0,
+ cancellable,
+ error);
+
+ g_free (profile);
+ }
+ }
+
+ camel_folder_info_free (fi);
+ g_free (fid);
+ }
+
+ if (success && g_hash_table_size (existing)) {
+ GHashTableIter iter;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, existing);
+ while (success && g_hash_table_iter_next (&iter, NULL, &value)) {
+ CamelMapiStoreInfo *msi = value;
+
+ if (msi) {
+ success = mapi_store_unsubscribe_folder_internal_sync (CAMEL_SUBSCRIBABLE
(mapi_store),
+ camel_store_info_path (mapi_store->summary, (CamelStoreInfo *) msi),
+ TRUE, cancellable, error);
+ }
+ }
+ }
+
+ camel_store_summary_save (mapi_store->summary);
+
+ g_hash_table_destroy (existing);
+ g_slist_free (subfolders);
+
+ return success;
+}
+
+static void
+mapi_store_update_foreign_subfolders_thread (CamelSession *session,
+ GCancellable *cancellable,
+ gpointer user_data,
+ GError **error)
+{
+ CamelMapiStore *mapi_store = user_data;
+ EMapiConnection *connection;
+ GHashTable *processed_fids;
+ GPtrArray *array;
+ guint ii;
+
+ g_return_if_fail (CAMEL_IS_MAPI_STORE (mapi_store));
+
+ connection = camel_mapi_store_ref_connection (mapi_store, cancellable, error);
+ if (!connection)
+ return;
+
+ processed_fids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ array = camel_store_summary_array (mapi_store->summary);
+ for (ii = 0; array && ii < array->len; ii++) {
+ CamelMapiStoreInfo *msi = g_ptr_array_index (array, ii);
+
+ if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS) != 0) {
+ gchar *fid = e_mapi_util_mapi_id_to_string (msi->folder_id);
+ mapi_object_t obj_folder;
+ GSList *mapi_folders = NULL;
+ gboolean success = TRUE;
+ GError *local_error = NULL;
+
+ if (!fid || g_hash_table_contains (processed_fids, fid)) {
+ g_free (fid);
+ continue;
+ }
+
+ g_hash_table_insert (processed_fids, fid, NULL);
+
+ if (!e_mapi_connection_open_foreign_folder (connection, msi->foreign_username,
msi->folder_id, &obj_folder, cancellable, &local_error)) {
+ if (!g_cancellable_is_cancelled (cancellable) &&
+ camel_offline_store_get_online (CAMEL_OFFLINE_STORE (mapi_store))) {
+ /* Unsubscribe from it only if it could not be found */
+ if (g_error_matches (local_error, E_MAPI_ERROR, MAPI_E_NOT_FOUND) &&
+ !mapi_store_unsubscribe_with_subfolders (mapi_store, msi, array,
processed_fids, cancellable, error)) {
+ g_clear_error (&local_error);
+ break;
+ }
+
+ g_clear_error (&local_error);
+ continue;
+ } else {
+ if (local_error)
+ g_propagate_error (error, local_error);
+
+ make_mapi_error (error, "e_mapi_connection_open_foreign_folder",
MAPI_E_CALL_FAILED);
+ break;
+ }
+ }
+
+ if (e_mapi_connection_get_subfolders_list (connection, &obj_folder,
E_MAPI_FOLDER_CATEGORY_FOREIGN,
+ &mapi_folders, camel_mapi_update_operation_progress_cb, NULL, cancellable,
NULL)) {
+ success = mapi_store_merge_with_subfolders (mapi_store, mapi_folders, msi,
array, processed_fids, cancellable, error);
+ }
+
+ g_slist_free_full (mapi_folders, (GDestroyNotify) e_mapi_folder_free);
+
+ if (!e_mapi_connection_close_folder (connection, &obj_folder, cancellable, error) ||
!success)
+ break;
+ }
+ }
+
+ camel_store_summary_array_free (mapi_store->summary, array);
+ g_hash_table_destroy (processed_fids);
+ g_object_unref (connection);
+}
+
static CamelAuthenticationResult
mapi_authenticate_sync (CamelService *service,
const gchar *mechanism,
@@ -2644,9 +3030,11 @@ mapi_authenticate_sync (CamelService *service,
store->priv->connection = e_mapi_connection_new (
e_mail_session_get_registry (E_MAIL_SESSION (session)),
profile, credentials, cancellable, &mapi_error);
- g_object_unref (session);
e_named_parameters_free (credentials);
if (store->priv->connection && e_mapi_connection_connected (store->priv->connection)) {
+ GPtrArray *array;
+ guint ii;
+
result = CAMEL_AUTHENTICATION_ACCEPTED;
if (!store->priv->updates_cancellable)
@@ -2656,6 +3044,23 @@ mapi_authenticate_sync (CamelService *service,
if (camel_mapi_settings_get_listen_notifications (mapi_settings))
e_mapi_connection_enable_notifications (store->priv->connection, NULL, 0, NULL, NULL);
+
+ /* Also update folder structures of foreign folders,
+ those which are subscribed with subfolders */
+ array = camel_store_summary_array (store->summary);
+ for (ii = 0; array && ii < array->len; ii++) {
+ CamelMapiStoreInfo *msi = g_ptr_array_index (array, ii);
+
+ if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS)
!= 0) {
+ camel_session_submit_job (session, _("Updating foreign folders"),
+ mapi_store_update_foreign_subfolders_thread,
+ g_object_ref (store), g_object_unref);
+ break;
+ }
+ }
+
+ camel_store_summary_array_free (store->summary, array);
} else if (g_error_matches (mapi_error, E_MAPI_ERROR, MAPI_E_LOGON_FAILED) ||
g_error_matches (mapi_error, E_MAPI_ERROR, ecRpcFailed)) {
g_clear_error (&mapi_error);
@@ -2674,6 +3079,7 @@ mapi_authenticate_sync (CamelService *service,
g_rec_mutex_unlock (&store->priv->connection_lock);
g_object_unref (settings);
+ g_object_unref (session);
return result;
}
@@ -3037,6 +3443,20 @@ camel_mapi_store_announce_subscribed_folder (CamelMapiStore *mapi_store,
camel_store_folder_created (CAMEL_STORE (mapi_store), fi);
camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (mapi_store), fi);
+ if ((msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN) != 0 &&
+ (msi->mapi_folder_flags & CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS) != 0) {
+ CamelSession *session;
+
+ session = camel_service_ref_session (CAMEL_SERVICE (mapi_store));
+
+ if (session) {
+ camel_session_submit_job (session, _("Updating foreign folders"),
+ mapi_store_update_foreign_subfolders_thread,
+ g_object_ref (mapi_store), g_object_unref);
+ g_object_unref (session);
+ }
+ }
+
camel_folder_info_free (fi);
camel_store_summary_info_unref (mapi_store->summary, si);
g_free (folder_id_str);
diff --git a/src/configuration/e-mapi-subscribe-foreign-folder.c
b/src/configuration/e-mapi-subscribe-foreign-folder.c
index 68959a4..612782e 100644
--- a/src/configuration/e-mapi-subscribe-foreign-folder.c
+++ b/src/configuration/e-mapi-subscribe-foreign-folder.c
@@ -42,6 +42,7 @@
#define STR_USER_NAME_SELECTOR_ENTRY "e-mapi-name-selector-entry"
#define STR_FOLDER_NAME_COMBO "e-mapi-folder-name-combo"
+#define STR_SUBFOLDERS_CHECK "e-mapi-subfolders-check"
#define STR_MAPI_CAMEL_SESSION "e-mapi-camel-session"
#define STR_MAPI_CAMEL_STORE "e-mapi-camel-store"
#define STR_MAPI_DIRECT_USER_NAME "e-mapi-direct-user-name"
@@ -51,6 +52,7 @@ add_foreign_folder_to_camel (CamelMapiStore *mapi_store,
const gchar *foreign_username,
mapi_id_t folder_id,
mapi_id_t parent_fid,
+ gboolean include_subfolders,
const gchar *display_username,
const gchar *display_foldername,
GError **perror)
@@ -122,7 +124,8 @@ add_foreign_folder_to_camel (CamelMapiStore *mapi_store,
if (camel_mapi_store_summary_add_from_full (mapi_store->summary, path, folder_id, parent_fid,
CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_FOLDER_NOCHILDREN |
CAMEL_FOLDER_SUBSCRIBED,
- CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL,
+ CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN | CAMEL_MAPI_STORE_FOLDER_FLAG_MAIL |
+ (include_subfolders ? CAMEL_MAPI_STORE_FOLDER_FLAG_FOREIGN_WITH_SUBFOLDERS : 0),
foreign_username)) {
if (parent_si) {
CamelMapiStoreInfo *msi = (CamelMapiStoreInfo *) parent_si;
@@ -172,6 +175,7 @@ name_entry_changed_cb (GObject *dialog)
struct EMapiCheckForeignFolderData
{
GtkWidget *dialog;
+ gboolean include_subfolders;
gchar *username;
gchar *direct_username;
gchar *user_displayname;
@@ -266,6 +270,11 @@ foreign_folder_get_props_cb (EMapiConnection *conn,
cffd->folder_container_class = g_strdup (e_mapi_util_find_array_propval (properties,
PidTagContainerClass));
cffd->parent_folder_id = pid ? *pid : 0;
+ if (!cffd->folder_container_class) {
+ /* Default to mail folder */
+ cffd->folder_container_class = g_strdup (IPF_NOTE);
+ }
+
return TRUE;
}
@@ -421,6 +430,7 @@ check_foreign_folder_idle (GObject *with_object,
cffd->username,
cffd->folder_id,
cffd->parent_folder_id,
+ cffd->include_subfolders,
base_username,
base_foldername,
perror)) ||
@@ -450,6 +460,7 @@ subscribe_foreign_response_cb (GObject *dialog,
struct EMapiCheckForeignFolderData *cffd;
ENameSelectorEntry *entry;
GtkComboBoxText *combo_text;
+ GtkToggleButton *subfolders_check;
EDestinationStore *dest_store;
CamelStore *cstore;
gchar *description;
@@ -465,6 +476,7 @@ subscribe_foreign_response_cb (GObject *dialog,
entry = g_object_get_data (dialog, STR_USER_NAME_SELECTOR_ENTRY);
combo_text = g_object_get_data (dialog, STR_FOLDER_NAME_COMBO);
+ subfolders_check = g_object_get_data (dialog, STR_SUBFOLDERS_CHECK);
cstore = g_object_get_data (dialog, STR_MAPI_CAMEL_STORE);
g_return_if_fail (entry != NULL);
@@ -517,6 +529,7 @@ subscribe_foreign_response_cb (GObject *dialog,
cffd->use_foldername = use_foldername;
cffd->folder_id = 0;
cffd->parent_folder_id = 0;
+ cffd->include_subfolders = gtk_toggle_button_get_active (subfolders_check);
description = g_strdup_printf (_("Testing availability of folder “%s” of user “%s”, please wait..."),
cffd->orig_foldername, cffd->username);
@@ -590,7 +603,7 @@ e_mapi_subscribe_foreign_folder (GtkWindow *parent,
ENameSelectorDialog *name_selector_dialog;
GObject *dialog;
GtkWidget *content;
- GtkWidget *label, *widget, *entry;
+ GtkWidget *label, *widget, *entry, *check;
GtkGrid *grid;
GtkComboBoxText *combo_text;
gint row;
@@ -710,9 +723,15 @@ e_mapi_subscribe_foreign_folder (GtkWindow *parent,
gtk_grid_attach (grid, label, 0, row, 1, 1);
gtk_grid_attach (grid, widget, 1, row, 2, 1);
+ row++;
+
+ check = gtk_check_button_new_with_mnemonic (_("Include _subfolders"));
+ gtk_grid_attach (grid, check, 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 (dialog, STR_SUBFOLDERS_CHECK, check);
g_object_set_data_full (dialog, STR_MAPI_CAMEL_SESSION, g_object_ref (session), g_object_unref);
g_object_set_data_full (dialog, STR_MAPI_CAMEL_STORE, g_object_ref (store), g_object_unref);
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index 757bff7..099bf06 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -6136,46 +6136,27 @@ get_folder_hierarchy_cb (EMapiConnection *conn,
return TRUE;
}
-static gboolean
-get_child_folders (EMapiConnection *conn,
- TALLOC_CTX *mem_ctx,
- EMapiFolderCategory folder_hier,
- mapi_object_t *parent,
- mapi_id_t folder_id,
- GSList **mapi_folders,
- ProgressNotifyCB cb,
- gpointer cb_user_data,
- GCancellable *cancellable,
- GError **perror)
+static enum MAPISTATUS
+get_child_folders_of_folder (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ mapi_object_t *folder,
+ EMapiFolderCategory folder_hier,
+ GSList **mapi_folders,
+ ProgressNotifyCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
{
- enum MAPISTATUS ms;
- mapi_object_t obj_folder;
- mapi_object_t obj_table;
- struct SPropTagArray *spropTagArray = NULL;
+ enum MAPISTATUS ms;
+ mapi_object_t obj_table;
+ struct SPropTagArray *spropTagArray = NULL;
uint32_t row_count = 0;
struct GetFolderHierarchyCBData gfh;
- /* sanity check */
- e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
- e_return_val_mapi_error_if_fail (parent != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
-
- mapi_object_init (&obj_folder);
mapi_object_init (&obj_table);
- /* Attempt to open the folder */
- ms = OpenFolder (parent, folder_id, &obj_folder);
- if (ms != MAPI_E_SUCCESS) {
- make_mapi_error (perror, "OpenFolder", ms);
- goto cleanup;
- }
-
- if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
- ms = MAPI_E_USER_CANCEL;
- goto cleanup;
- }
-
/* Get the hierarchy table */
- ms = GetHierarchyTable (&obj_folder, &obj_table, TableFlags_Depth | TableFlags_NoNotifications,
&row_count);
+ ms = GetHierarchyTable (folder, &obj_table, TableFlags_Depth | TableFlags_NoNotifications,
&row_count);
if (ms != MAPI_E_SUCCESS) {
make_mapi_error (perror, "GetHierarchyTable", ms);
goto cleanup;
@@ -6208,18 +6189,60 @@ get_child_folders (EMapiConnection *conn,
}
gfh.folder_hier = folder_hier;
- gfh.folder_id = folder_id;
+ gfh.folder_id = mapi_object_get_id (folder);
gfh.mapi_folders = mapi_folders;
gfh.cb = cb;
gfh.cb_user_data = cb_user_data;
ms = foreach_tablerow (conn, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
+ *mapi_folders = g_slist_reverse (*mapi_folders);
+
cleanup:
talloc_free (spropTagArray);
- mapi_object_release (&obj_folder);
mapi_object_release (&obj_table);
+ return ms;
+}
+
+static gboolean
+get_child_folders (EMapiConnection *conn,
+ TALLOC_CTX *mem_ctx,
+ EMapiFolderCategory folder_hier,
+ mapi_object_t *parent,
+ mapi_id_t folder_id,
+ GSList **mapi_folders,
+ ProgressNotifyCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ mapi_object_t obj_folder;
+
+ /* sanity check */
+ e_return_val_mapi_error_if_fail (mem_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (parent != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ mapi_object_init (&obj_folder);
+
+ /* Attempt to open the folder */
+ ms = OpenFolder (parent, folder_id, &obj_folder);
+ if (ms != MAPI_E_SUCCESS) {
+ make_mapi_error (perror, "OpenFolder", ms);
+ goto cleanup;
+ }
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ goto cleanup;
+ }
+
+ ms = get_child_folders_of_folder (conn, mem_ctx, &obj_folder, folder_hier, mapi_folders, cb,
cb_user_data, cancellable, perror);
+
+ cleanup:
+ mapi_object_release (&obj_folder);
+
return ms == MAPI_E_SUCCESS;
}
@@ -6491,8 +6514,6 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
/* FIXME: check status of get_child_folders */
result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PERSONAL, &priv->msg_store,
mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
- *mapi_folders = g_slist_reverse (*mapi_folders);
-
if (result && !set_default_folders (mem_ctx, &priv->msg_store, mapi_folders, cancellable, perror)) {
goto cleanup;
}
@@ -6558,7 +6579,6 @@ e_mapi_connection_get_pf_folders_list (EMapiConnection *conn,
folder->default_type = olPublicFoldersAllPublicFolders;
*mapi_folders = g_slist_prepend (*mapi_folders, folder);
result = get_child_folders (conn, mem_ctx, E_MAPI_FOLDER_CATEGORY_PUBLIC, &priv->public_store,
mailbox_id, mapi_folders, cb, cb_user_data, cancellable, perror);
- *mapi_folders = g_slist_reverse (*mapi_folders);
cleanup:
talloc_free (mem_ctx);
@@ -6570,6 +6590,48 @@ e_mapi_connection_get_pf_folders_list (EMapiConnection *conn,
return result;
}
+gboolean
+e_mapi_connection_get_subfolders_list (EMapiConnection *conn,
+ mapi_object_t *folder,
+ EMapiFolderCategory folder_hier,
+ GSList **mapi_folders,
+ ProgressNotifyCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror)
+{
+ enum MAPISTATUS ms;
+ TALLOC_CTX *mem_ctx;
+
+ CHECK_CORRECT_CONN_AND_GET_PRIV (conn, FALSE);
+ e_return_val_mapi_error_if_fail (folder != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+ e_return_val_mapi_error_if_fail (priv->session != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
+ e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
+
+ LOCK (cancellable, perror, FALSE);
+ mem_ctx = talloc_new (priv->session);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, perror)) {
+ ms = MAPI_E_USER_CANCEL;
+ } else {
+ *mapi_folders = NULL;
+
+ ms = get_child_folders_of_folder (conn, mem_ctx, folder, folder_hier, mapi_folders, cb,
cb_user_data, cancellable, perror);
+ }
+
+ talloc_free (mem_ctx);
+
+ if (ms != MAPI_E_SUCCESS)
+ make_mapi_error (perror, "get_subfolders_list", ms);
+
+ UNLOCK ();
+
+ e_mapi_debug_print("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
+
+ return ms == MAPI_E_SUCCESS;
+}
+
GSList *
e_mapi_connection_peek_folders_list (EMapiConnection *conn)
{
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 773b802..e45774f 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -33,6 +33,8 @@
#include <libmapi/mapi_nameid.h>
#include <libedataserver/libedataserver.h>
+#include <libexchangemapi/e-mapi-folder.h>
+
/* Standard GObject macros */
#define E_MAPI_TYPE_CONNECTION (e_mapi_connection_get_type ())
#define E_MAPI_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_MAPI_TYPE_CONNECTION, EMapiConnection))
@@ -463,6 +465,14 @@ gboolean e_mapi_connection_copymove_items (EMapiConnection *conn,
GSList *mids,
GCancellable *cancellable,
GError **perror);
+gboolean e_mapi_connection_get_subfolders_list (EMapiConnection *conn,
+ mapi_object_t *folder,
+ EMapiFolderCategory folder_hier,
+ GSList **mapi_folders,
+ ProgressNotifyCB cb,
+ gpointer cb_user_data,
+ GCancellable *cancellable,
+ GError **perror);
gboolean e_mapi_connection_get_folders_list (EMapiConnection *conn,
GSList **mapi_folders,
ProgressNotifyCB cb,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]