[evolution-data-server/account-mgmt: 21/42] Adapt calendar backends to the new ESource API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/account-mgmt: 21/42] Adapt calendar backends to the new ESource API.
- Date: Sun, 20 May 2012 19:47:33 +0000 (UTC)
commit 6dde380c3b4cb4c0f6c709f280f0c0782cda6e2e
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 | 378 +++++++------
calendar/backends/http/e-cal-backend-http.c | 674 ++++++++++++++---------
2 files changed, 639 insertions(+), 413 deletions(-)
---
diff --git a/calendar/backends/caldav/e-cal-backend-caldav.c b/calendar/backends/caldav/e-cal-backend-caldav.c
index e5955fc..406ad83 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 */
@@ -547,6 +552,9 @@ status_code_to_result (SoupMessage *message,
{
ECalBackendCalDAVPrivate *priv;
ESource *source;
+ ESourceWebdav *extension;
+ const gchar *extension_name;
+ gboolean ignore_invalid_cert;
g_return_val_if_fail (cbdav != NULL, FALSE);
g_return_val_if_fail (message != NULL, FALSE);
@@ -559,6 +567,10 @@ status_code_to_result (SoupMessage *message,
source = e_backend_get_source (E_BACKEND (cbdav));
+ extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+ extension = e_source_get_extension (source, extension_name);
+ ignore_invalid_cert = e_source_webdav_get_ignore_invalid_cert (extension);
+
switch (message->status_code) {
case SOUP_STATUS_CANT_CONNECT:
case SOUP_STATUS_CANT_CONNECT_PROXY:
@@ -592,7 +604,7 @@ status_code_to_result (SoupMessage *message,
break;
case SOUP_STATUS_SSL_FAILED:
- if (g_strcmp0 (e_source_get_property (source, "ignore-invalid-cert"), "1") == 0) {
+ if (ignore_invalid_cert) {
g_propagate_error (perror,
e_data_cal_create_error_fmt ( OtherError,
_("Failed to connect to a server using SSL: %s"),
@@ -974,13 +986,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);
}
}
@@ -1138,37 +1160,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
@@ -1228,7 +1233,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;
@@ -1386,7 +1391,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");
@@ -1431,7 +1436,7 @@ caldav_server_download_attachment (ECalBackendCalDAV *cbdav,
status_code_to_result (message, cbdav, FALSE, error);
if (message->status_code == 401)
- caldav_notify_auth_required (cbdav);
+ caldav_authenticate (cbdav, NULL, NULL);
g_object_unref (message);
return FALSE;
@@ -1473,7 +1478,7 @@ caldav_server_get_object (ECalBackendCalDAV *cbdav,
status_code_to_result (message, cbdav, FALSE, 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);
@@ -1539,7 +1544,7 @@ caldav_post_freebusy (ECalBackendCalDAV *cbdav,
if (!SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
status_code_to_result (message, cbdav, FALSE, 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");
@@ -1726,7 +1731,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);
@@ -1765,7 +1770,7 @@ caldav_server_delete_object (ECalBackendCalDAV *cbdav,
status_code_to_result (message, cbdav, FALSE, perror);
if (message->status_code == 401)
- caldav_notify_auth_required (cbdav);
+ caldav_authenticate (cbdav, NULL, NULL);
g_object_unref (message);
}
@@ -1880,7 +1885,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)
@@ -2388,27 +2393,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;
}
@@ -2430,9 +2446,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 ","
@@ -2444,12 +2462,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);
@@ -2490,79 +2509,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);
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ auth_extension = e_source_get_extension (source, extension_name);
- 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_OFFLINE;
+ offline_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_REFRESH;
+ refresh_extension = e_source_get_extension (source, extension_name);
- os_val = e_source_get_property(source, "ssl");
-
- 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);
@@ -2606,8 +2617,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;
@@ -2653,15 +2670,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);
@@ -2733,8 +2741,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)
@@ -2755,34 +2763,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,
@@ -4133,6 +4113,7 @@ process_object (ECalBackendCalDAV *cbdav,
icalproperty_method method,
GError **error)
{
+ ESourceRegistry *registry;
ECalBackend *backend;
struct icaltimetype now;
gchar *new_obj_str;
@@ -4145,6 +4126,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);
@@ -4161,7 +4144,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;
@@ -4608,11 +4591,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;
@@ -4662,16 +4649,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);
@@ -4863,13 +4850,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)
@@ -4905,9 +4933,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);
@@ -4933,11 +4958,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);
@@ -5001,11 +5053,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 db8ff9f..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);
+
+ if (soup_message == NULL) {
+ g_set_error (
+ error, SOUP_HTTP_ERROR,
+ SOUP_STATUS_MALFORMED,
+ _("Malformed URI: %s"), uri);
+ return FALSE;
+ }
- priv->is_loading = FALSE;
- d(g_message ("Retrieval done.\n"));
+ if (G_IS_CANCELLABLE (cancellable)) {
+ cancel_data.soup_session = soup_session;
+ cancel_data.soup_message = soup_message;
- if (!priv->uri) {
- /* uri changed meanwhile, retrieve again */
- begin_retrieval_cb (cbhttp);
- g_object_unref (cbhttp);
- return;
+ 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,60 +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 if (msg->status_code == SOUP_STATUS_SSL_FAILED) {
- ESource *source = e_backend_get_source (E_BACKEND (cbhttp));
- gchar *err_msg;
-
- if (g_strcmp0 (e_source_get_property (source, "ignore-invalid-cert"), "1") == 0) {
- err_msg = g_strdup_printf (_("Failed to connect to a server using SSL: %s"),
- 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")));
- } else {
- err_msg = g_strdup (_("Failed to connect to a server using SSL. "
- "One possible reason is an invalid certificate being used by the server. "
- "If this is expected, like self-signed certificate being used on the server, "
- "then disable certificate validity tests by selecting 'Ignore invalid SSL certificate' option "
- "in Properties"));
- }
-
- e_cal_backend_notify_error (E_CAL_BACKEND (cbhttp), err_msg);
- g_free (err_msg);
- } 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;
@@ -456,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);
@@ -490,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) {
@@ -514,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);
}
}
@@ -546,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 */
@@ -554,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;
}
@@ -687,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;
}
@@ -696,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;
@@ -711,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);
+
+ 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
@@ -724,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);
- g_free (new_uri);
+ 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 (old_uri);
}
}
@@ -759,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;
@@ -772,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 (
@@ -785,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);
@@ -812,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
@@ -927,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)
@@ -1248,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;
@@ -1265,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);
@@ -1278,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);
@@ -1382,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)
@@ -1411,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;
@@ -1430,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]