mirror of
https://github.com/getgrav/grav.git
synced 2025-02-20 19:56:53 +01:00
Merge branch 'release/1.7.46'
This commit is contained in:
commit
faa8ee5fe1
15
CHANGELOG.md
15
CHANGELOG.md
|
|
@ -1,7 +1,19 @@
|
|||
# v1.7.46
|
||||
## 05/15/2024
|
||||
|
||||
1. [](#improved)
|
||||
* Better handling of external protocols in `Utils::url()` such as `mailto:`, `tel:`, etc.
|
||||
* Handle `GRAV_ROOT` or `GRAV_WEBROOT` when `/` [#3667](https://github.com/getgrav/grav/pull/3667)
|
||||
1. [](#bugfix)
|
||||
* Fixes for multi-lang taxonomy when reinitializing the languages (e.g. LangSwitcher plugin)
|
||||
* Ensure the full filepath is checked for invalid filename in `MediaUploadTrait::checkFileMetadata()`
|
||||
* Fixed a bug in the `on_events` REGEX pattern of `Security::detectXss()` as it was not matching correctly.
|
||||
* Fixed an issue where `read_file()` Twig function could be used nefariously in content [#GHSA-f8v5-jmfh-pr69](https://github.com/getgrav/grav/security/advisories/GHSA-f8v5-jmfh-pr69)
|
||||
|
||||
# v1.7.45
|
||||
## 03/18/2024
|
||||
|
||||
1. [](#news)
|
||||
1. [](#new)
|
||||
* Added new Image trait for `decoding` attribute [#3796](https://github.com/getgrav/grav/pull/3796)
|
||||
1. [](#bugfix)
|
||||
* Fixed some multibyte issues in Inflector class [#732](https://github.com/getgrav/grav/issues/732)
|
||||
|
|
@ -117,6 +129,7 @@
|
|||
1. [](#improved)
|
||||
* Removed outdated `xcache` setting [#3615](https://github.com/getgrav/grav/pull/3615)
|
||||
* Updated `robots.txt` [#3625](https://github.com/getgrav/grav/pull/3625)
|
||||
* Handle the situation when GRAV_ROOT or GRAV_WEBROOT are `/` [#3625](https://github.com/getgrav/grav/pull/3667)
|
||||
1. [](#bugfix)
|
||||
* Fixed `force_ssl` redirect in case of undefined hostname [#3702](https://github.com/getgrav/grav/pull/3702)
|
||||
* Fixed an issue with duplicate identical page paths
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.7.45');
|
||||
define('GRAV_VERSION', '1.7.46');
|
||||
define('GRAV_SCHEMA', '1.7.0_2020-11-20_1');
|
||||
define('GRAV_TESTING', false);
|
||||
|
||||
|
|
@ -26,12 +26,12 @@ if (!defined('DS')) {
|
|||
// Absolute path to Grav root. This is where Grav is installed into.
|
||||
if (!defined('GRAV_ROOT')) {
|
||||
$path = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, getenv('GRAV_ROOT') ?: getcwd()), DS);
|
||||
define('GRAV_ROOT', $path);
|
||||
define('GRAV_ROOT', $path ?: DS);
|
||||
}
|
||||
// Absolute path to Grav webroot. This is the path where your site is located in.
|
||||
if (!defined('GRAV_WEBROOT')) {
|
||||
$path = rtrim(getenv('GRAV_WEBROOT') ?: GRAV_ROOT, DS);
|
||||
define('GRAV_WEBROOT', $path);
|
||||
define('GRAV_WEBROOT', $path ?: DS);
|
||||
}
|
||||
// Relative path to user folder. This path needs to be located under GRAV_WEBROOT.
|
||||
if (!defined('GRAV_USER_PATH')) {
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class Backups
|
|||
if ($locator->isStream($backup_root)) {
|
||||
$backup_root = $locator->findResource($backup_root);
|
||||
} else {
|
||||
$backup_root = rtrim(GRAV_ROOT . $backup_root, '/');
|
||||
$backup_root = rtrim(GRAV_ROOT . $backup_root, DS) ?: DS;
|
||||
}
|
||||
|
||||
if (!$backup_root || !file_exists($backup_root)) {
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ trait MediaUploadTrait
|
|||
$filepath = $folder . $filename;
|
||||
|
||||
// Check if the filename is allowed.
|
||||
if (!Utils::checkFilename($filename)) {
|
||||
if (!Utils::checkFilename($filepath)) {
|
||||
throw new RuntimeException(
|
||||
sprintf($this->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD'), $filepath, $this->translate('PLUGIN_ADMIN.BAD_FILENAME'))
|
||||
);
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ class Security
|
|||
// Set the patterns we'll test against
|
||||
$patterns = [
|
||||
// Match any attribute starting with "on" or xmlns
|
||||
'on_events' => '#(<[^>]+[[a-z\x00-\x20\"\'\/])([\s\/]on|\sxmlns)[a-z].*=>?#iUu',
|
||||
'on_events' => '#(<[^>]+[a-z\x00-\x20\"\'\/])(on[a-z]+|xmlns)\s*=[\s|\'\"].*[\s|\'\"]>#iUu',
|
||||
|
||||
// Match javascript:, livescript:, vbscript:, mocha:, feed: and data: protocols
|
||||
'invalid_protocols' => '#(' . implode('|', array_map('preg_quote', $invalid_protocols, ['#'])) . ')(:|\&\#58)\S.*?#iUu',
|
||||
|
|
@ -279,6 +279,7 @@ class Security
|
|||
'twig.getFunction',
|
||||
'core.setEscaper',
|
||||
'twig.safe_functions',
|
||||
'read_file',
|
||||
];
|
||||
$string = preg_replace('/(({{\s*|{%\s*)[^}]*?(' . implode('|', $bad_twig) . ')[^}]*?(\s*}}|\s*%}))/i', '{# $1 #}', $string);
|
||||
return $string;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
namespace Grav\Common;
|
||||
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Page\Collection;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use function is_string;
|
||||
|
|
@ -37,6 +38,8 @@ class Taxonomy
|
|||
protected $taxonomy_map;
|
||||
/** @var Grav */
|
||||
protected $grav;
|
||||
/** @var Language */
|
||||
protected $language;
|
||||
|
||||
/**
|
||||
* Constructor that resets the map
|
||||
|
|
@ -45,8 +48,9 @@ class Taxonomy
|
|||
*/
|
||||
public function __construct(Grav $grav)
|
||||
{
|
||||
$this->taxonomy_map = [];
|
||||
$this->grav = $grav;
|
||||
$this->language = $grav['language'];
|
||||
$this->taxonomy_map[$this->language->getLanguage()] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -107,7 +111,8 @@ class Taxonomy
|
|||
if (!empty($key)) {
|
||||
$taxonomy .= $key;
|
||||
}
|
||||
$this->taxonomy_map[$taxonomy][(string) $value][$page->path()] = ['slug' => $page->slug()];
|
||||
$active = $this->language->getLanguage();
|
||||
$this->taxonomy_map[$active][$taxonomy][(string) $value][$page->path()] = ['slug' => $page->slug()];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,14 +128,11 @@ class Taxonomy
|
|||
{
|
||||
$matches = [];
|
||||
$results = [];
|
||||
$active = $this->language->getLanguage();
|
||||
|
||||
foreach ((array)$taxonomies as $taxonomy => $items) {
|
||||
foreach ((array)$items as $item) {
|
||||
if (isset($this->taxonomy_map[$taxonomy][$item])) {
|
||||
$matches[] = $this->taxonomy_map[$taxonomy][$item];
|
||||
} else {
|
||||
$matches[] = [];
|
||||
}
|
||||
$matches[] = $this->taxonomy_map[$active][$taxonomy][$item] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -156,11 +158,13 @@ class Taxonomy
|
|||
*/
|
||||
public function taxonomy($var = null)
|
||||
{
|
||||
$active = $this->language->getLanguage();
|
||||
|
||||
if ($var) {
|
||||
$this->taxonomy_map = $var;
|
||||
$this->taxonomy_map[$active] = $var;
|
||||
}
|
||||
|
||||
return $this->taxonomy_map;
|
||||
return $this->taxonomy_map[$active] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -171,6 +175,7 @@ class Taxonomy
|
|||
*/
|
||||
public function getTaxonomyItemKeys($taxonomy)
|
||||
{
|
||||
return isset($this->taxonomy_map[$taxonomy]) ? array_keys($this->taxonomy_map[$taxonomy]) : [];
|
||||
$active = $this->language->getLanguage();
|
||||
return isset($this->taxonomy_map[$active][$taxonomy]) ? array_keys($this->taxonomy_map[$active][$taxonomy]) : [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ class Uri
|
|||
$uri = $language->setActiveFromUri($uri);
|
||||
|
||||
// split the URL and params (and make sure that the path isn't seen as domain)
|
||||
$bits = parse_url('http://domain.com' . $uri);
|
||||
$bits = static::parseUrl('http://domain.com' . $uri);
|
||||
|
||||
//process fragment
|
||||
if (isset($bits['fragment'])) {
|
||||
|
|
@ -265,6 +265,7 @@ class Uri
|
|||
return $this->paths;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return route to the current URI. By default route doesn't include base path.
|
||||
*
|
||||
|
|
@ -742,7 +743,7 @@ class Uri
|
|||
*/
|
||||
public static function isExternal($url)
|
||||
{
|
||||
return (0 === strpos($url, 'http://') || 0 === strpos($url, 'https://') || 0 === strpos($url, '//'));
|
||||
return (0 === strpos($url, 'http://') || 0 === strpos($url, 'https://') || 0 === strpos($url, '//') || 0 === strpos($url, 'mailto:') || 0 === strpos($url, 'tel:') || 0 === strpos($url, 'ftp://') || 0 === strpos($url, 'ftps://') || 0 === strpos($url, 'news:') || 0 === strpos($url, 'irc:') || 0 === strpos($url, 'gopher:') || 0 === strpos($url, 'nntp:') || 0 === strpos($url, 'feed:') || 0 === strpos($url, 'cvs:') || 0 === strpos($url, 'ssh:') || 0 === strpos($url, 'git:') || 0 === strpos($url, 'svn:') || 0 === strpos($url, 'hg:'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -954,9 +955,7 @@ class Uri
|
|||
$grav = Grav::instance();
|
||||
|
||||
// Remove extra slash from streams, parse_url() doesn't like it.
|
||||
if ($pos = strpos($url, ':///')) {
|
||||
$url = substr_replace($url, '://', $pos, 4);
|
||||
}
|
||||
$url = preg_replace('/([^:])(\/{2,})/', '$1/', $url);
|
||||
|
||||
$encodedUrl = preg_replace_callback(
|
||||
'%[^:/@?&=#]+%usD',
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Codeception\Util\Fixtures;
|
||||
use Grav\Common\Config\Config;
|
||||
use Grav\Common\Grav;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Utils;
|
||||
|
|
@ -16,6 +17,9 @@ class UriTest extends \Codeception\TestCase\Test
|
|||
/** @var Uri $uri */
|
||||
protected $uri;
|
||||
|
||||
/** @var Config $config */
|
||||
protected $config;
|
||||
|
||||
protected $tests = [
|
||||
'/path' => [
|
||||
'scheme' => '',
|
||||
|
|
@ -704,7 +708,7 @@ class UriTest extends \Codeception\TestCase\Test
|
|||
'route' => '/localhost',
|
||||
'paths' => ['localhost'],
|
||||
'params' => '/script%3E:',
|
||||
'url' => '//localhost',
|
||||
'url' => '/localhost',
|
||||
'environment' => 'unknown',
|
||||
'basename' => 'localhost',
|
||||
'base' => '',
|
||||
|
|
@ -859,6 +863,7 @@ class UriTest extends \Codeception\TestCase\Test
|
|||
$grav = Fixtures::get('grav');
|
||||
$this->grav = $grav();
|
||||
$this->uri = $this->grav['uri'];
|
||||
$this->config = $this->grav['config'];
|
||||
}
|
||||
|
||||
protected function _after(): void
|
||||
|
|
@ -1149,4 +1154,25 @@ class UriTest extends \Codeception\TestCase\Test
|
|||
{
|
||||
$this->runTestSet($this->tests, 'addNonce');
|
||||
}
|
||||
|
||||
public function testCustomBase(): void
|
||||
{
|
||||
$current_base = $this->config->get('system.custom_base_url');
|
||||
$this->config->set('system.custom_base_url', '/test');
|
||||
$this->uri->initializeWithURL('https://mydomain.example.com:8090/test/korteles/kodai%20something?test=true#some-fragment')->init();
|
||||
|
||||
$this->assertSame([
|
||||
"scheme" => "https",
|
||||
"host" => "mydomain.example.com",
|
||||
"port" => 8090,
|
||||
"user" => null,
|
||||
"pass" => null,
|
||||
"path" => "/korteles/kodai%20something",
|
||||
"params" => [],
|
||||
"query" => "test=true",
|
||||
"fragment" => "some-fragment",
|
||||
], $this->uri->toArray());
|
||||
|
||||
$this->config->set('system.custom_base_url', $current_base);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ class UtilsTest extends \Codeception\TestCase\Test
|
|||
self::assertSame('pop://domain.com', Utils::url('pop://domain.com'));
|
||||
self::assertSame('foo://bar/baz', Utils::url('foo://bar/baz'));
|
||||
self::assertSame('foo://bar/baz', Utils::url('foo://bar/baz', true));
|
||||
// self::assertSame('mailto:joe@domain.com', Utils::url('mailto:joe@domain.com', true)); // FIXME <-
|
||||
self::assertSame('mailto:joe@domain.com', Utils::url('mailto:joe@domain.com', true)); // FIXME <-
|
||||
}
|
||||
|
||||
public function testUrlWithRoot(): void
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user