Compare commits

..

7 Commits

Author SHA1 Message Date
Dan Brown
446b4a7d3d Updated version and assets for release v25.12.9 2026-03-12 11:01:04 +00:00
Dan Brown
d335b49be0 Merge branch 'v25-12' into release 2026-03-12 10:59:00 +00:00
Dan Brown
5f5fea7c83 Deps: Bumped PHP packages before release 2026-03-12 10:52:12 +00:00
Dan Brown
6e7cc169d1 Preferences: Updated return redirect with better origin checks
As suggested by Alex Dan in their security report.
2026-03-10 18:31:51 +00:00
Dan Brown
6216c89f82 Packages: Updated PHP package versions 2026-03-10 17:48:12 +00:00
Dan Brown
404e67afbc Page Revisions: Added testing coverage to basic diffing 2026-03-10 17:47:07 +00:00
Dan Brown
6d64262a61 Revision Diffs: Added filtering post-diff render 2026-03-10 15:03:43 +00:00
7 changed files with 204 additions and 123 deletions

View File

@@ -12,6 +12,8 @@ use BookStack\Exceptions\NotFoundException;
use BookStack\Facades\Activity;
use BookStack\Http\Controller;
use BookStack\Permissions\Permission;
use BookStack\Util\HtmlContentFilter;
use BookStack\Util\HtmlContentFilterConfig;
use BookStack\Util\SimpleListOptions;
use Illuminate\Http\Request;
use Ssddanbrown\HtmlDiff\Diff;
@@ -101,12 +103,15 @@ class PageRevisionController extends Controller
$prev = $revision->getPreviousRevision();
$prevContent = $prev->html ?? '';
$diff = Diff::excecute($prevContent, $revision->html);
// TODO - Refactor PageContent so we can de-dupe these steps
$rawDiff = Diff::excecute($prevContent, $revision->html);
$filterConfig = HtmlContentFilterConfig::fromConfigString(config('app.content_filtering'));
$filter = new HtmlContentFilter($filterConfig);
$diff = $filter->filterString($rawDiff);
$page->fill($revision->toArray());
// TODO - Refactor PageContent so we don't need to juggle this
$page->html = $revision->html;
$page->html = (new PageContent($page))->render();
$page->html = '';
$this->setPageTitle(trans('entities.pages_revision_named', ['pageName' => $page->getShortName()]));
return view('pages.revision', [

View File

@@ -167,14 +167,26 @@ abstract class Controller extends BaseController
/**
* Redirect to the URL provided in the request as a '_return' parameter.
* Will check that the parameter leads to a URL under the root path of the system.
* Will check that the parameter leads to a URL under the same origin as the application.
*/
protected function redirectToRequest(Request $request): RedirectResponse
{
$basePath = url('/');
$returnUrl = $request->input('_return') ?? $basePath;
if (!str_starts_with($returnUrl, $basePath)) {
// Only allow use of _return on requests where we expect CSRF to be active
// to prevent it potentially being used as an open redirect
$allowedMethods = ['POST', 'PUT', 'PATCH', 'DELETE'];
if (!in_array($request->getMethod(), $allowedMethods)) {
return redirect($basePath);
}
$intendedUrl = parse_url($returnUrl);
$baseUrl = parse_url($basePath);
$isSameOrigin = ($intendedUrl['host'] ?? '') === ($baseUrl['host'] ?? '')
&& ($intendedUrl['scheme'] ?? '') === ($baseUrl['scheme'] ?? '')
&& ($intendedUrl['port'] ?? 0) === ($baseUrl['port'] ?? 0);
if (!$isSameOrigin) {
return redirect($basePath);
}

232
composer.lock generated
View File

@@ -62,16 +62,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.371.2",
"version": "3.373.0",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec"
"reference": "fb74a2dca7ae2363e929c5cea33a4a4db0d22690"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec",
"reference": "32090a8ac3ec8859cb83bdde800b8f0ecf92d8ec",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fb74a2dca7ae2363e929c5cea33a4a4db0d22690",
"reference": "fb74a2dca7ae2363e929c5cea33a4a4db0d22690",
"shasum": ""
},
"require": {
@@ -135,11 +135,11 @@
"authors": [
{
"name": "Amazon Web Services",
"homepage": "http://aws.amazon.com"
"homepage": "https://aws.amazon.com"
}
],
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
"homepage": "http://aws.amazon.com/sdkforphp",
"homepage": "https://aws.amazon.com/sdk-for-php",
"keywords": [
"amazon",
"aws",
@@ -153,9 +153,9 @@
"support": {
"forum": "https://github.com/aws/aws-sdk-php/discussions",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.371.2"
"source": "https://github.com/aws/aws-sdk-php/tree/3.373.0"
},
"time": "2026-02-26T19:06:10+00:00"
"time": "2026-03-11T18:33:36+00:00"
},
{
"name": "bacon/bacon-qr-code",
@@ -635,16 +635,16 @@
},
{
"name": "dompdf/dompdf",
"version": "v3.1.4",
"version": "v3.1.5",
"source": {
"type": "git",
"url": "https://github.com/dompdf/dompdf.git",
"reference": "db712c90c5b9868df3600e64e68da62e78a34623"
"reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/db712c90c5b9868df3600e64e68da62e78a34623",
"reference": "db712c90c5b9868df3600e64e68da62e78a34623",
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496",
"reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496",
"shasum": ""
},
"require": {
@@ -693,9 +693,9 @@
"homepage": "https://github.com/dompdf/dompdf",
"support": {
"issues": "https://github.com/dompdf/dompdf/issues",
"source": "https://github.com/dompdf/dompdf/tree/v3.1.4"
"source": "https://github.com/dompdf/dompdf/tree/v3.1.5"
},
"time": "2025-10-29T12:43:30+00:00"
"time": "2026-03-03T13:54:37+00:00"
},
{
"name": "dompdf/php-font-lib",
@@ -1387,16 +1387,16 @@
},
{
"name": "guzzlehttp/psr7",
"version": "2.8.0",
"version": "2.9.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "21dc724a0583619cd1652f673303492272778051"
"reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
"reference": "21dc724a0583619cd1652f673303492272778051",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884",
"reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884",
"shasum": ""
},
"require": {
@@ -1412,6 +1412,7 @@
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "0.9.0",
"jshttp/mime-db": "1.54.0.1",
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
},
"suggest": {
@@ -1483,7 +1484,7 @@
],
"support": {
"issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.8.0"
"source": "https://github.com/guzzle/psr7/tree/2.9.0"
},
"funding": [
{
@@ -1499,7 +1500,7 @@
"type": "tidelift"
}
],
"time": "2025-08-23T21:21:41+00:00"
"time": "2026-03-10T16:41:02+00:00"
},
{
"name": "guzzlehttp/uri-template",
@@ -1800,16 +1801,16 @@
},
{
"name": "laravel/framework",
"version": "v12.53.0",
"version": "v12.54.1",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "f57f035c0d34503d9ff30be76159bb35a003cd1f"
"reference": "325497463e7599cd14224c422c6e5dd2fe832868"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/f57f035c0d34503d9ff30be76159bb35a003cd1f",
"reference": "f57f035c0d34503d9ff30be76159bb35a003cd1f",
"url": "https://api.github.com/repos/laravel/framework/zipball/325497463e7599cd14224c422c6e5dd2fe832868",
"reference": "325497463e7599cd14224c422c6e5dd2fe832868",
"shasum": ""
},
"require": {
@@ -1830,7 +1831,7 @@
"guzzlehttp/uri-template": "^1.0",
"laravel/prompts": "^0.3.0",
"laravel/serializable-closure": "^1.3|^2.0",
"league/commonmark": "^2.7",
"league/commonmark": "^2.8.1",
"league/flysystem": "^3.25.1",
"league/flysystem-local": "^3.25.1",
"league/uri": "^7.5.1",
@@ -2018,20 +2019,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2026-02-24T14:35:15+00:00"
"time": "2026-03-10T20:25:56+00:00"
},
{
"name": "laravel/prompts",
"version": "v0.3.13",
"version": "v0.3.14",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
"reference": "ed8c466571b37e977532fb2fd3c272c784d7050d"
"reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/ed8c466571b37e977532fb2fd3c272c784d7050d",
"reference": "ed8c466571b37e977532fb2fd3c272c784d7050d",
"url": "https://api.github.com/repos/laravel/prompts/zipball/9f0e371244eedfe2ebeaa72c79c54bb5df6e0176",
"reference": "9f0e371244eedfe2ebeaa72c79c54bb5df6e0176",
"shasum": ""
},
"require": {
@@ -2075,9 +2076,9 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.3.13"
"source": "https://github.com/laravel/prompts/tree/v0.3.14"
},
"time": "2026-02-06T12:17:10+00:00"
"time": "2026-03-01T09:02:38+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -2142,16 +2143,16 @@
},
{
"name": "laravel/socialite",
"version": "v5.24.3",
"version": "v5.25.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/socialite.git",
"reference": "0feb62267e7b8abc68593ca37639ad302728c129"
"reference": "231f572e1a37c9ca1fb8085e9fb8608285beafb3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/socialite/zipball/0feb62267e7b8abc68593ca37639ad302728c129",
"reference": "0feb62267e7b8abc68593ca37639ad302728c129",
"url": "https://api.github.com/repos/laravel/socialite/zipball/231f572e1a37c9ca1fb8085e9fb8608285beafb3",
"reference": "231f572e1a37c9ca1fb8085e9fb8608285beafb3",
"shasum": ""
},
"require": {
@@ -2210,7 +2211,7 @@
"issues": "https://github.com/laravel/socialite/issues",
"source": "https://github.com/laravel/socialite"
},
"time": "2026-02-21T13:32:50+00:00"
"time": "2026-02-27T13:56:35+00:00"
},
{
"name": "laravel/tinker",
@@ -2280,16 +2281,16 @@
},
{
"name": "league/commonmark",
"version": "2.8.0",
"version": "2.8.1",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb"
"reference": "84b1ca48347efdbe775426f108622a42735a6579"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
"reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/84b1ca48347efdbe775426f108622a42735a6579",
"reference": "84b1ca48347efdbe775426f108622a42735a6579",
"shasum": ""
},
"require": {
@@ -2314,9 +2315,9 @@
"phpstan/phpstan": "^1.8.2",
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
"scrutinizer/ocular": "^1.8.1",
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"symfony/finder": "^5.3 | ^6.0 | ^7.0 || ^8.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0 || ^8.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0 || ^8.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
},
@@ -2383,7 +2384,7 @@
"type": "tidelift"
}
],
"time": "2025-11-26T21:48:24+00:00"
"time": "2026-03-05T21:37:03+00:00"
},
{
"name": "league/config",
@@ -3360,16 +3361,16 @@
},
{
"name": "nesbot/carbon",
"version": "3.11.1",
"version": "3.11.3",
"source": {
"type": "git",
"url": "https://github.com/CarbonPHP/carbon.git",
"reference": "f438fcc98f92babee98381d399c65336f3a3827f"
"reference": "6a7e652845bb018c668220c2a545aded8594fbbf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/f438fcc98f92babee98381d399c65336f3a3827f",
"reference": "f438fcc98f92babee98381d399c65336f3a3827f",
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6a7e652845bb018c668220c2a545aded8594fbbf",
"reference": "6a7e652845bb018c668220c2a545aded8594fbbf",
"shasum": ""
},
"require": {
@@ -3461,7 +3462,7 @@
"type": "tidelift"
}
],
"time": "2026-01-29T09:26:29+00:00"
"time": "2026-03-11T17:23:39+00:00"
},
{
"name": "nette/schema",
@@ -4188,16 +4189,16 @@
},
{
"name": "predis/predis",
"version": "v3.4.1",
"version": "v3.4.2",
"source": {
"type": "git",
"url": "https://github.com/predis/predis.git",
"reference": "0850f2f36ee179f0ff96c92c750e1366c6cd754c"
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/predis/predis/zipball/0850f2f36ee179f0ff96c92c750e1366c6cd754c",
"reference": "0850f2f36ee179f0ff96c92c750e1366c6cd754c",
"url": "https://api.github.com/repos/predis/predis/zipball/2033429520d8997a7815a2485f56abe6d2d0e075",
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075",
"shasum": ""
},
"require": {
@@ -4239,7 +4240,7 @@
],
"support": {
"issues": "https://github.com/predis/predis/issues",
"source": "https://github.com/predis/predis/tree/v3.4.1"
"source": "https://github.com/predis/predis/tree/v3.4.2"
},
"funding": [
{
@@ -4247,7 +4248,7 @@
"type": "github"
}
],
"time": "2026-02-23T19:51:21+00:00"
"time": "2026-03-09T20:33:04+00:00"
},
{
"name": "psr/clock",
@@ -4663,16 +4664,16 @@
},
{
"name": "psy/psysh",
"version": "v0.12.20",
"version": "v0.12.21",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
"reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373"
"reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/19678eb6b952a03b8a1d96ecee9edba518bb0373",
"reference": "19678eb6b952a03b8a1d96ecee9edba518bb0373",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/4821fab5b7cd8c49a673a9fd5754dc9162bb9e97",
"reference": "4821fab5b7cd8c49a673a9fd5754dc9162bb9e97",
"shasum": ""
},
"require": {
@@ -4736,9 +4737,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.12.20"
"source": "https://github.com/bobthecow/psysh/tree/v0.12.21"
},
"time": "2026-02-11T15:05:28+00:00"
"time": "2026-03-06T21:21:28+00:00"
},
{
"name": "ralouphie/getallheaders",
@@ -4982,16 +4983,16 @@
},
{
"name": "sabberworm/php-css-parser",
"version": "v9.2.0",
"version": "v9.3.0",
"source": {
"type": "git",
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
"reference": "59373045e11ad47b5c18fc615feee0219e42f6d3"
"reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/59373045e11ad47b5c18fc615feee0219e42f6d3",
"reference": "59373045e11ad47b5c18fc615feee0219e42f6d3",
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949",
"reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949",
"shasum": ""
},
"require": {
@@ -5018,7 +5019,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "9.3.x-dev"
"dev-main": "9.4.x-dev"
}
},
"autoload": {
@@ -5056,9 +5057,9 @@
],
"support": {
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.2.0"
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0"
},
"time": "2026-02-21T17:12:03+00:00"
"time": "2026-03-03T17:31:43+00:00"
},
{
"name": "socialiteproviders/discord",
@@ -5508,16 +5509,16 @@
},
{
"name": "symfony/console",
"version": "v7.4.6",
"version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "6d643a93b47398599124022eb24d97c153c12f27"
"reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6d643a93b47398599124022eb24d97c153c12f27",
"reference": "6d643a93b47398599124022eb24d97c153c12f27",
"url": "https://api.github.com/repos/symfony/console/zipball/e1e6770440fb9c9b0cf725f81d1361ad1835329d",
"reference": "e1e6770440fb9c9b0cf725f81d1361ad1835329d",
"shasum": ""
},
"require": {
@@ -5582,7 +5583,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v7.4.6"
"source": "https://github.com/symfony/console/tree/v7.4.7"
},
"funding": [
{
@@ -5602,7 +5603,7 @@
"type": "tidelift"
}
],
"time": "2026-02-25T17:02:47+00:00"
"time": "2026-03-06T14:06:20+00:00"
},
{
"name": "symfony/css-selector",
@@ -6123,16 +6124,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v7.4.6",
"version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065"
"reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/fd97d5e926e988a363cef56fbbf88c5c528e9065",
"reference": "fd97d5e926e988a363cef56fbbf88c5c528e9065",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/f94b3e7b7dafd40e666f0c9ff2084133bae41e81",
"reference": "f94b3e7b7dafd40e666f0c9ff2084133bae41e81",
"shasum": ""
},
"require": {
@@ -6181,7 +6182,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.6"
"source": "https://github.com/symfony/http-foundation/tree/v7.4.7"
},
"funding": [
{
@@ -6201,20 +6202,20 @@
"type": "tidelift"
}
],
"time": "2026-02-21T16:25:55+00:00"
"time": "2026-03-06T13:15:18+00:00"
},
{
"name": "symfony/http-kernel",
"version": "v7.4.6",
"version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
"reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83"
"reference": "3b3fcf386c809be990c922e10e4c620d6367cab1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/002ac0cf4cd972a7fd0912dcd513a95e8a81ce83",
"reference": "002ac0cf4cd972a7fd0912dcd513a95e8a81ce83",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/3b3fcf386c809be990c922e10e4c620d6367cab1",
"reference": "3b3fcf386c809be990c922e10e4c620d6367cab1",
"shasum": ""
},
"require": {
@@ -6300,7 +6301,7 @@
"description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-kernel/tree/v7.4.6"
"source": "https://github.com/symfony/http-kernel/tree/v7.4.7"
},
"funding": [
{
@@ -6320,7 +6321,7 @@
"type": "tidelift"
}
],
"time": "2026-02-26T08:30:57+00:00"
"time": "2026-03-06T16:33:18+00:00"
},
{
"name": "symfony/mailer",
@@ -6408,16 +6409,16 @@
},
{
"name": "symfony/mime",
"version": "v7.4.6",
"version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f"
"reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/9fc881d95feae4c6c48678cb6372bd8a7ba04f5f",
"reference": "9fc881d95feae4c6c48678cb6372bd8a7ba04f5f",
"url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
"reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
"shasum": ""
},
"require": {
@@ -6473,7 +6474,7 @@
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v7.4.6"
"source": "https://github.com/symfony/mime/tree/v7.4.7"
},
"funding": [
{
@@ -6493,7 +6494,7 @@
"type": "tidelift"
}
],
"time": "2026-02-05T15:57:06+00:00"
"time": "2026-03-05T15:24:09+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -8721,40 +8722,40 @@
},
{
"name": "larastan/larastan",
"version": "v3.9.2",
"version": "v3.9.3",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
"reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2"
"reference": "64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2",
"reference": "2e9ed291bdc1969e7f270fb33c9cdf3c912daeb2",
"url": "https://api.github.com/repos/larastan/larastan/zipball/64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65",
"reference": "64a52bcc5347c89fdf131cb59f96ebfbc8d1ad65",
"shasum": ""
},
"require": {
"ext-json": "*",
"iamcal/sql-parser": "^0.7.0",
"illuminate/console": "^11.44.2 || ^12.4.1",
"illuminate/container": "^11.44.2 || ^12.4.1",
"illuminate/contracts": "^11.44.2 || ^12.4.1",
"illuminate/database": "^11.44.2 || ^12.4.1",
"illuminate/http": "^11.44.2 || ^12.4.1",
"illuminate/pipeline": "^11.44.2 || ^12.4.1",
"illuminate/support": "^11.44.2 || ^12.4.1",
"illuminate/console": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/container": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/database": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/http": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13",
"illuminate/support": "^11.44.2 || ^12.4.1 || ^13",
"php": "^8.2",
"phpstan/phpstan": "^2.1.32"
},
"require-dev": {
"doctrine/coding-standard": "^13",
"laravel/framework": "^11.44.2 || ^12.7.2",
"laravel/framework": "^11.44.2 || ^12.7.2 || ^13",
"mockery/mockery": "^1.6.12",
"nikic/php-parser": "^5.4",
"orchestra/canvas": "^v9.2.2 || ^10.0.1",
"orchestra/testbench-core": "^9.12.0 || ^10.1",
"orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11",
"orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11",
"phpstan/phpstan-deprecation-rules": "^2.0.1",
"phpunit/phpunit": "^10.5.35 || ^11.5.15"
"phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8"
},
"suggest": {
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench",
@@ -8799,7 +8800,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.9.2"
"source": "https://github.com/larastan/larastan/tree/v3.9.3"
},
"funding": [
{
@@ -8807,7 +8808,7 @@
"type": "github"
}
],
"time": "2026-01-30T15:16:32+00:00"
"time": "2026-02-20T12:07:12+00:00"
},
{
"name": "mockery/mockery",
@@ -10743,21 +10744,22 @@
},
{
"name": "ssddanbrown/asserthtml",
"version": "v3.1.0",
"version": "v3.2.0",
"source": {
"type": "git",
"url": "https://codeberg.org/danb/asserthtml",
"reference": "cf8206171d667d43e1bdde17d67191f30e95c8a0"
"reference": "0811b5c8d541f344c193bd7f2c2d79d13d23b141"
},
"dist": {
"type": "zip",
"url": "https://codeberg.org/api/v1/repos/danb/asserthtml/archive/%prettyVersion%.zip"
"url": "https://codeberg.org/api/v1/repos/danb/asserthtml/archive/%prettyVersion%.zip",
"reference": "0811b5c8d541f344c193bd7f2c2d79d13d23b141"
},
"require": {
"ext-dom": "*",
"ext-json": "*",
"php": ">=8.1",
"phpunit/phpunit": "^10.0|^11.0",
"phpunit/phpunit": "^10.0|^11.0|^12.0|^13.0",
"symfony/css-selector": "^6.0|^7.0",
"symfony/dom-crawler": "^6.0|^7.0"
},
@@ -10783,7 +10785,7 @@
],
"description": "HTML Content Assertions for PHPUnit",
"homepage": "https://codeberg.org/danb/asserthtml",
"time": "2025-01-11T13:35:55+00:00"
"time": "2026-03-04T14:19:44+00:00"
},
{
"name": "staabm/side-effects-detector",

View File

@@ -1 +1 @@
6b4fe778d645978b3720f7d035a6c3965024d4d5d6d29e3114bb6db499b7e61e
e2acb4ea1edce1e2c9af0d7598a3de9ae1d44ff9e647f018f4f732ab5f560f9d

View File

@@ -47,6 +47,20 @@ class PageRevisionTest extends TestCase
$revisionView->assertSee('new revision content');
}
public function test_page_revision_preview_filters_html_content()
{
$this->asEditor();
$page = $this->entities->page();
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => '<script>dontwantthishere</script><style>dontwantthishere</style><p>expectthisthough</p>']);
$pageRevision = $page->revisions->last();
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => '<p>Updated content</p>']);
$revisionView = $this->get($page->getUrl() . '/revisions/' . $pageRevision->id);
$revisionView->assertStatus(200);
$revisionView->assertSee('expectthisthough');
$revisionView->assertDontSee('dontwantthishere');
}
public function test_page_revision_restore_updates_content()
{
$this->asEditor();
@@ -215,6 +229,34 @@ class PageRevisionTest extends TestCase
$html->assertElementContains('.item-list > .item-list-row:nth-child(2)', 'Changes');
}
public function test_revision_changes_view_shows_diff()
{
$this->asEditor();
$page = $this->entities->page();
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => '<p id="bkmrk-hello">Hello there dog</p>']);
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => '<p id="bkmrk-hello">Hello there cat</p>']);
$pageRevision = $page->revisions()->orderBy('id', 'desc')->first();
$revisionView = $this->get("{$page->getUrl()}/revisions/{$pageRevision->id}/changes");
$revisionView->assertStatus(200);
$revisionView->assertSee('<p id="bkmrk-hello">Hello there <del class="diffmod">dog</del><ins class="diffmod">cat</ins></p>', false);
}
public function test_revision_changes_view_filters_html_content()
{
$this->asEditor();
$page = $this->entities->page();
$html = '<script>dontwantthishere</script><style>dontwantthishere</style><p>expectthisthough</p>';
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => $html]);
$this->createRevisions($page, 1, ['name' => 'updated page', 'html' => $html]);
$pageRevision = $page->revisions()->orderBy('id', 'desc')->first();
$revisionView = $this->get("{$page->getUrl()}/revisions/{$pageRevision->id}/changes");
$revisionView->assertStatus(200);
$revisionView->assertSee('expectthisthough');
$revisionView->assertDontSee('dontwantthishere');
}
public function test_revision_restore_action_only_visible_with_permission()
{
$page = $this->entities->page();

View File

@@ -153,6 +153,26 @@ class UserPreferencesTest extends TestCase
->assertElementNotExists('.content-wrap .entity-list-item');
}
public function test_redirect_on_preference_change_checks_host()
{
$expectedByRedirect = [
'http://localhost/beans' => 'http://localhost/beans',
'https://localhost/beans' => 'http://localhost',
'http://localhost:9090/beans' => 'http://localhost',
'http://localhost.example.com/beans' => 'http://localhost',
'http://localhost@example.com/beans' => 'http://localhost',
];
$this->asEditor();
foreach ($expectedByRedirect as $url => $expected) {
$req = $this->patch("/preferences/change-view/bookshelf", [
'view' => 'grid',
'_return' => $url,
]);
$req->assertRedirect($expected);
}
}
public function test_update_code_language_favourite()
{
$editor = $this->users->editor();

View File

@@ -1 +1 @@
v25.12.8
v25.12.9