ソースを参照

Search: quote parentheses and OR when serialising terms (#9541)

   `FreshRSS_Search::__toString()` did not quote values containing parentheses or the `OR` keyword, so serialising a parsed search and parsing it again could change its structure (e.g. `"a(b"` was serialised as `a(b`).

   This makes the serialisation lossless for such values, and adds tests, including a round-trip test (parse → toString → parse).
Mehmet 6 時間 前
親
コミット
4ec877d299
2 ファイル変更、37 行追加、1 行削除
  1. 1 1
      app/Models/Search.php
  2. 36 0
      tests/app/Models/SearchTest.php

+ 1 - 1
app/Models/Search.php

@@ -173,7 +173,7 @@ class FreshRSS_Search implements \Stringable {
 			// Discard user queries
 			return $s;
 		}
-		if (strpbrk($s, ' "\'\\/:') !== false || $s === '') {
+		if (strpbrk($s, ' "\'\\/:()') !== false || $s === '' || preg_match('/\bOR\b/i', $s) === 1) {
 			return '"' . addcslashes($s, '"') . '"';
 		}
 		return $s;

+ 36 - 0
tests/app/Models/SearchTest.php

@@ -1234,9 +1234,45 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
 				'intitle:/^A B OR C D/i',
 				'intitle:/^A B OR C D/i',
 			],
+			[
+				'"a(b"',
+				'"a(b"',
+			],
+			[
+				'intitle:"(test)"',
+				'intitle:"(test)"',
+			],
+			[
+				'"a)OR(b"',
+				'"a)OR(b"',
+			],
+			[
+				'"x.OR.y"',
+				'"x.OR.y"',
+			],
 		];
 	}
 
+	#[DataProvider('provideBooleanSearchToStringRoundTrip')]
+	public static function testBooleanSearchToStringRoundTrip(string $input): void {
+		$search = new FreshRSS_BooleanSearch($input);
+		$reparsed = new FreshRSS_BooleanSearch($search->toString());
+		self::assertSame($search->toString(), $reparsed->toString());
+	}
+
+	/** @return list<list{string}> */
+	public static function provideBooleanSearchToStringRoundTrip(): array {
+		return [
+			['"a(b"'],
+			['"a)OR(b"'],
+			['"a b" ("cd)OR(ef")'],
+			['intitle:"(x)" author:"a OR b"'],
+			['"x.OR.y" OR z'],
+			['intitle:/^(ab|cd)/ "e)f"'],
+		];
+	}
+
+
 	/**
 	 * @param list<array{search:string,name?:string}> $queries
 	 */