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



commit 3b091f9ddbedc8624255256104059ff783ce6dcd
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/caldav/e-cal-backend-caldav.c |  369 +++++++------
 calendar/backends/http/e-cal-backend-http.c     |  656 +++++++++++++++--------
 2 files changed, 631 insertions(+), 394 deletions(-)
---
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index fcbfecc..d81b097 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -31,6 +31,11 @@
 #include <libedataserver/e-data-server-util.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-offline.h>
+#include <libedataserver/e-source-refresh.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>
@@ -114,7 +119,7 @@ struct _ECalBackendCalDAVPrivate {
 	gchar *uri;
 
 	/* Authentication info */
-	ECredentials *credentials;
+	gchar *password;
 	gboolean auth_required;
 
 	/* object cleanup */
@@ -945,13 +950,23 @@ soup_authenticate (SoupSession *session,
                    gpointer data)
 {
 	ECalBackendCalDAV *cbdav;
+	ESourceAuthentication *auth_extension;
+	ESource *source;
+	const gchar *extension_name;
 
 	cbdav = E_CAL_BACKEND_CALDAV (data);
 
+	source = e_backend_get_source (E_BACKEND (data));
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
+
 	/* do not send same password twice, but keep it for later use */
-	if (!retrying && cbdav->priv->credentials && e_credentials_has_key (cbdav->priv->credentials, E_CREDENTIALS_KEY_USERNAME)) {
-		soup_auth_authenticate (auth, e_credentials_peek (cbdav->priv->credentials, E_CREDENTIALS_KEY_USERNAME), e_credentials_peek (cbdav->priv->credentials, E_CREDENTIALS_KEY_PASSWORD));
-		e_credentials_clear_peek (cbdav->priv->credentials);
+	if (!retrying && cbdav->priv->password != NULL) {
+		gchar *user;
+
+		user = e_source_authentication_dup_user (auth_extension);
+		soup_auth_authenticate (auth, user, cbdav->priv->password);
+		g_free (user);
 	}
 }
 
@@ -1109,37 +1124,20 @@ caldav_server_open_calendar (ECalBackendCalDAV *cbdav,
 	return FALSE;
 }
 
-static void
-caldav_notify_auth_required (ECalBackendCalDAV *cbdav)
+static gboolean
+caldav_authenticate (ECalBackendCalDAV *cbdav,
+                     GCancellable *cancellable,
+                     GError **error)
 {
-	ECredentials *credentials;
-	guint prompt_flags;
-	gchar *prompt_flags_str;
-
-	g_return_if_fail (E_IS_CAL_BACKEND_CALDAV (cbdav));
-
-	cbdav->priv->opened = FALSE;
-	update_slave_cmd (cbdav->priv, SLAVE_SHOULD_SLEEP);
-
-	if (!e_backend_get_online (E_BACKEND (cbdav)))
-		return;
-
-	if (cbdav->priv->credentials)
-		credentials = e_credentials_new_clone (cbdav->priv->credentials);
-	else
-		credentials = e_credentials_new ();
-	prompt_flags = E_CREDENTIALS_PROMPT_FLAG_REMEMBER_FOREVER
-		     | E_CREDENTIALS_PROMPT_FLAG_SECRET
-		     | E_CREDENTIALS_PROMPT_FLAG_ONLINE
-		     | E_CREDENTIALS_PROMPT_FLAG_REPROMPT;
-
-	prompt_flags_str = e_credentials_util_prompt_flags_to_string (prompt_flags);
-	e_credentials_set (credentials, E_CREDENTIALS_KEY_PROMPT_FLAGS, prompt_flags_str);
-	g_free (prompt_flags_str);
+	ESource *source;
+	ESourceRegistry *registry;
 
-	e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbdav), TRUE, credentials);
+	source = e_backend_get_source (E_BACKEND (cbdav));
+	registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbdav));
 
-	e_credentials_free (credentials);
+	return e_source_registry_authenticate_sync (
+		registry, source, E_SOURCE_AUTHENTICATOR (cbdav),
+		cancellable, error);
 }
 
 /* Returns whether calendar changed on the server. This works only when server
@@ -1199,7 +1197,7 @@ check_calendar_changed_on_server (ECalBackendCalDAV *cbdav)
 
 	/* Check the result */
 	if (message->status_code == 401) {
-		caldav_notify_auth_required (cbdav);
+		caldav_authenticate (cbdav, NULL, NULL);
 	} else if (message->status_code != 207) {
 		/* does not support it, but report calendar changed to update cache */
 		cbdav->priv->ctag_supported = FALSE;
@@ -1357,7 +1355,7 @@ caldav_server_list_objects (ECalBackendCalDAV *cbdav,
 				E_CAL_BACKEND (cbdav), cbdav->priv->read_only);
 			break;
 		case 401:
-			caldav_notify_auth_required (cbdav);
+			caldav_authenticate (cbdav, NULL, NULL);
 			break;
 		default:
 			g_warning ("Server did not response with 207, but with code %d (%s)", message->status_code, soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : "Unknown code");
@@ -1402,7 +1400,7 @@ caldav_server_download_attachment (ECalBackendCalDAV *cbdav,
 		status_code_to_result (message, cbdav->priv, error);
 
 		if (message->status_code == 401)
-			caldav_notify_auth_required (cbdav);
+			caldav_authenticate (cbdav, NULL, NULL);
 
 		g_object_unref (message);
 		return FALSE;
@@ -1444,7 +1442,7 @@ caldav_server_get_object (ECalBackendCalDAV *cbdav,
 		status_code_to_result (message, cbdav->priv, perror);
 
 		if (message->status_code == 401)
-			caldav_notify_auth_required (cbdav);
+			caldav_authenticate (cbdav, NULL, NULL);
 		else
 			g_warning ("Could not fetch object '%s' from server, status:%d (%s)", uri, message->status_code, soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : "Unknown code");
 		g_object_unref (message);
@@ -1510,7 +1508,7 @@ caldav_post_freebusy (ECalBackendCalDAV *cbdav,
 	if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
 		status_code_to_result (message, cbdav->priv, error);
 		if (message->status_code == 401)
-			caldav_notify_auth_required (cbdav);
+			caldav_authenticate (cbdav, NULL, NULL);
 		else
 			g_warning ("Could not post free/busy request to '%s', status:%d (%s)", url, message->status_code, soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : "Unknown code");
 
@@ -1697,7 +1695,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 			g_propagate_error (perror, local_error);
 		}
 	} else if (message->status_code == 401) {
-		caldav_notify_auth_required (cbdav);
+		caldav_authenticate (cbdav, NULL, NULL);
 	}
 
 	g_object_unref (message);
@@ -1736,7 +1734,7 @@ caldav_server_delete_object (ECalBackendCalDAV *cbdav,
 	status_code_to_result (message, cbdav->priv, perror);
 
 	if (message->status_code == 401)
-		caldav_notify_auth_required (cbdav);
+		caldav_authenticate (cbdav, NULL, NULL);
 
 	g_object_unref (message);
 }
@@ -1851,7 +1849,7 @@ caldav_receive_schedule_outbox_url (ECalBackendCalDAV *cbdav)
 		xmlOutputBufferClose (buf);
 		xmlFreeDoc (doc);
 	} else if (message->status_code == 401) {
-		caldav_notify_auth_required (cbdav);
+		caldav_authenticate (cbdav, NULL, NULL);
 	}
 
 	if (message)
@@ -2359,27 +2357,38 @@ maybe_append_email_domain (const gchar *username,
 static gchar *
 get_usermail (ECalBackend *backend)
 {
-	ECalBackendCalDAV        *cbdav;
+	ECalBackendCalDAV *cbdav;
 	ESource *source;
+	ESourceAuthentication *auth_extension;
+	ESourceWebdav *webdav_extension;
+	const gchar *extension_name;
+	gchar *usermail;
+	gchar *username;
 	gchar *res = NULL;
 
 	g_return_val_if_fail (backend != NULL, NULL);
 
 	source = e_backend_get_source (E_BACKEND (backend));
-	if (source) {
-		res = e_source_get_duped_property (source, "usermail");
-		if (res && *res)
-			return res;
 
-		g_free (res);
-		res = NULL;
-	}
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	webdav_extension = e_source_get_extension (source, extension_name);
+
+	/* This will never return an empty string. */
+	usermail = e_source_webdav_dup_email_address (webdav_extension);
+
+	if (usermail != NULL)
+		return usermail;
 
 	cbdav = E_CAL_BACKEND_CALDAV (backend);
 
-	if (cbdav->priv->is_google && cbdav->priv->credentials) {
-		res = maybe_append_email_domain (e_credentials_peek (cbdav->priv->credentials, E_CREDENTIALS_KEY_USERNAME), "@gmail.com");
-	}
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
+	username = e_source_authentication_dup_user (auth_extension);
+
+	if (cbdav->priv && cbdav->priv->is_google)
+		res = maybe_append_email_domain (username, "@gmail.com");
+
+	g_free (username);
 
 	return res;
 }
@@ -2401,9 +2410,11 @@ caldav_get_backend_property (ECalBackendSync *backend,
 	g_return_val_if_fail (prop_value != NULL, FALSE);
 
 	if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
+		ESourceWebdav *extension;
 		ESource *source;
 		GString *caps;
 		gchar *usermail;
+		const gchar *extension_name;
 
 		caps = g_string_new (CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
 				     CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
@@ -2415,12 +2426,13 @@ caldav_get_backend_property (ECalBackendSync *backend,
 		g_free (usermail);
 
 		source = e_backend_get_source (E_BACKEND (backend));
-		if (source) {
-			const gchar *prop = e_source_get_property (source, "autoschedule");
 
-			if (prop && g_str_equal (prop, "1"))
-				g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
-						       "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
+		extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+		extension = e_source_get_extension (source, extension_name);
+
+		if (e_source_webdav_get_calendar_auto_schedule (extension)) {
+			g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
+					       "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
 		}
 
 		*prop_value = g_string_free (caps, FALSE);
@@ -2461,79 +2473,71 @@ static gboolean
 initialize_backend (ECalBackendCalDAV *cbdav,
                     GError **perror)
 {
+	ESourceAuthentication    *auth_extension;
+	ESourceOffline           *offline_extension;
+	ESourceRefresh           *refresh_extension;
+	ESourceWebdav            *webdav_extension;
 	ECalBackend              *backend;
+	SoupURI                  *soup_uri;
 	ESource                  *source;
-	const gchar		 *os_val;
-	gchar			 *uri;
 	gsize                     len;
-	const gchar              *refresh;
 	const gchar              *cache_dir;
+	const gchar              *extension_name;
+	guint                     interval_in_minutes;
 
 	backend = E_CAL_BACKEND (cbdav);
 	cache_dir = e_cal_backend_get_cache_dir (backend);
 	source = e_backend_get_source (E_BACKEND (backend));
-	uri = e_source_get_uri (source);
-
-	if (!g_signal_handler_find (G_OBJECT (source), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, caldav_source_changed_cb, cbdav))
-		g_signal_connect (G_OBJECT (source), "changed", G_CALLBACK (caldav_source_changed_cb), cbdav);
 
-	os_val = e_source_get_property (source, "offline_sync");
-	cbdav->priv->do_offline = os_val && g_str_equal (os_val, "1");
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
 
-	os_val = e_source_get_property (source, "auth");
-	cbdav->priv->auth_required = os_val != NULL;
+	extension_name = E_SOURCE_EXTENSION_OFFLINE;
+	offline_extension = e_source_get_extension (source, extension_name);
 
-	os_val = e_source_get_property(source, "ssl");
+	extension_name = E_SOURCE_EXTENSION_REFRESH;
+	refresh_extension = e_source_get_extension (source, extension_name);
 
-	g_free (cbdav->priv->uri);
-	cbdav->priv->uri = NULL;
-	if (g_str_has_prefix (uri, "caldav://")) {
-		const gchar *proto;
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	webdav_extension = e_source_get_extension (source, extension_name);
 
-		if (os_val && os_val[0] == '1') {
-			proto = "https://";;
-		} else {
-			proto = "http://";;
-		}
+	if (!g_signal_handler_find (G_OBJECT (source), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, 0, 0, NULL, caldav_source_changed_cb, cbdav))
+		g_signal_connect (G_OBJECT (source), "changed", G_CALLBACK (caldav_source_changed_cb), cbdav);
 
-		cbdav->priv->uri = g_strconcat (proto, uri + 9, NULL);
+	cbdav->priv->do_offline = e_source_offline_get_stay_synchronized (offline_extension);
 
-		g_free (uri);
-	} else {
-		cbdav->priv->uri = uri;
-	}
+	cbdav->priv->auth_required = e_source_authentication_required (auth_extension);
 
-	if (cbdav->priv->uri) {
-		SoupURI *suri = soup_uri_new (cbdav->priv->uri);
+	soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
 
-		/* properly encode uri */
-		if (suri && suri->path) {
-			gchar *tmp, *path;
+	/* properly encode uri */
+	if (soup_uri != NULL && soup_uri->path != NULL) {
+		gchar *tmp, *path;
 
-			if (suri->path && strchr (suri->path, '%')) {
-				/* If path contains anything already encoded, then decode it first,
-				 * thus it'll be managed properly. For example, the '#' in a path
-				 * is in URI shown as %23 and not doing this decode makes it being
-				 * like %2523, which is not what is wanted here. */
-				tmp = soup_uri_decode (suri->path);
-				soup_uri_set_path (suri, tmp);
-				g_free (tmp);
-			}
+		if (strchr (soup_uri->path, '%')) {
+			/* If path contains anything already encoded, then
+			 * decode it first, thus it'll be managed properly.
+			 * For example, the '#' in a path is in URI shown as
+			 * %23 and not doing this decode makes it being like
+			 * %2523, which is not what is wanted here. */
+			tmp = soup_uri_decode (soup_uri->path);
+			soup_uri_set_path (soup_uri, tmp);
+			g_free (tmp);
+		}
 
-			tmp = soup_uri_encode (suri->path, NULL);
-			path = soup_uri_normalize (tmp, "/");
+		tmp = soup_uri_encode (soup_uri->path, NULL);
+		path = soup_uri_normalize (tmp, "/");
 
-			soup_uri_set_path (suri, path);
+		soup_uri_set_path (soup_uri, path);
 
-			g_free (tmp);
-			g_free (path);
-			g_free (cbdav->priv->uri);
+		g_free (tmp);
+		g_free (path);
+	}
 
-			cbdav->priv->uri = soup_uri_to_string (suri, FALSE);
-		}
+	g_free (cbdav->priv->uri);
+	cbdav->priv->uri = soup_uri_to_string (soup_uri, FALSE);
 
-		soup_uri_free (suri);
-	}
+	soup_uri_free (soup_uri);
 
 	g_return_val_if_fail (cbdav->priv->uri != NULL, FALSE);
 
@@ -2577,8 +2581,14 @@ initialize_backend (ECalBackendCalDAV *cbdav,
 		return FALSE;
 	}
 
-	refresh = e_source_get_property (source, "refresh");
-	cbdav->priv->refresh_time.tv_sec  = (refresh && atoi (refresh) > 0) ? (60 * atoi (refresh)) : (DEFAULT_REFRESH_TIME);
+	/* FIXME Not honoring ESourceRefresh:enabled. */
+	interval_in_minutes =
+		e_source_refresh_get_interval_minutes (refresh_extension);
+
+	if (interval_in_minutes == 0)
+		cbdav->priv->refresh_time.tv_sec = DEFAULT_REFRESH_TIME;
+	else
+		cbdav->priv->refresh_time.tv_sec = interval_in_minutes * 60;
 
 	if (!cbdav->priv->synch_slave) {
 		GThread *slave;
@@ -2624,15 +2634,6 @@ open_calendar (ECalBackendCalDAV *cbdav,
 
 	g_return_val_if_fail (cbdav != NULL, FALSE);
 
-	if (cbdav->priv->session) {
-		ESource *source = e_backend_get_source (E_BACKEND (cbdav));
-
-		g_object_set (G_OBJECT (cbdav->priv->session),
-			SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-			g_strcmp0 (e_source_get_property (source, "ignore-invalid-cert"), "1") != 0,
-			NULL);
-	}
-
 	/* set forward proxy */
 	proxy_settings_changed (cbdav->priv->proxy, cbdav->priv);
 
@@ -2704,8 +2705,8 @@ caldav_do_open (ECalBackendSync *backend,
 
 		if (g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationRequired) || g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationFailed)) {
 			g_clear_error (&local_error);
-			e_cal_backend_notify_auth_required (E_CAL_BACKEND (cbdav), TRUE, cbdav->priv->credentials);
-			opened = FALSE;
+			opened = caldav_authenticate (
+				cbdav, cancellable, perror);
 		}
 
 		if (local_error != NULL)
@@ -2726,34 +2727,6 @@ caldav_do_open (ECalBackendSync *backend,
 }
 
 static void
-caldav_authenticate_user (ECalBackendSync *backend,
-                          GCancellable *cancellable,
-                          ECredentials *credentials,
-                          GError **error)
-{
-	ECalBackendCalDAV        *cbdav;
-
-	cbdav = E_CAL_BACKEND_CALDAV (backend);
-
-	g_mutex_lock (cbdav->priv->busy_lock);
-
-	e_credentials_free (cbdav->priv->credentials);
-	cbdav->priv->credentials = NULL;
-
-	if (!credentials || !e_credentials_has_key (credentials, E_CREDENTIALS_KEY_USERNAME)) {
-		g_mutex_unlock (cbdav->priv->busy_lock);
-		g_propagate_error (error, EDC_ERROR (AuthenticationRequired));
-		return;
-	}
-
-	cbdav->priv->credentials = e_credentials_new_clone (credentials);
-
-	open_calendar (cbdav, error);
-
-	g_mutex_unlock (cbdav->priv->busy_lock);
-}
-
-static void
 caldav_refresh (ECalBackendSync *backend,
                 EDataCal *cal,
                 GCancellable *cancellable,
@@ -4104,6 +4077,7 @@ process_object (ECalBackendCalDAV *cbdav,
                 icalproperty_method method,
                 GError **error)
 {
+	ESourceRegistry *registry;
 	ECalBackend              *backend;
 	struct icaltimetype       now;
 	gchar *new_obj_str;
@@ -4116,6 +4090,8 @@ process_object (ECalBackendCalDAV *cbdav,
 
 	e_return_data_cal_error_if_fail (id != NULL, InvalidObject);
 
+	registry = e_cal_backend_get_registry (E_CAL_BACKEND (cbdav));
+
 	/* ctime, mtime */
 	now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
 	e_cal_component_set_created (ecomp, &now);
@@ -4132,7 +4108,7 @@ process_object (ECalBackendCalDAV *cbdav,
 	case ICAL_METHOD_REQUEST:
 	case ICAL_METHOD_REPLY:
 		is_declined = e_cal_backend_user_declined (
-			e_cal_component_get_icalcomponent (ecomp));
+			registry, e_cal_component_get_icalcomponent (ecomp));
 		if (is_in_cache) {
 			if (!is_declined) {
 				GSList *new_components = NULL, *old_components = NULL;
@@ -4579,11 +4555,15 @@ caldav_get_free_busy (ECalBackendSync *backend,
 	icalcomponent *icalcomp;
 	ECalComponent *comp;
 	ECalComponentDateTime dt;
+	ECalComponentOrganizer organizer = {NULL};
+	ESourceAuthentication *auth_extension;
+	ESource *source;
 	struct icaltimetype dtvalue;
 	icaltimezone *utc;
 	gchar *str;
 	const GSList *u;
 	GSList *attendees = NULL, *to_free = NULL;
+	const gchar *extension_name;
 	gchar *usermail;
 	GError *err = NULL;
 
@@ -4633,16 +4613,16 @@ caldav_get_free_busy (ECalBackendSync *backend,
 		usermail = NULL;
 	}
 
-	if ((cbdav->priv->credentials && e_credentials_has_key (cbdav->priv->credentials, E_CREDENTIALS_KEY_USERNAME)) || usermail) {
-		ECalComponentOrganizer organizer = {NULL};
-
-		organizer.value = usermail ? usermail : e_credentials_peek (cbdav->priv->credentials, E_CREDENTIALS_KEY_USERNAME);
-		organizer.value = g_strconcat ("mailto:";, organizer.value, NULL);
+	source = e_backend_get_source (E_BACKEND (backend));
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
 
-		e_cal_component_set_organizer (comp, &organizer);
+	if (usermail == NULL)
+		usermail = e_source_authentication_dup_user (auth_extension);
 
-		g_free ((gchar *) organizer.value);
-	}
+	organizer.value = g_strconcat ("mailto:";, usermail, NULL);
+	e_cal_component_set_organizer (comp, &organizer);
+	g_free ((gchar *) organizer.value);
 
 	g_free (usermail);
 
@@ -4834,13 +4814,54 @@ caldav_source_changed_cb (ESource *source,
 	}
 }
 
+static ESourceAuthenticationResult
+caldav_try_password_sync (ESourceAuthenticator *authenticator,
+                          const GString *password,
+                          GCancellable *cancellable,
+                          GError **error)
+{
+	ECalBackendCalDAV *cbdav;
+	ESourceAuthenticationResult result;
+	GError *local_error = NULL;
+
+	cbdav = E_CAL_BACKEND_CALDAV (authenticator);
+
+	/* Busy lock is already acquired by caldav_do_open(). */
+
+	g_free (cbdav->priv->password);
+	cbdav->priv->password = g_strdup (password->str);
+
+	open_calendar (cbdav, &local_error);
+
+	if (local_error == NULL) {
+		result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+	} else if (g_error_matches (local_error, E_DATA_CAL_ERROR, AuthenticationFailed)) {
+		result = E_SOURCE_AUTHENTICATION_REJECTED;
+		g_clear_error (&local_error);
+	} else {
+		result = E_SOURCE_AUTHENTICATION_ERROR;
+		g_propagate_error (error, local_error);
+	}
+
+	return result;
+}
+
+static void
+caldav_source_authenticator_init (ESourceAuthenticatorInterface *interface)
+{
+	interface->try_password_sync = caldav_try_password_sync;
+}
+
 /* ************************************************************************* */
 /* ***************************** GObject Foo ******************************* */
 
-G_DEFINE_TYPE (
+G_DEFINE_TYPE_WITH_CODE (
 	ECalBackendCalDAV,
 	e_cal_backend_caldav,
-	E_TYPE_CAL_BACKEND_SYNC)
+	E_TYPE_CAL_BACKEND_SYNC,
+	G_IMPLEMENT_INTERFACE (
+		E_TYPE_SOURCE_AUTHENTICATOR,
+		caldav_source_authenticator_init))
 
 static void
 e_cal_backend_caldav_dispose (GObject *object)
@@ -4876,9 +4897,6 @@ e_cal_backend_caldav_dispose (GObject *object)
 	g_object_unref (priv->session);
 	g_object_unref (priv->proxy);
 
-	e_credentials_free (priv->credentials);
-	priv->credentials = NULL;
-
 	g_free (priv->uri);
 	g_free (priv->schedule_outbox_url);
 
@@ -4904,11 +4922,38 @@ e_cal_backend_caldav_finalize (GObject *object)
 	g_cond_free (priv->cond);
 	g_cond_free (priv->slave_gone_cond);
 
+	g_free (priv->password);
+
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static void
+cal_backend_caldav_constructed (GObject *object)
+{
+	ESource *source;
+	ESourceWebdav *extension;
+	ECalBackendCalDAV *cbdav;
+	const gchar *extension_name;
+
+	cbdav = E_CAL_BACKEND_CALDAV (object);
+
+	source = e_backend_get_source (E_BACKEND (cbdav));
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	extension = e_source_get_extension (source, extension_name);
+
+	g_object_bind_property (
+		extension, "ignore-invalid-cert",
+		cbdav->priv->session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_INVERT_BOOLEAN);
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_cal_backend_caldav_parent_class)->
+		constructed (object);
+}
+
+static void
 e_cal_backend_caldav_init (ECalBackendCalDAV *cbdav)
 {
 	cbdav->priv = E_CAL_BACKEND_CALDAV_GET_PRIVATE (cbdav);
@@ -4972,11 +5017,11 @@ e_cal_backend_caldav_class_init (ECalBackendCalDAVClass *class)
 
 	object_class->dispose  = e_cal_backend_caldav_dispose;
 	object_class->finalize = e_cal_backend_caldav_finalize;
+	object_class->constructed = cal_backend_caldav_constructed;
 
 	sync_class->get_backend_property_sync	= caldav_get_backend_property;
 
 	sync_class->open_sync			= caldav_do_open;
-	sync_class->authenticate_user_sync	= caldav_authenticate_user;
 	sync_class->refresh_sync		= caldav_refresh;
 	sync_class->remove_sync			= caldav_remove;
 
diff --git a/calendar/backends/http/e-cal-backend-http.c b/calendar/backends/http/e-cal-backend-http.c
index c9e8f08..0b0ada1 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>
@@ -46,10 +51,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 (
+/* 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)
+	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 {
@@ -72,14 +84,40 @@ struct _ECalBackendHttpPrivate {
 	gboolean opened;
 	gboolean requires_auth;
 
-	ECredentials *credentials;
+	gchar *password;
 };
 
 #define d(x)
 
-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 void
+soup_authenticate (SoupSession *session,
+                   SoupMessage *msg,
+                   SoupAuth *auth,
+                   gboolean retrying,
+                   gpointer data)
+{
+	ECalBackendHttp *cbhttp;
+	ESourceAuthentication *auth_extension;
+	ESource *source;
+	const gchar *extension_name;
+
+	cbhttp = E_CAL_BACKEND_HTTP (data);
+
+	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 && cbhttp->priv->password != NULL) {
+		gchar *user;
+
+		user = e_source_authentication_dup_user (auth_extension);
+		soup_auth_authenticate (auth, user, cbhttp->priv->password);
+		g_free (user);
+	}
+}
+
 /* Dispose handler for the file backend */
 static void
 e_cal_backend_http_dispose (GObject *object)
@@ -100,10 +138,6 @@ 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)),
@@ -131,11 +165,55 @@ e_cal_backend_http_finalize (GObject *object)
 	}
 
 	g_free (priv->uri);
+	g_free (priv->password);
 
 	/* Chain up to parent's finalize() method. */
 	G_OBJECT_CLASS (e_cal_backend_http_parent_class)->finalize (object);
 }
 
+static void
+e_cal_backend_http_constructed (GObject *object)
+{
+	ESource *source;
+	ECalBackendHttp *backend;
+	ESourceWebdav *extension;
+	SoupSession *soup_session;
+	const gchar *extension_name;
+
+	/* Chain up to parent's constructed() method. */
+	G_OBJECT_CLASS (e_cal_backend_http_parent_class)->constructed (object);
+
+	soup_session = soup_session_sync_new ();
+
+	backend = E_CAL_BACKEND_HTTP (object);
+	backend->priv->soup_session = soup_session;
+
+	source = e_backend_get_source (E_BACKEND (backend));
+	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+	extension = e_source_get_extension (source, extension_name);
+
+	g_object_bind_property (
+		extension, "ignore-invalid-cert",
+		soup_session, SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
+		G_BINDING_SYNC_CREATE |
+		G_BINDING_INVERT_BOOLEAN);
+
+	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 */
 
 static gboolean
@@ -335,56 +413,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)) {
+	if (SOUP_STATUS_IS_REDIRECTION (status_code)) {
+		gboolean success;
+
 		newuri = soup_message_headers_get (
-			msg->response_headers, "Location");
+			soup_message->response_headers, "Location");
 
-		d(g_message ("Redirected from %s to %s\n", priv->uri, newuri));
+		d(g_message ("Redirected from %s to %s\n", async_context->uri, newuri));
 
 		if (newuri != NULL) {
+			gchar *redirected_uri;
+
 			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); */
@@ -394,42 +543,39 @@ 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;
+
+		etag = soup_message_headers_get_one (
+			soup_message->response_headers, "ETag");
 
 		if (etag != NULL && *etag == '\0')
 			etag = NULL;
@@ -438,25 +584,32 @@ retrieval_done (SoupSession *session,
 	}
 
 	/* 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);
 
@@ -472,7 +625,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) {
@@ -496,18 +649,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);
 				}
 			}
 
@@ -528,7 +681,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 */
@@ -536,123 +689,112 @@ 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");
-		gchar *uri = e_source_get_uri (source);
+	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 (uri,
-			(secure_prop && g_str_equal(secure_prop, "1")));
+	g_object_set (
+		G_OBJECT (backend->priv->soup_session),
+		SOUP_SESSION_PROXY_URI, soup_uri, NULL);
 
-		g_free (uri);
-	}
+	g_object_unref (proxy);
 
-	/* create the Soup session if not already created */
-	if (!priv->soup_session) {
-		EProxy *proxy;
-		SoupURI *proxy_uri = NULL;
-		ESource *source = e_backend_get_source (E_BACKEND (cbhttp));
+	return backend->priv->uri;
+}
 
-		priv->soup_session = soup_session_async_new_with_options (
-			SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-			g_strcmp0 (e_source_get_property (source, "ignore-invalid-cert"), "1") != 0,
-			NULL);
+static void     maybe_start_reload_timeout (ECalBackendHttp *cbhttp);
 
-		g_signal_connect (priv->soup_session, "authenticate",
-				  G_CALLBACK (soup_authenticate), cbhttp);
+static gboolean
+begin_retrieval_cb (GIOSchedulerJob *job,
+                    GCancellable *cancellable,
+                    ECalBackendHttp *backend)
+{
+	ESource *source;
+	ESourceRegistry *registry;
+	const gchar *uri;
+	GError *error = NULL;
 
-		if (g_getenv ("WEBCAL_DEBUG") != NULL) {
-			SoupLogger *logger;
+	if (!e_backend_get_online (E_BACKEND (backend)))
+		return FALSE;
 
-			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);
-		}
+	maybe_start_reload_timeout (backend);
 
-		/* 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);
-		}
+	if (backend->priv->is_loading)
+		return FALSE;
 
-		g_object_set (G_OBJECT (priv->soup_session), SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
+	d(g_message ("Starting retrieval...\n"));
 
-		g_object_unref (proxy);
-	}
+	backend->priv->is_loading = TRUE;
 
-	/* 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;
+	source = e_backend_get_source (E_BACKEND (backend));
+	registry = e_cal_backend_get_registry (E_CAL_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_registry_authenticate_sync (
+			registry, 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;
 }
 
@@ -669,7 +811,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;
 }
 
@@ -678,7 +826,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;
 
@@ -693,10 +843,17 @@ 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);
 
-	priv->reload_timeout_id = g_timeout_add ((refresh_str ? atoi (refresh_str) : 30) * 60000,
-						 (GSourceFunc) reload_cb, cbhttp);
+	if (e_source_refresh_get_enabled (extension))
+		interval_in_minutes =
+			e_source_refresh_get_interval_minutes (extension);
+
+	if (interval_in_minutes > 0)
+		priv->reload_timeout_id = g_timeout_add_seconds (
+			interval_in_minutes * 60,
+			(GSourceFunc) reload_cb, cbhttp);
 }
 
 static void
@@ -706,27 +863,27 @@ source_changed_cb (ESource *source,
 	g_return_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp));
 
 	if (cbhttp->priv->uri != NULL) {
-		ESource *source;
-		const gchar *secure_prop;
-		gchar *new_uri;
+		gboolean uri_changed;
+		const gchar *new_uri;
+		gchar *old_uri;
 
-		source = e_backend_get_source (E_BACKEND (cbhttp));
-		secure_prop = e_source_get_property (source, "use_ssl");
+		old_uri = g_strdup (cbhttp->priv->uri);
 
-		new_uri = webcal_to_http_method (
-			e_source_get_uri (source),
-			(secure_prop && g_str_equal(secure_prop, "1")));
+		g_free (cbhttp->priv->uri);
+		cbhttp->priv->uri = NULL;
 
-		if (new_uri && !g_str_equal (cbhttp->priv->uri, new_uri)) {
-			/* uri changed, do reload some time soon */
-			g_free (cbhttp->priv->uri);
-			cbhttp->priv->uri = NULL;
+		new_uri = cal_backend_http_ensure_uri (cbhttp);
 
-			if (!cbhttp->priv->is_loading)
-				g_idle_add ((GSourceFunc) begin_retrieval_cb, cbhttp);
-		}
+		uri_changed = (g_strcmp0 (old_uri, new_uri) != 0);
+
+		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);
 	}
 }
 
@@ -741,6 +898,12 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	ECalBackendHttp *cbhttp;
 	ECalBackendHttpPrivate *priv;
 	ESource *source;
+	ESourceRegistry *registry;
+	ESourceAuthentication *auth_extension;
+	const gchar *extension_name;
+	const gchar *cache_dir;
+	gboolean auth_required;
+	gboolean opened = TRUE;
 	gboolean online;
 	gchar *tmp;
 
@@ -754,6 +917,13 @@ 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));
+
+	registry = e_cal_backend_get_registry (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 (
@@ -767,10 +937,6 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	g_free (tmp);
 
 	if (priv->store == NULL) {
-		const gchar *cache_dir;
-
-		cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));
-
 		/* 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);
@@ -794,54 +960,34 @@ e_cal_backend_http_open (ECalBackendSync *backend,
 	e_cal_backend_notify_online (E_CAL_BACKEND (backend), online);
 
 	if (online) {
-		if (priv->soup_session)
-			g_object_set (G_OBJECT (priv->soup_session),
-				SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE,
-				g_strcmp0 (e_source_get_property (source, "ignore-invalid-cert"), "1") != 0,
-				NULL);
-
-		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_registry_authenticate_sync (
+				registry, 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 +1055,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)
@@ -1230,6 +1380,7 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
                                   GSList **freebusy,
                                   GError **error)
 {
+	ESourceRegistry *registry;
 	ECalBackendHttp *cbhttp;
 	ECalBackendHttpPrivate *priv;
 	gchar *address, *name;
@@ -1247,8 +1398,10 @@ e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
 		return;
 	}
 
+	registry = e_cal_backend_get_registry (E_CAL_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);
@@ -1260,7 +1413,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);
@@ -1364,6 +1517,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)
@@ -1393,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_objects_sync		= e_cal_backend_http_create_objects;
@@ -1412,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]