aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Models/BooleanSearch.php14
-rw-r--r--app/Models/Search.php2
-rw-r--r--docs/en/users/10_filter.md2
-rw-r--r--docs/fr/users/03_Main_view.md2
-rw-r--r--tests/app/Models/SearchTest.php2
5 files changed, 11 insertions, 11 deletions
diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php
index 375705036..529bcd338 100644
--- a/app/Models/BooleanSearch.php
+++ b/app/Models/BooleanSearch.php
@@ -39,7 +39,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
$this->raw_input = $input;
if ($level === 0) {
- $input = self::escapeRegexParentheses($input);
+ $input = self::escapeLiteralParentheses($input);
$input = $this->parseUserQueryNames($input, $allowUserQueries);
$input = $this->parseUserQueryIds($input, $allowUserQueries);
$input = trim($input);
@@ -83,7 +83,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
if (!empty($queries[$name])) {
$fromS[] = $matches[0][$i];
if ($allowUserQueries) {
- $toS[] = '(' . self::escapeRegexParentheses($queries[$name]) . ')';
+ $toS[] = '(' . self::escapeLiteralParentheses($queries[$name]) . ')';
} else {
$toS[] = '';
}
@@ -124,7 +124,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
if (!empty($queries[$id])) {
$fromS[] = $matches[0][$i];
if ($allowUserQueries) {
- $toS[] = '(' . self::escapeRegexParentheses($queries[$id]) . ')';
+ $toS[] = '(' . self::escapeLiteralParentheses($queries[$id]) . ')';
} else {
$toS[] = '';
}
@@ -138,16 +138,16 @@ class FreshRSS_BooleanSearch implements \Stringable {
}
/**
- * Temporarily escape parentheses used in regex expressions.
+ * Temporarily escape parentheses used in regex expressions or inside quoted strings.
*/
- public static function escapeRegexParentheses(string $input): string {
- return preg_replace_callback('%(?<=[\\s(:#!-]|^)(?<![\\\\])/.+?(?<!\\\\)/[im]*%',
+ public static function escapeLiteralParentheses(string $input): string {
+ return preg_replace_callback('%(?<=[\\s(:#!-]|^)(?<![\\\\])(?P<delim>[\'"/]).+?(?<!\\\\)(?P=delim)[im]*%',
fn(array $matches): string => str_replace(['(', ')'], ['\\u0028', '\\u0029'], $matches[0]),
$input
) ?? '';
}
- public static function unescapeRegexParentheses(string $input): string {
+ public static function unescapeLiteralParentheses(string $input): string {
return str_replace(['\\u0028', '\\u0029'], ['(', ')'], $input);
}
diff --git a/app/Models/Search.php b/app/Models/Search.php
index 4a006c2d0..a887ec2f7 100644
--- a/app/Models/Search.php
+++ b/app/Models/Search.php
@@ -94,7 +94,7 @@ class FreshRSS_Search implements \Stringable {
public function __construct(string $input) {
$input = self::cleanSearch($input);
$input = self::unescape($input);
- $input = FreshRSS_BooleanSearch::unescapeRegexParentheses($input);
+ $input = FreshRSS_BooleanSearch::unescapeLiteralParentheses($input);
$this->raw_input = $input;
$input = $this->parseNotEntryIds($input);
diff --git a/docs/en/users/10_filter.md b/docs/en/users/10_filter.md
index 0aa9ed018..0aecfbaa0 100644
--- a/docs/en/users/10_filter.md
+++ b/docs/en/users/10_filter.md
@@ -116,7 +116,7 @@ Finally, parentheses may be used to express more complex queries, with basic neg
* `(author:Alice intitle:hello) !(author:Bob intitle:world)`
* `!(S:1 OR S:2)`
-> ℹ️ If you need to search for a parenthesis, it needs to be escaped like `\(` or `\)`
+> ℹ️ If you need to search for a parenthesis, it needs to be escaped like `\(` or `\)` or used inside a quoted string like `"a (b)"`
### Regex
diff --git a/docs/fr/users/03_Main_view.md b/docs/fr/users/03_Main_view.md
index 8274d0b79..e1be4ca3d 100644
--- a/docs/fr/users/03_Main_view.md
+++ b/docs/fr/users/03_Main_view.md
@@ -275,7 +275,7 @@ Enfin, les parenthèses peuvent être utilisées pour des expressions plus compl
* `(author:Alice intitle:bonjour) !(author:Bob intitle:monde)`
* `!(S:1 OR S:2)`
-> ℹ️ Si vous devez chercher une parenthèse, elle doit être *échappée* comme suit : `\(` ou `\)`
+> ℹ️ Si vous devez chercher une parenthèse, elle doit être *échappée* comme suit : `\(` ou `\)`, ou bien être au sein d’une chaîne de texte entre guillemets comme `"a (b)"`
#### Regex
diff --git a/tests/app/Models/SearchTest.php b/tests/app/Models/SearchTest.php
index 7c03d5aed..04da65d3a 100644
--- a/tests/app/Models/SearchTest.php
+++ b/tests/app/Models/SearchTest.php
@@ -370,7 +370,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
['%Alice%', '%hello%', '%Bob%', '%world%'],
],
[
- 'intitle:"\\(test\\)"',
+ 'intitle:"(test)"',
'(e.title LIKE ? )',
['%(test)%'],
],