From abde372ea0188d7c1ca7a183b5a5be152e7a377b Mon Sep 17 00:00:00 2001 From: Sergey Cherevko Date: Fri, 15 Mar 2024 12:34:26 +0300 Subject: [PATCH] Added yandex disk webdav support (by Alexey Berezhok ) --- daemon/gvfsbackenddav.c | 242 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 240 insertions(+), 2 deletions(-) diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c index 967f1db..7d6814e 100644 --- a/daemon/gvfsbackenddav.c +++ b/daemon/gvfsbackenddav.c @@ -114,6 +114,205 @@ 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) { @@ -1488,6 +1687,7 @@ soup_authenticate_interactive (SoupSession *session, char *new_username; char *new_password; char *prompt; + GType auth_type_oauth; g_debug ("+ soup_authenticate_interactive (%s) \n", retrying ? "retrying" : "first auth"); @@ -1555,7 +1755,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; } @@ -1591,7 +1797,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); @@ -1820,6 +2032,7 @@ do_mount (GVfsBackend *backend, char *last_good_path; const char *host; const char *type; + SoupAuth *soup_auth_oauth; g_debug ("+ mount\n"); @@ -1876,6 +2089,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.3