From 15b6ce16543e04deabc415f4ff70fca6c767bc7a Mon Sep 17 00:00:00 2001 From: Alexey Berezhok Date: Mon, 21 Aug 2023 18:52:07 +0300 Subject: [PATCH] Added yandex disk webdav support --- daemon/gvfsbackenddav.c | 241 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 239 insertions(+), 2 deletions(-) diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c index 12de62e..7564924 100644 --- a/daemon/gvfsbackenddav.c +++ b/daemon/gvfsbackenddav.c @@ -119,6 +119,204 @@ struct _GVfsBackendDav G_DEFINE_TYPE (GVfsBackendDav, g_vfs_backend_dav, G_VFS_TYPE_BACKEND_HTTP); +/*Yandex Oauth, looks like same as basik, but another token*/ + +/* Standard GObject macros */ +#define E_TYPE_SOUP_AUTH_BEARER \ + (e_soup_auth_bearer_get_type ()) +#define E_SOUP_AUTH_BEARER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearer)) +#define E_SOUP_AUTH_BEARER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearerClass)) +#define E_IS_SOUP_AUTH_BEARER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SOUP_AUTH_BEARER)) +#define E_IS_SOUP_AUTH_BEARER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SOUP_AUTH_BEARER)) +#define E_SOUP_AUTH_BEARER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SOUP_AUTH_BEARER, ESoupAuthBearerClass)) + +G_BEGIN_DECLS + +typedef struct _ESoupAuthBearer ESoupAuthBearer; +typedef struct _ESoupAuthBearerClass ESoupAuthBearerClass; +typedef struct _ESoupAuthBearerPrivate ESoupAuthBearerPrivate; + + +struct _ESoupAuthBearer { + /*< private >*/ + SoupAuth parent; + ESoupAuthBearerPrivate *priv; +}; + +struct _ESoupAuthBearerClass { + SoupAuthClass parent_class; +}; + +GType e_soup_auth_bearer_get_type (void) G_GNUC_CONST; +void e_soup_auth_bearer_set_access_token + (ESoupAuthBearer *bearer, + const gchar *access_token); +gboolean +e_soup_auth_bearer_set_custom_bearer_name (ESoupAuthBearer *bearer, +const gchar *bearer_name); + +G_END_DECLS + +#define OAUTH_SAUTH_STRENGTH 1 + +struct _ESoupAuthBearerPrivate { + GMutex property_lock; + gchar *access_token; +}; + +G_DEFINE_TYPE_WITH_PRIVATE ( + ESoupAuthBearer, + e_soup_auth_bearer, + SOUP_TYPE_AUTH) + +static void +e_soup_auth_bearer_finalize (GObject *object) +{ + ESoupAuthBearerPrivate *priv; + + priv = E_SOUP_AUTH_BEARER (object)->priv; + + g_mutex_clear (&priv->property_lock); + g_free (priv->access_token); + + G_OBJECT_CLASS (e_soup_auth_bearer_parent_class)->finalize (object); +} + +static gboolean +e_soup_auth_bearer_update (SoupAuth *auth, + SoupMessage *message, + GHashTable *auth_header) +{ + + ESoupAuthBearer *bearer; + + g_return_val_if_fail (E_IS_SOUP_AUTH_BEARER (auth), FALSE); + + bearer = E_SOUP_AUTH_BEARER (auth); + + g_mutex_lock (&bearer->priv->property_lock); + + if (bearer->priv->access_token){ + memset (bearer->priv->access_token, 0, strlen (bearer->priv->access_token)); + g_free (bearer->priv->access_token); + bearer->priv->access_token = NULL; + } + + g_mutex_unlock (&bearer->priv->property_lock); + + return TRUE; +} + +static GSList * +e_soup_auth_bearer_get_protection_space (SoupAuth *auth, + SoupURI *source_uri) +{ + return g_slist_prepend (NULL, g_strdup ("")); +} + +static gboolean +e_soup_auth_bearer_is_authenticated (SoupAuth *auth) +{ + ESoupAuthBearer *bearer; + gboolean authenticated = FALSE; + + bearer = E_SOUP_AUTH_BEARER (auth); + + g_mutex_lock (&bearer->priv->property_lock); + + authenticated = (bearer->priv->access_token != NULL); + + g_mutex_unlock (&bearer->priv->property_lock); + + return authenticated; +} + +static gchar * +e_soup_auth_bearer_get_authorization (SoupAuth *auth, + SoupMessage *message) +{ + ESoupAuthBearer *bearer; + gchar *res; + + bearer = E_SOUP_AUTH_BEARER (auth); + + g_mutex_lock (&bearer->priv->property_lock); + res = g_strdup_printf ("OAuth %s", bearer->priv->access_token); + g_mutex_unlock (&bearer->priv->property_lock); + + return res; +} + +static void +e_soup_auth_bearer_class_init (ESoupAuthBearerClass *class) +{ + GObjectClass *object_class; + SoupAuthClass *auth_class; + + object_class = G_OBJECT_CLASS (class); + object_class->finalize = e_soup_auth_bearer_finalize; + + auth_class = SOUP_AUTH_CLASS (class); + auth_class->scheme_name = "Basic"; + auth_class->strength = OAUTH_SAUTH_STRENGTH; + auth_class->update = e_soup_auth_bearer_update; + auth_class->get_protection_space = e_soup_auth_bearer_get_protection_space; + auth_class->is_authenticated = e_soup_auth_bearer_is_authenticated; + auth_class->get_authorization = e_soup_auth_bearer_get_authorization; +} + +static void +e_soup_auth_bearer_init (ESoupAuthBearer *bearer) +{ + bearer->priv = e_soup_auth_bearer_get_instance_private (bearer); + g_mutex_init (&bearer->priv->property_lock); +} + +void +e_soup_auth_bearer_set_access_token (ESoupAuthBearer *bearer, + const gchar *access_token) +{ + gboolean was_authenticated; + gboolean now_authenticated; + + g_return_if_fail (E_IS_SOUP_AUTH_BEARER (bearer)); + + was_authenticated = soup_auth_is_authenticated (SOUP_AUTH (bearer)); + + g_mutex_lock (&bearer->priv->property_lock); + + if (g_strcmp0 (bearer->priv->access_token, access_token) == 0) { + g_mutex_unlock (&bearer->priv->property_lock); + return; + } + + g_free (bearer->priv->access_token); + bearer->priv->access_token = g_strdup (access_token); + + g_mutex_unlock (&bearer->priv->property_lock); + + now_authenticated = soup_auth_is_authenticated (SOUP_AUTH (bearer)); + + if (was_authenticated != now_authenticated) + g_object_notify ( + G_OBJECT (bearer), + SOUP_AUTH_IS_AUTHENTICATED); +} + +/* +end of Yandex ouath +*/ + static void g_vfs_backend_dav_finalize (GObject *object) { @@ -1509,6 +1707,7 @@ soup_authenticate_interactive (SoupSession *session, char *new_username; char *new_password; char *prompt; + GType auth_type_oauth; data = (MountAuthData *) user_data; @@ -1578,7 +1777,13 @@ soup_authenticate_interactive (SoupSession *session, if (retrying == FALSE && have_auth) { - soup_auth_authenticate (auth, info->username, info->password); + auth_type_oauth = G_OBJECT_TYPE (auth); + if (auth_type_oauth == E_TYPE_SOUP_AUTH_BEARER){ + ESoupAuthBearer *soup_auth_oauth = (ESoupAuthBearer *)auth; + e_soup_auth_bearer_set_access_token (soup_auth_oauth, info->password); + } else { + soup_auth_authenticate (auth, info->username, info->password); + } return; } @@ -1615,7 +1820,13 @@ soup_authenticate_interactive (SoupSession *session, if (new_username == NULL) new_username = g_strdup (info->username); - soup_auth_authenticate (auth, new_username, new_password); + auth_type_oauth = G_OBJECT_TYPE (auth); + if (auth_type_oauth == E_TYPE_SOUP_AUTH_BEARER){ + ESoupAuthBearer *soup_auth_oauth = (ESoupAuthBearer *)auth; + e_soup_auth_bearer_set_access_token (soup_auth_oauth, new_password); + } else { + soup_auth_authenticate (auth, new_username, new_password); + } g_free (info->username); g_free (info->password); @@ -1860,6 +2071,7 @@ do_mount (GVfsBackend *backend, char *last_good_path; const char *host; const char *type; + SoupAuth *soup_auth_oauth; g_debug ("+ mount\n"); @@ -1923,6 +2135,31 @@ do_mount (GVfsBackend *backend, data->server_auth.pw_save = G_PASSWORD_SAVE_NEVER; data->proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER; + if (!g_strcmp0("webdav.yandex.ru",mount_base->host)){ + SoupAuthManager *auth_manager; + GType auth_type_outh; + soup_auth_oauth = g_object_new ( + E_TYPE_SOUP_AUTH_BEARER, + SOUP_AUTH_HOST, mount_base->host, NULL); + SoupSessionFeature *feature; + feature = soup_session_get_feature (session, SOUP_TYPE_AUTH_MANAGER); + auth_type_outh = G_OBJECT_TYPE (soup_auth_oauth); + + if (soup_session_feature_has_feature (feature, SOUP_TYPE_AUTH_BASIC)){ + soup_session_feature_remove_feature(feature, SOUP_TYPE_AUTH_BASIC); + } + + if (!soup_session_feature_has_feature (feature, auth_type_outh)) { + soup_session_feature_add_feature (feature, auth_type_outh); + } + + auth_manager = SOUP_AUTH_MANAGER (feature); + + soup_auth_manager_clear_cached_credentials (auth_manager); + soup_auth_manager_use_auth (auth_manager, mount_base, soup_auth_oauth); + g_object_unref(soup_auth_oauth); + } + signal_id = g_signal_connect (session, "authenticate", G_CALLBACK (soup_authenticate_interactive), data); -- 2.39.1