Browse Source

Make SDL_URIToLocal available to multiple platforms

Moves the functions out of core/unix into SDL_utils.c
Frank Praznik 9 months ago
parent
commit
6a74ade73d

+ 114 - 0
src/SDL_utils.c

@@ -22,6 +22,10 @@
 
 #include "SDL_hashtable.h"
 
+#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE)
+#include <unistd.h>
+#endif
+
 /* Common utility functions that aren't in the public API */
 
 int SDL_powerof2(int x)
@@ -206,3 +210,113 @@ void SDL_SetObjectsInvalid(void)
         SDL_objects = NULL;
     }
 }
+
+static int SDL_URIDecode(const char *src, char *dst, int len)
+{
+    int ri, wi, di;
+    char decode = '\0';
+    if (!src || !dst || len < 0) {
+        return -1;
+    }
+    if (len == 0) {
+        len = SDL_strlen(src);
+    }
+    for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
+        if (di == 0) {
+            /* start decoding */
+            if (src[ri] == '%') {
+                decode = '\0';
+                di += 1;
+                continue;
+            }
+            /* normal write */
+            dst[wi] = src[ri];
+            wi += 1;
+        } else if (di == 1 || di == 2) {
+            char off = '\0';
+            char isa = src[ri] >= 'a' && src[ri] <= 'f';
+            char isA = src[ri] >= 'A' && src[ri] <= 'F';
+            char isn = src[ri] >= '0' && src[ri] <= '9';
+            if (!(isa || isA || isn)) {
+                /* not a hexadecimal */
+                int sri;
+                for (sri = ri - di; sri <= ri; sri += 1) {
+                    dst[wi] = src[sri];
+                    wi += 1;
+                }
+                di = 0;
+                continue;
+            }
+            /* itsy bitsy magicsy */
+            if (isn) {
+                off = 0 - '0';
+            } else if (isa) {
+                off = 10 - 'a';
+            } else if (isA) {
+                off = 10 - 'A';
+            }
+            decode |= (src[ri] + off) << (2 - di) * 4;
+            if (di == 2) {
+                dst[wi] = decode;
+                wi += 1;
+                di = 0;
+            } else {
+                di += 1;
+            }
+        }
+    }
+    dst[wi] = '\0';
+    return wi;
+}
+
+int SDL_URIToLocal(const char *src, char *dst)
+{
+    if (SDL_memcmp(src, "file:/", 6) == 0) {
+        src += 6; /* local file? */
+    } else if (SDL_strstr(src, ":/") != NULL) {
+        return -1; /* wrong scheme */
+    }
+
+    SDL_bool local = src[0] != '/' || (src[0] != '\0' && src[1] == '/');
+
+    /* Check the hostname, if present. RFC 3986 states that the hostname component of a URI is not case-sensitive. */
+    if (!local && src[0] == '/' && src[2] != '/') {
+        char *hostname_end = SDL_strchr(src + 1, '/');
+        if (hostname_end) {
+            const size_t src_len = hostname_end - (src + 1);
+            size_t hostname_len;
+
+#if defined(SDL_PLATFORM_UNIX) || defined(SDL_PLATFORM_APPLE)
+            char hostname[257];
+            if (gethostname(hostname, 255) == 0) {
+                hostname[256] = '\0';
+                hostname_len = SDL_strlen(hostname);
+                if (hostname_len == src_len && SDL_strncasecmp(src + 1, hostname, src_len) == 0) {
+                    src = hostname_end + 1;
+                    local = SDL_TRUE;
+                }
+            }
+#endif
+
+            if (!local) {
+                static const char *localhost = "localhost";
+                hostname_len = SDL_strlen(localhost);
+                if (hostname_len == src_len && SDL_strncasecmp(src + 1, localhost, src_len) == 0) {
+                    src = hostname_end + 1;
+                    local = SDL_TRUE;
+                }
+            }
+        }
+    }
+
+    if (local) {
+        /* Convert URI escape sequences to real characters */
+        if (src[0] == '/') {
+            src++;
+        } else {
+            src--;
+        }
+        return SDL_URIDecode(src, dst, 0);
+    }
+    return -1;
+}

+ 13 - 0
src/SDL_utils_c.h

@@ -32,6 +32,19 @@ extern void SDL_CalculateFraction(float x, int *numerator, int *denominator);
 
 extern SDL_bool SDL_endswith(const char *string, const char *suffix);
 
+/** Convert URI to a local filename, stripping the "file://"
+ *  preamble and hostname if present, and writes the result
+ *  to the dst buffer. Since URI-encoded characters take
+ *  three times the space of normal characters, src and dst
+ *  can safely point to the same buffer for in situ conversion.
+ *
+ *  Returns the number of decoded bytes that wound up in
+ *  the destination buffer, excluding the terminating NULL byte.
+ *
+ *  On error, -1 is returned.
+ */
+extern int SDL_URIToLocal(const char *src, char *dst);
+
 typedef enum
 {
     SDL_OBJECT_TYPE_UNKNOWN,

+ 0 - 123
src/core/unix/SDL_uri_decode.c

@@ -1,123 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "SDL_internal.h"
-
-#include "SDL_uri_decode.h"
-#include <errno.h>
-#include <unistd.h>
-
-int SDL_URIDecode(const char *src, char *dst, int len)
-{
-    int ri, wi, di;
-    char decode = '\0';
-    if (!src || !dst || len < 0) {
-        errno = EINVAL;
-        return -1;
-    }
-    if (len == 0) {
-        len = SDL_strlen(src);
-    }
-    for (ri = 0, wi = 0, di = 0; ri < len && wi < len; ri += 1) {
-        if (di == 0) {
-            /* start decoding */
-            if (src[ri] == '%') {
-                decode = '\0';
-                di += 1;
-                continue;
-            }
-            /* normal write */
-            dst[wi] = src[ri];
-            wi += 1;
-            continue;
-        } else if (di == 1 || di == 2) {
-            char off = '\0';
-            char isa = src[ri] >= 'a' && src[ri] <= 'f';
-            char isA = src[ri] >= 'A' && src[ri] <= 'F';
-            char isn = src[ri] >= '0' && src[ri] <= '9';
-            if (!(isa || isA || isn)) {
-                /* not a hexadecimal */
-                int sri;
-                for (sri = ri - di; sri <= ri; sri += 1) {
-                    dst[wi] = src[sri];
-                    wi += 1;
-                }
-                di = 0;
-                continue;
-            }
-            /* itsy bitsy magicsy */
-            if (isn) {
-                off = 0 - '0';
-            } else if (isa) {
-                off = 10 - 'a';
-            } else if (isA) {
-                off = 10 - 'A';
-            }
-            decode |= (src[ri] + off) << (2 - di) * 4;
-            if (di == 2) {
-                dst[wi] = decode;
-                wi += 1;
-                di = 0;
-            } else {
-                di += 1;
-            }
-            continue;
-        }
-    }
-    dst[wi] = '\0';
-    return wi;
-}
-
-int SDL_URIToLocal(const char *src, char *dst)
-{
-    if (SDL_memcmp(src, "file:/", 6) == 0) {
-        src += 6; /* local file? */
-    } else if (SDL_strstr(src, ":/") != NULL) {
-        return -1; /* wrong scheme */
-    }
-
-    SDL_bool local = src[0] != '/' || (src[0] != '\0' && src[1] == '/');
-
-    /* got a hostname? */
-    if (!local && src[0] == '/' && src[2] != '/') {
-        char *hostname_end = SDL_strchr(src + 1, '/');
-        if (hostname_end) {
-            char hostname[257];
-            if (gethostname(hostname, 255) == 0) {
-                hostname[256] = '\0';
-                if (SDL_memcmp(src + 1, hostname, hostname_end - (src + 1)) == 0) {
-                    src = hostname_end + 1;
-                    local = SDL_TRUE;
-                }
-            }
-        }
-    }
-    if (local) {
-        /* Convert URI escape sequences to real characters */
-        if (src[0] == '/') {
-            src++;
-        } else {
-            src--;
-        }
-        return SDL_URIDecode(src, dst, 0);
-    }
-    return -1;
-}

+ 0 - 56
src/core/unix/SDL_uri_decode.h

@@ -1,56 +0,0 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "SDL_internal.h"
-
-#ifndef SDL_uri_decode_h_
-#define SDL_uri_decode_h_
-
-/* Decodes URI escape sequences in string src of len bytes
- * (excluding the terminating NULL byte) into the dst buffer.
- * Since URI-encoded characters take three times the space of
- * normal characters, src and dst can safely point to the same
- * buffer for in situ conversion.
- *
- * The buffer is guaranteed to be NULL-terminated, but
- * may contain embedded NULL bytes.
- *
- * Returns the number of decoded bytes that wound up in
- * the destination buffer, excluding the terminating NULL byte.
- *
- * On error, -1 is returned.
- */
-int SDL_URIDecode(const char *src, char *dst, int len);
-
-/* Convert URI to a local filename, stripping the "file://"
- * preamble and hostname if present, and writes the result
- * to the dst buffer. Since URI-encoded characters take
- * three times the space of normal characters, src and dst
- * can safely point to the same buffer for in situ conversion.
- *
- * Returns the number of decoded bytes that wound up in
- * the destination buffer, excluding the terminating NULL byte.
- *
- * On error, -1 is returned;
- */
-int SDL_URIToLocal(const char *src, char *dst);
-
-#endif /* SDL_uri_decode_h_ */

+ 0 - 1
src/dialog/unix/SDL_portaldialog.c

@@ -22,7 +22,6 @@
 #include "../SDL_dialog_utils.h"
 
 #include "../../core/linux/SDL_dbus.h"
-#include "../../core/unix/SDL_uri_decode.h"
 
 #ifdef SDL_USE_LIBDBUS
 

+ 0 - 1
src/video/wayland/SDL_waylandevents.c

@@ -24,7 +24,6 @@
 #ifdef SDL_VIDEO_DRIVER_WAYLAND
 
 #include "../../core/unix/SDL_poll.h"
-#include "../../core/unix/SDL_uri_decode.h"
 #include "../../events/SDL_events_c.h"
 #include "../../events/SDL_scancode_tables_c.h"
 #include "../../core/linux/SDL_system_theme.h"

+ 0 - 1
src/video/x11/SDL_x11events.c

@@ -36,7 +36,6 @@
 #include "SDL_x11settings.h"
 #include "../SDL_clipboard_c.h"
 #include "../../core/unix/SDL_poll.h"
-#include "../../core/unix/SDL_uri_decode.h"
 #include "../../events/SDL_events_c.h"
 #include "../../events/SDL_mouse_c.h"
 #include "../../events/SDL_touch_c.h"