From b9efd68267d638e8373d87f0277204a84043688e Mon Sep 17 00:00:00 2001 From: Fikri Date: Wed, 8 Apr 2026 01:06:01 +0200 Subject: [PATCH 1/2] fix: escape special characters in environment variable keys for regex substitution Environment variable keys containing regex metacharacters (., *, +, ?, [], etc.) caused FormatException crashes when used in request fields. This fix properly escapes all special characters using RegExp.escape() before building the regex pattern. - Fixed substituteVariables function in lib/utils/envvar_utils.dart - Added comprehensive test cases for special characters, regex metacharacters, and mixed character scenarios - Resolves crash when using environment variables like 'api.key', 'user+id', etc. --- lib/utils/envvar_utils.dart | 3 ++- test/utils/envvar_utils_test.dart | 35 +++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lib/utils/envvar_utils.dart b/lib/utils/envvar_utils.dart index f817dd967c..e830e7785f 100644 --- a/lib/utils/envvar_utils.dart +++ b/lib/utils/envvar_utils.dart @@ -44,7 +44,8 @@ String? substituteVariables( if (envVarMap.keys.isEmpty) { return input; } - final regex = RegExp("{{(${envVarMap.keys.join('|')})}}"); + final escapedKeys = envVarMap.keys.map((key) => RegExp.escape(key)).join('|'); + final regex = RegExp("{{($escapedKeys)}}"); String result = input.replaceAllMapped(regex, (match) { final key = match.group(1)?.trim() ?? ''; diff --git a/test/utils/envvar_utils_test.dart b/test/utils/envvar_utils_test.dart index 8d43df8346..2b2138982e 100644 --- a/test/utils/envvar_utils_test.dart +++ b/test/utils/envvar_utils_test.dart @@ -168,6 +168,41 @@ void main() { String expected = "{{url1}}/humanize/social?num=8940000"; expect(substituteVariables(input, combinedEnvVarsMap), expected); }); + + test("Testing substituteVariables with special characters in variable keys", () { + Map envMap = { + "api.key": "value_with_dot", + "user+id": "value_with_plus", + "var*name": "value_with_asterisk", + "test[0]": "value_with_brackets", + }; + String input = "API: {{api.key}}, User: {{user+id}}, Var: {{var*name}}, Test: {{test[0]}}"; + String expected = "API: value_with_dot, User: value_with_plus, Var: value_with_asterisk, Test: value_with_brackets"; + expect(substituteVariables(input, envMap), expected); + }); + + test("Testing substituteVariables with regex metacharacters in keys", () { + Map envMap = { + "api\$key": "dollar_value", + "var^name": "caret_value", + "test|pipe": "pipe_value", + "back\\slash": "backslash_value", + }; + String input = "Dollar: {{api\$key}}, Caret: {{var^name}}, Pipe: {{test|pipe}}, Backslash: {{back\\slash}}"; + String expected = "Dollar: dollar_value, Caret: caret_value, Pipe: pipe_value, Backslash: backslash_value"; + expect(substituteVariables(input, envMap), expected); + }); + + test("Testing substituteVariables with mixed special and normal characters", () { + Map envMap = { + "normal_var": "normal", + "api.key": "dotted", + "user-id": "dashed", + }; + String input = "{{normal_var}}/{{api.key}}/{{user-id}}"; + String expected = "normal/dotted/dashed"; + expect(substituteVariables(input, envMap), expected); + }); }); group("Testing substituteHttpRequestModel function", () { From d3bfb1522a9c40664a192d1e3226baf87cae3573 Mon Sep 17 00:00:00 2001 From: Fikri Date: Tue, 14 Apr 2026 01:52:55 +0200 Subject: [PATCH 2/2] fix: prevent crash when filtering collection with AI requests The filter ListView force-unwrapped httpRequestModel to access its url, but httpRequestModel is null for APIType.ai requests. Typing anything in the search box with an AI request present caused an immediate crash. Changed to safe navigation with a false fallback so AI requests are matched by name only, consistent with how they are displayed. --- lib/screens/home_page/collection_pane.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/screens/home_page/collection_pane.dart b/lib/screens/home_page/collection_pane.dart index c62e3ce96d..695b704d9f 100644 --- a/lib/screens/home_page/collection_pane.dart +++ b/lib/screens/home_page/collection_pane.dart @@ -146,9 +146,10 @@ class _RequestListState extends ConsumerState { controller: controller, children: requestSequence.map((id) { var item = requestItems[id]!; - if (item.httpRequestModel!.url.toLowerCase().contains( - filterQuery, - ) || + if ((item.httpRequestModel?.url.toLowerCase().contains( + filterQuery, + ) ?? + false) || item.name.toLowerCase().contains(filterQuery)) { return Padding( padding: kP1,