dbus: Better handle local URI paths

Decode file URIs before trying to open them, and properly handle non-URI local paths.

(cherry picked from commit b8e8caf7c5)
This commit is contained in:
Frank Praznik
2026-04-06 19:22:13 -04:00
parent 6b73386987
commit ff2c970c15
3 changed files with 59 additions and 4 deletions

View File

@@ -384,6 +384,39 @@ int SDL_URIToLocal(const char *src, char *dst)
return -1;
}
bool SDL_IsURI(const char *uri)
{
/* A valid URI begins with a letter and is followed by any sequence of
* letters, digits, '+', '.', or '-'.
*/
if (!uri) {
return false;
}
// The first character of the scheme must be a letter.
if (!((*uri >= 'a' && *uri <= 'z') || (*uri >= 'A' && *uri <= 'Z'))) {
return false;
}
/* If the colon is found before encountering the end of the string or
* any invalid characters, the scheme can be considered valid.
*/
while (*uri) {
if (!((*uri >= 'a' && *uri <= 'z') ||
(*uri >= 'A' && *uri <= 'Z') ||
(*uri >= '0' && *uri <= '9') ||
*uri == '+' || *uri == '-' || *uri == '.')) {
return false;
}
if (*++uri == ':') {
return true;
}
}
return false;
}
// This is a set of per-thread persistent strings that we can return from the SDL API.
// This is used for short strings that might persist past the lifetime of the object
// they are related to.

View File

@@ -48,6 +48,9 @@ extern bool SDL_endswith(const char *string, const char *suffix);
*/
extern int SDL_URIToLocal(const char *src, char *dst);
/// Determine if a URI is valid by validating the scheme.
extern bool SDL_IsURI(const char *uri);
typedef enum
{
SDL_OBJECT_TYPE_UNKNOWN,

View File

@@ -487,14 +487,31 @@ bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activa
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;
const bool has_file_scheme = SDL_strncasecmp(uri, "file:/", 6) == 0;
if (SDL_strncasecmp(uri, "file://", 7) == 0) {
fd = open(uri + 7, O_RDWR | O_CLOEXEC);
// The OpenURI method can't open 'file://' URIs or local paths, so OpenFile must be used instead.
if (has_file_scheme || !SDL_IsURI(uri)) {
char *decoded_path = NULL;
// Decode the path if it is a URI.
if (has_file_scheme) {
const size_t len = SDL_strlen(uri) + 1;
decoded_path = SDL_malloc(len);
if (!decoded_path) {
goto done;
}
if (SDL_URIToLocal(uri, decoded_path) < 0) {
SDL_free(decoded_path);
goto done;
}
uri = decoded_path;
}
fd = open(uri, O_RDWR | O_CLOEXEC);
SDL_free(decoded_path);
if (fd >= 0) {
msg = dbus.message_new_method_call(bus_name, path, interface, "OpenFile");
}
@@ -548,7 +565,9 @@ bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activa
}
done:
dbus.message_unref(msg);
if (msg) {
dbus.message_unref(msg);
}
// The file descriptor is duplicated by D-Bus, so it can be closed on this end.
if (fd >= 0) {