corrections de problèmes de liens inter articles et de display du about
This commit is contained in:
parent
97231dd6bf
commit
7c640a7a14
|
@ -1,79 +0,0 @@
|
|||
name: Release Builds
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
permissions:
|
||||
contents: write # for release creation (svenstaro/upload-release-action)
|
||||
|
||||
if: "!github.event.release.prerelease"
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Extract Tag
|
||||
run: echo "PACKAGE_VERSION=${{ github.ref }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: 7.3
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GLOBAL_TOKEN }}
|
||||
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
sudo apt-get -y update -qq < /dev/null > /dev/null
|
||||
sudo apt-get -y install -qq git zip < /dev/null > /dev/null
|
||||
|
||||
- name: Retrieval of Builder Scripts
|
||||
run: |
|
||||
# Real Grav URL
|
||||
curl --silent -H "Authorization: token ${{ secrets.GLOBAL_TOKEN }}" -H "Accept: application/vnd.github.v3.raw" ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
|
||||
|
||||
# Development Local URL
|
||||
# curl ${{ secrets.BUILD_SCRIPT_URL }} --output build-grav.sh
|
||||
|
||||
- name: Grav Builder
|
||||
run: |
|
||||
bash ./build-grav.sh
|
||||
|
||||
- name: Upload packages to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ env.PACKAGE_VERSION }}
|
||||
file: ./grav-dist/*.zip
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
|
||||
slack:
|
||||
permissions:
|
||||
actions: read # to list jobs for workflow run (technote-space/workflow-conclusion-action)
|
||||
|
||||
name: Slack
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- uses: technote-space/workflow-conclusion-action@v2
|
||||
- uses: 8398a7/action-slack@v3
|
||||
with:
|
||||
status: failure
|
||||
fields: repo,message,author,action
|
||||
icon_emoji: ':octocat:'
|
||||
author_name: 'Github Action Build'
|
||||
text: '🚚 Automated Build Failure'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GLOBAL_TOKEN }}
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
if: env.WORKFLOW_CONCLUSION == 'failure'
|
|
@ -1,76 +0,0 @@
|
|||
name: PHP Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
|
||||
unit-tests:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
php: [8.3, 8.2, 8.1, 8.0, 7.4, 7.3]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: opcache, gd
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
env:
|
||||
COMPOSER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# - name: Update composer
|
||||
# run: composer update
|
||||
#
|
||||
# - name: Validate composer.json and composer.lock
|
||||
# run: composer validate
|
||||
|
||||
- name: Get composer cache directory
|
||||
id: composer-cache
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer install --prefer-dist --no-progress
|
||||
|
||||
- name: Run test suite
|
||||
run: vendor/bin/codecept run
|
||||
|
||||
# slack:
|
||||
# name: Slack
|
||||
# needs: unit-tests
|
||||
# runs-on: ubuntu-latest
|
||||
# if: always()
|
||||
# steps:
|
||||
# - uses: technote-space/workflow-conclusion-action@v2
|
||||
# - uses: 8398a7/action-slack@v3
|
||||
# with:
|
||||
# status: failure
|
||||
# fields: repo,message,author,action
|
||||
# icon_emoji: ':octocat:'
|
||||
# author_name: 'Github Action Tests'
|
||||
# text: '💥 Automated Test Failure'
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||||
# if: env.WORKFLOW_CONCLUSION == 'failure'
|
|
@ -1,48 +0,0 @@
|
|||
name: Trigger Skeletons Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Which Grav release to use'
|
||||
required: true
|
||||
default: 'latest'
|
||||
admin:
|
||||
description: 'Create also a package with Admin'
|
||||
required: true
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
WORKFLOW: "build-skeleton.yml"
|
||||
AUTH: ":${{secrets.GLOBAL_TOKEN}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Make it rain ☔️
|
||||
run: |
|
||||
SKELETONS=`curl -s "${{secrets.SKELETONS_JSON_LIST}}"`
|
||||
echo "$SKELETONS" | jq -cr '.[]' | while read SKELETON; do
|
||||
KEY=$(echo "$SKELETON" | jq -cr 'keys[0]')
|
||||
VERSION=$(echo "$SKELETON" | jq -cr '.[]')
|
||||
URL="https://api.github.com/repos/${KEY}/actions/workflows/${WORKFLOW}/dispatches"
|
||||
|
||||
curl -X POST \
|
||||
-u "${AUTH}" \
|
||||
-H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-sS \
|
||||
${URL} \
|
||||
--data '{ "ref": "develop",
|
||||
"inputs": {
|
||||
"tag": "'"$VERSION"'",
|
||||
"version": "'"$INPUT_VERSION"'",
|
||||
"admin": "'"$INPUT_ADMIN"'"
|
||||
}
|
||||
}' > /dev/null
|
||||
echo "Dispatched Worfklow for ${KEY}@$VERSION"
|
||||
done
|
27
CHANGELOG.md
27
CHANGELOG.md
|
@ -1,3 +1,29 @@
|
|||
# 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. [](#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)
|
||||
* Fallback to page modified date if Page date provided is invalid and can't be parsed [getgrav/grav-plugin-admin#2394](https://github.com/getgrav/grav-plugin-admin/issues/2394)
|
||||
* Fixed a path traversal vulnerability with file uploads [#GHSA-m7hx-hw6h-mqmc](https://github.com/getgrav/grav/security/advisories/GHSA-m7hx-hw6h-mqmc)
|
||||
* Fixed a security issue with insecure Twig functions be processed [#GHSA-2m7x-c7px-hp58](https://github.com/getgrav/grav/security/advisories/GHSA-2m7x-c7px-hp58) [#GHSA-r6vw-8v8r-pmp4](https://github.com/getgrav/grav/security/advisories/GHSA-r6vw-8v8r-pmp4) [#GHSA-qfv4-q44r-g7rv](https://github.com/getgrav/grav/security/advisories/GHSA-qfv4-q44r-g7rv) [#GHSA-c9gp-64c4-2rrh](https://github.com/getgrav/grav/security/advisories/GHSA-c9gp-64c4-2rrh)
|
||||
1. [](#improved)
|
||||
* Updated composer packages
|
||||
* Updated `bin/composer.phar` to latest `2.7.2`
|
||||
|
||||
# v1.7.44
|
||||
## 01/05/2024
|
||||
|
||||
|
@ -103,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
|
||||
|
|
17
SECURITY.md
17
SECURITY.md
|
@ -7,22 +7,31 @@ We are focusing our security updates on the following versions
|
|||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.7.x | :white_check_mark: |
|
||||
| 1.6.x | :warning: |
|
||||
| 1.6.x | :x: |
|
||||
| < 1.6 | :x: |
|
||||
|
||||
## :pushpin: Note on Security Severity
|
||||
|
||||
> NOTE: Please use the following guidlines when selecting a **Severity**. Submitted advisories that are marked **High** or **Critical** that don't meet the guidelines below will be cliosed.
|
||||
|
||||
* **CRITICAL** - no account required, can modify content, or run malicious code or nefarious activity without any access.
|
||||
* **HIGH** - publisher level account able to run malicious code or nefarious activity, or other high level security things.
|
||||
* **MODERATE** - admin level account able to run malicious code or do nefarious things. other moderate security things.
|
||||
* **LOW** - super admin level account able to run malicious code or do nefarious things. other minor security things.
|
||||
|
||||
## :warning: Versions
|
||||
|
||||
Versions with :warning: will be supported for security issues, however you won't be able to update to them, you will need to manually update through the [`direct-install` command](https://learn.getgrav.org/17/admin-panel/tools).
|
||||
|
||||
If you cannot update to the latest stable version available because, for example, your server does not meet the minimum PHP requirements, you can manually install a previous version by downloading the package from our Releases directory (https://github.com/getgrav/grav/releases).
|
||||
|
||||
## Reporting a Vulnerability
|
||||
## :pencil: Reporting a Vulnerability
|
||||
|
||||
Please contact security@getgrav.org with a detailed explanation of the security issue found. If it appears to be a legitimate issues, please submit an **advisory via GitHub Security**: https://github.com/getgrav/grav/security/advisories
|
||||
|
||||
>> NOTE: Please do not use 3rd party security issue reporting services, we like to keep everything in the GitHub ecosystem for easier manageability.
|
||||
> NOTE: Please do not use 3rd party security issue reporting services, we like to keep everything in the GitHub ecosystem for easier manageability.
|
||||
|
||||
## Bug Bounties
|
||||
## :bug: Bug Bounties
|
||||
|
||||
We do greatly appreciate your efforts to improve Grav, but unfortunately because we are a small open source project, we **do not have the resources to offer bounties** for security issues found.
|
||||
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1301,6 +1301,17 @@ form:
|
|||
lazy: Lazy
|
||||
eager: Eager
|
||||
|
||||
images.defaults.decoding:
|
||||
type: select
|
||||
size: small
|
||||
label: PLUGIN_ADMIN.IMAGES_DECODING
|
||||
help: PLUGIN_ADMIN.IMAGES_DECODING_HELP
|
||||
highlight: auto
|
||||
options:
|
||||
auto: Auto
|
||||
sync: Sync
|
||||
async: Async
|
||||
|
||||
images.seofriendly:
|
||||
type: toggle
|
||||
label: PLUGIN_ADMIN.IMAGES_SEOFRIENDLY
|
||||
|
|
|
@ -168,6 +168,7 @@ images:
|
|||
retina_scale: 1 # scale to adjust auto-sizes for better handling of HiDPI resolutions
|
||||
defaults:
|
||||
loading: auto # Let browser pick [auto|lazy|eager]
|
||||
decoding: auto # Let browser pick [auto|sync|async]
|
||||
watermark:
|
||||
image: 'system://images/watermark.png' # Path to a watermark image
|
||||
position_y: 'center' # top|center|bottom
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
// Some standard defines
|
||||
define('GRAV', true);
|
||||
define('GRAV_VERSION', '1.7.44');
|
||||
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')) {
|
||||
|
|
|
@ -104,6 +104,7 @@ GRAV:
|
|||
VALIDATION_FAIL: '<b>Провера неуспела:</b>'
|
||||
INVALID_INPUT: 'Неисправан унос у'
|
||||
MISSING_REQUIRED_FIELD: 'Недостаје обавезн поље:'
|
||||
XSS_ISSUES: "Потенцијална грешка у XSS-у детектована у пољу '%s' "
|
||||
MONTHS_OF_THE_YEAR:
|
||||
- 'Јануар'
|
||||
- 'Фебруар'
|
||||
|
@ -125,6 +126,8 @@ GRAV:
|
|||
- 'Петак'
|
||||
- 'Субота'
|
||||
- 'Недеља'
|
||||
YES: "Да"
|
||||
NO: "Не"
|
||||
CRON:
|
||||
EVERY: сваки
|
||||
EVERY_HOUR: сваки сат
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -161,9 +161,15 @@ class Inflector
|
|||
*/
|
||||
public static function titleize($word, $uppercase = '')
|
||||
{
|
||||
$uppercase = $uppercase === 'first' ? 'ucfirst' : 'ucwords';
|
||||
$humanize_underscorize = static::humanize(static::underscorize($word));
|
||||
|
||||
if ($uppercase === 'first') {
|
||||
$firstLetter = mb_strtoupper(mb_substr($humanize_underscorize, 0, 1, "UTF-8"), "UTF-8");
|
||||
return $firstLetter . mb_substr($humanize_underscorize, 1, mb_strlen($humanize_underscorize, "UTF-8"), "UTF-8");
|
||||
} else {
|
||||
return mb_convert_case($humanize_underscorize, MB_CASE_TITLE, 'UTF-8');
|
||||
}
|
||||
|
||||
return $uppercase(static::humanize(static::underscorize($word)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -180,7 +186,7 @@ class Inflector
|
|||
*/
|
||||
public static function camelize($word)
|
||||
{
|
||||
return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
|
||||
return str_replace(' ', '', ucwords(preg_replace('/[^\p{L}^0-9]+/', ' ', $word)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,7 +204,7 @@ class Inflector
|
|||
{
|
||||
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
|
||||
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
|
||||
$regex3 = preg_replace('/[^A-Z^a-z^0-9]+/', '_', $regex2);
|
||||
$regex3 = preg_replace('/[^\p{L}^0-9]+/u', '_', $regex2);
|
||||
|
||||
return strtolower($regex3);
|
||||
}
|
||||
|
@ -219,7 +225,7 @@ class Inflector
|
|||
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
|
||||
$regex2 = preg_replace('/([a-z])([A-Z])/', '\1-\2', $regex1);
|
||||
$regex3 = preg_replace('/([0-9])([A-Z])/', '\1-\2', $regex2);
|
||||
$regex4 = preg_replace('/[^A-Z^a-z^0-9]+/', '-', $regex3);
|
||||
$regex4 = preg_replace('/[^\p{L}^0-9]+/', '-', $regex3);
|
||||
|
||||
$regex4 = trim($regex4, '-');
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Media
|
||||
* @author Pedro Moreno https://github.com/pmoreno-rodriguez
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Media\Traits;
|
||||
|
||||
use Grav\Common\Grav;
|
||||
|
||||
/**
|
||||
* Trait ImageDecodingTrait
|
||||
* @package Grav\Common\Media\Traits
|
||||
*/
|
||||
|
||||
trait ImageDecodingTrait
|
||||
{
|
||||
/**
|
||||
* Allows to set the decoding attribute from Markdown or Twig
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function decoding($value = null)
|
||||
{
|
||||
if (null === $value) {
|
||||
$value = Grav::instance()['config']->get('system.images.defaults.decoding', 'auto');
|
||||
}
|
||||
|
||||
// Validate the provided value (similar to loading)
|
||||
if ($value !== null && $value !== 'auto') {
|
||||
$this->attributes['decoding'] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
|
@ -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'))
|
||||
);
|
||||
|
|
|
@ -15,6 +15,7 @@ use Grav\Common\Media\Interfaces\ImageManipulateInterface;
|
|||
use Grav\Common\Media\Interfaces\ImageMediaInterface;
|
||||
use Grav\Common\Media\Interfaces\MediaLinkInterface;
|
||||
use Grav\Common\Media\Traits\ImageLoadingTrait;
|
||||
use Grav\Common\Media\Traits\ImageDecodingTrait;
|
||||
use Grav\Common\Media\Traits\ImageMediaTrait;
|
||||
use Grav\Common\Utils;
|
||||
use Gregwar\Image\Image;
|
||||
|
@ -30,6 +31,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
|
|||
{
|
||||
use ImageMediaTrait;
|
||||
use ImageLoadingTrait;
|
||||
use ImageDecodingTrait;
|
||||
|
||||
/**
|
||||
* @var mixed|string
|
||||
|
|
|
@ -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',
|
||||
|
@ -263,4 +263,25 @@ class Security
|
|||
'invalid_protocols' => array_map('trim', $config->get('security.xss_invalid_protocols')),
|
||||
];
|
||||
}
|
||||
|
||||
public static function cleanDangerousTwig(string $string): string
|
||||
{
|
||||
if ($string === '') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$bad_twig = [
|
||||
'twig_array_map',
|
||||
'twig_array_filter',
|
||||
'call_user_func',
|
||||
'registerUndefinedFunctionCallback',
|
||||
'undefined_functions',
|
||||
'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]) : [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ use Grav\Common\Language\Language;
|
|||
use Grav\Common\Language\LanguageCodes;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Page\Pages;
|
||||
use Grav\Common\Security;
|
||||
use Grav\Common\Twig\Exception\TwigException;
|
||||
use Grav\Common\Twig\Extension\FilesystemExtension;
|
||||
use Grav\Common\Twig\Extension\GravExtension;
|
||||
|
@ -319,6 +320,7 @@ class Twig
|
|||
public function processPage(PageInterface $item, $content = null)
|
||||
{
|
||||
$content = $content ?? $item->content();
|
||||
$content = Security::cleanDangerousTwig($content);
|
||||
|
||||
// override the twig header vars for local resolution
|
||||
$this->grav->fireEvent('onTwigPageVariables', new Event(['page' => $item]));
|
||||
|
@ -392,6 +394,8 @@ class Twig
|
|||
$this->grav->fireEvent('onTwigStringVariables');
|
||||
$vars += $this->twig_vars;
|
||||
|
||||
$string = Security::cleanDangerousTwig($string);
|
||||
|
||||
$name = '@Var:' . $string;
|
||||
$this->setTemplate($name, $string);
|
||||
|
||||
|
@ -418,7 +422,7 @@ class Twig
|
|||
try {
|
||||
$grav = $this->grav;
|
||||
|
||||
// set the page now its been processed
|
||||
// set the page now it's been processed
|
||||
$grav->fireEvent('onTwigSiteVariables');
|
||||
|
||||
/** @var Pages $pages */
|
||||
|
@ -427,13 +431,15 @@ class Twig
|
|||
/** @var PageInterface $page */
|
||||
$page = $grav['page'];
|
||||
|
||||
$content = Security::cleanDangerousTwig($page->content());
|
||||
|
||||
$twig_vars = $this->twig_vars;
|
||||
$twig_vars['theme'] = $grav['config']->get('theme');
|
||||
$twig_vars['pages'] = $pages->root();
|
||||
$twig_vars['page'] = $page;
|
||||
$twig_vars['header'] = $page->header();
|
||||
$twig_vars['media'] = $page->media();
|
||||
$twig_vars['content'] = $page->content();
|
||||
$twig_vars['content'] = $content;
|
||||
|
||||
// determine if params are set, if so disable twig cache
|
||||
$params = $grav['uri']->params(null, true);
|
||||
|
@ -568,4 +574,5 @@ class Twig
|
|||
|
||||
$this->autoescape = (bool) $state;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -989,6 +989,8 @@ abstract class Utils
|
|||
|| strtr($filename, "\t\v\n\r\0\\/", '_______') !== $filename
|
||||
// Filename should not start or end with dot or space.
|
||||
|| trim($filename, '. ') !== $filename
|
||||
// Filename should not contain path traversal
|
||||
|| str_replace('..', '', $filename) !== $filename
|
||||
// File extension should not be part of configured dangerous extensions
|
||||
|| in_array($extension, $dangerous_extensions)
|
||||
);
|
||||
|
@ -1330,7 +1332,11 @@ abstract class Utils
|
|||
if ($dateformat) {
|
||||
$datetime = DateTime::createFromFormat($dateformat, $date);
|
||||
} else {
|
||||
$datetime = new DateTime($date);
|
||||
try {
|
||||
$datetime = new DateTime($date);
|
||||
} catch (Exception $e) {
|
||||
$datetime = false;
|
||||
}
|
||||
}
|
||||
|
||||
// fallback to strtotime() if DateTime approach failed
|
||||
|
|
|
@ -160,7 +160,7 @@ log:
|
|||
tag: grav
|
||||
debugger:
|
||||
enabled: false
|
||||
provider: clockwork
|
||||
provider: debugbar
|
||||
censored: false
|
||||
shutdown:
|
||||
close_connection: true
|
||||
|
@ -178,6 +178,7 @@ images:
|
|||
retina_scale: '1'
|
||||
defaults:
|
||||
loading: auto
|
||||
decoding: auto
|
||||
watermark:
|
||||
image: 'system://images/watermark.png'
|
||||
position_y: center
|
||||
|
@ -189,7 +190,7 @@ media:
|
|||
unsupported_inline_types: null
|
||||
allowed_fallback_types: null
|
||||
auto_metadata_exif: false
|
||||
upload_limit: 2097152
|
||||
upload_limit: 2147483648
|
||||
session:
|
||||
enabled: true
|
||||
initialize: true
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
<div class="article-header">
|
||||
{% if page.parent.title == "Articles" %}
|
||||
<div class="article-siblings">
|
||||
{% if not page.isFirst %}
|
||||
<a href="{{ page.nextSibling.url }}">{{ page.nextSibling.title }}<i class="fa-solid fa-chevron-left"></i> Article suivant</a>
|
||||
{{ dump(page.parent.collection.prevSibling(page.path)) }}
|
||||
{% if not page.parent.collection.isFirst(page.path) %}
|
||||
<a href="{{ page.parent.collection.nextSibling(page.path).url }}"><i class="fa-solid fa-chevron-left"></i> Article suivant</a>
|
||||
{% else %}
|
||||
<div></div>
|
||||
{% endif %}
|
||||
{% if not page.isLast %}
|
||||
<a href="{{ page.prevSibling.url }}">{{ page.prevSibling.title }} Article précédent <i class="fa-solid fa-chevron-right"></i></a>
|
||||
{% if not page.parent.collection.isLast(page.path) %}
|
||||
<a href="{{ page.parent.collection.prevSibling(page.path).url }}">Article précédent <i class="fa-solid fa-chevron-right"></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{ page.find('/a-propos').summary|raw }}
|
||||
</div>
|
||||
<div id="about-hidden">
|
||||
{{ page.find('/a-propos').content|slice(page.summary|length, page.content|length)|markdown(false) }}
|
||||
{{ page.find('/a-propos').content|slice(page.find('/a-propos').summary|length, page.find('/a-propos').content|length)|markdown(false) }}
|
||||
</div>
|
||||
<div id="about-arrow">
|
||||
<div></div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<main>
|
||||
{% for article in page.find('/articles').children.published.order('date', 'desc') %}
|
||||
{% for article in page.find('/articles').collection %}
|
||||
<div class="article-card">
|
||||
<a href="{{ article.url }}" data-barba="link">
|
||||
<div class="img-cover">
|
||||
|
|
Loading…
Reference in New Issue