Upgrade to 4.1.1

This commit is contained in:
Bastian Allgeier
2024-02-26 11:15:36 +01:00
parent 9345fc1a0b
commit 2e8aa1ed80
20 changed files with 123 additions and 171 deletions

View File

@@ -19,4 +19,9 @@ You can also use the [security advisory form on GitHub](https://github.com/getki
We will send you a response as soon as possible and will keep you informed on our progress towards a fix and announcement.
**Please do not write to us publicly, e.g. in the forum, on Discord or in a GitHub issue. A public report can give attackers valuable time to exploit the issue before it is fixed. By letting us know directly and coordinating the disclosure with us, you can help to protect other Kirby users from such attacks.**
> [!IMPORTANT]
> Please do not write to us publicly, e.g. in the forum, on Discord or in a GitHub issue. A public report can give attackers valuable time to exploit the issue before it is fixed.
>
> By letting us know directly and coordinating the disclosure with us, you can help to protect other Kirby users from such attacks.
>
> Also please do *not* request a CVE ID from organizations like MITRE. The responsible CVE Numbering Authority (CNA) for Kirby is GitHub. We can and will request a CVE ID for each confirmed vulnerability and will provide it to you in advance of the coordinated release.

View File

@@ -3,7 +3,7 @@
"description": "The Kirby core",
"license": "proprietary",
"type": "kirby-cms",
"version": "4.1.0",
"version": "4.1.1",
"keywords": [
"kirby",
"cms",

4
kirby/composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "815a3c3a27039ef652b9619518a6cc9c",
"content-hash": "198d5d56dcbb8ba4ff42a1cb4a2630bc",
"packages": [
{
"name": "christian-riesen/base32",
@@ -1125,5 +1125,5 @@
"platform-overrides": {
"php": "8.1.0"
},
"plugin-api-version": "2.3.0"
"plugin-api-version": "2.6.0"
}

View File

@@ -1,6 +1,8 @@
<?php
use Kirby\Exception\Exception;
use Kirby\Filesystem\F;
use Kirby\Toolkit\Str;
/**
* User Routes
@@ -79,10 +81,27 @@ return [
],
'method' => 'POST',
'action' => function (string $id) {
$this->user($id)->avatar()?->delete();
return $this->upload(
function ($source, $filename) use ($id) {
$type = F::type($filename);
if ($type !== 'image') {
throw new Exception([
'key' => 'file.type.invalid',
'data' => compact('type')
]);
}
$mime = F::mime($source);
if (Str::startsWith($mime, 'image/') !== true) {
throw new Exception([
'key' => 'file.mime.invalid',
'data' => compact('mime')
]);
}
// delete the old avatar
$this->user($id)->avatar()?->delete();
$props = [
'filename' => 'profile.' . F::extension($filename),
'template' => 'avatar',

View File

@@ -22,8 +22,7 @@ return [
'file',
'email',
'tel',
'anchor',
'custom'
'anchor'
];
},
'value' => function (string|null $value = null) {

View File

@@ -8,7 +8,7 @@ return [
],
'props' => [
/**
* Array or query string for reports. Each report needs a `label` and `value` and can have additional `info`, `link` and `theme` settings.
* Array or query string for reports. Each report needs a `label` and `value` and can have additional `info`, `link`, `icon` and `theme` settings.
*/
'reports' => function ($reports = null) {
if ($reports === null) {

View File

@@ -347,7 +347,7 @@
"file": "Datei",
"file.blueprint": "Du kannst zusätzliche Felder und Bereiche für diese Datei in <strong>/site/blueprints/files/{blueprint}.yml</strong> anlegen",
"file.changeTemplate": "Vorlage ändern",
"file.changeTemplate.notice": "Das Ändern der Dateivoralge wird alle Inhalte von Feldern entfernen, deren Feldtypen nicht übereinstimmen. Wenn die neue Vorlage bestimmte Regeln definiert, z.B. Bildabmessungen, werden diese unwiderruflich angewandt. Benutze diese Funktion mit Vorsicht.",
"file.changeTemplate.notice": "Das Ändern der Dateivorlage wird alle Inhalte von Feldern entfernen, deren Feldtypen nicht übereinstimmen. Wenn die neue Vorlage bestimmte Regeln definiert, z.B. Bildabmessungen, werden diese unwiderruflich angewandt. Benutze diese Funktion mit Vorsicht.",
"file.delete.confirm": "Willst du die Datei <strong>{filename}</strong> <br>wirklich löschen?",
"file.focus.placeholder": "Fokuspunkt setzen",
"file.focus.reset": "Fokuspunkt entfernen",

View File

@@ -135,7 +135,7 @@
"error.license.domain": "Лицензия на этот домен отсутствует",
"error.license.email": "Пожалуйста, введите правильный Email",
"error.license.format": "Please enter a valid license code",
"error.license.format": "Пожалуйста, введите правильный лицензионный код",
"error.license.verification": "Лицензия не подтверждена",
"error.login.totp.confirm.invalid": "Неверный код",
@@ -417,7 +417,7 @@
"license.activate": "Активировать сейчас",
"license.activate.label": "Пожалуйста, активируйте Вашу лицензию",
"license.activate.domain": "Ваша лицензия будет активирована на {host}.",
"license.activate.local": "Вы собираетесьактивировать лицензию на локальный домен {host}. Если этот сайт будет размещен на общедоступном домене, то, пожалуйста, укажите его вместо {host}.",
"license.activate.local": "Вы собираетесь активировать лицензию на локальный домен {host}. Если этот сайт будет размещен на общедоступном домене, то, пожалуйста, укажите его вместо {host}.",
"license.activated": "Активировано",
"license.buy": "Купить лицензию",
"license.code": "Код",
@@ -425,8 +425,8 @@
"license.code.label": "Пожалуйста вставьте код лицензии",
"license.status.active.info": "Включает обновления до {date}",
"license.status.active.label": "Действительная лицензия",
"license.status.demo.info": "This is a demo installation",
"license.status.demo.label": "Demo",
"license.status.demo.info": "Это демонстрационная установка",
"license.status.demo.label": "Демо",
"license.status.inactive.info": "Обновите лицензию для перехода на новые версии",
"license.status.inactive.label": "Нет новых обновлений",
"license.status.legacy.bubble": "Вы готовы обновить вашу лицензию?",

View File

@@ -0,0 +1,2 @@
src/components/Text/Highlight.vue

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,95 +0,0 @@
/* eslint-env node */
import path from "path";
import { defineConfig, splitVendorChunkPlugin } from "vite";
import vue from "@vitejs/plugin-vue2";
import { viteStaticCopy } from "vite-plugin-static-copy";
import externalGlobals from "rollup-plugin-external-globals";
import kirby from "./scripts/vite-kirby.mjs";
let customServer;
try {
customServer = require("./vite.config.custom.js");
} catch (err) {
customServer = {};
}
export default defineConfig(({ command }) => {
// gather plugins depending on environment
const plugins = [vue(), splitVendorChunkPlugin(), kirby()];
if (command === "build") {
plugins.push(
viteStaticCopy({
targets: [
{
src: "node_modules/vue/dist/vue.min.js",
dest: "js"
}
]
})
);
}
if (!process.env.VITEST) {
plugins.push(
// Externalize Vue so it's not loaded from node_modules
// but accessed via window.Vue
{
...externalGlobals({ vue: "Vue" }),
enforce: "post"
}
);
}
const proxy = {
target: process.env.VUE_APP_DEV_SERVER ?? "http://sandbox.test",
changeOrigin: true,
secure: false
};
return {
plugins,
define: {
// Fix vuelidate error
"process.env.BUILD": JSON.stringify("production")
},
base: "./",
build: {
minify: "terser",
cssCodeSplit: false,
rollupOptions: {
input: "./src/index.js",
output: {
entryFileNames: "js/[name].min.js",
chunkFileNames: "js/[name].min.js",
assetFileNames: "[ext]/[name].min.[ext]"
}
}
},
optimizeDeps: {
entries: "src/**/*.{js,vue}",
exclude: ["vitest", "vue"]
},
resolve: {
alias: {
"@": path.resolve(__dirname, "src")
}
},
server: {
proxy: {
"/api": proxy,
"/env": proxy,
"/media": proxy
},
open: proxy.target + "/panel",
port: 3000,
...customServer
},
test: {
environment: "node",
include: ["**/*.test.js"],
setupFiles: ["vitest.setup.js"]
}
};
});

View File

@@ -105,6 +105,14 @@ trait FileModifications
]);
}
/**
* Sharpens the image
*/
public function sharpen(int $amount = 50): FileVersion|File|Asset
{
return $this->thumb(['sharpen' => $amount]);
}
/**
* Create a srcset definition for the given sizes
* Sizes can be defined as a simple array. They can

View File

@@ -62,10 +62,11 @@ enum LicenseStatus: string
/**
* Returns the dialog according to the status
*/
public function dialog(): string
public function dialog(): string|null
{
return match ($this) {
static::Missing => 'registration',
static::Demo => null,
default => 'license'
};
}

View File

@@ -277,6 +277,15 @@ class File
if (is_array($rules['mime'] ?? null) === true) {
$mime = $this->mime();
// the MIME type could not be determined, but matching
// to it was requested explicitly
if ($mime === null) {
throw new Exception([
'key' => 'file.mime.missing',
'data' => ['filename' => $this->filename()]
]);
}
// determine if any pattern matches the MIME type;
// once any pattern matches, `$carry` is `true` and the rest is skipped
$matches = array_reduce(

View File

@@ -306,6 +306,7 @@ class Remote
* Decode the response content
*
* @param bool $array decode as array or object
* @psalm-return ($array is true ? array|null : stdClass|null)
*/
public function json(bool $array = true): array|stdClass|null
{

View File

@@ -35,7 +35,7 @@ class Panel
/**
* Normalize a panel area
*/
public static function area(string $id, array|string $area): array
public static function area(string $id, array $area): array
{
$area['id'] = $id;
$area['label'] ??= $id;

View File

@@ -488,7 +488,16 @@ class Str
return $string;
}
return static::substr($string, 0, mb_strrpos(static::substr($string, 0, $chars), ' ')) . $rep;
// shorten the string to the specified number of characters,
// but make sure to not cut off in the middle of a word
$excerpt = static::substr($string, 0, $chars);
$cutoff = mb_strrpos($excerpt, ' ');
if ($cutoff !== false) {
$excerpt = static::substr($string, 0, $cutoff);
}
return $excerpt . $rep;
}
/**

View File

@@ -45,35 +45,34 @@ class ClassLoader
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -81,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
* @var array<string, string>
*/
private $classMap = array();
@@ -90,21 +88,20 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
/** @var string|null */
private $apcuPrefix;
/**
* @var self[]
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
@@ -113,7 +110,7 @@ class ClassLoader
}
/**
* @return string[]
* @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -125,8 +122,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -134,8 +130,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirs()
{
@@ -143,8 +138,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -152,8 +146,7 @@ class ClassLoader
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -161,8 +154,7 @@ class ClassLoader
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -180,23 +172,24 @@ class ClassLoader
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
$paths
);
}
@@ -205,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
$paths
);
}
}
@@ -227,7 +220,7 @@ class ClassLoader
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
@@ -236,17 +229,18 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -256,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
$paths
);
}
}
@@ -277,7 +271,7 @@ class ClassLoader
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -295,7 +289,7 @@ class ClassLoader
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -481,9 +475,9 @@ class ClassLoader
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return self[]
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{

View File

@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'getkirby/cms',
'pretty_version' => '4.1.0',
'version' => '4.1.0.0',
'reference' => NULL,
'pretty_version' => '4.1.1',
'version' => '4.1.1.0',
'reference' => null,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -47,9 +47,9 @@
'dev_requirement' => false,
),
'getkirby/cms' => array(
'pretty_version' => '4.1.0',
'version' => '4.1.0.0',
'reference' => NULL,
'pretty_version' => '4.1.1',
'version' => '4.1.1.0',
'reference' => null,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),