corrections de problèmes de liens inter articles et de display du about

This commit is contained in:
Valentin
2024-06-04 13:16:42 +02:00
parent 97231dd6bf
commit 7c640a7a14
27 changed files with 356 additions and 425 deletions

View File

@@ -1300,6 +1300,17 @@ form:
auto: Auto
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

View File

@@ -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

View File

@@ -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')) {

View File

@@ -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: сваки сат

View File

@@ -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)) {

View File

@@ -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, '-');

View File

@@ -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;
}
}

View File

@@ -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'))
);

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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]) : [];
}
}

View File

@@ -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;
}
}

View File

@@ -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',

View File

@@ -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

View File

0
system/src/Twig/DeferredExtension/DeferredNode.php Executable file → Normal file
View File