summaryrefslogtreecommitdiff
path: root/src
diff options
Diffstat (limited to 'src')
-rw-r--r--src/daemon/goadaemon.c3
-rw-r--r--src/goabackend/goadavclient.c53
-rw-r--r--src/goabackend/goaimapauthlogin.c91
-rw-r--r--src/goabackend/goamsgraphprovider.c10
-rw-r--r--src/goabackend/goaoauth2provider.c25
-rw-r--r--src/goabackend/goaproviderdialog.c7
-rw-r--r--src/goabackend/goautils.c2
7 files changed, 130 insertions, 61 deletions
diff --git a/src/daemon/goadaemon.c b/src/daemon/goadaemon.c
index d37d3c9c..ddbde25e 100644
--- a/src/daemon/goadaemon.c
+++ b/src/daemon/goadaemon.c
@@ -1398,6 +1398,7 @@ remove_account_cb (GObject *source_object, GAsyncResult *res, gpointer user_data
if (g_ptr_array_remove (self->accounts_needing_attention, account))
goa_daemon_update_notification (self);
+ g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
@@ -1797,6 +1798,8 @@ ensure_credentials_queue_collector (GObject *source_object, GAsyncResult *res, g
self->ensure_credentials_running = FALSE;
ensure_credentials_queue_check (self);
+
+ g_task_return_boolean (task, TRUE);
g_object_unref (task);
}
diff --git a/src/goabackend/goadavclient.c b/src/goabackend/goadavclient.c
index aaa55bba..5f74b7b3 100644
--- a/src/goabackend/goadavclient.c
+++ b/src/goabackend/goadavclient.c
@@ -48,6 +48,14 @@
#define MAILBOX_ORG_CALDAV "https://dav.mailbox.org/caldav"
#define MAILBOX_ORG_CARDDAV "https://dav.mailbox.org/carddav"
+/* mail.ru
+ * See: https://help.mail.ru/cloud_web/app/webdav/#linux
+ * https://help.mail.ru/calendar-help/synchronization/about/
+ */
+#define MAIL_RU_HOSTNAME "mail.ru"
+#define MAIL_RU_WEBDAV "https://webdav.cloud.mail.ru"
+#define MAIL_RU_CALDAV "https://calendar.mail.ru"
+
struct _GoaDavClient
{
GObject parent_instance;
@@ -890,6 +898,25 @@ dav_client_discover_postconfig_nexcloud (DiscoverData *discover,
if (server_root == NULL)
server_root = g_strrstr (path, "/remote.php/webdav");
+ /* Check the DAV headers for a Nextcloud-specific entry, which may
+ * have matched on a well-known without a proper redirect
+ */
+ if (server_root == NULL)
+ {
+ SoupMessageHeaders *headers = NULL;
+ const char *dav_header = NULL;
+
+ headers = soup_message_get_response_headers (message);
+ dav_header = soup_message_headers_get_list (headers, "DAV");
+
+ if (dav_header != NULL && g_strrstr (dav_header, "nextcloud-checksum-update") != NULL)
+ {
+ server_root = g_strrstr (path, WELL_KNOWN_CALDAV);
+ if (server_root == NULL)
+ server_root = g_strrstr (path, WELL_KNOWN_CARDDAV);
+ }
+ }
+
if (server_root != NULL)
{
int port = -1;
@@ -1177,13 +1204,6 @@ dav_client_discover_iterate (GTask *task)
{
g_autofree char *nc_uri = NULL;
- /* Start with Nextcloud, everyone's favourite sort of compliant DAV server, since
- * we can return early if we recognize the path.
- */
- nc_uri = g_uri_resolve_relative (discover->uri, "remote.php/dav", G_URI_FLAGS_NONE, NULL);
- g_queue_push_tail (&discover->candidates,
- goa_dav_config_new (GOA_SERVICE_TYPE_WEBDAV, nc_uri, NULL));
-
g_queue_push_tail (&discover->candidates,
goa_dav_config_new (GOA_SERVICE_TYPE_CALDAV, discover->uri, NULL));
g_queue_push_tail (&discover->candidates,
@@ -1191,6 +1211,12 @@ dav_client_discover_iterate (GTask *task)
g_queue_push_tail (&discover->candidates,
goa_dav_config_new (GOA_SERVICE_TYPE_WEBDAV, discover->uri, NULL));
+ /* Fallback to making an OPTIONS request to a known path for Nextcloud/ownCloud
+ */
+ nc_uri = g_uri_resolve_relative (discover->uri, "remote.php/dav", G_URI_FLAGS_NONE, NULL);
+ g_queue_push_tail (&discover->candidates,
+ goa_dav_config_new (GOA_SERVICE_TYPE_WEBDAV, nc_uri, NULL));
+
discover->uri_fallback = TRUE;
dav_client_discover_iterate (task);
}
@@ -1249,7 +1275,7 @@ dav_client_discover_preconfig (DiscoverData *discover,
|| g_strcmp0 (base_domain, "mailbox.org") == 0)
{
g_queue_push_tail (&discover->candidates,
- goa_dav_config_new (GOA_SERVICE_TYPE_CALDAV, MAILBOX_ORG_WEBDAV, NULL));
+ goa_dav_config_new (GOA_SERVICE_TYPE_CALDAV, MAILBOX_ORG_CALDAV, NULL));
g_queue_push_tail (&discover->candidates,
goa_dav_config_new (GOA_SERVICE_TYPE_CARDDAV, MAILBOX_ORG_CARDDAV, NULL));
g_queue_push_tail (&discover->candidates,
@@ -1258,6 +1284,17 @@ dav_client_discover_preconfig (DiscoverData *discover,
return TRUE;
}
+ if (g_strcmp0 (host, "mail.ru") == 0
+ || g_strcmp0 (base_domain, "mail.ru") == 0)
+ {
+ g_queue_push_tail (&discover->candidates,
+ goa_dav_config_new (GOA_SERVICE_TYPE_CALDAV, MAIL_RU_CALDAV, NULL));
+ g_queue_push_tail (&discover->candidates,
+ goa_dav_config_new (GOA_SERVICE_TYPE_WEBDAV, MAIL_RU_WEBDAV, NULL));
+
+ return TRUE;
+ }
+
return FALSE;
}
diff --git a/src/goabackend/goaimapauthlogin.c b/src/goabackend/goaimapauthlogin.c
index 0872c0e4..2c4aa04f 100644
--- a/src/goabackend/goaimapauthlogin.c
+++ b/src/goabackend/goaimapauthlogin.c
@@ -110,15 +110,6 @@ imap_auth_login_check_NO (const gchar *response, GError **error)
}
static gboolean
-imap_auth_login_check_not_CAPABILITY (const gchar *response)
-{
- if (!g_str_has_prefix (response, "* CAPABILITY"))
- return TRUE;
-
- return FALSE;
-}
-
-static gboolean
imap_auth_login_check_not_OK (const gchar *response, gboolean tagged, GError **error)
{
gboolean ret = FALSE;
@@ -170,6 +161,55 @@ imap_auth_login_check_not_STARTTLS (const gchar *response, GError **error)
return FALSE;
}
+static gboolean
+imap_auth_login_read_response (GDataInputStream *input,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+
+ g_assert (G_IS_DATA_INPUT_STREAM (input));
+ g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ g_assert (error == NULL || *error == NULL);
+
+ while (TRUE)
+ {
+ g_autofree char *response = NULL;
+
+ response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
+ if (response == NULL)
+ break;
+
+ g_debug("< %s", response);
+ if (g_str_has_prefix (response, IMAP_TAG))
+ {
+ if (imap_auth_login_check_NO (response, error))
+ break;
+ if (imap_auth_login_check_not_OK (response, TRUE, error))
+ break;
+
+ ret = TRUE;
+ break;
+ }
+ else if (g_str_has_prefix (response, "* "))
+ {
+ if (imap_auth_login_check_BYE (response, error))
+ break;
+ }
+ else
+ {
+ g_set_error (error,
+ GOA_ERROR,
+ GOA_ERROR_FAILED, /* TODO: more specific */
+ "Unexpected response `%s' while doing LOGIN authentication",
+ response);
+ break;
+ }
+ }
+
+ return ret;
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static gchar *
@@ -386,25 +426,8 @@ goa_imap_auth_login_run_sync (GoaMailAuth *auth,
goto out;
g_clear_pointer (&request, g_free);
- /* Skip post-login CAPABILITY, if any */
- response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
- if (response == NULL)
- goto out;
- g_debug ("< %s", response);
- if (imap_auth_login_check_not_CAPABILITY (response))
- goto check_login_response;
- g_clear_pointer (&response, g_free);
-
- response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
- if (response == NULL)
+ if (!imap_auth_login_read_response (input, cancellable, error))
goto out;
- g_debug ("< %s", response);
- check_login_response:
- if (imap_auth_login_check_NO (response, error))
- goto out;
- if (imap_auth_login_check_not_OK (response, TRUE, error))
- goto out;
- g_clear_pointer (&response, g_free);
ret = TRUE;
@@ -463,13 +486,8 @@ goa_imap_auth_login_starttls_sync (GoaMailAuth *auth,
goto out;
g_clear_pointer (&response, g_free);
- response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
- if (response == NULL)
- goto out;
- g_debug ("< %s", response);
- if (imap_auth_login_check_not_OK (response, TRUE, error))
+ if (!imap_auth_login_read_response (input, cancellable, error))
goto out;
- g_clear_pointer (&response, g_free);
/* Send STARTTLS */
@@ -479,13 +497,8 @@ goa_imap_auth_login_starttls_sync (GoaMailAuth *auth,
goto out;
g_clear_pointer (&request, g_free);
- response = goa_utils_data_input_stream_read_line (input, NULL, cancellable, error);
- if (response == NULL)
+ if (!imap_auth_login_read_response (input, cancellable, error))
goto out;
- g_debug ("< %s", response);
- if (imap_auth_login_check_not_OK (response, TRUE, error))
- goto out;
- g_clear_pointer (&response, g_free);
/* There won't be a greeting after this */
self->greeting_absent = TRUE;
diff --git a/src/goabackend/goamsgraphprovider.c b/src/goabackend/goamsgraphprovider.c
index 6eebb7eb..d0a70f37 100644
--- a/src/goabackend/goamsgraphprovider.c
+++ b/src/goabackend/goamsgraphprovider.c
@@ -229,8 +229,9 @@ get_identity_sync (GoaOAuth2Provider *oauth2_provider,
}
id = json_node_get_string (json_member);
- // Prefer "mail" then "displayName" for "PresentationIdentity", failing if neither is available
- json_member = json_object_get_member (json_object, "mail");
+ // Prefer "userPrincipalName" then "mail", failing if neither is available, since Gvfs requires
+ // a user and host for the GMountSpec
+ json_member = json_object_get_member (json_object, "userPrincipalName");
if (json_member != NULL && json_node_get_value_type (json_member) == G_TYPE_STRING)
{
presentation_identity = json_node_get_string (json_member);
@@ -238,14 +239,15 @@ get_identity_sync (GoaOAuth2Provider *oauth2_provider,
if (presentation_identity == NULL)
{
- json_member = json_object_get_member (json_object, "displayName");
+ json_member = json_object_get_member (json_object, "mail");
if (json_member != NULL && json_node_get_value_type (json_member) == G_TYPE_STRING)
{
presentation_identity = json_node_get_string (json_member);
}
else
{
- g_debug ("%s(): expected \"mail\" or \"displayName\" field holding a string", G_STRFUNC);
+ g_debug ("%s(): expected \"userPrincipalName\" or \"mail\" field holding a string",
+ G_STRFUNC);
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED,
diff --git a/src/goabackend/goaoauth2provider.c b/src/goabackend/goaoauth2provider.c
index 41a8a0d6..d4ca09c9 100644
--- a/src/goabackend/goaoauth2provider.c
+++ b/src/goabackend/goaoauth2provider.c
@@ -826,13 +826,23 @@ parse_request_uri (GoaOAuth2Provider *self,
AccountData *data = g_task_get_task_data (task);
g_autoptr(GHashTable) key_value_pairs = NULL;
g_autoptr(GUri) uri = NULL;
+ g_autoptr(GUri) redirect_uri = NULL;
const char *fragment;
const char *oauth2_error;
const char *query;
g_assert (error == NULL || *error == NULL);
- if (!g_str_has_prefix (requested_uri, data->redirect_uri))
+ uri = g_uri_parse (requested_uri, G_URI_FLAGS_ENCODED | G_URI_FLAGS_PARSE_RELAXED, error);
+ if (uri == NULL)
+ return FALSE;
+
+ redirect_uri = g_uri_parse (data->redirect_uri, G_URI_FLAGS_ENCODED | G_URI_FLAGS_PARSE_RELAXED, error);
+ if (redirect_uri == NULL)
+ return FALSE;
+
+ if (g_strcmp0 (g_uri_get_scheme (uri), g_uri_get_scheme (redirect_uri)) != 0
+ || g_strcmp0 (g_uri_get_path (uri), g_uri_get_path (redirect_uri)) != 0)
{
g_set_error (error,
GOA_ERROR,
@@ -842,10 +852,6 @@ parse_request_uri (GoaOAuth2Provider *self,
return FALSE;
}
- uri = g_uri_parse (requested_uri, G_URI_FLAGS_ENCODED | G_URI_FLAGS_PARSE_RELAXED, error);
- if (uri == NULL)
- return FALSE;
-
/* Three cases:
* 1) we can either have the backend handle the URI for us, or
* 2) we can either have the access_token and other information
@@ -1166,6 +1172,7 @@ oauth2_handler_dbus_method_call (GDBusConnection *connection,
g_debug ("Received OAuth2 response for client ID \"%s\"", client_id);
g_dbus_method_invocation_return_value (invocation, NULL);
+ authorize_uri_task_complete (NULL, task);
g_task_return_pointer (task, g_strdup (response), g_free);
}
else
@@ -1177,10 +1184,10 @@ oauth2_handler_dbus_method_call (GDBusConnection *connection,
G_DBUS_ERROR_INVALID_ARGS,
"Invalid URI \"%s\"",
response);
+ authorize_uri_task_complete (NULL, task);
g_task_return_error (task, g_steal_pointer (&error));
}
- authorize_uri_task_complete (NULL, task);
return;
}
@@ -1209,8 +1216,8 @@ authorize_uri_launch_uri_cb (GObject *object,
if (!g_app_info_launch_default_for_uri_finish (result, &error))
{
- g_task_return_error (task, g_steal_pointer (&error));
authorize_uri_task_complete (NULL, task);
+ g_task_return_error (task, g_steal_pointer (&error));
}
}
@@ -1242,8 +1249,8 @@ on_oauth2_bus_acquired (GDBusConnection *connection,
if (data->register_object_id == 0)
{
- g_task_return_error (task, g_steal_pointer (&error));
authorize_uri_task_complete (NULL, task);
+ g_task_return_error (task, g_steal_pointer (&error));
}
}
@@ -1278,11 +1285,11 @@ on_oauth2_name_lost (GDBusConnection *connection,
else
g_warning ("%s(): Failed to own %s on the session bus", G_STRFUNC, name);
+ authorize_uri_task_complete (NULL, task);
g_task_return_new_error_literal (task,
GOA_ERROR,
GOA_ERROR_FAILED,
_("Service not available"));
- authorize_uri_task_complete (NULL, task);
}
/* ---------------------------------------------------------------------------------------------------- */
diff --git a/src/goabackend/goaproviderdialog.c b/src/goabackend/goaproviderdialog.c
index a848b683..75386e80 100644
--- a/src/goabackend/goaproviderdialog.c
+++ b/src/goabackend/goaproviderdialog.c
@@ -888,6 +888,13 @@ goa_provider_dialog_push_account (GoaProviderDialog *self,
self);
adw_preferences_group_add (ADW_PREFERENCES_GROUP (group), row);
+ // Gvfs requires a user and host for OneDrive mount spec, so disallow
+ // custom presentation identities for this provider
+ if (g_str_equal (goa_provider_get_provider_type (self->provider), GOA_MS_GRAPH_NAME))
+ {
+ gtk_editable_set_editable (GTK_EDITABLE (row), FALSE);
+ }
+
revealer = gtk_revealer_new ();
gtk_revealer_set_transition_type (GTK_REVEALER (revealer), GTK_REVEALER_TRANSITION_TYPE_CROSSFADE);
adw_preferences_group_add (ADW_PREFERENCES_GROUP (group), revealer);
diff --git a/src/goabackend/goautils.c b/src/goabackend/goautils.c
index 1a188bf9..bd393ad9 100644
--- a/src/goabackend/goautils.c
+++ b/src/goabackend/goautils.c
@@ -721,7 +721,7 @@ goa_utils_normalize_url (const char *base_uri,
}
uri = g_uri_parse (uri_string, G_URI_FLAGS_ENCODED | G_URI_FLAGS_PARSE_RELAXED, NULL);
- if (uri == NULL)
+ if (uri == NULL || g_uri_get_host (uri) == NULL || g_uri_get_host (uri)[0] == '\0')
return NULL;
if (uri_ref != NULL)