diff options
| author | 2024-10-22 16:00:07 +0200 | |
|---|---|---|
| committer | 2024-10-22 16:00:07 +0200 | |
| commit | 60dd22d3b3916f5113954fc1472b1658c3c4245f (patch) | |
| tree | 1c895a8a6363d5dfb3effb452724d1c0f22fa4ad /app | |
| parent | da4b85624fc4426b94b3ee98e9e11cbb7e9af7f1 (diff) | |
Allow regex parentheses (#6926)
* Allow regex parentheses
While waiting for a new better search parser, auto-escape parentheses in regex expressions to allow them like in `/^(ab|cd)/`
* Allow escaped parenthesis in regex
* A couple more tests
Diffstat (limited to 'app')
| -rw-r--r-- | app/Models/BooleanSearch.php | 15 | ||||
| -rw-r--r-- | app/Models/Search.php | 1 |
2 files changed, 16 insertions, 0 deletions
diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php index 10c2321fb..749dbdfa5 100644 --- a/app/Models/BooleanSearch.php +++ b/app/Models/BooleanSearch.php @@ -37,6 +37,7 @@ class FreshRSS_BooleanSearch { if ($level === 0) { $input = $this->parseUserQueryNames($input, $allowUserQueries); $input = $this->parseUserQueryIds($input, $allowUserQueries); + $input = self::escapeRegexParentheses($input); $input = trim($input); } @@ -133,6 +134,20 @@ class FreshRSS_BooleanSearch { } /** + * Temporarily escape parentheses used in regex expressions. + */ + public static function escapeRegexParentheses(string $input): string { + return preg_replace_callback('#(?<=[\\s(:!-]|^)(?<![\\\\])/.*?(?<!\\\\)/[im]*#', + fn(array $matches): string => str_replace(['(', ')'], ['\\u0028', '\\u0029'], $matches[0]), + $input + ) ?? ''; + } + + public static function unescapeRegexParentheses(string $input): string { + return str_replace(['\\u0028', '\\u0029'], ['(', ')'], $input); + } + + /** * Example: 'ab cd OR ef OR "gh ij"' becomes '(ab cd) OR (ef) OR ("gh ij")' */ public static function addOrParentheses(string $input): string { diff --git a/app/Models/Search.php b/app/Models/Search.php index 0e2f5da6f..45fa742be 100644 --- a/app/Models/Search.php +++ b/app/Models/Search.php @@ -94,6 +94,7 @@ class FreshRSS_Search { public function __construct(string $input) { $input = self::cleanSearch($input); $input = self::unescape($input); + $input = FreshRSS_BooleanSearch::unescapeRegexParentheses($input); $this->raw_input = $input; $input = $this->parseNotEntryIds($input); |
