mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-27 10:57:22 +08:00
dbus: Better handle local URI paths
Decode file URIs before trying to open them, and properly handle non-URI local paths.
This commit is contained in:
@@ -384,6 +384,39 @@ int SDL_URIToLocal(const char *src, char *dst)
|
|||||||
return -1;
|
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 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
|
// This is used for short strings that might persist past the lifetime of the object
|
||||||
// they are related to.
|
// they are related to.
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ extern bool SDL_endswith(const char *string, const char *suffix);
|
|||||||
*/
|
*/
|
||||||
extern int SDL_URIToLocal(const char *src, char *dst);
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
SDL_OBJECT_TYPE_UNKNOWN,
|
SDL_OBJECT_TYPE_UNKNOWN,
|
||||||
|
|||||||
@@ -487,14 +487,31 @@ bool SDL_DBus_OpenURI(const char *uri, const char *window_id, const char *activa
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The OpenURI method can't open local 'file://' URIs, so OpenFile must be used instead.
|
|
||||||
DBusMessageIter iterInit;
|
DBusMessageIter iterInit;
|
||||||
DBusMessage *msg = NULL;
|
DBusMessage *msg = NULL;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
const bool has_file_scheme = SDL_strncasecmp(uri, "file:/", 6) == 0;
|
||||||
|
|
||||||
if (SDL_strncasecmp(uri, "file://", 7) == 0) {
|
// The OpenURI method can't open 'file://' URIs or local paths, so OpenFile must be used instead.
|
||||||
fd = open(uri + 7, O_RDWR | O_CLOEXEC);
|
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) {
|
if (fd >= 0) {
|
||||||
msg = dbus.message_new_method_call(bus_name, path, interface, "OpenFile");
|
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:
|
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.
|
// The file descriptor is duplicated by D-Bus, so it can be closed on this end.
|
||||||
if (fd >= 0) {
|
if (fd >= 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user