[evolution-data-server/account-mgmt: 20/38] Adapt calendar backends to the new ESource API.



commit ce6ec9eaf51e77cb553016717abe13dda11ee9d2
Author: Matthew Barnes <mbarnes redhat com>
Date:   Mon Nov 22 23:04:56 2010 -0500

    Adapt calendar backends to the new ESource API.

 calendar/backends/http/e-cal-backend-http.c |  660 +++++++++++++++++----------
 1 files changed, 421 insertions(+), 239 deletions(-)
---
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index 61fb4b5..4da687f 100644
--- a/calendar/backends/http/e-cal-backend-http.c
+++ b/calendar/backends/http/e-cal-backend-http.c
@@ -28,6 +28,11 @@
 #include <glib/gi18n-lib.h>
 #include "libedataserver/e-xml-hash-utils.h"
 #include "libedataserver/e-proxy.h"
+#include "libedataserver/e-source-authentication.h"
+#include "libedataserver/e-source-authenticator.h"
+#include "libedataserver/e-source-refresh.h"
+#include "libedataserver/e-source-security.h"
+#include "libedataserver/e-source-webdav.h"
 #include <libecal/e-cal-recur.h>
 #include <libecal/e-cal-util.h>
 #include <libecal/e-cal-time-util.h>
@@ -42,9 +47,17 @@
 #define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
 #define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
 
-G_DEFINE_TYPE (ECalBackendHttp, e_cal_backend_http, E_TYPE_CAL_BACKEND_SYNC)
+/* Forward Declarations */
+static void	e_cal_backend_http_source_authenticator_init
+				(ESourceAuthenticatorInterface *interface);
 
-
+G_DEFINE_TYPE_WITH_CODE (
+	ECalBackendHttp,
+	e_cal_backend_http,
+	E_TYPE_CAL_BACKEND_SYNC,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		e_cal_backend_http_source_authenticator_init))
 
 /* Private part of the ECalBackendHttp structure */
 struct _ECalBackendHttpPrivate {
@@ -67,21 +80,43 @@ struct _ECalBackendHttpPrivate {
 	gboolean opened;
 	gboolean requires_auth;
 
-	ECredentials *credentials;
+	gchar *password;
 };
 
-
-
 #define d(x)
 
-static void e_cal_backend_http_dispose (GObject *object);
-static void e_cal_backend_http_finalize (GObject *object);
-static gboolean begin_retrieval_cb (ECalBackendHttp *cbhttp);
 static void e_cal_backend_http_add_timezone (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, const gchar *tzobj, GError **perror);
 
 static ECalBackendSyncClass *parent_class;
 
-
+static void
+soup_authenticate (SoupSession *session,
+                   SoupMessage *msg,
+                   SoupAuth *auth,
+                   gboolean retrying,
+                   gpointer data)
+{
+	ECalBackendHttpPrivate *priv;
+	ECalBackendHttp *cbhttp;
+	ESourceAuthentication *auth_extension;
+	ESource *source;
+	const gchar *extension_name;
+
+	cbhttp = E_CAL_BACKEND_HTTP (data);
+	priv =  cbhttp->priv;
+
+	source = e_backend_get_source (E_BACKEND (data));
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
+
+	if (!retrying && priv->password != NULL) {
+		gchar *user;
+
+		user = e_source_authentication_dup_user (auth_extension);
+		soup_auth_authenticate (auth, user, priv->password);
+		g_free (user);
+	}
+}
 
 /* Dispose handler for the file backend */
 static void
@@ -103,12 +138,10 @@ e_cal_backend_http_dispose (GObject *object)
 		g_object_unref (priv->soup_session);
 		priv->soup_session = NULL;
 	}
-
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
-
 	if (priv->source_changed_id) {
-		g_signal_handler_disconnect (e_backend_get_source (E_BACKEND (cbhttp)), priv->source_changed_id);
+		g_signal_handler_disconnect (
+			e_backend_get_source (E_BACKEND (cbhttp)),
+			priv->source_changed_id);
 		priv->source_changed_id = 0;
 	}
 
@@ -141,6 +174,8 @@ e_cal_backend_http_finalize (GObject *object)
 		priv->uri = NULL;
 	}
 
+	g_free (priv->password);
+
 	g_free (priv);
 	cbhttp->priv = NULL;
 
@@ -148,7 +183,32 @@ e_cal_backend_http_finalize (GObject *object)
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-
+static void
+e_cal_backend_http_constructed (GObject *object)
+{
+	ECalBackendHttp *backend;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (parent_class)->constructed (object);
+
+	backend = E_CAL_BACKEND_HTTP (object);
+	backend->priv->soup_session = soup_session_sync_new ();
+
+	g_signal_connect (
+		backend->priv->soup_session, "authenticate",
+		G_CALLBACK (soup_authenticate), backend);
+
+	if (g_getenv ("WEBCAL_DEBUG") != NULL) {
+		SoupLogger *logger;
+
+		logger = soup_logger_new (
+			SOUP_LOGGER_LOG_BODY, 1024 * 1024);
+		soup_session_add_feature (
+			backend->priv->soup_session,
+			SOUP_SESSION_FEATURE (logger));
+		g_object_unref (logger);
+	}
+}
 
 /* Calendar backend methods */
 
@@ -349,56 +409,127 @@ put_component_to_store (ECalBackendHttp *cb,
 	return TRUE;
 }
 
+static SoupMessage *
+cal_backend_http_new_message (ECalBackendHttp *backend,
+                              const gchar *uri)
+{
+	SoupMessage *soup_message;
+
+	/* create message to be sent to server */
+	soup_message = soup_message_new (SOUP_METHOD_GET, uri);
+	if (soup_message == NULL)
+		return NULL;
+
+	soup_message_headers_append (
+		soup_message->request_headers,
+		"User-Agent", "Evolution/" VERSION);
+	soup_message_headers_append (
+		soup_message->request_headers,
+		"Connection", "close");
+	soup_message_set_flags (
+		soup_message, SOUP_MESSAGE_NO_REDIRECT);
+	if (backend->priv->store != NULL) {
+		const gchar *etag;
+
+		etag = e_cal_backend_store_get_key_value (
+			backend->priv->store, "ETag");
+
+		if (etag != NULL && *etag != '\0')
+			soup_message_headers_append (
+				soup_message->request_headers,
+				"If-None-Match", etag);
+	}
+
+	return soup_message;
+}
+
 static void
-retrieval_done (SoupSession *session,
-                SoupMessage *msg,
-                ECalBackendHttp *cbhttp)
+cal_backend_http_cancelled (GCancellable *cancellable,
+                            gpointer user_data)
 {
-	ECalBackendHttpPrivate *priv;
+	struct {
+		SoupSession *soup_session;
+		SoupMessage *soup_message;
+	} *cancel_data = user_data;
+
+	soup_session_cancel_message (
+		cancel_data->soup_session,
+		cancel_data->soup_message,
+		SOUP_STATUS_CANCELLED);
+}
+
+static gboolean
+cal_backend_http_load (ECalBackendHttp *backend,
+                       GCancellable *cancellable,
+                       const gchar *uri,
+                       GError **error)
+{
+	ECalBackendHttpPrivate *priv = backend->priv;
+	SoupMessage *soup_message;
+	SoupSession *soup_session;
 	icalcomponent *icalcomp, *subcomp;
 	icalcomponent_kind kind;
 	const gchar *newuri;
 	SoupURI *uri_parsed;
 	GHashTable *old_cache;
 	GSList *comps_in_cache;
+	guint status_code;
+	gulong cancel_id = 0;
 
-	if (!msg || msg->status_code == SOUP_STATUS_CANCELLED) {
-		/* the backend probably gone in this case, thus just return */
-		g_object_unref (cbhttp);
-		return;
-	}
+	struct {
+		SoupSession *soup_session;
+		SoupMessage *soup_message;
+	} cancel_data;
 
-	priv = cbhttp->priv;
+	soup_session = backend->priv->soup_session;
+	soup_message = cal_backend_http_new_message (backend, uri);
 
-	priv->is_loading = FALSE;
-	d(g_message ("Retrieval done.\n"));
+	if (soup_message == NULL) {
+		g_set_error (
+			error, SOUP_HTTP_ERROR,
+			SOUP_STATUS_MALFORMED,
+			_("Malformed URI: %s"), uri);
+		return FALSE;
+	}
 
-	if (!priv->uri) {
-		/* uri changed meanwhile, retrieve again */
-		begin_retrieval_cb (cbhttp);
-		g_object_unref (cbhttp);
-		return;
+	if (G_IS_CANCELLABLE (cancellable)) {
+		cancel_data.soup_session = soup_session;
+		cancel_data.soup_message = soup_message;
+
+		cancel_id = g_cancellable_connect (
+			cancellable,
+			G_CALLBACK (cal_backend_http_cancelled),
+			&cancel_data, (GDestroyNotify) NULL);
 	}
 
-	if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
+	status_code = soup_session_send_message (soup_session, soup_message);
+
+	if (G_IS_CANCELLABLE (cancellable))
+		g_cancellable_disconnect (cancellable, cancel_id);
+
+	if (status_code == SOUP_STATUS_NOT_MODIFIED) {
 		/* attempts with ETag can result in 304 status code */
+		g_object_unref (soup_message);
 		priv->opened = TRUE;
-		g_object_unref (cbhttp);
-		return;
+		return TRUE;
 	}
 
 	/* Handle redirection ourselves */
-	if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
-		newuri = soup_message_headers_get (msg->response_headers,
-						   "Location");
+	if (SOUP_STATUS_IS_REDIRECTION (status_code)) {
+		gboolean success;
 
-		d(g_message ("Redirected from %s to %s\n", priv->uri, newuri));
+		newuri = soup_message_headers_get (
+			soup_message->response_headers, "Location");
+
+		d(g_message ("Redirected from %s to %s\n", async_context->uri, newuri));
+
+		if (newuri != NULL) {
+			gchar *redirected_uri;
 
-		if (newuri) {
 			if (newuri[0]=='/') {
 				g_warning ("Hey! Relative URI returned! Working around...\n");
 
-				uri_parsed = soup_uri_new (priv->uri);
+				uri_parsed = soup_uri_new (uri);
 				soup_uri_set_path (uri_parsed, newuri);
 				soup_uri_set_query (uri_parsed, NULL);
 				/* g_free (newuri); */
@@ -408,69 +539,73 @@ retrieval_done (SoupSession *session,
 				soup_uri_free (uri_parsed);
 			}
 
-			g_free (priv->uri);
+			redirected_uri =
+				webcal_to_http_method (newuri, FALSE);
+			success = cal_backend_http_load (
+				backend, cancellable, redirected_uri, error);
+			g_free (redirected_uri);
 
-			priv->uri = webcal_to_http_method (newuri, FALSE);
-			begin_retrieval_cb (cbhttp);
 		} else {
-			if (!priv->opened) {
-				e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp),
-							    _("Redirected to Invalid URI"));
-			}
+			g_set_error (
+				error, SOUP_HTTP_ERROR,
+				SOUP_STATUS_BAD_REQUEST,
+				_("Redirected to Invalid URI"));
+			success = FALSE;
 		}
 
-		g_object_unref (cbhttp);
-		return;
+		g_object_unref (soup_message);
+		return success;
 	}
 
 	/* check status code */
-	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		if (!priv->opened) {
-			if (msg->status_code == 401 || msg->status_code == 403) {
-				priv->requires_auth = TRUE;
-				e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbhttp), TRUE, priv->credentials);
-				g_object_unref (cbhttp);
-				return;
-			} else
-				e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp),
-					msg->reason_phrase && *msg->reason_phrase ? msg->reason_phrase :
-					(soup_status_get_phrase (msg->status_code) ? soup_status_get_phrase (msg->status_code) : _("Unknown error")));
-		}
-
-		empty_cache (cbhttp);
-		g_object_unref (cbhttp);
-		return;
+	if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) {
+		g_set_error (
+			error, SOUP_HTTP_ERROR, status_code,
+			"%s", soup_message->reason_phrase);
+		g_object_unref (soup_message);
+		empty_cache (backend);
+		return FALSE;
 	}
 
 	if (priv->store) {
-		const gchar *etag = soup_message_headers_get_one (msg->response_headers, "ETag");
+		const gchar *etag;
 
-		if (!etag || !*etag)
+		etag = soup_message_headers_get_one (
+			soup_message->response_headers, "ETag");
+
+		if (etag != NULL && *etag == '\0')
 			etag = NULL;
 
 		e_cal_backend_store_put_key_value (priv->store, "ETag", etag);
 	}
 
 	/* get the calendar from the response */
-	icalcomp = icalparser_parse_string (msg->response_body->data);
+	icalcomp = icalparser_parse_string (soup_message->response_body->data);
 
 	if (!icalcomp) {
-		if (!priv->opened)
-			e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp), _("Bad file format."));
-		empty_cache (cbhttp);
-		g_object_unref (cbhttp);
-		return;
+		g_set_error (
+			error, SOUP_HTTP_ERROR,
+			SOUP_STATUS_MALFORMED,
+			_("Bad file format."));
+		g_object_unref (soup_message);
+		empty_cache (backend);
+		return FALSE;
 	}
 
 	if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) {
-		if (!priv->opened)
-			e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp), _("Not a calendar."));
+		g_set_error (
+			error, SOUP_HTTP_ERROR,
+			SOUP_STATUS_MALFORMED,
+			_("Not a calendar."));
 		icalcomponent_free (icalcomp);
-		empty_cache (cbhttp);
-		g_object_unref (cbhttp);
-		return;
+		g_object_unref (soup_message);
+		empty_cache (backend);
+		return FALSE;
 	}
 
+	g_object_unref (soup_message);
+	soup_message = NULL;
+
 	/* Update cache */
 	old_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
@@ -486,7 +621,7 @@ retrieval_done (SoupSession *session,
 		g_object_unref (comp);
 	}
 
-	kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbhttp));
+	kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
 	subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT);
 	e_cal_backend_store_freeze_changes (priv->store);
 	while (subcomp) {
@@ -510,18 +645,18 @@ retrieval_done (SoupSession *session,
 
 				e_cal_component_get_uid (comp, &uid);
 
-				if (!put_component_to_store (cbhttp, comp)) {
+				if (!put_component_to_store (backend, comp)) {
 					g_hash_table_remove (old_cache, uid);
 				} else if (g_hash_table_lookup_extended (old_cache, uid, &orig_key, &orig_value)) {
 					ECalComponent *orig_comp = e_cal_component_new_from_string (orig_value);
 
-					e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbhttp), orig_comp, comp);
+					e_cal_backend_notify_component_modified (E_CAL_BACKEND (backend), orig_comp, comp);
 
 					g_hash_table_remove (old_cache, uid);
 					if (orig_comp)
 						g_object_unref (orig_comp);
 				} else {
-					e_cal_backend_notify_component_created (E_CAL_BACKEND (cbhttp), comp);
+					e_cal_backend_notify_component_created (E_CAL_BACKEND (backend), comp);
 				}
 			}
 
@@ -542,7 +677,7 @@ retrieval_done (SoupSession *session,
 	e_cal_backend_store_thaw_changes (priv->store);
 
 	/* notify the removals */
-	g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, cbhttp);
+	g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, backend);
 	g_hash_table_destroy (old_cache);
 
 	/* free memory */
@@ -550,117 +685,109 @@ retrieval_done (SoupSession *session,
 
 	priv->opened = TRUE;
 
-	g_object_unref (cbhttp);
-
-	d(g_message ("Retrieval really done.\n"));
+	return TRUE;
 }
 
-/* ************************************************************************* */
-/* Authentication helpers for libsoup */
-
-static void
-soup_authenticate (SoupSession *session,
-                   SoupMessage *msg,
-                   SoupAuth *auth,
-                   gboolean retrying,
-                   gpointer data)
+static const gchar *
+cal_backend_http_ensure_uri (ECalBackendHttp *backend)
 {
-	ECalBackendHttpPrivate *priv;
-	ECalBackendHttp        *cbhttp;
+	ESource *source;
+	ESourceSecurity *security_extension;
+	ESourceWebdav *webdav_extension;
+	SoupURI *soup_uri;
+	EProxy *proxy;
+	gboolean secure_connection;
+	const gchar *extension_name;
+	gchar *uri_string;
 
-	cbhttp = E_CAL_BACKEND_HTTP (data);
-	priv =  cbhttp->priv;
+	if (backend->priv->uri != NULL)
+		return backend->priv->uri;
 
-	if (!retrying && priv->credentials && e_credentials_has_key (priv->credentials, E_CREDENTIALS_KEY_USERNAME)) {
-		soup_auth_authenticate (auth, e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_USERNAME), e_credentials_peek (priv->credentials, E_CREDENTIALS_KEY_PASSWORD));
-		e_credentials_clear_peek (priv->credentials);
-	}
-}
+	source = e_backend_get_source (E_BACKEND (backend));
 
-static gboolean reload_cb                  (ECalBackendHttp *cbhttp);
-static void     maybe_start_reload_timeout (ECalBackendHttp *cbhttp);
+	extension_name = E_SOURCE_EXTENSION_SECURITY;
+	security_extension = e_source_get_extension (source, extension_name);
 
-static gboolean
-begin_retrieval_cb (ECalBackendHttp *cbhttp)
-{
-	ECalBackendHttpPrivate *priv;
-	SoupMessage *soup_message;
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	webdav_extension = e_source_get_extension (source, extension_name);
 
-	priv = cbhttp->priv;
+	secure_connection = e_source_security_get_secure (security_extension);
 
-	if (!e_backend_get_online (E_BACKEND (cbhttp)))
-		return FALSE;
+	soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
+	uri_string = soup_uri_to_string (soup_uri, FALSE);
+	soup_uri_free (soup_uri);
 
-	maybe_start_reload_timeout (cbhttp);
+	backend->priv->uri = webcal_to_http_method (
+		uri_string, secure_connection);
 
-	d(g_message ("Starting retrieval...\n"));
+	g_free (uri_string);
 
-	if (priv->is_loading)
-		return FALSE;
+	/* set the HTTP proxy, if configuration is set to do so */
 
-	priv->is_loading = TRUE;
+	proxy = e_proxy_new ();
+	e_proxy_setup_proxy (proxy);
 
-	if (priv->uri == NULL) {
-		ESource *source = e_backend_get_source (E_BACKEND (cbhttp));
-		const gchar *secure_prop = e_source_get_property (source, "use_ssl");
+	if (e_proxy_require_proxy_for_uri (proxy, backend->priv->uri))
+		soup_uri = e_proxy_peek_uri_for (proxy, backend->priv->uri);
+	else
+		soup_uri = NULL;
 
-		priv->uri = webcal_to_http_method (
-			e_source_get_uri (source),
-			(secure_prop && g_str_equal(secure_prop, "1")));
-	}
+	g_object_set (
+		G_OBJECT (backend->priv->soup_session),
+		SOUP_SESSION_PROXY_URI, soup_uri, NULL);
 
-	/* create the Soup session if not already created */
-	if (!priv->soup_session) {
-		EProxy *proxy;
-		SoupURI *proxy_uri = NULL;
+	g_object_unref (proxy);
 
-		priv->soup_session = soup_session_async_new ();
+	return backend->priv->uri;
+}
 
-		g_signal_connect (priv->soup_session, "authenticate",
-				  G_CALLBACK (soup_authenticate), cbhttp);
+static void     maybe_start_reload_timeout (ECalBackendHttp *cbhttp);
 
-		if (g_getenv ("WEBCAL_DEBUG") != NULL) {
-			SoupLogger *logger;
+static gboolean
+begin_retrieval_cb (GIOSchedulerJob *job,
+                    GCancellable *cancellable,
+                    ECalBackendHttp *backend)
+{
+	ESource *source;
+	const gchar *uri;
+	GError *error = NULL;
 
-			logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, 1024 * 1024);
-			soup_session_add_feature (priv->soup_session, SOUP_SESSION_FEATURE (logger));
-			g_object_unref (logger);
-		}
+	if (!e_backend_get_online (E_BACKEND (backend)))
+		return FALSE;
 
-		/* set the HTTP proxy, if configuration is set to do so */
-		proxy = e_proxy_new ();
-		e_proxy_setup_proxy (proxy);
-		if (e_proxy_require_proxy_for_uri (proxy, priv->uri)) {
-			proxy_uri = e_proxy_peek_uri_for (proxy, priv->uri);
-		}
+	maybe_start_reload_timeout (backend);
 
-		g_object_set (G_OBJECT (priv->soup_session), SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
+	if (backend->priv->is_loading)
+		return FALSE;
 
-		g_object_unref (proxy);
-	}
+	d(g_message ("Starting retrieval...\n"));
 
-	/* create message to be sent to server */
-	soup_message = soup_message_new (SOUP_METHOD_GET, priv->uri);
-	if (soup_message == NULL) {
-		priv->is_loading = FALSE;
-		empty_cache (cbhttp);
-		return FALSE;
+	backend->priv->is_loading = TRUE;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+
+	uri = cal_backend_http_ensure_uri (backend);
+	cal_backend_http_load (backend, cancellable, uri, &error);
+
+	if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
+		g_clear_error (&error);
+		e_source_authenticate_sync (
+			source, E_SOURCE_AUTHENTICATOR (backend),
+			cancellable, &error);
 	}
 
-	soup_message_headers_append (soup_message->request_headers, "User-Agent", "Evolution/" VERSION);
-	soup_message_headers_append (soup_message->request_headers, "Connection", "close");
-	soup_message_set_flags (soup_message, SOUP_MESSAGE_NO_REDIRECT);
-	if (priv->store) {
-		const gchar *etag = e_cal_backend_store_get_key_value (priv->store, "ETag");
+	backend->priv->is_loading = FALSE;
 
-		if (etag && *etag)
-			soup_message_headers_append (soup_message->request_headers, "If-None-Match", etag);
+	if (error != NULL) {
+		e_cal_backend_notify_error (
+			E_CAL_BACKEND (backend),
+			error->message);
+		empty_cache (backend);
+		g_error_free (error);
 	}
 
-	soup_session_queue_message (priv->soup_session, soup_message,
-				    (SoupSessionCallback) retrieval_done, g_object_ref (cbhttp));
+	d(g_message ("Retrieval really done.\n"));
 
-	d(g_message ("Retrieval started.\n"));
 	return FALSE;
 }
 
@@ -677,7 +804,13 @@ reload_cb (ECalBackendHttp *cbhttp)
 	d(g_message ("Reload!\n"));
 
 	priv->reload_timeout_id = 0;
-	begin_retrieval_cb (cbhttp);
+
+	g_io_scheduler_push_job (
+		(GIOSchedulerJobFunc) begin_retrieval_cb,
+		g_object_ref (cbhttp),
+		(GDestroyNotify) g_object_unref,
+		G_PRIORITY_DEFAULT, NULL);
+
 	return FALSE;
 }
 
@@ -686,7 +819,9 @@ maybe_start_reload_timeout (ECalBackendHttp *cbhttp)
 {
 	ECalBackendHttpPrivate *priv;
 	ESource *source;
-	const gchar *refresh_str;
+	ESourceRefresh *extension;
+	const gchar *extension_name;
+	guint interval_in_minutes = 0;
 
 	priv = cbhttp->priv;
 
@@ -701,45 +836,48 @@ maybe_start_reload_timeout (ECalBackendHttp *cbhttp)
 		return;
 	}
 
-	refresh_str = e_source_get_property (source, "refresh");
+	extension_name = E_SOURCE_EXTENSION_REFRESH;
+	extension = e_source_get_extension (source, extension_name);
+
+	if (e_source_refresh_get_enabled (extension))
+		interval_in_minutes =
+			e_source_refresh_get_interval_minutes (extension);
 
-	priv->reload_timeout_id = g_timeout_add ((refresh_str ? atoi (refresh_str) : 30) * 60000,
-						 (GSourceFunc) reload_cb, cbhttp);
+	if (interval_in_minutes > 0)
+		priv->reload_timeout_id = g_timeout_add_seconds (
+			interval_in_minutes * 60,
+			(GSourceFunc) reload_cb, cbhttp);
 }
 
 static void
 source_changed_cb (ESource *source,
                    ECalBackendHttp *cbhttp)
 {
-	ECalBackendHttpPrivate *priv;
-
 	g_return_if_fail (cbhttp != NULL);
 	g_return_if_fail (cbhttp->priv != NULL);
 
-	priv = cbhttp->priv;
+	if (cbhttp->priv->uri != NULL) {
+		gboolean uri_changed;
+		const gchar *new_uri;
+		gchar *old_uri;
 
-	if (priv->uri) {
-		ESource *source;
-		const gchar *secure_prop;
-		gchar *new_uri;
+		old_uri = g_strdup (cbhttp->priv->uri);
 
-		source = e_backend_get_source (E_BACKEND (cbhttp));
-		secure_prop = e_source_get_property (source, "use_ssl");
+		g_free (cbhttp->priv->uri);
+		cbhttp->priv->uri = NULL;
 
-		new_uri = webcal_to_http_method (
-			e_source_get_uri (source),
-			(secure_prop && g_str_equal(secure_prop, "1")));
+		new_uri = cal_backend_http_ensure_uri (cbhttp);
 
-		if (new_uri && !g_str_equal (priv->uri, new_uri)) {
-			/* uri changed, do reload some time soon */
-			g_free (priv->uri);
-			priv->uri = NULL;
+		uri_changed = (g_strcmp0 (old_uri, new_uri) != 0);
 
-			if (!priv->is_loading)
-				g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
-		}
+		if (uri_changed && !cbhttp->priv->is_loading)
+			g_io_scheduler_push_job (
+				(GIOSchedulerJobFunc) begin_retrieval_cb,
+				g_object_ref (cbhttp),
+				(GDestroyNotify) g_object_unref,
+				G_PRIORITY_DEFAULT, NULL);
 
-		g_free (new_uri);
+		g_free (old_uri);
 	}
 }
 
@@ -754,6 +892,11 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	ECalBackendHttp *cbhttp;
 	ECalBackendHttpPrivate *priv;
 	ESource *source;
+	ESourceAuthentication *auth_extension;
+	const gchar *extension_name;
+	const gchar *cache_dir;
+	gboolean auth_required;
+	gboolean opened = TRUE;
 	gboolean online;
 	gchar *tmp;
 
@@ -767,9 +910,16 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	}
 
 	source = e_backend_get_source (E_BACKEND (backend));
+	cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));
+
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
+	auth_required = e_source_authentication_required (auth_extension);
 
 	if (priv->source_changed_id == 0) {
-		priv->source_changed_id = g_signal_connect (source, "changed", G_CALLBACK (source_changed_cb), cbhttp);
+		priv->source_changed_id = g_signal_connect (
+			source, "changed",
+			G_CALLBACK (source_changed_cb), cbhttp);
 	}
 
 	/* always read uri again */
@@ -777,19 +927,20 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	priv->uri = NULL;
 	g_free (tmp);
 
-	if (!priv->store) {
-		const gchar *cache_dir;
-
-		cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));
-
+	if (priv->store == NULL) {
 		/* remove the old cache while migrating to ECalBackendStore */
 		e_cal_backend_cache_remove (cache_dir, "cache.xml");
 		priv->store = e_cal_backend_file_store_new (cache_dir);
 		e_cal_backend_store_load (priv->store);
 
 		if (!priv->store) {
-			g_propagate_error (perror, EDC_ERROR_EX (OtherError, _("Could not create cache file")));
-			e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR_EX (OtherError, _("Could not create cache file")));
+			g_propagate_error (
+				perror, EDC_ERROR_EX (OtherError,
+				_("Could not create cache file")));
+			e_cal_backend_notify_opened (
+				E_CAL_BACKEND (backend),
+				EDC_ERROR_EX (OtherError,
+				_("Could not create cache file")));
 			return;
 		}
 	}
@@ -800,48 +951,33 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	e_cal_backend_notify_online (E_CAL_BACKEND (backend), online);
 
 	if (online) {
-		if (e_source_get_property (source, "auth")) {
-			e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbhttp), TRUE, priv->credentials);
-		} else if (priv->requires_auth && perror && !*perror) {
-			g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
-			e_cal_backend_notify_opened (E_CAL_BACKEND (backend), EDC_ERROR (AuthenticationRequired));
-		} else {
-			e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
-			g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
+		const gchar *uri;
+		GError *local_error = NULL;
+
+		uri = cal_backend_http_ensure_uri (cbhttp);
+
+		if (!auth_required) {
+			opened = cal_backend_http_load (
+				cbhttp, cancellable,
+				uri, &local_error);
+			auth_required = g_error_matches (
+				local_error, SOUP_HTTP_ERROR,
+				SOUP_STATUS_UNAUTHORIZED);
 		}
-	} else {
-		e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
-	}
-}
-
-static void
-e_cal_backend_http_authenticate_user (ECalBackendSync *backend,
-                                      GCancellable *cancellable,
-                                      ECredentials *credentials,
-                                      GError **error)
-{
-	ECalBackendHttp        *cbhttp;
-	ECalBackendHttpPrivate *priv;
-
-	cbhttp = E_CAL_BACKEND_HTTP (backend);
-	priv  = cbhttp->priv;
-
-	if (priv->credentials && credentials && e_credentials_equal_keys (priv->credentials, credentials, E_CREDENTIALS_KEY_USERNAME, E_CREDENTIALS_KEY_PASSWORD, NULL)) {
-		g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
-		return;
-	}
 
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
+		if (auth_required) {
+			g_clear_error (&local_error);
+			opened = e_source_authenticate_sync (
+				source, E_SOURCE_AUTHENTICATOR (backend),
+				cancellable, &local_error);
+		}
 
-	if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
-		g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
-		return;
+		if (local_error != NULL)
+			g_propagate_error (perror, local_error);
 	}
 
-	priv->credentials = e_credentials_new_clone (credentials);
-
-	g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
+	if (opened)
+		e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
 }
 
 static void
@@ -909,7 +1045,11 @@ e_cal_backend_http_notify_online_cb (ECalBackend *backend,
 		}
 	} else {
 		if (loaded)
-			g_idle_add ((GSourceFunc) begin_retrieval_cb, backend);
+			g_io_scheduler_push_job (
+				(GIOSchedulerJobFunc) begin_retrieval_cb,
+				g_object_ref (backend),
+				(GDestroyNotify) g_object_unref,
+				G_PRIORITY_DEFAULT, NULL);
 	}
 
 	if (loaded)
@@ -1232,6 +1372,7 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
                                   GSList **freebusy,
                                   GError **error)
 {
+	ESourceRegistry *registry;
 	ECalBackendHttp *cbhttp;
 	ECalBackendHttpPrivate *priv;
 	gchar *address, *name;
@@ -1249,8 +1390,10 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
 		return;
 	}
 
+	registry = e_backend_get_registry (E_BACKEND (backend));
+
 	if (users == NULL) {
-		if (e_cal_backend_mail_account_get_default (&address, &name)) {
+		if (e_cal_backend_mail_account_get_default (registry, &address, &name)) {
 			vfb = create_user_free_busy (cbhttp, address, name, start, end);
 			calobj = icalcomponent_as_ical_string_r (vfb);
                         *freebusy = g_slist_append (*freebusy, calobj);
@@ -1262,7 +1405,7 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
 		const GSList *l;
 		for (l = users; l != NULL; l = l->next ) {
 			address = l->data;
-			if (e_cal_backend_mail_account_is_valid (address, &name)) {
+			if (e_cal_backend_mail_account_is_valid (registry, address, &name)) {
 				vfb = create_user_free_busy (cbhttp, address, name, start, end);
 				calobj = icalcomponent_as_ical_string_r (vfb);
                                 *freebusy = g_slist_append (*freebusy, calobj);
@@ -1367,6 +1510,38 @@ e_cal_backend_http_internal_get_timezone (ECalBackend *backend,
 	return zone;
 }
 
+static ESourceAuthenticationResult
+cal_backend_http_try_password_sync (ESourceAuthenticator *authenticator,
+                                    const GString *password,
+                                    GCancellable *cancellable,
+                                    GError **error)
+{
+	ECalBackendHttp *backend;
+	ESourceAuthenticationResult result;
+	const gchar *uri;
+	GError *local_error = NULL;
+
+	backend = E_CAL_BACKEND_HTTP (authenticator);
+
+	g_free (backend->priv->password);
+	backend->priv->password = g_strdup (password->str);
+
+	uri = cal_backend_http_ensure_uri (backend);
+	cal_backend_http_load (backend, cancellable, uri, &local_error);
+
+	if (local_error == NULL) {
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+	} else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
+		result = E_SOURCE_AUTHENTICATION_REJECTED;
+		g_clear_error (&local_error);
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		g_propagate_error (error, local_error);
+	}
+
+	return result;
+}
+
 /* Object initialization function for the file backend */
 static void
 e_cal_backend_http_init (ECalBackendHttp *cbhttp)
@@ -1403,10 +1578,10 @@ e_cal_backend_http_class_init (ECalBackendHttpClass *class)
 
 	object_class->dispose = e_cal_backend_http_dispose;
 	object_class->finalize = e_cal_backend_http_finalize;
+	object_class->constructed = e_cal_backend_http_constructed;
 
 	sync_class->get_backend_property_sync	= e_cal_backend_http_get_backend_property;
 	sync_class->open_sync			= e_cal_backend_http_open;
-	sync_class->authenticate_user_sync	= e_cal_backend_http_authenticate_user;
 	sync_class->refresh_sync		= e_cal_backend_http_refresh;
 	sync_class->remove_sync			= e_cal_backend_http_remove;
 	sync_class->create_object_sync		= e_cal_backend_http_create_object;
@@ -1422,3 +1597,10 @@ e_cal_backend_http_class_init (ECalBackendHttpClass *class)
 	backend_class->start_view		= e_cal_backend_http_start_view;
 	backend_class->internal_get_timezone	= e_cal_backend_http_internal_get_timezone;
 }
+
+static void
+e_cal_backend_http_source_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = cal_backend_http_try_password_sync;
+}
+



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