[evolution-data-server/wip/offline-cache] [EWebDAVSession] MKCALENDAR and REPORT
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] [EWebDAVSession] MKCALENDAR and REPORT
- Date: Fri, 31 Mar 2017 11:02:31 +0000 (UTC)
commit f165e5100ec677b98321b8ce781b4dd715fe79d6
Author: Milan Crha <mcrha redhat com>
Date: Fri Mar 31 13:02:04 2017 +0200
[EWebDAVSession] MKCALENDAR and REPORT
src/libedataserver/e-webdav-session.c | 412 +++++++++++++++++++++++++++++----
src/libedataserver/e-webdav-session.h | 27 ++-
2 files changed, 394 insertions(+), 45 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 6871416..55046c1 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -357,6 +357,7 @@ 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)
{
@@ -634,6 +635,48 @@ e_webdav_session_replace_with_detailed_error (EWebDAVSession *webdav,
return error_set;
}
+/**
+ * e_webdav_session_ensure_full_uri:
+ * @webdav: an #EWebDAVSession
+ * @request_uri: a #SoupURI to which the @href belongs
+ * @href: a possibly path-only href
+ *
+ * Converts possbily path-only @href into a full URI under
+ * the @request_uri. Free the returned pointer with g_free(),
+ * when no longer needed.
+ *
+ * Returns: (transfer full): The @href as a full URI
+ *
+ * Since: 3.24
+ **/
+gchar *
+e_webdav_session_ensure_full_uri (EWebDAVSession *webdav,
+ const SoupURI *request_uri,
+ const gchar *href)
+{
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), NULL);
+ g_return_val_if_fail (request_uri != NULL, NULL);
+ g_return_val_if_fail (href != NULL, NULL);
+
+ if (*href == '/' || !strstr (href, "://")) {
+ SoupURI *soup_uri;
+ gchar *full_uri;
+
+ soup_uri = soup_uri_copy ((SoupURI *) request_uri);
+ soup_uri_set_path (soup_uri, href);
+ soup_uri_set_user (soup_uri, NULL);
+ soup_uri_set_password (soup_uri, NULL);
+
+ full_uri = soup_uri_to_string (soup_uri, FALSE);
+
+ soup_uri_free (soup_uri);
+
+ return full_uri;
+ }
+
+ return g_strdup (href);
+}
+
static GHashTable *
e_webdav_session_comma_header_to_hashtable (SoupMessageHeaders *headers,
const gchar *header_name)
@@ -912,13 +955,134 @@ e_webdav_session_proppatch_sync (EWebDAVSession *webdav,
}
/**
+ * e_webdav_session_report_sync:
+ * @webdav: an #EWebDAVSession
+ * @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_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
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Issues REPORT request on the provided @uri, or, in case it's %NULL, on the URI
+ * defined in associated #ESource. On success, 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 report can result in a multistatus response, but also to raw data. In case
+ * the @func is provided and the result is a multistatus response, then it is traversed
+ * using this @func. 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.
+ *
+ * The optional @out_content_type can be used to get content type of the response.
+ * Free it with g_free(), when no longer needed.
+ *
+ * The optional @out_content can be used to get actual result content. Free it
+ * with g_byte_array_free(), when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_report_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *depth,
+ const EXmlDocument *xml,
+ EWebDAVMultistatusTraverseFunc func,
+ gpointer func_user_data,
+ gchar **out_content_type,
+ GByteArray **out_content,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupRequestHTTP *request;
+ SoupMessage *message;
+ GByteArray *bytes;
+ gchar *content;
+ gsize content_length;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (E_IS_XML_DOCUMENT (xml), FALSE);
+
+ if (out_content_type)
+ *out_content_type = NULL;
+
+ if (out_content)
+ *out_content = NULL;
+
+ request = e_webdav_session_new_request (webdav, "REPORT", 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;
+ }
+
+ if (!depth)
+ depth = E_WEBDAV_DEPTH_THIS;
+
+ soup_message_headers_replace (message->request_headers, "Depth", depth);
+
+ content = e_xml_document_get_content (xml, &content_length);
+ if (!content) {
+ g_object_unref (message);
+ g_object_unref (request);
+
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Failed to get input
XML content"));
+
+ return FALSE;
+ }
+
+ soup_message_set_request (message, E_WEBDAV_CONTENT_TYPE_XML,
+ SOUP_MEMORY_TAKE, content, content_length);
+
+ 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, TRUE, _("Failed to
issue REPORT"), error) &&
+ bytes != NULL;
+
+ if (success && func && message->status_code == SOUP_STATUS_MULTI_STATUS)
+ success = e_webdav_session_traverse_multistatus_response (webdav, message, bytes, func,
func_user_data, error);
+
+ if (success) {
+ if (out_content_type) {
+ *out_content_type = g_strdup (soup_message_headers_get_content_type
(message->response_headers, NULL));
+ }
+
+ if (out_content) {
+ *out_content = bytes;
+ bytes = NULL;
+ }
+ }
+
+ if (bytes)
+ g_byte_array_free (bytes, TRUE);
+ g_object_unref (message);
+ g_object_unref (request);
+
+ return success;
+}
+
+/**
* e_webdav_session_mkcol_sync:
* @webdav: an #EWebDAVSession
* @uri: URI of the collection to create
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Creates a new collection resource identified by @uri on the server.
+ * Creates a new generic collection identified by @uri on the server.
+ * To create specific collections use e_webdav_session_mkcalendar_sync().
*
* Returns: Whether succeeded.
*
@@ -953,25 +1117,159 @@ e_webdav_session_mkcol_sync (EWebDAVSession *webdav,
return success;
}
-/* This assumes ownership of 'text' */
-static gchar *
-e_webdav_session_maybe_dequote (gchar *text)
+/**
+ * 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
+ * @color: (nullable): a color to set, in format "#RRGGBB", or %NULL
+ * @supports: a bit-or of EWebDAVResourceSupports values
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a new calendar collection identified by @uri on the server.
+ * The @supports defines what component types can be stored into
+ * the created calendar collection. Only %E_WEBDAV_RESOURCE_SUPPORTS_NONE
+ * and values related to iCalendar content can be used here.
+ * Using %E_WEBDAV_RESOURCE_SUPPORTS_NONE means that everything is supported.
+ *
+ * Note that CalDAV RFC 4791 Section 4.2 forbids to create calendar
+ * resources under other calendar resources (no nested calendars
+ * are allowed).
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_mkcalendar_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *display_name,
+ const gchar *description,
+ const gchar *color,
+ guint32 supports,
+ GCancellable *cancellable,
+ GError **error)
{
- gchar *dequoted;
- gint len;
+ SoupRequestHTTP *request;
+ SoupMessage *message;
+ GByteArray *bytes;
+ gboolean success;
- if (!text || *text != '\"')
- return text;
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
- len = strlen (text);
+ request = e_webdav_session_new_request (webdav, "MKCALENDAR", uri, error);
+ if (!request)
+ return FALSE;
- if (len < 2 || text[len - 1] != '\"')
- return text;
+ message = soup_request_http_get_message (request);
+ if (!message) {
+ g_warn_if_fail (message != NULL);
+ g_object_unref (request);
+
+ return FALSE;
+ }
+
+ supports = supports & (
+ E_WEBDAV_RESOURCE_SUPPORTS_EVENTS |
+ E_WEBDAV_RESOURCE_SUPPORTS_MEMOS |
+ E_WEBDAV_RESOURCE_SUPPORTS_TASKS |
+ E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY |
+ E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE);
+
+ if ((display_name && *display_name) ||
+ (description && *description) ||
+ (color && *color) ||
+ (supports != 0)) {
+ EXmlDocument *xml;
+ gchar *content;
+ gsize content_length;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_CALDAV, "mkcalendar");
+ e_xml_document_add_namespaces (xml, "D", E_WEBDAV_NS_DAV, NULL);
+
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "set");
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "prop");
+
+ 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_CALDAV, "calendar-description");
+ e_xml_document_write_string (xml, description);
+ e_xml_document_end_element (xml);
+ }
- dequoted = g_strndup (text + 1, len - 2);
- g_free (text);
+ if (color && *color) {
+ e_xml_document_add_namespaces (xml, "IC", E_WEBDAV_NS_ICAL, NULL);
+
+ e_xml_document_start_text_element (xml, E_WEBDAV_NS_ICAL, "calendar-color");
+ e_xml_document_write_string (xml, color);
+ e_xml_document_end_element (xml);
+ }
+
+ if (supports != 0) {
+ struct SupportValues {
+ guint32 mask;
+ const gchar *value;
+ } values[] = {
+ { E_WEBDAV_RESOURCE_SUPPORTS_EVENTS, "VEVENT" },
+ { E_WEBDAV_RESOURCE_SUPPORTS_MEMOS, "VJOURNAL" },
+ { E_WEBDAV_RESOURCE_SUPPORTS_TASKS, "VTODO" },
+ { E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY, "VFREEBUSY" },
+ { E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE, "TIMEZONE" }
+ };
+ gint ii;
+
+ e_xml_document_start_text_element (xml, E_WEBDAV_NS_CALDAV,
"supported-calendar-component-set");
+
+ for (ii = 0; ii < G_N_ELEMENTS (values); ii++) {
+ if ((supports & values[ii].mask) != 0) {
+ e_xml_document_start_text_element (xml, E_WEBDAV_NS_CALDAV, "comp");
+ e_xml_document_add_attribute (xml, NULL, "name", values[ii].value);
+ e_xml_document_end_element (xml); /* comp */
+ }
+ }
+
+ e_xml_document_end_element (xml); /* supported-calendar-component-set */
+ }
+
+ 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);
- return dequoted;
+ 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 calendar"), error) &&
+ bytes != NULL;
+
+ if (bytes)
+ g_byte_array_free (bytes, TRUE);
+ g_object_unref (message);
+ g_object_unref (request);
+
+ return success;
}
static void
@@ -1011,7 +1309,7 @@ e_webdav_session_extract_href_and_etag (SoupMessage *message,
header = soup_message_headers_get_list (message->response_headers, "ETag");
if (header)
- *out_etag = e_webdav_session_maybe_dequote (g_strdup (header));
+ *out_etag = e_webdav_session_util_maybe_dequote (g_strdup (header));
}
}
@@ -2059,7 +2357,7 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
NULL);
if (xpath_ctx &&
- func (webdav, xpath_ctx, NULL, request_uri, SOUP_STATUS_NONE, func_user_data)) {
+ 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");
@@ -2078,8 +2376,20 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
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);
+ if (href) {
+ gchar *full_uri;
+
+ full_uri = e_webdav_session_ensure_full_uri (webdav,
request_uri, href);
+ if (full_uri) {
+ g_free (href);
+ href = full_uri;
+ }
+ }
+
propstat_length = xmlXPathNodeSetGetLength
(xpath_obj_propstat->nodesetval);
for (propstat_index = 0; propstat_index < propstat_length &&
!do_stop; propstat_index++) {
@@ -2094,12 +2404,13 @@ e_webdav_session_traverse_multistatus_response (EWebDAVSession *webdav,
status_code = 0;
g_free (status);
- do_stop = !func (webdav, xpath_ctx, propstat_prefix,
request_uri, status_code, func_user_data);
+ do_stop = !func (webdav, xpath_ctx, propstat_prefix,
request_uri, href, status_code, func_user_data);
g_free (propstat_prefix);
}
xmlXPathFreeObject (xpath_obj_propstat);
+ g_free (href);
}
}
@@ -2119,6 +2430,7 @@ e_webdav_session_getctag_cb (EWebDAVSession *webdav,
xmlXPathContextPtr xpath_ctx,
const gchar *xpath_prop_prefix,
const SoupURI *request_uri,
+ const gchar *href,
guint status_code,
gpointer user_data)
{
@@ -2139,7 +2451,7 @@ e_webdav_session_getctag_cb (EWebDAVSession *webdav,
ctag = e_xml_xpath_eval_as_string (xpath_ctx, "%s/CS:getctag", xpath_prop_prefix);
if (ctag && *ctag) {
- *out_ctag = e_webdav_session_maybe_dequote (ctag);
+ *out_ctag = e_webdav_session_util_maybe_dequote (ctag);
} else {
g_free (ctag);
}
@@ -2260,6 +2572,8 @@ e_webdav_session_extract_supports (xmlXPathContextPtr xpath_ctx,
supports |= E_WEBDAV_RESOURCE_SUPPORTS_TASKS;
else if (g_ascii_strcasecmp (name, "VFREEBUSY") == 0)
supports |= E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY;
+ else if (g_ascii_strcasecmp (name, "VTIMEZONE") == 0)
+ supports |= E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE;
g_free (name);
}
@@ -2272,7 +2586,8 @@ e_webdav_session_extract_supports (xmlXPathContextPtr xpath_ctx,
E_WEBDAV_RESOURCE_SUPPORTS_EVENTS |
E_WEBDAV_RESOURCE_SUPPORTS_MEMOS |
E_WEBDAV_RESOURCE_SUPPORTS_TASKS |
- E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY;
+ E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY |
+ E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE;
}
}
@@ -2302,7 +2617,7 @@ e_webdav_session_extract_nonempty (xmlXPathContextPtr xpath_ctx,
return NULL;
}
- return e_webdav_session_maybe_dequote (value);
+ return e_webdav_session_util_maybe_dequote (value);
}
static gsize
@@ -2358,6 +2673,7 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
xmlXPathContextPtr xpath_ctx,
const gchar *xpath_prop_prefix,
const SoupURI *request_uri,
+ const gchar *href,
guint status_code,
gpointer user_data)
{
@@ -2381,7 +2697,6 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
EWebDAVResource *resource;
EWebDAVResourceKind kind;
guint32 supports;
- gchar *href;
gchar *etag;
gchar *display_name;
gchar *content_type;
@@ -2395,27 +2710,6 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
if (kind == E_WEBDAV_RESOURCE_KIND_UNKNOWN)
return TRUE;
- href = e_xml_xpath_eval_as_string (xpath_ctx, "%s/../../D:href", xpath_prop_prefix);
- if (!href)
- return TRUE;
-
- if (!strstr (href, "://")) {
- SoupURI *soup_uri;
- gchar *full_uri;
-
- soup_uri = soup_uri_copy ((SoupURI *) request_uri);
- soup_uri_set_path (soup_uri, href);
- soup_uri_set_user (soup_uri, NULL);
- soup_uri_set_password (soup_uri, NULL);
-
- full_uri = soup_uri_to_string (soup_uri, FALSE);
-
- soup_uri_free (soup_uri);
- g_free (href);
-
- href = full_uri;
- }
-
supports = e_webdav_session_extract_supports (xpath_ctx, xpath_prop_prefix);
etag = e_webdav_session_extract_nonempty (xpath_ctx, xpath_prop_prefix, "D:getetag",
"CS:getctag");
display_name = e_webdav_session_extract_nonempty (xpath_ctx, xpath_prop_prefix,
"D:displayname", NULL);
@@ -2427,7 +2721,7 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
color = e_webdav_session_extract_nonempty (xpath_ctx, xpath_prop_prefix, "IC:calendar-color",
NULL);
resource = e_webdav_resource_new (kind, supports,
- NULL, /* href */
+ href,
NULL, /* etag */
NULL, /* display_name */
NULL, /* content_type */
@@ -2436,7 +2730,6 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
last_modified,
NULL, /* description */
NULL); /* color */
- resource->href = href;
resource->etag = etag;
resource->display_name = display_name;
resource->content_type = content_type;
@@ -2791,3 +3084,34 @@ e_webdav_session_lock_resource_sync (EWebDAVSession *webdav,
return success;
}
+
+/**
+ * e_webdav_session_util_maybe_dequote:
+ * @text: (inout): text to dequote
+ *
+ * Dequotes @text, if it's enclosed in double-quotes. The function
+ * changes @text, it doesn't allocate new string. The function does
+ * nothing when the @text is not enclosed in double-quotes.
+ *
+ * Returns: possibly dequoted @text
+ *
+ * Since: 3.26
+ **/
+gchar *
+e_webdav_session_util_maybe_dequote (gchar *text)
+{
+ gint len;
+
+ if (!text || *text != '\"')
+ return text;
+
+ len = strlen (text);
+
+ if (len < 2 || text[len - 1] != '\"')
+ return text;
+
+ memmove (text, text + 1, len - 2);
+ text[len - 2] = '\0';
+
+ return text;
+}
diff --git a/src/libedataserver/e-webdav-session.h b/src/libedataserver/e-webdav-session.h
index d845e50..c1aed39 100644
--- a/src/libedataserver/e-webdav-session.h
+++ b/src/libedataserver/e-webdav-session.h
@@ -110,7 +110,8 @@ typedef enum {
E_WEBDAV_RESOURCE_SUPPORTS_EVENTS = 1 << 1,
E_WEBDAV_RESOURCE_SUPPORTS_MEMOS = 1 << 2,
E_WEBDAV_RESOURCE_SUPPORTS_TASKS = 1 << 3,
- E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY = 1 << 4
+ E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY = 1 << 4,
+ E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE = 1 << 5
} EWebDAVResourceSupports;
typedef struct _EWebDAVResource {
@@ -164,6 +165,7 @@ typedef enum {
* @xpath_ctx: an #xmlXPathContextPtr
* @xpath_prop_prefix: (nullable): an XPath prefix for the current prop element, without trailing forward
slash
* @request_uri: a #SoupURI, containing the request URI, maybe redirected by the server
+ * @href: (nullable): a full URI to which the property belongs, or %NULL, when not found
* @status_code: an HTTP status code for this property
* @user_data: user data, as passed to e_webdav_session_propfind_sync()
*
@@ -183,6 +185,7 @@ typedef gboolean (* EWebDAVMultistatusTraverseFunc) (EWebDAVSession *webdav,
xmlXPathContextPtr xpath_ctx,
const gchar *xpath_prop_prefix,
const SoupURI *request_uri,
+ const gchar *href,
guint status_code,
gpointer user_data);
@@ -251,6 +254,9 @@ gboolean e_webdav_session_replace_with_detailed_error
gboolean ignore_multistatus,
const gchar *prefix,
GError **inout_error);
+gchar * e_webdav_session_ensure_full_uri (EWebDAVSession *webdav,
+ const SoupURI *request_uri,
+ const gchar *href);
gboolean e_webdav_session_options_sync (EWebDAVSession *webdav,
const gchar *uri,
GHashTable **out_capabilities,
@@ -270,10 +276,28 @@ gboolean e_webdav_session_proppatch_sync (EWebDAVSession *webdav,
const EXmlDocument *xml,
GCancellable *cancellable,
GError **error);
+gboolean e_webdav_session_report_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *depth,
+ const EXmlDocument *xml,
+ EWebDAVMultistatusTraverseFunc func,
+ gpointer func_user_data,
+ gchar **out_content_type,
+ GByteArray **out_content,
+ GCancellable *cancellable,
+ GError **error);
gboolean e_webdav_session_mkcol_sync (EWebDAVSession *webdav,
const gchar *uri,
GCancellable *cancellable,
GError **error);
+gboolean e_webdav_session_mkcalendar_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const gchar *display_name,
+ const gchar *description,
+ const gchar *color,
+ guint32 supports, /* bit-or of
EWebDAVResourceSupports */
+ GCancellable *cancellable,
+ GError **error);
gboolean e_webdav_session_get_sync (EWebDAVSession *webdav,
const gchar *uri,
gchar **out_href,
@@ -379,6 +403,7 @@ gboolean e_webdav_session_lock_resource_sync (EWebDAVSession *webdav,
gchar **out_lock_token,
GCancellable *cancellable,
GError **error);
+gchar * e_webdav_session_util_maybe_dequote (gchar *text);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]