aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2025-12-23 11:58:51 +0100
committerGravatar GitHub <noreply@github.com> 2025-12-23 11:58:51 +0100
commit6d57a9de47be4bb80a2121b6c4b8ebf278b93d70 (patch)
tree6cba47ef73451a678d9fd152fa385ac75c02460f /app
parentcf3ca7076566909bd5b6eb519036f8d1b857f356 (diff)
Fix parsing of literal "or" in regex (#8338)
fix https://github.com/FreshRSS/FreshRSS/issues/7879
Diffstat (limited to 'app')
-rw-r--r--app/Models/BooleanSearch.php28
-rw-r--r--app/Models/Search.php2
2 files changed, 21 insertions, 9 deletions
diff --git a/app/Models/BooleanSearch.php b/app/Models/BooleanSearch.php
index 6be189cda..1c0d6c18c 100644
--- a/app/Models/BooleanSearch.php
+++ b/app/Models/BooleanSearch.php
@@ -29,7 +29,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
$this->raw_input = $input;
if ($level === 0) {
- $input = self::escapeLiteralParentheses($input);
+ $input = self::escapeLiterals($input);
$input = $this->parseUserQueryNames($input, $allowUserQueries);
$input = $this->parseUserQueryIds($input, $allowUserQueries);
$input = trim($input);
@@ -79,7 +79,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
if (!empty($queries[$name])) {
$fromS[] = $matches[0][$i];
if ($allowUserQueries) {
- $toS[] = '(' . self::escapeLiteralParentheses($queries[$name]) . ')';
+ $toS[] = '(' . self::escapeLiterals($queries[$name]) . ')';
} else {
$toS[] = '';
}
@@ -130,7 +130,7 @@ class FreshRSS_BooleanSearch implements \Stringable {
$fromS[] = $matches[0][$i];
if ($allowUserQueries) {
- $escapedQueries = array_map(fn(string $query): string => self::escapeLiteralParentheses($query), $matchedQueries);
+ $escapedQueries = array_map(fn(string $query): string => self::escapeLiterals($query), $matchedQueries);
$toS[] = '(' . implode(') OR (', $escapedQueries) . ')';
} else {
$toS[] = '';
@@ -144,17 +144,29 @@ class FreshRSS_BooleanSearch implements \Stringable {
}
/**
- * Temporarily escape parentheses used in regex expressions or inside quoted strings.
+ * Temporarily escape parentheses and 'OR' used in regex expressions or inside "quoted strings".
*/
- public static function escapeLiteralParentheses(string $input): string {
+ public static function escapeLiterals(string $input): string {
return preg_replace_callback('%(?<=[\\s(:#!-]|^)(?<![\\\\])(?P<delim>[\'"/]).+?(?<!\\\\)(?P=delim)[im]*%',
- fn(array $matches): string => str_replace(['(', ')'], ['\\u0028', '\\u0029'], $matches[0]),
+ function (array $matches): string {
+ $match = $matches[0];
+ $match = str_replace(['(', ')'], ['\\u0028', '\\u0029'], $match);
+ $match = preg_replace_callback('/\bOR\b/i', fn(array $ms): string =>
+ str_replace(['O', 'o', 'R', 'r'], ['\\u004f', '\\u006f', '\\u0052', '\\u0072'], $ms[0]),
+ $match
+ ) ?? '';
+ return $match;
+ },
$input
) ?? '';
}
- public static function unescapeLiteralParentheses(string $input): string {
- return str_replace(['\\u0028', '\\u0029'], ['(', ')'], $input);
+ public static function unescapeLiterals(string $input): string {
+ return str_replace(
+ ['\\u0028', '\\u0029', '\\u004f', '\\u006f', '\\u0052', '\\u0072'],
+ ['(', ')', 'O', 'o', 'R', 'r'],
+ $input
+ );
}
/**
diff --git a/app/Models/Search.php b/app/Models/Search.php
index 046f61a2b..2b207134c 100644
--- a/app/Models/Search.php
+++ b/app/Models/Search.php
@@ -114,7 +114,7 @@ class FreshRSS_Search implements \Stringable {
public function __construct(string $input) {
$input = self::cleanSearch($input);
$input = self::unescape($input);
- $input = FreshRSS_BooleanSearch::unescapeLiteralParentheses($input);
+ $input = FreshRSS_BooleanSearch::unescapeLiterals($input);
$this->raw_input = $input;
$input = $this->parseNotEntryIds($input);