mirror of
https://github.com/NNTmux/newznab-tmux.git
synced 2026-08-28 17:01:16 +00:00
Merge branch 'master' of https://github.com/NNTmux/newznab-tmux
This commit is contained in:
@@ -304,6 +304,19 @@ if (! function_exists('escapeString')) {
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('regex_display_value')) {
|
||||
/**
|
||||
* Decode entity-encoded regex text at the presentation boundary.
|
||||
*
|
||||
* Blade should still render the returned value with escaped {{ }} output so regexes that
|
||||
* contain HTML-looking text remain safe while displaying named groups and quotes readably.
|
||||
*/
|
||||
function regex_display_value(mixed $value): string
|
||||
{
|
||||
return html_entity_decode((string) ($value ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('realDuration')) {
|
||||
|
||||
function realDuration(mixed $milliseconds): string
|
||||
|
||||
Generated
+16
-16
@@ -2162,16 +2162,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/horizon",
|
||||
"version": "v5.47.1",
|
||||
"version": "v5.47.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/horizon.git",
|
||||
"reference": "356e3ec86321361a4cb8259cb73fdb3406fa3b30"
|
||||
"reference": "a6ac142293ad02db4d7cccb961dd32f56ef1462d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/356e3ec86321361a4cb8259cb73fdb3406fa3b30",
|
||||
"reference": "356e3ec86321361a4cb8259cb73fdb3406fa3b30",
|
||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/a6ac142293ad02db4d7cccb961dd32f56ef1462d",
|
||||
"reference": "a6ac142293ad02db4d7cccb961dd32f56ef1462d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2236,9 +2236,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/horizon/issues",
|
||||
"source": "https://github.com/laravel/horizon/tree/v5.47.1"
|
||||
"source": "https://github.com/laravel/horizon/tree/v5.47.2"
|
||||
},
|
||||
"time": "2026-05-20T12:12:55+00:00"
|
||||
"time": "2026-06-03T15:11:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@@ -2301,16 +2301,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/pulse",
|
||||
"version": "v1.7.3",
|
||||
"version": "v1.7.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/pulse.git",
|
||||
"reference": "dfd3b8e98cd1ada8d105e528da0afe1bbfe7d990"
|
||||
"reference": "6daab88ef368c0a1272a4401d90d514b30829225"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/pulse/zipball/dfd3b8e98cd1ada8d105e528da0afe1bbfe7d990",
|
||||
"reference": "dfd3b8e98cd1ada8d105e528da0afe1bbfe7d990",
|
||||
"url": "https://api.github.com/repos/laravel/pulse/zipball/6daab88ef368c0a1272a4401d90d514b30829225",
|
||||
"reference": "6daab88ef368c0a1272a4401d90d514b30829225",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2385,7 +2385,7 @@
|
||||
"issues": "https://github.com/laravel/pulse/issues",
|
||||
"source": "https://github.com/laravel/pulse"
|
||||
},
|
||||
"time": "2026-03-26T14:27:31+00:00"
|
||||
"time": "2026-06-03T14:04:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sentinel",
|
||||
@@ -12845,16 +12845,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/sail",
|
||||
"version": "v1.61.0",
|
||||
"version": "v1.62.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sail.git",
|
||||
"reference": "68ef35015630fe510432e63e11e21749006df688"
|
||||
"reference": "3aaeefc979f8ba6586fbc5b6e0b1b3638058f98e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/68ef35015630fe510432e63e11e21749006df688",
|
||||
"reference": "68ef35015630fe510432e63e11e21749006df688",
|
||||
"url": "https://api.github.com/repos/laravel/sail/zipball/3aaeefc979f8ba6586fbc5b6e0b1b3638058f98e",
|
||||
"reference": "3aaeefc979f8ba6586fbc5b6e0b1b3638058f98e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -12904,7 +12904,7 @@
|
||||
"issues": "https://github.com/laravel/sail/issues",
|
||||
"source": "https://github.com/laravel/sail"
|
||||
},
|
||||
"time": "2026-05-23T23:33:57+00:00"
|
||||
"time": "2026-05-27T04:02:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "localheinz/diff",
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
id="group_regex"
|
||||
name="group_regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
value="{{ htmlspecialchars($regex->group_regex ?? '') }}"
|
||||
value="{{ $regex->group_regex ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
@@ -66,7 +66,7 @@
|
||||
name="regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
|
||||
rows="4"
|
||||
required>{{ htmlspecialchars($regex->regex ?? '') }}</textarea>
|
||||
required>{{ regex_display_value($regex->regex ?? '') }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Regex to use when categorizing releases.<br>
|
||||
@@ -87,7 +87,7 @@
|
||||
<textarea id="description"
|
||||
name="description"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
rows="3">{{ htmlspecialchars($regex->description ?? '') }}</textarea>
|
||||
rows="3">{{ $regex->description ?? '' }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Description for this regex. You can include an example usenet subject this regex would match on.
|
||||
|
||||
@@ -94,8 +94,8 @@
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<div class="max-w-[200px] wrap-break-word">
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ htmlspecialchars($row->regex) }}">
|
||||
{{ htmlspecialchars($row->regex) }}
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ regex_display_value($row->regex) }}">
|
||||
{{ regex_display_value($row->regex) }}
|
||||
</code>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
id="group_regex"
|
||||
name="group_regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
value="{{ htmlspecialchars($regex->group_regex ?? '') }}"
|
||||
value="{{ $regex->group_regex ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
@@ -66,7 +66,7 @@
|
||||
name="regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
|
||||
rows="4"
|
||||
required>{{ htmlspecialchars($regex->regex ?? '') }}</textarea>
|
||||
required>{{ regex_display_value($regex->regex ?? '') }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
Regex to use when grouping binaries into collections.<br>
|
||||
@@ -87,7 +87,7 @@
|
||||
<textarea id="description"
|
||||
name="description"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
rows="3">{{ htmlspecialchars($regex->description ?? '') }}</textarea>
|
||||
rows="3">{{ $regex->description ?? '' }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
Description for this regex. You can include an example usenet subject this regex would match on.
|
||||
|
||||
@@ -93,8 +93,8 @@
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<div class="max-w-[200px] wrap-break-word">
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ htmlspecialchars($row->regex) }}">
|
||||
{{ htmlspecialchars($row->regex) }}
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ regex_display_value($row->regex) }}">
|
||||
{{ regex_display_value($row->regex) }}
|
||||
</code>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
|
||||
rows="4"
|
||||
required
|
||||
placeholder="/^(?P<name>.*?)([\. ]S\d{1,3}[\. ]?E\d{1,3})/i">{{ $regex }}</textarea>
|
||||
placeholder="/^(?P<name>.*?)([\. ]S\d{1,3}[\. ]?E\d{1,3})/i">{{ regex_display_value($regex) }}</textarea>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Enter the regex pattern to test. Include delimiters and flags.
|
||||
</p>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
id="group_regex"
|
||||
name="group_regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
value="{{ htmlspecialchars($regex->group_regex ?? '') }}"
|
||||
value="{{ $regex->group_regex ?? '' }}"
|
||||
required>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
@@ -66,7 +66,7 @@
|
||||
name="regex"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
|
||||
rows="4"
|
||||
required>{{ htmlspecialchars($regex->regex ?? '') }}</textarea>
|
||||
required>{{ regex_display_value($regex->regex ?? '') }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Regex to use when renaming releases.<br>
|
||||
@@ -87,7 +87,7 @@
|
||||
<textarea id="description"
|
||||
name="description"
|
||||
class="pl-10 w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
||||
rows="3">{{ htmlspecialchars($regex->description ?? '') }}</textarea>
|
||||
rows="3">{{ $regex->description ?? '' }}</textarea>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Description for this regex. You can include an example release name this regex would match on.
|
||||
|
||||
@@ -93,8 +93,8 @@
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm">
|
||||
<div class="max-w-[200px] wrap-break-word">
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ htmlspecialchars($row->regex) }}">
|
||||
{{ htmlspecialchars($row->regex) }}
|
||||
<code class="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-xs break-all" title="{{ regex_display_value($row->regex) }}">
|
||||
{{ regex_display_value($row->regex) }}
|
||||
</code>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
class="w-full px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"
|
||||
rows="4"
|
||||
required
|
||||
placeholder="/^(?P<name>.*?)([\. ]S\d{1,3}[\. ]?E\d{1,3})/i">{{ $regex }}</textarea>
|
||||
placeholder="/^(?P<name>.*?)([\. ]S\d{1,3}[\. ]?E\d{1,3})/i">{{ regex_display_value($regex) }}</textarea>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
Enter the regex pattern to test. Include delimiters and flags.
|
||||
</p>
|
||||
|
||||
@@ -166,6 +166,63 @@ class AdminRegexesControllerTest extends TestCase
|
||||
->assertNotFound();
|
||||
}
|
||||
|
||||
public function test_admin_regex_list_pages_decode_entity_encoded_regexes_without_double_escaping(): void
|
||||
{
|
||||
$admin = $this->createUserWithRole('Admin');
|
||||
$rawRegex = '/^(?P<name>.+?) - "(?P<title>.+?)"$/i';
|
||||
$entityEncodedRegex = '/^(?P<name>.+?) - "(?P<title>.+?)"$/i';
|
||||
$scriptTag = '<'.'script>alert("x")</'.'script>';
|
||||
$htmlLookingRegex = '/^(?P<name>.+?)'.$scriptTag.'$/i';
|
||||
|
||||
foreach (['release_naming_regexes', 'collection_regexes', 'category_regexes'] as $table) {
|
||||
$this->insertRegexFixture($table, $rawRegex, 'Raw regex fixture');
|
||||
$this->insertRegexFixture($table, $entityEncodedRegex, 'Entity encoded regex fixture');
|
||||
$this->insertRegexFixture($table, $htmlLookingRegex, 'HTML-looking regex fixture');
|
||||
}
|
||||
|
||||
foreach ([
|
||||
route('admin.release_naming_regexes-list'),
|
||||
route('admin.collection_regexes-list'),
|
||||
route('admin.category_regexes-list'),
|
||||
] as $url) {
|
||||
$response = $this->actingAs($admin)->get($url);
|
||||
|
||||
$response->assertOk()
|
||||
->assertSee(e($rawRegex), false)
|
||||
->assertSee(e(html_entity_decode($entityEncodedRegex, ENT_QUOTES | ENT_HTML5, 'UTF-8')), false)
|
||||
->assertSee(e(html_entity_decode($htmlLookingRegex, ENT_QUOTES | ENT_HTML5, 'UTF-8')), false)
|
||||
->assertDontSee('&quot;', false)
|
||||
->assertDontSee('&lt;', false)
|
||||
->assertDontSee('&gt;', false)
|
||||
->assertDontSee($scriptTag, false);
|
||||
}
|
||||
}
|
||||
|
||||
public function test_admin_regex_edit_pages_decode_entity_encoded_regexes_without_double_escaping(): void
|
||||
{
|
||||
$admin = $this->createUserWithRole('Admin');
|
||||
$entityEncodedRegex = '/^(?P<name>.+?) - "(?P<title>.+?)"$/i';
|
||||
$expectedRenderedRegex = e(html_entity_decode($entityEncodedRegex, ENT_QUOTES | ENT_HTML5, 'UTF-8'));
|
||||
|
||||
$releaseNamingRegexId = $this->insertRegexFixture('release_naming_regexes', $entityEncodedRegex, 'Release naming encoded regex');
|
||||
$collectionRegexId = $this->insertRegexFixture('collection_regexes', $entityEncodedRegex, 'Collection encoded regex');
|
||||
$categoryRegexId = $this->insertRegexFixture('category_regexes', $entityEncodedRegex, 'Category encoded regex');
|
||||
|
||||
foreach ([
|
||||
route('admin.release_naming_regexes-edit', ['id' => (string) $releaseNamingRegexId]),
|
||||
route('admin.collection_regexes-edit', ['id' => (string) $collectionRegexId]),
|
||||
route('admin.category_regexes-edit', ['id' => (string) $categoryRegexId]),
|
||||
] as $url) {
|
||||
$this->actingAs($admin)
|
||||
->get($url)
|
||||
->assertOk()
|
||||
->assertSee($expectedRenderedRegex, false)
|
||||
->assertDontSee('&quot;', false)
|
||||
->assertDontSee('&lt;', false)
|
||||
->assertDontSee('&gt;', false);
|
||||
}
|
||||
}
|
||||
|
||||
private function setEnvironmentValue(string $key, ?string $value): void
|
||||
{
|
||||
if ($value === null) {
|
||||
@@ -373,6 +430,23 @@ class AdminRegexesControllerTest extends TestCase
|
||||
return $user->fresh();
|
||||
}
|
||||
|
||||
private function insertRegexFixture(string $table, string $regex, string $description): int
|
||||
{
|
||||
$data = [
|
||||
'group_regex' => 'alt\\.binaries\\.example',
|
||||
'regex' => $regex,
|
||||
'description' => $description,
|
||||
'ordinal' => 10,
|
||||
'status' => 1,
|
||||
];
|
||||
|
||||
if ($table === 'category_regexes') {
|
||||
$data['categories_id'] = 1;
|
||||
}
|
||||
|
||||
return (int) DB::table($table)->insertGetId($data);
|
||||
}
|
||||
|
||||
private function resetGlobalComposerState(): void
|
||||
{
|
||||
$reflection = new ReflectionClass(GlobalDataComposer::class);
|
||||
|
||||
Reference in New Issue
Block a user