[evolution-data-server/wip/offline-cache] [EWebDAVSession] MKCOL for address books and enhance error reading a bit more
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] [EWebDAVSession] MKCOL for address books and enhance error reading a bit more
- Date: Mon, 3 Apr 2017 12:25:09 +0000 (UTC)
commit dc3c24f9f8a41ad945e023e8fd88431eef8506e8
Author: Milan Crha <mcrha redhat com>
Date: Mon Apr 3 14:24:07 2017 +0200
[EWebDAVSession] MKCOL for address books and enhance error reading a bit more
src/libedataserver/e-webdav-session.c | 457 +++++++++++++++++++++++++--------
src/libedataserver/e-webdav-session.h | 37 ++-
2 files changed, 384 insertions(+), 110 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 55046c1..1a0c3bf 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -353,13 +353,13 @@ e_webdav_session_new_request (EWebDAVSession *webdav,
}
static gboolean
-e_webdav_session_extract_multistatus_error_cb (EWebDAVSession *webdav,
- xmlXPathContextPtr xpath_ctx,
- const gchar *xpath_prop_prefix,
- const SoupURI *request_uri,
- const gchar *href,
- guint status_code,
- gpointer user_data)
+e_webdav_session_extract_propstat_error_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
{
GError **error = user_data;
@@ -390,6 +390,64 @@ e_webdav_session_extract_multistatus_error_cb (EWebDAVSession *webdav,
return TRUE;
}
+static gboolean
+e_webdav_session_extract_dav_error (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prefix,
+ gchar **out_detail_text)
+{
+ xmlXPathObjectPtr xpath_obj;
+ gchar *detail_text;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (xpath_ctx != NULL, FALSE);
+ g_return_val_if_fail (xpath_prefix != NULL, FALSE);
+ g_return_val_if_fail (out_detail_text != NULL, FALSE);
+
+ if (!e_xml_xpath_eval_exists (xpath_ctx, "%s/D:error", xpath_prefix))
+ return FALSE;
+
+ detail_text = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:error", xpath_prefix);
+
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/D:error", xpath_prefix);
+ if (xpath_obj) {
+ if (xpath_obj->type == XPATH_NODESET &&
+ xpath_obj->nodesetval &&
+ xpath_obj->nodesetval->nodeNr == 1 &&
+ xpath_obj->nodesetval->nodeTab &&
+ xpath_obj->nodesetval->nodeTab[0] &&
+ xpath_obj->nodesetval->nodeTab[0]->children) {
+ GString *text = g_string_new ("");
+ xmlNodePtr node;
+
+ for (node = xpath_obj->nodesetval->nodeTab[0]->children; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE &&
+ node->name && *(node->name))
+ g_string_append_printf (text, "[%s]", (const gchar *) node->name);
+ }
+
+ if (text->len > 0) {
+ if (detail_text) {
+ g_strstrip (detail_text);
+ if (*detail_text)
+ g_string_prepend (text, detail_text);
+ g_free (detail_text);
+ }
+
+ detail_text = g_string_free (text, FALSE);
+ } else {
+ g_string_free (text, TRUE);
+ }
+ }
+
+ xmlXPathFreeObject (xpath_obj);
+ }
+
+ *out_detail_text = detail_text;
+
+ return detail_text != NULL;
+}
+
/**
* e_webdav_session_replace_with_detailed_error:
* @webdav: an #EWebDAVSession
@@ -461,7 +519,7 @@ e_webdav_session_replace_with_detailed_error (EWebDAVSession *webdav,
if (status_code == SOUP_STATUS_MULTI_STATUS &&
!ignore_multistatus &&
!e_webdav_session_traverse_multistatus_response (webdav, message, &byte_array,
- e_webdav_session_extract_multistatus_error_cb, &local_error, NULL)) {
+ e_webdav_session_extract_propstat_error_cb, &local_error, NULL)) {
g_clear_error (&local_error);
}
@@ -491,61 +549,42 @@ e_webdav_session_replace_with_detailed_error (EWebDAVSession *webdav,
xpath_ctx = e_xml_new_xpath_context_with_namespaces (doc,
"D", E_WEBDAV_NS_DAV,
+ "C", E_WEBDAV_NS_CALDAV,
+ "A", E_WEBDAV_NS_CARDDAV,
NULL);
if (xpath_ctx &&
- e_xml_xpath_eval_exists (xpath_ctx, "/D:error")) {
- xmlXPathObjectPtr xpath_obj;
-
- detail_text = e_xml_xpath_eval_as_string (xpath_ctx, "/D:error");
-
- xpath_obj = e_xml_xpath_eval (xpath_ctx, "/D:error");
- if (xpath_obj) {
- if (xpath_obj->type == XPATH_NODESET &&
- xpath_obj->nodesetval &&
- xpath_obj->nodesetval->nodeNr == 1 &&
- xpath_obj->nodesetval->nodeTab &&
- xpath_obj->nodesetval->nodeTab[0] &&
- xpath_obj->nodesetval->nodeTab[0]->children) {
- GString *text = g_string_new ("");
- xmlNodePtr node;
-
- for (node = xpath_obj->nodesetval->nodeTab[0]->children;
node; node = node->next) {
- if (node->type == XML_ELEMENT_NODE &&
- node->name && *(node->name))
- g_string_append_printf (text, "[%s]", (const
gchar *) node->name);
- }
-
- if (text->len > 0) {
- if (detail_text) {
- g_strstrip (detail_text);
- if (*detail_text)
- g_string_prepend (text, detail_text);
- g_free (detail_text);
- }
-
- detail_text = g_string_free (text, FALSE);
- } else {
- g_string_free (text, TRUE);
- }
+ e_webdav_session_extract_dav_error (webdav, xpath_ctx, "", &detail_text)) {
+ /* do nothing, detail_text is set */
+ } else if (xpath_ctx) {
+ const gchar *path_prefix = NULL;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "/D:multistatus/D:response/D:status"))
+ path_prefix = "/D:multistatus/D:response";
+ else if (e_xml_xpath_eval_exists (xpath_ctx,
"/C:mkcalendar-response/D:status"))
+ path_prefix = "/C:mkcalendar-response";
+ else if (e_xml_xpath_eval_exists (xpath_ctx, "/D:mkcol-response/D:status"))
+ path_prefix = "/D:mkcol-response";
+
+ if (path_prefix) {
+ guint parsed_status = 0;
+ gchar *status;
+
+ status = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:status",
path_prefix);
+ if (status && soup_headers_parse_status_line (status, NULL,
&parsed_status, &reason_phrase_copy) &&
+ !SOUP_STATUS_IS_SUCCESSFUL (parsed_status)) {
+ status_code = parsed_status;
+ reason_phrase = reason_phrase_copy;
+ detail_text = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/D:responsedescription", path_prefix);
+
+ if (!detail_text)
+ e_webdav_session_extract_dav_error (webdav,
xpath_ctx, path_prefix, &detail_text);
+ } else {
+ e_webdav_session_extract_dav_error (webdav, xpath_ctx,
path_prefix, &detail_text);
}
- xmlXPathFreeObject (xpath_obj);
- }
- } else if (xpath_ctx &&
- e_xml_xpath_eval_exists (xpath_ctx, "/D:multistatus/D:response/D:status"))
{
- guint parsed_status = 0;
- gchar *status;
-
- status = e_xml_xpath_eval_as_string (xpath_ctx,
"/D:multistatus/D:response/D:status");
- if (status && soup_headers_parse_status_line (status, NULL, &parsed_status,
&reason_phrase_copy) &&
- !SOUP_STATUS_IS_SUCCESSFUL (parsed_status)) {
- status_code = parsed_status;
- reason_phrase = reason_phrase_copy;
- detail_text = e_xml_xpath_eval_as_string (xpath_ctx,
"/D:multistatus/D:response/D:responsedescription");
+ g_free (status);
}
-
- g_free (status);
}
if (xpath_ctx)
@@ -793,7 +832,7 @@ e_webdav_session_options_sync (EWebDAVSession *webdav,
* @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
* @depth: requested depth, can be one of %E_WEBDAV_DEPTH_THIS, %E_WEBDAV_DEPTH_THIS_AND_CHILDREN or
%E_WEBDAV_DEPTH_INFINITY
* @xml: (nullable): the request itself, as an #EXmlDocument, the root element should be DAV:propfind, or
%NULL
- * @func: an #EWebDAVMultistatusTraverseFunc function to call for each DAV:propstat in the multistatus
response
+ * @func: an #EWebDAVPropstatTraverseFunc function to call for each DAV:propstat in the multistatus response
* @func_user_data: user data passed to @func
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
@@ -819,7 +858,7 @@ e_webdav_session_propfind_sync (EWebDAVSession *webdav,
const gchar *uri,
const gchar *depth,
const EXmlDocument *xml,
- EWebDAVMultistatusTraverseFunc func,
+ EWebDAVPropstatTraverseFunc func,
gpointer func_user_data,
GCancellable *cancellable,
GError **error)
@@ -960,7 +999,7 @@ e_webdav_session_proppatch_sync (EWebDAVSession *webdav,
* @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
* @depth: (nullable): requested depth, can be %NULL, then %E_WEBDAV_DEPTH_THIS is used
* @xml: the request itself, as an #EXmlDocument
- * @func: (nullable): an #EWebDAVMultistatusTraverseFunc function to call for each DAV:propstat in the
multistatus response, or %NULL
+ * @func: (nullable): an #EWebDAVPropstatTraverseFunc function to call for each DAV:propstat in the
multistatus response, or %NULL
* @func_user_data: user data passed to @func
* @out_content_type: (nullable) (transfer full): return location for response Content-Type, or %NULL
* @out_content: (nullable) (transfer full): return location for response content, or %NULL
@@ -994,7 +1033,7 @@ e_webdav_session_report_sync (EWebDAVSession *webdav,
const gchar *uri,
const gchar *depth,
const EXmlDocument *xml,
- EWebDAVMultistatusTraverseFunc func,
+ EWebDAVPropstatTraverseFunc func,
gpointer func_user_data,
gchar **out_content_type,
GByteArray **out_content,
@@ -1082,7 +1121,8 @@ e_webdav_session_report_sync (EWebDAVSession *webdav,
* @error: return location for a #GError, or %NULL
*
* Creates a new generic collection identified by @uri on the server.
- * To create specific collections use e_webdav_session_mkcalendar_sync().
+ * To create specific collections use e_webdav_session_mkcalendar_sync()
+ * or e_webdav_session_mkcol_addressbook_sync().
*
* Returns: Whether succeeded.
*
@@ -1118,11 +1158,117 @@ e_webdav_session_mkcol_sync (EWebDAVSession *webdav,
}
/**
+ * e_webdav_session_mkcol_addressbook_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: URI of the collection to create
+ * @display_name: (nullable): a human-readable display name to set, or %NULL
+ * @description: (nullable): a human-readable description of the address book, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a new address book collection identified by @uri on the server.
+ *
+ * Note that CardDAV RFC 6352 Section 5.2 forbids to create address book
+ * resources under other address book resources (no nested address books
+ * are allowed).
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_mkcol_addressbook_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *display_name,
+ const gchar *description,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupRequestHTTP *request;
+ SoupMessage *message;
+ EXmlDocument *xml;
+ gchar *content;
+ gsize content_length;
+ GByteArray *bytes;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+
+ request = e_webdav_session_new_request (webdav, SOUP_METHOD_MKCOL, uri, error);
+ if (!request)
+ return FALSE;
+
+ message = soup_request_http_get_message (request);
+ if (!message) {
+ g_warn_if_fail (message != NULL);
+ g_object_unref (request);
+
+ return FALSE;
+ }
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "mkcol");
+ e_xml_document_add_namespaces (xml, "A", E_WEBDAV_NS_CARDDAV, NULL);
+
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "set");
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "prop");
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "resourcetype");
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "collection");
+ e_xml_document_end_element (xml);
+ e_xml_document_start_element (xml, E_WEBDAV_NS_CARDDAV, "addressbook");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* resourcetype */
+
+ if (display_name && *display_name) {
+ e_xml_document_start_text_element (xml, E_WEBDAV_NS_DAV, "displayname");
+ e_xml_document_write_string (xml, display_name);
+ e_xml_document_end_element (xml);
+ }
+
+ if (description && *description) {
+ e_xml_document_start_text_element (xml, E_WEBDAV_NS_CARDDAV, "addressbook-description");
+ e_xml_document_write_string (xml, description);
+ e_xml_document_end_element (xml);
+ }
+
+ e_xml_document_end_element (xml); /* prop */
+ e_xml_document_end_element (xml); /* set */
+
+ content = e_xml_document_get_content (xml, &content_length);
+ if (!content) {
+ g_object_unref (message);
+ g_object_unref (request);
+ g_object_unref (xml);
+
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Failed to get XML
request content"));
+
+ return FALSE;
+ }
+
+ soup_message_set_request (message, E_WEBDAV_CONTENT_TYPE_XML,
+ SOUP_MEMORY_TAKE, content, content_length);
+
+ g_object_unref (xml);
+
+ bytes = e_soup_session_send_request_simple_sync (E_SOUP_SESSION (webdav), request, cancellable,
error);
+
+ success = !e_webdav_session_replace_with_detailed_error (webdav, request, bytes, FALSE, _("Failed to
create address book"), error) &&
+ bytes != NULL;
+
+ if (bytes)
+ g_byte_array_free (bytes, TRUE);
+ g_object_unref (message);
+ g_object_unref (request);
+
+ return success;
+}
+
+/**
* e_webdav_session_mkcalendar_sync:
* @webdav: an #EWebDAVSession
* @uri: URI of the collection to create
* @display_name: (nullable): a human-readable display name to set, or %NULL
- * @description: (nullable): a human-readable description of the calednar, or %NULL
+ * @description: (nullable): a human-readable description of the calendar, or %NULL
* @color: (nullable): a color to set, in format "#RRGGBB", or %NULL
* @supports: a bit-or of EWebDAVResourceSupports values
* @cancellable: optional #GCancellable object, or %NULL
@@ -2273,38 +2419,17 @@ e_webdav_session_unlock_sync (EWebDAVSession *webdav,
return success;
}
-/**
- * e_webdav_session_traverse_multistatus_response:
- * @webdav: an #EWebDAVSession
- * @message: (nullable): an optional #SoupMessage corresponding to the response, or %NULL
- * @xml_data: a #GByteArray containing DAV:multistatus response
- * @func: an #EWebDAVMultistatusTraverseFunc function to call for each DAV:propstat in the multistatus
response
- * @func_user_data: user data passed to @func
- * @error: return location for a #GError, or %NULL
- *
- * Traverses a DAV:multistatus response and calls @func for each returned DAV:propstat.
- * The provided XPath context has registered %E_WEBDAV_NS_DAV namespace with prefix "D".
- * It doesn't have any other namespace registered.
- *
- * The @message, if provided, is used to verify that the response is a multi-status
- * and that the Content-Type is properly set. It's used to get a request URI as well.
- *
- * The @func is called always at least once, with %NULL xpath_prop_prefix, which
- * is meant to let the caller setup the xpath_ctx, like to register its own namespaces
- * to it with e_xml_xpath_context_register_namespaces(). All other invocations of @func
- * will have xpath_prop_prefix non-%NULL.
- *
- * Returns: Whether succeeded.
- *
- * Since: 3.26
- **/
-gboolean
-e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
- const SoupMessage *message,
- const GByteArray *xml_data,
- EWebDAVMultistatusTraverseFunc func,
- gpointer func_user_data,
- GError **error)
+static gboolean
+e_webdav_session_traverse_propstat_response (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ gboolean require_multistatus,
+ const gchar *additional_ns_prefix,
+ const gchar *additional_ns,
+ const gchar *propstat_path_prefix,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error)
{
SoupURI *request_uri = NULL;
xmlDocPtr doc;
@@ -2312,12 +2437,13 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
g_return_val_if_fail (xml_data != NULL, FALSE);
+ g_return_val_if_fail (propstat_path_prefix != NULL, FALSE);
g_return_val_if_fail (func != NULL, FALSE);
if (message) {
const gchar *content_type;
- if (message->status_code != SOUP_STATUS_MULTI_STATUS) {
+ if (require_multistatus && message->status_code != SOUP_STATUS_MULTI_STATUS) {
g_set_error (error, SOUP_HTTP_ERROR, message->status_code,
_("Expected multistatus response, but %d returned (%s)"),
message->status_code,
e_soup_session_util_status_to_string (message->status_code,
message->reason_phrase));
@@ -2354,13 +2480,14 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
xpath_ctx = e_xml_new_xpath_context_with_namespaces (doc,
"D", E_WEBDAV_NS_DAV,
+ additional_ns_prefix, additional_ns,
NULL);
if (xpath_ctx &&
func (webdav, xpath_ctx, NULL, request_uri, NULL, SOUP_STATUS_NONE, func_user_data)) {
xmlXPathObjectPtr xpath_obj_response;
- xpath_obj_response = e_xml_xpath_eval (xpath_ctx, "/D:multistatus/D:response");
+ xpath_obj_response = e_xml_xpath_eval (xpath_ctx, "%s", propstat_path_prefix);
if (xpath_obj_response != NULL) {
gboolean do_stop = FALSE;
@@ -2372,14 +2499,14 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
xmlXPathObjectPtr xpath_obj_propstat;
xpath_obj_propstat = e_xml_xpath_eval (xpath_ctx,
- "/D:multistatus/D:response[%d]/D:propstat",
- response_index + 1);
+ "%s[%d]/D:propstat",
+ propstat_path_prefix, response_index + 1);
if (xpath_obj_propstat != NULL) {
gchar *href;
gint propstat_index, propstat_length;
- href = e_xml_xpath_eval_as_string (xpath_ctx,
"/D:multistatus/D:response[%d]/D:href", response_index + 1);
+ href = e_xml_xpath_eval_as_string (xpath_ctx, "%s[%d]/D:href",
propstat_path_prefix, response_index + 1);
if (href) {
gchar *full_uri;
@@ -2396,8 +2523,8 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
gchar *status, *propstat_prefix;
guint status_code;
- propstat_prefix = g_strdup_printf
("/D:multistatus/D:response[%d]/D:propstat[%d]/D:prop",
- response_index + 1, propstat_index + 1);
+ propstat_prefix = g_strdup_printf
("%s[%d]/D:propstat[%d]/D:prop",
+ propstat_path_prefix, response_index + 1,
propstat_index + 1);
status = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/../D:status", propstat_prefix);
if (!status || !soup_headers_parse_status_line (status, NULL,
&status_code, NULL))
@@ -2425,6 +2552,132 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
return TRUE;
}
+/**
+ * e_webdav_session_traverse_multistatus_response:
+ * @webdav: an #EWebDAVSession
+ * @message: (nullable): an optional #SoupMessage corresponding to the response, or %NULL
+ * @xml_data: a #GByteArray containing DAV:multistatus response
+ * @func: an #EWebDAVPropstatTraverseFunc function to call for each DAV:propstat in the multistatus response
+ * @func_user_data: user data passed to @func
+ * @error: return location for a #GError, or %NULL
+ *
+ * Traverses a DAV:multistatus response and calls @func for each returned DAV:propstat.
+ * The provided XPath context has registered %E_WEBDAV_NS_DAV namespace with prefix "D".
+ * It doesn't have any other namespace registered.
+ *
+ * The @message, if provided, is used to verify that the response is a multi-status
+ * and that the Content-Type is properly set. It's used to get a request URI as well.
+ *
+ * The @func is called always at least once, with %NULL xpath_prop_prefix, which
+ * is meant to let the caller setup the xpath_ctx, like to register its own namespaces
+ * to it with e_xml_xpath_context_register_namespaces(). All other invocations of @func
+ * will have xpath_prop_prefix non-%NULL.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (xml_data != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ return e_webdav_session_traverse_propstat_response (webdav, message, xml_data, TRUE,
+ NULL, NULL, "/D:multistatus/D:response",
+ func, func_user_data, error);
+}
+
+/**
+ * e_webdav_session_traverse_mkcol_response:
+ * @webdav: an #EWebDAVSession
+ * @message: (nullable): an optional #SoupMessage corresponding to the response, or %NULL
+ * @xml_data: a #GByteArray containing DAV:mkcol-response response
+ * @func: an #EWebDAVPropstatTraverseFunc function to call for each DAV:propstat in the response
+ * @func_user_data: user data passed to @func
+ * @error: return location for a #GError, or %NULL
+ *
+ * Traverses a DAV:mkcol-response response and calls @func for each returned DAV:propstat.
+ * The provided XPath context has registered %E_WEBDAV_NS_DAV namespace with prefix "D".
+ * It doesn't have any other namespace registered.
+ *
+ * The @message, if provided, is used to verify that the response is an XML Content-Type.
+ * It's used to get the request URI as well.
+ *
+ * The @func is called always at least once, with %NULL xpath_prop_prefix, which
+ * is meant to let the caller setup the xpath_ctx, like to register its own namespaces
+ * to it with e_xml_xpath_context_register_namespaces(). All other invocations of @func
+ * will have xpath_prop_prefix non-%NULL.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_traverse_mkcol_response (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (xml_data != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ return e_webdav_session_traverse_propstat_response (webdav, message, xml_data, FALSE,
+ NULL, NULL, "/D:mkcol-response",
+ func, func_user_data, error);
+}
+
+/**
+ * e_webdav_session_traverse_mkcalendar_response:
+ * @webdav: an #EWebDAVSession
+ * @message: (nullable): an optional #SoupMessage corresponding to the response, or %NULL
+ * @xml_data: a #GByteArray containing CALDAV:mkcalendar-response response
+ * @func: an #EWebDAVPropstatTraverseFunc function to call for each DAV:propstat in the response
+ * @func_user_data: user data passed to @func
+ * @error: return location for a #GError, or %NULL
+ *
+ * Traverses a CALDAV:mkcalendar-response response and calls @func for each returned DAV:propstat.
+ * The provided XPath context has registered %E_WEBDAV_NS_DAV namespace with prefix "D" and
+ * %E_WEBDAV_NS_CALDAV namespace with prefix "C". It doesn't have any other namespace registered.
+ *
+ * The @message, if provided, is used to verify that the response is an XML Content-Type.
+ * It's used to get the request URI as well.
+ *
+ * The @func is called always at least once, with %NULL xpath_prop_prefix, which
+ * is meant to let the caller setup the xpath_ctx, like to register its own namespaces
+ * to it with e_xml_xpath_context_register_namespaces(). All other invocations of @func
+ * will have xpath_prop_prefix non-%NULL.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_traverse_mkcalendar_response (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error)
+{
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (xml_data != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ return e_webdav_session_traverse_propstat_response (webdav, message, xml_data, FALSE,
+ "C", E_WEBDAV_NS_CALDAV, "/C:mkcalendar-response",
+ func, func_user_data, error);
+}
+
static gboolean
e_webdav_session_getctag_cb (EWebDAVSession *webdav,
xmlXPathContextPtr xpath_ctx,
diff --git a/src/libedataserver/e-webdav-session.h b/src/libedataserver/e-webdav-session.h
index c1aed39..b20395e 100644
--- a/src/libedataserver/e-webdav-session.h
+++ b/src/libedataserver/e-webdav-session.h
@@ -160,7 +160,7 @@ typedef enum {
} EWebDAVListFlags;
/**
- * EWebDAVMultistatusTraverseFunc:
+ * EWebDAVPropstatTraverseFunc:
* @webdav: an #EWebDAVSession
* @xpath_ctx: an #xmlXPathContextPtr
* @xpath_prop_prefix: (nullable): an XPath prefix for the current prop element, without trailing forward
slash
@@ -169,19 +169,20 @@ typedef enum {
* @status_code: an HTTP status code for this property
* @user_data: user data, as passed to e_webdav_session_propfind_sync()
*
- * A callback function for e_webdav_session_propfind_sync().
+ * A callback function for e_webdav_session_propfind_sync(),
+ * e_webdav_session_report_sync() and other XML response with DAV:propstat
+ * elements traversal functions.
*
* The @xpath_prop_prefix can be %NULL only once, for the first time,
* which is meant to let the caller setup the @xpath_ctx, like to register
* its own namespaces to it with e_xml_xpath_context_register_namespaces().
* All other invocations of the function will have @xpath_prop_prefix non-%NULL.
*
- * Returns: %TRUE to continue traversal of the returned multistatus response,
- * %FALSE otherwise.
+ * Returns: %TRUE to continue traversal of the returned response, %FALSE otherwise.
*
* Since: 3.26
**/
-typedef gboolean (* EWebDAVMultistatusTraverseFunc) (EWebDAVSession *webdav,
+typedef gboolean (* EWebDAVPropstatTraverseFunc) (EWebDAVSession *webdav,
xmlXPathContextPtr xpath_ctx,
const gchar *xpath_prop_prefix,
const SoupURI *request_uri,
@@ -267,7 +268,7 @@ gboolean e_webdav_session_propfind_sync (EWebDAVSession *webdav,
const gchar *uri,
const gchar *depth,
const EXmlDocument *xml,
- EWebDAVMultistatusTraverseFunc func,
+ EWebDAVPropstatTraverseFunc func,
gpointer func_user_data,
GCancellable *cancellable,
GError **error);
@@ -280,7 +281,7 @@ gboolean e_webdav_session_report_sync (EWebDAVSession *webdav,
const gchar *uri,
const gchar *depth,
const EXmlDocument *xml,
- EWebDAVMultistatusTraverseFunc func,
+ EWebDAVPropstatTraverseFunc func,
gpointer func_user_data,
gchar **out_content_type,
GByteArray **out_content,
@@ -290,6 +291,12 @@ gboolean e_webdav_session_mkcol_sync (EWebDAVSession *webdav,
const gchar *uri,
GCancellable *cancellable,
GError **error);
+gboolean e_webdav_session_mkcol_addressbook_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *display_name,
+ const gchar *description,
+ GCancellable *cancellable,
+ GError **error);
gboolean e_webdav_session_mkcalendar_sync (EWebDAVSession *webdav,
const gchar *uri,
const gchar *display_name,
@@ -375,7 +382,21 @@ gboolean e_webdav_session_traverse_multistatus_response
(EWebDAVSession *webdav,
const SoupMessage *message,
const GByteArray *xml_data,
- EWebDAVMultistatusTraverseFunc func,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error);
+gboolean e_webdav_session_traverse_mkcol_response
+ (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ EWebDAVPropstatTraverseFunc func,
+ gpointer func_user_data,
+ GError **error);
+gboolean e_webdav_session_traverse_mkcalendar_response
+ (EWebDAVSession *webdav,
+ const SoupMessage *message,
+ const GByteArray *xml_data,
+ EWebDAVPropstatTraverseFunc func,
gpointer func_user_data,
GError **error);
gboolean e_webdav_session_getctag_sync (EWebDAVSession *webdav,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]