[evolution-ews/wip/mcrha/office365: 16/50] Added CamelO365StoreSummary
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews/wip/mcrha/office365: 16/50] Added CamelO365StoreSummary
- Date: Mon, 3 Aug 2020 15:24:07 +0000 (UTC)
commit f5e0de071954d3f695b4b8713ab3371019691f9d
Author: Milan Crha <mcrha redhat com>
Date: Wed Jun 10 17:43:44 2020 +0200
Added CamelO365StoreSummary
src/Office365/camel/CMakeLists.txt | 2 +
src/Office365/camel/camel-o365-store-summary.c | 585 +++++++++++++++++++++
src/Office365/camel/camel-o365-store-summary.h | 138 +++++
src/Office365/common/CMakeLists.txt | 5 +
src/Office365/common/e-o365-connection.c | 85 ++-
src/Office365/common/e-o365-connection.h | 3 +-
src/Office365/common/e-o365-enums.h | 37 ++
.../evolution/e-mail-config-o365-backend.c | 2 +-
8 files changed, 844 insertions(+), 13 deletions(-)
---
diff --git a/src/Office365/camel/CMakeLists.txt b/src/Office365/camel/CMakeLists.txt
index 56e506b9..65b471e1 100644
--- a/src/Office365/camel/CMakeLists.txt
+++ b/src/Office365/camel/CMakeLists.txt
@@ -10,6 +10,8 @@ set(SOURCES
camel-o365-provider.c
camel-o365-store.c
camel-o365-store.h
+ camel-o365-store-summary.c
+ camel-o365-store-summary.h
camel-o365-transport.c
camel-o365-transport.h
)
diff --git a/src/Office365/camel/camel-o365-store-summary.c b/src/Office365/camel/camel-o365-store-summary.c
new file mode 100644
index 00000000..068b4637
--- /dev/null
+++ b/src/Office365/camel/camel-o365-store-summary.c
@@ -0,0 +1,585 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2020 Red Hat (www.redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-ews-config.h"
+
+#include <string.h>
+
+#include "camel-o365-store-summary.h"
+
+#define STORE_GROUP_NAME "##storepriv##"
+#define DATA_VERSION 1
+
+#define LOCK(summary) g_rec_mutex_lock (&(summary->priv->property_lock))
+#define UNLOCK(summary) g_rec_mutex_unlock (&(summary->priv->property_lock))
+
+struct _CamelO365StoreSummaryPrivate {
+ GRecMutex property_lock;
+ gchar *path;
+ GKeyFile *key_file;
+ GFileMonitor *monitor_delete;
+ gboolean dirty;
+
+ /* Note: We use the *same* strings in both of these hash tables, and
+ * only id_fname_hash has g_free() hooked up as the destructor func.
+ * So entries must always be removed from fname_id_hash *first*. */
+ GHashTable *id_fname_hash; /* id ~> folder name */
+ GHashTable *fname_id_hash; /* folder name ~> id */
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (CamelO365StoreSummary, camel_o365_store_summary, G_TYPE_OBJECT)
+
+static void
+camel_o365_store_summary_migrate_data_locked (CamelO365StoreSummary *store_summary,
+ gint from_version)
+{
+ /* Here will be any future migration of old data in the summary to new data. */
+
+ g_key_file_set_integer (store_summary->priv->key_file, STORE_GROUP_NAME, "Version", DATA_VERSION);
+}
+
+static void
+o365_store_summary_delete_cb (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ CamelO365StoreSummary *store_summary = user_data;
+
+ if (event == G_FILE_MONITOR_EVENT_DELETED) {
+ LOCK (store_summary);
+
+ if (store_summary->priv->key_file)
+ camel_o365_store_summary_clear (store_summary);
+
+ UNLOCK (store_summary);
+ }
+}
+
+static void
+o365_store_summary_dispose (GObject *object)
+{
+ CamelO365StoreSummary *store_summary = CAMEL_O365_STORE_SUMMARY (object);
+
+ LOCK (store_summary);
+
+ if (store_summary->priv->monitor_delete) {
+ g_signal_handlers_disconnect_by_func (store_summary->priv->monitor_delete,
+ G_CALLBACK (o365_store_summary_delete_cb), store_summary);
+
+ g_clear_object (&store_summary->priv->monitor_delete);
+ }
+
+ UNLOCK (store_summary);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_o365_store_summary_parent_class)->dispose (object);
+}
+
+static void
+o365_store_summary_finalize (GObject *object)
+{
+ CamelO365StoreSummary *store_summary = CAMEL_O365_STORE_SUMMARY (object);
+
+ g_rec_mutex_clear (&store_summary->priv->property_lock);
+ g_hash_table_destroy (store_summary->priv->id_fname_hash);
+ g_hash_table_destroy (store_summary->priv->fname_id_hash);
+ g_key_file_free (store_summary->priv->key_file);
+ g_free (store_summary->priv->path);
+
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (camel_o365_store_summary_parent_class)->finalize (object);
+}
+
+static void
+camel_o365_store_summary_class_init (CamelO365StoreSummaryClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->dispose = o365_store_summary_dispose;
+ object_class->finalize = o365_store_summary_finalize;
+}
+
+static void
+camel_o365_store_summary_init (CamelO365StoreSummary *store_summary)
+{
+ store_summary->priv = camel_o365_store_summary_get_instance_private (store_summary);
+ store_summary->priv->key_file = g_key_file_new ();
+ store_summary->priv->id_fname_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ store_summary->priv->fname_id_hash = g_hash_table_new (g_str_hash, g_str_equal); /* shared data with
'id_fname_hash' */
+
+ g_rec_mutex_init (&store_summary->priv->property_lock);
+}
+
+CamelO365StoreSummary *
+camel_o365_store_summary_new (const gchar *path)
+{
+ CamelO365StoreSummary *store_summary;
+ GError *error = NULL;
+ GFile *file;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ file = g_file_new_for_path (path);
+
+ store_summary = g_object_new (CAMEL_TYPE_O365_STORE_SUMMARY, NULL);
+ store_summary->priv->path = g_strdup (path);
+ store_summary->priv->monitor_delete = g_file_monitor_file (file, G_FILE_MONITOR_SEND_MOVED, NULL,
&error);
+
+ if (!error) {
+ g_signal_connect (
+ store_summary->priv->monitor_delete, "changed",
+ G_CALLBACK (o365_store_summary_delete_cb), store_summary);
+ } else {
+ g_warning ("%s: Failed to create monitor_delete: %s", G_STRFUNC, error->message);
+ g_clear_error (&error);
+ }
+
+ g_object_unref (file);
+
+ return store_summary;
+}
+
+gboolean
+camel_o365_store_summary_load (CamelO365StoreSummary *store_summary,
+ GError **error)
+{
+ gboolean success;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary), FALSE);
+
+ LOCK (store_summary);
+
+ success = g_key_file_load_from_file (store_summary->priv->key_file, store_summary->priv->path,
G_KEY_FILE_NONE, &local_error);
+
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
+ g_key_file_set_integer (store_summary->priv->key_file, STORE_GROUP_NAME, "Version",
DATA_VERSION);
+
+ g_clear_error (&local_error);
+ success = TRUE;
+ } else if (local_error) {
+ g_propagate_error (error, local_error);
+ } else {
+ gint version;
+
+ version = g_key_file_get_integer (store_summary->priv->key_file, STORE_GROUP_NAME, "Version",
NULL);
+
+ if (version && version < DATA_VERSION)
+ camel_o365_store_summary_migrate_data_locked (store_summary, version);
+ }
+
+ UNLOCK (store_summary);
+
+ return success;
+}
+
+gboolean
+camel_o365_store_summary_save (CamelO365StoreSummary *store_summary,
+ GError **error)
+{
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary), FALSE);
+
+ LOCK (store_summary);
+
+ if (store_summary->priv->dirty) {
+ success = g_key_file_save_to_file (store_summary->priv->key_file, store_summary->priv->path,
error);
+
+ if (success)
+ store_summary->priv->dirty = FALSE;
+ }
+
+ UNLOCK (store_summary);
+
+ return success;
+}
+
+void
+camel_o365_store_summary_clear (CamelO365StoreSummary *store_summary)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+
+ LOCK (store_summary);
+
+ store_summary->priv->dirty = g_hash_table_size (store_summary->priv->id_fname_hash) > 0;
+
+ g_key_file_free (store_summary->priv->key_file);
+ store_summary->priv->key_file = g_key_file_new ();
+
+ g_hash_table_remove_all (store_summary->priv->fname_id_hash);
+ g_hash_table_remove_all (store_summary->priv->id_fname_hash);
+
+ UNLOCK (store_summary);
+}
+
+void
+camel_o365_store_summary_lock (CamelO365StoreSummary *store_summary)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+
+ LOCK (store_summary);
+}
+
+void
+camel_o365_store_summary_unlock (CamelO365StoreSummary *store_summary)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+
+ UNLOCK (store_summary);
+}
+
+void
+camel_o365_store_summary_set_delta_link (CamelO365StoreSummary *store_summary,
+ const gchar *delta_link)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+
+ LOCK (store_summary);
+
+ g_key_file_set_string (store_summary->priv->key_file, STORE_GROUP_NAME, "DeltaLink", delta_link ?
delta_link : "");
+
+ store_summary->priv->dirty = TRUE;
+
+ UNLOCK (store_summary);
+}
+
+gchar *
+camel_o365_store_summary_dup_delta_link (CamelO365StoreSummary *store_summary)
+{
+ gchar *value;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary), NULL);
+
+ LOCK (store_summary);
+
+ value = g_key_file_get_string (store_summary->priv->key_file, STORE_GROUP_NAME, "DeltaLink", NULL);
+
+ UNLOCK (store_summary);
+
+ if (value && !*value) {
+ g_clear_pointer (&value, g_free);
+ }
+
+ return value;
+}
+
+void
+camel_o365_store_summary_set_folder (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *parent_id,
+ const gchar *display_name,
+ gint32 total_count,
+ gint32 unread_count,
+ guint32 flags,
+ EO365FolderKind kind,
+ gboolean is_foreign,
+ gboolean is_public)
+{
+ gboolean changed;
+
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+ g_return_if_fail (display_name != NULL);
+
+ LOCK (store_summary);
+
+ camel_o365_store_summary_set_folder_display_name (store_summary, id, display_name);
+ camel_o365_store_summary_set_folder_parent_id (store_summary, id, parent_id);
+ camel_o365_store_summary_set_folder_total_count (store_summary, id, total_count);
+ camel_o365_store_summary_set_folder_unread_count (store_summary, id, unread_count);
+ camel_o365_store_summary_set_folder_flags (store_summary, id, flags);
+
+ if (g_key_file_get_integer (store_summary->priv->key_file, id, "Kind", NULL) != kind) {
+ g_key_file_set_integer (store_summary->priv->key_file, id, "Kind", kind);
+ changed = TRUE;
+ }
+
+ if (g_key_file_get_boolean (store_summary->priv->key_file, id, "IsForeign", NULL) != is_foreign) {
+ g_key_file_set_boolean (store_summary->priv->key_file, id, "IsForeign", is_foreign);
+ changed = TRUE;
+ }
+
+ if (g_key_file_get_boolean (store_summary->priv->key_file, id, "IsPublic", NULL) != is_public) {
+ g_key_file_set_boolean (store_summary->priv->key_file, id, "IsPublic", is_public);
+ changed = TRUE;
+ }
+
+ if (changed)
+ store_summary->priv->dirty = TRUE;
+
+ UNLOCK (store_summary);
+}
+
+gboolean
+camel_o365_store_summary_get_folder (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gchar **out_parent_id,
+ gchar **out_display_name,
+ gint32 *out_total_count,
+ gint32 *out_unread_count,
+ guint32 *out_flags,
+ EO365FolderKind *out_kind,
+ gboolean *out_is_foreign,
+ gboolean *out_is_public)
+{
+ gboolean found;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary), FALSE);
+ g_return_val_if_fail (id != NULL, FALSE);
+
+ LOCK (store_summary);
+
+ found = g_key_file_has_group (store_summary->priv->key_file, id);
+
+ if (found) {
+ if (out_display_name)
+ *out_display_name = g_key_file_get_string (store_summary->priv->key_file, id,
"DisplayName", NULL);
+
+ if (out_parent_id)
+ *out_parent_id = g_key_file_get_string (store_summary->priv->key_file, id,
"ParentId", NULL);
+
+ if (out_total_count)
+ *out_total_count = g_key_file_get_integer (store_summary->priv->key_file, id,
"TotalCount", NULL);
+
+ if (out_unread_count)
+ *out_unread_count = g_key_file_get_integer (store_summary->priv->key_file, id,
"UnreadCount", NULL);
+
+ if (out_flags)
+ *out_flags = g_key_file_get_uint64 (store_summary->priv->key_file, id, "Flags", NULL);
+
+ if (out_kind)
+ *out_kind = g_key_file_get_integer (store_summary->priv->key_file, id, "Kind", NULL);
+
+ if (out_is_foreign)
+ *out_is_foreign = g_key_file_get_boolean (store_summary->priv->key_file, id,
"IsForeign", NULL);
+
+ if (out_is_public)
+ *out_is_public = g_key_file_get_boolean (store_summary->priv->key_file, id,
"IsPublic", NULL);
+ }
+
+ UNLOCK (store_summary);
+
+ return found;
+}
+
+void
+camel_o365_store_summary_set_folder_parent_id (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *parent_id)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+
+ LOCK (store_summary);
+
+ if (parent_id && *parent_id) {
+ gchar *current_parent_id;
+
+ current_parent_id = g_key_file_get_string (store_summary->priv->key_file, id, "ParentId",
NULL);
+
+ if (g_strcmp0 (current_parent_id, parent_id) != 0) {
+ g_key_file_set_string (store_summary->priv->key_file, id, "ParentId", parent_id);
+ store_summary->priv->dirty = TRUE;
+ }
+
+ g_free (current_parent_id);
+ } else if (g_key_file_has_key (store_summary->priv->key_file, id, "ParentId", NULL)) {
+ g_key_file_remove_key (store_summary->priv->key_file, id, "ParentId", NULL);
+ store_summary->priv->dirty = TRUE;
+ }
+
+ UNLOCK (store_summary);
+}
+
+gchar *
+camel_o365_store_summary_dup_folder_parent_id (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gchar *value = NULL;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, &value, NULL, NULL, NULL, NULL, NULL,
NULL, NULL))
+ value = NULL;
+
+ return value;
+}
+
+void
+camel_o365_store_summary_set_folder_display_name (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *display_name)
+{
+ const gchar *current_display_name;
+
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+ g_return_if_fail (display_name != NULL);
+
+ LOCK (store_summary);
+
+ current_display_name = g_hash_table_lookup (store_summary->priv->id_fname_hash, id);
+
+ if (g_strcmp0 (current_display_name, display_name) != 0) {
+ g_key_file_set_string (store_summary->priv->key_file, id, "DisplayName", display_name);
+ store_summary->priv->dirty = TRUE;
+
+ // TODO: update hashes on display name change
+ }
+
+ UNLOCK (store_summary);
+}
+
+gchar *
+camel_o365_store_summary_dup_folder_display_name (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gchar *value = NULL;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, &value, NULL, NULL, NULL, NULL,
NULL, NULL))
+ value = NULL;
+
+ return value;
+}
+
+void
+camel_o365_store_summary_set_folder_total_count (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gint32 total_count)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+
+ LOCK (store_summary);
+
+ if (g_key_file_get_integer (store_summary->priv->key_file, id, "TotalCount", NULL) != total_count) {
+ g_key_file_set_integer (store_summary->priv->key_file, id, "TotalCount", total_count);
+ store_summary->priv->dirty = TRUE;
+ }
+
+ UNLOCK (store_summary);
+}
+
+gint32
+camel_o365_store_summary_get_folder_total_count (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gint32 value = 0;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, &value, NULL, NULL, NULL,
NULL, NULL))
+ value = 0;
+
+ return value;
+}
+
+void
+camel_o365_store_summary_set_folder_unread_count (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gint32 unread_count)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+
+ LOCK (store_summary);
+
+ if (g_key_file_get_integer (store_summary->priv->key_file, id, "UnreadCount", NULL) != unread_count) {
+ g_key_file_set_integer (store_summary->priv->key_file, id, "UnreadCount", unread_count);
+ store_summary->priv->dirty = TRUE;
+ }
+
+ UNLOCK (store_summary);
+}
+
+gint32
+camel_o365_store_summary_get_folder_unread_count (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gint32 value = 0;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, NULL, &value, NULL, NULL,
NULL, NULL))
+ value = 0;
+
+ return value;
+}
+
+void
+camel_o365_store_summary_set_folder_flags (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ guint32 flags)
+{
+ g_return_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary));
+ g_return_if_fail (id != NULL);
+
+ LOCK (store_summary);
+
+ if (g_key_file_get_uint64 (store_summary->priv->key_file, id, "Flags", NULL) != flags) {
+ g_key_file_set_uint64 (store_summary->priv->key_file, id, "Flags", flags);
+ store_summary->priv->dirty = TRUE;
+ }
+
+ UNLOCK (store_summary);
+}
+
+guint32
+camel_o365_store_summary_get_folder_flags (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ guint32 value = 0;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, NULL, NULL, &value, NULL,
NULL, NULL))
+ value = 0;
+
+ return value;
+}
+
+EO365FolderKind
+camel_o365_store_summary_get_folder_kind (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ EO365FolderKind value = E_O365_FOLDER_KIND_UNKNOWN;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, NULL, NULL, NULL, &value,
NULL, NULL))
+ value = E_O365_FOLDER_KIND_UNKNOWN;
+
+ return value;
+}
+
+gboolean
+camel_o365_store_summary_get_folder_is_foreign (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gboolean value = FALSE;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, NULL, NULL, NULL, NULL,
&value, NULL))
+ value = FALSE;
+
+ return value;
+}
+
+gboolean
+camel_o365_store_summary_get_folder_is_public (CamelO365StoreSummary *store_summary,
+ const gchar *id)
+{
+ gboolean value = FALSE;
+
+ if (!camel_o365_store_summary_get_folder (store_summary, id, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, &value))
+ value = FALSE;
+
+ return value;
+}
diff --git a/src/Office365/camel/camel-o365-store-summary.h b/src/Office365/camel/camel-o365-store-summary.h
new file mode 100644
index 00000000..6a24463d
--- /dev/null
+++ b/src/Office365/camel/camel-o365-store-summary.h
@@ -0,0 +1,138 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2020 Red Hat (www.redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CAMEL_O365_STORE_SUMMARY_H
+#define CAMEL_O365_STORE_SUMMARY_H
+
+#include <camel/camel.h>
+
+#include "common/e-o365-enums.h"
+
+/* Standard GObject macros */
+#define CAMEL_TYPE_O365_STORE_SUMMARY \
+ (camel_o365_store_summary_get_type ())
+#define CAMEL_O365_STORE_SUMMARY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), CAMEL_TYPE_O365_STORE_SUMMARY, CamelO365StoreSummary))
+#define CAMEL_O365_STORE_SUMMARY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), CAMEL_TYPE_O365_STORE_SUMMARY, CamelO365StoreSummaryClass))
+#define CAMEL_IS_O365_STORE_SUMMARY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), CAMEL_TYPE_O365_STORE_SUMMARY))
+#define CAMEL_IS_O365_STORE_SUMMARY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), CAMEL_TYPE_O365_STORE_SUMMARY))
+#define CAMEL_O365_STORE_SUMMARY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), CAMEL_TYPE_O365_STORE_SUMMARY, CamelO365StoreSummaryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _CamelO365StoreSummary CamelO365StoreSummary;
+typedef struct _CamelO365StoreSummaryClass CamelO365StoreSummaryClass;
+typedef struct _CamelO365StoreSummaryPrivate CamelO365StoreSummaryPrivate;
+
+struct _CamelO365StoreSummary {
+ GObject parent;
+ CamelO365StoreSummaryPrivate *priv;
+};
+
+struct _CamelO365StoreSummaryClass {
+ GObjectClass parent_class;
+};
+
+GType camel_o365_store_summary_get_type (void);
+
+CamelO365StoreSummary *
+ camel_o365_store_summary_new (const gchar *path);
+gboolean camel_o365_store_summary_load (CamelO365StoreSummary *store_summary,
+ GError **error);
+gboolean camel_o365_store_summary_save (CamelO365StoreSummary *store_summary,
+ GError **error);
+void camel_o365_store_summary_clear (CamelO365StoreSummary *store_summary);
+void camel_o365_store_summary_lock (CamelO365StoreSummary *store_summary);
+void camel_o365_store_summary_unlock (CamelO365StoreSummary *store_summary);
+void camel_o365_store_summary_set_delta_link (CamelO365StoreSummary *store_summary,
+ const gchar *delta_link);
+gchar * camel_o365_store_summary_dup_delta_link (CamelO365StoreSummary *store_summary);
+void camel_o365_store_summary_set_folder (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *parent_id,
+ const gchar *display_name,
+ gint32 total_count,
+ gint32 unread_count,
+ guint32 flags,
+ EO365FolderKind kind,
+ gboolean is_foreign,
+ gboolean is_public);
+gboolean camel_o365_store_summary_get_folder (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gchar **out_parent_id,
+ gchar **out_display_name,
+ gint32 *out_total_count,
+ gint32 *out_unread_count,
+ guint32 *out_flags,
+ EO365FolderKind *out_kind,
+ gboolean *out_is_foreign,
+ gboolean *out_is_public);
+void camel_o365_store_summary_set_folder_parent_id
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *parent_id);
+gchar * camel_o365_store_summary_dup_folder_parent_id
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+void camel_o365_store_summary_set_folder_display_name
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ const gchar *display_name);
+gchar * camel_o365_store_summary_dup_folder_display_name
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+void camel_o365_store_summary_set_folder_total_count
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gint32 total_count);
+gint32 camel_o365_store_summary_get_folder_total_count
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+void camel_o365_store_summary_set_folder_unread_count
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ gint32 unread_count);
+gint32 camel_o365_store_summary_get_folder_unread_count
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+void camel_o365_store_summary_set_folder_flags
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id,
+ guint32 flags);
+guint32 camel_o365_store_summary_get_folder_flags
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+EO365FolderKind camel_o365_store_summary_get_folder_kind(CamelO365StoreSummary *store_summary,
+ const gchar *id);
+gboolean camel_o365_store_summary_get_folder_is_foreign
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+gboolean camel_o365_store_summary_get_folder_is_public
+ (CamelO365StoreSummary *store_summary,
+ const gchar *id);
+G_END_DECLS
+
+#endif /* CAMEL_O365_STORE_SUMMARY_H */
diff --git a/src/Office365/common/CMakeLists.txt b/src/Office365/common/CMakeLists.txt
index 8fa026c0..65090442 100644
--- a/src/Office365/common/CMakeLists.txt
+++ b/src/Office365/common/CMakeLists.txt
@@ -1,3 +1,5 @@
+glib_mkenums(e-o365-enumtypes e-o365-enums.h E_O365_ENUMTYPES_H)
+
set(SOURCES
camel-sasl-xoauth2-office365.c
camel-sasl-xoauth2-office365.h
@@ -5,6 +7,7 @@ set(SOURCES
camel-o365-settings.h
e-o365-connection.c
e-o365-connection.h
+ e-o365-enums.h
e-o365-json-utils.c
e-o365-json-utils.h
e-o365-soup-logger.c
@@ -13,6 +16,8 @@ set(SOURCES
e-oauth2-service-office365.h
e-source-o365-folder.c
e-source-o365-folder.h
+ ${CMAKE_CURRENT_BINARY_DIR}/e-o365-enumtypes.c
+ ${CMAKE_CURRENT_BINARY_DIR}/e-o365-enumtypes.h
)
add_library(evolution-office365 SHARED
diff --git a/src/Office365/common/e-o365-connection.c b/src/Office365/common/e-o365-connection.c
index 2da65b34..ddb731b0 100644
--- a/src/Office365/common/e-o365-connection.c
+++ b/src/Office365/common/e-o365-connection.c
@@ -827,6 +827,53 @@ o365_connection_request_cancelled_cb (GCancellable *cancellable,
e_flag_set (flag);
}
+/* An example error response:
+
+ {
+ "error": {
+ "code": "BadRequest",
+ "message": "Parsing Select and Expand failed.",
+ "innerError": {
+ "request-id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
+ "date": "2020-06-10T13:44:43"
+ }
+ }
+ }
+
+ */
+static gboolean
+o365_connection_extract_error (JsonNode *node,
+ guint status_code,
+ GError **error)
+{
+ JsonObject *object;
+ const gchar *code, *message;
+
+ if (!node || !JSON_NODE_HOLDS_OBJECT (node))
+ return FALSE;
+
+ object = e_o365_json_get_object_member (json_node_get_object (node), "error");
+
+ if (!object)
+ return FALSE;
+
+ code = e_o365_json_get_string_member (object, "code", NULL);
+ message = e_o365_json_get_string_member (object, "message", NULL);
+
+ if (!code && !message)
+ return FALSE;
+
+ if (!status_code || !SOUP_STATUS_IS_SUCCESSFUL (status_code))
+ status_code = SOUP_STATUS_MALFORMED;
+
+ if (code && message)
+ g_set_error (error, SOUP_HTTP_ERROR, status_code, "%s: %s", code, message);
+ else
+ g_set_error_literal (error, SOUP_HTTP_ERROR, status_code, code ? code : message);
+
+ return TRUE;
+}
+
typedef gboolean (* EO365ResponseFunc) (EO365Connection *cnc,
SoupMessage *message,
GInputStream *input_stream,
@@ -984,6 +1031,9 @@ o365_connection_send_request_sync (EO365Connection *cnc,
json_parser = json_parser_new_immutable ();
success = json_parser_load_from_stream (json_parser, input_stream,
cancellable, error);
+
+ if (success && error && !*error)
+ success = !o365_connection_extract_error
(json_parser_get_root (json_parser), message->status_code, error);
}
if (success) {
@@ -1011,6 +1061,14 @@ o365_connection_send_request_sync (EO365Connection *cnc,
}
g_free (next_link);
+ } else if (error && !*error && message->status_code &&
!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
+ if (message->status_code == SOUP_STATUS_CANCELLED) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ message->reason_phrase ? message->reason_phrase :
soup_status_get_phrase (message->status_code));
+ } else {
+ g_set_error_literal (error, SOUP_HTTP_ERROR,
message->status_code,
+ message->reason_phrase ? message->reason_phrase :
soup_status_get_phrase (message->status_code));
+ }
}
g_clear_object (&json_parser);
@@ -1021,8 +1079,13 @@ o365_connection_send_request_sync (EO365Connection *cnc,
if (!message->status_code)
soup_message_set_status (message, SOUP_STATUS_CANCELLED);
- g_set_error_literal (error, SOUP_HTTP_ERROR, message->status_code,
- message->reason_phrase ? message->reason_phrase : soup_status_get_phrase
(message->status_code));
+ if (message->status_code == SOUP_STATUS_CANCELLED) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ message->reason_phrase ? message->reason_phrase :
soup_status_get_phrase (message->status_code));
+ } else {
+ g_set_error_literal (error, SOUP_HTTP_ERROR, message->status_code,
+ message->reason_phrase ? message->reason_phrase :
soup_status_get_phrase (message->status_code));
+ }
}
g_clear_object (&soup_session);
@@ -1265,15 +1328,15 @@ e_o365_connection_list_folders_sync (EO365Connection *cnc,
}
gboolean
-e_o365_connection_get_folders_delta_sync (EO365Connection *cnc,
- const gchar *user_override, /* for which user, NULL to use the
account user */
- const gchar *select, /* fields to select, nullable */
- const gchar *delta_link, /* previous delta link */
- guint max_page_size, /* 0 for default by the server */
- gchar **out_delta_link,
- GSList **out_folders, /* JsonObject * - the returned mailFolder
objects */
- GCancellable *cancellable,
- GError **error)
+e_o365_connection_get_mail_folders_delta_sync (EO365Connection *cnc,
+ const gchar *user_override, /* for which user, NULL to use the
account user */
+ const gchar *select, /* fields to select, nullable */
+ const gchar *delta_link, /* previous delta link */
+ guint max_page_size, /* 0 for default by the server */
+ gchar **out_delta_link,
+ GSList **out_folders, /* JsonObject * - the returned
mailFolder objects */
+ GCancellable *cancellable,
+ GError **error)
{
EO365ResponseData rd;
SoupMessage *message = NULL;
diff --git a/src/Office365/common/e-o365-connection.h b/src/Office365/common/e-o365-connection.h
index 566d3c01..a21a8558 100644
--- a/src/Office365/common/e-o365-connection.h
+++ b/src/Office365/common/e-o365-connection.h
@@ -24,6 +24,7 @@
#include <libsoup/soup.h>
#include "camel-o365-settings.h"
+#include "e-o365-enums.h"
/* Standard GObject macros */
#define E_TYPE_O365_CONNECTION \
@@ -101,7 +102,7 @@ gboolean e_o365_connection_list_folders_sync
GSList **out_folders, /* JsonObject * - the returned
mailFolder objects */
GCancellable *cancellable,
GError **error);
-gboolean e_o365_connection_get_folders_delta_sync
+gboolean e_o365_connection_get_mail_folders_delta_sync
(EO365Connection *cnc,
const gchar *user_override, /* for which user, NULL to use
the account user */
const gchar *select, /* fields to select, nullable */
diff --git a/src/Office365/common/e-o365-enums.h b/src/Office365/common/e-o365-enums.h
new file mode 100644
index 00000000..b2718c74
--- /dev/null
+++ b/src/Office365/common/e-o365-enums.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2020 Red Hat (www.redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef E_O365_ENUMS_H
+#define E_O365_ENUMS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ E_O365_FOLDER_KIND_UNKNOWN,
+ E_O365_FOLDER_KIND_MAILBOX,
+ E_O365_FOLDER_KIND_CALENDAR,
+ E_O365_FOLDER_KIND_CONTACTS,
+ E_O365_FOLDER_KIND_SEARCH,
+ E_O365_FOLDER_KIND_TASKS,
+ E_O365_FOLDER_KIND_MEMOS
+} EO365FolderKind;
+
+G_END_DECLS
+
+#endif /* E_O365_ENUMS_H */
diff --git a/src/Office365/evolution/e-mail-config-o365-backend.c
b/src/Office365/evolution/e-mail-config-o365-backend.c
index 18394184..7faba8c0 100644
--- a/src/Office365/evolution/e-mail-config-o365-backend.c
+++ b/src/Office365/evolution/e-mail-config-o365-backend.c
@@ -103,7 +103,7 @@ test_clicked_cb (GtkButton *button,
g_return_if_fail (cnc != NULL);
//success = e_o365_connection_list_folders_sync (cnc, NULL, NULL, NULL, &folders, NULL, &error);
- success = e_o365_connection_get_folders_delta_sync (cnc, NULL, NULL, delta_link, 0, &new_delta_link,
&folders, NULL, &error);
+ success = e_o365_connection_get_mail_folders_delta_sync (cnc, NULL, NULL, delta_link, 0,
&new_delta_link, &folders, NULL, &error);
if (success) {
g_free (delta_link);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]