From 492cc1d2f11eda6d139e27d23ff3d0fcc8ea7d06 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 14 Mar 2022 18:55:56 +0200 Subject: [PATCH 01/19] Added XSS check for uploaded SVG files before they get stored (in Form plugin) --- system/src/Grav/Framework/Form/Traits/FormTrait.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Framework/Form/Traits/FormTrait.php b/system/src/Grav/Framework/Form/Traits/FormTrait.php index f4be9e7aa..710d8b0cc 100644 --- a/system/src/Grav/Framework/Form/Traits/FormTrait.php +++ b/system/src/Grav/Framework/Form/Traits/FormTrait.php @@ -23,6 +23,7 @@ use Grav\Common\User\Interfaces\UserInterface; use Grav\Common\Utils; use Grav\Framework\Compat\Serializable; use Grav\Framework\ContentBlock\HtmlBlock; +use Grav\Framework\Form\FormFlashFile; use Grav\Framework\Form\Interfaces\FormFlashInterface; use Grav\Framework\Form\Interfaces\FormInterface; use Grav\Framework\Session\SessionInterface; @@ -775,13 +776,16 @@ trait FormTrait { // Handle bad filenames. $filename = $file->getClientFilename(); - if ($filename && !Utils::checkFilename($filename)) { $grav = Grav::instance(); throw new RuntimeException( sprintf($grav['language']->translate('PLUGIN_FORM.FILEUPLOAD_UNABLE_TO_UPLOAD', null, true), $filename, 'Bad filename') ); } + + if ($file instanceof FormFlashFile) { + $file->checkXss(); + } } /** From 0d19bc6e970221716a489c43614cb99c51649fa3 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Mon, 14 Mar 2022 11:34:33 -0600 Subject: [PATCH 02/19] prepare for release --- CHANGELOG.md | 4 ++-- system/defines.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cffdfcc2..5b396bd18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # v1.7.31 -## mm/dd/2022 +## 03/14/2022 1. [](#new) * Added new local Multiavatar (local generation). **This will be default in Grav 1.8** @@ -7,7 +7,7 @@ * Added XSS check for uploaded SVG files before they get stored * Fixed phpstan issues (All level 2, Framework level 5) 2. [](#improved) - * Moved Accounts out of Experimental section of System configuration + * Moved Accounts out of Experimental section of System configuration to new "Accounts" tab 3. [](#bugfix) * Fixed `'mbstring' extension is not loaded` error, use Polyfill instead [#3504](https://github.com/getgrav/grav/pull/3504) * Fixed new `Utils::pathinfo()` and `Utils::basename()` being too strict for legacy use [#3542](https://github.com/getgrav/grav/issues/3542) diff --git a/system/defines.php b/system/defines.php index 39dd69264..5f743db3f 100644 --- a/system/defines.php +++ b/system/defines.php @@ -9,7 +9,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '1.7.30'); +define('GRAV_VERSION', '1.7.31'); define('GRAV_SCHEMA', '1.7.0_2020-11-20_1'); define('GRAV_TESTING', false); From d36bc4b8a295130370f60f675da0e61ab24844d3 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 16 Mar 2022 14:28:07 -0600 Subject: [PATCH 03/19] Fix for multilang URLs in Utils::url() --- CHANGELOG.md | 6 ++++++ system/src/Grav/Common/Utils.php | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b396bd18..0e5e85af7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# v1.7.32 +## mm/dd/2022 + +1. [](#improved) + * Added multilanguage support for page routes in `Utils::url()` + # v1.7.31 ## 03/14/2022 diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 145a89356..bad8f1a07 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -78,6 +78,14 @@ abstract class Utils $grav = Grav::instance(); + // is this a page? + /** @var Pages $pages */ + $pages = $grav['pages']; + $page = $pages->dispatch($input); + if ($page) { + return $page->url($domain); + } + /** @var Uri $uri */ $uri = $grav['uri']; From 010753bdd63a8ad08e4b2d9ade5e68286f215b65 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 16 Mar 2022 14:29:05 -0600 Subject: [PATCH 04/19] typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e5e85af7..6808460cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## mm/dd/2022 1. [](#improved) - * Added multilanguage support for page routes in `Utils::url()` + * Added multi-language support for page routes in `Utils::url()` # v1.7.31 ## 03/14/2022 From c08341046bcc93ca0d3c99146002576626811729 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 17 Mar 2022 12:15:05 +0200 Subject: [PATCH 05/19] Added `|replace_last(search, replace)` filter --- CHANGELOG.md | 2 ++ .../Grav/Common/Twig/Extension/GravExtension.php | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6808460cc..b77eabea8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # v1.7.32 ## mm/dd/2022 +1. [](#new) + * Added `|replace_last(search, replace)` filter 1. [](#improved) * Added multi-language support for page routes in `Utils::url()` diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index 52e2a1841..d46b28f08 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -145,6 +145,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface new TwigFilter('yaml_encode', [$this, 'yamlEncodeFilter']), new TwigFilter('yaml_decode', [$this, 'yamlDecodeFilter']), new TwigFilter('nicecron', [$this, 'niceCronFilter']), + new TwigFilter('replace_last', [$this, 'replaceLastFilter']), // Translations new TwigFilter('t', [$this, 'translate'], ['needs_environment' => true]), @@ -547,6 +548,21 @@ class GravExtension extends AbstractExtension implements GlobalsInterface return $cron->getText('en'); } + /** + * @param $str + * @param $search + * @param $replace + * @return string|mixed + */ + public function replaceLastFilter($str, $search, $replace) + { + if (is_string($str) && ($pos = mb_strrpos($str, $search)) !== false) { + $str = substr_replace($str, $replace, $pos, mb_strlen($search)); + } + + return $str; + } + /** * Get Cron object for a crontab 'at' format * From 3e7f67f589267e61f823d19824f3ee1b9a8a38ff Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 17 Mar 2022 13:04:06 +0200 Subject: [PATCH 06/19] Set default maximum length for text fields --- CHANGELOG.md | 7 ++++++- system/src/Grav/Common/Data/Validation.php | 22 ++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b77eabea8..0a03cd199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,13 @@ 1. [](#new) * Added `|replace_last(search, replace)` filter -1. [](#improved) +2. [](#improved) * Added multi-language support for page routes in `Utils::url()` + * Set default maximum length for text fields + - `password`: 256 + - `email`: 320 + - `text`, `url`, `hidden`, `commalist`: 2048 + - `text` (multiline), `textarea`: 65536 # v1.7.31 ## 03/14/2022 diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php index 569ea512a..4b2bbf776 100644 --- a/system/src/Grav/Common/Data/Validation.php +++ b/system/src/Grav/Common/Data/Validation.php @@ -246,7 +246,9 @@ class Validation return false; } - $max = (int)($params['max'] ?? 0); + $multiline = isset($params['multiline']) && $params['multiline']; + + $max = (int)($params['max'] ?? ($multiline ? 65536 : 2048)); if ($max && $len > $max) { return false; } @@ -256,7 +258,7 @@ class Validation return false; } - if ((!isset($params['multiline']) || !$params['multiline']) && preg_match('/\R/um', $value)) { + if (!$multiline && preg_match('/\R/um', $value)) { return false; } @@ -317,6 +319,10 @@ class Validation */ public static function typeCommaList($value, array $params, array $field) { + if (!isset($params['max'])) { + $params['max'] = 2048; + } + return is_array($value) ? true : self::typeText($value, $params, $field); } @@ -379,6 +385,10 @@ class Validation */ public static function typePassword($value, array $params, array $field) { + if (!isset($params['max'])) { + $params['max'] = 256; + } + return self::typeText($value, $params, $field); } @@ -621,6 +631,10 @@ class Validation */ public static function typeEmail($value, array $params, array $field) { + if (!isset($params['max'])) { + $params['max'] = 320; + } + $values = !is_array($value) ? explode(',', preg_replace('/\s+/', '', $value)) : $value; foreach ($values as $val) { @@ -642,6 +656,10 @@ class Validation */ public static function typeUrl($value, array $params, array $field) { + if (!isset($params['max'])) { + $params['max'] = 2048; + } + return self::typeText($value, $params, $field) && filter_var($value, FILTER_VALIDATE_URL); } From 35d4d00429e61e9c03d4e857120138cfc0546201 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Thu, 17 Mar 2022 16:55:34 +0200 Subject: [PATCH 07/19] Better fix for multilang URLs in Utils::url() --- system/src/Grav/Common/Utils.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index bad8f1a07..30889e299 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -81,8 +81,8 @@ abstract class Utils // is this a page? /** @var Pages $pages */ $pages = $grav['pages']; - $page = $pages->dispatch($input); - if ($page) { + $page = $pages->find($input, true); + if ($page && $page->routable()) { return $page->url($domain); } From aa1e1bc0adfc286f5b9333c8aa1825c7e3212f5f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 18 Mar 2022 20:38:33 +0200 Subject: [PATCH 08/19] Optimization for Utils::url() --- system/src/Grav/Common/Utils.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 30889e299..6a4e89fbe 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -78,19 +78,12 @@ abstract class Utils $grav = Grav::instance(); - // is this a page? - /** @var Pages $pages */ - $pages = $grav['pages']; - $page = $pages->find($input, true); - if ($page && $page->routable()) { - return $page->url($domain); - } - /** @var Uri $uri */ $uri = $grav['uri']; $resource = false; if (static::contains((string)$input, '://')) { + // Url contains a scheme (https:// , user:// etc). /** @var UniformResourceLocator $locator */ $locator = $grav['locator']; @@ -142,6 +135,16 @@ abstract class Utils $resource = $locator->findResource($input, false); } } else { + // Just a path. + /** @var Pages $pages */ + $pages = $grav['pages']; + + // Is this a page? + $page = $pages->find($input, true); + if ($page && $page->routable()) { + return $page->url($domain); + } + $root = preg_quote($uri->rootUrl(), '#'); $pattern = '#(' . $root . '$|' . $root . '/)#'; if (!empty($root) && preg_match($pattern, $input, $matches)) { From 4376c8ce5793d7391f38bd3d48bb660be928e7be Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Fri, 18 Mar 2022 20:39:10 +0200 Subject: [PATCH 09/19] Better multi-byte support for replace_last() filter --- system/src/Grav/Common/Twig/Extension/GravExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index d46b28f08..62621a2a1 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -557,7 +557,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface public function replaceLastFilter($str, $search, $replace) { if (is_string($str) && ($pos = mb_strrpos($str, $search)) !== false) { - $str = substr_replace($str, $replace, $pos, mb_strlen($search)); + $str = mb_substr($str, 0, $pos) . $replace . mb_substr($str, $pos + mb_strlen($search)); } return $str; From 82015d4ae7b00c543ecca52b19ffbc7fa1b4d96e Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 18 Mar 2022 13:15:37 -0600 Subject: [PATCH 10/19] gzip enabled breaking in close() --- system/src/Grav/Common/Grav.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index b9b44a4df..8c5f48612 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -351,8 +351,9 @@ class Grav extends Container */ public function close(ResponseInterface $response): void { + $gzip_enabled = (int) Grav::instance()['config']->get('system.cache.gzip'); // Make sure nothing extra gets written to the response. - while (ob_get_level()) { + while (ob_get_level() > 2 + $gzip_enabled) { ob_end_clean(); } From d82851af1038be012e6a9e1c8ca3d0f96301e3f8 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Fri, 18 Mar 2022 13:18:54 -0600 Subject: [PATCH 11/19] changelog updated --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a03cd199..c05689659 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ - `email`: 320 - `text`, `url`, `hidden`, `commalist`: 2048 - `text` (multiline), `textarea`: 65536 +3. [](#bugfix) + * Fixed issue with `system.cache.gzip: true` resulted in admin "Fetch Failed" for PHP 8.0+ # v1.7.31 ## 03/14/2022 From ae55b4794ffd233d4f2cd4b36a29e48d2724b244 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 20 Mar 2022 18:22:12 -0600 Subject: [PATCH 12/19] Fix for multi-lang issues with Security report --- CHANGELOG.md | 1 + system/src/Grav/Common/Security.php | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c05689659..4f0e1115f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - `text` (multiline), `textarea`: 65536 3. [](#bugfix) * Fixed issue with `system.cache.gzip: true` resulted in admin "Fetch Failed" for PHP 8.0+ + * Fix for multi-lang issues with Security Report # v1.7.31 ## 03/14/2022 diff --git a/system/src/Grav/Common/Security.php b/system/src/Grav/Common/Security.php index 779e61918..11153a625 100644 --- a/system/src/Grav/Common/Security.php +++ b/system/src/Grav/Common/Security.php @@ -97,7 +97,7 @@ class Security */ public static function detectXssFromPages(Pages $pages, $route = true, callable $status = null) { - $routes = $pages->routes(); + $routes = $pages->getList(null, 0, true); // Remove duplicate for homepage unset($routes['/']); @@ -110,26 +110,23 @@ class Security 'steps' => count($routes), ]); - foreach ($routes as $path) { + foreach (array_keys($routes) as $route) { $status && $status([ 'type' => 'progress', ]); try { - $page = $pages->get($path); + $page = $pages->find($route); + if ($page->exists()) { + // call the content to load/cache it + $header = (array) $page->header(); + $content = $page->value('content'); - // call the content to load/cache it - $header = (array) $page->header(); - $content = $page->value('content'); + $data = ['header' => $header, 'content' => $content]; + $results = static::detectXssFromArray($data); - $data = ['header' => $header, 'content' => $content]; - $results = static::detectXssFromArray($data); - - if (!empty($results)) { - if ($route) { - $list[$page->route()] = $results; - } else { - $list[$page->filePathClean()] = $results; + if (!empty($results)) { + $list[$page->rawRoute()] = $results; } } } catch (Exception $e) { From 57d6be0f78c7d7fa0b2aa690cee8d3a4e43956c8 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Sun, 20 Mar 2022 19:02:36 -0600 Subject: [PATCH 13/19] Expose parse_url via parseurl() Twig function --- CHANGELOG.md | 1 + system/src/Grav/Common/Twig/Extension/GravExtension.php | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f0e1115f..5d0116053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ 1. [](#new) * Added `|replace_last(search, replace)` filter + * Added `urlparse` Twig function to expose PHP's `url_parse` function 2. [](#improved) * Added multi-language support for page routes in `Utils::url()` * Set default maximum length for text fields diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index 62621a2a1..399c08995 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -195,6 +195,7 @@ class GravExtension extends AbstractExtension implements GlobalsInterface new TwigFunction('gist', [$this, 'gistFunc']), new TwigFunction('nonce_field', [$this, 'nonceFieldFunc']), new TwigFunction('pathinfo', 'pathinfo'), + new TwigFunction('parseurl', 'parse_url'), new TwigFunction('random_string', [$this, 'randomStringFunc']), new TwigFunction('repeat', [$this, 'repeatFunc']), new TwigFunction('regex_replace', [$this, 'regexReplace']), From 4f7dad2872ae2c7afc6df4bf8a4bb8c6fba9e3ca Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Mon, 21 Mar 2022 12:21:12 +0200 Subject: [PATCH 14/19] Changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d0116053..2a3590c4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 1. [](#new) * Added `|replace_last(search, replace)` filter - * Added `urlparse` Twig function to expose PHP's `url_parse` function + * Added `parseurl` Twig function to expose PHP's `parse_url` function 2. [](#improved) * Added multi-language support for page routes in `Utils::url()` * Set default maximum length for text fields From 62d9db76500bcd0fc85d917a7bfbcaaad4c033a5 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Tue, 22 Mar 2022 17:30:55 -0600 Subject: [PATCH 15/19] gzip fixes for downloading --- system/src/Grav/Common/Utils.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 6a4e89fbe..5d0169c8c 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -676,8 +676,10 @@ abstract class Utils $mimetype = $options['mime'] ?? static::getMimeByExtension($file_parts['extension']); $size = filesize($file); // File size + $gzip_enabled = (int) Grav::instance()['config']->get('system.cache.gzip'); + // clean all buffers - while (ob_get_level()) { + while (ob_get_level() > 2 + $gzip_enabled) { ob_end_clean(); } From c9271c80a7108ba186d56ee887f062d8d3cd12e3 Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 23 Mar 2022 10:49:19 +0200 Subject: [PATCH 16/19] Create method `cleanOutputBuffers()` and use it --- system/src/Grav/Common/Grav.php | 27 +++++++++++++++++++++------ system/src/Grav/Common/Utils.php | 15 ++++++--------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 8c5f48612..68a0bf3cf 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -341,6 +341,25 @@ class Grav extends Container } } + /** + * Clean any output buffers. Useful when exiting from the application. + * + * Please use $grav->close() and $grav->redirect() instead of calling this one! + * + * @return void + */ + public function cleanOutputBuffers(): void + { + /** @var Config $config */ + $config = $this['config']; + $gzip_enabled = (int) $config->get('system.cache.gzip'); + + // Make sure nothing extra gets written to the response. + while (ob_get_level() > 2 + $gzip_enabled) { + ob_end_clean(); + } + } + /** * Terminates Grav request with a response. * @@ -351,11 +370,7 @@ class Grav extends Container */ public function close(ResponseInterface $response): void { - $gzip_enabled = (int) Grav::instance()['config']->get('system.cache.gzip'); - // Make sure nothing extra gets written to the response. - while (ob_get_level() > 2 + $gzip_enabled) { - ob_end_clean(); - } + $this->cleanOutputBuffers(); // Close the session. if (isset($this['session'])) { @@ -401,7 +416,7 @@ class Grav extends Container /** * @param ResponseInterface $response * @return never-return - * @deprecated 1.7 Do not use + * @deprecated 1.7 Use $grav->close() instead. */ public function exit(ResponseInterface $response): void { diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 5d0169c8c..55e7f1dec 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -668,20 +668,17 @@ abstract class Utils */ public static function download($file, $force_download = true, $sec = 0, $bytes = 1024, array $options = []) { + $grav = Grav::instance(); + if (file_exists($file)) { // fire download event - Grav::instance()->fireEvent('onBeforeDownload', new Event(['file' => $file, 'options' => &$options])); + $grav->fireEvent('onBeforeDownload', new Event(['file' => $file, 'options' => &$options])); $file_parts = static::pathinfo($file); $mimetype = $options['mime'] ?? static::getMimeByExtension($file_parts['extension']); $size = filesize($file); // File size - $gzip_enabled = (int) Grav::instance()['config']->get('system.cache.gzip'); - - // clean all buffers - while (ob_get_level() > 2 + $gzip_enabled) { - ob_end_clean(); - } + $grav->cleanOutputBuffers(); // required for IE, otherwise Content-Disposition may be ignored if (ini_get('zlib.output_compression')) { @@ -716,8 +713,8 @@ abstract class Utils $new_length = $size; header('Content-Length: ' . $size); - if (Grav::instance()['config']->get('system.cache.enabled')) { - $expires = $options['expires'] ?? Grav::instance()['config']->get('system.pages.expires'); + if ($grav['config']->get('system.cache.enabled')) { + $expires = $options['expires'] ?? $grav['config']->get('system.pages.expires'); if ($expires > 0) { $expires_date = gmdate('D, d M Y H:i:s T', time() + $expires); header('Cache-Control: max-age=' . $expires); From 8f0443a73ded13117efd8ec029046044b5867dfe Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 23 Mar 2022 13:05:54 +0200 Subject: [PATCH 17/19] Fixed phpstan issues, composer update --- composer.lock | 95 +++++++++---------- .../Common/Flex/Types/Pages/PageObject.php | 1 + .../Common/Twig/Extension/GravExtension.php | 6 +- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/composer.lock b/composer.lock index d0dc8dfd3..2a9fd9e37 100644 --- a/composer.lock +++ b/composer.lock @@ -730,16 +730,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.8.3", + "version": "1.8.5", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85" + "reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", - "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/337e3ad8e5716c15f9657bd214d16cc5e69df268", + "reference": "337e3ad8e5716c15f9657bd214d16cc5e69df268", "shasum": "" }, "require": { @@ -820,7 +820,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.8.3" + "source": "https://github.com/guzzle/psr7/tree/1.8.5" }, "funding": [ { @@ -836,7 +836,7 @@ "type": "tidelift" } ], - "time": "2021-10-05T13:56:00+00:00" + "time": "2022-03-20T21:51:18+00:00" }, { "name": "itsgoingd/clockwork", @@ -1230,16 +1230,16 @@ }, { "name": "monolog/monolog", - "version": "1.26.1", + "version": "1.27.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5" + "reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/c6b00f05152ae2c9b04a448f99c7590beb6042f5", - "reference": "c6b00f05152ae2c9b04a448f99c7590beb6042f5", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/52ebd235c1f7e0d5e1b16464b695a28335f8e44a", + "reference": "52ebd235c1f7e0d5e1b16464b695a28335f8e44a", "shasum": "" }, "require": { @@ -1300,7 +1300,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/1.26.1" + "source": "https://github.com/Seldaek/monolog/tree/1.27.0" }, "funding": [ { @@ -1312,7 +1312,7 @@ "type": "tidelift" } ], - "time": "2021-05-28T08:32:12+00:00" + "time": "2022-03-13T20:29:46+00:00" }, { "name": "multiavatar/multiavatar-php", @@ -3491,16 +3491,16 @@ }, { "name": "codeception/codeception", - "version": "4.1.30", + "version": "4.1.31", "source": { "type": "git", "url": "https://github.com/Codeception/Codeception.git", - "reference": "a035d77d070fa57fad438e07a65447aeca248c45" + "reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Codeception/Codeception/zipball/a035d77d070fa57fad438e07a65447aeca248c45", - "reference": "a035d77d070fa57fad438e07a65447aeca248c45", + "url": "https://api.github.com/repos/Codeception/Codeception/zipball/15524571ae0686a7facc2eb1f40f600e5bbce9e5", + "reference": "15524571ae0686a7facc2eb1f40f600e5bbce9e5", "shasum": "" }, "require": { @@ -3577,7 +3577,7 @@ ], "support": { "issues": "https://github.com/Codeception/Codeception/issues", - "source": "https://github.com/Codeception/Codeception/tree/4.1.30" + "source": "https://github.com/Codeception/Codeception/tree/4.1.31" }, "funding": [ { @@ -3585,7 +3585,7 @@ "type": "open_collective" } ], - "time": "2022-03-05T18:12:30+00:00" + "time": "2022-03-13T17:07:08+00:00" }, { "name": "codeception/lib-asserts", @@ -4025,16 +4025,16 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.4.1", + "version": "7.4.2", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79" + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ee0a041b1760e6a53d2a39c8c34115adc2af2c79", - "reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/ac1ec1cd9b5624694c3a40be801d94137afb12b4", + "reference": "ac1ec1cd9b5624694c3a40be801d94137afb12b4", "shasum": "" }, "require": { @@ -4129,7 +4129,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.4.1" + "source": "https://github.com/guzzle/guzzle/tree/7.4.2" }, "funding": [ { @@ -4145,7 +4145,7 @@ "type": "tidelift" } ], - "time": "2021-12-06T18:43:05+00:00" + "time": "2022-03-20T14:16:28+00:00" }, { "name": "guzzlehttp/promises", @@ -4686,16 +4686,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.4.8", + "version": "1.4.10", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "2a6d6704b17c4db6190cc3104056c0aad740cb15" + "reference": "898c479c39caa727bedf4311dd294a8f4e250e72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2a6d6704b17c4db6190cc3104056c0aad740cb15", - "reference": "2a6d6704b17c4db6190cc3104056c0aad740cb15", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/898c479c39caa727bedf4311dd294a8f4e250e72", + "reference": "898c479c39caa727bedf4311dd294a8f4e250e72", "shasum": "" }, "require": { @@ -4709,11 +4709,6 @@ "phpstan.phar" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { "files": [ "bootstrap.php" @@ -4726,7 +4721,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.4.8" + "source": "https://github.com/phpstan/phpstan/tree/1.4.10" }, "funding": [ { @@ -4746,7 +4741,7 @@ "type": "tidelift" } ], - "time": "2022-03-04T13:03:56+00:00" + "time": "2022-03-14T10:25:45+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -5118,16 +5113,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.18", + "version": "9.5.19", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1b5856028273bfd855e60a887278857d872ec67a" + "reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1b5856028273bfd855e60a887278857d872ec67a", - "reference": "1b5856028273bfd855e60a887278857d872ec67a", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/35ea4b7f3acabb26f4bb640f8c30866c401da807", + "reference": "35ea4b7f3acabb26f4bb640f8c30866c401da807", "shasum": "" }, "require": { @@ -5157,7 +5152,7 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.4", + "sebastian/type": "^3.0", "sebastian/version": "^3.0.2" }, "require-dev": { @@ -5205,7 +5200,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.18" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.19" }, "funding": [ { @@ -5217,7 +5212,7 @@ "type": "github" } ], - "time": "2022-03-08T06:52:28+00:00" + "time": "2022-03-15T09:57:31+00:00" }, { "name": "psr/http-client", @@ -6128,28 +6123,28 @@ }, { "name": "sebastian/type", - "version": "2.3.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914" + "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b8cd8a1c753c90bc1a0f5372170e3e489136f914", - "reference": "b8cd8a1c753c90bc1a0f5372170e3e489136f914", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", + "reference": "b233b84bc4465aff7b57cf1c4bc75c86d00d6dad", "shasum": "" }, "require": { "php": ">=7.3" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -6172,7 +6167,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/2.3.4" + "source": "https://github.com/sebastianbergmann/type/tree/3.0.0" }, "funding": [ { @@ -6180,7 +6175,7 @@ "type": "github" } ], - "time": "2021-06-15T12:49:02+00:00" + "time": "2022-03-15T09:54:48+00:00" }, { "name": "sebastian/version", diff --git a/system/src/Grav/Common/Flex/Types/Pages/PageObject.php b/system/src/Grav/Common/Flex/Types/Pages/PageObject.php index a05f0eb42..ebf3c2712 100644 --- a/system/src/Grav/Common/Flex/Types/Pages/PageObject.php +++ b/system/src/Grav/Common/Flex/Types/Pages/PageObject.php @@ -242,6 +242,7 @@ class PageObject extends FlexPageObject { /** @var PageCollection $siblings */ $siblings = $variables['siblings']; + /** @var PageObject $sibling */ foreach ($siblings as $sibling) { $sibling->save(false); } diff --git a/system/src/Grav/Common/Twig/Extension/GravExtension.php b/system/src/Grav/Common/Twig/Extension/GravExtension.php index 399c08995..a2a76b317 100644 --- a/system/src/Grav/Common/Twig/Extension/GravExtension.php +++ b/system/src/Grav/Common/Twig/Extension/GravExtension.php @@ -550,9 +550,9 @@ class GravExtension extends AbstractExtension implements GlobalsInterface } /** - * @param $str - * @param $search - * @param $replace + * @param string|mixed $str + * @param string $search + * @param string $replace * @return string|mixed */ public function replaceLastFilter($str, $search, $replace) From c9c23c6c4f77d0628126e2e839f477794cb8a59f Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 23 Mar 2022 15:47:45 +0200 Subject: [PATCH 18/19] Better fix for `system.cache.gzip: true` --- CHANGELOG.md | 2 +- .../src/Grav/Common/Errors/SystemFacade.php | 21 +++++++++++++++++++ system/src/Grav/Common/Grav.php | 8 +++---- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a3590c4e..165516638 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - `text`, `url`, `hidden`, `commalist`: 2048 - `text` (multiline), `textarea`: 65536 3. [](#bugfix) - * Fixed issue with `system.cache.gzip: true` resulted in admin "Fetch Failed" for PHP 8.0+ + * Fixed issue with `system.cache.gzip: true` resulted in admin "Fetch Failed" for PHP 8.0.17 and PHP 8.1.4 [PHP bug #8218](https://github.com/php/php-src/issues/8218). * Fix for multi-lang issues with Security Report # v1.7.31 diff --git a/system/src/Grav/Common/Errors/SystemFacade.php b/system/src/Grav/Common/Errors/SystemFacade.php index edf2b5338..e13b0f6e7 100644 --- a/system/src/Grav/Common/Errors/SystemFacade.php +++ b/system/src/Grav/Common/Errors/SystemFacade.php @@ -43,4 +43,25 @@ class SystemFacade extends \Whoops\Util\SystemFacade $handler(); } } + + + /** + * @param int $httpCode + * + * @return int + */ + public function setHttpResponseCode($httpCode) + { + if (!headers_sent()) { + // Ensure that no 'location' header is present as otherwise this + // will override the HTTP code being set here, and mask the + // expected error page. + header_remove('location'); + + // Work around PHP bug #8218 (8.0.17 & 8.1.4). + header_remove('Content-Encoding'); + } + + return http_response_code($httpCode); + } } diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 68a0bf3cf..7e3dcaff8 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -350,14 +350,12 @@ class Grav extends Container */ public function cleanOutputBuffers(): void { - /** @var Config $config */ - $config = $this['config']; - $gzip_enabled = (int) $config->get('system.cache.gzip'); - // Make sure nothing extra gets written to the response. - while (ob_get_level() > 2 + $gzip_enabled) { + while (ob_get_level()) { ob_end_clean(); } + // Work around PHP bug #8218 (8.0.17 & 8.1.4). + header_remove('Content-Encoding'); } /** From 236c38e65ddb7c487cf4d9f4b43a045c1c05d18e Mon Sep 17 00:00:00 2001 From: Matias Griese Date: Wed, 23 Mar 2022 15:49:12 +0200 Subject: [PATCH 19/19] Changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 165516638..1bf0b6791 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - `text`, `url`, `hidden`, `commalist`: 2048 - `text` (multiline), `textarea`: 65536 3. [](#bugfix) - * Fixed issue with `system.cache.gzip: true` resulted in admin "Fetch Failed" for PHP 8.0.17 and PHP 8.1.4 [PHP bug #8218](https://github.com/php/php-src/issues/8218). + * Fixed issue with `system.cache.gzip: true` resulted in "Fetch Failed" for PHP 8.0.17 and PHP 8.1.4 [PHP issue #8218](https://github.com/php/php-src/issues/8218). * Fix for multi-lang issues with Security Report # v1.7.31