[evolution-ews/wip/mcrha/office365: 22/50] Implement create mail folder
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews/wip/mcrha/office365: 22/50] Implement create mail folder
- Date: Mon, 3 Aug 2020 15:24:07 +0000 (UTC)
commit 98f30434ff78540e4815c5c02f431859e872addf
Author: Milan Crha <mcrha redhat com>
Date: Wed Jun 24 22:36:00 2020 +0200
Implement create mail folder
src/Office365/camel/camel-o365-store-summary.c | 46 +++++++++
src/Office365/camel/camel-o365-store-summary.h | 2 +
src/Office365/camel/camel-o365-store.c | 125 +++++++++++++++++++++++-
src/Office365/common/e-o365-connection.c | 127 +++++++++++++++++++++----
src/Office365/common/e-o365-connection.h | 8 ++
5 files changed, 289 insertions(+), 19 deletions(-)
---
diff --git a/src/Office365/camel/camel-o365-store-summary.c b/src/Office365/camel/camel-o365-store-summary.c
index 163d3a43..619f01ac 100644
--- a/src/Office365/camel/camel-o365-store-summary.c
+++ b/src/Office365/camel/camel-o365-store-summary.c
@@ -466,6 +466,24 @@ camel_o365_store_summary_has_folder (CamelO365StoreSummary *store_summary,
return has;
}
+gboolean
+camel_o365_store_summary_has_full_name (CamelO365StoreSummary *store_summary,
+ const gchar *full_name)
+{
+ gboolean has;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE_SUMMARY (store_summary), FALSE);
+ g_return_val_if_fail (full_name != NULL, FALSE);
+
+ LOCK (store_summary);
+
+ has = g_hash_table_contains (store_summary->priv->full_name_id_hash, full_name);
+
+ UNLOCK (store_summary);
+
+ return has;
+}
+
void
camel_o365_store_summary_remove_folder (CamelO365StoreSummary *store_summary,
const gchar *id)
@@ -852,6 +870,34 @@ camel_o365_store_summary_set_folder_display_name (CamelO365StoreSummary *store_s
g_slist_free_full (rpd.removed, id_full_name_data_free);
g_free (new_full_name);
+ } else {
+ gchar *parent_id, *encoded_folder_name, *id_copy, *new_full_name = NULL;
+
+ encoded_folder_name = o365_store_summary_encode_folder_name (display_name);
+
+ parent_id = camel_o365_store_summary_dup_folder_parent_id (store_summary, id);
+
+ if (parent_id && *parent_id) {
+ const gchar *parent_full_name;
+
+ parent_full_name = g_hash_table_lookup
(store_summary->priv->id_full_name_hash, parent_id);
+
+ if (parent_full_name && *parent_full_name)
+ new_full_name = g_strconcat (parent_full_name, "/",
encoded_folder_name, NULL);
+ }
+
+ if (!new_full_name) {
+ new_full_name = encoded_folder_name;
+ encoded_folder_name = NULL;
+ }
+
+ g_free (encoded_folder_name);
+ g_free (parent_id);
+
+ id_copy = g_strdup (id);
+
+ g_hash_table_insert (store_summary->priv->id_full_name_hash, id_copy,
new_full_name);
+ g_hash_table_insert (store_summary->priv->full_name_id_hash, new_full_name,
id_copy);
}
}
}
diff --git a/src/Office365/camel/camel-o365-store-summary.h b/src/Office365/camel/camel-o365-store-summary.h
index a83783e9..670f739b 100644
--- a/src/Office365/camel/camel-o365-store-summary.h
+++ b/src/Office365/camel/camel-o365-store-summary.h
@@ -73,6 +73,8 @@ void camel_o365_store_summary_set_delta_link (CamelO365StoreSummary *store_summ
gchar * camel_o365_store_summary_dup_delta_link (CamelO365StoreSummary *store_summary);
gboolean camel_o365_store_summary_has_folder (CamelO365StoreSummary *store_summary,
const gchar *id);
+gboolean camel_o365_store_summary_has_full_name (CamelO365StoreSummary *store_summary,
+ const gchar *full_name);
void camel_o365_store_summary_remove_folder (CamelO365StoreSummary *store_summary,
const gchar *id);
void camel_o365_store_summary_set_folder (CamelO365StoreSummary *store_summary,
diff --git a/src/Office365/camel/camel-o365-store.c b/src/Office365/camel/camel-o365-store.c
index 4771eec4..adf925f8 100644
--- a/src/Office365/camel/camel-o365-store.c
+++ b/src/Office365/camel/camel-o365-store.c
@@ -415,6 +415,100 @@ o365_store_save_summary_locked (CamelO365StoreSummary *summary,
g_clear_error (&error);
}
+static CamelFolderInfo *
+o365_store_create_folder_sync (CamelStore *store,
+ const gchar *parent_name,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelO365Store *o365_store;
+ EO365MailFolder *mail_folder = NULL;
+ gchar *fid = NULL;
+ gchar *full_name;
+ EO365Connection *cnc;
+ CamelFolderInfo *fi = NULL;
+ guint32 flags;
+ gboolean success;
+ GError *local_error = NULL;
+
+ g_return_val_if_fail (CAMEL_IS_O365_STORE (store), NULL);
+
+ o365_store = CAMEL_O365_STORE (store);
+
+ if (parent_name && *parent_name)
+ full_name = g_strdup_printf ("%s/%s", parent_name, folder_name);
+ else
+ full_name = g_strdup (folder_name);
+
+ fid = camel_o365_store_summary_dup_folder_id_for_full_name (o365_store->priv->summary, full_name);
+
+ if (fid) {
+ g_free (fid);
+ g_set_error (
+ error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ _("Cannot create folder “%s”, folder already exists"),
+ full_name);
+ g_free (full_name);
+ return NULL;
+ }
+
+ g_free (full_name);
+
+ /* Get Parent folder ID */
+ if (parent_name && parent_name[0]) {
+ fid = camel_o365_store_summary_dup_folder_id_for_full_name (o365_store->priv->summary,
parent_name);
+
+ if (!fid) {
+ g_set_error (error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
+ _("Parent folder “%s” does not exist"),
+ parent_name);
+ return NULL;
+ }
+ }
+
+ if (!camel_o365_store_ensure_connected (o365_store, &cnc, cancellable, error)) {
+ g_free (fid);
+
+ return NULL;
+ }
+
+ success = e_o365_connection_create_mail_folder_sync (cnc, NULL, fid, folder_name, &mail_folder,
cancellable, &local_error);
+
+ g_object_unref (cnc);
+ g_free (fid);
+
+ if (!success) {
+ camel_o365_store_maybe_disconnect (o365_store, local_error);
+ g_propagate_error (error, local_error);
+
+ return NULL;
+ }
+
+ flags = e_o365_mail_folder_get_child_folder_count (mail_folder) ? CAMEL_STORE_INFO_FOLDER_CHILDREN :
CAMEL_STORE_INFO_FOLDER_NOCHILDREN;
+
+ camel_o365_store_summary_set_folder (o365_store->priv->summary, TRUE,
+ e_o365_mail_folder_get_id (mail_folder),
+ e_o365_mail_folder_get_parent_folder_id (mail_folder),
+ e_o365_mail_folder_get_display_name (mail_folder),
+ e_o365_mail_folder_get_total_item_count (mail_folder),
+ e_o365_mail_folder_get_unread_item_count (mail_folder),
+ flags, E_O365_FOLDER_KIND_MAIL, FALSE, FALSE);
+
+ fi = camel_o365_store_summary_build_folder_info_for_id (o365_store->priv->summary,
e_o365_mail_folder_get_id (mail_folder));
+
+ camel_store_folder_created (store, fi);
+ camel_subscribable_folder_subscribed (CAMEL_SUBSCRIBABLE (o365_store), fi);
+
+ json_object_unref (mail_folder);
+
+ LOCK (o365_store);
+ o365_store_save_summary_locked (o365_store->priv->summary, G_STRFUNC);
+ UNLOCK (o365_store);
+
+ return fi;
+}
+
typedef struct _FolderRenamedData {
gchar *id;
gchar *old_name;
@@ -845,6 +939,33 @@ o365_store_can_refresh_folder (CamelStore *store,
return CAMEL_STORE_CLASS (camel_o365_store_parent_class)->can_refresh_folder (store, info, error);
}
+static gboolean
+o365_store_folder_is_subscribed (CamelSubscribable *subscribable,
+ const gchar *folder_name)
+{
+ CamelO365Store *o365_store = CAMEL_O365_STORE (subscribable);
+
+ return camel_o365_store_summary_has_full_name (o365_store->priv->summary, folder_name);
+}
+
+static gboolean
+o365_store_subscribe_folder_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+o365_store_unsubscribe_folder_sync (CamelSubscribable *subscribable,
+ const gchar *folder_name,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return TRUE;
+}
+
static void
o365_store_set_property (GObject *object,
guint property_id,
@@ -956,8 +1077,8 @@ camel_o365_store_class_init (CamelO365StoreClass *class)
store_class = CAMEL_STORE_CLASS (class);
store_class->get_folder_sync = o365_store_get_folder_sync;
-#if 0
store_class->create_folder_sync = o365_store_create_folder_sync;
+#if 0
store_class->delete_folder_sync = o365_store_delete_folder_sync;
store_class->rename_folder_sync = o365_store_rename_folder_sync;
#endif
@@ -979,11 +1100,9 @@ camel_o365_store_initable_init (GInitableIface *iface)
static void
camel_o365_subscribable_init (CamelSubscribableInterface *iface)
{
-#if 0
iface->folder_is_subscribed = o365_store_folder_is_subscribed;
iface->subscribe_folder_sync = o365_store_subscribe_folder_sync;
iface->unsubscribe_folder_sync = o365_store_unsubscribe_folder_sync;
-#endif
}
static void
diff --git a/src/Office365/common/e-o365-connection.c b/src/Office365/common/e-o365-connection.c
index e1855790..6df4ba51 100644
--- a/src/Office365/common/e-o365-connection.c
+++ b/src/Office365/common/e-o365-connection.c
@@ -1407,6 +1407,31 @@ e_o365_read_valued_response_cb (EO365Connection *cnc,
return can_continue;
}
+static gboolean
+e_o365_read_json_object_response_cb (EO365Connection *cnc,
+ SoupMessage *message,
+ GInputStream *input_stream,
+ JsonNode *node,
+ gpointer user_data,
+ gchar **out_next_link,
+ GCancellable *cancellable,
+ GError **error)
+{
+ JsonObject **out_json_object = user_data;
+ JsonObject *object;
+
+ g_return_val_if_fail (out_json_object != NULL, FALSE);
+ g_return_val_if_fail (out_next_link != NULL, FALSE);
+ g_return_val_if_fail (JSON_NODE_HOLDS_OBJECT (node), FALSE);
+
+ object = json_node_get_object (node);
+ g_return_val_if_fail (object != NULL, FALSE);
+
+ *out_json_object = json_object_ref (object);
+
+ return TRUE;
+}
+
gboolean
e_o365_connection_get_ssl_error_details (EO365Connection *cnc,
gchar **out_certificate_pem,
@@ -1660,6 +1685,34 @@ e_o365_connection_construct_uri (EO365Connection *cnc,
return g_string_free (uri, FALSE);
}
+static void
+e_o365_connection_set_json_body (SoupMessage *message,
+ JsonBuilder *builder)
+{
+ JsonGenerator *generator;
+ JsonNode *node;
+ gchar *data;
+ gsize data_length = 0;
+
+ g_return_if_fail (SOUP_IS_MESSAGE (message));
+ g_return_if_fail (builder != NULL);
+
+ node = json_builder_get_root (builder);
+
+ generator = json_generator_new ();
+ json_generator_set_root (generator, node);
+
+ data = json_generator_to_data (generator, &data_length);
+
+ soup_message_headers_append (message->request_headers, "Content-Type", "application/json");
+
+ if (data)
+ soup_message_body_append_take (message->request_body, (guchar *) data, data_length);
+
+ g_object_unref (generator);
+ json_node_unref (node);
+}
+
static void
e_o365_fill_message_headers_cb (JsonObject *object,
const gchar *member_name,
@@ -1772,11 +1825,8 @@ e_o365_connection_batch_request_internal_sync (EO365Connection *cnc,
{
SoupMessage *message;
JsonBuilder *builder;
- JsonGenerator *generator;
- JsonNode *node;
gboolean success;
- gchar *uri, buff[128], *data;
- gsize data_length = 0;
+ gchar *uri, buff[128];
guint ii;
g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
@@ -1888,22 +1938,11 @@ e_o365_connection_batch_request_internal_sync (EO365Connection *cnc,
json_builder_end_array (builder);
json_builder_end_object (builder);
- node = json_builder_get_root (builder);
-
- generator = json_generator_new ();
- json_generator_set_root (generator, node);
-
- data = json_generator_to_data (generator, &data_length);
+ e_o365_connection_set_json_body (message, builder);
- soup_message_headers_append (message->request_headers, "Content-Type", "application/json");
soup_message_headers_append (message->request_headers, "Accept", "application/json");
- if (data)
- soup_message_body_append_take (message->request_body, (guchar *) data, data_length);
-
- json_node_unref (node);
g_object_unref (builder);
- g_object_unref (generator);
success = o365_connection_send_request_sync (cnc, message, e_o365_read_batch_response_cb, NULL,
requests, cancellable, error);
@@ -2145,6 +2184,62 @@ e_o365_connection_get_mail_folders_delta_sync (EO365Connection *cnc,
return success;
}
+/* https://docs.microsoft.com/en-us/graph/api/user-post-mailfolders?view=graph-rest-1.0&tabs=http
+ https://docs.microsoft.com/en-us/graph/api/mailfolder-post-childfolders?view=graph-rest-1.0&tabs=http */
+
+gboolean
+e_o365_connection_create_mail_folder_sync (EO365Connection *cnc,
+ const gchar *user_override, /* for which user, NULL to use the
account user */
+ const gchar *parent_folder_id, /* NULL for the folder root */
+ const gchar *display_name,
+ EO365MailFolder **out_mail_folder,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupMessage *message = NULL;
+ JsonBuilder *builder;
+ gboolean success;
+ gchar *uri;
+
+ g_return_val_if_fail (E_IS_O365_CONNECTION (cnc), FALSE);
+ g_return_val_if_fail (display_name != NULL, FALSE);
+ g_return_val_if_fail (out_mail_folder != NULL, FALSE);
+
+ uri = e_o365_connection_construct_uri (cnc, TRUE, user_override, E_O365_API_V1_0, NULL,
+ "mailFolders",
+ parent_folder_id,
+ parent_folder_id ? "childFolders" : NULL,
+ NULL);
+
+ message = soup_message_new (SOUP_METHOD_POST, uri);
+
+ if (!message) {
+ g_set_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Malformed URI: “%s”"), uri);
+ g_free (uri);
+
+ return FALSE;
+ }
+
+ g_free (uri);
+
+ builder = json_builder_new_immutable ();
+
+ json_builder_begin_object (builder);
+ json_builder_set_member_name (builder, "displayName");
+ json_builder_add_string_value (builder, display_name);
+ json_builder_end_object (builder);
+
+ e_o365_connection_set_json_body (message, builder);
+
+ g_object_unref (builder);
+
+ success = o365_connection_send_request_sync (cnc, message, e_o365_read_json_object_response_cb, NULL,
out_mail_folder, cancellable, error);
+
+ g_clear_object (&message);
+
+ return success;
+}
+
/* https://docs.microsoft.com/en-us/graph/api/message-delta?view=graph-rest-1.0&tabs=http */
gboolean
diff --git a/src/Office365/common/e-o365-connection.h b/src/Office365/common/e-o365-connection.h
index 9854e02f..cc1de355 100644
--- a/src/Office365/common/e-o365-connection.h
+++ b/src/Office365/common/e-o365-connection.h
@@ -178,6 +178,14 @@ gboolean e_o365_connection_get_mail_folders_delta_sync
gchar **out_delta_link,
GCancellable *cancellable,
GError **error);
+gboolean e_o365_connection_create_mail_folder_sync
+ (EO365Connection *cnc,
+ const gchar *user_override, /* for which user, NULL to use
the account user */
+ const gchar *parent_folder_id, /* NULL for the folder root */
+ const gchar *display_name,
+ EO365MailFolder **out_mail_folder,
+ GCancellable *cancellable,
+ GError **error);
gboolean e_o365_connection_get_mail_messages_delta_sync
(EO365Connection *cnc,
const gchar *user_override, /* for which user, NULL to use
the account user */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]