From 20b4715a361e135ee33ba3af440821a893d62b84 Mon Sep 17 00:00:00 2001 From: Dmitry Samoylik Date: Mon, 10 Feb 2025 15:02:13 +0300 Subject: [PATCH] Added yandex disk webdav support --- daemon/gvfsbackenddav.c | 159 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/daemon/gvfsbackenddav.c b/daemon/gvfsbackenddav.c index 3be104f..76c7e4c 100644 --- a/daemon/gvfsbackenddav.c +++ b/daemon/gvfsbackenddav.c @@ -124,6 +124,129 @@ 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*/ + +G_BEGIN_DECLS + +#define SOUP_TYPE_AUTH_BEARER (soup_auth_bearer_get_type ()) + +SOUP_AVAILABLE_IN_ALL +G_DECLARE_FINAL_TYPE (SoupAuthBearer, soup_auth_bearer, SOUP, AUTH_BEARER, SoupAuth) + +G_END_DECLS + +struct _SoupAuthBearer { + SoupAuth parent; +}; + +typedef struct { + char *token; +} SoupAuthBearerPrivate; + +G_DEFINE_FINAL_TYPE_WITH_PRIVATE (SoupAuthBearer, soup_auth_bearer, SOUP_TYPE_AUTH) + +static void +soup_auth_bearer_init (SoupAuthBearer *basic) +{ +} + +static void +soup_auth_bearer_finalize (GObject *object) +{ + SoupAuthBearerPrivate *priv = soup_auth_bearer_get_instance_private (SOUP_AUTH_BEARER (object)); + + g_free (priv->token); + + G_OBJECT_CLASS (soup_auth_bearer_parent_class)->finalize (object); +} + +static gboolean +soup_auth_bearer_update (SoupAuth *auth, SoupMessage *msg, + GHashTable *auth_params) +{ + SoupAuthBearerPrivate *priv = soup_auth_bearer_get_instance_private (SOUP_AUTH_BEARER (auth)); + + /* If we're updating a pre-existing auth, the + * username/password must be bad now, so forget it. + * Other than that, there's nothing to do here. + */ + if (priv->token) { + memset (priv->token, 0, strlen (priv->token)); + g_free (priv->token); + priv->token = NULL; + } + + return TRUE; +} + +static GSList * +soup_auth_bearer_get_protection_space (SoupAuth *auth, GUri *source_uri) +{ + char *space, *p; + + space = g_strdup (g_uri_get_path (source_uri)); + + /* Strip filename component */ + p = strrchr (space, '/'); + if (p == space && p[1]) + p[1] = '\0'; + else if (p && p[1]) + *p = '\0'; + + return g_slist_prepend (NULL, space); +} + +static void +soup_auth_bearer_authenticate (SoupAuth *auth, const char *username, + const char *password) +{ + SoupAuthBearerPrivate *priv = soup_auth_bearer_get_instance_private (SOUP_AUTH_BEARER (auth)); + + if (priv->token) { + memset (priv->token, 0, strlen (priv->token)); + g_free (priv->token); + } + priv->token = g_strdup(password); +} + +static gboolean +soup_auth_bearer_is_authenticated (SoupAuth *auth) +{ + SoupAuthBearerPrivate *priv = soup_auth_bearer_get_instance_private (SOUP_AUTH_BEARER (auth)); + + return priv->token != NULL; +} + +static char * +soup_auth_bearer_get_authorization (SoupAuth *auth, SoupMessage *msg) +{ + SoupAuthBearerPrivate *priv = soup_auth_bearer_get_instance_private (SOUP_AUTH_BEARER (auth)); + + return g_strdup_printf ("OAuth %s", priv->token); +} + +static void +soup_auth_bearer_class_init (SoupAuthBearerClass *auth_basic_class) +{ + SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_basic_class); + GObjectClass *object_class = G_OBJECT_CLASS (auth_basic_class); + + auth_class->scheme_name = "Basic"; + auth_class->strength = 1; + + auth_class->update =soup_auth_bearer_update; + auth_class->get_protection_space =soup_auth_bearer_get_protection_space; + auth_class->authenticate =soup_auth_bearer_authenticate; + auth_class->is_authenticated =soup_auth_bearer_is_authenticated; + auth_class->get_authorization =soup_auth_bearer_get_authorization; + + object_class->finalize =soup_auth_bearer_finalize; +} + +/* +end of Yandex ouath +*/ + static void g_vfs_backend_dav_finalize (GObject *object) { @@ -1668,6 +1791,8 @@ soup_authenticate (SoupMessage *msg, char *new_password; char *prompt; + GType auth_type_oauth; + data = (MountAuthData *) user_data; is_proxy = soup_auth_is_for_proxy (auth); @@ -1800,7 +1925,10 @@ soup_authenticate (SoupMessage *msg, /* it's not safe to assume that we get the username filed in, in the case that we provied a default username */ if (new_username == NULL) + { new_username = g_strdup (info->username); + soup_auth_authenticate (auth, new_username, new_password); + } soup_auth_authenticate (auth, new_username, new_password); @@ -2346,6 +2474,8 @@ try_mount_send_opts (GVfsJobMount *job, GVfsBackendDav *dav_backend = G_VFS_BACKEND_DAV (job->backend); GVfsBackendHttp *http_backend = G_VFS_BACKEND_HTTP (job->backend); SoupMessage *msg_opts; + SoupAuth *soup_auth_oauth; + char *authority; if (http_backend->mount_base == NULL) { @@ -2367,6 +2497,35 @@ try_mount_send_opts (GVfsJobMount *job, dav_backend->auth_info.proxy_auth.pw_save = G_PASSWORD_SAVE_NEVER; dav_backend->auth_info.interactive = TRUE; + if (!g_strcmp0("webdav.yandex.ru", g_uri_get_host(http_backend->mount_base))){ + SoupAuthManager *auth_manager; + GType auth_type_outh; + + authority = g_strdup_printf ("%s:%d", g_uri_get_host (http_backend->mount_base), g_uri_get_port (http_backend->mount_base)); + soup_auth_oauth = g_object_new (SOUP_TYPE_AUTH_BEARER, "authority", authority, NULL); + g_free (authority); + + SoupSessionFeature *feature; + feature = soup_session_get_feature (http_backend->session, SOUP_TYPE_AUTH_MANAGER); + auth_type_outh = G_OBJECT_TYPE (soup_auth_oauth); + + if (soup_session_has_feature (http_backend->session, SOUP_TYPE_AUTH_BASIC)){ + soup_session_remove_feature_by_type(http_backend->session, SOUP_TYPE_AUTH_BASIC); + } + + if (!soup_session_has_feature (http_backend->session, auth_type_outh)) { + soup_session_add_feature_by_type (http_backend->session, auth_type_outh); + } + + auth_manager = SOUP_AUTH_MANAGER (feature); + + soup_auth_manager_clear_cached_credentials (auth_manager); + + soup_auth_manager_use_auth (auth_manager, http_backend->mount_base, soup_auth_oauth); + + g_object_unref(soup_auth_oauth); + } + dav_backend->last_good_path = NULL; msg_opts = soup_message_new_from_uri (SOUP_METHOD_OPTIONS, http_backend->mount_base); -- 2.39.5