Merge branch 'develop' of https://github.com/getgrav/grav into 2.0

# Conflicts:
#	CHANGELOG.md
#	composer.lock
#	system/src/Grav/Common/Twig/TwigExtension.php
This commit is contained in:
Matias Griese
2017-10-04 13:09:31 +03:00
19 changed files with 433 additions and 231 deletions

View File

@@ -11,6 +11,32 @@
1. [](#improved)
* Make it possible to include debug bar also into non-HTML responses
# v1.3.5
## xx/xx/2017
1. [](#improved)
* Updated `bin/grav clean` command to remove unnecessary vendor files (save some bytes)
* Added a `http_status_code` Twig function to allow setting HTTP status codes from Twig directly.
* Deter XSS attacks via URI path/uri methods (credit:newbthenewbd)
# v1.3.4
## 09/29/2017
1. [](#new)
* Added filter support for Page collections (routable/visible/type/access/etc.)
1. [](#improved)
* Implemented `Composer\CaBundle` for SSL Certs [#1241](https://github.com/getgrav/grav/issues/1241)
* Refactored the Assets sorting logic
* Improved language overrides to merge only 'extra' translations [#1514](https://github.com/getgrav/grav/issues/1514)
* Improved support for Assets with query strings [#1451](https://github.com/getgrav/grav/issues/1451)
* Twig extension cleanup
1. [](#bugfix)
* Fixed an issue where fallback was not supporting dynamic page generation
* Fixed issue with Image query string not being fully URL encoded [#1622](https://github.com/getgrav/grav/issues/1622)
* Fixed `Page::summary()` when using delimiter and multibyte UTF8 Characters [#1644](https://github.com/getgrav/grav/issues/1644)
* Fixed missing `.json` thumbnail throwing error when adding media [grav-plugin-admin#1156](https://github.com/getgrav/grav-plugin-admin/issues/1156)
* Fixed insecure session cookie initialization [#1656](https://github.com/getgrav/grav/pull/1656)
# v1.3.3
## 09/07/2017
@@ -32,7 +58,7 @@
* Updated vendor libraries
* Updated `travis.yml` to add support for PHP 7.1 as well as 7.0.21 for test suite
1. [](#bugfix)
* Fixed UTF8 2 character support in `Page::summary()` [#1554](https://github.com/getgrav/grav/issues/1554)
* Fixed UTF8 multibyte UTF8 character support in `Page::summary()` [#1554](https://github.com/getgrav/grav/issues/1554)
# v1.3.2
## 08/16/2017
@@ -43,9 +69,9 @@
* Added new `onTwigLoader()` event to enable utilization of loader methods
* Added new `Twig::addPath()` and `Twig::prependPath()` methods to wrap loader methods and support namespacing [#1604](https://github.com/getgrav/grav/issues/1604)
* Added new `array_key_exists()` Twig function wrapper
* Added a new `Collection::intersect()` method [#1605](github.com/getgrav/grav/issues/1605)
* Added a new `Collection::intersect()` method [#1605](https://github.com/getgrav/grav/issues/1605)
1. [](#bugfix)
* Allow `session.timetout` field to be set to `0` via blueprints [#1598](https://github.com/getgrav/grav/issues/1598)
* Allow `session.timeout` field to be set to `0` via blueprints [#1598](https://github.com/getgrav/grav/issues/1598)
* Fixed `Data::exists()` and `Data::raw()` functions breaking if `Data::file()` hasn't been called with non-null value
* Fixed parent theme auto-loading in child themes of Gantry 5

View File

@@ -32,13 +32,21 @@
"ext-zip": "*",
"league/climate": "^3.2",
"antoligy/dom-string-iterators": "^1.0",
"miljar/php-exif": "^0.6.3"
"miljar/php-exif": "^0.6.3",
"composer/ca-bundle": "^1.0"
},
"require-dev": {
"codeception/codeception": "^2.1",
"phpunit/php-code-coverage": "~2.0",
"fzaninotto/faker": "^1.5"
"fzaninotto/faker": "^1.5",
"victorjonsson/markdowndocs": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator"
}
],
"autoload": {
"psr-4": {
"Grav\\": "system/src/Grav"

243
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "dc8f7a8290f6716042298bd4495c6560",
"content-hash": "24c56b5fbd83e5c8173f1c38c2805b68",
"packages": [
{
"name": "antoligy/dom-string-iterators",
@@ -50,6 +50,65 @@
"description": "Composer package for DOMWordsIterator and DOMLettersIterator",
"time": "2015-11-04T17:33:14+00:00"
},
{
"name": "composer/ca-bundle",
"version": "1.0.8",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "9dd73a03951357922d8aee6cc084500de93e2343"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/9dd73a03951357922d8aee6cc084500de93e2343",
"reference": "9dd73a03951357922d8aee6cc084500de93e2343",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"ext-pcre": "*",
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5",
"psr/log": "^1.0",
"symfony/process": "^2.5 || ^3.0"
},
"suggest": {
"symfony/process": "This is necessary to reliably check whether openssl_x509_parse is vulnerable on older php versions, but can be ignored on PHP 5.5.6+"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\CaBundle\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
"keywords": [
"cabundle",
"cacert",
"certificate",
"ssl",
"tls"
],
"time": "2017-09-11T07:24:36+00:00"
},
{
"name": "doctrine/cache",
"version": "v1.6.2",
@@ -532,16 +591,16 @@
},
{
"name": "matthiasmullie/minify",
"version": "1.3.46",
"version": "1.3.52",
"source": {
"type": "git",
"url": "https://github.com/matthiasmullie/minify.git",
"reference": "1443646268465b8930c9a7f2f8ff1a51453796d1"
"reference": "134b25a63d83a80ae128aedc9a99987e064b4382"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/matthiasmullie/minify/zipball/1443646268465b8930c9a7f2f8ff1a51453796d1",
"reference": "1443646268465b8930c9a7f2f8ff1a51453796d1",
"url": "https://api.github.com/repos/matthiasmullie/minify/zipball/134b25a63d83a80ae128aedc9a99987e064b4382",
"reference": "134b25a63d83a80ae128aedc9a99987e064b4382",
"shasum": ""
},
"require": {
@@ -588,7 +647,7 @@
"minifier",
"minify"
],
"time": "2017-07-06T12:26:44+00:00"
"time": "2017-09-15T13:02:11+00:00"
},
{
"name": "matthiasmullie/path-converter",
@@ -979,66 +1038,18 @@
],
"time": "2016-10-10T12:19:37+00:00"
},
{
"name": "psr/simple-cache",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/simple-cache.git",
"reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/753fa598e8f3b9966c886fe13f370baa45ef0e24",
"reference": "753fa598e8f3b9966c886fe13f370baa45ef0e24",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\SimpleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interfaces for simple caching",
"keywords": [
"cache",
"caching",
"psr",
"psr-16",
"simple-cache"
],
"time": "2017-01-02T13:31:39+00:00"
},
{
"name": "rockettheme/toolbox",
"version": "1.3.7",
"version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/rockettheme/toolbox.git",
"reference": "670ad362eb948d14ebc589b957965cf178674a33"
"reference": "2f7c83780bbcf527e057f15efe755e10694eb2bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rockettheme/toolbox/zipball/670ad362eb948d14ebc589b957965cf178674a33",
"reference": "670ad362eb948d14ebc589b957965cf178674a33",
"url": "https://api.github.com/repos/rockettheme/toolbox/zipball/2f7c83780bbcf527e057f15efe755e10694eb2bc",
"reference": "2f7c83780bbcf527e057f15efe755e10694eb2bc",
"shasum": ""
},
"require": {
@@ -1073,7 +1084,7 @@
"php",
"rockettheme"
],
"time": "2017-08-28T20:31:35+00:00"
"time": "2017-09-23T13:39:25+00:00"
},
{
"name": "seld/cli-prompt",
@@ -1538,16 +1549,16 @@
},
{
"name": "twig/twig",
"version": "v1.34.4",
"version": "v1.35.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "f878bab48edb66ad9c6ed626bf817f60c6c096ee"
"reference": "daa657073e55b0a78cce8fdd22682fddecc6385f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/f878bab48edb66ad9c6ed626bf817f60c6c096ee",
"reference": "f878bab48edb66ad9c6ed626bf817f60c6c096ee",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/daa657073e55b0a78cce8fdd22682fddecc6385f",
"reference": "daa657073e55b0a78cce8fdd22682fddecc6385f",
"shasum": ""
},
"require": {
@@ -1561,7 +1572,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.34-dev"
"dev-master": "1.35-dev"
}
},
"autoload": {
@@ -1599,7 +1610,7 @@
"keywords": [
"templating"
],
"time": "2017-07-04T13:19:31+00:00"
"time": "2017-09-27T18:06:46+00:00"
}
],
"packages-dev": [
@@ -2096,16 +2107,16 @@
},
{
"name": "phpdocumentor/reflection-common",
"version": "1.0",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
"reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
"reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6",
"shasum": ""
},
"require": {
@@ -2146,26 +2157,26 @@
"reflection",
"static analysis"
],
"time": "2015-12-27T11:43:31+00:00"
"time": "2017-09-11T18:02:19+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "4.1.1",
"version": "3.2.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2"
"reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2d3d238c433cf69caeb4842e97a3223a116f94b2",
"reference": "2d3d238c433cf69caeb4842e97a3223a116f94b2",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/4aada1f93c72c35e22fb1383b47fee43b8f1d157",
"reference": "4aada1f93c72c35e22fb1383b47fee43b8f1d157",
"shasum": ""
},
"require": {
"php": "^7.0",
"php": ">=5.5",
"phpdocumentor/reflection-common": "^1.0@dev",
"phpdocumentor/type-resolver": "^0.4.0",
"phpdocumentor/type-resolver": "^0.3.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
@@ -2191,20 +2202,20 @@
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2017-08-30T18:51:59+00:00"
"time": "2017-08-08T06:39:58+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "0.4.0",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7"
"reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7",
"reference": "9c977708995954784726e25d0cd1dddf4e65b0f7",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/fb3933512008d8162b3cdf9e18dba9309b7c3773",
"reference": "fb3933512008d8162b3cdf9e18dba9309b7c3773",
"shasum": ""
},
"require": {
@@ -2238,7 +2249,7 @@
"email": "me@mikevanriel.com"
}
],
"time": "2017-07-14T14:27:02+00:00"
"time": "2017-06-03T08:32:36+00:00"
},
{
"name": "phpspec/prophecy",
@@ -3148,7 +3159,7 @@
},
{
"name": "symfony/browser-kit",
"version": "v3.3.8",
"version": "v3.3.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
@@ -3205,7 +3216,7 @@
},
{
"name": "symfony/css-selector",
"version": "v3.3.8",
"version": "v3.3.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -3258,16 +3269,16 @@
},
{
"name": "symfony/dom-crawler",
"version": "v3.3.8",
"version": "v3.3.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "d15dfaf71b65bf3affb80900470caf4451a8217e"
"reference": "6b511d7329b203a620f09a2288818d27dcc915ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/d15dfaf71b65bf3affb80900470caf4451a8217e",
"reference": "d15dfaf71b65bf3affb80900470caf4451a8217e",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6b511d7329b203a620f09a2288818d27dcc915ae",
"reference": "6b511d7329b203a620f09a2288818d27dcc915ae",
"shasum": ""
},
"require": {
@@ -3310,11 +3321,11 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2017-08-15T13:31:09+00:00"
"time": "2017-09-11T15:55:22+00:00"
},
{
"name": "symfony/finder",
"version": "v3.3.8",
"version": "v3.3.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
@@ -3363,7 +3374,7 @@
},
{
"name": "symfony/process",
"version": "v3.3.8",
"version": "v3.3.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
@@ -3410,6 +3421,52 @@
"homepage": "https://symfony.com",
"time": "2017-07-29T21:54:42+00:00"
},
{
"name": "victorjonsson/markdowndocs",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator.git",
"reference": "c9fa153b28a79f5da89ec32aa501be92db212aed"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/trilbymedia/PHP-Markdown-Documentation-Generator/zipball/c9fa153b28a79f5da89ec32aa501be92db212aed",
"reference": "c9fa153b28a79f5da89ec32aa501be92db212aed",
"shasum": ""
},
"require": {
"php": ">=5.5.0",
"symfony/console": ">=2.6"
},
"require-dev": {
"phpunit/phpunit": "3.7.23"
},
"bin": [
"bin/phpdoc-md"
],
"type": "library",
"autoload": {
"psr-0": {
"PHPDocsMD": "src/"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Victor Jonsson",
"email": "kontakt@victorjonsson.se"
}
],
"description": "Command line tool for generating markdown-formatted class documentation",
"homepage": "https://github.com/victorjonsson/PHP-Markdown-Documentation-Generator",
"support": {
"source": "https://github.com/trilbymedia/PHP-Markdown-Documentation-Generator/tree/master"
},
"time": "2017-09-20T13:29:22+00:00"
},
{
"name": "webmozart/assert",
"version": "1.2.0",
@@ -3463,7 +3520,9 @@
],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"stability-flags": {
"victorjonsson/markdowndocs": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": {

View File

@@ -8,7 +8,7 @@
// Some standard defines
define('GRAV', true);
define('GRAV_VERSION', '1.3.3');
define('GRAV_VERSION', '1.3.4');
//define('GRAV_TESTING', true);
define('DS', '/');

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@@ -184,7 +184,7 @@ class Assets
// Set timestamp
if (isset($config['enable_asset_timestamp']) && $config['enable_asset_timestamp'] === true) {
$this->timestamp = '?' . Grav::instance()['cache']->getKey();
$this->timestamp = Grav::instance()['cache']->getKey();
}
return $this;
@@ -285,9 +285,20 @@ class Assets
return $this;
}
$query = [];
$modified = false;
$remote = $this->isRemoteLink($asset);
if (!$remote) {
$asset_parts = parse_url($asset);
if (isset($asset_parts['query'])) {
$query[] = $asset_parts['query'];
unset($asset_parts['query']);
$asset = Uri::buildUrl($asset_parts);
}
$modified = $this->getLastModificationTime($asset);
$asset = $this->buildLocalLink($asset);
}
@@ -305,7 +316,8 @@ class Assets
'pipeline' => (bool) $pipeline,
'loading' => $loading ?: '',
'group' => $group ?: 'head',
'modified' => $modified
'modified' => $modified,
'query' => implode('&', $query),
];
// check for dynamic array and merge with defaults
@@ -508,24 +520,9 @@ class Assets
// Sort array by priorities (larger priority first)
if (Grav::instance()) {
uasort($this->css, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
uasort($this->inline_css, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
uasort($this->css, array($this, 'sortAssetsByPriorityThenOrder'));
uasort($this->inline_css, array($this, 'sortAssetsByPriorityThenOrder'));
}
$this->css = array_reverse($this->css);
$this->inline_css = array_reverse($this->inline_css);
$inlineGroup = array_key_exists('loading', $attributes) && $attributes['loading'] === 'inline';
@@ -553,7 +550,7 @@ class Assets
}
else {
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->getQuerystring($file) . '"' . $attributes . $media . ' />' . "\n";
}
}
}
@@ -573,7 +570,7 @@ class Assets
}
else {
$media = isset($file['media']) ? sprintf(' media="%s"', $file['media']) : '';
$output .= '<link href="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . $media . ' />' . "\n";
$output .= '<link href="' . $file['asset'] . $this->getQuerystring($file) . '"' . $attributes . $media . ' />' . "\n";
}
}
}
@@ -609,24 +606,8 @@ class Assets
}
// Sort array by priorities (larger priority first)
uasort($this->js, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
uasort($this->inline_js, function ($a, $b) {
if ($a['priority'] == $b['priority']) {
return $b['order'] - $a['order'];
}
return $a['priority'] - $b['priority'];
});
$this->js = array_reverse($this->js);
$this->inline_js = array_reverse($this->inline_js);
uasort($this->js, array($this, 'sortAssetsByPriorityThenOrder'));
uasort($this->inline_js, array($this, 'sortAssetsByPriorityThenOrder'));
$inlineGroup = array_key_exists('loading', $attributes) && $attributes['loading'] === 'inline';
@@ -653,7 +634,7 @@ class Assets
$inline_js .= $this->gatherLinks([$file], JS_ASSET) . "\n";
}
else {
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->getQuerystring($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
}
}
}
@@ -672,7 +653,7 @@ class Assets
$inline_js .= $this->gatherLinks([$file], JS_ASSET) . "\n";
}
else {
$output .= '<script src="' . $file['asset'] . $this->getTimestamp($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
$output .= '<script src="' . $file['asset'] . $this->getQuerystring($file) . '"' . $attributes . ' ' . $file['loading'] . '></script>' . "\n";
}
}
}
@@ -1384,22 +1365,50 @@ class Assets
*/
public function setTimestamp($value)
{
$this->timestamp = '?' . $value;
$this->timestamp = $value;
}
public function getTimestamp($asset = null)
/**
* Get the timestamp for assets
*
* @return string
*/
public function getTimestamp($include_join = true)
{
if (is_array($asset)) {
if ($asset['remote'] === false) {
if (Utils::contains($asset['asset'], '?')) {
return str_replace('?', '&', $this->timestamp);
} else {
return $this->timestamp;
}
}
} elseif (empty($asset)) {
return $this->timestamp;
if ($this->timestamp) {
$timestamp = $include_join ? '?' . $this->timestamp : $this->timestamp;
return $timestamp;
}
return;
}
/**
*
*
* @param $asset
* @return string
*/
public function getQuerystring($asset)
{
$querystring = '';
if (!empty($asset['query'])) {
if (Utils::contains($asset['asset'], '?')) {
$querystring .= '&' . $asset['query'];
} else {
$querystring .= '?' . $asset['query'];
}
}
if ($this->timestamp) {
if (Utils::contains($asset['asset'], '?') || $querystring) {
$querystring .= '&' . $this->timestamp;
} else {
$querystring .= '?' . $this->timestamp;
}
}
return $querystring;
}
/**
@@ -1416,9 +1425,13 @@ class Assets
*
* @return mixed
*/
protected function priorityCompare($a, $b)
protected function sortAssetsByPriorityThenOrder($a, $b)
{
return $a ['priority'] - $b ['priority'];
if ($a['priority'] == $b['priority']) {
return $a['order'] - $b['order'];
}
return $b['priority'] - $a['priority'];
}
}

View File

@@ -60,9 +60,9 @@ class CompiledLanguages extends CompiledBase
{
$file = CompiledYamlFile::instance($filename);
if (preg_match('|languages\.yaml$|', $filename)) {
$this->object->mergeRecursive((array)$file->content());
$this->object->mergeRecursive($file->content());
} else {
$this->object->join($name, $file->content(), '/');
$this->object->mergeRecursive([$name => $file->content()]);
}
$file->free();
}

View File

@@ -9,6 +9,7 @@
namespace Grav\Common\Config;
use Grav\Common\Data\Data;
use Grav\Common\Utils;
class Languages extends Data
{
@@ -49,6 +50,6 @@ class Languages extends Data
public function mergeRecursive(array $data)
{
$this->items = array_merge_recursive($this->items, $data);
$this->items = Utils::arrayMergeRecursiveUnique($this->items, $data);
}
}

View File

@@ -112,6 +112,16 @@ class Response
$config = Grav::instance()['config'];
$overrides = [];
// Override CA Bundle
$caPathOrFile = \Composer\CaBundle\CaBundle::getSystemCaRootBundlePath();
if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir(readlink($caPathOrFile)))) {
$overrides['curl'][CURLOPT_CAPATH] = $caPathOrFile;
$overrides['fopen']['ssl']['capath'] = $caPathOrFile;
} else {
$overrides['curl'][CURLOPT_CAINFO] = $caPathOrFile;
$overrides['fopen']['ssl']['cafile'] = $caPathOrFile;
}
// SSL Verify Peer and Proxy Setting
$settings = [
'method' => $config->get('system.gpm.method', self::$method),

View File

@@ -496,5 +496,7 @@ class Grav extends Container
Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download);
}
}
return $page;
}
}

View File

@@ -490,7 +490,7 @@ class Medium extends Data implements RenderableInterface
{
$qs = $method;
if (count($args) > 1 || (count($args) == 1 && !empty($args[0]))) {
$qs .= '=' . implode(',', array_map(function ($a) { return urlencode($a); }, $args));
$qs .= '=' . implode(',', array_map(function ($a) { return rawurlencode($a); }, $args));
}
if (!empty($qs)) {

View File

@@ -520,7 +520,7 @@ class Page
} elseif (($format === 'short') && isset($summary_size)) {
// Use mb_strimwidth to slice the string
if (mb_strwidth($content, 'utf8') > $summary_size) {
return mb_strimwidth($content, 0, $summary_size);
return mb_substr($content, 0, $summary_size);
} else {
return $content;
}
@@ -2269,7 +2269,7 @@ class Page
return false;
}
/**
* Returns the item in the current position.
*
@@ -2507,6 +2507,41 @@ class Page
}
}
// If a filter or filters are set, filter the collection...
if (isset($params['filter'])) {
foreach ((array)$params['filter'] as $type => $filter) {
switch ($type) {
case 'visible':
$collection->visible($filter);
break;
case 'non-visible':
$collection->nonVisible($filter);
break;
case 'modular':
$collection->modular($filter);
break;
case 'non-modular':
$collection->nonModular($filter);
break;
case 'routable':
$collection->routable($filter);
break;
case 'non-routable':
$collection->nonRoutable($filter);
break;
case 'type':
$collection->ofType($filter);
break;
case 'types':
$collection->ofOneOfTheseTypes($filter);
break;
case 'access':
$collection->ofOneOfTheseAccessLevels($filter);
break;
}
}
}
if (isset($params['dateRange'])) {
$start = isset($params['dateRange']['start']) ? $params['dateRange']['start'] : 0;
$end = isset($params['dateRange']['end']) ? $params['dateRange']['end'] : false;

View File

@@ -41,7 +41,7 @@ class PageServiceProvider implements ServiceProviderInterface
// some debugger override logic
if ($page->debugger() === false) {
Grav::instance()['debugger']->enabled(false);
$c['debugger']->enabled(false);
}
if ($c['config']->get('system.force_ssl')) {
@@ -86,7 +86,7 @@ class PageServiceProvider implements ServiceProviderInterface
if (!$page || !$page->routable()) {
// Try fallback URL stuff...
$c->fallbackUrl($path);
$page = $c->fallbackUrl($path);
if (!$page) {
$path = $c['locator']->findResource('system://pages/notfound.md');
@@ -94,7 +94,6 @@ class PageServiceProvider implements ServiceProviderInterface
$page->init(new \SplFileInfo($path));
$page->routable(false);
}
}
return $page;

View File

@@ -83,6 +83,8 @@ class Session extends BaseSession
$session_name .= '-admin';
}
$this->setName($session_name);
ini_set('session.cookie_secure', $secure);
ini_set('session.cookie_httponly', $httponly);
$this->start();
setcookie(session_name(), session_id(), $session_timeout ? time() + $session_timeout : 0, $session_path, $domain, $secure, $httponly);
}

View File

@@ -99,8 +99,9 @@ class TwigExtension extends \Twig_Extension
new \Twig_SimpleFilter('truncate_html', ['\Grav\Common\Utils', 'truncateHTML']),
new \Twig_SimpleFilter('json_decode', [$this, 'jsonDecodeFilter']),
new \Twig_SimpleFilter('array_unique', 'array_unique'),
new \Twig_SimpleFilter('basename', 'basenameFilter'),
new \Twig_SimpleFilter('dirname', 'dirnameFilter'),
new \Twig_SimpleFilter('basename', 'basename'),
new \Twig_SimpleFilter('dirname', 'dirname'),
new \Twig_SimpleFilter('print_r', 'print_r'),
];
}
@@ -114,17 +115,20 @@ class TwigExtension extends \Twig_Extension
return [
new \Twig_SimpleFunction('array', [$this, 'arrayFunc']),
new \Twig_SimpleFunction('array_key_value', [$this, 'arrayKeyValueFunc']),
new \Twig_SimpleFunction('array_key_exists', [$this, 'arrayKeyExistsFunc']),
new \Twig_SimpleFunction('array_key_exists', 'array_key_exists'),
new \Twig_SimpleFunction('array_unique', 'array_unique'),
new \Twig_SimpleFunction('array_intersect', [$this, 'arrayIntersectFunc']),
new \Twig_simpleFunction('authorize', [$this, 'authorize']),
new \Twig_SimpleFunction('debug', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('dump', [$this, 'dump'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('vardump', [$this, 'vardumpFunc']),
new \Twig_SimpleFunction('print_r', 'print_r'),
new \Twig_SimpleFunction('http_response_code', 'http_response_code'),
new \Twig_SimpleFunction('evaluate', [$this, 'evaluateStringFunc'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('evaluate_twig', [$this, 'evaluateTwigFunc'], ['needs_context' => true, 'needs_environment' => true]),
new \Twig_SimpleFunction('gist', [$this, 'gistFunc']),
new \Twig_SimpleFunction('nonce_field', [$this, 'nonceFieldFunc']),
new \Twig_SimpleFunction('pathinfo', [$this, 'pathinfoFunc']),
new \Twig_SimpleFunction('pathinfo', 'pathinfo'),
new \Twig_simpleFunction('random_string', [$this, 'randomStringFunc']),
new \Twig_SimpleFunction('repeat', [$this, 'repeatFunc']),
new \Twig_SimpleFunction('regex_replace', [$this, 'regexReplace']),
@@ -245,15 +249,15 @@ class TwigExtension extends \Twig_Extension
/**
* Inflector supports following notations:
*
* {{ 'person'|pluralize }} => people
* {{ 'shoes'|singularize }} => shoe
* {{ 'welcome page'|titleize }} => "Welcome Page"
* {{ 'send_email'|camelize }} => SendEmail
* {{ 'CamelCased'|underscorize }} => camel_cased
* {{ 'Something Text'|hyphenize }} => something-text
* {{ 'something_text_to_read'|humanize }} => "Something text to read"
* {{ '181'|monthize }} => 5
* {{ '10'|ordinalize }} => 10th
* `{{ 'person'|pluralize }} => people`
* `{{ 'shoes'|singularize }} => shoe`
* `{{ 'welcome page'|titleize }} => "Welcome Page"`
* `{{ 'send_email'|camelize }} => SendEmail`
* `{{ 'CamelCased'|underscorize }} => camel_cased`
* `{{ 'Something Text'|hyphenize }} => something-text`
* `{{ 'something_text_to_read'|humanize }} => "Something text to read"`
* `{{ '181'|monthize }} => 5`
* `{{ '10'|ordinalize }} => 10th`
*
* @param string $action
* @param string $data
@@ -855,19 +859,6 @@ class TwigExtension extends \Twig_Extension
}
}
/**
* Check to see if an array key exists
*
* @param string $key key of item
* @param string $current_array optional array to add to
*
* @return array
*/
public function arrayKeyExistsFunc($key, $current_array = null)
{
return array_key_exists($key, $current_array);
}
/**
* Wrapper for array_intersect() method
*
@@ -1105,33 +1096,6 @@ class TwigExtension extends \Twig_Extension
var_dump($var);
}
/**
* Simple wrapper for pathinfo()
*
* @param $var
* @return mixed
*/
public function pathinfoFunc($var)
{
return pathinfo($var);
}
/**
* Simple wrapper for basename()
*
* @param $var
* @return string
*/
public function basenameFilter($var)
{
return basename($var);
}
public function dirnameFilter($var)
{
return dirname($var);
}
/**
* Returns a nicer more readable number
*

View File

@@ -117,7 +117,9 @@ class Uri
{
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
return rawurldecode($uri);
$uri = Uri::cleanUrl($uri);
return $uri;
}
private function buildScheme()
@@ -216,7 +218,7 @@ class Uri
$this->name = $uri_bits['host'];
$this->port = isset($uri_bits['port']) ? $uri_bits['port'] : '80';
$this->uri = $uri_bits['path'];
$this->uri = Uri::cleanUrl($uri_bits['path']);
// set active language
$uri = $language->setActiveFromUri($this->uri);
@@ -349,7 +351,7 @@ class Uri
// set the new url
$this->url = $this->root . $path;
$this->path = $path;
$this->path = Uri::cleanPath($path);
$this->content_path = trim(str_replace($this->base, '', $this->path), '/');
if ($this->content_path != '') {
$this->paths = explode('/', $this->content_path);
@@ -1107,4 +1109,36 @@ class Uri
return false;
}
}
/**
* Removes extra double slashes and fixes back-slashes
*
* @param $path
* @return mixed|string
*/
public static function cleanPath($path)
{
$regex = '/(\/)\/+/';
$path = str_replace(['\\', '/ /'], '/', $path);
$path = preg_replace($regex,'$1',$path);
return $path;
}
/**
* Strips out any <script> tags and sanitizes the URL
*
* @param $url
* @return mixed|string
*/
public static function cleanUrl($url)
{
$regex = '/<script\b[^>]*>(.*?)<\/script>/';
$url = rawurldecode($url);
$url = preg_replace($regex, '', $url);
$url = filter_var($url, FILTER_SANITIZE_STRING);
return $url;
}
}

View File

@@ -28,6 +28,25 @@ class CleanCommand extends Command
protected $paths_to_remove = [
'codeception.yml',
'tests/',
'user/plugins/admin/vendor/bacon/bacon-qr-code/tests',
'user/plugins/admin/vendor/bacon/bacon-qr-code/.gitignore',
'user/plugins/admin/vendor/bacon/bacon-qr-code/.travis.yml',
'user/plugins/admin/vendor/bacon/bacon-qr-code/composer.json',
'user/plugins/admin/vendor/robthree/twofactorauth/demo',
'user/plugins/admin/vendor/robthree/twofactorauth/.vs',
'user/plugins/admin/vendor/robthree/twofactorauth/tests',
'user/plugins/admin/vendor/robthree/twofactorauth/.gitignore',
'user/plugins/admin/vendor/robthree/twofactorauth/.travis.yml',
'user/plugins/admin/vendor/robthree/twofactorauth/composer.json',
'user/plugins/admin/vendor/robthree/twofactorauth/composer.lock',
'user/plugins/admin/vendor/robthree/twofactorauth/logo.png',
'user/plugins/admin/vendor/robthree/twofactorauth/multifactorauthforeveryone.png',
'user/plugins/admin/vendor/robthree/twofactorauth/TwoFactorAuth.phpproj',
'user/plugins/admin/vendor/robthree/twofactorauth/TwoFactorAuth.sin',
'user/plugins/admin/vendor/zendframework/zendxml/tests',
'user/plugins/admin/vendor/zendframework/zendxml/.gitignore',
'user/plugins/admin/vendor/zendframework/zendxml/.travis.yml',
'user/plugins/admin/vendor/zendframework/zendxml/composer.json',
'user/plugins/email/vendor/swiftmailer/swiftmailer/.travis.yml',
'user/plugins/email/vendor/swiftmailer/swiftmailer/build.xml',
'user/plugins/email/vendor/swiftmailer/swiftmailer/composer.json',
@@ -111,9 +130,18 @@ class CleanCommand extends Command
'vendor/maximebf/debugbar/docs',
'vendor/maximebf/debugbar/tests',
'vendor/maximebf/debugbar/phpunit.xml.dist',
'vendor/miljar/php-exif/.coveralls.yml',
'vendor/miljar/php-exif/.gitignore',
'vendor/miljar/php-exif/.travis.yml',
'vendor/miljar/php-exif/composer.json',
'vendor/miljar/php-exif/composer.lock',
'vendor/miljar/php-exif/phpunit.xml.dist',
'vendor/miljar/php-exif/Resources',
'vendor/miljar/php-exif/tests',
'vendor/monolog/monolog/composer.json',
'vendor/monolog/monolog/doc',
'vendor/monolog/monolog/phpunit.xml.dist',
'vendor/monolog/monolog/.php_cs',
'vendor/monolog/monolog/tests',
'vendor/pimple/pimple/.gitignore',
'vendor/pimple/pimple/.travis.yml',
@@ -121,6 +149,8 @@ class CleanCommand extends Command
'vendor/pimple/pimple/ext',
'vendor/pimple/pimple/phpunit.xml.dist',
'vendor/pimple/pimple/src/Pimple/Tests',
'vendor/psr/container/composer.json',
'vendor/psr/container/.gitignore',
'vendor/psr/log/composer.json',
'vendor/psr/log/.gitignore',
'vendor/rockettheme/toolbox/.git',
@@ -130,6 +160,7 @@ class CleanCommand extends Command
'vendor/rockettheme/toolbox/composer.json',
'vendor/rockettheme/toolbox/phpunit.xml',
'vendor/seld/cli-prompt/composer.json',
'vendor/seld/cli-prompt/.gitignore',
'vendor/symfony/console/composer.json',
'vendor/symfony/console/phpunit.xml.dist',
'vendor/symfony/console/.gitignore',
@@ -165,6 +196,7 @@ class CleanCommand extends Command
'vendor/symfony/yaml/.git',
'vendor/symfony/yaml/Tests',
'vendor/twig/twig/.editorconfig',
'vendor/twig/twig/.php_cs.dist',
'vendor/twig/twig/.travis.yml',
'vendor/twig/twig/.gitignore',
'vendor/twig/twig/.git',

View File

@@ -43,7 +43,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
$this->assets->add('test.js');
@@ -59,7 +60,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//test addCss(). Test adding asset to a separate group
@@ -77,7 +79,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//test addCss(). Testing with remote URL
@@ -95,7 +98,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//test addCss() adding asset to a separate group, and with an alternate rel attribute
@@ -119,7 +123,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//Test CSS Groups
@@ -139,7 +144,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'footer',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//Test JS Groups
@@ -159,7 +165,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => '',
'group' => 'footer',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//Test async / defer
@@ -177,7 +184,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => 'async',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
$this->assets->reset();
@@ -194,7 +202,8 @@ class AssetsTest extends \Codeception\TestCase\Test
'pipeline' => true,
'loading' => 'defer',
'group' => 'head',
'modified' => false
'modified' => false,
'query' => ''
], reset($array));
//Test inline
@@ -412,14 +421,14 @@ class AssetsTest extends \Codeception\TestCase\Test
$this->assets->setTimestamp('foo');
$this->assets->addCSS('http://somesite.com/test.css');
$css = $this->assets->css();
$this->assertSame('<link href="http://somesite.com/test.css" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
$this->assertSame('<link href="http://somesite.com/test.css?foo" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// external CSS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addCSS('http://somesite.com/test.css?bar');
$css = $this->assets->css();
$this->assertSame('<link href="http://somesite.com/test.css?bar" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
$this->assertSame('<link href="http://somesite.com/test.css?bar&foo" type="text/css" rel="stylesheet" />' . PHP_EOL, $css);
// local JS nothing extra
$this->assets->reset();
@@ -440,14 +449,14 @@ class AssetsTest extends \Codeception\TestCase\Test
$this->assets->setTimestamp('foo');
$this->assets->addJs('http://somesite.com/test.js');
$css = $this->assets->js();
$this->assertSame('<script src="http://somesite.com/test.js" type="text/javascript" ></script>' . PHP_EOL, $css);
$this->assertSame('<script src="http://somesite.com/test.js?foo" type="text/javascript" ></script>' . PHP_EOL, $css);
// external JS already with param
$this->assets->reset();
$this->assets->setTimestamp('foo');
$this->assets->addJs('http://somesite.com/test.js?bar');
$css = $this->assets->js();
$this->assertSame('<script src="http://somesite.com/test.js?bar" type="text/javascript" ></script>' . PHP_EOL, $css);
$this->assertSame('<script src="http://somesite.com/test.js?bar&foo" type="text/javascript" ></script>' . PHP_EOL, $css);
}
public function testAddInlineCss()

View File

@@ -433,5 +433,13 @@ class UriTest extends \Codeception\TestCase\Test
$this->assertTrue(is_string($this->uri->param('nonce')));
$this->assertSame(Utils::getNonce('test-action'), $this->uri->param('nonce'));
}
public function testXSSViaUri()
{
$url = 'https://localhost/something/"><script>eval(atob("aGlzdG9yeS5wdXNoU3RhdGUoJycsJycsJy8nKTskKCdoZWFkLGJvZHknKS5odG1sKCcnKS5sb2FkKCcvJyk7JC5wb3N0KCcvYWRtaW4nLGZ1bmN0aW9uKGRhdGEpeyQucG9zdCgkKGRhdGEpLmZpbmQoJ1tpZD1hZG1pbi11c2VyLWRldGFpbHNdIGEnKS5hdHRyKCdocmVmJykseydhZG1pbi1ub25jZSc6JChkYXRhKS5maW5kKCdbZGF0YS1jbGVhci1jYWNoZV0nKS5hdHRyKCdkYXRhLWNsZWFyLWNhY2hlJykuc3BsaXQoJzonKS5wb3AoKS50cmltKCksJ2RhdGFbcGFzc3dvcmRdJzonSW0zdjFsaDR4eDByJywndGFzayc6J3NhdmUnfSl9KQ=="))</script><';
$this->uri->initializeWithURL($url)->init();
$this->assertSame('/something/&', $this->uri->path());
}
}