SDL: dialog: Use case-insensitive filter matching on portal dialogs

From 387439d00917c6e416592aaa467dce617e6024b5 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Tue, 21 Apr 2026 10:02:22 -0400
Subject: [PATCH] dialog: Use case-insensitive filter matching on portal
 dialogs

On most implementations, filter pattern matching is case-sensitive. For case-insensitive matching of a pattern such as '*.png', the pattern *.[pP][nN][gG]' must be used.
---
 src/dialog/unix/SDL_portaldialog.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/dialog/unix/SDL_portaldialog.c b/src/dialog/unix/SDL_portaldialog.c
index 7949a330d18e0..c0f957c8e2761 100644
--- a/src/dialog/unix/SDL_portaldialog.c
+++ b/src/dialog/unix/SDL_portaldialog.c
@@ -86,10 +86,25 @@ static void DBus_AppendFilter(SDL_DBusContext *dbus, DBusMessageIter *parent, co
     dbus->message_iter_append_basic(&filter_entry, DBUS_TYPE_STRING, &filter.name);
     dbus->message_iter_open_container(&filter_entry, DBUS_TYPE_ARRAY, "(us)", &filter_array);
 
-    patterns = SDL_strdup(filter.pattern);
+    /* Copy the filter string, converting to a case-insensitive version.
+     * For example, for case-insensitive matching of '*.png', the pattern '*.[pP][nN][gG]' is used.
+     */
+    const size_t len = SDL_strlen(filter.pattern) + 1;
+    patterns = SDL_malloc(len * 4); // Single characters may be expanded to 4 characters.
     if (!patterns) {
         goto cleanup;
     }
+    for (size_t i = 0, p = 0; i < len; ++i) {
+        if ((filter.pattern[i] >= 'a' && filter.pattern[i] <= 'z') ||
+            (filter.pattern[i] >= 'A' && filter.pattern[i] <= 'Z')) {
+            patterns[p++] = '[';
+            patterns[p++] = SDL_tolower(filter.pattern[i]);
+            patterns[p++] = SDL_toupper(filter.pattern[i]);
+            patterns[p++] = ']';
+        } else {
+            patterns[p++] = filter.pattern[i];
+        }
+    }
 
     pattern = SDL_strtok_r(patterns, ";", &state);
     while (pattern) {