[evolution-data-server/wip/offline-cache] Make EWebDAVDiscover use EWebDAVSession
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] Make EWebDAVDiscover use EWebDAVSession
- Date: Tue, 16 May 2017 12:51:32 +0000 (UTC)
commit d93f5ab215900aaa184105f5e906d6861bd2d51b
Author: Milan Crha <mcrha redhat com>
Date: Tue May 16 14:50:54 2017 +0200
Make EWebDAVDiscover use EWebDAVSession
src/libedataserver/e-webdav-discover.c | 1927 +++++---------------------------
src/libedataserver/e-webdav-session.c | 2 +-
2 files changed, 287 insertions(+), 1642 deletions(-)
---
diff --git a/src/libedataserver/e-webdav-discover.c b/src/libedataserver/e-webdav-discover.c
index b25577a..43eaeff 100644
--- a/src/libedataserver/e-webdav-discover.c
+++ b/src/libedataserver/e-webdav-discover.c
@@ -21,1582 +21,329 @@
#include <libsoup/soup.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-
-#include "e-soup-auth-bearer.h"
-#include "e-soup-ssl-trust.h"
-#include "e-source-authentication.h"
-#include "e-source-credentials-provider-impl-google.h"
#include "e-source-webdav.h"
-#include "e-webdav-discover.h"
-
-#define XC(string) ((xmlChar *) string)
-
-/* Standard Namespaces */
-#define NS_WEBDAV "DAV:"
-#define NS_CALDAV "urn:ietf:params:xml:ns:caldav"
-#define NS_CARDDAV "urn:ietf:params:xml:ns:carddav"
-
-/* Application-Specific Namespaces */
-#define NS_ICAL "http://apple.com/ns/ical/"
+#include "e-webdav-session.h"
+#include "e-xml-utils.h"
-/* Mainly for readability. */
-enum {
- DEPTH_0 = 0,
- DEPTH_1 = 1
-};
+#include "e-webdav-discover.h"
-typedef struct _EWebDAVDiscoverContext {
- ESource *source;
- gchar *url_use_path;
+typedef struct _WebDAVDiscoverData {
+ GHashTable *covered_hrefs;
+ GSList *addressbooks;
+ GSList *calendars;
guint32 only_supports;
- ENamedParameters *credentials;
- gchar *out_certificate_pem;
- GTlsCertificateFlags out_certificate_errors;
- GSList *out_discovered_sources;
- GSList *out_calendar_user_addresses;
-} EWebDAVDiscoverContext;
-
-static EWebDAVDiscoverContext *
-e_webdav_discover_context_new (ESource *source,
- const gchar *url_use_path,
- guint32 only_supports,
- const ENamedParameters *credentials)
-{
- EWebDAVDiscoverContext *context;
-
- context = g_new0 (EWebDAVDiscoverContext, 1);
- context->source = g_object_ref (source);
- context->url_use_path = g_strdup (url_use_path);
- context->only_supports = only_supports;
- context->credentials = e_named_parameters_new_clone (credentials);
- context->out_certificate_pem = NULL;
- context->out_certificate_errors = 0;
- context->out_discovered_sources = NULL;
- context->out_calendar_user_addresses = NULL;
-
- return context;
-}
+ GSList **out_calendar_user_addresses;
+ GCancellable *cancellable;
+ GError **error;
+} WebDAVDiscoverData;
static void
-e_webdav_discover_context_free (gpointer ptr)
-{
- EWebDAVDiscoverContext *context = ptr;
-
- if (!context)
- return;
-
- g_clear_object (&context->source);
- g_free (context->url_use_path);
- e_named_parameters_free (context->credentials);
- g_free (context->out_certificate_pem);
- e_webdav_discover_free_discovered_sources (context->out_discovered_sources);
- g_slist_free_full (context->out_calendar_user_addresses, g_free);
- g_free (context);
-}
-
-static gchar *
-e_webdav_discover_make_href_full_uri (SoupURI *base_uri,
- const gchar *href)
+e_webdav_discover_split_resources (WebDAVDiscoverData *wdd,
+ const GSList *resources)
{
- SoupURI *soup_uri;
- gchar *full_uri;
-
- if (!base_uri || !href)
- return g_strdup (href);
-
- if (strstr (href, "://"))
- return g_strdup (href);
-
- soup_uri = soup_uri_copy (base_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;
-}
-
-static void
-e_webdav_discover_redirect (SoupMessage *message,
- SoupSession *session)
-{
- SoupURI *soup_uri;
- const gchar *location;
-
- if (!SOUP_STATUS_IS_REDIRECTION (message->status_code))
- return;
-
- location = soup_message_headers_get_list (message->response_headers, "Location");
-
- if (location == NULL)
- return;
-
- soup_uri = soup_uri_new_with_base (soup_message_get_uri (message), location);
-
- if (soup_uri == NULL) {
- soup_message_set_status_full (
- message, SOUP_STATUS_MALFORMED,
- _("Invalid Redirect URL"));
- return;
- }
-
- soup_message_set_uri (message, soup_uri);
- soup_session_requeue_message (session, message);
-
- soup_uri_free (soup_uri);
-}
-
-static gconstpointer
-compat_libxml_output_buffer_get_content (xmlOutputBufferPtr buf,
- gsize *out_len)
-{
-#ifdef LIBXML2_NEW_BUFFER
- *out_len = xmlOutputBufferGetSize (buf);
- return xmlOutputBufferGetContent (buf);
-#else
- *out_len = buf->buffer->use;
- return buf->buffer->content;
-#endif
-}
-
-static G_GNUC_NULL_TERMINATED SoupMessage *
-e_webdav_discover_new_propfind (SoupSession *session,
- SoupURI *soup_uri,
- gint depth,
- ...)
-{
- GHashTable *namespaces;
- SoupMessage *message;
- xmlDocPtr doc;
- xmlNodePtr root;
- xmlNodePtr node;
- xmlNsPtr ns;
- xmlOutputBufferPtr output;
- gconstpointer content;
- gsize length;
- gpointer key;
- va_list va;
-
- /* Construct the XML content. */
-
- doc = xmlNewDoc (XC ("1.0"));
- node = xmlNewDocNode (doc, NULL, XC ("propfind"), NULL);
-
- /* Build a hash table of namespace URIs to xmlNs structs. */
- namespaces = g_hash_table_new (NULL, NULL);
-
- ns = xmlNewNs (node, XC (NS_CALDAV), XC ("C"));
- g_hash_table_insert (namespaces, (gpointer) NS_CALDAV, ns);
-
- ns = xmlNewNs (node, XC (NS_CARDDAV), XC ("A"));
- g_hash_table_insert (namespaces, (gpointer) NS_CARDDAV, ns);
-
- ns = xmlNewNs (node, XC (NS_ICAL), XC ("IC"));
- g_hash_table_insert (namespaces, (gpointer) NS_ICAL, ns);
-
- /* Add WebDAV last since we use it below. */
- ns = xmlNewNs (node, XC (NS_WEBDAV), XC ("D"));
- g_hash_table_insert (namespaces, (gpointer) NS_WEBDAV, ns);
-
- xmlSetNs (node, ns);
- xmlDocSetRootElement (doc, node);
-
- node = xmlNewTextChild (node, ns, XC ("prop"), NULL);
-
- va_start (va, depth);
- while ((key = va_arg (va, gpointer)) != NULL) {
- xmlChar *name;
-
- ns = g_hash_table_lookup (namespaces, key);
- name = va_arg (va, xmlChar *);
-
- if (ns != NULL && name != NULL)
- xmlNewTextChild (node, ns, name, NULL);
- else
- g_warn_if_reached ();
- }
- va_end (va);
-
- g_hash_table_destroy (namespaces);
-
- /* Construct the SoupMessage. */
-
- message = soup_message_new_from_uri (SOUP_METHOD_PROPFIND, soup_uri);
-
- soup_message_set_flags (message, SOUP_MESSAGE_NO_REDIRECT);
-
- soup_message_headers_append (
- message->request_headers,
- "User-Agent", "Evolution/" VERSION);
-
- soup_message_headers_append (
- message->request_headers,
- "Connection", "close");
-
- soup_message_headers_append (
- message->request_headers,
- "Depth", (depth == 0) ? "0" : "1");
-
- output = xmlAllocOutputBuffer (NULL);
-
- root = xmlDocGetRootElement (doc);
- xmlNodeDumpOutput (output, doc, root, 0, 1, NULL);
- xmlOutputBufferFlush (output);
-
- content = compat_libxml_output_buffer_get_content (output, &length);
-
- soup_message_set_request (
- message, "application/xml", SOUP_MEMORY_COPY,
- content, length);
-
- xmlOutputBufferClose (output);
- xmlFreeDoc (doc);
-
- soup_message_add_header_handler (
- message, "got-body", "Location",
- G_CALLBACK (e_webdav_discover_redirect), session);
-
- return message;
-}
-
-static xmlXPathObjectPtr
-e_webdav_discover_get_xpath (xmlXPathContextPtr xp_ctx,
- const gchar *path_format,
- ...)
-{
- xmlXPathObjectPtr xp_obj;
- va_list va;
- gchar *path;
-
- va_start (va, path_format);
- path = g_strdup_vprintf (path_format, va);
- va_end (va);
-
- xp_obj = xmlXPathEvalExpression (XC (path), xp_ctx);
-
- g_free (path);
-
- if (xp_obj == NULL)
- return NULL;
-
- if (xp_obj->type != XPATH_NODESET) {
- xmlXPathFreeObject (xp_obj);
- return NULL;
- }
-
- if (xmlXPathNodeSetGetLength (xp_obj->nodesetval) == 0) {
- xmlXPathFreeObject (xp_obj);
- return NULL;
- }
-
- return xp_obj;
-}
-
-static gchar *
-e_webdav_discover_get_xpath_string (xmlXPathContextPtr xp_ctx,
- const gchar *path_format,
- ...)
-{
- xmlXPathObjectPtr xp_obj;
- va_list va;
- gchar *path;
- gchar *expression;
- gchar *string = NULL;
-
- va_start (va, path_format);
- path = g_strdup_vprintf (path_format, va);
- va_end (va);
-
- expression = g_strdup_printf ("string(%s)", path);
- xp_obj = xmlXPathEvalExpression (XC (expression), xp_ctx);
- g_free (expression);
-
- g_free (path);
-
- if (xp_obj == NULL)
- return NULL;
-
- if (xp_obj->type == XPATH_STRING)
- string = g_strdup ((gchar *) xp_obj->stringval);
-
- /* If the string is empty, return NULL. */
- if (string != NULL && *string == '\0') {
- g_free (string);
- string = NULL;
+ const GSList *link;
+
+ g_return_if_fail (wdd != NULL);
+
+ for (link = resources; link; link = g_slist_next (link)) {
+ const EWebDAVResource *resource = link->data;
+
+ if (resource && (
+ resource->kind == E_WEBDAV_RESOURCE_KIND_ADDRESSBOOK ||
+ resource->kind == E_WEBDAV_RESOURCE_KIND_CALENDAR)) {
+ EWebDAVDiscoveredSource *discovered;
+
+ if (resource->kind == E_WEBDAV_RESOURCE_KIND_CALENDAR &&
+ wdd->only_supports != E_WEBDAV_DISCOVER_SUPPORTS_NONE &&
+ (resource->supports & wdd->only_supports) == 0)
+ continue;
+
+ discovered = g_new0 (EWebDAVDiscoveredSource, 1);
+ discovered->href = g_strdup (resource->href);
+ discovered->supports = resource->supports;
+ discovered->display_name = g_strdup (resource->display_name);
+ discovered->description = g_strdup (resource->description);
+ discovered->color = g_strdup (resource->color);
+
+ if (resource->kind == E_WEBDAV_RESOURCE_KIND_ADDRESSBOOK) {
+ wdd->addressbooks = g_slist_prepend (wdd->addressbooks, discovered);
+ } else {
+ wdd->calendars = g_slist_prepend (wdd->calendars, discovered);
+ }
+ }
}
-
- xmlXPathFreeObject (xp_obj);
-
- return string;
}
static gboolean
-e_webdav_discover_setup_bearer_auth (ESource *source,
- const ENamedParameters *credentials,
- ESoupAuthBearer *bearer,
- GCancellable *cancellable,
- GError **error)
-{
- gchar *access_token = NULL;
- gint expires_in_seconds = -1;
- gboolean success = FALSE;
-
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
- g_return_val_if_fail (credentials != NULL, FALSE);
-
- success = e_util_get_source_oauth2_access_token_sync (source, credentials,
- &access_token, &expires_in_seconds, cancellable, error);
-
- if (success)
- e_soup_auth_bearer_set_access_token (bearer, access_token, expires_in_seconds);
-
- g_free (access_token);
-
- return success;
-}
-
-typedef struct _AuthenticateData {
- ESource *source;
- const ENamedParameters *credentials;
-} AuthenticateData;
+e_webdav_discover_propfind_uri_sync (EWebDAVSession *webdav,
+ WebDAVDiscoverData *wdd,
+ const gchar *uri,
+ gboolean only_sets);
-static void
-e_webdav_discover_authenticate_cb (SoupSession *session,
- SoupMessage *msg,
- SoupAuth *auth,
- gboolean retrying,
- gpointer user_data)
+static gboolean
+e_webdav_discover_traverse_propfind_response_cb (EWebDAVSession *webdav,
+ xmlXPathContextPtr xpath_ctx,
+ const gchar *xpath_prop_prefix,
+ const SoupURI *request_uri,
+ const gchar *href,
+ guint status_code,
+ gpointer user_data)
{
- AuthenticateData *auth_data = user_data;
-
- g_return_if_fail (auth_data != NULL);
-
- if (retrying)
- return;
-
- if (E_IS_SOUP_AUTH_BEARER (auth)) {
- GError *local_error = NULL;
-
- e_webdav_discover_setup_bearer_auth (auth_data->source, auth_data->credentials,
- E_SOUP_AUTH_BEARER (auth), NULL, &local_error);
-
- if (local_error != NULL) {
- soup_message_set_status_full (msg, SOUP_STATUS_FORBIDDEN, local_error->message);
-
- g_error_free (local_error);
- }
- } else {
- gchar *auth_user = NULL;
+ WebDAVDiscoverData *wdd = user_data;
- if (e_named_parameters_get (auth_data->credentials, E_SOURCE_CREDENTIAL_USERNAME))
- auth_user = g_strdup (e_named_parameters_get (auth_data->credentials,
E_SOURCE_CREDENTIAL_USERNAME));
-
- if (auth_user && !*auth_user) {
- g_free (auth_user);
- auth_user = NULL;
- }
+ g_return_val_if_fail (wdd != NULL, FALSE);
- if (!auth_user) {
- ESourceAuthentication *auth_extension;
-
- auth_extension = e_source_get_extension (auth_data->source,
E_SOURCE_EXTENSION_AUTHENTICATION);
- auth_user = e_source_authentication_dup_user (auth_extension);
- }
+ if (!xpath_prop_prefix) {
+ e_xml_xpath_context_register_namespaces (xpath_ctx,
+ "C", E_WEBDAV_NS_CALDAV,
+ "A", E_WEBDAV_NS_CARDDAV,
+ NULL);
+ } else if (status_code == SOUP_STATUS_OK) {
+ xmlXPathObjectPtr xpath_obj;
+ gchar *principal_href, *full_href;
- if (!auth_user || !*auth_user || !auth_data->credentials || !e_named_parameters_get
(auth_data->credentials, E_SOURCE_CREDENTIAL_PASSWORD))
- soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
- else
- soup_auth_authenticate (auth, auth_user, e_named_parameters_get
(auth_data->credentials, E_SOURCE_CREDENTIAL_PASSWORD));
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/A:addressbook-home-set", xpath_prop_prefix);
+ if (xpath_obj) {
+ gint ii, length;
- g_free (auth_user);
- }
-}
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
-static gboolean
-e_webdav_discover_check_successful (SoupMessage *message,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GError **error)
-{
- GIOErrorEnum error_code;
+ for (ii = 0; ii < length; ii++) {
+ gchar *home_set_href;
- g_return_val_if_fail (message != NULL, FALSE);
+ full_href = NULL;
- /* Loosely copied from the GVFS DAV backend. */
+ home_set_href = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/A:addressbook-home-set/D:href[%d]", xpath_prop_prefix, ii + 1);
+ if (home_set_href && *home_set_href) {
+ GSList *resources = NULL;
- if (SOUP_STATUS_IS_SUCCESSFUL (message->status_code))
- return TRUE;
+ full_href = e_webdav_session_ensure_full_uri (webdav, request_uri,
home_set_href);
+ if (full_href && *full_href && !g_hash_table_contains
(wdd->covered_hrefs, full_href) &&
+ e_webdav_session_list_sync (webdav, full_href,
E_WEBDAV_DEPTH_THIS_AND_CHILDREN,
+ E_WEBDAV_LIST_SUPPORTS | E_WEBDAV_LIST_DISPLAY_NAME |
E_WEBDAV_LIST_DESCRIPTION | E_WEBDAV_LIST_COLOR,
+ &resources, wdd->cancellable, wdd->error)) {
+ e_webdav_discover_split_resources (wdd, resources);
+ g_slist_free_full (resources, e_webdav_resource_free);
+ }
- switch (message->status_code) {
- case SOUP_STATUS_CANCELLED:
- error_code = G_IO_ERROR_CANCELLED;
- break;
- case SOUP_STATUS_NOT_FOUND:
- error_code = G_IO_ERROR_NOT_FOUND;
- break;
- case SOUP_STATUS_UNAUTHORIZED:
- case SOUP_STATUS_FORBIDDEN:
- g_set_error (
- error, SOUP_HTTP_ERROR, message->status_code,
- _("HTTP Error: %s"), message->reason_phrase);
- return FALSE;
- case SOUP_STATUS_PAYMENT_REQUIRED:
- error_code = G_IO_ERROR_PERMISSION_DENIED;
- break;
- case SOUP_STATUS_REQUEST_TIMEOUT:
- error_code = G_IO_ERROR_TIMED_OUT;
- break;
- case SOUP_STATUS_CANT_RESOLVE:
- error_code = G_IO_ERROR_HOST_NOT_FOUND;
- break;
- case SOUP_STATUS_NOT_IMPLEMENTED:
- error_code = G_IO_ERROR_NOT_SUPPORTED;
- break;
- case SOUP_STATUS_INSUFFICIENT_STORAGE:
- error_code = G_IO_ERROR_NO_SPACE;
- break;
- case SOUP_STATUS_SSL_FAILED:
- if (out_certificate_pem) {
- GTlsCertificate *certificate = NULL;
-
- g_free (*out_certificate_pem);
- *out_certificate_pem = NULL;
-
- g_object_get (G_OBJECT (message), "tls-certificate", &certificate, NULL);
-
- if (certificate) {
- g_object_get (certificate, "certificate-pem", out_certificate_pem,
NULL);
- g_object_unref (certificate);
+ if (full_href && *full_href)
+ g_hash_table_insert (wdd->covered_hrefs, g_strdup
(full_href), GINT_TO_POINTER (1));
}
- }
- if (out_certificate_errors) {
- *out_certificate_errors = 0;
- g_object_get (G_OBJECT (message), "tls-errors", out_certificate_errors, NULL);
+ g_free (home_set_href);
+ g_free (full_href);
}
- g_set_error (
- error, SOUP_HTTP_ERROR, message->status_code,
- _("HTTP Error: %s"), message->reason_phrase);
- return FALSE;
- default:
- error_code = G_IO_ERROR_FAILED;
- break;
- }
-
- g_set_error (
- error, G_IO_ERROR, error_code,
- _("HTTP Error: %s"), message->reason_phrase);
-
- return FALSE;
-}
-
-static xmlDocPtr
-e_webdav_discover_parse_xml (SoupMessage *message,
- const gchar *expected_name,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GError **error)
-{
- xmlDocPtr doc;
- xmlNodePtr root;
-
- if (!e_webdav_discover_check_successful (message, out_certificate_pem, out_certificate_errors, error))
- return NULL;
-
- doc = xmlReadMemory (
- message->response_body->data,
- message->response_body->length,
- "response.xml", NULL,
- XML_PARSE_NONET |
- XML_PARSE_NOWARNING |
- XML_PARSE_NOCDATA |
- XML_PARSE_COMPACT);
-
- if (doc == NULL) {
- g_set_error_literal (
- error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Could not parse response"));
- return NULL;
- }
-
- root = xmlDocGetRootElement (doc);
-
- if (root == NULL || root->children == NULL) {
- g_set_error_literal (
- error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Empty response"));
- xmlFreeDoc (doc);
- return NULL;
- }
-
- if (g_strcmp0 ((gchar *) root->name, expected_name) != 0) {
- g_set_error_literal (
- error, G_IO_ERROR, G_IO_ERROR_FAILED,
- _("Unexpected reply from server"));
- xmlFreeDoc (doc);
- return NULL;
- }
-
- return doc;
-}
-
-static void
-e_webdav_discover_process_user_address_set (xmlXPathContextPtr xp_ctx,
- GSList **out_calendar_user_addresses)
-{
- xmlXPathObjectPtr xp_obj;
- gint ii, length;
-
- if (!out_calendar_user_addresses)
- return;
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/C:calendar-user-address-set");
-
- if (xp_obj == NULL)
- return;
-
- length = xmlXPathNodeSetGetLength (xp_obj->nodesetval);
-
- for (ii = 0; ii < length; ii++) {
- GSList *duplicate;
- const gchar *address;
- gchar *href;
-
- href = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/C:calendar-user-address-set"
- "/D:href[%d]", ii + 1);
-
- if (href == NULL)
- continue;
-
- if (!g_str_has_prefix (href, "mailto:")) {
- g_free (href);
- continue;
- }
-
- /* strlen("mailto:") == 7 */
- address = href + 7;
-
- /* Avoid duplicates. */
- duplicate = g_slist_find_custom (
- *out_calendar_user_addresses,
- address, (GCompareFunc) g_ascii_strcasecmp);
-
- if (duplicate != NULL) {
- g_free (href);
- continue;
+ xmlXPathFreeObject (xpath_obj);
}
- *out_calendar_user_addresses = g_slist_prepend (
- *out_calendar_user_addresses, g_strdup (address));
-
- g_free (href);
- }
-
- xmlXPathFreeObject (xp_obj);
-}
-
-static guint32
-e_webdav_discover_get_supported_component_set (xmlXPathContextPtr xp_ctx,
- gint response_index,
- gint propstat_index)
-{
- xmlXPathObjectPtr xp_obj;
- guint32 set = 0;
- gint ii, length;
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/C:supported-calendar-component-set"
- "/C:comp",
- response_index,
- propstat_index);
-
- /* If the property is not present, assume all component
- * types are supported. (RFC 4791, Section 5.2.3) */
- if (xp_obj == NULL)
- return E_WEBDAV_DISCOVER_SUPPORTS_EVENTS |
- E_WEBDAV_DISCOVER_SUPPORTS_MEMOS |
- E_WEBDAV_DISCOVER_SUPPORTS_TASKS;
-
- length = xmlXPathNodeSetGetLength (xp_obj->nodesetval);
-
- for (ii = 0; ii < length; ii++) {
- gchar *name;
-
- name = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/C:supported-calendar-component-set"
- "/C:comp[%d]"
- "/@name",
- response_index,
- propstat_index,
- ii + 1);
-
- if (name == NULL)
- continue;
-
- if (g_ascii_strcasecmp (name, "VEVENT") == 0)
- set |= E_WEBDAV_DISCOVER_SUPPORTS_EVENTS;
- else if (g_ascii_strcasecmp (name, "VJOURNAL") == 0)
- set |= E_WEBDAV_DISCOVER_SUPPORTS_MEMOS;
- else if (g_ascii_strcasecmp (name, "VTODO") == 0)
- set |= E_WEBDAV_DISCOVER_SUPPORTS_TASKS;
-
- g_free (name);
- }
-
- xmlXPathFreeObject (xp_obj);
-
- return set;
-}
-
-static void
-e_webdav_discover_process_calendar_response_propstat (SoupMessage *message,
- xmlXPathContextPtr xp_ctx,
- gint response_index,
- gint propstat_index,
- GSList **out_discovered_sources)
-{
- xmlXPathObjectPtr xp_obj;
- guint32 comp_set;
- gchar *color_spec;
- gchar *display_name;
- gchar *description;
- gchar *href_encoded;
- gchar *status_line;
- guint status;
- gboolean success;
- EWebDAVDiscoveredSource *discovered_source;
-
- if (!out_discovered_sources)
- return;
-
- status_line = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:status",
- response_index,
- propstat_index);
-
- if (status_line == NULL)
- return;
-
- success = soup_headers_parse_status_line (
- status_line, NULL, &status, NULL);
-
- g_free (status_line);
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/C:calendar-home-set", xpath_prop_prefix);
+ if (xpath_obj) {
+ gint ii, length;
- if (!success || status != SOUP_STATUS_OK)
- return;
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
- comp_set = e_webdav_discover_get_supported_component_set (xp_ctx, response_index, propstat_index);
- if (comp_set == E_WEBDAV_DISCOVER_SUPPORTS_NONE)
- return;
+ for (ii = 0; ii < length; ii++) {
+ gchar *home_set_href, *full_href = NULL;
- href_encoded = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:href",
- response_index);
+ home_set_href = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/C:calendar-home-set/D:href[%d]", xpath_prop_prefix, ii + 1);
+ if (home_set_href && *home_set_href) {
+ GSList *resources = NULL;
- if (href_encoded == NULL)
- return;
-
- /* Make sure the resource is a calendar. */
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/D:resourcetype"
- "/C:calendar",
- response_index,
- propstat_index);
-
- if (xp_obj == NULL) {
- g_free (href_encoded);
- return;
- }
+ full_href = e_webdav_session_ensure_full_uri (webdav, request_uri,
home_set_href);
+ if (full_href && *full_href && !g_hash_table_contains
(wdd->covered_hrefs, full_href) &&
+ e_webdav_session_list_sync (webdav, full_href,
E_WEBDAV_DEPTH_THIS_AND_CHILDREN,
+ E_WEBDAV_LIST_SUPPORTS | E_WEBDAV_LIST_DISPLAY_NAME |
E_WEBDAV_LIST_DESCRIPTION | E_WEBDAV_LIST_COLOR,
+ &resources, wdd->cancellable, wdd->error)) {
+ e_webdav_discover_split_resources (wdd, resources);
+ g_slist_free_full (resources, e_webdav_resource_free);
+ }
- xmlXPathFreeObject (xp_obj);
-
- /* Get the display name or fall back to the href. */
-
- display_name = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/D:displayname",
- response_index,
- propstat_index);
-
- if (display_name == NULL) {
- gchar *href_decoded = soup_uri_decode (href_encoded);
-
- if (href_decoded) {
- gchar *cp;
-
- /* Use the last non-empty path segment. */
- while ((cp = strrchr (href_decoded, '/')) != NULL) {
- if (*(cp + 1) == '\0')
- *cp = '\0';
- else {
- display_name = g_strdup (cp + 1);
- break;
+ if (full_href && *full_href)
+ g_hash_table_insert (wdd->covered_hrefs, g_strdup
(full_href), GINT_TO_POINTER (1));
}
- }
- }
-
- g_free (href_decoded);
- }
-
- description = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/C:calendar-description",
- response_index,
- propstat_index);
-
- /* Get the color specification string. */
-
- color_spec = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/IC:calendar-color",
- response_index,
- propstat_index);
-
- discovered_source = g_new0 (EWebDAVDiscoveredSource, 1);
- discovered_source->href = e_webdav_discover_make_href_full_uri (soup_message_get_uri (message),
href_encoded);
- discovered_source->supports = comp_set;
- discovered_source->display_name = g_strdup (display_name);
- discovered_source->description = g_strdup (description);
- discovered_source->color = g_strdup (color_spec);
-
- *out_discovered_sources = g_slist_prepend (*out_discovered_sources, discovered_source);
-
- g_free (href_encoded);
- g_free (display_name);
- g_free (description);
- g_free (color_spec);
-}
-static void
-e_webdav_discover_traverse_responses (SoupMessage *message,
- xmlXPathContextPtr xp_ctx,
- GSList **out_discovered_sources,
- void (* func) (
- SoupMessage *message,
- xmlXPathContextPtr xp_ctx,
- gint response_index,
- gint propstat_index,
- GSList **out_discovered_sources))
-{
- xmlXPathObjectPtr xp_obj_response;
-
- xp_obj_response = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response");
-
- if (xp_obj_response != NULL) {
- gint response_index, response_length;
+ g_free (home_set_href);
+ g_free (full_href);
+ }
- response_length = xmlXPathNodeSetGetLength (xp_obj_response->nodesetval);
+ xmlXPathFreeObject (xpath_obj);
+ }
- for (response_index = 0; response_index < response_length; response_index++) {
- xmlXPathObjectPtr xp_obj_propstat;
+ xpath_obj = e_xml_xpath_eval (xpath_ctx, "%s/C:calendar-user-address-set", xpath_prop_prefix);
+ if (xpath_obj) {
+ gint ii, length;
- xp_obj_propstat = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat",
- response_index + 1);
+ length = xmlXPathNodeSetGetLength (xpath_obj->nodesetval);
- if (xp_obj_propstat != NULL) {
- gint propstat_index, propstat_length;
+ for (ii = 0; ii < length; ii++) {
+ gchar *address_href;
- propstat_length = xmlXPathNodeSetGetLength (xp_obj_propstat->nodesetval);
+ address_href = e_xml_xpath_eval_as_string (xpath_ctx,
"%s/C:calendar-user-address-set/D:href[%d]", xpath_prop_prefix, ii + 1);
+ if (address_href && g_ascii_strncasecmp (address_href, "mailto:", 7) == 0) {
+ /* Skip the "mailto:" prefix */
+ const gchar *address = address_href + 7;
- for (propstat_index = 0; propstat_index < propstat_length; propstat_index++) {
- func (message, xp_ctx, response_index + 1, propstat_index + 1,
out_discovered_sources);
+ /* Avoid duplicates and empty values */
+ if (*address &&
+ !g_slist_find_custom (*wdd->out_calendar_user_addresses, address,
(GCompareFunc) g_ascii_strcasecmp)) {
+ *wdd->out_calendar_user_addresses = g_slist_prepend (
+ *wdd->out_calendar_user_addresses, g_strdup
(address));
+ }
}
- xmlXPathFreeObject (xp_obj_propstat);
+ g_free (address_href);
}
- }
- xmlXPathFreeObject (xp_obj_response);
- }
-}
-
-static gboolean
-e_webdav_discover_get_calendar_collection_details (SoupSession *session,
- SoupMessage *message,
- const gchar *path_or_uri,
- ESource *source,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GSList **out_discovered_sources,
- GCancellable *cancellable,
- GError **error)
-{
- xmlDocPtr doc;
- xmlXPathContextPtr xp_ctx;
- SoupURI *soup_uri;
- GError *local_error = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return FALSE;
-
- soup_uri = soup_uri_new (path_or_uri);
- if (!soup_uri ||
- !soup_uri_get_scheme (soup_uri) ||
- !soup_uri_get_host (soup_uri) ||
- !soup_uri_get_path (soup_uri) ||
- !*soup_uri_get_scheme (soup_uri) ||
- !*soup_uri_get_host (soup_uri) ||
- !*soup_uri_get_path (soup_uri)) {
- /* it's a path only, not full uri */
- if (soup_uri)
- soup_uri_free (soup_uri);
- soup_uri = soup_uri_copy (soup_message_get_uri (message));
- soup_uri_set_path (soup_uri, path_or_uri);
- }
+ xmlXPathFreeObject (xpath_obj);
+ }
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_1,
- NS_WEBDAV, XC ("displayname"),
- NS_WEBDAV, XC ("resourcetype"),
- NS_CALDAV, XC ("calendar-description"),
- NS_CALDAV, XC ("supported-calendar-component-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NS_ICAL, XC ("calendar-color"),
- NULL);
-
- e_soup_ssl_trust_connect (message, source);
-
- /* This takes ownership of the message. */
- soup_session_send_message (session, message);
-
- if (message->status_code == SOUP_STATUS_BAD_REQUEST) {
- g_clear_object (&message);
-
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_0,
- NS_WEBDAV, XC ("displayname"),
- NS_WEBDAV, XC ("resourcetype"),
- NS_CALDAV, XC ("calendar-description"),
- NS_CALDAV, XC ("supported-calendar-component-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NS_ICAL, XC ("calendar-color"),
- NULL);
+ principal_href = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:current-user-principal/D:href",
xpath_prop_prefix);
+ if (principal_href && *principal_href) {
+ full_href = e_webdav_session_ensure_full_uri (webdav, request_uri, principal_href);
- e_soup_ssl_trust_connect (message, source);
- soup_session_send_message (session, message);
- }
+ if (full_href && *full_href)
+ e_webdav_discover_propfind_uri_sync (webdav, wdd, full_href, TRUE);
- soup_uri_free (soup_uri);
-
- doc = e_webdav_discover_parse_xml (message, "multistatus", out_certificate_pem,
out_certificate_errors, &local_error);
- if (!doc) {
- g_clear_object (&message);
+ g_free (full_href);
+ g_free (principal_href);
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
- g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
- /* Ignore these errors, but still propagate them. */
- g_propagate_error (error, local_error);
return TRUE;
- } else if (local_error) {
- g_propagate_error (error, local_error);
}
- return FALSE;
- }
-
- xp_ctx = xmlXPathNewContext (doc);
- xmlXPathRegisterNs (xp_ctx, XC ("D"), XC (NS_WEBDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("C"), XC (NS_CALDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("A"), XC (NS_CARDDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("IC"), XC (NS_ICAL));
-
- e_webdav_discover_traverse_responses (message, xp_ctx, out_discovered_sources,
- e_webdav_discover_process_calendar_response_propstat);
-
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
-
- g_clear_object (&message);
-
- return TRUE;
-}
-
-static gboolean
-e_webdav_discover_process_calendar_home_set (SoupSession *session,
- SoupMessage *message,
- ESource *source,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GSList **out_discovered_sources,
- GSList **out_calendar_user_addresses,
- GCancellable *cancellable,
- GError **error)
-{
- SoupURI *soup_uri;
- xmlDocPtr doc;
- xmlXPathContextPtr xp_ctx;
- xmlXPathObjectPtr xp_obj;
- gchar *calendar_home_set;
- GError *local_error = NULL;
- gboolean success;
+ g_free (principal_href);
- g_return_val_if_fail (SOUP_IS_SESSION (session), FALSE);
- g_return_val_if_fail (SOUP_IS_MESSAGE (message), FALSE);
- g_return_val_if_fail (out_discovered_sources != NULL, FALSE);
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
+ principal_href = e_xml_xpath_eval_as_string (xpath_ctx, "%s/D:principal-URL/D:href",
xpath_prop_prefix);
+ if (principal_href && *principal_href) {
+ full_href = e_webdav_session_ensure_full_uri (webdav, request_uri, principal_href);
- if (g_cancellable_is_cancelled (cancellable))
- return FALSE;
+ if (full_href && *full_href)
+ e_webdav_discover_propfind_uri_sync (webdav, wdd, full_href, TRUE);
- doc = e_webdav_discover_parse_xml (message, "multistatus", out_certificate_pem,
out_certificate_errors, &local_error);
+ g_free (full_href);
+ g_free (principal_href);
- if (!doc) {
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
- g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
- /* Ignore these errors, but still propagate them. */
- g_propagate_error (error, local_error);
return TRUE;
- } else if (local_error) {
- g_propagate_error (error, local_error);
}
- return FALSE;
- }
+ g_free (principal_href);
- xp_ctx = xmlXPathNewContext (doc);
- xmlXPathRegisterNs (xp_ctx, XC ("D"), XC (NS_WEBDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("C"), XC (NS_CALDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("A"), XC (NS_CARDDAV));
-
- /* Record any "C:calendar-user-address-set" properties. */
- e_webdav_discover_process_user_address_set (xp_ctx, out_calendar_user_addresses);
-
- /* Try to find the calendar home URL using the
- * following properties in order of preference:
- *
- * "C:calendar-home-set"
- * "D:current-user-principal"
- * "D:principal-URL"
- *
- * If the second or third URL preference is used, rerun
- * the PROPFIND method on that URL at Depth=1 in hopes
- * of getting a proper "C:calendar-home-set" property.
- */
-
- /* FIXME There can be multiple "D:href" elements for a
- * "C:calendar-home-set". We're only processing
- * the first one. Need to iterate over them. */
-
- calendar_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/C:calendar-home-set"
- "/D:href");
-
- if (calendar_home_set != NULL)
- goto get_collection_details;
-
- g_free (calendar_home_set);
-
- calendar_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:current-user-principal"
- "/D:href");
-
- if (calendar_home_set != NULL)
- goto retry_propfind;
-
- g_free (calendar_home_set);
-
- calendar_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:principal-URL"
- "/D:href");
-
- if (calendar_home_set != NULL)
- goto retry_propfind;
-
- g_free (calendar_home_set);
- calendar_home_set = NULL;
-
- /* None of the aforementioned properties are present. If the
- * user-supplied CalDAV URL is a calendar resource, use that. */
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:resourcetype"
- "/C:calendar");
-
- if (xp_obj != NULL) {
- soup_uri = soup_message_get_uri (message);
-
- if (soup_uri->path != NULL && *soup_uri->path != '\0') {
- gchar *slash;
-
- soup_uri = soup_uri_copy (soup_uri);
-
- slash = strrchr (soup_uri->path, '/');
- while (slash != NULL && slash != soup_uri->path) {
-
- if (slash[1] != '\0') {
- slash[1] = '\0';
- calendar_home_set =
- g_strdup (soup_uri->path);
- break;
- }
+ if (e_xml_xpath_eval_exists (xpath_ctx, "%s/D:resourcetype/C:calendar", xpath_prop_prefix) ||
+ e_xml_xpath_eval_exists (xpath_ctx, "%s/D:resourcetype/A:addressbook",
xpath_prop_prefix)) {
+ GSList *resources = NULL;
- slash[0] = '\0';
- slash = strrchr (soup_uri->path, '/');
+ if (!g_hash_table_contains (wdd->covered_hrefs, href) &&
+ e_webdav_session_list_sync (webdav, href, E_WEBDAV_DEPTH_THIS,
+ E_WEBDAV_LIST_SUPPORTS | E_WEBDAV_LIST_DISPLAY_NAME |
E_WEBDAV_LIST_DESCRIPTION | E_WEBDAV_LIST_COLOR,
+ &resources, wdd->cancellable, wdd->error)) {
+ e_webdav_discover_split_resources (wdd, resources);
+ g_slist_free_full (resources, e_webdav_resource_free);
}
- soup_uri_free (soup_uri);
+ g_hash_table_insert (wdd->covered_hrefs, g_strdup (href), GINT_TO_POINTER (1));
}
-
- xmlXPathFreeObject (xp_obj);
}
- if (calendar_home_set == NULL || *calendar_home_set == '\0') {
- g_free (calendar_home_set);
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
- return TRUE;
- }
-
- get_collection_details:
-
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
-
- if (!e_webdav_discover_get_calendar_collection_details (
- session, message, calendar_home_set, source,
- out_certificate_pem, out_certificate_errors, out_discovered_sources,
- cancellable, error)) {
- g_free (calendar_home_set);
- return FALSE;
- }
-
- g_free (calendar_home_set);
-
return TRUE;
-
- retry_propfind:
-
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
-
- soup_uri = soup_uri_copy (soup_message_get_uri (message));
- soup_uri_set_path (soup_uri, calendar_home_set);
-
- /* Note that we omit "D:resourcetype", "D:current-user-principal"
- * and "D:principal-URL" in order to short-circuit the recursion. */
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_1,
- NS_CALDAV, XC ("calendar-home-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NULL);
-
- e_soup_ssl_trust_connect (message, source);
-
- /* This takes ownership of the message. */
- soup_session_send_message (session, message);
-
- if (message->status_code == SOUP_STATUS_BAD_REQUEST) {
- g_clear_object (&message);
-
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_0,
- NS_CALDAV, XC ("calendar-home-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NULL);
-
- e_soup_ssl_trust_connect (message, source);
- soup_session_send_message (session, message);
- }
-
- soup_uri_free (soup_uri);
-
- g_free (calendar_home_set);
-
- success = e_webdav_discover_process_calendar_home_set (session, message, source,
- out_certificate_pem, out_certificate_errors, out_discovered_sources,
out_calendar_user_addresses,
- cancellable, error);
-
- g_object_unref (message);
-
- return success;
}
-static void
-e_webdav_discover_process_addressbook_response_propstat (SoupMessage *message,
- xmlXPathContextPtr xp_ctx,
- gint response_index,
- gint propstat_index,
- GSList **out_discovered_sources)
+static gboolean
+e_webdav_discover_propfind_uri_sync (EWebDAVSession *webdav,
+ WebDAVDiscoverData *wdd,
+ const gchar *uri,
+ gboolean only_sets)
{
- xmlXPathObjectPtr xp_obj;
- gchar *display_name;
- gchar *description;
- gchar *href_encoded;
- gchar *status_line;
- guint status;
+ EXmlDocument *xml;
gboolean success;
- EWebDAVDiscoveredSource *discovered_source;
-
- if (!out_discovered_sources)
- return;
-
- status_line = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:status",
- response_index,
- propstat_index);
-
- if (status_line == NULL)
- return;
- success = soup_headers_parse_status_line (
- status_line, NULL, &status, NULL);
+ g_return_val_if_fail (E_IS_WEBDAV_SESSION (webdav), FALSE);
+ g_return_val_if_fail (wdd != NULL, FALSE);
+ g_return_val_if_fail (uri && *uri, FALSE);
- g_free (status_line);
+ if (g_hash_table_contains (wdd->covered_hrefs, uri))
+ return TRUE;
- if (!success || status != SOUP_STATUS_OK)
- return;
+ g_hash_table_insert (wdd->covered_hrefs, g_strdup (uri), GINT_TO_POINTER (1));
- href_encoded = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:href",
- response_index);
+ xml = e_xml_document_new (E_WEBDAV_NS_DAV, "propfind");
+ g_return_val_if_fail (xml != NULL, FALSE);
- if (href_encoded == NULL)
- return;
+ e_xml_document_start_element (xml, E_WEBDAV_NS_DAV, "prop");
- /* Make sure the resource is an addressbook. */
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/D:resourcetype"
- "/A:addressbook",
- response_index,
- propstat_index);
-
- if (xp_obj == NULL) {
- g_free (href_encoded);
- return;
+ if (!only_sets) {
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_DAV, "resourcetype");
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_DAV, "current-user-principal");
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_DAV, "principal-URL");
}
- xmlXPathFreeObject (xp_obj);
-
- /* Get the display name or fall back to the href. */
-
- display_name = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/D:displayname",
- response_index,
- propstat_index);
-
- if (display_name == NULL) {
- gchar *href_decoded = soup_uri_decode (href_encoded);
-
- if (href_decoded) {
- gchar *cp;
-
- /* Use the last non-empty path segment. */
- while ((cp = strrchr (href_decoded, '/')) != NULL) {
- if (*(cp + 1) == '\0')
- *cp = '\0';
- else {
- display_name = g_strdup (cp + 1);
- break;
- }
- }
- }
-
- g_free (href_decoded);
+ if ((wdd->only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
+ (wdd->only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_EVENTS | E_WEBDAV_DISCOVER_SUPPORTS_MEMOS |
E_WEBDAV_DISCOVER_SUPPORTS_TASKS)) != 0)) {
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_CALDAV, "calendar-home-set");
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_CALDAV, "calendar-user-address-set");
}
- description = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response[%d]"
- "/D:propstat[%d]"
- "/D:prop"
- "/A:addressbook-description",
- response_index,
- propstat_index);
-
- discovered_source = g_new0 (EWebDAVDiscoveredSource, 1);
- discovered_source->href = e_webdav_discover_make_href_full_uri (soup_message_get_uri (message),
href_encoded);
- discovered_source->supports = E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS;
- discovered_source->display_name = g_strdup (display_name);
- discovered_source->description = g_strdup (description);
- discovered_source->color = NULL;
-
- *out_discovered_sources = g_slist_prepend (*out_discovered_sources, discovered_source);
-
- g_free (href_encoded);
- g_free (display_name);
- g_free (description);
-}
-
-static gboolean
-e_webdav_discover_get_addressbook_collection_details (SoupSession *session,
- SoupMessage *message,
- const gchar *path_or_uri,
- ESource *source,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GSList **out_discovered_sources,
- GCancellable *cancellable,
- GError **error)
-{
- xmlDocPtr doc;
- xmlXPathContextPtr xp_ctx;
- SoupURI *soup_uri;
- GError *local_error = NULL;
-
- if (g_cancellable_is_cancelled (cancellable))
- return FALSE;
-
- soup_uri = soup_uri_new (path_or_uri);
- if (!soup_uri ||
- !soup_uri_get_scheme (soup_uri) ||
- !soup_uri_get_host (soup_uri) ||
- !soup_uri_get_path (soup_uri) ||
- !*soup_uri_get_scheme (soup_uri) ||
- !*soup_uri_get_host (soup_uri) ||
- !*soup_uri_get_path (soup_uri)) {
- /* it's a path only, not full uri */
- if (soup_uri)
- soup_uri_free (soup_uri);
- soup_uri = soup_uri_copy (soup_message_get_uri (message));
- soup_uri_set_path (soup_uri, path_or_uri);
+ if ((wdd->only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
+ (wdd->only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS)) != 0)) {
+ e_xml_document_add_empty_element (xml, E_WEBDAV_NS_CARDDAV, "addressbook-home-set");
}
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_1,
- NS_WEBDAV, XC ("displayname"),
- NS_WEBDAV, XC ("resourcetype"),
- NS_CARDDAV, XC ("addressbook-description"),
- NULL);
-
- e_soup_ssl_trust_connect (message, source);
+ e_xml_document_end_element (xml); /* prop */
- /* This takes ownership of the message. */
- soup_session_send_message (session, message);
-
- soup_uri_free (soup_uri);
-
- doc = e_webdav_discover_parse_xml (message, "multistatus", out_certificate_pem,
out_certificate_errors, &local_error);
- if (!doc) {
- g_clear_object (&message);
-
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
- g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
- /* Ignore these errors, but still propagate them. */
- g_propagate_error (error, local_error);
- return TRUE;
- } else if (local_error) {
- g_propagate_error (error, local_error);
- }
+ success = e_webdav_session_propfind_sync (webdav, uri, E_WEBDAV_DEPTH_THIS, xml,
+ e_webdav_discover_traverse_propfind_response_cb, wdd, wdd->cancellable, wdd->error);
- return FALSE;
- }
+ g_clear_object (&xml);
- xp_ctx = xmlXPathNewContext (doc);
- xmlXPathRegisterNs (xp_ctx, XC ("D"), XC (NS_WEBDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("C"), XC (NS_CALDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("A"), XC (NS_CARDDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("IC"), XC (NS_ICAL));
+ return success;
+}
- e_webdav_discover_traverse_responses (message, xp_ctx, out_discovered_sources,
- e_webdav_discover_process_addressbook_response_propstat);
+typedef struct _EWebDAVDiscoverContext {
+ ESource *source;
+ gchar *url_use_path;
+ guint32 only_supports;
+ ENamedParameters *credentials;
+ gchar *out_certificate_pem;
+ GTlsCertificateFlags out_certificate_errors;
+ GSList *out_discovered_sources;
+ GSList *out_calendar_user_addresses;
+} EWebDAVDiscoverContext;
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
+static EWebDAVDiscoverContext *
+e_webdav_discover_context_new (ESource *source,
+ const gchar *url_use_path,
+ guint32 only_supports,
+ const ENamedParameters *credentials)
+{
+ EWebDAVDiscoverContext *context;
- g_clear_object (&message);
+ context = g_new0 (EWebDAVDiscoverContext, 1);
+ context->source = g_object_ref (source);
+ context->url_use_path = g_strdup (url_use_path);
+ context->only_supports = only_supports;
+ context->credentials = e_named_parameters_new_clone (credentials);
+ context->out_certificate_pem = NULL;
+ context->out_certificate_errors = 0;
+ context->out_discovered_sources = NULL;
+ context->out_calendar_user_addresses = NULL;
- return TRUE;
+ return context;
}
-static gboolean
-e_webdav_discover_process_addressbook_home_set (SoupSession *session,
- SoupMessage *message,
- ESource *source,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GSList **out_discovered_sources,
- GCancellable *cancellable,
- GError **error)
+static void
+e_webdav_discover_context_free (gpointer ptr)
{
- SoupURI *soup_uri;
- xmlDocPtr doc;
- xmlXPathContextPtr xp_ctx;
- xmlXPathObjectPtr xp_obj;
- gchar *addressbook_home_set;
- GError *local_error = NULL;
- gboolean success;
-
- g_return_val_if_fail (SOUP_IS_SESSION (session), FALSE);
- g_return_val_if_fail (SOUP_IS_MESSAGE (message), FALSE);
- g_return_val_if_fail (out_discovered_sources != NULL, FALSE);
- g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
-
- if (g_cancellable_is_cancelled (cancellable))
- return FALSE;
-
- doc = e_webdav_discover_parse_xml (message, "multistatus", out_certificate_pem,
out_certificate_errors, &local_error);
- if (!doc) {
- if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED) ||
- g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) {
- /* Ignore these errors, but still propagate them. */
- g_propagate_error (error, local_error);
- return TRUE;
- } else if (local_error) {
- g_propagate_error (error, local_error);
- }
-
- return FALSE;
- }
-
- xp_ctx = xmlXPathNewContext (doc);
- xmlXPathRegisterNs (xp_ctx, XC ("D"), XC (NS_WEBDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("C"), XC (NS_CALDAV));
- xmlXPathRegisterNs (xp_ctx, XC ("A"), XC (NS_CARDDAV));
-
- /* Try to find the addressbook home URL using the
- * following properties in order of preference:
- *
- * "A:addressbook-home-set"
- * "D:current-user-principal"
- * "D:principal-URL"
- *
- * If the second or third URL preference is used, rerun
- * the PROPFIND method on that URL at Depth=1 in hopes
- * of getting a proper "A:addressbook-home-set" property.
- */
-
- /* FIXME There can be multiple "D:href" elements for a
- * "A:addressbook-home-set". We're only processing
- * the first one. Need to iterate over them. */
-
- addressbook_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/A:addressbook-home-set"
- "/D:href");
-
- if (addressbook_home_set != NULL)
- goto get_collection_details;
-
- g_free (addressbook_home_set);
-
- addressbook_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:current-user-principal"
- "/D:href");
-
- if (addressbook_home_set != NULL)
- goto retry_propfind;
-
- g_free (addressbook_home_set);
-
- addressbook_home_set = e_webdav_discover_get_xpath_string (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:principal-URL"
- "/D:href");
-
- if (addressbook_home_set != NULL)
- goto retry_propfind;
-
- g_free (addressbook_home_set);
- addressbook_home_set = NULL;
-
- /* None of the aforementioned properties are present. If the
- * user-supplied CardDAV URL is an addressbook resource, use that. */
-
- xp_obj = e_webdav_discover_get_xpath (
- xp_ctx,
- "/D:multistatus"
- "/D:response"
- "/D:propstat"
- "/D:prop"
- "/D:resourcetype"
- "/A:addressbook");
-
- if (xp_obj != NULL) {
- soup_uri = soup_message_get_uri (message);
-
- if (soup_uri->path != NULL && *soup_uri->path != '\0') {
- gchar *slash;
-
- soup_uri = soup_uri_copy (soup_uri);
-
- slash = strrchr (soup_uri->path, '/');
- while (slash != NULL && slash != soup_uri->path) {
-
- if (slash[1] != '\0') {
- slash[1] = '\0';
- addressbook_home_set =
- g_strdup (soup_uri->path);
- break;
- }
-
- slash[0] = '\0';
- slash = strrchr (soup_uri->path, '/');
- }
-
- soup_uri_free (soup_uri);
- }
-
- xmlXPathFreeObject (xp_obj);
- }
-
- if (addressbook_home_set == NULL || *addressbook_home_set == '\0') {
- g_free (addressbook_home_set);
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
- return TRUE;
- }
-
- get_collection_details:
-
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
-
- if (!e_webdav_discover_get_addressbook_collection_details (
- session, message, addressbook_home_set, source,
- out_certificate_pem, out_certificate_errors, out_discovered_sources,
- cancellable, error)) {
- g_free (addressbook_home_set);
- return FALSE;
- }
-
- g_free (addressbook_home_set);
-
- return TRUE;
-
- retry_propfind:
-
- xmlXPathFreeContext (xp_ctx);
- xmlFreeDoc (doc);
-
- soup_uri = soup_uri_copy (soup_message_get_uri (message));
- soup_uri_set_path (soup_uri, addressbook_home_set);
-
- /* Note that we omit "D:resourcetype", "D:current-user-principal"
- * and "D:principal-URL" in order to short-circuit the recursion. */
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_1,
- NS_CARDDAV, XC ("addressbook-home-set"),
- NULL);
-
- e_soup_ssl_trust_connect (message, source);
-
- /* This takes ownership of the message. */
- soup_session_send_message (session, message);
-
- soup_uri_free (soup_uri);
-
- g_free (addressbook_home_set);
-
- success = e_webdav_discover_process_addressbook_home_set (session, message, source,
- out_certificate_pem, out_certificate_errors, out_discovered_sources,
- cancellable, error);
+ EWebDAVDiscoverContext *context = ptr;
- g_object_unref (message);
+ if (!context)
+ return;
- return success;
+ g_clear_object (&context->source);
+ g_free (context->url_use_path);
+ e_named_parameters_free (context->credentials);
+ g_free (context->out_certificate_pem);
+ e_webdav_discover_free_discovered_sources (context->out_discovered_sources);
+ g_slist_free_full (context->out_calendar_user_addresses, g_free);
+ g_free (context);
}
static void
@@ -1779,13 +526,6 @@ e_webdav_discover_sources_finish (ESource *source,
return g_task_propagate_boolean (G_TASK (result), error);
}
-static void
-e_webdav_discover_cancelled_cb (GCancellable *cancellable,
- SoupSession *session)
-{
- soup_session_abort (session);
-}
-
/**
* e_webdav_discover_sources_sync:
* @source: an #ESource from which to take connection details
@@ -1843,11 +583,8 @@ e_webdav_discover_sources_sync (ESource *source,
GError **error)
{
ESourceWebdav *webdav_extension;
- AuthenticateData auth_data;
- SoupSession *session;
- SoupMessage *message;
+ EWebDAVSession *webdav;
SoupURI *soup_uri;
- gulong cancelled_handler_id = 0, authenticate_handler_id;
gboolean success;
g_return_val_if_fail (E_IS_SOURCE (source), FALSE);
@@ -1889,166 +626,76 @@ e_webdav_discover_sources_sync (ESource *source,
g_string_free (new_path, TRUE);
}
- session = soup_session_new ();
- g_object_set (
- session,
- SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
- NULL);
-
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_0,
- NS_WEBDAV, XC ("resourcetype"),
- NS_WEBDAV, XC ("current-user-principal"),
- NS_WEBDAV, XC ("principal-URL"),
- NS_CALDAV, XC ("calendar-home-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NS_CARDDAV, XC ("addressbook-home-set"),
- NS_CARDDAV, XC ("principal-address"),
- NULL);
-
- if (!message) {
- soup_uri_free (soup_uri);
- g_object_unref (session);
- return FALSE;
- }
+ webdav = e_webdav_session_new (source);
+ e_soup_session_setup_logging (E_SOUP_SESSION (webdav), g_getenv ("WEBDAV_DEBUG"));
+ e_soup_session_set_credentials (E_SOUP_SESSION (webdav), credentials);
- if (g_getenv ("WEBDAV_DEBUG") != NULL) {
- SoupLogger *logger;
+ if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ WebDAVDiscoverData wdd;
+ gchar *uri;
+ GError *local_error = NULL;
- logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, 100 * 1024 * 1024);
- soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));
- g_object_unref (logger);
- }
+ wdd.covered_hrefs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ wdd.addressbooks = NULL;
+ wdd.calendars = NULL;
+ wdd.only_supports = only_supports;
+ wdd.out_calendar_user_addresses = out_calendar_user_addresses;
+ wdd.cancellable = cancellable;
+ wdd.error = &local_error;
- if (e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) {
- SoupSessionFeature *feature;
- ESourceAuthentication *auth_extension;
- gchar *auth_method;
+ uri = soup_uri_to_string (soup_uri, FALSE);
- feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER);
+ success = uri && *uri && e_webdav_discover_propfind_uri_sync (webdav, &wdd, uri, FALSE);
- success = TRUE;
+ g_free (uri);
- auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
- auth_method = e_source_authentication_dup_method (auth_extension);
+ if (success && !wdd.calendars && (only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
+ (only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_EVENTS | E_WEBDAV_DISCOVER_SUPPORTS_MEMOS |
E_WEBDAV_DISCOVER_SUPPORTS_TASKS)) != 0) &&
+ (!soup_uri_get_path (soup_uri) || !strstr (soup_uri_get_path (soup_uri),
"/.well-known/"))) {
+ gchar *saved_path;
- if (g_strcmp0 (auth_method, "OAuth2") == 0 || g_strcmp0 (auth_method, "Google") == 0) {
- SoupAuth *soup_auth;
+ saved_path = g_strdup (soup_uri_get_path (soup_uri));
- soup_auth = g_object_new (E_TYPE_SOUP_AUTH_BEARER, SOUP_AUTH_HOST, soup_uri->host,
NULL);
+ soup_uri_set_path (soup_uri, "/.well-known/caldav");
- success = e_webdav_discover_setup_bearer_auth (source, credentials,
- E_SOUP_AUTH_BEARER (soup_auth), cancellable, error);
+ uri = soup_uri_to_string (soup_uri, FALSE);
- if (success) {
- soup_session_feature_add_feature (feature, E_TYPE_SOUP_AUTH_BEARER);
- soup_auth_manager_use_auth (
- SOUP_AUTH_MANAGER (feature),
- soup_uri, soup_auth);
- }
+ /* Ignore errors here */
+ wdd.error = NULL;
+ wdd.only_supports = E_WEBDAV_DISCOVER_SUPPORTS_EVENTS |
E_WEBDAV_DISCOVER_SUPPORTS_MEMOS | E_WEBDAV_DISCOVER_SUPPORTS_TASKS;
- g_object_unref (soup_auth);
- }
+ success = uri && *uri && e_webdav_discover_propfind_uri_sync (webdav, &wdd, uri,
FALSE);
- g_free (auth_method);
+ g_free (uri);
- if (!success) {
- soup_uri_free (soup_uri);
- g_object_unref (message);
- g_object_unref (session);
- return FALSE;
+ soup_uri_set_path (soup_uri, saved_path);
+ g_free (saved_path);
}
- }
-
- auth_data.source = source;
- auth_data.credentials = credentials;
-
- authenticate_handler_id = g_signal_connect (session, "authenticate",
- G_CALLBACK (e_webdav_discover_authenticate_cb), &auth_data);
-
- if (cancellable)
- cancelled_handler_id = g_cancellable_connect (cancellable, G_CALLBACK
(e_webdav_discover_cancelled_cb), session, NULL);
- if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
- GSList *calendars = NULL, *addressbooks = NULL;
- GError *local_error = NULL;
-
- e_soup_ssl_trust_connect (message, source);
- soup_session_send_message (session, message);
-
- success = TRUE;
-
- if (only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
- (only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_EVENTS | E_WEBDAV_DISCOVER_SUPPORTS_MEMOS |
E_WEBDAV_DISCOVER_SUPPORTS_TASKS)) != 0) {
- success = e_webdav_discover_process_calendar_home_set (session, message, source,
out_certificate_pem,
- out_certificate_errors, &calendars, out_calendar_user_addresses, cancellable,
&local_error);
-
- if (!calendars && !g_cancellable_is_cancelled (cancellable) && (!soup_uri_get_path
(soup_uri) ||
- !strstr (soup_uri_get_path (soup_uri), "/.well-known/"))) {
- SoupMessage *well_known_message;
- gchar *saved_path;
-
- saved_path = g_strdup (soup_uri_get_path (soup_uri));
+ if (success && !wdd.addressbooks && (only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
+ (only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS)) != 0) &&
+ (!soup_uri_get_path (soup_uri) || !strstr (soup_uri_get_path (soup_uri),
"/.well-known/"))) {
+ gchar *saved_path;
- soup_uri_set_path (soup_uri, "/.well-known/caldav");
+ saved_path = g_strdup (soup_uri_get_path (soup_uri));
- well_known_message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_0,
- NS_WEBDAV, XC ("resourcetype"),
- NS_WEBDAV, XC ("current-user-principal"),
- NS_WEBDAV, XC ("principal-URL"),
- NS_CALDAV, XC ("calendar-home-set"),
- NS_CALDAV, XC ("calendar-user-address-set"),
- NULL);
+ soup_uri_set_path (soup_uri, "/.well-known/carddav");
- soup_uri_set_path (soup_uri, saved_path);
- g_free (saved_path);
+ uri = soup_uri_to_string (soup_uri, FALSE);
- if (well_known_message) {
- e_soup_ssl_trust_connect (well_known_message, source);
- soup_session_send_message (session, well_known_message);
+ /* Ignore errors here */
+ wdd.error = NULL;
+ wdd.only_supports = E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS;
- /* Ignore errors here */
- e_webdav_discover_process_calendar_home_set (session,
well_known_message, source, out_certificate_pem,
- out_certificate_errors, &calendars,
out_calendar_user_addresses, cancellable, NULL);
+ success = uri && *uri && e_webdav_discover_propfind_uri_sync (webdav, &wdd, uri,
FALSE);
- g_clear_object (&well_known_message);
- }
- }
- }
+ g_free (uri);
- if (success && (only_supports == E_WEBDAV_DISCOVER_SUPPORTS_NONE ||
- (only_supports & (E_WEBDAV_DISCOVER_SUPPORTS_CONTACTS)) != 0)) {
- success = e_webdav_discover_process_addressbook_home_set (session, message, source,
out_certificate_pem,
- out_certificate_errors, &addressbooks, cancellable, local_error ? NULL :
&local_error);
-
- if (!addressbooks && !g_cancellable_is_cancelled (cancellable) && (!soup_uri_get_path
(soup_uri) ||
- !strstr (soup_uri_get_path (soup_uri), "/.well-known/"))) {
- g_clear_object (&message);
-
- soup_uri_set_path (soup_uri, "/.well-known/carddav");
-
- message = e_webdav_discover_new_propfind (
- session, soup_uri, DEPTH_0,
- NS_WEBDAV, XC ("resourcetype"),
- NS_WEBDAV, XC ("current-user-principal"),
- NS_WEBDAV, XC ("principal-URL"),
- NS_CARDDAV, XC ("addressbook-home-set"),
- NS_CARDDAV, XC ("principal-address"),
- NULL);
-
- if (message) {
- e_soup_ssl_trust_connect (message, source);
- soup_session_send_message (session, message);
-
- /* Ignore errors here */
- e_webdav_discover_process_addressbook_home_set (session, message,
source, out_certificate_pem,
- out_certificate_errors, &addressbooks, cancellable, NULL);
- }
- }
+ soup_uri_set_path (soup_uri, saved_path);
+ g_free (saved_path);
}
- if (calendars || addressbooks) {
+ if (wdd.calendars || wdd.addressbooks) {
success = TRUE;
g_clear_error (&local_error);
} else if (local_error) {
@@ -2056,13 +703,13 @@ e_webdav_discover_sources_sync (ESource *source,
}
if (out_discovered_sources) {
- if (calendars)
- *out_discovered_sources = g_slist_concat (*out_discovered_sources, calendars);
- if (addressbooks)
- *out_discovered_sources = g_slist_concat (*out_discovered_sources,
addressbooks);
+ if (wdd.calendars)
+ *out_discovered_sources = g_slist_concat (*out_discovered_sources,
wdd.calendars);
+ if (wdd.addressbooks)
+ *out_discovered_sources = g_slist_concat (*out_discovered_sources,
wdd.addressbooks);
} else {
- e_webdav_discover_free_discovered_sources (calendars);
- e_webdav_discover_free_discovered_sources (addressbooks);
+ e_webdav_discover_free_discovered_sources (wdd.calendars);
+ e_webdav_discover_free_discovered_sources (wdd.addressbooks);
}
if (out_calendar_user_addresses && *out_calendar_user_addresses)
@@ -2070,19 +717,17 @@ e_webdav_discover_sources_sync (ESource *source,
if (out_discovered_sources && *out_discovered_sources)
*out_discovered_sources = g_slist_reverse (*out_discovered_sources);
+
+ g_hash_table_destroy (wdd.covered_hrefs);
} else {
success = FALSE;
}
- if (cancellable && cancelled_handler_id)
- g_cancellable_disconnect (cancellable, cancelled_handler_id);
-
- if (authenticate_handler_id)
- g_signal_handler_disconnect (session, authenticate_handler_id);
+ if (!success)
+ e_soup_session_get_ssl_error_details (E_SOUP_SESSION (webdav), out_certificate_pem,
out_certificate_errors);
soup_uri_free (soup_uri);
- g_clear_object (&message);
- g_object_unref (session);
+ g_object_unref (webdav);
return success;
}
diff --git a/src/libedataserver/e-webdav-session.c b/src/libedataserver/e-webdav-session.c
index 29f2f8a..cfb0652 100644
--- a/src/libedataserver/e-webdav-session.c
+++ b/src/libedataserver/e-webdav-session.c
@@ -966,7 +966,7 @@ e_webdav_session_replace_with_detailed_error (EWebDAVSession *webdav,
e_soup_session_util_status_to_string (status_code, reason_phrase),
detail_text);
}
- } else if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
+ } else if (status_code && !SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
error_set = TRUE;
g_clear_error (inout_error);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]