From 0a54fdb8624f47eae1c796e3cddf475481d948fd Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 6 Apr 2026 11:11:23 -0400 Subject: [PATCH] dbus: Use OpenFile for opening local 'file://' URIs Per the spec, OpenURI can't open local paths, so OpenFile needs to be used instead. --- src/core/linux/SDL_dbus.c | 54 ++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c index df114e0e19..3b1f095a23 100644 --- a/src/core/linux/SDL_dbus.c +++ b/src/core/linux/SDL_dbus.c @@ -22,6 +22,9 @@ #include "SDL_dbus.h" #include "../../stdlib/SDL_vacopy.h" +#include +#include + #ifdef SDL_USE_LIBDBUS // we never link directly to libdbus. #define SDL_DRIVER_DBUS_DYNAMIC "libdbus-1.so.3" @@ -473,11 +476,9 @@ static bool SDL_DBus_AppendDictWithKeyValue(DBusMessageIter *iterInit, const cha bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activation_token) { - const char *bus_name = "org.freedesktop.portal.Desktop"; - const char *path = "/org/freedesktop/portal/desktop"; - const char *interface = "org.freedesktop.portal.OpenURI"; - DBusMessageIter iterInit; - bool ret = false; + static const char *bus_name = "org.freedesktop.portal.Desktop"; + static const char *path = "/org/freedesktop/portal/desktop"; + static const char *interface = "org.freedesktop.portal.OpenURI"; if (!dbus.session_conn) { /* We either lost connection to the session bus or were not able to @@ -486,20 +487,43 @@ bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activa return false; } - DBusMessage *msg = dbus.message_new_method_call(bus_name, path, interface, "OpenURI"); - if (!msg) { - return false; - } + // The OpenURI method can't open local 'file://' URIs, so OpenFile must be used instead. + DBusMessageIter iterInit; + DBusMessage *msg = NULL; + int fd = -1; + bool ret = false; - if (!window_id) { - window_id = ""; + if (SDL_strncasecmp(uri, "file://", 7) == 0) { + fd = open(uri + 7, O_RDWR | O_CLOEXEC); + if (fd >= 0) { + msg = dbus.message_new_method_call(bus_name, path, interface, "OpenFile"); + } + } else { + msg = dbus.message_new_method_call(bus_name, path, interface, "OpenURI"); } - if (!dbus.message_append_args(msg, DBUS_TYPE_STRING, &window_id, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID)) { + if (!msg) { goto done; } dbus.message_iter_init_append(msg, &iterInit); + if (!window_id) { + window_id = ""; + } + if (!dbus.message_iter_append_basic(&iterInit, DBUS_TYPE_STRING, &window_id)) { + goto done; + } + + if (fd >= 0) { + if (!dbus.message_iter_append_basic(&iterInit, DBUS_TYPE_UNIX_FD, &fd)) { + goto done; + } + } else { + if (!dbus.message_iter_append_basic(&iterInit, DBUS_TYPE_STRING, &uri)) { + goto done; + } + } + if (activation_token) { if (!SDL_DBus_AppendDictWithKeyValue(&iterInit, "activation_token", activation_token)) { goto done; @@ -525,6 +549,12 @@ bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activa done: dbus.message_unref(msg); + + // The file descriptor is duplicated by D-Bus, so it can be closed on this end. + if (fd >= 0) { + close(fd); + } + return ret; }