From 33090dc31870e71f756ab8292d6c1cc1e06662bf Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
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.
(cherry picked from commit 0a54fdb8624f47eae1c796e3cddf475481d948fd)
---
src/core/linux/SDL_dbus.c | 48 +++++++++++++++++++++++++++++++--------
1 file changed, 39 insertions(+), 9 deletions(-)
diff --git a/src/core/linux/SDL_dbus.c b/src/core/linux/SDL_dbus.c
index df114e0e19189..3b1f095a23c0b 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 <fcntl.h>
+#include <unistd.h>
+
#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,19 +487,42 @@ 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");
+ // 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 (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 (!msg) {
- return false;
+ goto done;
}
+ dbus.message_iter_init_append(msg, &iterInit);
+
if (!window_id) {
window_id = "";
}
- if (!dbus.message_append_args(msg, DBUS_TYPE_STRING, &window_id, DBUS_TYPE_STRING, &uri, DBUS_TYPE_INVALID)) {
+ if (!dbus.message_iter_append_basic(&iterInit, DBUS_TYPE_STRING, &window_id)) {
goto done;
}
- dbus.message_iter_init_append(msg, &iterInit);
+ 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)) {
@@ -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;
}