[evolution-data-server/wip/offline-cache] EWebDAVSession - add ACL extension functions
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] EWebDAVSession - add ACL extension functions
- Date: Tue, 4 Apr 2017 17:51:12 +0000 (UTC)
commit 02e8005b50e1052584520573f3866653a570dd4c
Author: Milan Crha <mcrha redhat com>
Date: Tue Apr 4 19:50:38 2017 +0200
EWebDAVSession - add ACL extension functions
src/libedataserver/e-webdav-session.c | 1534 ++++++++++++++++++++++++++++++++-
src/libedataserver/e-webdav-session.h | 143 +++
2 files changed, 1663 insertions(+), 14 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 1a0c3bf..6202396 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -22,7 +22,8 @@
*
* The #EWebDAVSession is a class to work with WebDAV (RFC 4918),
* CalDAV (RFC 4791) or CardDAV (RFC 6352) servers, providing API
- * for common requests/responses, on top of an #ESoupSession.
+ * for common requests/responses, on top of an #ESoupSession. It
+ * supports also Access Control Protocol (RFC 3744).
**/
#include "evolution-data-server-config.h"
@@ -48,6 +49,8 @@ G_DEFINE_TYPE (EWebDAVSession, e_webdav_session, E_TYPE_SOUP_SESSION)
G_DEFINE_BOXED_TYPE (EWebDAVResource, e_webdav_resource, e_webdav_resource_copy, e_webdav_resource_free)
G_DEFINE_BOXED_TYPE (EWebDAVPropertyChange, e_webdav_property_change, e_webdav_property_change_copy,
e_webdav_property_change_free)
+G_DEFINE_BOXED_TYPE (EWebDAVPrivilege, e_webdav_privilege, e_webdav_privilege_copy, e_webdav_privilege_free)
+G_DEFINE_BOXED_TYPE (EWebDAVAccessControlEntry, e_webdav_access_control_entry,
e_webdav_access_control_entry_copy, e_webdav_access_control_entry_free)
/**
* e_webdav_resource_new:
@@ -135,7 +138,7 @@ e_webdav_resource_copy (const EWebDAVResource *src)
* @ptr: (nullable): an #EWebDAVResource
*
* Frees an #EWebDAVResource previously created with e_webdav_resource_new()
- * or e_webdav_resource_copy(). The function does nothing if @ptr is %NULL.
+ * or e_webdav_resource_copy(). The function does nothing, if @ptr is %NULL.
*
* Since: 3.26
**/
@@ -253,7 +256,7 @@ e_webdav_property_change_copy (const EWebDAVPropertyChange *src)
*
* Frees an #EWebDAVPropertyChange previously created with e_webdav_property_change_new_set(),
* e_webdav_property_change_new_remove() or or e_webdav_property_change_copy().
- * The function does nothing if @ptr is %NULL.
+ * The function does nothing, if @ptr is %NULL.
*
* Since: 3.26
**/
@@ -270,6 +273,324 @@ e_webdav_property_change_free (gpointer ptr)
}
}
+/**
+ * e_webdav_privilege_new:
+ * @ns_uri: (nullable): a namespace URI
+ * @name: (nullable): element name
+ * @description: (nullable): human read-able description, or %NULL
+ * @kind: an #EWebDAVPrivilegeKind
+ * @hint: an #EWebDAVPrivilegeHint
+ *
+ * Describes one privilege entry. The @hint can be %E_WEBDAV_PRIVILEGE_HINT_UNKNOWN
+ * for privileges which are not known to the #EWebDAVSession. It's possible, because
+ * the servers can define their own privileges. The hint is also tried to pair with
+ * known hnts when it's %E_WEBDAV_PRIVILEGE_HINT_UNKNOWN.
+ *
+ * The @ns_uri and @name can be %NULL only if the @hint is one of the known
+ * privileges. Otherwise it's an error to pass either of the two as %NULL.
+ *
+ * Returns: (transfer full): A newly created #EWebDAVPrivilege, prefilled with
+ * given values. Free it with e_webdav_privilege_free(), when no longer needed.
+ *
+ * Since: 3.26
+ **/
+EWebDAVPrivilege *
+e_webdav_privilege_new (const gchar *ns_uri,
+ const gchar *name,
+ const gchar *description,
+ EWebDAVPrivilegeKind kind,
+ EWebDAVPrivilegeHint hint)
+{
+ EWebDAVPrivilege *privilege;
+
+ if ((!ns_uri || !name) && hint != E_WEBDAV_PRIVILEGE_HINT_UNKNOWN) {
+ const gchar *use_ns_uri = NULL, *use_name = NULL;
+
+ switch (hint) {
+ case E_WEBDAV_PRIVILEGE_HINT_UNKNOWN:
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_READ:
+ use_name = "read";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_WRITE:
+ use_name = "write";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_WRITE_PROPERTIES:
+ use_name = "write-properties";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_WRITE_CONTENT:
+ use_name = "write-content";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_UNLOCK:
+ use_name = "unlock";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_READ_ACL:
+ use_name = "read-acl";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_WRITE_ACL:
+ use_name = "write-acl";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_READ_CURRENT_USER_PRIVILEGE_SET:
+ use_name = "read-current-user-privilege-set";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_BIND:
+ use_name = "bind";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_UNBIND:
+ use_name = "unbind";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_ALL:
+ use_name = "all";
+ break;
+ case E_WEBDAV_PRIVILEGE_HINT_CALDAV_READ_FREE_BUSY:
+ use_ns_uri = E_WEBDAV_NS_CALDAV;
+ use_name = "read-free-busy";
+ break;
+ }
+
+ if (use_name) {
+ ns_uri = use_ns_uri ? use_ns_uri : E_WEBDAV_NS_DAV;
+ name = use_name;
+ }
+ }
+
+ g_return_val_if_fail (ns_uri != NULL, NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ if (hint == E_WEBDAV_PRIVILEGE_HINT_UNKNOWN) {
+ if (g_str_equal (ns_uri, E_WEBDAV_NS_DAV)) {
+ if (g_str_equal (name, "read"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_READ;
+ else if (g_str_equal (name, "write"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_WRITE;
+ else if (g_str_equal (name, "write-properties"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_WRITE_PROPERTIES;
+ else if (g_str_equal (name, "write-content"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_WRITE_CONTENT;
+ else if (g_str_equal (name, "unlock"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_UNLOCK;
+ else if (g_str_equal (name, "read-acl"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_READ_ACL;
+ else if (g_str_equal (name, "write-acl"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_WRITE_ACL;
+ else if (g_str_equal (name, "read-current-user-privilege-set"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_READ_CURRENT_USER_PRIVILEGE_SET;
+ else if (g_str_equal (name, "bind"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_BIND;
+ else if (g_str_equal (name, "unbind"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_UNBIND;
+ else if (g_str_equal (name, "all"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_ALL;
+ } else if (g_str_equal (ns_uri, E_WEBDAV_NS_CALDAV)) {
+ if (g_str_equal (name, "read-free-busy"))
+ hint = E_WEBDAV_PRIVILEGE_HINT_CALDAV_READ_FREE_BUSY;
+ }
+ }
+
+ privilege = g_new (EWebDAVPrivilege, 1);
+ privilege->ns_uri = g_strdup (ns_uri);
+ privilege->name = g_strdup (name);
+ privilege->description = g_strdup (description);
+ privilege->kind = kind;
+ privilege->hint = hint;
+
+ return privilege;
+}
+
+/**
+ * e_webdav_privilege_copy:
+ * @src: (nullable): an #EWebDAVPrivilege to make a copy of
+ *
+ * Returns: (transfer full): A new #EWebDAVPrivilege prefilled with
+ * the same values as @src, or %NULL, when @src is %NULL.
+ * Free it with e_webdav_privilege_free(), when no longer needed.
+ *
+ * Since: 3.26
+ **/
+EWebDAVPrivilege *
+e_webdav_privilege_copy (const EWebDAVPrivilege *src)
+{
+ if (!src)
+ return NULL;
+
+ return e_webdav_privilege_new (
+ src->ns_uri,
+ src->name,
+ src->description,
+ src->kind,
+ src->hint);
+}
+
+/**
+ * e_webdav_privilege_free:
+ * @ptr: (nullable): an #EWebDAVPrivilege
+ *
+ * Frees an #EWebDAVPrivilege previously created with e_webdav_privilege_new()
+ * or e_webdav_privilege_copy(). The function does nothing, if @ptr is %NULL.
+ *
+ * Since: 3.26
+ **/
+void
+e_webdav_privilege_free (gpointer ptr)
+{
+ EWebDAVPrivilege *privilege = ptr;
+
+ if (privilege) {
+ g_free (privilege->ns_uri);
+ g_free (privilege->name);
+ g_free (privilege->description);
+ g_free (privilege);
+ }
+}
+
+/**
+ * e_webdav_access_control_entry_new:
+ * @principal_kind: an #EWebDAVACEPrincipalKind
+ * @principal_href: (nullable): principal href; should be set only if @principal_kind is
@E_WEBDAV_ACE_PRINCIPAL_HREF
+ * @flags: bit-or of #EWebDAVACEFlag values
+ * @inherited_href: (nullable): href of the resource from which inherits; should be set only if @flags
contain E_WEBDAV_ACE_FLAG_INHERITED
+ *
+ * Describes one Access Control Entry (ACE).
+ *
+ * The @flags should always contain either %E_WEBDAV_ACE_FLAG_GRANT or
+ * %E_WEBDAV_ACE_FLAG_DENY value.
+ *
+ * Use e_webdav_access_control_entry_append_privilege() to add respective
+ * privileges to the entry.
+ *
+ * Returns: (transfer full): A newly created #EWebDAVAccessControlEntry, prefilled with
+ * given values. Free it with e_webdav_access_control_entry_free(), when no longer needed.
+ *
+ * Since: 3.26
+ **/
+EWebDAVAccessControlEntry *
+e_webdav_access_control_entry_new (EWebDAVACEPrincipalKind principal_kind,
+ const gchar *principal_href,
+ guint32 flags,
+ const gchar *inherited_href)
+{
+ EWebDAVAccessControlEntry *ace;
+
+ if (principal_kind == E_WEBDAV_ACE_PRINCIPAL_HREF)
+ g_return_val_if_fail (principal_href != NULL, NULL);
+ else
+ g_return_val_if_fail (principal_href == NULL, NULL);
+
+ if ((flags & E_WEBDAV_ACE_FLAG_INHERITED) != 0)
+ g_return_val_if_fail (inherited_href != NULL, NULL);
+ else
+ g_return_val_if_fail (inherited_href == NULL, NULL);
+
+ ace = g_new0 (EWebDAVAccessControlEntry, 1);
+ ace->principal_kind = principal_kind;
+ ace->principal_href = g_strdup (principal_href);
+ ace->flags = flags;
+ ace->inherited_href = g_strdup (inherited_href);
+ ace->privileges = NULL;
+
+ return ace;
+}
+
+/**
+ * e_webdav_access_control_entry_copy:
+ * @src: (nullable): an #EWebDAVAccessControlEntry to make a copy of
+ *
+ * Returns: (transfer full): A new #EWebDAVAccessControlEntry prefilled with
+ * the same values as @src, or %NULL, when @src is %NULL.
+ * Free it with e_webdav_access_control_entry_free(), when no longer needed.
+ *
+ * Since: 3.26
+ **/
+EWebDAVAccessControlEntry *
+e_webdav_access_control_entry_copy (const EWebDAVAccessControlEntry *src)
+{
+ EWebDAVAccessControlEntry *ace;
+ GSList *link;
+
+ if (!src)
+ return NULL;
+
+ ace = e_webdav_access_control_entry_new (
+ src->principal_kind,
+ src->principal_href,
+ src->flags,
+ src->inherited_href);
+ if (!ace)
+ return NULL;
+
+ for (link = src->privileges; link; link = g_slist_next (link)) {
+ EWebDAVPrivilege *privilege = link->data;
+
+ if (privilege)
+ ace->privileges = g_slist_prepend (ace->privileges, e_webdav_privilege_copy
(privilege));
+ }
+
+ ace->privileges = g_slist_reverse (ace->privileges);
+
+ return ace;
+}
+
+/**
+ * e_webdav_access_control_entry_free:
+ * @ptr: (nullable): an #EWebDAVAccessControlEntry
+ *
+ * Frees an #EWebDAVAccessControlEntry previously created with e_webdav_access_control_entry_new()
+ * or e_webdav_access_control_entry_copy(). The function does nothing, if @ptr is %NULL.
+ *
+ * Since: 3.26
+ **/
+void
+e_webdav_access_control_entry_free (gpointer ptr)
+{
+ EWebDAVAccessControlEntry *ace = ptr;
+
+ if (ace) {
+ g_free (ace->principal_href);
+ g_free (ace->inherited_href);
+ g_slist_free_full (ace->privileges, e_webdav_privilege_free);
+ g_free (ace);
+ }
+}
+
+/**
+ * e_webdav_access_control_entry_append_privilege:
+ * @ace: an #EWebDAVAccessControlEntry
+ * @privilege: (transfer full): an #EWebDAVPrivilege
+ *
+ * Appends a new @privilege to the list of privileges for the @ace.
+ * The function assumes ownership of the @privilege, which is freed
+ * together with the @ace.
+ *
+ * Since: 3.26
+ **/
+void
+e_webdav_access_control_entry_append_privilege (EWebDAVAccessControlEntry *ace,
+ EWebDAVPrivilege *privilege)
+{
+ g_return_if_fail (ace != NULL);
+ g_return_if_fail (privilege != NULL);
+
+ ace->privileges = g_slist_append (ace->privileges, privilege);
+}
+
+/**
+ * e_webdav_access_control_entry_get_privileges:
+ * @ace: an #EWebDAVAccessControlEntry
+ *
+ * Returns: (element-type EWebDAVPrivilege) (transfer none): A #GSList of #EWebDAVPrivilege
+ * with the list of privileges for the @ace. The reurned #GSList, together with its data
+ * is owned by the @ace.
+ *
+ * Since: 3.26
+ **/
+GSList *
+e_webdav_access_control_entry_get_privileges (EWebDAVAccessControlEntry *ace)
+{
+ g_return_val_if_fail (ace != NULL, NULL);
+
+ return ace->privileges;
+}
+
static void
e_webdav_session_class_init (EWebDAVSessionClass *klass)
{
@@ -2489,7 +2810,7 @@ e_webdav_session_traverse_propstat_response (EWebDAVSession *webdav,
xpath_obj_response = e_xml_xpath_eval (xpath_ctx, "%s", propstat_path_prefix);
- if (xpath_obj_response != NULL) {
+ if (xpath_obj_response) {
gboolean do_stop = FALSE;
gint response_index, response_length;
@@ -2502,7 +2823,7 @@ e_webdav_session_traverse_propstat_response (EWebDAVSession *webdav,
"%s[%d]/D:propstat",
propstat_path_prefix, response_index + 1);
- if (xpath_obj_propstat != NULL) {
+ if (xpath_obj_propstat) {
gchar *href;
gint propstat_index, propstat_length;
@@ -2721,10 +3042,11 @@ e_webdav_session_getctag_cb (EWebDAVSession *webdav,
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Issues a getctag property request for a collection identified by @uri, or
- * by the #ESource resource reference. The ctag is a collection tag, which
- * changes whenever the collection changes (similar to etag). The getctag is
- * an extension, thus the function can fail when the server doesn't support it.
+ * Issues a getctag property request for a collection identified by @uri, or,
+ * in case it's %NULL, on the URI defined in associated #ESource. The ctag is
+ * a collection tag, which changes whenever the collection changes (similar
+ * to etag). The getctag is an extension, thus the function can fail when
+ * the server doesn't support it.
*
* Free the returned @out_ctag with g_free(), when no longer needed.
*
@@ -3005,9 +3327,9 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Lists content of the @uri, or the one stored with the associated #ESource,
- * which should point to a collection. The @flags influences which properties
- * are read for the resources.
+ * Lists content of the @uri, or, in case it's %NULL, of the URI defined
+ * in associated #ESource, which should point to a collection. The @flags
+ * influences which properties are read for the resources.
*
* The @out_resources is in no particular order.
*
@@ -3159,7 +3481,7 @@ e_webdav_session_list_sync (EWebDAVSession *webdav,
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Updates proeprties (set/remove) on the provided @uri, or, in case it's %NULL,
+ * Updates properties (set/remove) on the provided @uri, or, in case it's %NULL,
* on the URI defined in associated #ESource, with the @changes. The order
* of @changes is significant, unlike on other places.
*
@@ -3235,7 +3557,7 @@ e_webdav_session_update_properties_sync (EWebDAVSession *webdav,
* @cancellable: optional #GCancellable object, or %NULL
* @error: return location for a #GError, or %NULL
*
- * Locks a resource identified by @uri, or, in case it's %NULL, on the URI defined
+ * Locks a resource identified by @uri, or, in case it's %NULL, by the URI defined
* in associated #ESource. It obtains a write lock with the given @lock_scope.
*
* The @owner is used to identify the lock owner. When it's an http:// or https://,
@@ -3338,6 +3660,1159 @@ e_webdav_session_lock_resource_sync (EWebDAVSession *webdav,
return success;
}
+static void
+e_webdav_session_traverse_privilege_level (xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prefix,
+ GNode *parent)
+{
+ xmlXPathObjectPtr xpath_obj;
+
+ g_return_if_fail (xpath_ctx != NULL);
+ g_return_if_fail (xpath_prefix != NULL);
+ g_return_if_fail (parent != NULL);
+
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/D:supported-privilege", xpath_prefix);
+
+ if (xpath_obj) {
+ gint ii, length;
+
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ xmlXPathObjectPtr xpath_obj_privilege;
+ gchar *prefix;
+
+ prefix = g_strdup_printf ("%s/D:supported-privilege[%d]", xpath_prefix, ii + 1);
+ xpath_obj_privilege = e_xml_xpath_eval (xpath_ctx, "%s/D:privilege", prefix);
+
+ if (xpath_obj_privilege &&
+ xpath_obj_privilege->type == XPATH_NODESET &&
+ xpath_obj_privilege->nodesetval &&
+ xpath_obj_privilege->nodesetval->nodeNr == 1 &&
+ xpath_obj_privilege->nodesetval->nodeTab &&
+ xpath_obj_privilege->nodesetval->nodeTab[0] &&
+ xpath_obj_privilege->nodesetval->nodeTab[0]->children) {
+ xmlNodePtr node;
+
+ for (node = xpath_obj_privilege->nodesetval->nodeTab[0]->children; node; node
= node->next) {
+ if (node->type == XML_ELEMENT_NODE &&
+ node->name && *(node->name) &&
+ node->ns && node->ns->href && *(node->ns->href)) {
+ break;
+ }
+ }
+
+ if (node) {
+ GNode *child;
+ gchar *description;
+ EWebDAVPrivilegeKind kind = E_WEBDAV_PRIVILEGE_KIND_COMMON;
+ EWebDAVPrivilegeHint hint = E_WEBDAV_PRIVILEGE_HINT_UNKNOWN;
+ EWebDAVPrivilege *privilege;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:abstract", prefix))
+ kind = E_WEBDAV_PRIVILEGE_KIND_ABSTRACT;
+ else if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:aggregate",
prefix))
+ kind = E_WEBDAV_PRIVILEGE_KIND_AGGREGATE;
+
+ description = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/D:description", prefix);
+ privilege = e_webdav_privilege_new ((const gchar *) node->ns->href,
(const gchar *) node->name, description, kind, hint);
+ child = g_node_new (privilege);
+ g_node_append (parent, child);
+
+ g_free (description);
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:supported-privilege",
prefix))
+ e_webdav_session_traverse_privilege_level (xpath_ctx, prefix,
child);
+ }
+ }
+
+ if (xpath_obj_privilege)
+ xmlXPathFreeObject (xpath_obj_privilege);
+
+ g_free (prefix);
+ }
+
+ xmlXPathFreeObject (xpath_obj);
+ }
+}
+
+static gboolean
+e_webdav_session_supported_privilege_set_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ GNode **out_privileges = user_data;
+
+ g_return_val_if_fail (out_privileges != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ e_xml_xpath_context_register_namespaces (xpath_ctx,
+ "C", E_WEBDAV_NS_CALDAV,
+ NULL);
+ } else if (status_code == SOUP_STATUS_OK &&
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:supported-privilege-set/D:supported-privilege",
xpath_prop_prefix)) {
+ GNode *root;
+ gchar *prefix;
+
+ prefix = g_strconcat (xpath_prop_prefix, "/D:supported-privilege-set", NULL);
+ root = g_node_new (NULL);
+
+ e_webdav_session_traverse_privilege_level (xpath_ctx, prefix, root);
+
+ *out_privileges = root;
+
+ g_free (prefix);
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_acl_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @xml:the request itself, as an #EXmlDocument, the root element should be DAV:acl
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Issues ACL request on the provided @uri, or, in case it's %NULL, on the URI
+ * defined in associated #ESource.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const EXmlDocument *xml,
+ 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);
+
+ request = e_webdav_session_new_request (webdav, "ACL", 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;
+ }
+
+ 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
get properties"), error) &&
+ bytes != NULL;
+
+ if (bytes)
+ g_byte_array_free (bytes, TRUE);
+ g_object_unref (message);
+ g_object_unref (request);
+
+ return success;
+}
+
+/**
+ * e_webdav_session_get_supported_privilege_set_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @out_privileges: (out) (transfer full) (element-type EWebDAVPrivilege): return location for the tree of
supported privileges
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets supported privileges for the @uri, or, in case it's %NULL, for the URI
+ * defined in associated #ESource.
+ *
+ * The root node of @out_privileges has always %NULL data.
+ *
+ * Free the returned @out_privileges with e_webdav_session_util_free_privileges()
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_get_supported_privilege_set_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ GNode **out_privileges,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (out_privileges != NULL, FALSE);
+
+ *out_privileges = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "supported-privilege-set");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_supported_privilege_set_cb, out_privileges, cancellable, error);
+
+ g_object_unref (xml);
+
+ return success;
+}
+
+static EWebDAVPrivilege *
+e_webdav_session_extract_privilege_simple (xmlXPathObjectPtr xpath_obj_privilege)
+{
+ EWebDAVPrivilege *privilege = NULL;
+
+ if (xpath_obj_privilege &&
+ xpath_obj_privilege->type == XPATH_NODESET &&
+ xpath_obj_privilege->nodesetval &&
+ xpath_obj_privilege->nodesetval->nodeNr == 1 &&
+ xpath_obj_privilege->nodesetval->nodeTab &&
+ xpath_obj_privilege->nodesetval->nodeTab[0] &&
+ xpath_obj_privilege->nodesetval->nodeTab[0]->children) {
+ xmlNodePtr node;
+
+ for (node = xpath_obj_privilege->nodesetval->nodeTab[0]->children; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE &&
+ node->name && *(node->name) &&
+ node->ns && node->ns->href && *(node->ns->href)) {
+ break;
+ }
+ }
+
+ if (node) {
+ privilege = e_webdav_privilege_new ((const gchar *) node->ns->href, (const gchar *)
node->name,
+ NULL, E_WEBDAV_PRIVILEGE_KIND_COMMON, E_WEBDAV_PRIVILEGE_HINT_UNKNOWN);
+ }
+ }
+
+ return privilege;
+}
+
+static gboolean
+e_webdav_session_current_user_privilege_set_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ GSList **out_privileges = user_data;
+
+ g_return_val_if_fail (xpath_ctx != NULL, FALSE);
+ g_return_val_if_fail (out_privileges != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ e_xml_xpath_context_register_namespaces (xpath_ctx,
+ "C", E_WEBDAV_NS_CALDAV,
+ NULL);
+ } else if (status_code == SOUP_STATUS_OK &&
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:current-user-privilege-set/D:privilege",
xpath_prop_prefix)) {
+ xmlXPathObjectPtr xpath_obj;
+
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/D:current-user-privilege-set/D:privilege",
xpath_prop_prefix);
+
+ if (xpath_obj) {
+ gint ii, length;
+
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ xmlXPathObjectPtr xpath_obj_privilege;
+
+ xpath_obj_privilege = e_xml_xpath_eval (xpath_ctx,
"%s/D:current-user-privilege-set/D:privilege[%d]", xpath_prop_prefix, ii + 1);
+
+ if (xpath_obj_privilege) {
+ EWebDAVPrivilege *privilege;
+
+ privilege = e_webdav_session_extract_privilege_simple
(xpath_obj_privilege);
+ if (privilege)
+ *out_privileges = g_slist_prepend (*out_privileges,
privilege);
+
+ xmlXPathFreeObject (xpath_obj_privilege);
+ }
+ }
+
+ xmlXPathFreeObject (xpath_obj);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_get_current_user_privilege_set_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @out_privileges: (out) (transfer full) (element-type EWebDAVPrivilege): return location for a %GSList of
#EWebDAVPrivilege
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets current user privileges for the @uri, or, in case it's %NULL, for the URI
+ * defined in associated #ESource.
+ *
+ * Free the returned @out_privileges with
+ * g_slist_free_full (privileges, e_webdav_privilege_free);
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_get_current_user_privilege_set_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_privileges,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (out_privileges != NULL, FALSE);
+
+ *out_privileges = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "current-user-privilege-set");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_current_user_privilege_set_cb, out_privileges, cancellable, error);
+
+ g_object_unref (xml);
+
+ if (success)
+ *out_privileges = g_slist_reverse (*out_privileges);
+
+ return success;
+}
+
+static EWebDAVACEPrincipalKind
+e_webdav_session_extract_acl_principal (xmlXPathContextPtr xpath_ctx,
+ const gchar *principal_prefix,
+ gchar **out_principal_href,
+ GSList **out_principal_hrefs)
+{
+ g_return_val_if_fail (xpath_ctx != NULL, E_WEBDAV_ACE_PRINCIPAL_UNKNOWN);
+ g_return_val_if_fail (principal_prefix != NULL, E_WEBDAV_ACE_PRINCIPAL_UNKNOWN);
+ g_return_val_if_fail (out_principal_href != NULL || out_principal_hrefs != NULL,
E_WEBDAV_ACE_PRINCIPAL_UNKNOWN);
+
+ *out_principal_href = NULL;
+
+ if (!e_xml_xpath_eval_exists (xpath_ctx, "%s", principal_prefix))
+ return E_WEBDAV_ACE_PRINCIPAL_UNKNOWN;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:href", principal_prefix)) {
+ if (out_principal_href) {
+ *out_principal_href = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:href",
principal_prefix);
+ } else {
+ xmlXPathObjectPtr xpath_obj;
+
+ *out_principal_hrefs = NULL;
+
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/D:href", principal_prefix);
+
+ if (xpath_obj) {
+ gint ii, length;
+
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ gchar *href;
+
+ href = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:href[%d]",
principal_prefix, ii + 1);
+ if (href)
+ *out_principal_hrefs = g_slist_prepend (*out_principal_hrefs,
href);
+ }
+ }
+
+ *out_principal_hrefs = g_slist_reverse (*out_principal_hrefs);
+ }
+
+ return E_WEBDAV_ACE_PRINCIPAL_HREF;
+ }
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:all", principal_prefix))
+ return E_WEBDAV_ACE_PRINCIPAL_ALL;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:authenticated", principal_prefix))
+ return E_WEBDAV_ACE_PRINCIPAL_AUTHENTICATED;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:unauthenticated", principal_prefix))
+ return E_WEBDAV_ACE_PRINCIPAL_UNAUTHENTICATED;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:self", principal_prefix))
+ return E_WEBDAV_ACE_PRINCIPAL_SELF;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:property", principal_prefix)) {
+ /* No details read about what properties */
+ EWebDAVACEPrincipalKind kind = E_WEBDAV_ACE_PRINCIPAL_PROPERTY;
+
+ /* Special-case owner */
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:property/D:owner", principal_prefix)) {
+ xmlXPathObjectPtr xpath_obj_property;
+
+ xpath_obj_property = e_xml_xpath_eval (xpath_ctx, "%s/D:property", principal_prefix);
+
+ /* DAV:owner is the only child and there is only one DAV:property child of the
DAV:principal */
+ if (xpath_obj_property &&
+ xpath_obj_property->type == XPATH_NODESET &&
+ xmlXPathNodeSetGetLength (xpath_obj_property->nodesetval) == 1 &&
+ xpath_obj_property->nodesetval &&
+ xpath_obj_property->nodesetval->nodeNr == 1 &&
+ xpath_obj_property->nodesetval->nodeTab &&
+ xpath_obj_property->nodesetval->nodeTab[0] &&
+ xpath_obj_property->nodesetval->nodeTab[0]->children) {
+ xmlNodePtr node;
+ gint subelements = 0;
+
+ for (node = xpath_obj_property->nodesetval->nodeTab[0]->children; node &&
subelements <= 1; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE)
+ subelements++;
+ }
+
+ if (subelements == 1)
+ kind = E_WEBDAV_ACE_PRINCIPAL_OWNER;
+ }
+
+ if (xpath_obj_property)
+ xmlXPathFreeObject (xpath_obj_property);
+ }
+
+ return kind;
+ }
+
+ return E_WEBDAV_ACE_PRINCIPAL_UNKNOWN;
+}
+
+static gboolean
+e_webdav_session_acl_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ GSList **out_entries = user_data;
+
+ g_return_val_if_fail (xpath_ctx != NULL, FALSE);
+ g_return_val_if_fail (out_entries != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ } else if (status_code == SOUP_STATUS_OK &&
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl/D:ace", xpath_prop_prefix)) {
+ xmlXPathObjectPtr xpath_obj_ace;
+
+ xpath_obj_ace = e_xml_xpath_eval (xpath_ctx, "%s/D:acl/D:ace", xpath_prop_prefix);
+
+ if (xpath_obj_ace) {
+ gint ii, length;
+
+ length = xmlXPathNodeSetGetLength (xpath_obj_ace->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ EWebDAVACEPrincipalKind principal_kind = E_WEBDAV_ACE_PRINCIPAL_UNKNOWN;
+ xmlXPathObjectPtr xpath_obj = NULL;
+ gchar *principal_href = NULL;
+ guint32 flags = E_WEBDAV_ACE_FLAG_UNKNOWN;
+ gchar *inherited_href = NULL;
+ gchar *privilege_prefix = NULL;
+ gchar *ace_prefix;
+
+ ace_prefix = g_strdup_printf ("%s/D:acl/D:ace[%d]", xpath_prop_prefix, ii +
1);
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:invert", ace_prefix)) {
+ gchar *prefix;
+
+ flags |= E_WEBDAV_ACE_FLAG_INVERT;
+
+ prefix = g_strdup_printf ("%s/D:invert/D:principal", ace_prefix);
+ principal_kind = e_webdav_session_extract_acl_principal (xpath_ctx,
prefix, &principal_href, NULL);
+ g_free (prefix);
+ } else {
+ gchar *prefix;
+
+ prefix = g_strdup_printf ("%s/D:principal", ace_prefix);
+ principal_kind = e_webdav_session_extract_acl_principal (xpath_ctx,
prefix, &principal_href, NULL);
+ g_free (prefix);
+ }
+
+ if (principal_kind == E_WEBDAV_ACE_PRINCIPAL_UNKNOWN) {
+ g_free (ace_prefix);
+ continue;
+ }
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:protected", ace_prefix))
+ flags |= E_WEBDAV_ACE_FLAG_PROTECTED;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:inherited/D:href", ace_prefix))
{
+ flags |= E_WEBDAV_ACE_FLAG_INHERITED;
+ inherited_href = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/D:inherited/D:href", ace_prefix);
+ }
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:grant", ace_prefix)) {
+ privilege_prefix = g_strdup_printf ("%s/D:grant/D:privilege",
ace_prefix);
+ flags |= E_WEBDAV_ACE_FLAG_GRANT;
+ } else if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:deny", ace_prefix)) {
+ privilege_prefix = g_strdup_printf ("%s/D:deny/D:privilege",
ace_prefix);
+ flags |= E_WEBDAV_ACE_FLAG_DENY;
+ }
+
+ if (privilege_prefix)
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s", privilege_prefix);
+
+ if (xpath_obj) {
+ EWebDAVAccessControlEntry *ace;
+ gint ii, length;
+
+ ace = e_webdav_access_control_entry_new (principal_kind,
principal_href, flags, inherited_href);
+ if (ace) {
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ xmlXPathObjectPtr xpath_obj_privilege;
+
+ xpath_obj_privilege = e_xml_xpath_eval (xpath_ctx,
"%s[%d]", privilege_prefix, ii + 1);
+
+ if (xpath_obj_privilege) {
+ EWebDAVPrivilege *privilege;
+
+ privilege =
e_webdav_session_extract_privilege_simple (xpath_obj_privilege);
+ if (privilege)
+ ace->privileges = g_slist_prepend
(ace->privileges, privilege);
+
+ xmlXPathFreeObject (xpath_obj_privilege);
+ }
+ }
+
+ ace->privileges = g_slist_reverse (ace->privileges);
+
+ *out_entries = g_slist_prepend (*out_entries, ace);
+ }
+
+ xmlXPathFreeObject (xpath_obj);
+ }
+
+ g_free (principal_href);
+ g_free (inherited_href);
+ g_free (privilege_prefix);
+ g_free (ace_prefix);
+ }
+
+ xmlXPathFreeObject (xpath_obj_ace);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_get_acl_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @out_entries: (out) (transfer full) (element-type EWebDAVAccessControlEntry): return location for a
#GSList of #EWebDAVAccessControlEntry
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets Access Control List (ACL) for the @uri, or, in case it's %NULL, for the URI
+ * defined in associated #ESource.
+ *
+ * This function doesn't read general #E_WEBDAV_ACE_PRINCIPAL_PROPERTY.
+ *
+ * Free the returned @out_entries with
+ * g_slist_free_full (entries, e_webdav_access_control_entry_free);
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_get_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_entries,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (out_entries != NULL, FALSE);
+
+ *out_entries = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "acl");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_acl_cb, out_entries, cancellable, error);
+
+ g_object_unref (xml);
+
+ if (success)
+ *out_entries = g_slist_reverse (*out_entries);
+
+ return success;
+}
+
+typedef struct _ACLRestrictionsData {
+ guint32 *out_restrictions;
+ EWebDAVACEPrincipalKind *out_principal_kind;
+ GSList **out_principal_hrefs;
+} ACLRestrictionsData;
+
+static gboolean
+e_webdav_session_acl_restrictions_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ ACLRestrictionsData *ard = user_data;
+
+ g_return_val_if_fail (xpath_ctx != NULL, FALSE);
+ g_return_val_if_fail (ard != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ } else if (status_code == SOUP_STATUS_OK &&
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl-restrictions", xpath_prop_prefix)) {
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl-restrictions/D:grant-only",
xpath_prop_prefix))
+ *ard->out_restrictions |= E_WEBDAV_ACL_RESTRICTION_GRANT_ONLY;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl-restrictions/D:no-invert",
xpath_prop_prefix))
+ *ard->out_restrictions |= E_WEBDAV_ACL_RESTRICTION_NO_INVERT;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl-restrictions/D:deny-before-grant",
xpath_prop_prefix))
+ *ard->out_restrictions |= E_WEBDAV_ACL_RESTRICTION_DENY_BEFORE_GRANT;
+
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:acl-restrictions/D:required-principal",
xpath_prop_prefix)) {
+ gchar *prefix;
+
+ *ard->out_restrictions |= E_WEBDAV_ACL_RESTRICTION_REQUIRED_PRINCIPAL;
+
+ prefix = g_strdup_printf ("%s/D:acl-restrictions/D:required-principal",
xpath_prop_prefix);
+ *ard->out_principal_kind = e_webdav_session_extract_acl_principal (xpath_ctx, prefix,
NULL, ard->out_principal_hrefs);
+ g_free (prefix);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_get_acl_restrictions_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @out_restrictions: (out): return location for bit-or of #EWebDAVACLRestrictions
+ * @out_principal_kind: (out): return location for principal kind
+ * @out_principal_hrefs: (out) (transfer full) (element-type utf8): return location for a #GSList of
principal href-s
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets Access Control List (ACL) restrictions for the @uri, or, in case it's %NULL,
+ * for the URI defined in associated #ESource. The @out_principal_kind is valid only
+ * if the @out_restrictions contains #E_WEBDAV_ACL_RESTRICTION_REQUIRED_PRINCIPAL.
+ * The @out_principal_hrefs is valid only if the @out_principal_kind is valid and when
+ * it is #E_WEBDAV_ACE_PRINCIPAL_HREF.
+ *
+ * Free the returned @out_principal_hrefs with
+ * g_slist_free_full (entries, g_free);
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_get_acl_restrictions_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ guint32 *out_restrictions,
+ EWebDAVACEPrincipalKind *out_principal_kind,
+ GSList **out_principal_hrefs,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ACLRestrictionsData ard;
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (out_restrictions != NULL, FALSE);
+ g_return_val_if_fail (out_principal_kind != NULL, FALSE);
+ g_return_val_if_fail (out_principal_hrefs != NULL, FALSE);
+
+ *out_restrictions = E_WEBDAV_ACL_RESTRICTION_NONE;
+ *out_principal_kind = E_WEBDAV_ACE_PRINCIPAL_UNKNOWN;
+ *out_principal_hrefs = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "acl-restrictions");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ ard.out_restrictions = out_restrictions;
+ ard.out_principal_kind = out_principal_kind;
+ ard.out_principal_hrefs = out_principal_hrefs;
+
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_acl_restrictions_cb, &ard, cancellable, error);
+
+ g_object_unref (xml);
+
+ return success;
+}
+
+static gboolean
+e_webdav_session_principal_collection_set_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ GSList **out_principal_hrefs = user_data;
+
+ g_return_val_if_fail (xpath_ctx != NULL, FALSE);
+ g_return_val_if_fail (out_principal_hrefs != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ } else if (status_code == SOUP_STATUS_OK &&
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:principal-collection-set", xpath_prop_prefix)) {
+ xmlXPathObjectPtr xpath_obj;
+
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/D:principal-collection-set/D:href",
xpath_prop_prefix);
+
+ if (xpath_obj) {
+ gint ii, length;
+
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
+
+ for (ii = 0; ii < length; ii++) {
+ gchar *href;
+
+ href = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/D:principal-collection-set/D:href[%d]", xpath_prop_prefix, ii + 1);
+ if (href)
+ *out_principal_hrefs = g_slist_prepend (*out_principal_hrefs, href);
+ }
+
+ xmlXPathFreeObject (xpath_obj);
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_get_principal_collection_set_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @out_principal_hrefs: (out) (transfer full) (element-type utf8): return location for a #GSList of
principal href-s
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets list of principal collection href for the @uri, or, in case it's %NULL,
+ * for the URI defined in associated #ESource. The @out_principal_hrefs are root
+ * collections that contain the principals that are available on the server that
+ * implements this resource.
+ *
+ * Free the returned @out_principal_hrefs with
+ * g_slist_free_full (entries, g_free);
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_get_principal_collection_set_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_principal_hrefs, /* gchar * */
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (out_principal_hrefs != NULL, FALSE);
+
+ *out_principal_hrefs = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "principal-collection-set");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_principal_collection_set_cb, out_principal_hrefs, cancellable, error);
+
+ g_object_unref (xml);
+
+ if (success)
+ *out_principal_hrefs = g_slist_reverse (*out_principal_hrefs);
+
+ return success;
+}
+
+/**
+ * e_webdav_session_set_acl_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @entries: (element-type EWebDAVAccessControlEntry): entries to write
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Changes Access Control List (ACL) for the @uri, or, in case it's %NULL,
+ * for the URI defined in associated #ESource.
+ *
+ * Make sure that the @entries satisfy ACL restrictions, as returned
+ * by e_webdav_session_get_acl_restrictions_sync(). The order in the @entries
+ * is preserved. It cannot contain any %E_WEBDAV_ACE_FLAG_PROTECTED,
+ * nor @E_WEBDAV_ACE_FLAG_INHERITED, items.
+ *
+ * Use e_webdav_session_get_acl_sync() to read currently known ACL entries,
+ * remove from the list those protected and inherited, and then modify
+ * the rest with the required changed.
+ *
+ * Note this function doesn't support general %E_WEBDAV_ACE_PRINCIPAL_PROPERTY and
+ * returns %G_IO_ERROR_NOT_SUPPORTED error when any such is tried to be written.
+ *
+ * In case the returned entries contain any %E_WEBDAV_ACE_PRINCIPAL_PROPERTY,
+ * or there's a need to write such Access Control Entry, then do not use
+ * e_webdav_session_get_acl_sync(), neither e_webdav_session_set_acl_sync(),
+ * and write more generic implementation.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_set_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const GSList *entries,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ GSList *link, *plink;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (entries != NULL, FALSE);
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "acl");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ for (link = (GSList *) entries; link; link = g_slist_next (link)) {
+ EWebDAVAccessControlEntry *ace = link->data;
+
+ if (!ace) {
+ g_warn_if_fail (ace != NULL);
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ if ((ace->flags & E_WEBDAV_ACE_FLAG_PROTECTED) != 0 ||
+ (ace->flags & E_WEBDAV_ACE_FLAG_INHERITED) != 0) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Cannot store protected nor inherited Access Control Entry."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ if (ace->principal_kind == E_WEBDAV_ACE_PRINCIPAL_UNKNOWN) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Provided invalid principal kind for Access Control Entry."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ if (ace->principal_kind == E_WEBDAV_ACE_PRINCIPAL_PROPERTY) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ _("Cannot store property-based Access Control Entry."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ if ((ace->flags & (E_WEBDAV_ACE_FLAG_GRANT | E_WEBDAV_ACE_FLAG_DENY)) == 0) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Access Control Entry can be only to Grant or Deny, but not None."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ if ((ace->flags & E_WEBDAV_ACE_FLAG_GRANT) != 0 &&
+ (ace->flags & E_WEBDAV_ACE_FLAG_DENY) != 0) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Access Control Entry can be only to Grant or Deny, but not both."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ e_xml_document_start_element (xml, NULL, "ace");
+
+ if ((ace->flags & E_WEBDAV_ACE_FLAG_INVERT) != 0)
+ e_xml_document_start_element (xml, NULL, "invert");
+
+ e_xml_document_start_element (xml, NULL, "principal");
+ switch (ace->principal_kind) {
+ case E_WEBDAV_ACE_PRINCIPAL_UNKNOWN:
+ g_warn_if_reached ();
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_HREF:
+ e_xml_document_start_text_element (xml, NULL, "href");
+ e_xml_document_write_string (xml, ace->principal_href);
+ e_xml_document_end_element (xml);
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_ALL:
+ e_xml_document_start_element (xml, NULL, "all");
+ e_xml_document_end_element (xml);
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_AUTHENTICATED:
+ e_xml_document_start_element (xml, NULL, "authenticated");
+ e_xml_document_end_element (xml);
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_UNAUTHENTICATED:
+ e_xml_document_start_element (xml, NULL, "unauthenticated");
+ e_xml_document_end_element (xml);
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_PROPERTY:
+ g_warn_if_reached ();
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_SELF:
+ e_xml_document_start_element (xml, NULL, "self");
+ e_xml_document_end_element (xml);
+ break;
+ case E_WEBDAV_ACE_PRINCIPAL_OWNER:
+ e_xml_document_start_element (xml, NULL, "property");
+ e_xml_document_start_element (xml, NULL, "owner");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml);
+ break;
+
+ }
+ e_xml_document_end_element (xml); /* principal */
+
+ if ((ace->flags & E_WEBDAV_ACE_FLAG_INVERT) != 0)
+ e_xml_document_end_element (xml); /* invert */
+
+ if ((ace->flags & E_WEBDAV_ACE_FLAG_GRANT) != 0)
+ e_xml_document_start_element (xml, NULL, "grant");
+ else if ((ace->flags & E_WEBDAV_ACE_FLAG_DENY) != 0)
+ e_xml_document_start_element (xml, NULL, "deny");
+ else
+ g_warn_if_reached ();
+
+ for (plink = ace->privileges; plink; plink = g_slist_next (plink)) {
+ EWebDAVPrivilege *privilege = plink->data;
+
+ if (!privilege) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ _("Access Control Entry privilege cannot be NULL."));
+ g_object_unref (xml);
+ return FALSE;
+ }
+
+ e_xml_document_start_element (xml, NULL, "privilege");
+ e_xml_document_start_element (xml, privilege->ns_uri, privilege->name);
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* privilege */
+ }
+
+ e_xml_document_end_element (xml); /* grant or deny */
+
+ e_xml_document_end_element (xml); /* ace */
+ }
+
+ success = e_webdav_session_acl_sync (webdav, uri, xml, cancellable, error);
+
+ g_object_unref (xml);
+
+ return success;
+}
+
+static gboolean
+e_webdav_session_principal_property_search_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
+{
+ GSList **out_principals = user_data;
+
+ g_return_val_if_fail (out_principals != NULL, FALSE);
+
+ if (!xpath_prop_prefix) {
+ } else if (status_code == SOUP_STATUS_OK) {
+ EWebDAVResource *resource;
+ gchar *display_name;
+
+ display_name = e_webdav_session_extract_nonempty (xpath_ctx, xpath_prop_prefix,
"D:displayname", NULL);
+
+ resource = e_webdav_resource_new (
+ E_WEBDAV_RESOURCE_KIND_PRINCIPAL,
+ 0, /* supports */
+ href,
+ NULL, /* etag */
+ NULL, /* display_name */
+ NULL, /* content_type */
+ 0, /* content_length */
+ 0, /* creation_date */
+ 0, /* last_modified */
+ NULL, /* description */
+ NULL); /* color */
+ resource->display_name = display_name;
+
+ *out_principals = g_slist_prepend (*out_principals, resource);
+ }
+
+ return TRUE;
+}
+
+/**
+ * e_webdav_session_principal_property_search_sync:
+ * @webdav: an #EWebDAVSession
+ * @uri: (nullable): URI to issue the request for, or %NULL to read from #ESource
+ * @apply_to_principal_collection_set: whether to apply to principal-collection-set
+ * @match_displayname: a string to match DAV:displayname with
+ * @out_principals: (out) (transfer full) (element-type EWebDAVResource): return location for matching
principals
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Issues a DAV:principal-property-search for the @uri, or, in case it's %NULL,
+ * for the URI defined in associated #ESource. The DAV:principal-property-search
+ * performs a search for all principals whose properties contain character data
+ * that matches the search criteria @match_displayname.
+ *
+ * By default, the function searches all members (at any depth) of the collection
+ * identified by the @uri. If @apply_to_principal_collection_set is set to %TRUE,
+ * the search is applied instead to each collection returned by
+ * e_webdav_session_get_principal_collection_set_sync() for the @uri.
+ *
+ * The @out_principals is a #GSList of #EWebDAVResource, where the kind
+ * is set to %E_WEBDAV_RESOURCE_KIND_PRINCIPAL and only href with displayname
+ * are filled. All other members of #EWebDAVResource are not set.
+ *
+ * Free the returned @out_principals with
+ * g_slist_free_full (principals, e_webdav_resource_free);
+ * when no longer needed.
+ *
+ * Returns: Whether succeeded. Note it can report success also when no matching
+ * principal had been found.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_webdav_session_principal_property_search_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ gboolean apply_to_principal_collection_set,
+ const gchar *match_displayname,
+ GSList **out_principals,
+ GCancellable *cancellable,
+ GError **error)
+{
+ EXmlDocument *xml;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (match_displayname != NULL, FALSE);
+ g_return_val_if_fail (out_principals != NULL, FALSE);
+
+ *out_principals = NULL;
+
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "principal-property-search");
+ g_return_val_if_fail (xml != NULL, FALSE);
+
+ if (apply_to_principal_collection_set) {
+ e_xml_document_start_element (xml, NULL, "apply-to-principal-collection-set");
+ e_xml_document_end_element (xml);
+ }
+
+ e_xml_document_start_element (xml, NULL, "property-search");
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "displayname");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+ e_xml_document_start_text_element (xml, NULL, "match");
+ e_xml_document_write_string (xml, match_displayname);
+ e_xml_document_end_element (xml); /* match */
+ e_xml_document_end_element (xml); /* property-search */
+
+ e_xml_document_start_element (xml, NULL, "prop");
+ e_xml_document_start_element (xml, NULL, "displayname");
+ e_xml_document_end_element (xml);
+ e_xml_document_end_element (xml); /* prop */
+
+ success = e_webdav_session_report_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_session_principal_property_search_cb, out_principals, NULL, NULL, cancellable,
error);
+
+ g_object_unref (xml);
+
+ if (success)
+ *out_principals = g_slist_reverse (*out_principals);
+
+ return success;
+}
+
/**
* e_webdav_session_util_maybe_dequote:
* @text: (inout): text to dequote
@@ -3368,3 +4843,34 @@ e_webdav_session_util_maybe_dequote (gchar *text)
return text;
}
+
+static gboolean
+e_webdav_session_free_in_traverse_cb (GNode *node,
+ gpointer user_data)
+{
+ if (node) {
+ e_webdav_privilege_free (node->data);
+ node->data = NULL;
+ }
+
+ return FALSE;
+}
+
+/**
+ * e_webdav_session_util_free_privileges:
+ * @privileges: (nullable): a tree of #EWebDAVPrivilege structures
+ *
+ * Frees @privileges returned by e_webdav_session_get_supported_privilege_set_sync().
+ * The function does nothing, if @privileges is %NULL.
+ *
+ * Since: 3.26
+ **/
+void
+e_webdav_session_util_free_privileges (GNode *privileges)
+{
+ if (!privileges)
+ return;
+
+ g_node_traverse (privileges, G_PRE_ORDER, G_TRAVERSE_ALL, -1, e_webdav_session_free_in_traverse_cb,
NULL);
+ g_node_destroy (privileges);
+}
diff --git a/src/libedataserver/e-webdav-session.h b/src/libedataserver/e-webdav-session.h
index 19c9266..abbec06 100644
--- a/src/libedataserver/e-webdav-session.h
+++ b/src/libedataserver/e-webdav-session.h
@@ -231,6 +231,99 @@ typedef enum {
#define E_WEBDAV_COLLATION_UNICODE_CASEMAP_SUFFIX "unicode-casemap"
#define E_WEBDAV_COLLATION_UNICODE_CASEMAP "i;" E_WEBDAV_COLLATION_UNICODE_CASEMAP_SUFFIX
+typedef enum {
+ E_WEBDAV_PRIVILEGE_KIND_UNKNOWN = 0,
+ E_WEBDAV_PRIVILEGE_KIND_ABSTRACT,
+ E_WEBDAV_PRIVILEGE_KIND_AGGREGATE,
+ E_WEBDAV_PRIVILEGE_KIND_COMMON
+} EWebDAVPrivilegeKind;
+
+typedef enum {
+ E_WEBDAV_PRIVILEGE_HINT_UNKNOWN = 0,
+ E_WEBDAV_PRIVILEGE_HINT_READ,
+ E_WEBDAV_PRIVILEGE_HINT_WRITE,
+ E_WEBDAV_PRIVILEGE_HINT_WRITE_PROPERTIES,
+ E_WEBDAV_PRIVILEGE_HINT_WRITE_CONTENT,
+ E_WEBDAV_PRIVILEGE_HINT_UNLOCK,
+ E_WEBDAV_PRIVILEGE_HINT_READ_ACL,
+ E_WEBDAV_PRIVILEGE_HINT_WRITE_ACL,
+ E_WEBDAV_PRIVILEGE_HINT_READ_CURRENT_USER_PRIVILEGE_SET,
+ E_WEBDAV_PRIVILEGE_HINT_BIND,
+ E_WEBDAV_PRIVILEGE_HINT_UNBIND,
+ E_WEBDAV_PRIVILEGE_HINT_ALL,
+ E_WEBDAV_PRIVILEGE_HINT_CALDAV_READ_FREE_BUSY
+} EWebDAVPrivilegeHint;
+
+typedef struct _EWebDAVPrivilege {
+ gchar *ns_uri;
+ gchar *name;
+ gchar *description;
+ EWebDAVPrivilegeKind kind;
+ EWebDAVPrivilegeHint hint;
+} EWebDAVPrivilege;
+
+GType e_webdav_privilege_get_type (void) G_GNUC_CONST;
+EWebDAVPrivilege *
+ e_webdav_privilege_new (const gchar *ns_uri,
+ const gchar *name,
+ const gchar *description,
+ EWebDAVPrivilegeKind kind,
+ EWebDAVPrivilegeHint hint);
+EWebDAVPrivilege *
+ e_webdav_privilege_copy (const EWebDAVPrivilege *src);
+void e_webdav_privilege_free (gpointer ptr); /* EWebDAVPrivilege * */
+
+typedef enum {
+ E_WEBDAV_ACE_PRINCIPAL_UNKNOWN = 0,
+ E_WEBDAV_ACE_PRINCIPAL_HREF,
+ E_WEBDAV_ACE_PRINCIPAL_ALL,
+ E_WEBDAV_ACE_PRINCIPAL_AUTHENTICATED,
+ E_WEBDAV_ACE_PRINCIPAL_UNAUTHENTICATED,
+ E_WEBDAV_ACE_PRINCIPAL_PROPERTY,
+ E_WEBDAV_ACE_PRINCIPAL_SELF,
+ E_WEBDAV_ACE_PRINCIPAL_OWNER /* special-case, 'property' with only 'DAV:owner' child */
+} EWebDAVACEPrincipalKind;
+
+typedef enum {
+ E_WEBDAV_ACE_FLAG_UNKNOWN = 0,
+ E_WEBDAV_ACE_FLAG_GRANT = 1 << 0,
+ E_WEBDAV_ACE_FLAG_DENY = 1 << 1,
+ E_WEBDAV_ACE_FLAG_INVERT = 1 << 2,
+ E_WEBDAV_ACE_FLAG_PROTECTED = 1 << 3,
+ E_WEBDAV_ACE_FLAG_INHERITED = 1 << 4
+} EWebDAVACEFlag;
+
+typedef struct _EWebDAVAccessControlEntry {
+ EWebDAVACEPrincipalKind principal_kind;
+ gchar *principal_href; /* valid onyl if principal_kind is E_WEBDAV_ACE_PRINCIPAL_HREF */
+ guint32 flags; /* bit-or of EWebDAVACEFlag */
+ gchar *inherited_href; /* valid only if flags contain E_WEBDAV_ACE_INHERITED */
+ GSList *privileges; /* EWebDAVPrivilege * */
+} EWebDAVAccessControlEntry;
+
+GType e_webdav_access_control_entry_get_type (void) G_GNUC_CONST;
+EWebDAVAccessControlEntry *
+ e_webdav_access_control_entry_new (EWebDAVACEPrincipalKind principal_kind,
+ const gchar *principal_href,
+ guint32 flags, /* bit-or of EWebDAVACEFlag */
+ const gchar *inherited_href);
+EWebDAVAccessControlEntry *
+ e_webdav_access_control_entry_copy (const EWebDAVAccessControlEntry *src);
+void e_webdav_access_control_entry_free (gpointer ptr); /* EWebDAVAccessControlEntry * */
+void e_webdav_access_control_entry_append_privilege
+ (EWebDAVAccessControlEntry *ace,
+ EWebDAVPrivilege *privilege);
+GSList * e_webdav_access_control_entry_get_privileges
+ (EWebDAVAccessControlEntry *ace); /* EWebDAVPrivilege
* */
+
+typedef enum {
+ E_WEBDAV_ACL_RESTRICTION_NONE = 0,
+ E_WEBDAV_ACL_RESTRICTION_GRANT_ONLY = 1 << 0,
+ E_WEBDAV_ACL_RESTRICTION_NO_INVERT = 1 << 1,
+ E_WEBDAV_ACL_RESTRICTION_DENY_BEFORE_GRANT = 1 << 2,
+ E_WEBDAV_ACL_RESTRICTION_REQUIRED_PRINCIPAL = 1 << 3
+} EWebDAVACLRestrictions;
+
/**
* EWebDAVSession:
*
@@ -436,7 +529,57 @@ gboolean e_webdav_session_lock_resource_sync (EWebDAVSession *webdav,
gchar **out_lock_token,
GCancellable *cancellable,
GError **error);
+gboolean e_webdav_session_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const EXmlDocument *xml,
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_get_supported_privilege_set_sync
+ (EWebDAVSession *webdav,
+ const gchar *uri,
+ GNode **out_privileges, /* EWebDAVPrivilege * */
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_get_current_user_privilege_set_sync
+ (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_privileges, /* EWebDAVPrivilege * */
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_get_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_entries, /* EWebDAVAccessControlEntry *
*/
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_get_acl_restrictions_sync
+ (EWebDAVSession *webdav,
+ const gchar *uri,
+ guint32 *out_restrictions, /* bit-or of
EWebDAVACLRestrictions */
+ EWebDAVACEPrincipalKind *out_principal_kind,
+ GSList **out_principal_hrefs, /* gchar * */
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_get_principal_collection_set_sync
+ (EWebDAVSession *webdav,
+ const gchar *uri,
+ GSList **out_principal_hrefs, /* gchar * */
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_set_acl_sync (EWebDAVSession *webdav,
+ const gchar *uri,
+ const GSList *entries, /* EWebDAVAccessControlEntry
* */
+ GCancellable *cancellable,
+ GError **error);
+gboolean e_webdav_session_principal_property_search_sync
+ (EWebDAVSession *webdav,
+ const gchar *uri,
+ gboolean apply_to_principal_collection_set,
+ const gchar *match_displayname,
+ GSList **out_principals, /* EWebDAVResource * */
+ GCancellable *cancellable,
+ GError **error);
gchar * e_webdav_session_util_maybe_dequote (gchar *text);
+void e_webdav_session_util_free_privileges (GNode *privileges); /* EWebDAVPrivilege * */
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]