[evolution-ews] I#61 - Add option to show public folders beside user folders



commit 70a6ebc51551034aa77c27ab4a2605472be3a72a
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jan 10 11:58:51 2020 +0100

    I#61 - Add option to show public folders beside user folders
    
    Closes https://gitlab.gnome.org/GNOME/evolution-ews/issues/61

 src/camel/camel-ews-provider.c         |   2 +
 src/camel/camel-ews-store-summary.c    |  10 +-
 src/camel/camel-ews-store-summary.h    |   3 +-
 src/camel/camel-ews-store.c            | 268 +++++++++++++++++++++++++++++++--
 src/camel/camel-ews-utils.c            |  14 +-
 src/configuration/e-ews-config-utils.c |   2 +-
 src/server/camel-ews-settings.c        |  51 ++++++-
 src/server/camel-ews-settings.h        |   5 +
 src/server/e-ews-folder.c              |  19 +++
 src/server/e-ews-folder.h              |   2 +
 10 files changed, 353 insertions(+), 23 deletions(-)
---
diff --git a/src/camel/camel-ews-provider.c b/src/camel/camel-ews-provider.c
index 56878dc8..a5fac675 100644
--- a/src/camel/camel-ews-provider.c
+++ b/src/camel/camel-ews-provider.c
@@ -61,6 +61,8 @@ static CamelProviderConfEntry ews_conf_entries[] = {
        { CAMEL_PROVIDER_CONF_CHECKBOX, "stay-synchronized", NULL,
          N_("Synchroni_ze remote mail locally in all folders"), "0" },
        { CAMEL_PROVIDER_CONF_PLACEHOLDER, "ews-limit-by-age-placeholder", NULL },
+       { CAMEL_PROVIDER_CONF_CHECKBOX, "show-public-folders", NULL,
+         N_("Show _Public Folders beside user folders"), "0" },
        { CAMEL_PROVIDER_CONF_SECTION_END },
 
        { CAMEL_PROVIDER_CONF_SECTION_START, "connection", NULL, N_("Connection") },
diff --git a/src/camel/camel-ews-store-summary.c b/src/camel/camel-ews-store-summary.c
index 43ca0326..d3301ff4 100644
--- a/src/camel/camel-ews-store-summary.c
+++ b/src/camel/camel-ews-store-summary.c
@@ -124,7 +124,7 @@ load_id_fname_hash (CamelEwsStoreSummary *ews_summary)
        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);
+       folders = camel_ews_store_summary_get_folders (ews_summary, NULL, FALSE);
 
        for (l = folders; l != NULL; l = g_slist_next (l)) {
                gchar *id = l->data;
@@ -866,7 +866,8 @@ camel_ews_store_summary_get_string_val (CamelEwsStoreSummary *ews_summary,
 
 GSList *
 camel_ews_store_summary_get_folders (CamelEwsStoreSummary *ews_summary,
-                                     const gchar *prefix)
+                                    const gchar *prefix,
+                                    gboolean only_direct_subfolders)
 {
        GSList *folders = NULL;
        gchar **groups = NULL;
@@ -893,7 +894,8 @@ camel_ews_store_summary_get_folders (CamelEwsStoreSummary *ews_summary,
                                ews_summary->priv->id_fname_hash, groups[i]);
 
                        if (!fname || strncmp (fname, prefix, prefixlen) ||
-                           (fname[prefixlen] && fname[prefixlen] != '/'))
+                           (fname[prefixlen] && fname[prefixlen] != '/') ||
+                           (only_direct_subfolders && (!fname[prefixlen] || strchr (fname + prefixlen + 1, 
'/'))))
                                continue;
                }
                folders = g_slist_append (folders, g_strdup (groups[i]));
@@ -1011,7 +1013,7 @@ camel_ews_store_summary_get_folder_id_from_folder_type (CamelEwsStoreSummary *ew
 
        S_LOCK (ews_summary);
 
-       folders = camel_ews_store_summary_get_folders (ews_summary, NULL);
+       folders = camel_ews_store_summary_get_folders (ews_summary, NULL, FALSE);
 
        for (l = folders; l != NULL; l = g_slist_next (l)) {
                gchar *id = l->data;
diff --git a/src/camel/camel-ews-store-summary.h b/src/camel/camel-ews-store-summary.h
index 1c6723cc..38cb7e1f 100644
--- a/src/camel/camel-ews-store-summary.h
+++ b/src/camel/camel-ews-store-summary.h
@@ -178,7 +178,8 @@ gboolean    camel_ews_store_summary_get_public
 
 GSList *       camel_ews_store_summary_get_folders
                                                (CamelEwsStoreSummary *ews_summary,
-                                                const gchar *prefix);
+                                                const gchar *prefix,
+                                                gboolean only_direct_subfolders);
 GSList *       camel_ews_store_summary_get_foreign_folders
                                                (CamelEwsStoreSummary *ews_summary,
                                                 const gchar *prefix);
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index 8b3003b0..d97845ee 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -378,11 +378,27 @@ ews_store_get_public_folders_name (CamelEwsStore *ews_store)
        return use_name;
 }
 
+static gboolean
+ews_store_show_public_folders (CamelEwsStore *ews_store)
+{
+       CamelSettings *settings;
+       gboolean show;
+
+       settings = camel_service_ref_settings (CAMEL_SERVICE (ews_store));
+
+       show = settings && camel_ews_settings_get_show_public_folders (CAMEL_EWS_SETTINGS (settings));
+
+       g_clear_object (&settings);
+
+       return show;
+}
+
 void
 camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
 {
        gboolean needs_foreign = FALSE, has_foreign = FALSE;
        gboolean needs_public = FALSE, has_public = FALSE;
+       gboolean show_public_folders;
        CamelFolderInfo *fi;
        GSList *folders, *iter;
        GHashTable *children_count;
@@ -391,10 +407,11 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
 
        g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
 
-       folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL);
+       folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL, FALSE);
        if (!folders)
                return;
 
+       show_public_folders = ews_store_show_public_folders (ews_store);
        children_count = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 
        for (iter = folders; iter; iter = iter->next) {
@@ -442,7 +459,7 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
                                guint64 fflags;
 
                                fflags = camel_ews_store_summary_get_folder_flags (ews_store->summary, fid, 
&error);
-                               if ((fflags & CAMEL_FOLDER_SUBSCRIBED) != 0 && !error) {
+                               if (show_public_folders || ((fflags & CAMEL_FOLDER_SUBSCRIBED) != 0 && 
!error)) {
                                        needs_public = TRUE;
 
                                        pfid = camel_ews_store_summary_get_parent_folder_id 
(ews_store->summary, fid, NULL);
@@ -460,6 +477,8 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
                g_clear_error (&error);
        }
 
+       needs_public = needs_public || show_public_folders;
+
        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);
@@ -467,6 +486,9 @@ camel_ews_store_ensure_virtual_folders (CamelEwsStore *ews_store)
                if (!count) {
                        CamelFolderInfo *fi;
 
+                       if (needs_public && g_str_equal (key, EWS_PUBLIC_FOLDER_ROOT_ID))
+                               continue;
+
                        if (has_foreign && g_str_equal (key, EWS_FOREIGN_FOLDER_ROOT_ID))
                                has_foreign = FALSE;
 
@@ -735,6 +757,171 @@ free_schedule_update_data (gpointer ptr)
        g_free (sud);
 }
 
+static GHashTable * /* gchar *id ~> gchar *change_key */
+ews_store_get_existing_folders_in_path (CamelEwsStore *ews_store,
+                                       const gchar *in_path)
+{
+       GHashTable *folders;
+       GSList *stored_folders, *link;
+
+       g_return_val_if_fail (CAMEL_IS_EWS_STORE (ews_store), NULL);
+       g_return_val_if_fail (in_path != NULL, NULL);
+
+       folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       stored_folders = camel_ews_store_summary_get_folders (ews_store->summary, in_path, TRUE);
+
+       for (link = stored_folders; link; link = g_slist_next (link)) {
+               g_hash_table_insert (folders, link->data,
+                       camel_ews_store_summary_get_change_key (ews_store->summary, link->data, NULL));
+       }
+
+       /* The ::data is used in 'folders', thus do not free it here */
+       g_slist_free (stored_folders);
+
+       return folders;
+}
+
+static gboolean
+ews_store_sync_public_folders (CamelEwsStore *ews_store,
+                              EEwsConnection *connection,
+                              const gchar *top,
+                              GSList **pfolders_created,
+                              GSList **pfolders_updated,
+                              GSList **pfolders_deleted,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+       gboolean includes_last_folder = TRUE;
+       GHashTable *existing_folders;
+       GSList *folders = NULL;
+       gchar *fid_str;
+       EwsFolderId *folder_id;
+       GError *local_error = NULL;
+
+       g_return_val_if_fail (pfolders_created != NULL, FALSE);
+       g_return_val_if_fail (pfolders_updated != NULL, FALSE);
+       g_return_val_if_fail (pfolders_deleted != NULL, FALSE);
+
+       /* Read only explicit 'Public Folders' hierarchy, and not recursively,
+          due to possibly deep/large Public Folders hierarchy */
+       if (!top || !*top || !g_str_has_prefix (top, EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME))
+               return TRUE;
+
+       existing_folders = ews_store_get_existing_folders_in_path (ews_store, top);
+       fid_str = camel_ews_store_summary_get_folder_id_from_name (ews_store->summary, top);
+
+       /* This should never be removed in this function */
+       g_hash_table_remove (existing_folders, EWS_PUBLIC_FOLDER_ROOT_ID);
+
+       if (!fid_str || g_strcmp0 (fid_str, EWS_PUBLIC_FOLDER_ROOT_ID) == 0)
+               folder_id = e_ews_folder_id_new ("publicfoldersroot", NULL, TRUE);
+       else
+               folder_id = e_ews_folder_id_new (fid_str, NULL, FALSE);
+
+       while (e_ews_connection_find_folder_sync (connection, EWS_PRIORITY_MEDIUM, folder_id, 
&includes_last_folder, &folders,
+               cancellable, &local_error) && !local_error &&
+               !g_cancellable_is_cancelled (cancellable)) {
+               GSList *fiter;
+
+               if (!folders)
+                       break;
+
+               for (fiter = folders; fiter != NULL; fiter = fiter->next) {
+                       EEwsFolder *folder = fiter->data;
+                       const EwsFolderId *fid;
+                       const gchar *existing_change_key;
+
+                       if (!folder || e_ews_folder_is_error (folder))
+                               continue;
+
+                       fid = e_ews_folder_get_id (folder);
+
+                       if (!fid)
+                               continue;
+
+                       if (!e_ews_folder_get_parent_id (folder)) {
+                               if (!folder_id->is_distinguished_id) {
+                                       e_ews_folder_set_parent_id (folder,
+                                               e_ews_folder_id_new (folder_id->id, folder_id->change_key, 
folder_id->is_distinguished_id));
+                               } else {
+                                       e_ews_folder_set_parent_id (folder, e_ews_folder_id_new 
(EWS_PUBLIC_FOLDER_ROOT_ID, NULL, FALSE));
+                               }
+                       }
+
+                       e_ews_folder_set_public (folder, TRUE);
+
+                       existing_change_key = g_hash_table_lookup (existing_folders, fid->id);
+
+                       if (!existing_change_key) {
+                               *pfolders_created = g_slist_prepend (*pfolders_created, g_object_ref 
(folder));
+                       } else {
+                               /* Always claim the folder as updated, thus the summary updates also folder
+                                  flags with information about child folders */
+                               *pfolders_updated = g_slist_prepend (*pfolders_updated, g_object_ref 
(folder));
+                       }
+
+                       g_hash_table_remove (existing_folders, fid->id);
+               }
+
+               g_slist_free_full (folders, g_object_unref);
+
+               if (includes_last_folder)
+                       break;
+       }
+
+       e_ews_folder_id_free (folder_id);
+       g_free (fid_str);
+
+       if (!local_error && g_hash_table_size (existing_folders) > 0) {
+               GHashTableIter iter;
+               gpointer key;
+
+               g_hash_table_iter_init (&iter, existing_folders);
+
+               while (g_hash_table_iter_next (&iter, &key, NULL)) {
+                       const gchar *id = key;
+                       gchar *full_name;
+                       GSList *removed_folders;
+
+                       full_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, id, 
NULL);
+
+                       if (!full_name) {
+                               *pfolders_deleted = g_slist_prepend (*pfolders_deleted, g_strdup (id));
+                               continue;
+                       }
+
+                       removed_folders = camel_ews_store_summary_get_folders (ews_store->summary, full_name, 
FALSE);
+
+                       if (removed_folders)
+                               *pfolders_deleted = g_slist_concat (*pfolders_deleted, removed_folders);
+
+                       g_free (full_name);
+               }
+       }
+
+       g_hash_table_destroy (existing_folders);
+
+       if (local_error) {
+               if (g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_FOLDERNOTFOUND) 
&&
+                   !g_str_equal (top, EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME)) {
+                       GSList *removed_folders;
+
+                       removed_folders = camel_ews_store_summary_get_folders (ews_store->summary, top, 
FALSE);
+
+                       if (removed_folders)
+                               *pfolders_deleted = g_slist_concat (*pfolders_deleted, removed_folders);
+               }
+
+               camel_ews_store_maybe_disconnect (ews_store, local_error);
+               g_propagate_error (error, local_error);
+
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 static gpointer
 camel_ews_folder_list_update_thread (gpointer user_data)
 {
@@ -779,6 +966,9 @@ camel_ews_folder_list_update_thread (gpointer user_data)
                goto exit;
        }
 
+       if (ews_store_show_public_folders (ews_store))
+               ews_store_sync_public_folders (ews_store, cnc, EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME, &created, 
&updated, &deleted, sud->cancellable, NULL);
+
        if (created != NULL || updated != NULL || deleted != NULL) {
                ews_update_folder_hierarchy (
                                ews_store,
@@ -1506,8 +1696,10 @@ ews_store_set_flags (CamelEwsStore *ews_store,
                if (folder && !e_ews_folder_is_error (folder)) {
                        fid = e_ews_folder_get_id (folder);
 
-                       if (camel_ews_store_summary_has_folder (ews_store->summary, fid->id))
-                               camel_ews_store_summary_set_folder_flags (ews_store->summary, fid->id, 
system_folder[n].info_flags);
+                       if (camel_ews_store_summary_has_folder (ews_store->summary, fid->id)) {
+                               camel_ews_store_summary_set_folder_flags (ews_store->summary, fid->id, 
system_folder[n].info_flags |
+                                       (camel_ews_store_summary_get_folder_flags (ews_store->summary, 
fid->id, NULL) & (CAMEL_FOLDER_CHILDREN | CAMEL_FOLDER_NOCHILDREN)));
+                       }
                }
 
                temp = temp->next;
@@ -1526,7 +1718,7 @@ ews_store_forget_all_folders (CamelEwsStore *ews_store)
 
        store = CAMEL_STORE (ews_store);
        subscribable = CAMEL_SUBSCRIBABLE (ews_store);
-       folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL);
+       folders = camel_ews_store_summary_get_folders (ews_store->summary, NULL, FALSE);
 
        if (!folders)
                return;
@@ -1630,7 +1822,7 @@ ews_store_update_foreign_subfolders (CamelSession *session,
        if (!local_error && !g_cancellable_is_cancelled (cancellable)) {
                gchar *full_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, 
euf->folder_id, NULL);
                if (full_name) {
-                       local_folders = camel_ews_store_summary_get_folders (ews_store->summary, full_name);
+                       local_folders = camel_ews_store_summary_get_folders (ews_store->summary, full_name, 
FALSE);
                }
                g_free (full_name);
        }
@@ -2215,6 +2407,38 @@ ews_store_has_as_parent_id (CamelEwsStoreSummary *ews_summary,
        return found;
 }
 
+static gboolean
+ews_store_folder_is_direct_subfolder (CamelEwsStore *ews_store,
+                                     const gchar *fid,
+                                     const gchar *path)
+{
+       gchar *fid_path;
+       gboolean res;
+
+       g_return_val_if_fail (CAMEL_IS_EWS_STORE (ews_store), FALSE);
+       g_return_val_if_fail (fid != NULL, FALSE);
+       g_return_val_if_fail (path != NULL, FALSE);
+
+       fid_path = camel_ews_store_summary_get_folder_full_name (ews_store->summary, fid, NULL);
+
+       if (!fid_path)
+               return FALSE;
+
+       res = g_str_has_prefix (fid_path, path);
+
+       if (res) {
+               gint path_len;
+
+               path_len = strlen (path);
+
+               res = fid_path[path_len] == '/' && !strchr (fid_path + path_len + 1, '/');
+       }
+
+       g_free (fid_path);
+
+       return res;
+}
+
 static CamelFolderInfo *
 folder_info_from_store_summary (CamelEwsStore *store,
                                 const gchar *top,
@@ -2347,12 +2571,17 @@ folder_info_from_store_summary (CamelEwsStore *store,
        } else {
                GSList *folders, *fiter;
                gchar *mailroot_fid = NULL, *inbox_fid;
+               gboolean show_public_folders, is_in_public_folders_root;
+               gboolean is_online;
 
                ews_summary = store->summary;
-               folders = camel_ews_store_summary_get_folders (ews_summary, top);
+               folders = camel_ews_store_summary_get_folders (ews_summary, top, FALSE);
                if (!folders)
                        return NULL;
 
+               show_public_folders = ews_store_show_public_folders (store);
+               is_in_public_folders_root = top && g_str_has_prefix (top, 
EWS_PUBLIC_FOLDER_ROOT_DISPLAY_NAME);
+               is_online = camel_offline_store_get_online (CAMEL_OFFLINE_STORE (store));
                inbox_fid = camel_ews_store_summary_get_folder_id_from_folder_type (ews_summary, 
CAMEL_FOLDER_TYPE_INBOX);
                if (inbox_fid) {
                        mailroot_fid = camel_ews_store_summary_get_parent_folder_id (ews_summary, inbox_fid, 
NULL);
@@ -2370,18 +2599,25 @@ folder_info_from_store_summary (CamelEwsStore *store,
                        if (ftype != E_EWS_FOLDER_TYPE_MAILBOX)
                                continue;
 
-                       if (camel_ews_store_summary_get_public (ews_summary, fid, NULL)) {
-                               guint64 fflags;
+                       if (camel_ews_store_summary_get_public (ews_summary, fid, NULL) ||
+                           (show_public_folders && g_strcmp0 (fid, EWS_PUBLIC_FOLDER_ROOT_ID) == 0)) {
+                               if (!show_public_folders || (!is_in_public_folders_root && g_strcmp0 (fid, 
EWS_PUBLIC_FOLDER_ROOT_ID) != 0)) {
+                                       guint64 fflags;
 
-                               fflags = camel_ews_store_summary_get_folder_flags (ews_summary, fid, NULL);
-                               if (!(fflags & CAMEL_FOLDER_SUBSCRIBED))
-                                       continue;
+                                       fflags = camel_ews_store_summary_get_folder_flags (ews_summary, fid, 
NULL);
+                                       if (!(fflags & CAMEL_FOLDER_SUBSCRIBED))
+                                               continue;
+                               }
                        } else if (!camel_ews_store_summary_get_foreign (ews_summary, fid, NULL) &&
                                mailroot_fid && !ews_store_has_as_parent_id (ews_summary, fid, mailroot_fid)) 
{
                                /* Skip mail folders out of the msgfolderroot hierarchy */
                                continue;
                        }
 
+                       if (is_in_public_folders_root && is_online && show_public_folders &&
+                           g_strcmp0 (fid, EWS_PUBLIC_FOLDER_ROOT_ID) != 0 && 
!ews_store_folder_is_direct_subfolder (store, fid, top))
+                               continue;
+
                        fi = camel_ews_utils_build_folder_info (store, fid);
                        g_ptr_array_add (folder_infos, fi);
                }
@@ -2549,12 +2785,13 @@ ews_get_folder_info_sync (CamelStore *store,
        if (!old_sync_state)
                initial_setup = TRUE;
 
-       if (!initial_setup && (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) != 0) {
+       if (!initial_setup && (flags & CAMEL_STORE_FOLDER_INFO_REFRESH) != 0) {
                time_t now = time (NULL);
 
                g_free (old_sync_state);
                if (now - priv->last_refresh_time > FINFO_REFRESH_INTERVAL && ews_refresh_finfo (ews_store))
                        ews_store->priv->last_refresh_time = time (NULL);
+               else
 
                g_mutex_unlock (&priv->get_finfo_lock);
                goto offline;
@@ -2580,6 +2817,9 @@ ews_get_folder_info_sync (CamelStore *store,
                        cancellable, &local_error);
        }
 
+       if (success && ews_store_show_public_folders (ews_store))
+               ews_store_sync_public_folders (ews_store, connection, top, &folders_created, 
&folders_updated, &folders_deleted, cancellable, NULL);
+
        g_object_unref (connection);
 
        if (!success) {
@@ -3549,7 +3789,7 @@ ews_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
                        GSList *local_folders = NULL, *ii;
                        gchar *full_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, 
fid, NULL);
                        if (full_name) {
-                               local_folders = camel_ews_store_summary_get_folders (ews_store->summary, 
full_name);
+                               local_folders = camel_ews_store_summary_get_folders (ews_store->summary, 
full_name, FALSE);
                        }
                        g_free (full_name);
 
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index 39224277..914883a3 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -97,6 +97,9 @@ camel_ews_utils_build_folder_info (CamelEwsStore *store,
                }
        }
 
+       if (g_strcmp0 (fid, EWS_PUBLIC_FOLDER_ROOT_ID) == 0)
+               fi->flags |= CAMEL_FOLDER_CHILDREN;
+
        return fi;
 }
 
@@ -254,6 +257,11 @@ sync_updated_folders (CamelEwsStore *store,
                        g_clear_error (&error);
                }
  done:
+               if (e_ews_folder_get_public (ews_folder)) {
+                       camel_ews_store_summary_set_folder_flags (ews_summary, fid->id,
+                               e_ews_folder_get_child_count (ews_folder) > 0 ? CAMEL_FOLDER_CHILDREN : 
CAMEL_FOLDER_NOCHILDREN);
+               }
+
                g_free (folder_name);
                g_free (display_name);
        }
@@ -269,6 +277,7 @@ add_folder_to_summary (CamelEwsStore *store,
        const EwsFolderId *pfid, *fid;
        const gchar *dname;
        gint64 unread, total;
+       guint64 flags = 0;
        EEwsFolderType ftype;
 
        fid = e_ews_folder_get_id (folder);
@@ -277,13 +286,14 @@ add_folder_to_summary (CamelEwsStore *store,
        total = e_ews_folder_get_total_count (folder);
        unread = e_ews_folder_get_unread_count (folder);
        ftype = e_ews_folder_get_folder_type (folder);
+       flags = e_ews_folder_get_child_count (folder) ? CAMEL_FOLDER_CHILDREN : CAMEL_FOLDER_NOCHILDREN;
 
        camel_ews_store_summary_new_folder (
                ews_summary, fid->id,
                pfid ? pfid->id : NULL, fid->change_key,
-               dname, ftype, 0, total,
+               dname, ftype, flags, total,
                e_ews_folder_get_foreign (folder),
-               FALSE);
+               e_ews_folder_get_public (folder));
        camel_ews_store_summary_set_folder_unread (
                ews_summary, fid->id, unread);
 }
diff --git a/src/configuration/e-ews-config-utils.c b/src/configuration/e-ews-config-utils.c
index 1d44fd99..f740f586 100644
--- a/src/configuration/e-ews-config-utils.c
+++ b/src/configuration/e-ews-config-utils.c
@@ -675,7 +675,7 @@ ews_settings_get_folder_sizes_thread (gpointer user_data)
                ext_uri->prop_type = g_strdup ("Integer");
                add_props->extended_furis = g_slist_prepend (add_props->extended_furis, ext_uri);
 
-               ids = camel_ews_store_summary_get_folders (fsd->ews_store->summary, NULL);
+               ids = camel_ews_store_summary_get_folders (fsd->ews_store->summary, NULL, FALSE);
                for (l = ids; l != NULL; l = l->next) {
                        EwsFolderId *fid;
                        fid = e_ews_folder_id_new (l->data, NULL, FALSE);
diff --git a/src/server/camel-ews-settings.c b/src/server/camel-ews-settings.c
index 96034348..8f0e3714 100644
--- a/src/server/camel-ews-settings.c
+++ b/src/server/camel-ews-settings.c
@@ -34,6 +34,7 @@ struct _CamelEwsSettingsPrivate {
        gboolean filter_junk_inbox;
        gboolean oab_offline;
        gboolean use_impersonation;
+       gboolean show_public_folders;
        gchar *email;
        gchar *gal_uid;
        gchar *hosturl;
@@ -74,7 +75,8 @@ enum {
        PROP_OVERRIDE_OAUTH2,
        PROP_OAUTH2_TENANT,
        PROP_OAUTH2_CLIENT_ID,
-       PROP_OAUTH2_REDIRECT_URI
+       PROP_OAUTH2_REDIRECT_URI,
+       PROP_SHOW_PUBLIC_FOLDERS
 };
 
 G_DEFINE_TYPE_WITH_CODE (
@@ -263,6 +265,12 @@ ews_settings_set_property (GObject *object,
                                CAMEL_EWS_SETTINGS (object),
                                g_value_get_string (value));
                        return;
+
+               case PROP_SHOW_PUBLIC_FOLDERS:
+                       camel_ews_settings_set_show_public_folders (
+                               CAMEL_EWS_SETTINGS (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -442,6 +450,13 @@ ews_settings_get_property (GObject *object,
                                camel_ews_settings_dup_oauth2_redirect_uri (
                                CAMEL_EWS_SETTINGS (object)));
                        return;
+
+               case PROP_SHOW_PUBLIC_FOLDERS:
+                       g_value_set_boolean (
+                               value,
+                               camel_ews_settings_get_show_public_folders (
+                               CAMEL_EWS_SETTINGS (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -740,6 +755,18 @@ camel_ews_settings_class_init (CamelEwsSettingsClass *class)
                        G_PARAM_READWRITE |
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_SHOW_PUBLIC_FOLDERS,
+               g_param_spec_boolean (
+                       "show-public-folders",
+                       "Show Public Folders",
+                       NULL,
+                       FALSE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -1543,3 +1570,25 @@ camel_ews_settings_set_oauth2_redirect_uri (CamelEwsSettings *settings,
 
        g_object_notify (G_OBJECT (settings), "oauth2-redirect-uri");
 }
+
+gboolean
+camel_ews_settings_get_show_public_folders (CamelEwsSettings *settings)
+{
+       g_return_val_if_fail (CAMEL_IS_EWS_SETTINGS (settings), FALSE);
+
+       return settings->priv->show_public_folders;
+}
+
+void
+camel_ews_settings_set_show_public_folders (CamelEwsSettings *settings,
+                                           gboolean show_public_folders)
+{
+       g_return_if_fail (CAMEL_IS_EWS_SETTINGS (settings));
+
+       if ((settings->priv->show_public_folders ? 1 : 0) == (show_public_folders ? 1 : 0))
+               return;
+
+       settings->priv->show_public_folders = show_public_folders;
+
+       g_object_notify (G_OBJECT (settings), "show-public-folders");
+}
diff --git a/src/server/camel-ews-settings.h b/src/server/camel-ews-settings.h
index b4891595..8df535c2 100644
--- a/src/server/camel-ews-settings.h
+++ b/src/server/camel-ews-settings.h
@@ -167,6 +167,11 @@ gchar *            camel_ews_settings_dup_oauth2_redirect_uri
 void           camel_ews_settings_set_oauth2_redirect_uri
                                                (CamelEwsSettings *settings,
                                                 const gchar *redirect_uri);
+gboolean       camel_ews_settings_get_show_public_folders
+                                               (CamelEwsSettings *settings);
+void           camel_ews_settings_set_show_public_folders
+                                               (CamelEwsSettings *settings,
+                                                gboolean show_public_folders);
 
 G_END_DECLS
 
diff --git a/src/server/e-ews-folder.c b/src/server/e-ews-folder.c
index 86538882..5148487f 100644
--- a/src/server/e-ews-folder.c
+++ b/src/server/e-ews-folder.c
@@ -46,6 +46,7 @@ struct _EEwsFolderPrivate {
        guint64 size;
        gboolean foreign;
        gchar *foreign_mail;
+       gboolean is_public;
 };
 
 static void
@@ -108,6 +109,7 @@ e_ews_folder_init (EEwsFolder *folder)
        folder->priv->error = NULL;
        folder->priv->folder_type = E_EWS_FOLDER_TYPE_UNKNOWN;
        folder->priv->foreign = FALSE;
+       folder->priv->is_public = FALSE;
 }
 
 static gboolean
@@ -554,6 +556,23 @@ e_ews_folder_set_foreign_mail (EEwsFolder *folder,
        folder->priv->foreign_mail = g_strdup (foreign_mail);
 }
 
+gboolean
+e_ews_folder_get_public (const EEwsFolder *folder)
+{
+       g_return_val_if_fail (E_IS_EWS_FOLDER (folder), FALSE);
+
+       return folder->priv->is_public;
+}
+
+void
+e_ews_folder_set_public (EEwsFolder *folder,
+                        gboolean is_public)
+{
+       g_return_if_fail (E_IS_EWS_FOLDER (folder));
+
+       folder->priv->is_public = is_public;
+}
+
 /* escapes backslashes with \5C and forward slashes with \2F */
 gchar *
 e_ews_folder_utils_escape_name (const gchar *folder_name)
diff --git a/src/server/e-ews-folder.h b/src/server/e-ews-folder.h
index 4164fc3a..f07957e9 100644
--- a/src/server/e-ews-folder.h
+++ b/src/server/e-ews-folder.h
@@ -82,6 +82,8 @@ gboolean      e_ews_folder_get_foreign (const EEwsFolder *folder);
 void           e_ews_folder_set_foreign (EEwsFolder *folder, gboolean is_foreign);
 const gchar *  e_ews_folder_get_foreign_mail (const EEwsFolder *folder);
 void           e_ews_folder_set_foreign_mail (EEwsFolder *folder, const gchar *foreign_mail);
+gboolean       e_ews_folder_get_public (const EEwsFolder *folder);
+void           e_ews_folder_set_public (EEwsFolder *folder, gboolean is_public);
 
 EwsFolderId *  e_ews_folder_id_new (const gchar *id,
                                     const gchar *change_key,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]