Blame SOURCES/evolution-data-server-3.12.11-caldav-daily-limit-exceeded.patch

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