[evolution-data-server/gnome-42] I#386 - e-webdav-discover: Fails to find Radicale calendars within collection account



commit 0a2e5eb786921407e8d1b61d88f9441b63e0194c
Author: Milan Crha <mcrha redhat com>
Date:   Mon Apr 25 15:51:02 2022 +0200

    I#386 - e-webdav-discover: Fails to find Radicale calendars within collection account
    
    Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/386

 src/libedataserver/e-webdav-discover.c | 70 +++++++++++++++++++++++++------
 src/libedataserver/e-webdav-session.c  | 77 ++++++++++++++++++----------------
 2 files changed, 98 insertions(+), 49 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-discover.c b/src/libedataserver/e-webdav-discover.c
index 79980200b..a824cdf2c 100644
--- a/src/libedataserver/e-webdav-discover.c
+++ b/src/libedataserver/e-webdav-discover.c
@@ -45,15 +45,18 @@ G_DEFINE_BOXED_TYPE (EWebDAVDiscoveredSource, e_webdav_discovered_source, e_webd
 
 static gboolean
 e_webdav_discovery_already_discovered (const gchar *href,
-                                      const GSList *discovered_sources)
+                                      const GSList *discovered_sources,
+                                      guint32 href_supports)
 {
        GSList *link;
 
        for (link = (GSList *) discovered_sources; link; link = g_slist_next (link)) {
                EWebDAVDiscoveredSource *discovered = link->data;
 
-               if (discovered && g_strcmp0 (href, discovered->href) == 0)
+               if (discovered && g_strcmp0 (href, discovered->href) == 0) {
+                       discovered->supports |= href_supports;
                        return TRUE;
+               }
        }
 
        return FALSE;
@@ -82,7 +85,8 @@ e_webdav_discover_split_resources (WebDAVDiscoverData *wdd,
                                continue;
 
                        if (e_webdav_discovery_already_discovered (resource->href,
-                               resource->kind == E_WEBDAV_RESOURCE_KIND_ADDRESSBOOK ? wdd->addressbooks : 
wdd->calendars))
+                               resource->kind == E_WEBDAV_RESOURCE_KIND_ADDRESSBOOK ? wdd->addressbooks : 
wdd->calendars,
+                               resource->supports))
                                continue;
 
                        discovered = g_slice_new0 (EWebDAVDiscoveredSource);
@@ -105,6 +109,45 @@ e_webdav_discover_split_resources (WebDAVDiscoverData *wdd,
        }
 }
 
+typedef enum {
+       COVERED_LOOKUP          = 1 << 0,
+       COVERED_ADDRESSBOOK     = 1 << 1,
+       COVERED_CALENDAR        = 1 << 2
+} ECoveredMark;
+
+static void
+e_webdav_discover_mark_covered (GHashTable *covered_hrefs,
+                               const gchar *href,
+                               ECoveredMark mark)
+{
+       gint value;
+
+       if (!covered_hrefs || !href || !*href)
+               return;
+
+       value = GPOINTER_TO_INT (g_hash_table_lookup (covered_hrefs, href));
+
+       if ((value & mark) != mark) {
+               value |= mark;
+               g_hash_table_insert (covered_hrefs, g_strdup (href), GINT_TO_POINTER (value));
+       }
+}
+
+static gboolean
+e_webdav_discover_is_covered (GHashTable *covered_hrefs,
+                             const gchar *href,
+                             ECoveredMark mark)
+{
+       gint value;
+
+       if (!covered_hrefs || !href || !*href)
+               return FALSE;
+
+       value = GPOINTER_TO_INT (g_hash_table_lookup (covered_hrefs, href));
+
+       return (value & mark) == mark;
+}
+
 static gboolean
 e_webdav_discover_propfind_uri_sync (EWebDAVSession *webdav,
                                     WebDAVDiscoverData *wdd,
@@ -145,7 +188,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
 
                        full_href = e_webdav_session_ensure_full_uri (webdav, request_uri, (const gchar *) 
home_set_href);
 
-                       if (full_href && *full_href && GPOINTER_TO_INT (g_hash_table_contains 
(wdd->covered_hrefs, full_href)) != 2 &&
+                       if (full_href && *full_href && !e_webdav_discover_is_covered (wdd->covered_hrefs, 
full_href, COVERED_ADDRESSBOOK) &&
                            e_webdav_session_list_sync (webdav, full_href, E_WEBDAV_DEPTH_THIS_AND_CHILDREN,
                                E_WEBDAV_LIST_ONLY_ADDRESSBOOK | E_WEBDAV_LIST_ALL,
                                &resources, wdd->cancellable, &local_error)) {
@@ -154,7 +197,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
                        }
 
                        if (full_href && *full_href)
-                               g_hash_table_insert (wdd->covered_hrefs, g_strdup (full_href), 
GINT_TO_POINTER (2));
+                               e_webdav_discover_mark_covered (wdd->covered_hrefs, full_href, 
COVERED_ADDRESSBOOK);
 
                        if (local_error && wdd->error && !*wdd->error)
                                g_propagate_error (wdd->error, local_error);
@@ -181,7 +224,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
 
                        full_href = e_webdav_session_ensure_full_uri (webdav, request_uri, (const gchar *) 
home_set_href);
 
-                       if (full_href && *full_href && GPOINTER_TO_INT (g_hash_table_contains 
(wdd->covered_hrefs, full_href)) != 2 &&
+                       if (full_href && *full_href && !e_webdav_discover_is_covered (wdd->covered_hrefs, 
full_href, COVERED_CALENDAR) &&
                            e_webdav_session_list_sync (webdav, full_href, E_WEBDAV_DEPTH_THIS_AND_CHILDREN,
                                E_WEBDAV_LIST_ONLY_CALENDAR | E_WEBDAV_LIST_ALL,
                                &resources, wdd->cancellable, &local_error)) {
@@ -190,7 +233,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
                        }
 
                        if (full_href && *full_href)
-                               g_hash_table_insert (wdd->covered_hrefs, g_strdup (full_href), 
GINT_TO_POINTER (2));
+                               e_webdav_discover_mark_covered (wdd->covered_hrefs, full_href, 
COVERED_CALENDAR);
 
                        if (local_error && wdd->error && !*wdd->error)
                                g_propagate_error (wdd->error, local_error);
@@ -262,10 +305,11 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
        is_addressbook = e_xml_find_child (node, E_WEBDAV_NS_CARDDAV, "addressbook") != NULL;
 
        if (is_calendar || is_addressbook) {
+               gint covered_mark = (is_addressbook ? COVERED_ADDRESSBOOK : 0) | (is_calendar ? 
COVERED_CALENDAR : 0);
                GSList *resources = NULL;
                GError *local_error = NULL;
 
-               if (GPOINTER_TO_INT (g_hash_table_contains (wdd->covered_hrefs, href)) != 2 &&
+               if (!e_webdav_discover_is_covered (wdd->covered_hrefs, href, covered_mark) &&
                    !g_cancellable_is_cancelled (wdd->cancellable) &&
                    e_webdav_session_list_sync (webdav, href, E_WEBDAV_DEPTH_THIS,
                        (is_calendar ? E_WEBDAV_LIST_ONLY_CALENDAR : 0) | (is_addressbook ? 
E_WEBDAV_LIST_ONLY_ADDRESSBOOK : 0) | E_WEBDAV_LIST_ALL,
@@ -274,7 +318,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
                        g_slist_free_full (resources, e_webdav_resource_free);
                }
 
-               g_hash_table_insert (wdd->covered_hrefs, g_strdup (href), GINT_TO_POINTER (2));
+               e_webdav_discover_mark_covered (wdd->covered_hrefs, href, covered_mark);
 
                if (local_error && wdd->error && !*wdd->error)
                        g_propagate_error (wdd->error, local_error);
@@ -285,7 +329,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
        if (((wdd->only_supports & (~CUSTOM_SUPPORTS_FLAGS)) == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
            (wdd->only_supports & E_WEBDAV_DISCOVER_SUPPORTS_WEBDAV_NOTES) != 0) &&
            (g_str_has_suffix (href, "/Notes") || g_str_has_suffix (href, "/Notes/")) &&
-           !e_webdav_discovery_already_discovered (href, wdd->calendars) &&
+           !e_webdav_discovery_already_discovered (href, wdd->calendars, 0) &&
            e_xml_find_in_hierarchy (prop_node, E_WEBDAV_NS_DAV, "resourcetype", E_WEBDAV_NS_DAV, 
"collection", NULL, NULL)) {
                GSList *resources = NULL;
 
@@ -299,7 +343,7 @@ e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
 
                g_slist_free_full (resources, e_webdav_resource_free);
 
-               g_hash_table_insert (wdd->covered_hrefs, g_strdup (href), GINT_TO_POINTER (2));
+               e_webdav_discover_mark_covered (wdd->covered_hrefs, href, COVERED_CALENDAR);
        }
 
        return TRUE;
@@ -319,10 +363,10 @@ e_webdav_discover_propfind_uri_sync (EWebDAVSession *webdav,
        g_return_val_if_fail (wdd != NULL, FALSE);
        g_return_val_if_fail (uri && *uri, FALSE);
 
-       if (g_hash_table_contains (wdd->covered_hrefs, uri))
+       if (e_webdav_discover_is_covered (wdd->covered_hrefs, uri, COVERED_LOOKUP))
                return TRUE;
 
-       g_hash_table_insert (wdd->covered_hrefs, g_strdup (uri), GINT_TO_POINTER (1));
+       e_webdav_discover_mark_covered (wdd->covered_hrefs, uri, COVERED_LOOKUP);
 
        xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
        g_return_val_if_fail (xml != NULL, FALSE);
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 57e75f3d1..e9825a24f 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -3459,57 +3459,62 @@ e_webdav_session_extract_kind (xmlNodePtr parent_node)
 }
 
 static guint32
-e_webdav_session_extract_supports (xmlNodePtr prop_node)
+e_webdav_session_extract_supports (xmlNodePtr prop_node,
+                                  EWebDAVResourceKind kind)
 {
-       xmlNodePtr calendar_components;
        guint32 supports = E_WEBDAV_RESOURCE_SUPPORTS_NONE;
 
        g_return_val_if_fail (prop_node != NULL, E_WEBDAV_RESOURCE_SUPPORTS_NONE);
 
-       if (e_xml_find_in_hierarchy (prop_node, E_WEBDAV_NS_DAV, "resourcetype", E_WEBDAV_NS_CARDDAV, 
"addressbook", NULL, NULL))
+       if (kind == E_WEBDAV_RESOURCE_KIND_ADDRESSBOOK &&
+           e_xml_find_in_hierarchy (prop_node, E_WEBDAV_NS_DAV, "resourcetype", E_WEBDAV_NS_CARDDAV, 
"addressbook", NULL, NULL))
                supports = supports | E_WEBDAV_RESOURCE_SUPPORTS_CONTACTS;
 
-       calendar_components = e_xml_find_child (prop_node, E_WEBDAV_NS_CALDAV, 
"supported-calendar-component-set");
+       if (kind == E_WEBDAV_RESOURCE_KIND_CALENDAR) {
+               xmlNodePtr calendar_components;
 
-       if (calendar_components) {
-               xmlNodePtr node;
-               gint found_comps = 0;
+               calendar_components = e_xml_find_child (prop_node, E_WEBDAV_NS_CALDAV, 
"supported-calendar-component-set");
+
+               if (calendar_components) {
+                       xmlNodePtr node;
+                       gint found_comps = 0;
 
-               for (node = calendar_components->children; node; node = xmlNextElementSibling (node)) {
-                       if (e_xml_is_element_name (node, E_WEBDAV_NS_CALDAV, "comp")) {
-                               xmlChar *name;
+                       for (node = calendar_components->children; node; node = xmlNextElementSibling (node)) 
{
+                               if (e_xml_is_element_name (node, E_WEBDAV_NS_CALDAV, "comp")) {
+                                       xmlChar *name;
 
-                               found_comps++;
+                                       found_comps++;
 
-                               name = xmlGetProp (node, (const xmlChar *) "name");
+                                       name = xmlGetProp (node, (const xmlChar *) "name");
 
-                               if (!name)
-                                       continue;
+                                       if (!name)
+                                               continue;
 
-                               if (g_ascii_strcasecmp ((const gchar *) name, "VEVENT") == 0)
-                                       supports |= E_WEBDAV_RESOURCE_SUPPORTS_EVENTS;
-                               else if (g_ascii_strcasecmp ((const gchar *) name, "VJOURNAL") == 0)
-                                       supports |= E_WEBDAV_RESOURCE_SUPPORTS_MEMOS;
-                               else if (g_ascii_strcasecmp ((const gchar *) name, "VTODO") == 0)
-                                       supports |= E_WEBDAV_RESOURCE_SUPPORTS_TASKS;
-                               else if (g_ascii_strcasecmp ((const gchar *) name, "VFREEBUSY") == 0)
-                                       supports |= E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY;
-                               else if (g_ascii_strcasecmp ((const gchar *) name, "VTIMEZONE") == 0)
-                                       supports |= E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE;
+                                       if (g_ascii_strcasecmp ((const gchar *) name, "VEVENT") == 0)
+                                               supports |= E_WEBDAV_RESOURCE_SUPPORTS_EVENTS;
+                                       else if (g_ascii_strcasecmp ((const gchar *) name, "VJOURNAL") == 0)
+                                               supports |= E_WEBDAV_RESOURCE_SUPPORTS_MEMOS;
+                                       else if (g_ascii_strcasecmp ((const gchar *) name, "VTODO") == 0)
+                                               supports |= E_WEBDAV_RESOURCE_SUPPORTS_TASKS;
+                                       else if (g_ascii_strcasecmp ((const gchar *) name, "VFREEBUSY") == 0)
+                                               supports |= E_WEBDAV_RESOURCE_SUPPORTS_FREEBUSY;
+                                       else if (g_ascii_strcasecmp ((const gchar *) name, "VTIMEZONE") == 0)
+                                               supports |= E_WEBDAV_RESOURCE_SUPPORTS_TIMEZONE;
 
-                               xmlFree (name);
+                                       xmlFree (name);
+                               }
                        }
-               }
 
-               if (!found_comps) {
-                       /* If the property is not present, assume all component
-                        * types are supported.  (RFC 4791, Section 5.2.3) */
-                       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 (!found_comps) {
+                               /* If the property is not present, assume all component
+                                * types are supported.  (RFC 4791, Section 5.2.3) */
+                               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;
+                       }
                }
        }
 
@@ -3672,7 +3677,7 @@ e_webdav_session_list_cb (EWebDAVSession *webdav,
                        source_href = e_webdav_session_util_maybe_dequote (g_strdup ((const gchar *) 
x_source_href));
                }
 
-               supports = e_webdav_session_extract_supports (prop_node);
+               supports = e_webdav_session_extract_supports (prop_node, kind);
                etag = e_webdav_session_extract_nonempty (prop_node, E_WEBDAV_NS_DAV, "getetag", 
E_WEBDAV_NS_CALENDARSERVER, "getctag");
                display_name = e_webdav_session_extract_nonempty (prop_node, E_WEBDAV_NS_DAV, "displayname", 
NULL, NULL);
                content_type = e_webdav_session_extract_nonempty (prop_node, E_WEBDAV_NS_DAV, 
"getcontenttype", NULL, NULL);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]