mirror of
https://github.com/BookStackApp/BookStack.git
synced 2026-07-15 21:31:36 +03:00
Merge branch 'v26051_sec' into development
This commit is contained in:
@@ -25,6 +25,7 @@ class Handler extends ExceptionHandler
|
||||
protected $dontReport = [
|
||||
NotFoundException::class,
|
||||
StoppedAuthenticationException::class,
|
||||
NotifyException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,18 +6,22 @@ use Exception;
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
|
||||
|
||||
/**
|
||||
* An exception that is thrown to notify the user of something which went wrong.
|
||||
* Typically these should be translated messages since they will be shown to the end user
|
||||
* via a pop up notification error message in the UI.
|
||||
*
|
||||
* This exception is not intended to be used for internal system/application errors,
|
||||
* and therefore will not be logged by the exception handler.
|
||||
*/
|
||||
class NotifyException extends Exception implements Responsable, HttpExceptionInterface
|
||||
{
|
||||
public $message;
|
||||
public string $redirectLocation;
|
||||
protected int $status;
|
||||
|
||||
public function __construct(string $message, string $redirectLocation = '/', int $status = 500)
|
||||
{
|
||||
public function __construct(
|
||||
string $message,
|
||||
public string $redirectLocation = '/',
|
||||
protected int $status = 500
|
||||
) {
|
||||
$this->message = $message;
|
||||
$this->redirectLocation = $redirectLocation;
|
||||
$this->status = $status;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ class SearchRunner
|
||||
$query->where('name', '=', $tagParts['name']);
|
||||
}
|
||||
|
||||
if (is_numeric($tagParts['value']) && $tagParts['operator'] !== 'like') {
|
||||
if (is_numeric($tagParts['value']) && is_finite($tagParts['value']) && $tagParts['operator'] !== 'like') {
|
||||
// We have to do a raw sql query for this since otherwise PDO will quote the value and MySQL will
|
||||
// search the value as a string which prevents being able to do number-based operations
|
||||
// on the tag values. We ensure it has a numeric value and then cast it just to be sure.
|
||||
|
||||
@@ -107,6 +107,9 @@ class AttachmentController extends Controller
|
||||
{
|
||||
/** @var Attachment $attachment */
|
||||
$attachment = Attachment::query()->findOrFail($attachmentId);
|
||||
$this->checkOwnablePermission(Permission::PageView, $attachment->page);
|
||||
$this->checkOwnablePermission(Permission::PageUpdate, $attachment->page);
|
||||
$this->checkOwnablePermission(Permission::AttachmentUpdate, $attachment);
|
||||
|
||||
try {
|
||||
$this->validate($request, [
|
||||
@@ -120,10 +123,6 @@ class AttachmentController extends Controller
|
||||
]), 422);
|
||||
}
|
||||
|
||||
$this->checkOwnablePermission(Permission::PageView, $attachment->page);
|
||||
$this->checkOwnablePermission(Permission::PageUpdate, $attachment->page);
|
||||
$this->checkOwnablePermission(Permission::AttachmentUpdate, $attachment);
|
||||
|
||||
$attachment = $this->attachmentService->updateFile($attachment, [
|
||||
'name' => $request->input('attachment_edit_name'),
|
||||
'link' => $request->input('attachment_edit_url'),
|
||||
@@ -142,6 +141,10 @@ class AttachmentController extends Controller
|
||||
public function attachLink(Request $request)
|
||||
{
|
||||
$pageId = $request->input('attachment_link_uploaded_to');
|
||||
$page = $this->pageQueries->findVisibleByIdOrFail($pageId);
|
||||
|
||||
$this->checkPermission(Permission::AttachmentCreateAll);
|
||||
$this->checkOwnablePermission(Permission::PageUpdate, $page);
|
||||
|
||||
try {
|
||||
$this->validate($request, [
|
||||
@@ -156,11 +159,6 @@ class AttachmentController extends Controller
|
||||
]), 422);
|
||||
}
|
||||
|
||||
$page = $this->pageQueries->findVisibleByIdOrFail($pageId);
|
||||
|
||||
$this->checkPermission(Permission::AttachmentCreateAll);
|
||||
$this->checkOwnablePermission(Permission::PageUpdate, $page);
|
||||
|
||||
$attachmentName = $request->input('attachment_link_name');
|
||||
$link = $request->input('attachment_link_url');
|
||||
$this->attachmentService->saveNewFromLink($attachmentName, $link, intval($pageId));
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace BookStack\Util;
|
||||
|
||||
use BookStack\Util\HtmlPurifier\ConfiguredHtmlPurifier;
|
||||
use DOMAttr;
|
||||
use DOMElement;
|
||||
use DOMNodeList;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Util;
|
||||
namespace BookStack\Util\HtmlPurifier;
|
||||
|
||||
use BookStack\App\AppVersion;
|
||||
use BookStack\Util\HtmlPurifier\Filters\UriLimitFileProtocolToAnchors;
|
||||
use HTMLPurifier;
|
||||
use HTMLPurifier_Config;
|
||||
use HTMLPurifier_DefinitionCache_Serializer;
|
||||
use HTMLPurifier_HTML5Config;
|
||||
use HTMLPurifier_HTMLDefinition;
|
||||
use HTMLPurifier_URIDefinition;
|
||||
|
||||
/**
|
||||
* Provides a configured HTML Purifier instance.
|
||||
@@ -33,7 +35,13 @@ class ConfiguredHtmlPurifier
|
||||
|
||||
$htmlDef = $config->getDefinition('HTML', true, true);
|
||||
if ($htmlDef instanceof HTMLPurifier_HTMLDefinition) {
|
||||
$this->configureDefinition($htmlDef);
|
||||
$this->configureHtmlDefinition($htmlDef);
|
||||
}
|
||||
|
||||
/** @var \HTMLPurifier_URIDefinition $uriDef */
|
||||
$uriDef = $config->getDefinition('URI', true, true);
|
||||
if ($uriDef instanceof HTMLPurifier_URIDefinition) {
|
||||
$this->configureUriDefinition($uriDef);
|
||||
}
|
||||
|
||||
$this->purifier = new HTMLPurifier($config);
|
||||
@@ -91,7 +99,7 @@ class ConfiguredHtmlPurifier
|
||||
// $config->set('Cache.DefinitionImpl', null); // Disable cache during testing
|
||||
}
|
||||
|
||||
public function configureDefinition(HTMLPurifier_HTMLDefinition $definition): void
|
||||
protected function configureHtmlDefinition(HTMLPurifier_HTMLDefinition $definition): void
|
||||
{
|
||||
// Allow the object element
|
||||
$definition->addElement(
|
||||
@@ -151,6 +159,11 @@ class ConfiguredHtmlPurifier
|
||||
$definition->addAttribute('a', 'data-mention-user-id', 'Number');
|
||||
}
|
||||
|
||||
protected function configureUriDefinition(HTMLPurifier_URIDefinition $definition): void
|
||||
{
|
||||
$definition->registerFilter(new UriLimitFileProtocolToAnchors());
|
||||
}
|
||||
|
||||
public function purify(string $html): string
|
||||
{
|
||||
return $this->purifier->purify($html);
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace BookStack\Util\HtmlPurifier\Filters;
|
||||
|
||||
use HTMLPurifier_Config;
|
||||
use HTMLPurifier_Context;
|
||||
use HTMLPurifier_URI;
|
||||
use HTMLPurifier_URIFilter;
|
||||
|
||||
/**
|
||||
* Limits file:// URIs to only be used on anchor tags href attributes.
|
||||
* This prevents use on iframes/embeds/images where they can be used to load external
|
||||
* content on the network, triggering calls which may include NTLM auth hashes when in
|
||||
* certain windows based environments.
|
||||
*/
|
||||
class UriLimitFileProtocolToAnchors extends HTMLPurifier_URIFilter
|
||||
{
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $name = 'LimitFileProtocolToAnchors';
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $always_load = true;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_URI $uri
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool
|
||||
*/
|
||||
public function filter(&$uri, $config, $context)
|
||||
{
|
||||
// Ensure we're only filtering file:// URIs'
|
||||
if ($uri->scheme !== 'file') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$token = $context->get('CurrentToken', true);
|
||||
$attr = $context->get('CurrentAttr', true);
|
||||
|
||||
// Only allow if used on hrefs on anchor tags
|
||||
$isAnchor = $token && $token->name === 'a';
|
||||
$isHref = $attr === 'href';
|
||||
if ($isAnchor && $isHref) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
118
composer.lock
generated
118
composer.lock
generated
@@ -62,16 +62,16 @@
|
||||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.382.2",
|
||||
"version": "3.384.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "6844cc6421c47d6b96633ab8039045012acbeb27"
|
||||
"reference": "c7d34f2d60515bd0c307e462268f75877842da4a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/6844cc6421c47d6b96633ab8039045012acbeb27",
|
||||
"reference": "6844cc6421c47d6b96633ab8039045012acbeb27",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c7d34f2d60515bd0c307e462268f75877842da4a",
|
||||
"reference": "c7d34f2d60515bd0c307e462268f75877842da4a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -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.382.2"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.384.5"
|
||||
},
|
||||
"time": "2026-05-27T18:11:41+00:00"
|
||||
"time": "2026-06-08T18:25:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -1179,25 +1179,26 @@
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "7.10.5",
|
||||
"version": "7.11.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "7c8d84b39e680315f687e8662a9d6fb0865c5148"
|
||||
"reference": "5af96f374e0ab4ebd747b8310888c99d3adb0a8c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7c8d84b39e680315f687e8662a9d6fb0865c5148",
|
||||
"reference": "7c8d84b39e680315f687e8662a9d6fb0865c5148",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/5af96f374e0ab4ebd747b8310888c99d3adb0a8c",
|
||||
"reference": "5af96f374e0ab4ebd747b8310888c99d3adb0a8c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/promises": "^2.3",
|
||||
"guzzlehttp/psr7": "^2.8",
|
||||
"guzzlehttp/promises": "^2.5",
|
||||
"guzzlehttp/psr7": "^2.11",
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.2 || ^3.0"
|
||||
"symfony/deprecation-contracts": "^2.5 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.24"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-client-implementation": "1.0"
|
||||
@@ -1206,7 +1207,7 @@
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
"ext-curl": "*",
|
||||
"guzzle/client-integration-tests": "3.0.2",
|
||||
"guzzlehttp/test-server": "^0.4",
|
||||
"guzzlehttp/test-server": "^0.5",
|
||||
"php-http/message-factory": "^1.1",
|
||||
"phpunit/phpunit": "^8.5.52 || ^9.6.34",
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0"
|
||||
@@ -1286,7 +1287,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/guzzle/issues",
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.10.5"
|
||||
"source": "https://github.com/guzzle/guzzle/tree/7.11.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1302,24 +1303,25 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-27T11:53:46+00:00"
|
||||
"time": "2026-06-07T22:54:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "2.4.1",
|
||||
"version": "2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2"
|
||||
"reference": "4360e982f87f5f258bf872d094647791db2f4c8e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/09e8a212562fb1fb6a512c4156ed71525969d6c2",
|
||||
"reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/4360e982f87f5f258bf872d094647791db2f4c8e",
|
||||
"reference": "4360e982f87f5f258bf872d094647791db2f4c8e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5 || ^8.0"
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"symfony/deprecation-contracts": "^2.5 || ^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8.2",
|
||||
@@ -1369,7 +1371,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/promises/issues",
|
||||
"source": "https://github.com/guzzle/promises/tree/2.4.1"
|
||||
"source": "https://github.com/guzzle/promises/tree/2.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1385,27 +1387,29 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-20T22:57:30+00:00"
|
||||
"time": "2026-06-02T12:23:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "2.10.3",
|
||||
"version": "2.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "7c1472269227dc6f18930bd903d7a88fe6c52130"
|
||||
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7c1472269227dc6f18930bd903d7a88fe6c52130",
|
||||
"reference": "7c1472269227dc6f18930bd903d7a88fe6c52130",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/bbb5e61349fa5cb822b3e87842b951088b76b81f",
|
||||
"reference": "bbb5e61349fa5cb822b3e87842b951088b76b81f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.1 || ^2.0",
|
||||
"ralouphie/getallheaders": "^3.0"
|
||||
"ralouphie/getallheaders": "^3.0",
|
||||
"symfony/deprecation-contracts": "^2.5 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.24"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-factory-implementation": "1.0",
|
||||
@@ -1486,7 +1490,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.10.3"
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.11.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -1502,7 +1506,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-27T11:48:20+00:00"
|
||||
"time": "2026-06-02T12:30:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/uri-template",
|
||||
@@ -1803,16 +1807,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v12.61.0",
|
||||
"version": "v12.61.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "1124062a1ca92d290c8bcb9b7f649920fa6816bf"
|
||||
"reference": "e8472ca9774452fe50841d9bdced060679f4d58d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/1124062a1ca92d290c8bcb9b7f649920fa6816bf",
|
||||
"reference": "1124062a1ca92d290c8bcb9b7f649920fa6816bf",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/e8472ca9774452fe50841d9bdced060679f4d58d",
|
||||
"reference": "e8472ca9774452fe50841d9bdced060679f4d58d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2021,7 +2025,7 @@
|
||||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2026-05-26T23:41:33+00:00"
|
||||
"time": "2026-06-04T14:22:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/prompts",
|
||||
@@ -4191,16 +4195,16 @@
|
||||
},
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"version": "v3.4.2",
|
||||
"version": "v3.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/predis/predis.git",
|
||||
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075"
|
||||
"reference": "8cc4319c06924c8ff0c5c7eec4243a19e3be32f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/2033429520d8997a7815a2485f56abe6d2d0e075",
|
||||
"reference": "2033429520d8997a7815a2485f56abe6d2d0e075",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/8cc4319c06924c8ff0c5c7eec4243a19e3be32f1",
|
||||
"reference": "8cc4319c06924c8ff0c5c7eec4243a19e3be32f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4242,7 +4246,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/predis/predis/issues",
|
||||
"source": "https://github.com/predis/predis/tree/v3.4.2"
|
||||
"source": "https://github.com/predis/predis/tree/v3.5.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -4250,7 +4254,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-09T20:33:04+00:00"
|
||||
"time": "2026-06-02T19:25:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/clock",
|
||||
@@ -6845,16 +6849,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.38.1",
|
||||
"version": "v1.38.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92"
|
||||
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92",
|
||||
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||
"reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6906,7 +6910,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1"
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6926,7 +6930,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-26T12:51:13+00:00"
|
||||
"time": "2026-05-27T06:59:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
@@ -7014,16 +7018,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php83",
|
||||
"version": "v1.38.1",
|
||||
"version": "v1.38.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php83.git",
|
||||
"reference": "8339098cae28673c15cce00d80734af0453054e2"
|
||||
"reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/8339098cae28673c15cce00d80734af0453054e2",
|
||||
"reference": "8339098cae28673c15cce00d80734af0453054e2",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/796a26abb75ce49f3a84433cd81bf1009d73d5f8",
|
||||
"reference": "796a26abb75ce49f3a84433cd81bf1009d73d5f8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7070,7 +7074,7 @@
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.38.1"
|
||||
"source": "https://github.com/symfony/polyfill-php83/tree/v1.38.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7090,7 +7094,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-26T12:51:13+00:00"
|
||||
"time": "2026-05-27T06:51:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php84",
|
||||
@@ -9179,11 +9183,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4cd98348c809924f62bb9cc8c047f5e73bc9a58",
|
||||
"reference": "b4cd98348c809924f62bb9cc8c047f5e73bc9a58",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
|
||||
"reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9239,7 +9243,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-05-28T08:22:43+00:00"
|
||||
"time": "2026-06-05T09:00:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
@@ -464,6 +464,11 @@ HTML;
|
||||
'<div style="background:#FF0000;left:0;color:#00FFEE;">Hello!</div>' => '<div style="background:#FF0000;color:#00FFEE;">Hello!</div>',
|
||||
'<div style="color:#00FFEE;">Hello!<style>testinghello!</style></div>' => '<div style="color:#00FFEE;">Hello!</div>',
|
||||
'<div drawio-diagram="5332" another-attr="cat">Hello!</div>' => '<div drawio-diagram="5332">Hello!</div>',
|
||||
'<iframe src="file://link/to/file" id="bkmrk-file-iframe"></iframe>' => '<iframe id="bkmrk-file-iframe"></iframe>',
|
||||
'<embed src="file://link/to/file" id="bkmrk-file-embed"></embed>' => '<embed id="bkmrk-file-embed">',
|
||||
'<object data="file://link/to/file" id="bkmrk-file-object"></object>' => '<object id="bkmrk-file-object">',
|
||||
'<div id="bkmrk-file-img"><img src="file://link/to/file" alt="My local image"></div>' => '<div id="bkmrk-file-img"></div>',
|
||||
'<div id="bkmrk-file-img"><img srcset="file://link/to/file" alt="My local image"></div>' => '<div id="bkmrk-file-img"></div>',
|
||||
];
|
||||
|
||||
config()->set('app.content_filtering', 'a');
|
||||
@@ -476,6 +481,7 @@ HTML;
|
||||
$resp = $this->get($page->getUrl());
|
||||
|
||||
$resp->assertSee($expected, false);
|
||||
$resp->assertDontSee($input, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +490,7 @@ HTML;
|
||||
$testCasesExpectedByInput = [
|
||||
'<p><a href="https://example.com" target="_blank">New tab linkydoodle</a></p>',
|
||||
'<p><a href="https://example.com/user/1" data-mention-user-id="5">@mentionusertext</a></p>',
|
||||
'<p><a href="file://link/to/file">Link to file</a></p>',
|
||||
'<details><summary>Hello</summary><p>Mydetailshere</p></details>',
|
||||
];
|
||||
|
||||
|
||||
@@ -233,6 +233,18 @@ class EntitySearchTest extends TestCase
|
||||
$this->get('/search?term=' . urlencode('danzorbhsing {created_before:2037-01-01}'))->assertDontSee($page->name);
|
||||
}
|
||||
|
||||
public function test_search_tags_with_unexpected_numeric_values_does_not_cause_error()
|
||||
{
|
||||
$pageA = $this->entities->page();
|
||||
$pageA->name = 'MyTestPageWithAwkwardNumericTagValue';
|
||||
$pageA->save();
|
||||
$pageA->tags()->save(new Tag(['name' => 'Count', 'value' => '1E999']));
|
||||
|
||||
$resp = $this->asEditor()->get('/search?term=' . urlencode('[Count=1E999]'));
|
||||
$resp->assertStatus(200);
|
||||
$resp->assertSee('MyTestPageWithAwkwardNumericTagValue');
|
||||
}
|
||||
|
||||
public function test_entity_selector_search()
|
||||
{
|
||||
$page = $this->entities->newPage(['name' => 'my ajax search test', 'html' => 'ajax test']);
|
||||
|
||||
@@ -159,6 +159,38 @@ class AttachmentTest extends TestCase
|
||||
$this->files->deleteAllAttachmentFiles();
|
||||
}
|
||||
|
||||
public function test_attachment_update_without_permission()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
$attachment = Attachment::factory()->create(['uploaded_to' => $page->id]);
|
||||
|
||||
$this->permissions->disableEntityInheritedPermissions($page);
|
||||
|
||||
$resp = $this->asViewer()->put("attachments/{$attachment->id}", [
|
||||
'attachment_edit_name' => 'My new attachment name',
|
||||
'attachment_edit_url' => 'https://test.example.com',
|
||||
]);
|
||||
|
||||
$this->assertPermissionError($resp);
|
||||
}
|
||||
|
||||
public function test_attachment_update_without_permission_with_validation_errors()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
/** @var Attachment $attachment */
|
||||
$attachment = Attachment::factory()->create(['uploaded_to' => $page->id]);
|
||||
|
||||
$this->permissions->disableEntityInheritedPermissions($page);
|
||||
|
||||
$resp = $this->asViewer()->put("attachments/{$attachment->id}", [
|
||||
'attachment_edit_name' => '',
|
||||
'attachment_edit_url' => 'https://test.example.com',
|
||||
]);
|
||||
|
||||
$this->assertPermissionError($resp);
|
||||
$resp->assertDontSee($attachment->path);
|
||||
}
|
||||
|
||||
public function test_file_deletion()
|
||||
{
|
||||
$page = $this->entities->page();
|
||||
|
||||
Reference in New Issue
Block a user