Просмотр исходного кода

dbus: Better handle local URI paths

Decode file URIs before trying to open them, and properly handle non-URI local paths.
Frank Praznik 1 день назад
Родитель
Сommit
b8e8caf7c5
3 измененных файлов с 60 добавлено и 5 удалено
  1. 33 0
      src/SDL_utils.c
  2. 3 0
      src/SDL_utils_c.h
  3. 24 5
      src/core/linux/SDL_dbus.c

+ 33 - 0
src/SDL_utils.c

@@ -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.

+ 3 - 0
src/SDL_utils_c.h

@@ -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,

+ 24 - 5
src/core/linux/SDL_dbus.c

@@ -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;
-
-    if (SDL_strncasecmp(uri, "file://", 7) == 0) {
-        fd = open(uri + 7, O_RDWR | O_CLOEXEC);
+    const bool has_file_scheme = SDL_strncasecmp(uri, "file:/", 6) == 0;
+
+    // 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) {