From 27194b7903b3b0d8caf1cbe3a68270cafa2d725c Mon Sep 17 00:00:00 2001 From: Jan Horak Date: Wed, 15 Jan 2025 13:53:43 +0100 Subject: [PATCH] Try harder to find the host path for the documents When the access to the directory is provided by the portal (like browser download directory) the stored files in the directory are not found by xdp_get_real_path_for_doc_path and /run/user/... path is opened instead of host path by the OpenFile or OpenDirectory portal. This fix tries to recreate host path from the document id and rest of the given path. --- src/file-chooser.c | 41 +++-------------------------------------- src/open-uri.c | 31 +++++++++++++++++++++++++++++-- src/xdp-utils.c | 37 +++++++++++++++++++++++++++++++++++++ src/xdp-utils.h | 1 + 4 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/file-chooser.c b/src/file-chooser.c index 7beebf460..201b972d9 100644 --- a/src/file-chooser.c +++ b/src/file-chooser.c @@ -155,41 +155,6 @@ send_response_in_thread_func (GTask *task, g_task_return_boolean (task, TRUE); } -/* Calling Lookup on a nonexisting path does not work, so we - * pull the doc id out of the path manually. - */ -static gboolean -looks_like_document_portal_path (const char *path, - char **guessed_docid) -{ - const char *prefix = "/run/user/"; - char *docid; - char *p, *q; - - if (!g_str_has_prefix (path, prefix)) - return FALSE; - - p = strstr (path, "/doc/"); - if (!p) - return FALSE; - - p += strlen ("/doc/"); - q = strchr (p, '/'); - if (q) - docid = g_strndup (p, q - p); - else - docid = g_strdup (p); - - if (docid[0] == '\0') - { - g_free (docid); - return FALSE; - } - - *guessed_docid = docid; - return TRUE; -} - static char * get_host_folder_for_doc_id (const char *doc_id) { @@ -555,7 +520,7 @@ handle_open_file (XdpDbusFileChooser *object, const char *path_from_app = g_variant_get_bytestring (value); g_autofree char *host_path = g_strdup (path_from_app); g_autofree char *doc_id_from_app = NULL; - if (looks_like_document_portal_path (host_path, &doc_id_from_app)) + if (xdp_looks_like_document_portal_path (host_path, &doc_id_from_app)) { char *real_path = get_host_folder_for_doc_id (doc_id_from_app); if (real_path) @@ -696,7 +661,7 @@ handle_save_file (XdpDbusFileChooser *object, g_autofree char *doc_id = NULL; if (strcmp (path, host_path) == 0 && - looks_like_document_portal_path (path, &doc_id)) + xdp_looks_like_document_portal_path (path, &doc_id)) { char *real_path = xdp_get_real_path_for_doc_id (doc_id); @@ -721,7 +686,7 @@ handle_save_file (XdpDbusFileChooser *object, const char *path_from_app = g_variant_get_bytestring (value); g_autofree char *host_path = g_strdup (path_from_app); g_autofree char *doc_id_from_app = NULL; - if (looks_like_document_portal_path (host_path, &doc_id_from_app)) + if (xdp_looks_like_document_portal_path (host_path, &doc_id_from_app)) { char *real_path = get_host_folder_for_doc_id (doc_id_from_app); if (real_path) diff --git a/src/open-uri.c b/src/open-uri.c index b5447c2ef..148dbbb59 100644 --- a/src/open-uri.c +++ b/src/open-uri.c @@ -585,6 +585,23 @@ app_exists (const char *app_id) return (info != NULL); } +static char* +build_host_path_from_doc_id(const char* doc_id, const char* doc_path) +{ + gchar *result; + g_autofree char *host_path = xdp_get_real_path_for_doc_id (doc_id); + g_autofree char *doc_path_regex = g_strconcat("/run/user/[0-9]+/doc/", doc_id, "/[^/]+(.*)", NULL); + gchar **path_postfix = g_regex_split_simple(doc_path_regex, doc_path, 0, 0); + + if (path_postfix[0] && path_postfix[1]) { + result = g_strconcat(host_path, path_postfix[1], NULL); + } else { + result = g_strdup(host_path); + } + g_strfreev (path_postfix); + return result; +} + static void handle_open_in_thread_func (GTask *task, gpointer source_object, @@ -688,7 +705,11 @@ handle_open_in_thread_func (GTask *task, if (path != NULL) { - host_path = xdp_get_real_path_for_doc_path (path, request->app_info); + g_autofree char *guessed_docid = NULL; + if (xdp_looks_like_document_portal_path(path, &guessed_docid)) + { + host_path = build_host_path_from_doc_id(guessed_docid, path); + } if (host_path) { g_debug ("OpenFile: translating path value '%s' to host path '%s'", path, host_path); @@ -724,7 +745,13 @@ handle_open_in_thread_func (GTask *task, if (open_dir) { - g_autofree char *real_path = xdp_get_real_path_for_doc_path (path, request->app_info); + g_autofree char *guessed_docid = NULL; + g_autofree char *real_path = NULL; + if (xdp_looks_like_document_portal_path(path, &guessed_docid)) { + real_path = build_host_path_from_doc_id(guessed_docid, path); + } else { + real_path = g_strdup(path); + } /* Try opening the directory via the file manager interface, then fall back to a plain URI open */ g_autoptr(GError) local_error = NULL; diff --git a/src/xdp-utils.c b/src/xdp-utils.c index 902bb3199..63b615359 100644 --- a/src/xdp-utils.c +++ b/src/xdp-utils.c @@ -284,6 +284,43 @@ is_valid_name_character (gint c, gboolean allow_dash) (c == '_') || (allow_dash && c == '-'); } + +/* Get the document id from the path, if there's any. + * Returns TRUE when path seems to point to the documents + * storage. + */ +gboolean +xdp_looks_like_document_portal_path (const char *path, + char **guessed_docid) +{ + const char *prefix = "/run/user/"; + char *docid; + char *p, *q; + + if (!g_str_has_prefix (path, prefix)) + return FALSE; + + p = strstr (path, "/doc/"); + if (!p) + return FALSE; + + p += strlen ("/doc/"); + q = strchr (p, '/'); + if (q) + docid = g_strndup (p, q - p); + else + docid = g_strdup (p); + + if (docid[0] == '\0') + { + g_free (docid); + return FALSE; + } + + *guessed_docid = docid; + return TRUE; +} + /* This is the same as flatpak apps, except we also allow names to start with digits, and two-element names so that ids of the form snap.$snapname is allowed for all snap names. */ diff --git a/src/xdp-utils.h b/src/xdp-utils.h index 59a18d67c..c3f89921c 100644 --- a/src/xdp-utils.h +++ b/src/xdp-utils.h @@ -66,6 +66,7 @@ G_DEFINE_AUTO_CLEANUP_FREE_FUNC(XdpFd, close, -1) void xdp_set_documents_mountpoint (const char *path); const char * xdp_get_documents_mountpoint (void); char * xdp_get_alternate_document_path (const char *path, const char *app_id); +gboolean xdp_looks_like_document_portal_path (const char *path, char **guessed_docid); void xdp_connection_track_name_owners (GDBusConnection *connection, XdpPeerDiedCallback peer_died_cb);