[evolution-data-server/account-mgmt: 26/38] Add an ESource extension for the caldav backend.



commit b5ed266f908bfcd4590d57e28731dac425b5daf3
Author: Matthew Barnes <mbarnes redhat com>
Date:   Tue Nov 23 20:23:52 2010 -0500

    Add an ESource extension for the caldav backend.

 calendar/backends/caldav/Makefile.am               |    4 +-
 .../backends/caldav/e-cal-backend-caldav-factory.c |    2 +
 calendar/backends/caldav/e-cal-backend-caldav.c    |  395 +++++++++++---------
 calendar/backends/caldav/e-source-caldav.c         |  231 ++++++++++++
 calendar/backends/caldav/e-source-caldav.h         |   72 ++++
 5 files changed, 529 insertions(+), 175 deletions(-)
---
diff --git a/calendar/backends/caldav/Makefile.am b/calendar/backends/caldav/Makefile.am
index 5ecd526..e72d446 100644
--- a/calendar/backends/caldav/Makefile.am
+++ b/calendar/backends/caldav/Makefile.am
@@ -14,7 +14,9 @@ libecalbackendcaldav_la_CPPFLAGS = \
 libecalbackendcaldav_la_SOURCES = \
 	e-cal-backend-caldav-factory.c \
 	e-cal-backend-caldav.c \
-	e-cal-backend-caldav.h
+	e-cal-backend-caldav.h \
+	e-source-caldav.c \
+	e-source-caldav.h
 
 libecalbackendcaldav_la_LIBADD = \
 	$(top_builddir)/calendar/libedata-cal/libedata-cal-1.2.la \
diff --git a/calendar/backends/caldav/e-cal-backend-caldav-factory.c b/calendar/backends/caldav/e-cal-backend-caldav-factory.c
index ef6cab4..99adadb 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav-factory.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav-factory.c
@@ -26,6 +26,7 @@
 
 #include <libedata-cal/e-cal-backend-factory.h>
 #include "e-cal-backend-caldav.h"
+#include "e-source-caldav.h"
 
 #define FACTORY_NAME "caldav"
 
@@ -119,6 +120,7 @@ e_cal_backend_caldav_todos_factory_init (ECalBackendFactory *factory)
 G_MODULE_EXPORT void
 e_module_load (GTypeModule *type_module)
 {
+	e_source_caldav_type_register (type_module);
 	e_cal_backend_caldav_events_factory_register_type (type_module);
 	e_cal_backend_caldav_journal_factory_register_type (type_module);
 	e_cal_backend_caldav_todos_factory_register_type (type_module);
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index 8df9121..13121df 100644
--- a/calendar/backends/caldav/e-cal-backend-caldav.c
+++ b/calendar/backends/caldav/e-cal-backend-caldav.c
@@ -31,6 +31,10 @@
 #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 <libecal/e-cal-recur.h>
 #include <libecal/e-cal-util.h>
 #include <libecal/e-cal-time-util.h>
@@ -49,6 +53,7 @@
 #include <libsoup/soup.h>
 
 #include "e-cal-backend-caldav.h"
+#include "e-source-caldav.h"
 
 #define d(x)
 
@@ -114,7 +119,7 @@ struct _ECalBackendCalDAVPrivate {
 	gchar *uri;
 
 	/* Authentication info */
-	ECredentials *credentials;
+	gchar *password;
 	gboolean auth_required;
 
 	/* object cleanup */
@@ -932,13 +937,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);
 	}
 }
 
@@ -1096,38 +1111,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 (cbdav != NULL);
-	g_return_if_fail (cbdav->priv != NULL);
-
-	cbdav->priv->opened = FALSE;
-	cbdav->priv->slave_cmd = 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_backend_get_registry (E_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
@@ -1187,7 +1184,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;
@@ -1345,7 +1342,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");
@@ -1391,7 +1388,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;
@@ -1433,7 +1430,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);
@@ -1499,7 +1496,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");
 
@@ -1623,7 +1620,7 @@ caldav_server_put_object (ECalBackendCalDAV *cbdav,
 				icalcomponent_free (use_comp);
 		}
 	} else if (message->status_code == 401) {
-		caldav_notify_auth_required (cbdav);
+		caldav_authenticate (cbdav, NULL, NULL);
 	}
 
 	g_object_unref (message);
@@ -1662,7 +1659,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);
 }
@@ -1779,7 +1776,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)
@@ -2287,27 +2284,38 @@ maybe_append_email_domain (const gchar *username,
 static gchar *
 get_usermail (ECalBackend *backend)
 {
-	ECalBackendCalDAV        *cbdav;
+	ECalBackendCalDAV *cbdav;
 	ESource *source;
+	ESourceAuthentication *auth_extension;
+	ESourceCaldav *caldav_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_CALDAV_BACKEND;
+	caldav_extension = e_source_get_extension (source, extension_name);
+
+	/* This will never return an empty string. */
+	usermail = e_source_caldav_dup_email (caldav_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;
 }
@@ -2329,9 +2337,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)) {
+		ESourceCaldav *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 ","
@@ -2343,12 +2353,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_CALDAV_BACKEND;
+		extension = e_source_get_extension (source, extension_name);
+
+		if (e_source_caldav_get_autoschedule (extension)) {
+			g_string_append (caps, "," CAL_STATIC_CAPABILITY_CREATE_MESSAGES
+					       "," CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
 		}
 
 		*prop_value = g_string_free (caps, FALSE);
@@ -2389,92 +2400,84 @@ static gboolean
 initialize_backend (ECalBackendCalDAV *cbdav,
                     GError **perror)
 {
+	ESourceAuthentication    *auth_extension;
+	ESourceCaldav            *caldav_extension;
+	ESourceOffline           *offline_extension;
+	ESourceRefresh           *refresh_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");
+	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+	auth_extension = e_source_get_extension (source, extension_name);
 
-	if (!os_val || !g_str_equal (os_val, "1")) {
-		cbdav->priv->do_offline = FALSE;
-	}
+	extension_name = E_SOURCE_EXTENSION_CALDAV_BACKEND;
+	caldav_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;
+	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);
 
-		if (os_val && os_val[0] == '1') {
-			proto = "https://";;
-		} else {
-			proto = "http://";;
-		}
+	cbdav->priv->do_offline = e_source_offline_get_stay_synchronized (offline_extension);
 
-		cbdav->priv->uri = g_strconcat (proto, uri + 9, NULL);
+	cbdav->priv->auth_required = e_source_authentication_required (auth_extension);
 
-		g_free (uri);
-	} else {
-		cbdav->priv->uri = uri;
-	}
+	soup_uri = e_source_webdav_dup_soup_uri (
+		E_SOURCE_WEBDAV (caldav_extension));
 
-	if (cbdav->priv->uri) {
-		SoupURI *suri = soup_uri_new (cbdav->priv->uri);
+	/* properly encode uri */
+	if (soup_uri != NULL && soup_uri->path != NULL) {
+		gchar *tmp, *path;
 
-		/* properly encode uri */
-		if (suri && suri->path) {
-			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);
 
 	/* remove trailing slashes... */
-	len = strlen (cbdav->priv->uri);
-	while (len--) {
-		if (cbdav->priv->uri[len] == '/') {
-			cbdav->priv->uri[len] = '\0';
-		} else {
-			break;
+	if (cbdav->priv->uri != NULL) {
+		len = strlen (cbdav->priv->uri);
+		while (len--) {
+			if (cbdav->priv->uri[len] == '/') {
+				cbdav->priv->uri[len] = '\0';
+			} else {
+				break;
+			}
 		}
 	}
 
@@ -2506,8 +2509,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;
@@ -2543,19 +2552,23 @@ proxy_settings_changed (EProxy *proxy,
 	g_object_set (priv->session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
 }
 
-static void
+static gboolean
 open_calendar (ECalBackendCalDAV *cbdav,
                GError **error)
 {
 	gboolean server_unreachable = FALSE;
+	gboolean success;
 	GError *local_error = NULL;
 
-	g_return_if_fail (cbdav != NULL);
+	g_return_val_if_fail (cbdav != NULL, FALSE);
 
 	/* set forward proxy */
 	proxy_settings_changed (cbdav->priv->proxy, cbdav->priv);
 
-	if (caldav_server_open_calendar (cbdav, &server_unreachable, &local_error)) {
+	success = caldav_server_open_calendar (
+		cbdav, &server_unreachable, &local_error);
+
+	if (success) {
 		cbdav->priv->slave_cmd = SLAVE_SHOULD_WORK;
 		g_cond_signal (cbdav->priv->cond);
 
@@ -2568,10 +2581,14 @@ open_calendar (ECalBackendCalDAV *cbdav,
 			e_cal_backend_notify_error (E_CAL_BACKEND (cbdav), msg);
 			g_free (msg);
 			g_clear_error (&local_error);
+			success = TRUE;
 		}
-	} else if (local_error) {
-		g_propagate_error (error, local_error);
 	}
+
+	if (local_error != NULL)
+		g_propagate_error (error, local_error);
+
+	return success;
 }
 
 static void
@@ -2582,6 +2599,7 @@ caldav_do_open (ECalBackendSync *backend,
                 GError **perror)
 {
 	ECalBackendCalDAV        *cbdav;
+	gboolean opened = TRUE;
 	gboolean online;
 
 	cbdav = E_CAL_BACKEND_CALDAV (backend);
@@ -2611,52 +2629,27 @@ caldav_do_open (ECalBackendSync *backend,
 	if (online) {
 		GError *local_error = NULL;
 
-		open_calendar (cbdav, &local_error);
+		opened = open_calendar (cbdav, &local_error);
 
 		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);
-		} else {
-			e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
+			opened = caldav_authenticate (
+				cbdav, cancellable, perror);
 		}
 
-		if (local_error)
+		if (local_error != NULL)
 			g_propagate_error (perror, local_error);
+
 	} else {
 		cbdav->priv->read_only = TRUE;
-		e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
 	}
 
-	e_cal_backend_notify_readonly (E_CAL_BACKEND (backend), cbdav->priv->read_only);
-	e_cal_backend_notify_online (E_CAL_BACKEND (backend), online);
-
-	g_mutex_unlock (cbdav->priv->busy_lock);
-}
-
-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);
+	if (opened)
+		e_cal_backend_notify_opened (E_CAL_BACKEND (backend), NULL);
 
-	open_calendar (cbdav, error);
+	e_cal_backend_notify_readonly (
+		E_CAL_BACKEND (backend), cbdav->priv->read_only);
+	e_cal_backend_notify_online (E_CAL_BACKEND (backend), online);
 
 	g_mutex_unlock (cbdav->priv->busy_lock);
 }
@@ -4013,6 +4006,7 @@ process_object (ECalBackendCalDAV *cbdav,
                 icalproperty_method method,
                 GError **error)
 {
+	ESourceRegistry *registry;
 	ECalBackend              *backend;
 	struct icaltimetype       now;
 	gchar *new_obj_str;
@@ -4025,6 +4019,8 @@ process_object (ECalBackendCalDAV *cbdav,
 
 	e_return_data_cal_error_if_fail (id != NULL, InvalidObject);
 
+	registry = e_backend_get_registry (E_BACKEND (cbdav));
+
 	/* ctime, mtime */
 	now = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
 	e_cal_component_set_created (ecomp, &now);
@@ -4040,7 +4036,8 @@ process_object (ECalBackendCalDAV *cbdav,
 	case ICAL_METHOD_PUBLISH:
 	case ICAL_METHOD_REQUEST:
 	case ICAL_METHOD_REPLY:
-		is_declined = e_cal_backend_user_declined (e_cal_component_get_icalcomponent (ecomp));
+		is_declined = e_cal_backend_user_declined (
+			registry, e_cal_component_get_icalcomponent (ecomp));
 		if (is_in_cache) {
 			if (!is_declined) {
 				GSList *new_components = NULL, *old_components = NULL;
@@ -4487,11 +4484,16 @@ 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, *usermail;
+	gchar *str;
 	const GSList *u;
 	GSList *attendees = NULL, *to_free = NULL;
+	const gchar *extension_name;
+	gchar *usermail;
 	GError *err = NULL;
 
 	cbdav = E_CAL_BACKEND_CALDAV (backend);
@@ -4535,21 +4537,21 @@ caldav_get_free_busy (ECalBackendSync *backend,
 	e_cal_component_set_dtend (comp, &dt);
 
 	usermail = get_usermail (E_CAL_BACKEND (backend));
-	if (usermail && !*usermail) {
+	if (usermail != NULL && *usermail == '\0') {
 		g_free (usermail);
 		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);
 
@@ -4741,10 +4743,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 (ECalBackendCalDAV, e_cal_backend_caldav, E_TYPE_CAL_BACKEND_SYNC)
+G_DEFINE_TYPE_WITH_CODE (
+	ECalBackendCalDAV,
+	e_cal_backend_caldav,
+	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)
@@ -4780,9 +4826,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);
 
@@ -4808,6 +4851,8 @@ 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);
 }
@@ -4880,7 +4925,6 @@ e_cal_backend_caldav_class_init (ECalBackendCalDAVClass *class)
 	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;
 
@@ -4898,4 +4942,7 @@ e_cal_backend_caldav_class_init (ECalBackendCalDAVClass *class)
 	backend_class->start_view		= caldav_start_view;
 
 	backend_class->internal_get_timezone	= caldav_internal_get_timezone;
+
+	/* Register our ESource extension. */
+	E_TYPE_SOURCE_CALDAV;
 }
diff --git a/calendar/backends/caldav/e-source-caldav.c b/calendar/backends/caldav/e-source-caldav.c
new file mode 100644
index 0000000..69bae9f
--- /dev/null
+++ b/calendar/backends/caldav/e-source-caldav.c
@@ -0,0 +1,231 @@
+/*
+ * e-source-caldav.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#include "e-source-caldav.h"
+
+#define E_SOURCE_CALDAV_GET_PRIVATE(obj) \
+	(G_TYPE_INSTANCE_GET_PRIVATE \
+	((obj), E_TYPE_SOURCE_CALDAV, ESourceCaldavPrivate))
+
+struct _ESourceCaldavPrivate {
+	GMutex *property_lock;
+	gboolean autoschedule;
+	gchar *email;
+};
+
+enum {
+	PROP_0,
+	PROP_AUTOSCHEDULE,
+	PROP_EMAIL
+};
+
+G_DEFINE_DYNAMIC_TYPE (
+	ESourceCaldav,
+	e_source_caldav,
+	E_TYPE_SOURCE_WEBDAV)
+
+static void
+source_caldav_set_property (GObject *object,
+                            guint property_id,
+                            const GValue *value,
+                            GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_AUTOSCHEDULE:
+			e_source_caldav_set_autoschedule (
+				E_SOURCE_CALDAV (object),
+				g_value_get_boolean (value));
+			return;
+
+		case PROP_EMAIL:
+			e_source_caldav_set_email (
+				E_SOURCE_CALDAV (object),
+				g_value_get_string (value));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_caldav_get_property (GObject *object,
+                            guint property_id,
+                            GValue *value,
+                            GParamSpec *pspec)
+{
+	switch (property_id) {
+		case PROP_AUTOSCHEDULE:
+			g_value_set_boolean (
+				value,
+				e_source_caldav_get_autoschedule (
+				E_SOURCE_CALDAV (object)));
+			return;
+
+		case PROP_EMAIL:
+			g_value_take_string (
+				value,
+				e_source_caldav_dup_email (
+				E_SOURCE_CALDAV (object)));
+			return;
+	}
+
+	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+source_caldav_finalize (GObject *object)
+{
+	ESourceCaldavPrivate *priv;
+
+	priv = E_SOURCE_CALDAV_GET_PRIVATE (object);
+
+	g_mutex_free (priv->property_lock);
+
+	g_free (priv->email);
+
+	/* Chain up to parent's finalize() method. */
+	G_OBJECT_CLASS (e_source_caldav_parent_class)->finalize (object);
+}
+
+static void
+e_source_caldav_class_init (ESourceCaldavClass *class)
+{
+	GObjectClass *object_class;
+	ESourceExtensionClass *extension_class;
+
+	g_type_class_add_private (class, sizeof (ESourceCaldavPrivate));
+
+	object_class = G_OBJECT_CLASS (class);
+	object_class->set_property = source_caldav_set_property;
+	object_class->get_property = source_caldav_get_property;
+	object_class->finalize = source_caldav_finalize;
+
+	extension_class = E_SOURCE_EXTENSION_CLASS (class);
+	extension_class->name = E_SOURCE_EXTENSION_CALDAV_BACKEND;
+
+	g_object_class_install_property (
+		object_class,
+		PROP_AUTOSCHEDULE,
+		g_param_spec_boolean (
+			"autoschedule",
+			"Auto-Schedule",
+			"Server handles meeting invitations",
+			FALSE,
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			E_SOURCE_PARAM_SETTING));
+
+	g_object_class_install_property (
+		object_class,
+		PROP_EMAIL,
+		g_param_spec_string (
+			"email",
+			"Email",
+			"User's email address",
+			"",
+			G_PARAM_READWRITE |
+			G_PARAM_CONSTRUCT |
+			E_SOURCE_PARAM_SETTING));
+}
+
+static void
+e_source_caldav_class_finalize (ESourceCaldavClass *class)
+{
+}
+
+static void
+e_source_caldav_init (ESourceCaldav *extension)
+{
+	extension->priv = E_SOURCE_CALDAV_GET_PRIVATE (extension);
+	extension->priv->property_lock = g_mutex_new ();
+}
+
+void
+e_source_caldav_type_register (GTypeModule *type_module)
+{
+	/* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+	 *     function, so we have to wrap it with a public function in
+	 *     order to register types from a separate compilation unit. */
+	e_source_caldav_register_type (type_module);
+}
+
+gboolean
+e_source_caldav_get_autoschedule (ESourceCaldav *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_CALDAV (extension), FALSE);
+
+	return extension->priv->autoschedule;
+}
+
+void
+e_source_caldav_set_autoschedule (ESourceCaldav *extension,
+                                  gboolean autoschedule)
+{
+	g_return_if_fail (E_IS_SOURCE_CALDAV (extension));
+
+	extension->priv->autoschedule = autoschedule;
+
+	g_object_notify (G_OBJECT (extension), "autoschedule");
+}
+
+const gchar *
+e_source_caldav_get_email (ESourceCaldav *extension)
+{
+	g_return_val_if_fail (E_IS_SOURCE_CALDAV (extension), NULL);
+
+	return extension->priv->email;
+}
+
+gchar *
+e_source_caldav_dup_email (ESourceCaldav *extension)
+{
+	const gchar *protected;
+	gchar *duplicate;
+
+	g_return_val_if_fail (E_IS_SOURCE_CALDAV (extension), NULL);
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	protected = e_source_caldav_get_email (extension);
+	duplicate = g_strdup (protected);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	return duplicate;
+}
+
+void
+e_source_caldav_set_email (ESourceCaldav *extension,
+                           const gchar *email)
+{
+	g_return_if_fail (E_IS_SOURCE_CALDAV (extension));
+
+	/* Empty strings are equivalent to NULL. */
+	if (email != NULL && *email == '\0')
+		email = NULL;
+
+	g_mutex_lock (extension->priv->property_lock);
+
+	g_free (extension->priv->email);
+	extension->priv->email = g_strdup (email);
+
+	g_mutex_unlock (extension->priv->property_lock);
+
+	g_object_notify (G_OBJECT (extension), "email");
+}
+
diff --git a/calendar/backends/caldav/e-source-caldav.h b/calendar/backends/caldav/e-source-caldav.h
new file mode 100644
index 0000000..dca54de
--- /dev/null
+++ b/calendar/backends/caldav/e-source-caldav.h
@@ -0,0 +1,72 @@
+/*
+ * e-source-caldav.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <webcal://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef E_SOURCE_CALDAV_H
+#define E_SOURCE_CALDAV_H
+
+#include <libedataserver/e-source-webdav.h>
+
+/* Standard GObject macros */
+#define E_TYPE_SOURCE_CALDAV \
+	(e_source_caldav_get_type ())
+#define E_SOURCE_CALDAV(obj) \
+	(G_TYPE_CHECK_INSTANCE_CAST \
+	((obj), E_TYPE_SOURCE_CALDAV, ESourceCaldav))
+#define E_SOURCE_CALDAV_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_CAST \
+	((cls), E_TYPE_SOURCE_CALDAV, ESourceCaldavClass))
+#define E_IS_SOURCE_CALDAV(obj) \
+	(G_TYPE_CHECK_INSTANCE_TYPE \
+	((obj), E_TYPE_SOURCE_CALDAV))
+#define E_IS_SOURCE_CALDAV_CLASS(cls) \
+	(G_TYPE_CHECK_CLASS_TYPE \
+	((cls), E_TYPE_SOURCE_CALDAV))
+#define E_SOURCE_CALDAV_GET_CLASS(obj) \
+	(G_TYPE_INSTANCE_GET_CLASS \
+	((obj), E_TYPE_SOURCE_CALDAV, ESourceCaldavClass))
+
+#define E_SOURCE_EXTENSION_CALDAV_BACKEND "CalDAV Backend"
+
+G_BEGIN_DECLS
+
+typedef struct _ESourceCaldav ESourceCaldav;
+typedef struct _ESourceCaldavClass ESourceCaldavClass;
+typedef struct _ESourceCaldavPrivate ESourceCaldavPrivate;
+
+struct _ESourceCaldav {
+	ESourceWebdav parent;
+	ESourceCaldavPrivate *priv;
+};
+
+struct _ESourceCaldavClass {
+	ESourceWebdavClass parent_class;
+};
+
+GType		e_source_caldav_get_type	(void);
+void		e_source_caldav_type_register	(GTypeModule *type_module);
+gboolean	e_source_caldav_get_autoschedule
+						(ESourceCaldav *extension);
+void		e_source_caldav_set_autoschedule
+						(ESourceCaldav *extension,
+						 gboolean autoschedule);
+const gchar *	e_source_caldav_get_email	(ESourceCaldav *extension);
+gchar *		e_source_caldav_dup_email	(ESourceCaldav *extension);
+void		e_source_caldav_set_email	(ESourceCaldav *extension,
+						 const gchar *email);
+
+#endif /* E_SOURCE_CALDAV_H */



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