diff -up evolution-data-server-3.12.11/calendar/backends/caldav/e-cal-backend-caldav.c.caldav-daily-limit-exceeded evolution-data-server-3.12.11/calendar/backends/caldav/e-cal-backend-caldav.c
--- evolution-data-server-3.12.11/calendar/backends/caldav/e-cal-backend-caldav.c.caldav-daily-limit-exceeded 2016-09-06 11:43:45.023286287 +0200
+++ evolution-data-server-3.12.11/calendar/backends/caldav/e-cal-backend-caldav.c 2016-09-06 11:45:13.838282462 +0200
@@ -130,7 +130,7 @@ struct _ECalBackendCalDAVPrivate {
* message than a generic 401 description. */
GError *bearer_auth_error;
GMutex bearer_auth_error_lock;
- gboolean using_bearer_auth;
+ ESoupAuthBearer *using_bearer_auth;
};
/* Forward Declarations */
@@ -597,7 +597,24 @@ status_code_to_result (SoupMessage *mess
break;
case SOUP_STATUS_FORBIDDEN:
- g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
+ if (cbdav->priv->using_bearer_auth && message->response_body &&
+ message->response_body->data && message->response_body->length) {
+ gchar *body = g_strndup (message->response_body->data, message->response_body->length);
+
+ /* Do not localize this string, it is returned by the server. */
+ if (body && (e_util_strstrcase (body, "Daily Limit Exceeded") ||
+ e_util_strstrcase (body, "https://console.developers.google.com/"))) {
+ /* Special-case this condition and provide this error up to the UI. */
+ g_propagate_error (perror,
+ e_data_cal_create_error_fmt (OtherError, _("Failed to login to the server: %s"), body));
+ } else {
+ g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
+ }
+
+ g_free (body);
+ } else {
+ g_propagate_error (perror, EDC_ERROR (AuthenticationRequired));
+ }
break;
case SOUP_STATUS_UNAUTHORIZED:
@@ -1044,7 +1061,11 @@ soup_authenticate (SoupSession *session,
extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
auth_extension = e_source_get_extension (source, extension_name);
- cbdav->priv->using_bearer_auth = E_IS_SOUP_AUTH_BEARER (auth);
+ if (E_IS_SOUP_AUTH_BEARER (auth)) {
+ g_warn_if_fail ((gpointer) cbdav->priv->using_bearer_auth == (gpointer) auth);
+ g_clear_object (&cbdav->priv->using_bearer_auth);
+ cbdav->priv->using_bearer_auth = g_object_ref (auth);
+ }
if (retrying || cbdav->priv->force_ask_password) {
cbdav->priv->force_ask_password = !cbdav->priv->using_bearer_auth;
@@ -1070,6 +1091,34 @@ soup_authenticate (SoupSession *session,
/* ************************************************************************* */
/* direct CalDAV server access functions */
+static gboolean
+caldav_backend_setup_bearer_auth (ECalBackendCalDAV *cbdav,
+ ESoupAuthBearer *bearer,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ESource *source;
+ gchar *access_token = NULL;
+ gint expires_in_seconds = -1;
+ gboolean success;
+
+ g_return_val_if_fail (E_IS_CAL_BACKEND_CALDAV (cbdav), FALSE);
+ g_return_val_if_fail (E_IS_SOUP_AUTH_BEARER (bearer), FALSE);
+
+ source = e_backend_get_source (E_BACKEND (cbdav));
+
+ success = e_source_get_oauth2_access_token_sync (
+ source, cancellable, &access_token,
+ &expires_in_seconds, error);
+
+ if (success)
+ e_soup_auth_bearer_set_access_token (bearer, access_token, expires_in_seconds);
+
+ g_free (access_token);
+
+ return success;
+}
+
static void
redirect_handler (SoupMessage *msg,
gpointer user_data)
@@ -1120,6 +1169,20 @@ send_and_handle_redirection (ECalBackend
if (new_location)
old_uri = soup_uri_to_string (soup_message_get_uri (msg), FALSE);
+ if (cbdav->priv->using_bearer_auth && e_soup_auth_bearer_is_expired (cbdav->priv->using_bearer_auth)) {
+ GError *local_error = NULL;
+
+ if (!caldav_backend_setup_bearer_auth (cbdav, cbdav->priv->using_bearer_auth, cancellable, &local_error)) {
+ if (local_error) {
+ soup_message_set_status_full (msg, SOUP_STATUS_BAD_REQUEST, local_error->message);
+ g_propagate_error (error, local_error);
+ } else {
+ soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+ }
+ return;
+ }
+ }
+
soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
soup_message_add_header_handler (msg, "got_body", "Location", G_CALLBACK (redirect_handler), cbdav->priv->session);
soup_message_headers_append (msg->request_headers, "Connection", "close");
@@ -5238,6 +5301,7 @@ e_cal_backend_caldav_dispose (GObject *o
g_clear_object (&priv->store);
g_clear_object (&priv->session);
+ g_clear_object (&priv->using_bearer_auth);
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -5304,8 +5368,6 @@ caldav_backend_initable_init (GInitable
ESourceWebdav *extension;
SoupAuth *soup_auth;
SoupURI *soup_uri;
- gchar *access_token = NULL;
- gint expires_in_seconds = -1;
extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
extension = e_source_get_extension (source, extension_name);
@@ -5315,21 +5377,17 @@ caldav_backend_initable_init (GInitable
E_TYPE_SOUP_AUTH_BEARER,
SOUP_AUTH_HOST, soup_uri->host, NULL);
- success = e_source_get_oauth2_access_token_sync (
- source, cancellable, &access_token,
- &expires_in_seconds, error);
+ success = caldav_backend_setup_bearer_auth (E_CAL_BACKEND_CALDAV (initable),
+ E_SOUP_AUTH_BEARER (soup_auth), cancellable, error);
if (success) {
- e_soup_auth_bearer_set_access_token (
- E_SOUP_AUTH_BEARER (soup_auth),
- access_token, expires_in_seconds);
+ priv->using_bearer_auth = g_object_ref (soup_auth);
soup_auth_manager_use_auth (
SOUP_AUTH_MANAGER (feature),
soup_uri, soup_auth);
}
- g_free (access_token);
g_object_unref (soup_auth);
soup_uri_free (soup_uri);
}
diff -up evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.c.caldav-daily-limit-exceeded evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.c
--- evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.c.caldav-daily-limit-exceeded 2016-09-06 11:44:57.973283145 +0200
+++ evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.c 2016-09-06 11:45:13.839282462 +0200
@@ -52,17 +52,6 @@ G_DEFINE_TYPE (
e_soup_auth_bearer,
SOUP_TYPE_AUTH)
-static gboolean
-e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer)
-{
- gboolean expired = FALSE;
-
- if (bearer->priv->expiry != EXPIRY_INVALID)
- expired = (bearer->priv->expiry < time (NULL));
-
- return expired;
-}
-
static void
e_soup_auth_bearer_finalize (GObject *object)
{
@@ -193,3 +182,15 @@ e_soup_auth_bearer_set_access_token (ESo
SOUP_AUTH_IS_AUTHENTICATED);
}
+gboolean
+e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer)
+{
+ gboolean expired = TRUE;
+
+ g_return_val_if_fail (E_IS_SOUP_AUTH_BEARER (bearer), TRUE);
+
+ if (bearer->priv->expiry != EXPIRY_INVALID)
+ expired = (bearer->priv->expiry < time (NULL));
+
+ return expired;
+}
diff -up evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.h.caldav-daily-limit-exceeded evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.h
--- evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.h.caldav-daily-limit-exceeded 2016-09-06 11:45:05.941282802 +0200
+++ evolution-data-server-3.12.11/libebackend/e-soup-auth-bearer.h 2016-09-06 11:45:13.839282462 +0200
@@ -71,6 +71,7 @@ void e_soup_auth_bearer_set_access_toke
(ESoupAuthBearer *bearer,
const gchar *access_token,
gint expires_in_seconds);
+gboolean e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer);
G_END_DECLS