From 4046fed60f3950f1ceca2a0b8aa79cc8d8a020e0 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 27 Oct 2021 14:23:39 +0300 Subject: [PATCH 01/17] Changelog update --- CHANGELOG.md | 6 ++++++ .../Grav/Common/Processors/PagesProcessor.php | 20 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5320a0e5aa..0641d2bb9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.7.25 +## mm/dd/2021 + +1. [](#improved) + * Added `route` and `request` to `onPagesInitialized` event + # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Processors/PagesProcessor.php b/system/src/Grav/Common/Processors/PagesProcessor.php index 470ca907b5..36f6718d22 100644 --- a/system/src/Grav/Common/Processors/PagesProcessor.php +++ b/system/src/Grav/Common/Processors/PagesProcessor.php @@ -42,15 +42,29 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface $this->container['debugger']->addMessage($this->container['cache']->getCacheStatus()); $this->container['pages']->init(); - $this->container->fireEvent('onPagesInitialized', new Event(['pages' => $this->container['pages']])); - $this->container->fireEvent('onPageInitialized', new Event(['page' => $this->container['page']])); + + $route = $this->container['route']; + + $this->container->fireEvent('onPagesInitialized', new Event( + [ + 'pages' => $this->container['pages'], + 'route' => $route, + 'request' => $request + ] + )); + $this->container->fireEvent('onPageInitialized', new Event( + [ + 'page' => $this->container['page'], + 'route' => $route, + 'request' => $request + ] + )); /** @var PageInterface $page */ $page = $this->container['page']; if (!$page->routable()) { $exception = new RequestException($request, 'Page Not Found', 404); - $route = $this->container['route']; // If no page found, fire event $event = new Event([ 'page' => $page, From 125f2a8662f7eb1c654551db67d0d104be0b3e5a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 27 Oct 2021 14:24:16 +0300 Subject: [PATCH 02/17] Improved page cloning --- CHANGELOG.md | 1 + system/src/Grav/Common/Page/Page.php | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0641d2bb9e..5de83960a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 1. [](#improved) * Added `route` and `request` to `onPagesInitialized` event + * Improved page cloning # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 2099be2126..379f9bf581 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -218,6 +218,14 @@ public function init(SplFileInfo $file, $extension = null) return $this; } + public function __clone() + { + $this->header = $this->header ? clone $this->header : null; + $this->route = null; + $this->raw_route = null; + $this->_forms = null; + } + /** * @return void */ From 1d1c10f0a64c25c18368d3191a8077cc804faa23 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 27 Oct 2021 14:59:23 +0300 Subject: [PATCH 03/17] Added method `Page::initialize()` --- CHANGELOG.md | 2 +- system/src/Grav/Common/Page/Page.php | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5de83960a1..66f07b6654 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 1. [](#improved) * Added `route` and `request` to `onPagesInitialized` event - * Improved page cloning + * Improved page cloning, added method `Page::initialize()` # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 379f9bf581..11b9790ccb 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -220,10 +220,21 @@ public function init(SplFileInfo $file, $extension = null) public function __clone() { + $this->initialized = false; $this->header = $this->header ? clone $this->header : null; - $this->route = null; - $this->raw_route = null; - $this->_forms = null; + } + + /** + * @return void + */ + public function initialize(): void + { + if (!$this->initialized) { + $this->initialized = true; + $this->route = null; + $this->raw_route = null; + $this->_forms = null; + } } /** From cd1dc5b43dceffa0219308ff0377c6fa3b3b7aca Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 29 Oct 2021 10:53:01 -0600 Subject: [PATCH 04/17] better vardump variable --- CHANGELOG.md | 6 ++++++ system/src/Grav/Common/Twig/Extension/GravExtension.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5320a0e5aa..92c927a5c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.7.25 +## mm/dd/2021 + +2. [](#improved) + * Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function + # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index 638617c4df..bee1bbce8d 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -1354,7 +1354,7 @@ public function mediaDirFunc($media_dir) */ public function vardumpFunc($var) { - var_dump($var); + dump($var); } /** From 3d0d836d921e73c23aa76acf0280f3bc5da5f9c6 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 2 Nov 2021 15:27:53 +0200 Subject: [PATCH 05/17] Composer update --- composer.lock | 90 +++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/composer.lock b/composer.lock index 5fbc07ac55..dd87621f43 100644 --- a/composer.lock +++ b/composer.lock @@ -56,16 +56,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.2.11", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582" + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", - "reference": "0b072d51c5a9c6f3412f7ea3ab043d6603cb2582", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", + "reference": "4c679186f2aca4ab6a0f1b0b9cf9252decb44d0b", "shasum": "" }, "require": { @@ -112,7 +112,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.2.11" + "source": "https://github.com/composer/ca-bundle/tree/1.3.1" }, "funding": [ { @@ -128,7 +128,7 @@ "type": "tidelift" } ], - "time": "2021-09-25T20:32:43+00:00" + "time": "2021-10-28T20:44:15+00:00" }, { "name": "composer/semver", @@ -888,22 +888,22 @@ }, { "name": "itsgoingd/clockwork", - "version": "v5.1.0", + "version": "v5.1.1", "source": { "type": "git", "url": "https://github.com/itsgoingd/clockwork.git", - "reference": "b963dee47429a49c9669981cfa9a8362ce209278" + "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/b963dee47429a49c9669981cfa9a8362ce209278", - "reference": "b963dee47429a49c9669981cfa9a8362ce209278", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/2daf30fa6dfc5a1ccfdb2142df59243a72c473d8", + "reference": "2daf30fa6dfc5a1ccfdb2142df59243a72c473d8", "shasum": "" }, "require": { "ext-json": "*", "php": ">=5.6", - "psr/log": "1.*" + "psr/log": "1.* || ^2.0" }, "type": "library", "extra": { @@ -945,7 +945,7 @@ ], "support": { "issues": "https://github.com/itsgoingd/clockwork/issues", - "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.0" + "source": "https://github.com/itsgoingd/clockwork/tree/v5.1.1" }, "funding": [ { @@ -953,7 +953,7 @@ "type": "github" } ], - "time": "2021-08-07T23:04:17+00:00" + "time": "2021-11-01T17:38:35+00:00" }, { "name": "league/climate", @@ -1153,16 +1153,16 @@ }, { "name": "maximebf/debugbar", - "version": "v1.17.2", + "version": "v1.17.3", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418" + "reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", - "reference": "3541f09f09c003c4a9ff7ddb0eb3361a7f14d418", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e8ac3499af0ea5b440908e06cc0abe5898008b3c", + "reference": "e8ac3499af0ea5b440908e06cc0abe5898008b3c", "shasum": "" }, "require": { @@ -1212,9 +1212,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.2" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.17.3" }, - "time": "2021-10-18T09:39:00+00:00" + "time": "2021-10-19T12:33:27+00:00" }, { "name": "miljar/php-exif", @@ -2239,16 +2239,16 @@ }, { "name": "symfony/console", - "version": "v4.4.30", + "version": "v4.4.33", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22" + "reference": "8dbd23ef7a8884051482183ddee8d9061b5feed0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/a3f7189a0665ee33b50e9e228c46f50f5acbed22", - "reference": "a3f7189a0665ee33b50e9e228c46f50f5acbed22", + "url": "https://api.github.com/repos/symfony/console/zipball/8dbd23ef7a8884051482183ddee8d9061b5feed0", + "reference": "8dbd23ef7a8884051482183ddee8d9061b5feed0", "shasum": "" }, "require": { @@ -2309,7 +2309,7 @@ "description": "Eases the creation of beautiful and testable command line interfaces", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/console/tree/v4.4.30" + "source": "https://github.com/symfony/console/tree/v4.4.33" }, "funding": [ { @@ -2325,7 +2325,7 @@ "type": "tidelift" } ], - "time": "2021-08-25T19:27:26+00:00" + "time": "2021-10-25T16:36:08+00:00" }, { "name": "symfony/contracts", @@ -2507,16 +2507,16 @@ }, { "name": "symfony/http-client", - "version": "v4.4.31", + "version": "v4.4.33", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "6b900ffa399e25203f30f79f6f4a56b89eee14c2" + "reference": "9a5fdf129b522a06a46d13400500d326c41d8a73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/6b900ffa399e25203f30f79f6f4a56b89eee14c2", - "reference": "6b900ffa399e25203f30f79f6f4a56b89eee14c2", + "url": "https://api.github.com/repos/symfony/http-client/zipball/9a5fdf129b522a06a46d13400500d326c41d8a73", + "reference": "9a5fdf129b522a06a46d13400500d326c41d8a73", "shasum": "" }, "require": { @@ -2568,7 +2568,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v4.4.31" + "source": "https://github.com/symfony/http-client/tree/v4.4.33" }, "funding": [ { @@ -2584,7 +2584,7 @@ "type": "tidelift" } ], - "time": "2021-09-06T10:00:00+00:00" + "time": "2021-10-18T16:39:13+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3052,16 +3052,16 @@ }, { "name": "symfony/var-dumper", - "version": "v4.4.31", + "version": "v4.4.33", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "1f12cc0c2e880a5f39575c19af81438464717839" + "reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/1f12cc0c2e880a5f39575c19af81438464717839", - "reference": "1f12cc0c2e880a5f39575c19af81438464717839", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/50286e2b7189bfb4f419c0731e86632cddf7c5ee", + "reference": "50286e2b7189bfb4f419c0731e86632cddf7c5ee", "shasum": "" }, "require": { @@ -3121,7 +3121,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v4.4.31" + "source": "https://github.com/symfony/var-dumper/tree/v4.4.33" }, "funding": [ { @@ -3137,7 +3137,7 @@ "type": "tidelift" } ], - "time": "2021-09-24T15:30:11+00:00" + "time": "2021-10-25T20:24:58+00:00" }, { "name": "symfony/yaml", @@ -4716,23 +4716,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.7", + "version": "9.2.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218" + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d4c798ed8d51506800b441f7a13ecb0f76f12218", - "reference": "d4c798ed8d51506800b441f7a13ecb0f76f12218", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", + "reference": "cf04e88a2e3c56fc1a65488afd493325b4c1bc3e", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.12.0", + "nikic/php-parser": "^4.13.0", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -4781,7 +4781,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.8" }, "funding": [ { @@ -4789,7 +4789,7 @@ "type": "github" } ], - "time": "2021-09-17T05:39:03+00:00" + "time": "2021-10-30T08:01:38+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6620,5 +6620,5 @@ "platform-overrides": { "php": "7.3.6" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } From a723bcdb469eec822aa9861416f9968b31cd874f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 3 Nov 2021 11:50:23 +0200 Subject: [PATCH 06/17] Fixed unescaped error messages in JSON error responses --- CHANGELOG.md | 9 +++++---- .../Traits/ControllerResponseTrait.php | 2 +- .../RequestHandler/Middlewares/Exceptions.php | 20 +++++++++++++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11e23849e3..da5de244c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ ## mm/dd/2021 1. [](#improved) - * Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function - * Added `route` and `request` to `onPagesInitialized` event - * Improved page cloning, added method `Page::initialize()` - + * Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function + * Added `route` and `request` to `onPagesInitialized` event + * Improved page cloning, added method `Page::initialize()` +2. [](#bugfix) + * Fixed unescaped error messages in JSON error responses # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php index 62ed3e1035..53c9cd4c28 100644 --- a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php +++ b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php @@ -203,7 +203,7 @@ protected function createJsonErrorResponse(Throwable $e): ResponseInterface protected function getErrorJson(Throwable $e): array { $code = $this->getErrorCode($e instanceof RequestException ? $e->getHttpCode() : $e->getCode()); - $message = $e->getMessage(); + $message = htmlspecialchars($e->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $response = [ 'code' => $code, 'status' => 'error', diff --git a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php index a9935eeb03..63cfe3eade 100644 --- a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php +++ b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php @@ -14,6 +14,7 @@ use Grav\Common\Debugger; use Grav\Common\Grav; use Grav\Framework\Psr7\Response; +use JsonException; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -27,15 +28,26 @@ */ class Exceptions implements MiddlewareInterface { + /** + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + * @throws JsonException + */ public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { try { return $handler->handle($request); } catch (Throwable $exception) { + $code = $exception->getCode(); + $message = htmlspecialchars($exception->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $response = [ + 'code' => $code, + 'status' => 'error', + 'message' => $message, 'error' => [ - 'code' => $exception->getCode(), - 'message' => $exception->getMessage(), + 'code' => $code, + 'message' => $message, ] ]; @@ -51,9 +63,9 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } /** @var string $json */ - $json = json_encode($response); + $json = json_encode($response, JSON_THROW_ON_ERROR); - return new Response($exception->getCode() ?: 500, ['Content-Type' => 'application/json'], $json); + return new Response($code ?: 500, ['Content-Type' => 'application/json'], $json); } } } From 8bbf7a849b57bc4f943b266ece0572b341d593ea Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 3 Nov 2021 13:10:10 +0200 Subject: [PATCH 07/17] Fixed `|t(variable)` twig filter in admin --- CHANGELOG.md | 1 + system/src/Grav/Common/Twig/Extension/GravExtension.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da5de244c7..fa41efcf6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Improved page cloning, added method `Page::initialize()` 2. [](#bugfix) * Fixed unescaped error messages in JSON error responses + * Fixed `|t(variable)` twig filter in admin # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index bee1bbce8d..20d2648088 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -847,6 +847,12 @@ public function translate(Environment $twig, ...$args) if (($numargs === 3 && is_array($args[1])) || ($numargs === 2 && !is_array($args[1]))) { $lang = array_pop($args); + /** @var Language $language */ + $language = $this->grav['language']; + if (is_string($lang) && !$language->getLanguageCode($lang)) { + $args[] = $lang; + $lang = null; + } } elseif ($numargs === 2 && is_array($args[1])) { $subs = array_pop($args); $args = array_merge($args, $subs); From 8f9c417c04b89dc8d2de60b95e7696821b2826ce Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 3 Nov 2021 14:06:42 +0200 Subject: [PATCH 08/17] Fixed path traversal vulnerability when using `bin/grav server` --- CHANGELOG.md | 1 + system/router.php | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa41efcf6a..28dc8dbe68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Added `route` and `request` to `onPagesInitialized` event * Improved page cloning, added method `Page::initialize()` 2. [](#bugfix) + * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses * Fixed `|t(variable)` twig filter in admin diff --git a/system/router.php b/system/router.php index 187d4d8443..d58609c836 100644 --- a/system/router.php +++ b/system/router.php @@ -13,8 +13,25 @@ $_SERVER['PHP_CLI_ROUTER'] = true; -if (is_file($_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR . $_SERVER['SCRIPT_NAME'])) { - return false; +$root = $_SERVER['DOCUMENT_ROOT']; +$path = $_SERVER['SCRIPT_NAME']; +if ($path !== '/index.php' && is_file($root . $path)) { + if (!( + // Block all direct access to files and folders beginning with a dot + strpos($path, '/.') !== false + // Block all direct access for these folders + || preg_match('`^/(\.git|cache|bin|logs|backup|webserver-configs|tests)/`ui', $path) + // Block access to specific file types for these system folders + || preg_match('`^/(system|vendor)/(.*)\.(txt|xml|md|html|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path) + // Block access to specific file types for these user folders + || preg_match('`^/(user)/(.*)\.(txt|md|yaml|yml|php|pl|py|cgi|twig|sh|bat)$`ui', $path) + // Block all direct access to .md files + || preg_match('`\.md$`ui', $path) + // Block access to specific files in the root folder + || preg_match('`^/(LICENSE\.txt|composer\.lock|composer\.json|\.htaccess)$`ui', $path) + )) { + return false; + } } $grav_index = 'index.php'; From ad003a0fc41b2a1ff51a23cee53e085e13580bbb Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 4 Nov 2021 08:55:53 +0200 Subject: [PATCH 09/17] Updated phpstan to v1.0 --- CHANGELOG.md | 6 ++- composer.json | 4 +- composer.lock | 49 +++++++++---------- system/src/Grav/Common/Backup/Backups.php | 3 +- .../Common/Flex/Types/Pages/PageIndex.php | 8 +-- system/src/Grav/Common/Grav.php | 6 +-- .../Page/Interfaces/PageContentInterface.php | 2 +- system/src/Grav/Common/Page/Page.php | 2 +- .../Common/Processors/InitializeProcessor.php | 2 +- .../Common/Service/ConfigServiceProvider.php | 2 +- .../Common/Twig/Extension/GravExtension.php | 2 +- system/src/Grav/Common/User/Group.php | 2 +- system/src/Grav/Common/Utils.php | 9 ++-- system/src/Grav/Common/Yaml.php | 6 +-- system/src/Grav/Console/Gpm/IndexCommand.php | 2 - .../Grav/Framework/Acl/PermissionsReader.php | 2 +- .../Collection/AbstractFileCollection.php | 4 +- .../Collection/AbstractIndexCollection.php | 17 ++++--- .../Collection/CollectionInterface.php | 8 +-- .../Framework/Collection/FileCollection.php | 6 +-- system/src/Grav/Framework/Flex/Flex.php | 2 +- .../Grav/Framework/Flex/FlexDirectoryForm.php | 2 +- system/src/Grav/Framework/Flex/FlexIndex.php | 2 +- .../Framework/Flex/Storage/FolderStorage.php | 2 + .../Grav/Framework/Form/Traits/FormTrait.php | 2 +- .../Logger/Processors/UserProcessor.php | 34 +++++++++++++ .../src/Grav/Framework/Object/ObjectIndex.php | 7 +-- tests/phpstan/phpstan.neon | 2 +- tests/phpstan/plugins.neon | 2 +- 29 files changed, 116 insertions(+), 81 deletions(-) create mode 100644 system/src/Grav/Framework/Logger/Processors/UserProcessor.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 28dc8dbe68..e5a896fda1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # v1.7.25 ## mm/dd/2021 -1. [](#improved) +1. [](#new) + * Updated phpstan to v1.0 +2. [](#improved) * Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function * Added `route` and `request` to `onPagesInitialized` event * Improved page cloning, added method `Page::initialize()` -2. [](#bugfix) +3. [](#bugfix) * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses * Fixed `|t(variable)` twig filter in admin diff --git a/composer.json b/composer.json index e86c6aa06c..2067b69572 100644 --- a/composer.json +++ b/composer.json @@ -63,8 +63,8 @@ }, "require-dev": { "codeception/codeception": "^4.1", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-deprecation-rules": "^0.12", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-deprecation-rules": "^1.0", "phpunit/php-code-coverage": "~9.2", "getgrav/markdowndocs": "^2.0", "codeception/module-asserts": "^1.3", diff --git a/composer.lock b/composer.lock index dd87621f43..dbf6a60654 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "23dd68cea2a3f2d963e57638131f1122", + "content-hash": "88527e29c63574c4fdb788ff8ed34245", "packages": [ { "name": "antoligy/dom-string-iterators", @@ -4207,16 +4207,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.13.0", + "version": "v4.13.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53" + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/50953a2691a922aa1769461637869a0a2faa3f53", - "reference": "50953a2691a922aa1769461637869a0a2faa3f53", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd", + "reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd", "shasum": "" }, "require": { @@ -4257,9 +4257,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1" }, - "time": "2021-09-20T12:20:58+00:00" + "time": "2021-11-03T20:52:16+00:00" }, { "name": "phar-io/manifest", @@ -4601,16 +4601,16 @@ }, { "name": "phpstan/phpstan", - "version": "0.12.99", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7" + "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b4d40f1d759942f523be267a1bab6884f46ca3f7", - "reference": "b4d40f1d759942f523be267a1bab6884f46ca3f7", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e9e2a501102ba0b126b2f63a7f0a3b151056fe91", + "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91", "shasum": "" }, "require": { @@ -4626,7 +4626,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.12-dev" + "dev-master": "1.0-dev" } }, "autoload": { @@ -4641,7 +4641,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/0.12.99" + "source": "https://github.com/phpstan/phpstan/tree/1.0.2" }, "funding": [ { @@ -4661,36 +4661,35 @@ "type": "tidelift" } ], - "time": "2021-09-12T20:09:55+00:00" + "time": "2021-11-03T16:09:51+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "0.12.6", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "46dbd43c2db973d2876d6653e53f5c2cc3a01fbb" + "reference": "e5ccafb0dd8d835dd65d8d7a1a0d2b1b75414682" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/46dbd43c2db973d2876d6653e53f5c2cc3a01fbb", - "reference": "46dbd43c2db973d2876d6653e53f5c2cc3a01fbb", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/e5ccafb0dd8d835dd65d8d7a1a0d2b1b75414682", + "reference": "e5ccafb0dd8d835dd65d8d7a1a0d2b1b75414682", "shasum": "" }, "require": { "php": "^7.1 || ^8.0", - "phpstan/phpstan": "^0.12.60" + "phpstan/phpstan": "^1.0" }, "require-dev": { - "phing/phing": "^2.16.3", "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^0.12", - "phpunit/phpunit": "^7.5.20" + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" }, "type": "phpstan-extension", "extra": { "branch-alias": { - "dev-master": "0.12-dev" + "dev-master": "1.0-dev" }, "phpstan": { "includes": [ @@ -4710,9 +4709,9 @@ "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/0.12.6" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.0.0" }, - "time": "2020-12-13T10:20:54+00:00" + "time": "2021-09-23T11:02:21+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/system/src/Grav/Common/Backup/Backups.php b/system/src/Grav/Common/Backup/Backups.php index b70def96f7..4680f85462 100644 --- a/system/src/Grav/Common/Backup/Backups.php +++ b/system/src/Grav/Common/Backup/Backups.php @@ -144,9 +144,8 @@ public function getBackupNames() public static function getTotalBackupsSize() { $backups = static::getAvailableBackups(); - $size = array_sum(array_column($backups, 'size')); - return $size ?? 0; + return array_sum(array_column($backups, 'size')); } /** diff --git a/system/src/Grav/Common/Flex/Types/Pages/PageIndex.php b/system/src/Grav/Common/Flex/Types/Pages/PageIndex.php index f02a64866d..5a7d773a47 100644 --- a/system/src/Grav/Common/Flex/Types/Pages/PageIndex.php +++ b/system/src/Grav/Common/Flex/Types/Pages/PageIndex.php @@ -554,6 +554,9 @@ protected function getLevelListingRecurse(array $options): array $filters = array_filter($filters, static function($val) { return $val !== null && $val !== ''; }); if ($page) { + $status = 'success'; + $msg = 'PLUGIN_ADMIN.PAGE_ROUTE_FOUND'; + if ($page->root() && (!$filter_type || in_array('root', $filter_type, true))) { if ($field) { $response[] = [ @@ -593,9 +596,6 @@ protected function getLevelListingRecurse(array $options): array } } - $status = 'success'; - $msg = 'PLUGIN_ADMIN.PAGE_ROUTE_FOUND'; - /** @var PageIndex $children */ $children = $page->children()->getIndex(); $selectedChildren = $children->filterBy($filters, true); @@ -721,7 +721,7 @@ protected function getLevelListingRecurse(array $options): array $response = Utils::arrayFlatten($sorted); } - return [$status, $msg ?? 'PLUGIN_ADMIN.NO_ROUTE_PROVIDED', $response, $path]; + return [$status, $msg, $response, $path]; } /** diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index f5919613ba..1169b74f67 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -774,11 +774,9 @@ public function fallbackUrl($path) } Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download); } - - // Nothing found - return false; } - return $page ?? false; + // Nothing found + return false; } } diff --git a/system/src/Grav/Common/Page/Interfaces/PageContentInterface.php b/system/src/Grav/Common/Page/Interfaces/PageContentInterface.php index 5156ede294..d9d3105b6b 100644 --- a/system/src/Grav/Common/Page/Interfaces/PageContentInterface.php +++ b/system/src/Grav/Common/Page/Interfaces/PageContentInterface.php @@ -58,7 +58,7 @@ public function getRawContent(); /** * Needed by the onPageContentProcessed event to set the raw page content * - * @param string $content + * @param string|null $content */ public function setRawContent($content); diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 11b9790ccb..9e68a44f8f 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -994,7 +994,7 @@ public function getRawContent() /** * Needed by the onPageContentProcessed event to set the raw page content * - * @param string $content + * @param string|null $content * @return void */ public function setRawContent($content) diff --git a/system/src/Grav/Common/Processors/InitializeProcessor.php b/system/src/Grav/Common/Processors/InitializeProcessor.php index 55cba033cc..b31530e803 100644 --- a/system/src/Grav/Common/Processors/InitializeProcessor.php +++ b/system/src/Grav/Common/Processors/InitializeProcessor.php @@ -44,7 +44,7 @@ class InitializeProcessor extends ProcessorBase public $title = 'Initialize'; /** @var bool */ - private static $cli_initialized = false; + protected static $cli_initialized = false; /** * @param Grav $grav diff --git a/system/src/Grav/Common/Service/ConfigServiceProvider.php b/system/src/Grav/Common/Service/ConfigServiceProvider.php index b56f62fdee..3a5c2e27b3 100644 --- a/system/src/Grav/Common/Service/ConfigServiceProvider.php +++ b/system/src/Grav/Common/Service/ConfigServiceProvider.php @@ -179,7 +179,7 @@ public static function languages(Container $container) * @param string $folder_path * @return array */ - private static function pluginFolderPaths($plugins, $folder_path) + protected static function pluginFolderPaths($plugins, $folder_path) { $paths = []; diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index 20d2648088..4c0d9fe469 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -1424,7 +1424,7 @@ public function niceNumberFunc($n) * @param array $context Twig Context * @param string $var variable to be found (using dot notation) * @param null $default the default value to be used as last resort - * @param null $page an optional page to use for the current page + * @param PageInterface|null $page an optional page to use for the current page * @param bool $exists toggle to simply return the page where the variable is set, else null * @return mixed */ diff --git a/system/src/Grav/Common/User/Group.php b/system/src/Grav/Common/User/Group.php index 5be53869e7..7dd6d650cb 100644 --- a/system/src/Grav/Common/User/Group.php +++ b/system/src/Grav/Common/User/Group.php @@ -27,7 +27,7 @@ class Group extends Data * @return array * @deprecated 1.7, use $grav['user_groups'] Flex UserGroupCollection instead */ - private static function groups() + protected static function groups() { user_error(__METHOD__ . '() is deprecated since Grav 1.7, use $grav[\'user_groups\'] Flex UserGroupCollection instead', E_USER_DEPRECATED); diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index f843a0c663..5295a64007 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -21,6 +21,7 @@ use Grav\Common\Page\Pages; use Grav\Framework\Flex\Flex; use Grav\Framework\Flex\Interfaces\FlexObjectInterface; +use Grav\Framework\Media\Interfaces\MediaInterface; use InvalidArgumentException; use Negotiation\Accept; use Negotiation\Negotiator; @@ -150,7 +151,7 @@ public static function url($input, $domain = false, $fail_gracefully = false) $domain = $domain ?: $grav['config']->get('system.absolute_urls', false); - return rtrim($uri->rootUrl($domain), '/') . '/' . ($resource ?? ''); + return rtrim($uri->rootUrl($domain), '/') . '/' . ($resource ?: ''); } /** @@ -1566,7 +1567,7 @@ public static function getPathFromToken($path, $object = null) switch ($matches[0]) { case 'self': - if (null === $object) { + if (!$object instanceof MediaInterface) { throw new RuntimeException(sprintf('Page not available for self@ reference: %s', $path)); } @@ -1640,7 +1641,7 @@ public static function getPathFromToken($path, $object = null) * @param string $path * @return string[]|null */ - private static function resolveTokenPath(string $path): ?array + protected static function resolveTokenPath(string $path): ?array { if (strpos($path, '@') !== false) { $regex = '/^(@\w+|\w+@|@\w+@)([^:]*)(.*)$/u'; @@ -1774,7 +1775,7 @@ static function ($matches) { * * @param string $string * @param bool $block Block or Line processing - * @param null $page + * @param PageInterface|null $page * @return string * @throws Exception */ diff --git a/system/src/Grav/Common/Yaml.php b/system/src/Grav/Common/Yaml.php index 5adbd0c10a..330b6c383e 100644 --- a/system/src/Grav/Common/Yaml.php +++ b/system/src/Grav/Common/Yaml.php @@ -17,8 +17,8 @@ */ abstract class Yaml { - /** @var YamlFormatter */ - private static $yaml; + /** @var YamlFormatter|null */ + protected static $yaml; /** * @param string $data @@ -51,7 +51,7 @@ public static function dump($data, $inline = null, $indent = null) /** * @return void */ - private static function init() + protected static function init() { $config = [ 'inline' => 5, diff --git a/system/src/Grav/Console/Gpm/IndexCommand.php b/system/src/Grav/Console/Gpm/IndexCommand.php index 64d3597813..ecc91feb03 100644 --- a/system/src/Grav/Console/Gpm/IndexCommand.php +++ b/system/src/Grav/Console/Gpm/IndexCommand.php @@ -200,7 +200,6 @@ private function version(Package $package): string */ private function installed(Package $package): string { - $package = $list[$package->slug] ?? $package; $type = ucfirst(preg_replace('/s$/', '', $package->package_type)); $method = 'is' . $type . 'Installed'; $installed = $this->gpm->{$method}($package->slug); @@ -214,7 +213,6 @@ private function installed(Package $package): string */ private function enabled(Package $package): string { - $package = $list[$package->slug] ?? $package; $type = ucfirst(preg_replace('/s$/', '', $package->package_type)); $method = 'is' . $type . 'Installed'; $installed = $this->gpm->{$method}($package->slug); diff --git a/system/src/Grav/Framework/Acl/PermissionsReader.php b/system/src/Grav/Framework/Acl/PermissionsReader.php index 4f4a6a3174..b157a5d3bd 100644 --- a/system/src/Grav/Framework/Acl/PermissionsReader.php +++ b/system/src/Grav/Framework/Acl/PermissionsReader.php @@ -21,7 +21,7 @@ class PermissionsReader { /** @var array */ - private static $types; + protected static $types; /** * @param string $filename diff --git a/system/src/Grav/Framework/Collection/AbstractFileCollection.php b/system/src/Grav/Framework/Collection/AbstractFileCollection.php index f892267476..1be8d129a9 100644 --- a/system/src/Grav/Framework/Collection/AbstractFileCollection.php +++ b/system/src/Grav/Framework/Collection/AbstractFileCollection.php @@ -25,9 +25,9 @@ * * @package Grav\Framework\Collection * @template TKey of array-key - * @template T + * @template T of object * @extends AbstractLazyCollection - * @mplements FileCollectionInterface + * @implements FileCollectionInterface */ class AbstractFileCollection extends AbstractLazyCollection implements FileCollectionInterface { diff --git a/system/src/Grav/Framework/Collection/AbstractIndexCollection.php b/system/src/Grav/Framework/Collection/AbstractIndexCollection.php index 38d3ab51ef..25d8672c0c 100644 --- a/system/src/Grav/Framework/Collection/AbstractIndexCollection.php +++ b/system/src/Grav/Framework/Collection/AbstractIndexCollection.php @@ -22,6 +22,7 @@ * Abstract Index Collection. * @template TKey of array-key * @template T + * @template C of CollectionInterface * @implements CollectionInterface */ abstract class AbstractIndexCollection implements CollectionInterface @@ -184,7 +185,7 @@ public function offsetSet($offset, $value) #[\ReturnTypeWillChange] public function offsetUnset($offset) { - return $this->remove($offset); + $this->remove($offset); } /** @@ -365,7 +366,7 @@ public function slice($offset, $length = null) * @param int $start * @param int|null $limit * @return static - * @phpstan-return static + * @phpstan-return static */ public function limit($start, $limit = null) { @@ -376,7 +377,7 @@ public function limit($start, $limit = null) * Reverse the order of the items. * * @return static - * @phpstan-return static + * @phpstan-return static */ public function reverse() { @@ -387,7 +388,7 @@ public function reverse() * Shuffle items. * * @return static - * @phpstan-return static + * @phpstan-return static */ public function shuffle() { @@ -404,7 +405,7 @@ public function shuffle() * * @param array $keys * @return static - * @phpstan-return static + * @phpstan-return static */ public function select(array $keys) { @@ -423,7 +424,7 @@ public function select(array $keys) * * @param array $keys * @return static - * @phpstan-return static + * @phpstan-return static */ public function unselect(array $keys) { @@ -478,7 +479,7 @@ public function jsonSerialize() * * @param array $entries Elements. * @return static - * @phpstan-return static + * @phpstan-return static */ protected function createFrom(array $entries) { @@ -531,7 +532,7 @@ abstract protected function loadElements(array $entries = null): array; /** * @param array|null $entries * @return CollectionInterface - * @phpstan-return T + * @phpstan-return C */ abstract protected function loadCollection(array $entries = null): CollectionInterface; diff --git a/system/src/Grav/Framework/Collection/CollectionInterface.php b/system/src/Grav/Framework/Collection/CollectionInterface.php index 42414cecdd..0739109ba0 100644 --- a/system/src/Grav/Framework/Collection/CollectionInterface.php +++ b/system/src/Grav/Framework/Collection/CollectionInterface.php @@ -26,7 +26,7 @@ interface CollectionInterface extends Collection, JsonSerializable * Reverse the order of the items. * * @return CollectionInterface - * @phpstan-return CollectionInterface + * @phpstan-return static */ public function reverse(); @@ -34,7 +34,7 @@ public function reverse(); * Shuffle items. * * @return CollectionInterface - * @phpstan-return CollectionInterface + * @phpstan-return static */ public function shuffle(); @@ -53,7 +53,7 @@ public function chunk($size); * * @param array $keys * @return CollectionInterface - * @phpstan-return CollectionInterface + * @phpstan-return static */ public function select(array $keys); @@ -62,7 +62,7 @@ public function select(array $keys); * * @param array $keys * @return CollectionInterface - * @phpstan-return CollectionInterface + * @phpstan-return static */ public function unselect(array $keys); } diff --git a/system/src/Grav/Framework/Collection/FileCollection.php b/system/src/Grav/Framework/Collection/FileCollection.php index 59df2210e5..f7b4f258b9 100644 --- a/system/src/Grav/Framework/Collection/FileCollection.php +++ b/system/src/Grav/Framework/Collection/FileCollection.php @@ -9,13 +9,13 @@ namespace Grav\Framework\Collection; +use stdClass; + /** * Collection of objects stored into a filesystem. * * @package Grav\Framework\Collection - * @template TKey of array-key - * @template T - * @extends AbstractFileCollection + * @extends AbstractFileCollection */ class FileCollection extends AbstractFileCollection { diff --git a/system/src/Grav/Framework/Flex/Flex.php b/system/src/Grav/Framework/Flex/Flex.php index 87392823d4..ce285215cf 100644 --- a/system/src/Grav/Framework/Flex/Flex.php +++ b/system/src/Grav/Framework/Flex/Flex.php @@ -256,7 +256,7 @@ public function getObjects(array $keys, array $options = []): array } // Remove missing objects if not asked to keep them. - if (empty($option['keep_missing'])) { + if (empty($options['keep_missing'])) { $list = array_filter($list); } diff --git a/system/src/Grav/Framework/Flex/FlexDirectoryForm.php b/system/src/Grav/Framework/Flex/FlexDirectoryForm.php index 66b6f3e148..8d608fdf82 100644 --- a/system/src/Grav/Framework/Flex/FlexDirectoryForm.php +++ b/system/src/Grav/Framework/Flex/FlexDirectoryForm.php @@ -99,7 +99,7 @@ public function __construct(string $name, FlexDirectory $directory, array $optio $this->setFlashLookupFolder($directory->getDirectoryBlueprint()->get('form/flash_folder') ?? 'tmp://forms/[SESSIONID]'); $this->form = $options['form'] ?? null; - if (Utils::isPositive($this->items['disabled'] ?? $this->form['disabled'] ?? false)) { + if (Utils::isPositive($this->form['disabled'] ?? false)) { $this->disable(); } diff --git a/system/src/Grav/Framework/Flex/FlexIndex.php b/system/src/Grav/Framework/Flex/FlexIndex.php index 1df5c4d0d8..3ce0a46c48 100644 --- a/system/src/Grav/Framework/Flex/FlexIndex.php +++ b/system/src/Grav/Framework/Flex/FlexIndex.php @@ -35,7 +35,7 @@ * @package Grav\Framework\Flex * @template T of FlexObjectInterface * @template C of FlexCollectionInterface - * @extends ObjectIndex + * @extends ObjectIndex * @implements FlexIndexInterface * @mixin C */ diff --git a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php index ff2c94d7a6..b2b9533a26 100644 --- a/system/src/Grav/Framework/Flex/Storage/FolderStorage.php +++ b/system/src/Grav/Framework/Flex/Storage/FolderStorage.php @@ -224,6 +224,7 @@ public function replaceRows(array $rows): array * @param string $src * @param string $dst * @return bool + * @throws RuntimeException */ public function copyRow(string $src, string $dst): bool { @@ -247,6 +248,7 @@ public function copyRow(string $src, string $dst): bool /** * {@inheritdoc} * @see FlexStorageInterface::renameRow() + * @throws RuntimeException */ public function renameRow(string $src, string $dst): bool { diff --git a/system/src/Grav/Framework/Form/Traits/FormTrait.php b/system/src/Grav/Framework/Form/Traits/FormTrait.php index 4362cf5e47..d77a402747 100644 --- a/system/src/Grav/Framework/Form/Traits/FormTrait.php +++ b/system/src/Grav/Framework/Form/Traits/FormTrait.php @@ -711,7 +711,7 @@ protected function parseRequest(ServerRequestInterface $request): array return [ $data, - $files ?? [] + $files ]; } diff --git a/system/src/Grav/Framework/Logger/Processors/UserProcessor.php b/system/src/Grav/Framework/Logger/Processors/UserProcessor.php new file mode 100644 index 0000000000..885b4f0a83 --- /dev/null +++ b/system/src/Grav/Framework/Logger/Processors/UserProcessor.php @@ -0,0 +1,34 @@ +exists()) { + $record['extra']['user'] = ['username' => $user->username, 'email' => $user->email]; + } + + return $record; + } +} diff --git a/system/src/Grav/Framework/Object/ObjectIndex.php b/system/src/Grav/Framework/Object/ObjectIndex.php index b7b416d0a4..50ac4271be 100644 --- a/system/src/Grav/Framework/Object/ObjectIndex.php +++ b/system/src/Grav/Framework/Object/ObjectIndex.php @@ -24,8 +24,9 @@ * order to use the class. * * @template TKey of array-key - * @template T - * @extends AbstractIndexCollection + * @template T of \Grav\Framework\Object\Interfaces\ObjectInterface + * @template C of \Grav\Framework\Collection\CollectionInterface + * @extends AbstractIndexCollection * @implements NestedObjectCollectionInterface */ abstract class ObjectIndex extends AbstractIndexCollection implements NestedObjectCollectionInterface @@ -176,7 +177,7 @@ public function unsetNestedProperty($property, $separator = null) * Create a copy from this collection by cloning all objects in the collection. * * @return static - * @return static + * @return static */ public function copy() { diff --git a/tests/phpstan/phpstan.neon b/tests/phpstan/phpstan.neon index c41ae9bfe3..12dc402a2a 100644 --- a/tests/phpstan/phpstan.neon +++ b/tests/phpstan/phpstan.neon @@ -8,7 +8,7 @@ parameters: - dist bootstrapFiles: - phpstan-bootstrap.php - excludes_analyse: + excludePaths: - */system/src/Grav/Common/Errors/Resources/layout.html.php - */system/src/Twig/DeferredExtension/DeferredNodeVisitor.php diff --git a/tests/phpstan/plugins.neon b/tests/phpstan/plugins.neon index 8ef5700f68..ae257f80e2 100644 --- a/tests/phpstan/plugins.neon +++ b/tests/phpstan/plugins.neon @@ -4,7 +4,7 @@ includes: parameters: fileExtensions: - php - excludes_analyse: + excludePaths: - %currentWorkingDirectory%/user/plugins/*/vendor/* - %currentWorkingDirectory%/user/plugins/*/tests/* - %currentWorkingDirectory%/user/plugins/gantry5/src/platforms From 58b48c2f26ef246ff67290e0d796f4472d6e58a4 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Tue, 9 Nov 2021 19:12:39 +0200 Subject: [PATCH 10/17] Do not escape ValidationException --- .../Controller/Traits/ControllerResponseTrait.php | 7 ++++++- .../Framework/RequestHandler/Middlewares/Exceptions.php | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php index 53c9cd4c28..5b4863573f 100644 --- a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php +++ b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php @@ -12,6 +12,7 @@ namespace Grav\Framework\Controller\Traits; use Grav\Common\Config\Config; +use Grav\Common\Data\ValidationException; use Grav\Common\Debugger; use Grav\Common\Grav; use Grav\Common\Utils; @@ -203,7 +204,11 @@ protected function createJsonErrorResponse(Throwable $e): ResponseInterface protected function getErrorJson(Throwable $e): array { $code = $this->getErrorCode($e instanceof RequestException ? $e->getHttpCode() : $e->getCode()); - $message = htmlspecialchars($e->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + if ($e instanceof ValidationException) { + $message = $e->getMessage(); + } else { + $message = htmlspecialchars($e->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } $response = [ 'code' => $code, 'status' => 'error', diff --git a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php index 63cfe3eade..e09f1b2575 100644 --- a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php +++ b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php @@ -11,6 +11,7 @@ namespace Grav\Framework\RequestHandler\Middlewares; +use Grav\Common\Data\ValidationException; use Grav\Common\Debugger; use Grav\Common\Grav; use Grav\Framework\Psr7\Response; @@ -40,7 +41,11 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface return $handler->handle($request); } catch (Throwable $exception) { $code = $exception->getCode(); - $message = htmlspecialchars($exception->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + if ($exception instanceof ValidationException) { + $message = $exception->getMessage(); + } else { + $message = htmlspecialchars($exception->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); + } $response = [ 'code' => $code, 'status' => 'error', From 33b473c2905fc38b458203273262ce2247aee4aa Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 11 Nov 2021 15:48:18 +0200 Subject: [PATCH 11/17] Fixed `FlexObject::getChanges()` always returning empty array --- CHANGELOG.md | 1 + system/src/Grav/Framework/Flex/FlexObject.php | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5a896fda1..ee3b8604f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses * Fixed `|t(variable)` twig filter in admin + * Fixed `FlexObject::getChanges()` always returning empty array # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Framework/Flex/FlexObject.php b/system/src/Grav/Framework/Flex/FlexObject.php index 945f5adfed..f5949ec495 100644 --- a/system/src/Grav/Framework/Flex/FlexObject.php +++ b/system/src/Grav/Framework/Flex/FlexObject.php @@ -666,8 +666,10 @@ public function update(array $data, array $files = []) } // Store the changes - $this->_original = $this->getElements(); - $this->_changes = Utils::arrayDiffMultidimensional($this->_original, $elements); + if ($this->_original === null) { + $this->_original = $elements; + } + $this->_changes = Utils::arrayDiffMultidimensional($this->_original, $this->getElements()); } if ($files && method_exists($this, 'setUpdatedMedia')) { From 2a04628459d86e4ae7bf7cacbec4e1c77f1f4856 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 11 Nov 2021 20:06:24 +0200 Subject: [PATCH 12/17] Added `FlexObject::getDiff()` to see difference to the saved object --- CHANGELOG.md | 2 + system/src/Grav/Framework/Flex/FlexObject.php | 64 +++++++++++++++---- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee3b8604f4..90544568d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ 1. [](#new) * Updated phpstan to v1.0 + * Added `FlexObject::getDiff()` to see difference to the saved object 2. [](#improved) * Use Symfony `dump` instead of PHP's `vardump` in side the `{{ vardump(x) }}` Twig vardump function * Added `route` and `request` to `onPagesInitialized` event * Improved page cloning, added method `Page::initialize()` + * Improved `FlexObject::getChanges()`: return changed lists and arrays as whole instead of just changed keys/values 3. [](#bugfix) * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses diff --git a/system/src/Grav/Framework/Flex/FlexObject.php b/system/src/Grav/Framework/Flex/FlexObject.php index f5949ec495..ac51b3461d 100644 --- a/system/src/Grav/Framework/Flex/FlexObject.php +++ b/system/src/Grav/Framework/Flex/FlexObject.php @@ -12,6 +12,7 @@ use ArrayAccess; use Exception; use Grav\Common\Data\Blueprint; +use Grav\Common\Data\Data; use Grav\Common\Debugger; use Grav\Common\Grav; use Grav\Common\Inflector; @@ -72,8 +73,6 @@ class FlexObject implements FlexObjectInterface, FlexAuthorizeInterface private $_meta; /** @var array */ protected $_original; - /** @var array */ - protected $_changes; /** @var string */ protected $storage_key; /** @var int */ @@ -454,13 +453,50 @@ public function getOriginalData(): array } /** - * Get any changes based on data sent to update + * Get diff array from the object. + * + * @return array + */ + public function getDiff(): array + { + $blueprint = $this->getBlueprint(); + + $flattenOriginal = $blueprint->flattenData($this->getOriginalData()); + $flattenElements = $blueprint->flattenData($this->getElements()); + $removedElements = array_diff_key($flattenOriginal, $flattenElements); + $diff = []; + + // Include all added or changed keys. + foreach ($flattenElements as $key => $value) { + $orig = $flattenOriginal[$key] ?? null; + if ($orig !== $value) { + $diff[$key] = ['old' => $orig, 'new' => $value]; + } + } + + // Include all removed keys. + foreach ($removedElements as $key => $value) { + $diff[$key] = ['old' => $value, 'new' => null]; + } + + return $diff; + } + + /** + * Get any changes from the object. * * @return array */ public function getChanges(): array { - return $this->_changes ?? []; + $diff = $this->getDiff(); + + $data = new Data(); + foreach ($diff as $key => $change) { + $data->set($key, $change['new']); + } + + return $data->toArray(); } /** @@ -641,14 +677,19 @@ public function prepareStorage(): array public function update(array $data, array $files = []) { if ($data) { + // Get currently stored data. + $elements = $this->getElements(); + + // Store original version of the object. + if ($this->_original === null) { + $this->_original = $elements; + } + $blueprint = $this->getBlueprint(); // Process updated data through the object filters. $this->filterElements($data); - // Get currently stored data. - $elements = $this->getElements(); - // Merge existing object to the test data to be validated. $test = $blueprint->mergeData($elements, $data); @@ -657,19 +698,14 @@ public function update(array $data, array $files = []) $data = $blueprint->filter($data, true, true); // Finally update the object. - foreach ($blueprint->flattenData($data) as $key => $value) { + $flattenData = $blueprint->flattenData($data); + foreach ($flattenData as $key => $value) { if ($value === null) { $this->unsetNestedProperty($key); } else { $this->setNestedProperty($key, $value); } } - - // Store the changes - if ($this->_original === null) { - $this->_original = $elements; - } - $this->_changes = Utils::arrayDiffMultidimensional($this->_original, $this->getElements()); } if ($files && method_exists($this, 'setUpdatedMedia')) { From d9c9f6a5eb3b6fd9bdcb93acda65854a9b5fb0f4 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Nov 2021 09:35:26 +0200 Subject: [PATCH 13/17] Fixed form validation exceptions to use `400 Bad Request` instead of `500 Internal Server Error` --- CHANGELOG.md | 1 + system/src/Grav/Common/Data/BlueprintSchema.php | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90544568d0..5babb09b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Fixed unescaped error messages in JSON error responses * Fixed `|t(variable)` twig filter in admin * Fixed `FlexObject::getChanges()` always returning empty array + * Fixed form validation exceptions to use `400 Bad Request` instead of `500 Internal Server Error` # v1.7.24 ## 10/26/2021 diff --git a/system/src/Grav/Common/Data/BlueprintSchema.php b/system/src/Grav/Common/Data/BlueprintSchema.php index 7990bec291..db5e6af7d0 100644 --- a/system/src/Grav/Common/Data/BlueprintSchema.php +++ b/system/src/Grav/Common/Data/BlueprintSchema.php @@ -83,7 +83,7 @@ public function validate(array $data, array $options = []) } if (!empty($messages)) { - throw (new ValidationException())->setMessages($messages); + throw (new ValidationException('', 400))->setMessages($messages); } } @@ -199,7 +199,7 @@ protected function validateArray(array $data, array $rules, bool $strict, bool $ /** @var Config $config */ $config = Grav::instance()['config']; if (!$config->get('system.strict_mode.blueprint_strict_compat', true)) { - throw new RuntimeException(sprintf('%s is not defined in blueprints', $key)); + throw new RuntimeException(sprintf('%s is not defined in blueprints', $key), 400); } user_error(sprintf('Having extra key %s in your data is deprecated with blueprint having \'validation: strict\'', $key), E_USER_DEPRECATED); From e6911ce24ab14514f21075dc6599a8c07282993f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Nov 2021 09:36:54 +0200 Subject: [PATCH 14/17] Improved form validation JSON responses to contain list of failed fields with their error messages --- CHANGELOG.md | 1 + .../Grav/Common/Data/ValidationException.php | 23 +++++++++++++++---- .../Traits/ControllerResponseTrait.php | 6 ++++- .../RequestHandler/Middlewares/Exceptions.php | 6 ++++- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5babb09b91..fb744b44d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Added `route` and `request` to `onPagesInitialized` event * Improved page cloning, added method `Page::initialize()` * Improved `FlexObject::getChanges()`: return changed lists and arrays as whole instead of just changed keys/values + * Improved form validation JSON responses to contain list of failed fields with their error messages 3. [](#bugfix) * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses diff --git a/system/src/Grav/Common/Data/ValidationException.php b/system/src/Grav/Common/Data/ValidationException.php index 2d94ab8160..be6a674d70 100644 --- a/system/src/Grav/Common/Data/ValidationException.php +++ b/system/src/Grav/Common/Data/ValidationException.php @@ -10,16 +10,18 @@ namespace Grav\Common\Data; use Grav\Common\Grav; +use JsonSerializable; use RuntimeException; /** * Class ValidationException * @package Grav\Common\Data */ -class ValidationException extends RuntimeException +class ValidationException extends RuntimeException implements JsonSerializable { /** @var array */ protected $messages = []; + protected $escape = true; /** * @param array $messages @@ -32,21 +34,34 @@ public function setMessages(array $messages = []) $language = Grav::instance()['language']; $this->message = $language->translate('GRAV.FORM.VALIDATION_FAIL', null, true) . ' ' . $this->message; - foreach ($messages as $variable => &$list) { + foreach ($messages as $list) { $list = array_unique($list); foreach ($list as $message) { - $this->message .= "
$message"; + $this->message .= '
' . htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8'); } } return $this; } + public function setSimpleMessage(bool $escape = true): void + { + $first = reset($this->messages); + $message = reset($first); + + $this->message = $escape ? htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8') : $message; + } + /** * @return array */ - public function getMessages() + public function getMessages(): array { return $this->messages; } + + public function jsonSerialize(): array + { + return ['validation' => $this->messages]; + } } diff --git a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php index 5b4863573f..afa08aa42e 100644 --- a/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php +++ b/system/src/Grav/Framework/Controller/Traits/ControllerResponseTrait.php @@ -19,6 +19,7 @@ use Grav\Framework\Psr7\Response; use Grav\Framework\RequestHandler\Exception\RequestException; use Grav\Framework\Route\Route; +use JsonSerializable; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\StreamInterface; @@ -209,6 +210,9 @@ protected function getErrorJson(Throwable $e): array } else { $message = htmlspecialchars($e->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); } + + $extra = $e instanceof JsonSerializable ? $e->jsonSerialize() : []; + $response = [ 'code' => $code, 'status' => 'error', @@ -216,7 +220,7 @@ protected function getErrorJson(Throwable $e): array 'error' => [ 'code' => $code, 'message' => $message - ] + ] + $extra ]; /** @var Debugger $debugger */ diff --git a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php index e09f1b2575..9eadf72e3f 100644 --- a/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php +++ b/system/src/Grav/Framework/RequestHandler/Middlewares/Exceptions.php @@ -16,6 +16,7 @@ use Grav\Common\Grav; use Grav\Framework\Psr7\Response; use JsonException; +use JsonSerializable; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\MiddlewareInterface; @@ -46,6 +47,9 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface } else { $message = htmlspecialchars($exception->getMessage(), ENT_QUOTES | ENT_HTML5, 'UTF-8'); } + + $extra = $exception instanceof JsonSerializable ? $exception->jsonSerialize() : []; + $response = [ 'code' => $code, 'status' => 'error', @@ -53,7 +57,7 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface 'error' => [ 'code' => $code, 'message' => $message, - ] + ] + $extra ]; /** @var Debugger $debugger */ From 061ebf06c68d330d3da28ce2ab7ee59805877718 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Nov 2021 11:02:24 +0200 Subject: [PATCH 15/17] Composer update --- composer.json | 7 ++-- composer.lock | 107 +++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 97 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 2067b69572..42535abb0b 100644 --- a/composer.json +++ b/composer.json @@ -20,9 +20,10 @@ "ext-dom": "*", "ext-libxml": "*", "symfony/polyfill-mbstring": "~1.20", - "symfony/polyfill-iconv": "^1.20", - "symfony/polyfill-php74": "^1.20", - "symfony/polyfill-php80": "^1.20", + "symfony/polyfill-iconv": "^1.23", + "symfony/polyfill-php74": "^1.23", + "symfony/polyfill-php80": "^1.23", + "symfony/polyfill-php81": "^1.23", "psr/simple-cache": "^1.0", "psr/http-message": "^1.0", "psr/http-server-middleware": "^1.0", diff --git a/composer.lock b/composer.lock index dbf6a60654..3b66c8a462 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "88527e29c63574c4fdb788ff8ed34245", + "content-hash": "072f00e1bf64b4ef43f7125fe80b15a7", "packages": [ { "name": "antoligy/dom-string-iterators", @@ -2988,6 +2988,85 @@ ], "time": "2021-07-28T13:41:28+00:00" }, + { + "name": "symfony/polyfill-php81", + "version": "v1.23.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "e66119f3de95efc359483f810c4c3e6436279436" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/e66119f3de95efc359483f810c4c3e6436279436", + "reference": "e66119f3de95efc359483f810c4c3e6436279436", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.23-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.23.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-21T13:25:03+00:00" + }, { "name": "symfony/process", "version": "v4.4.30", @@ -4601,16 +4680,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.0.2", + "version": "1.1.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91" + "reference": "bcea0ae85868a89d5789c75f012c93129f842934" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e9e2a501102ba0b126b2f63a7f0a3b151056fe91", - "reference": "e9e2a501102ba0b126b2f63a7f0a3b151056fe91", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/bcea0ae85868a89d5789c75f012c93129f842934", + "reference": "bcea0ae85868a89d5789c75f012c93129f842934", "shasum": "" }, "require": { @@ -4641,7 +4720,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.0.2" + "source": "https://github.com/phpstan/phpstan/tree/1.1.2" }, "funding": [ { @@ -4661,7 +4740,7 @@ "type": "tidelift" } ], - "time": "2021-11-03T16:09:51+00:00" + "time": "2021-11-09T12:41:09+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -5615,16 +5694,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.3", + "version": "4.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65" + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/d89cc98761b8cb5a1a235a6b703ae50d34080e65", - "reference": "d89cc98761b8cb5a1a235a6b703ae50d34080e65", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9", + "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9", "shasum": "" }, "require": { @@ -5673,14 +5752,14 @@ } ], "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", + "homepage": "https://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4" }, "funding": [ { @@ -5688,7 +5767,7 @@ "type": "github" } ], - "time": "2020-09-28T05:24:23+00:00" + "time": "2021-11-11T14:18:36+00:00" }, { "name": "sebastian/global-state", From 956ed013cf98825737ff20df78d6ecb7aa378c9a Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 12 Nov 2021 12:08:13 +0200 Subject: [PATCH 16/17] Improved redirects: send redirect response in JSON if the request was in JSON --- CHANGELOG.md | 1 + system/src/Grav/Common/Grav.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb744b44d6..5ea47df75f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * Improved page cloning, added method `Page::initialize()` * Improved `FlexObject::getChanges()`: return changed lists and arrays as whole instead of just changed keys/values * Improved form validation JSON responses to contain list of failed fields with their error messages + * Improved redirects: send redirect response in JSON if the request was in JSON 3. [](#bugfix) * Fixed path traversal vulnerability when using `bin/grav server` * Fixed unescaped error messages in JSON error responses diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 1169b74f67..2398c116c0 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -464,6 +464,10 @@ public function getRedirectResponse($route, $code = null): ResponseInterface } } + if ($uri->extension() === 'json') { + return new Response(200, ['Content-Type' => 'application/json'], json_encode(['code' => $code, 'redirect' => $url], JSON_THROW_ON_ERROR)); + } + return new Response($code, ['Location' => $url]); } From 88ffa163c42f75c00bd1cf187253f99760477e86 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 16 Nov 2021 10:34:46 -0700 Subject: [PATCH 17/17] prepare for release --- CHANGELOG.md | 2 +- system/defines.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ea47df75f..b0c0eb3e8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v1.7.25 -## mm/dd/2021 +## 11/16/2021 1. [](#new) * Updated phpstan to v1.0 diff --git a/system/defines.php b/system/defines.php index 633534327e..f5ccba9006 100644 --- a/system/defines.php +++ b/system/defines.php @@ -9,7 +9,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.7.24'); +define('GRAV_VERSION', '1.7.25'); define('GRAV_SCHEMA', '1.7.0_2020-11-20_1'); define('GRAV_TESTING', false);