diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/daemon/goadaemon.c | 3 | ||||
| -rw-r--r-- | src/goabackend/goadavclient.c | 53 | ||||
| -rw-r--r-- | src/goabackend/goaimapauthlogin.c | 91 | ||||
| -rw-r--r-- | src/goabackend/goamsgraphprovider.c | 10 | ||||
| -rw-r--r-- | src/goabackend/goaoauth2provider.c | 25 | ||||
| -rw-r--r-- | src/goabackend/goaproviderdialog.c | 7 | ||||
| -rw-r--r-- | src/goabackend/goautils.c | 2 |
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) |
