Compare commits

...

4 commits

Author SHA1 Message Date
Paul Nicoué
5d9979fca8 Update npm dependencies 2025-07-04 15:36:09 +02:00
Paul Nicoué
9aa4718ac9 Edit npm dependency version constraints 2025-07-04 15:29:04 +02:00
Paul Nicoué
e5b51981ff Edit PHP version constraint and update Composer dependencies 2025-07-04 15:08:52 +02:00
Paul Nicoué
231e1bce63 Remove swiped-events library 2025-06-15 18:27:06 +02:00
57 changed files with 894 additions and 727 deletions

View file

@ -1,5 +1,4 @@
import Splide from '@splidejs/splide';
import create from 'swiped-events';
// ----------------------------------------------------------------------------
// DATA

View file

@ -11,7 +11,7 @@
}
],
"require": {
"php": ">=8.1.0 <8.4.0",
"php": "~8.3.0",
"getkirby/cms": "^4.0",
"kirbyzone/sitemapper": "^1.2.1",
"wearejust/kirby-twig": "^5.0"

117
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": "f17093a48c983686f90617c12b92d15c",
"content-hash": "d9d8444cbdb90e7d30acec264e245c6a",
"packages": [
{
"name": "christian-riesen/base32",
@ -272,16 +272,16 @@
},
{
"name": "getkirby/cms",
"version": "4.7.0",
"version": "4.8.0",
"source": {
"type": "git",
"url": "https://github.com/getkirby/kirby.git",
"reference": "938fe98951cace6c77aab744779bf4e0799ad705"
"reference": "5292c17832dd34b0e5f3e98dea837a357ef037b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/getkirby/kirby/zipball/938fe98951cace6c77aab744779bf4e0799ad705",
"reference": "938fe98951cace6c77aab744779bf4e0799ad705",
"url": "https://api.github.com/repos/getkirby/kirby/zipball/5292c17832dd34b0e5f3e98dea837a357ef037b6",
"reference": "5292c17832dd34b0e5f3e98dea837a357ef037b6",
"shasum": ""
},
"require": {
@ -301,13 +301,13 @@
"ext-simplexml": "*",
"filp/whoops": "2.18.0",
"getkirby/composer-installer": "^1.2.1",
"laminas/laminas-escaper": "2.16.0",
"laminas/laminas-escaper": "2.17.0",
"michelf/php-smartypants": "1.8.1",
"php": "~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0",
"phpmailer/phpmailer": "6.9.3",
"symfony/polyfill-intl-idn": "1.31.0",
"symfony/polyfill-mbstring": "1.31.0",
"symfony/yaml": "6.4.18"
"phpmailer/phpmailer": "6.10.0",
"symfony/polyfill-intl-idn": "1.32.0",
"symfony/polyfill-mbstring": "1.32.0",
"symfony/yaml": "6.4.21"
},
"replace": {
"symfony/polyfill-php72": "*"
@ -371,7 +371,7 @@
"type": "custom"
}
],
"time": "2025-03-25T11:15:09+00:00"
"time": "2025-06-03T09:52:03+00:00"
},
{
"name": "getkirby/composer-installer",
@ -459,16 +459,16 @@
},
{
"name": "laminas/laminas-escaper",
"version": "2.16.0",
"version": "2.17.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-escaper.git",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8"
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/df1ef9503299a8e3920079a16263b578eaf7c3ba",
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba",
"shasum": ""
},
"require": {
@ -516,7 +516,7 @@
"type": "community_bridge"
}
],
"time": "2025-02-17T12:40:19+00:00"
"time": "2025-05-06T19:29:36+00:00"
},
{
"name": "league/color-extractor",
@ -635,16 +635,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.9.3",
"version": "v6.10.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e"
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"shasum": ""
},
"require": {
@ -704,7 +704,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0"
},
"funding": [
{
@ -712,7 +712,7 @@
"type": "github"
}
],
"time": "2024-11-24T18:04:13+00:00"
"time": "2025-04-24T15:19:31+00:00"
},
{
"name": "psr/log",
@ -766,16 +766,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.1",
"version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
@ -788,7 +788,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
"dev-main": "3.6-dev"
}
},
"autoload": {
@ -813,7 +813,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@ -829,11 +829,11 @@
"type": "tidelift"
}
],
"time": "2024-09-25T14:20:29+00:00"
"time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -892,7 +892,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
},
"funding": [
{
@ -912,16 +912,16 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"shasum": ""
},
"require": {
@ -975,7 +975,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
},
"funding": [
{
@ -991,11 +991,11 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2024-09-10T14:38:51+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@ -1056,7 +1056,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
},
"funding": [
{
@ -1076,19 +1076,20 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
@ -1136,7 +1137,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
},
"funding": [
{
@ -1152,20 +1153,20 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/yaml",
"version": "v6.4.18",
"version": "v6.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5"
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"url": "https://api.github.com/repos/symfony/yaml/zipball/f01987f45676778b474468aa266fe2eda1f2bc7e",
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e",
"shasum": ""
},
"require": {
@ -1208,7 +1209,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.4.18"
"source": "https://github.com/symfony/yaml/tree/v6.4.21"
},
"funding": [
{
@ -1224,20 +1225,20 @@
"type": "tidelift"
}
],
"time": "2025-01-07T09:44:41+00:00"
"time": "2025-04-04T09:48:44+00:00"
},
{
"name": "twig/twig",
"version": "v3.20.0",
"version": "v3.21.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "3468920399451a384bef53cf7996965f7cd40183"
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/3468920399451a384bef53cf7996965f7cd40183",
"reference": "3468920399451a384bef53cf7996965f7cd40183",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d",
"shasum": ""
},
"require": {
@ -1291,7 +1292,7 @@
],
"support": {
"issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.20.0"
"source": "https://github.com/twigphp/Twig/tree/v3.21.1"
},
"funding": [
{
@ -1303,7 +1304,7 @@
"type": "tidelift"
}
],
"time": "2025-02-13T08:34:43+00:00"
"time": "2025-05-03T07:21:55+00:00"
},
{
"name": "wearejust/kirby-twig",
@ -1362,7 +1363,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=8.1.0 <8.4.0"
"php": "~8.3.0"
},
"platform-dev": {},
"platform-overrides": {

View file

@ -1,14 +1,14 @@
##
## Bundle of CA Root Certificates
##
## Certificate data from Mozilla as of: Tue Feb 25 04:12:03 2025 GMT
## Certificate data from Mozilla as of: Tue May 20 03:12:02 2025 GMT
##
## Find updated versions here: https://curl.se/docs/caextract.html
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
## file (certdata.txt). This file can be found in the mozilla source tree:
## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
## https://raw.githubusercontent.com/mozilla-firefox/firefox/refs/heads/release/security/nss/lib/ckfw/builtins/certdata.txt
##
## It contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
@ -16,76 +16,10 @@
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.29.
## SHA256: 620fd89c02acb0019f1899dab7907db5d20735904f5a9a0d3a8771a5857ac482
## SHA256: 8944ec6b572b577daee4fc681a425881f841ec2660e4cb5f0eee727f84620697
##
GlobalSign Root CA
==================
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
Entrust.net Premium 2048 Secure Server CA
=========================================
-----BEGIN CERTIFICATE-----
MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
-----END CERTIFICATE-----
Baltimore CyberTrust Root
=========================
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
-----END CERTIFICATE-----
Entrust Root Certification Authority
====================================
-----BEGIN CERTIFICATE-----
@ -112,30 +46,6 @@ W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
-----END CERTIFICATE-----
Comodo AAA Services root
========================
-----BEGIN CERTIFICATE-----
MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
-----END CERTIFICATE-----
QuoVadis Root CA 2
==================
-----BEGIN CERTIFICATE-----
@ -202,78 +112,6 @@ vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
-----END CERTIFICATE-----
XRamp Global CA Root
====================
-----BEGIN CERTIFICATE-----
MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
-----END CERTIFICATE-----
Go Daddy Class 2 CA
===================
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
vZ8=
-----END CERTIFICATE-----
Starfield Class 2 CA
====================
-----BEGIN CERTIFICATE-----
MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
QBFGmh95DmK/D5fs4C8fF5Q=
-----END CERTIFICATE-----
DigiCert Assured ID Root CA
===========================
-----BEGIN CERTIFICATE-----

View file

@ -3,7 +3,7 @@
"description": "The Kirby core",
"license": "proprietary",
"type": "kirby-cms",
"version": "4.7.0",
"version": "4.8.0",
"keywords": [
"kirby",
"cms",
@ -41,12 +41,12 @@
"composer/semver": "3.4.3",
"filp/whoops": "2.18.0",
"getkirby/composer-installer": "^1.2.1",
"laminas/laminas-escaper": "2.16.0",
"laminas/laminas-escaper": "2.17.0",
"michelf/php-smartypants": "1.8.1",
"phpmailer/phpmailer": "6.9.3",
"symfony/polyfill-intl-idn": "1.31.0",
"symfony/polyfill-mbstring": "1.31.0",
"symfony/yaml": "6.4.18"
"phpmailer/phpmailer": "6.10.0",
"symfony/polyfill-intl-idn": "1.32.0",
"symfony/polyfill-mbstring": "1.32.0",
"symfony/yaml": "6.4.21"
},
"replace": {
"symfony/polyfill-php72": "*"

83
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": "fa52461c55dc4e276cd5853b57c95c60",
"content-hash": "e70567909c74a3864f445abea10a85cc",
"packages": [
{
"name": "christian-riesen/base32",
@ -319,16 +319,16 @@
},
{
"name": "laminas/laminas-escaper",
"version": "2.16.0",
"version": "2.17.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-escaper.git",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8"
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/df1ef9503299a8e3920079a16263b578eaf7c3ba",
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba",
"shasum": ""
},
"require": {
@ -376,7 +376,7 @@
"type": "community_bridge"
}
],
"time": "2025-02-17T12:40:19+00:00"
"time": "2025-05-06T19:29:36+00:00"
},
{
"name": "league/color-extractor",
@ -495,16 +495,16 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.9.3",
"version": "v6.10.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e"
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"shasum": ""
},
"require": {
@ -564,7 +564,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0"
},
"funding": [
{
@ -572,7 +572,7 @@
"type": "github"
}
],
"time": "2024-11-24T18:04:13+00:00"
"time": "2025-04-24T15:19:31+00:00"
},
{
"name": "psr/log",
@ -626,16 +626,16 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.1",
"version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
@ -648,7 +648,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.5-dev"
"dev-main": "3.6-dev"
}
},
"autoload": {
@ -673,7 +673,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@ -689,11 +689,11 @@
"type": "tidelift"
}
],
"time": "2024-09-25T14:20:29+00:00"
"time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -752,7 +752,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
},
"funding": [
{
@ -772,16 +772,16 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"shasum": ""
},
"require": {
@ -835,7 +835,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
},
"funding": [
{
@ -851,11 +851,11 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2024-09-10T14:38:51+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@ -916,7 +916,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
},
"funding": [
{
@ -936,19 +936,20 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.31.0",
"version": "v1.32.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
@ -996,7 +997,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
},
"funding": [
{
@ -1012,20 +1013,20 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/yaml",
"version": "v6.4.18",
"version": "v6.4.21",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5"
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"url": "https://api.github.com/repos/symfony/yaml/zipball/f01987f45676778b474468aa266fe2eda1f2bc7e",
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e",
"shasum": ""
},
"require": {
@ -1068,7 +1069,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.4.18"
"source": "https://github.com/symfony/yaml/tree/v6.4.21"
},
"funding": [
{
@ -1084,7 +1085,7 @@
"type": "tidelift"
}
],
"time": "2025-01-07T09:44:41+00:00"
"time": "2025-04-04T09:48:44+00:00"
}
],
"packages-dev": [],

View file

@ -24,16 +24,20 @@ return [
},
/**
* Allowed incremental steps between numbers (i.e `0.5`)
* Use `any` to allow any decimal value.
*/
'step' => function ($step = null) {
return $this->toNumber($step) ?? '';
'step' => function ($step = null): float|string {
return match ($step) {
'any' => 'any',
default => $this->toNumber($step) ?? ''
};
},
'value' => function ($value = null) {
return $this->toNumber($value) ?? '';
}
],
'methods' => [
'toNumber' => function ($value) {
'toNumber' => function ($value): float|null {
if ($this->isEmpty($value) === true) {
return null;
}

View file

@ -1,6 +1,7 @@
<?php
use Kirby\Field\FieldOptions;
use Kirby\Toolkit\I18n;
return [
'extends' => 'radio',
@ -19,8 +20,8 @@ return [
/**
* Custom placeholder string for empty option.
*/
'placeholder' => function (string $placeholder = '—') {
return $placeholder;
'placeholder' => function (string|array $placeholder = '—') {
return I18n::translate($placeholder, $placeholder);
},
],
'methods' => [

View file

@ -366,7 +366,7 @@
"field.layout.delete": "Smazat rozvržení",
"field.layout.delete.confirm": "Opravdu chcete smazat toto rozvržení?",
"field.layout.delete.confirm.all": "Opravdu chcete smazat všechna rozvržení?",
"field.layout.empty": "Zatím žádné řádky",
"field.layout.empty": "Zatím žádné rozvržení",
"field.layout.select": "Vyberte rozvržení",
"field.object.empty": "Zatím žádná informace",

View file

@ -98,17 +98,17 @@
"error.content.lock.replace": "Þessi útfáfa er læst og það verður ekki skipt út",
"error.content.lock.update": "Þessi útgáfa er læst og hún verður ekki uppfærð",
"error.entries.max.plural": "You must not add more than {max} entries",
"error.entries.max.singular": "You must not add more than one entry",
"error.entries.min.plural": "You must add at least {min} entries",
"error.entries.min.singular": "You must add at least one entry",
"error.entries.supports": "\"{type}\" field type is not supported for the entries field",
"error.entries.max.plural": "Ekki fleiri en {max} færslur",
"error.entries.max.singular": "Hámark ein færsla",
"error.entries.min.plural": "Að minnsta kosti {min} færslur",
"error.entries.min.singular": "Þú skalt setja inn a.m.k. eina færslu",
"error.entries.supports": "\"{type}\" sviðsgerðin er ekki studd fyrir færslu svið",
"error.entries.validation": "Það er villa í \"{field}\" sviðinu í röð {index}",
"error.email.preset.notFound": "Netfangstillingarnar: \"{name}\" fundust ekki",
"error.field.converter.invalid": "Ógildur umbreytari \"{converter}\"",
"error.field.link.options": "Invalid options: {options}",
"error.field.link.options": "Ógildar stillingar: {options}",
"error.field.type.missing": "Sviðið \"{ name }\": Sviðgerðin er \"{type}\" er alls ekki til.",
"error.file.changeName.empty": "Nafn skal fylla út",
@ -116,7 +116,7 @@
"error.file.changeTemplate.invalid": "Sniðmátinu fyrir skránna \"{id}\" er ekki hægt að breyta í \"{template}\" (gild: \"{blueprints}\")",
"error.file.changeTemplate.permission": "Þú mátt ekkert breyta sniðmátinu fyrir skránna \"{id}\"",
"error.file.delete.multiple": "Not all files could be deleted. Try each remaining file individually to see the specific error that prevents deletion.",
"error.file.delete.multiple": "Ekki var unnt að eyða öllum skrám. Reyndu að eyða hverri og einni til þess að sjá hvort þessi villa hindri eyðingu.",
"error.file.duplicate": "Skrá með nafninu \"{filename}\" er nú þegar til",
"error.file.extension.forbidden": "Skrárendingin \"{extension}\" er ekki leyfð",
"error.file.extension.invalid": "Óleyfilegt skrársnið hér: {extension}",
@ -179,7 +179,7 @@
"error.page.delete": "Síðunni \"{slug}\" er ekki hægt að eyða",
"error.page.delete.confirm": "Ritaðu titil síðunnar til að staðfesta",
"error.page.delete.hasChildren": "Síðan hefur undirsíður og er því ekki hægt að eyða",
"error.page.delete.multiple": "Not all pages could be deleted. Try each remaining page individually to see the specific error that prevents deletion.",
"error.page.delete.multiple": "Ekki var unnt að eyða öllum síðum. Reyndu að eyða hverri og einni til þess að sjá hvort þessi villa hindri eyðingu.",
"error.page.delete.permission": "Þú mátt ekkert eyða \"{slug}\"",
"error.page.draft.duplicate": "Uppkast með slóðinni \"{slug}\" er þegar til",
"error.page.duplicate": "Síða með slóðinni \"{slug}\" er þegar til",
@ -394,13 +394,13 @@
"file.sort": "Breyta röðun",
"files": "Skrár",
"files.delete.confirm.selected": "Do you really want to delete the selected files? This action cannot be undone.",
"files.delete.confirm.selected": "Viltu virkilega eyða völdum skrám? Hér verður ekki aftur snúið.",
"files.empty": "Engar skrár enn",
"filter": "Sigta",
"form.discard": "Hunsa breytingar",
"form.discard.confirm": "Ætlarðu virkilega að <strong>hunsa alla breytingar</strong>?",
"form.discard.confirm": "Ætlarðu virkilega að <strong>hunsa allar breytingar</strong>?",
"form.locked": "Efnið er þér ekki aðgengilegt þar sem annar notandi er nú þegar að vinna í því",
"form.unsaved": "Þessar breytingar hafa ekki verið vistaðar",
"form.preview": "Skoða breytingar",
@ -482,7 +482,7 @@
"license.status.missing.info": "Ekkert gilt skráningarleyfi",
"license.status.missing.label": "Vinsamlegast virkjaðu leyfið þitt",
"license.status.unknown.info": "Staða leyfis fyrir hugbúnaðinn er óþekkt",
"license.status.unknown.label": "Unknown",
"license.status.unknown.label": "Óþekkt",
"license.manage": "Sýslaðu með leyfin þín",
"license.purchased": "Verslað",
"license.success": "Þakka þér fyrir að velja Kirby",
@ -604,7 +604,7 @@
"page.status.unlisted.description": "Síðan er útgefin en þó ólistuð.",
"pages": "Síður",
"pages.delete.confirm.selected": "Do you really want to delete the selected pages? This action cannot be undone.",
"pages.delete.confirm.selected": "Viltu virkilega eyða völdum síðum? Hér verður ekki aftur snúið.",
"pages.empty": "Engar síður enn",
"pages.status.draft": "Uppköst",
"pages.status.listed": "Útgefnar og listaðar",
@ -679,9 +679,9 @@
"system.issues.git": ".git mappan virðist vera berskjölduð",
"system.issues.https": "Við mælum harðlega með því að þú notir HTTPS fyrir öll þín vefsvæði",
"system.issues.kirby": "Kirby mappan virðist vera berskjölduð",
"system.issues.local": "The site is running locally with relaxed security checks",
"system.issues.local": "Vefsvæðið keyrir staðbundið (e. local) með ákaflega lágum öryggiskröfum.",
"system.issues.site": "Mappa vefsvæðisins virðist vera berskjölduð",
"system.issues.vue.compiler": "The Vue template compiler is enabled",
"system.issues.vue.compiler": "Vue sniðmátsþýðandinn er virkur",
"system.issues.vulnerability.kirby": "Uppsetningin þín gæti verið berskjölduð gagnvart eftirfarandi veikleika: ({ severity } veikleikinn): { description }",
"system.issues.vulnerability.plugin": "Uppsetningin þín gæti verið berskjölduð gagnvart eftirfarandi veikleika í viðbótinni { plugin }: ({ severity } veikleikinn): { description }",
"system.updateStatus": "Uppfærslustaða",
@ -761,7 +761,7 @@
"user.changeLanguage": "Breyta tungumáli",
"user.changeName": "Endurnefna þennan notanda",
"user.changePassword": "Breyta lykilorð",
"user.changePassword.current": "Your current password",
"user.changePassword.current": "Þitt núverandi lykilorð",
"user.changePassword.new": "Nýtt lykilorð",
"user.changePassword.new.confirm": "Staðfestu nýtt lykilorð…",
"user.changeRole": "Breyta hlutverki",

View file

@ -20,9 +20,9 @@
"coordinates": "Coordinates",
"copy": "Copia",
"copy.all": "Copia tutto",
"copy.success": "{count} copied!",
"copy.success": "Copiato",
"copy.success.multiple": "{count} copied!",
"copy.url": "Copy URL",
"copy.url": "Copia URL",
"create": "Crea",
"custom": "Custom",
@ -92,23 +92,23 @@
"error.cache.type.invalid": "Tipo di cache \"{type}\" non valido",
"error.content.lock.delete": "The version is locked and cannot be deleted",
"error.content.lock.move": "The source version is locked and cannot be moved",
"error.content.lock.publish": "This version is already published",
"error.content.lock.replace": "The version is locked and cannot be replaced",
"error.content.lock.update": "The version is locked and cannot be updated",
"error.content.lock.delete": "La versione è bloccata e non può essere eliminata",
"error.content.lock.move": "La versione di origine è bloccata e non può essere spostata",
"error.content.lock.publish": "Questa versione è già pubblica",
"error.content.lock.replace": "La versione è bloccata e non può essere rimpiazzata",
"error.content.lock.update": "La versione è bloccata e non può essere aggiornata",
"error.entries.max.plural": "You must not add more than {max} entries",
"error.entries.max.singular": "You must not add more than one entry",
"error.entries.min.plural": "You must add at least {min} entries",
"error.entries.min.singular": "You must add at least one entry",
"error.entries.supports": "\"{type}\" field type is not supported for the entries field",
"error.entries.max.plural": "Non puoi aggiungere più di {max} voci",
"error.entries.max.singular": "Non puoi aggiungere più di una voce ",
"error.entries.min.plural": "Devi aggiungere almeno {min} voci",
"error.entries.min.singular": "Devi aggiungere almeno una voce",
"error.entries.supports": "Il tipo di campo \"{type}\" non è supportato per il campo \"entries\"",
"error.entries.validation": "C'è un errore nel campo \"{field}\" nella riga {index}",
"error.email.preset.notFound": "Non è stato possibile trovare il preset email \"{name}\"",
"error.field.converter.invalid": "Convertitore \"{converter}\" non valido",
"error.field.link.options": "Invalid options: {options}",
"error.field.link.options": "Opzioni non valide: {options}",
"error.field.type.missing": "Campo \"{ name }\": il tipo di campo \"{ type }\" non esiste",
"error.file.changeName.empty": "Il nome non dev'essere vuoto",
@ -116,7 +116,7 @@
"error.file.changeTemplate.invalid": "The template for the file \"{id}\" cannot be changed to \"{template}\" (valid: \"{blueprints}\")",
"error.file.changeTemplate.permission": "You are not allowed to change the template for the file \"{id}\"",
"error.file.delete.multiple": "Not all files could be deleted. Try each remaining file individually to see the specific error that prevents deletion.",
"error.file.delete.multiple": "Non tutti i file possono essere eliminati. Prova a rimuovere i file uno per uno per vedere lerrore specifico che ne impedisce leliminazione.",
"error.file.duplicate": "Un file con il nome \"{filename}\" esiste già",
"error.file.extension.forbidden": "L'estensione \"{extension}\" non è consentita",
"error.file.extension.invalid": "Estensione non valida: {extension}",
@ -135,7 +135,7 @@
"error.file.name.missing": "Il nome del file non può essere vuoto",
"error.file.notFound": "Il file non \u00e8 stato trovato",
"error.file.orientation": "L'imaggine dev'essere orientata in \"{orientation}\"",
"error.file.sort.permission": "You are not allowed to change the sorting of \"{filename}\"",
"error.file.sort.permission": "Non ti è permesso riordinare \"{filename}\"",
"error.file.type.forbidden": "Non ti è permesso caricare file {type}",
"error.file.type.invalid": "Tipo di file non valido: {type}",
"error.file.undefined": "Il file non \u00e8 stato trovato",
@ -179,7 +179,7 @@
"error.page.delete": "La pagina \"{slug}\" non può essere eliminata",
"error.page.delete.confirm": "Inserisci il titolo della pagina per confermare",
"error.page.delete.hasChildren": "La pagina ha sottopagine e non può essere eliminata",
"error.page.delete.multiple": "Not all pages could be deleted. Try each remaining page individually to see the specific error that prevents deletion.",
"error.page.delete.multiple": "Non è stato possibile eliminare tutte le pagine. Prova ad eliminare le pagine restanti una ad una per vedere l'errore specifico che ne impedisce l'eliminazione. ",
"error.page.delete.permission": "Non ti è permesso eliminare \"{slug}\"",
"error.page.draft.duplicate": "Una bozza di pagina con l'URL \"{slug}\" esiste già",
"error.page.duplicate": "Una pagina con l'URL \"{slug}\" esiste già",
@ -187,7 +187,7 @@
"error.page.move.ancestor": "The page cannot be moved into itself",
"error.page.move.directory": "The page directory cannot be moved",
"error.page.move.duplicate": "A sub page with the URL appendix \"{slug}\" already exists",
"error.page.move.noSections": "The page \"{parent}\" cannot be a parent of any page because it lacks any pages sections in its blueprint",
"error.page.move.noSections": "La pagina \"{parent}\" non può contenere sottopagine perché il suo \"blueprint\" non definisce alcuna sezione di tipo \"pages\". ",
"error.page.move.notFound": "The moved page could not be found",
"error.page.move.permission": "You are not allowed to move \"{slug}\"",
"error.page.move.template": "The \"{template}\" template is not accepted as a subpage of \"{parent}\"",
@ -317,9 +317,9 @@
"field.blocks.heading.name": "Titolo",
"field.blocks.heading.text": "Testo",
"field.blocks.heading.placeholder": "Titolo …",
"field.blocks.figure.back.plain": "Plain",
"field.blocks.figure.back.pattern.light": "Pattern (light)",
"field.blocks.figure.back.pattern.dark": "Pattern (dark)",
"field.blocks.figure.back.plain": "Semplice",
"field.blocks.figure.back.pattern.light": "Pattern (chiaro)",
"field.blocks.figure.back.pattern.dark": "Pattern (scuro)",
"field.blocks.image.alt": "Testo alternativo",
"field.blocks.image.caption": "Didascalia",
"field.blocks.image.crop": "Ritaglio",
@ -357,10 +357,10 @@
"field.blocks.video.url.placeholder": "https://youtube.com/?v=",
"field.entries.delete.confirm.all": "Vuoi davvero cancellare tutte le voci?",
"field.entries.empty": "Non ci sono ancora elementi.",
"field.entries.empty": "Non contiene ancora voci",
"field.files.empty": "Nessun file selezionato",
"field.files.empty.single": "No file selected yet",
"field.files.empty.single": "Nessun file selezionato",
"field.layout.change": "Change layout",
"field.layout.delete": "Elimina layout",
@ -372,14 +372,14 @@
"field.object.empty": "Ancora nessuna informazione",
"field.pages.empty": "Nessuna pagina selezionata",
"field.pages.empty.single": "No page selected yet",
"field.pages.empty.single": "Nessuna pagina selezionata",
"field.structure.delete.confirm": "Vuoi veramente eliminare questo elemento?",
"field.structure.delete.confirm.all": "Vuoi davvero cancellare tutte le voci?",
"field.structure.empty": "Non ci sono ancora elementi.",
"field.structure.empty": "Non contiene ancora voci",
"field.users.empty": "Nessun utente selezionato",
"field.users.empty.single": "No user selected yet",
"field.users.empty.single": "Nessun utente selezionato",
"fields.empty": "No fields yet",
@ -394,17 +394,17 @@
"file.sort": "Cambia posizione",
"files": "Files",
"files.delete.confirm.selected": "Do you really want to delete the selected files? This action cannot be undone.",
"files.delete.confirm.selected": "Vuoi davvero eliminare i file selezionati? Questa azione è irreversibile.",
"files.empty": "Nessun file caricato",
"filter": "Filter",
"form.discard": "Discard changes",
"form.discard.confirm": "Do you really want to <strong>discard all your changes</strong>?",
"form.locked": "This content is disabled for you as it is currently edited by another user",
"form.unsaved": "The current changes have not yet been saved",
"form.preview": "Preview changes",
"form.preview.draft": "Preview draft",
"form.discard": "Annulla modifiche",
"form.discard.confirm": "Vuoi davvero <strong>scartare tutte le tue modifiche</strong>?",
"form.locked": "Questo contenuto è disabilitato perché è attualmente modificato da un altro utente",
"form.unsaved": "Le modifiche non sono ancora state salvate",
"form.preview": "Anteprima modifiche",
"form.preview.draft": "Anteprima della bozza",
"hide": "Nascondi",
"hour": "Ora",
@ -481,8 +481,8 @@
"license.status.missing.bubble": "Pronto a lanciare il tuo sito?",
"license.status.missing.info": "Nessuna licenza valida",
"license.status.missing.label": "Attiva la tua licenza ora",
"license.status.unknown.info": "The license status is unknown",
"license.status.unknown.label": "Unknown",
"license.status.unknown.info": "Lo stato della licenza è sconosciuto",
"license.status.unknown.label": "Sconosciuto",
"license.manage": "Gestisci le tue licenze",
"license.purchased": "Acquistata",
"license.success": "Ti ringraziamo per aver supportato Kirby",
@ -495,9 +495,9 @@
"lock.unsaved": "Modifiche non salvate",
"lock.unsaved.empty": "Non ci sono altre modifiche non salvate",
"lock.unsaved.files": "Unsaved files",
"lock.unsaved.pages": "Unsaved pages",
"lock.unsaved.users": "Unsaved accounts",
"lock.unsaved.files": "File non salvati",
"lock.unsaved.pages": "Pagine non salvate",
"lock.unsaved.users": "Account non salvati",
"lock.isLocked": "Unsaved changes by {email}",
"lock.unlock": "Sblocca",
"lock.unlock.submit": "Unlock and overwrite unsaved changes by <strong>{email}</strong>",
@ -604,7 +604,7 @@
"page.status.unlisted.description": "La pagina è accessibile soltanto tramite URL",
"pages": "Pagine",
"pages.delete.confirm.selected": "Do you really want to delete the selected pages? This action cannot be undone.",
"pages.delete.confirm.selected": "Vuoi davvero eliminare le pagine selezionate? Questa azione è irreversibile.",
"pages.empty": "Nessuna pagina",
"pages.status.draft": "Bozza",
"pages.status.listed": "Pubblicato",
@ -622,7 +622,7 @@
"prev": "Precedente",
"preview": "Anteprima",
"publish": "Publish",
"publish": "Pubblica",
"published": "Pubblicato",
"remove": "Rimuovi",
@ -644,9 +644,9 @@
"role.nobody.title": "Nessuno",
"save": "Salva",
"saved": "Saved",
"saved": "Salvato",
"search": "Cerca",
"searching": "Searching",
"searching": "Ricerca in corso",
"search.min": "Inserisci almeno {min} caratteri per la ricerca",
"search.all": "Mostra tutti i {count} risultati",
"search.results.none": "Nessun risultato",
@ -679,9 +679,9 @@
"system.issues.git": "La cartella .git sembra essere esposta",
"system.issues.https": "Raccomandiamo l'utilizzo di HTTPS per tutti i siti",
"system.issues.kirby": "La cartella kirby sembra essere esposta",
"system.issues.local": "The site is running locally with relaxed security checks",
"system.issues.local": "Il sito è in esecuzione in locale con controlli di sicurezza meno severi",
"system.issues.site": "La cartella site sembra essere esposta",
"system.issues.vue.compiler": "The Vue template compiler is enabled",
"system.issues.vue.compiler": "Il compilatore di template di Vue è abilitato",
"system.issues.vulnerability.kirby": "La tua installazione potrebbe essere colpita dalla seguente vulnerabilità ({ severity } gravità): { description }",
"system.issues.vulnerability.plugin": "La tua installazione potrebbe essere colpita dalla seguente vulnerabilità nel plugin { plugin } ({ severity } gravità): { description }",
"system.updateStatus": "Aggiorna lo stato",
@ -698,10 +698,10 @@
"tel.placeholder": "+49123456789",
"template": "Template",
"theme": "Theme",
"theme.light": "Lights on",
"theme.dark": "Lights off",
"theme.automatic": "Match system default",
"theme": "Tema",
"theme.light": "Luci accese",
"theme.dark": "Luci spente",
"theme.automatic": "Usa impostazione predefinita del sistema",
"title": "Titolo",
"today": "Oggi",
@ -753,7 +753,7 @@
"upload.progress": "Caricamento...",
"url": "URL",
"url.placeholder": "https://esempio.com",
"url.placeholder": "https://example.com",
"user": "Utente",
"user.blueprint": "Puoi definire ulteriori sezioni e campi del form aggiuntivi per questo ruolo in <strong>/site/blueprints/users/{blueprint}.yml</strong>",
@ -761,7 +761,7 @@
"user.changeLanguage": "Cambia lingua",
"user.changeName": "Rinomina questo utente",
"user.changePassword": "Cambia password",
"user.changePassword.current": "Your current password",
"user.changePassword.current": "La password attuale",
"user.changePassword.new": "Nuova password",
"user.changePassword.new.confirm": "Conferma la nuova password...",
"user.changeRole": "Cambia ruolo",
@ -773,13 +773,13 @@
"users": "Utenti",
"version": "Versione di Kirby",
"version.changes": "Changed version",
"version.compare": "Compare versions",
"version.changes": "Versione modificata",
"version.compare": "Confronta le versioni",
"version.current": "Versione corrente",
"version.latest": "Ultima versione",
"versionInformation": "Informazioni sulla versione",
"view": "View",
"view": "Visualizza",
"view.account": "Il tuo account",
"view.installation": "Installazione",
"view.languages": "Lingue",

View file

@ -20,9 +20,9 @@
"coordinates": "Coördinaten ",
"copy": "Kopiëren",
"copy.all": "Kopieer alles",
"copy.success": "{count} gekopieerd!",
"copy.success": "Gekopieerd",
"copy.success.multiple": "{count} gekopieerd!",
"copy.url": "Copy URL",
"copy.url": "Kopieer URL",
"create": "Aanmaken",
"custom": "Custom",
@ -92,23 +92,23 @@
"error.cache.type.invalid": "Ongeldig cache type \"{type}\"",
"error.content.lock.delete": "The version is locked and cannot be deleted",
"error.content.lock.move": "The source version is locked and cannot be moved",
"error.content.lock.publish": "This version is already published",
"error.content.lock.replace": "The version is locked and cannot be replaced",
"error.content.lock.update": "The version is locked and cannot be updated",
"error.content.lock.delete": "Deze versie is vergrendeld en kan niet worden verwijderd",
"error.content.lock.move": "De bronversie is vergrendeld en kan niet worden verplaatst",
"error.content.lock.publish": "Deze versie is al gepubliceerd",
"error.content.lock.replace": "Deze versie is vergrendeld en kan niet worden vervangen",
"error.content.lock.update": "Deze versie is vergrendeld en kan niet worden geüpdatet",
"error.entries.max.plural": "You must not add more than {max} entries",
"error.entries.max.singular": "You must not add more than one entry",
"error.entries.min.plural": "You must add at least {min} entries",
"error.entries.min.singular": "You must add at least one entry",
"error.entries.supports": "\"{type}\" field type is not supported for the entries field",
"error.entries.max.plural": "Je kunt niet meer dan {max} items toevoegen",
"error.entries.max.singular": "Je kunt niet meer dan één item toevoegen",
"error.entries.min.plural": "Je moet ten minste {min} items toevoegen",
"error.entries.min.singular": "Je moet ten minste één item toevoegen",
"error.entries.supports": "\"{type}\" veld type is niet ondersteund in het items veld",
"error.entries.validation": "Er is een fout opgetreden in veld \"{field}\" in rij {index}",
"error.email.preset.notFound": "De e-mailvoorinstelling \"{name}\" kan niet worden gevonden",
"error.field.converter.invalid": "Ongeldige converter \"{converter}\"",
"error.field.link.options": "Invalid options: {options}",
"error.field.link.options": "Ongeldige opties: {options}",
"error.field.type.missing": "Veld \"{ name }\": Het veldtype \"{ type }\" bestaat niet",
"error.file.changeName.empty": "De naam mag niet leeg zijn",
@ -116,7 +116,7 @@
"error.file.changeTemplate.invalid": "Het template voor het bestand \"{id}\" kan niet worden gewijzigd in \"{template}\" (geldig: \"{blueprints}\")",
"error.file.changeTemplate.permission": "Je hebt geen rechten om het template te wijzigen voor bestand \"{id}\"",
"error.file.delete.multiple": "Not all files could be deleted. Try each remaining file individually to see the specific error that prevents deletion.",
"error.file.delete.multiple": "Niet alle bestanden kunnen worden verwijderd. Probeer de overgebleven bestanden individueel te verwijderen om het probleem te achterhalen.",
"error.file.duplicate": "Er bestaat al een bestand met de naam \"{filename}\"",
"error.file.extension.forbidden": "Bestandsextensie \"{extension}\" is niet toegestaan",
"error.file.extension.invalid": "Ongeldige extensie: {extension}",
@ -135,7 +135,7 @@
"error.file.name.missing": "De bestandsnaam mag niet leeg zijn",
"error.file.notFound": "Het bestand kan niet worden gevonden",
"error.file.orientation": "De oriëntatie van de afbeelding moet \"{orientation}\" zijn",
"error.file.sort.permission": "You are not allowed to change the sorting of \"{filename}\"",
"error.file.sort.permission": "Je hebt geen rechten om de sortering te wijzigen van \"{filename}\"",
"error.file.type.forbidden": "Je hebt geen rechten om {type} bestanden up te loaden",
"error.file.type.invalid": "Ongeldig bestands type: {type}",
"error.file.undefined": "Het bestand kan niet worden gevonden",
@ -179,7 +179,7 @@
"error.page.delete": "De pagina \"{slug}\" kan niet worden verwijderd",
"error.page.delete.confirm": "Voer de paginatitel in om te bevestigen",
"error.page.delete.hasChildren": "Deze pagina heeft subpagina's en kan niet worden verwijderd",
"error.page.delete.multiple": "Not all pages could be deleted. Try each remaining page individually to see the specific error that prevents deletion.",
"error.page.delete.multiple": "Niet alle pagina's kunnen worden verwijderd. Probeer de overgebleven pagina's individueel te verwijderen om het probleem te achterhalen.",
"error.page.delete.permission": "Je hebt geen rechten om \"{slug}\" te verwijderen",
"error.page.draft.duplicate": "Er bestaat al een conceptpagina met de URL-appendix \"{slug}\"",
"error.page.duplicate": "Er bestaat al een pagina met de URL-appendix \"{slug}\"",
@ -187,7 +187,7 @@
"error.page.move.ancestor": "De pagina kan niet in zichzelf worden verplaatst",
"error.page.move.directory": "De page map kan niet worden verplaatst",
"error.page.move.duplicate": "Er bestaat al een subpagina met de URL-appendix \"{slug}\"",
"error.page.move.noSections": "The page \"{parent}\" cannot be a parent of any page because it lacks any pages sections in its blueprint",
"error.page.move.noSections": "De pagina \"{parent}\" kan geen bovenliggende pagina zijn omdat het een pages sectie mist in de blueprint.",
"error.page.move.notFound": "De verplaatste pagina kan niet gevonden worden",
"error.page.move.permission": "Je hebt geen rechten om \"{slug}\" te verplaatsen",
"error.page.move.template": "De \"{template}\" template is niet toegestaan als een subpagina van \"{parent}\"",
@ -317,9 +317,9 @@
"field.blocks.heading.name": "Koptekst",
"field.blocks.heading.text": "Tekst",
"field.blocks.heading.placeholder": "Koptekst ...",
"field.blocks.figure.back.plain": "Plain",
"field.blocks.figure.back.pattern.light": "Pattern (light)",
"field.blocks.figure.back.pattern.dark": "Pattern (dark)",
"field.blocks.figure.back.plain": "Neutraal",
"field.blocks.figure.back.pattern.light": "Patroon (licht)",
"field.blocks.figure.back.pattern.dark": "Patroon (donker)",
"field.blocks.image.alt": "Alternatieve tekst",
"field.blocks.image.caption": "Beschrijving",
"field.blocks.image.crop": "Uitsnede",
@ -360,7 +360,7 @@
"field.entries.empty": "Nog geen items",
"field.files.empty": "Nog geen bestanden geselecteerd",
"field.files.empty.single": "No file selected yet",
"field.files.empty.single": "Nog geen bestand geselecteerd",
"field.layout.change": "Verander layout",
"field.layout.delete": "Verwijder indeling",
@ -372,14 +372,14 @@
"field.object.empty": "Nog geen informatie",
"field.pages.empty": "Nog geen pagina's geselecteerd",
"field.pages.empty.single": "No page selected yet",
"field.pages.empty.single": "Nog geen pagina geselecteerd",
"field.structure.delete.confirm": "Wil je deze rij verwijderen?",
"field.structure.delete.confirm.all": "Weet je zeker dat je alle items wil verwijderen?",
"field.structure.empty": "Nog geen items",
"field.users.empty": "Nog geen gebruikers geselecteerd",
"field.users.empty.single": "No user selected yet",
"field.users.empty.single": "Nog geen gebruiker geselecteerd",
"fields.empty": "Nog geen velden",
@ -394,17 +394,17 @@
"file.sort": "Verander positie",
"files": "Bestanden",
"files.delete.confirm.selected": "Do you really want to delete the selected files? This action cannot be undone.",
"files.delete.confirm.selected": "Weet je zeker dat je de geselecteerde bestanden wil verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
"files.empty": "Nog geen bestanden",
"filter": "Filter",
"form.discard": "Discard changes",
"form.discard.confirm": "Do you really want to <strong>discard all your changes</strong>?",
"form.locked": "This content is disabled for you as it is currently edited by another user",
"form.unsaved": "The current changes have not yet been saved",
"form.preview": "Preview changes",
"form.preview.draft": "Preview draft",
"form.discard": "Wijzigingen annuleren",
"form.discard.confirm": "Weet je zeker dat je <strong>alle wijzigingen ongedaan wil maken</strong>?",
"form.locked": "Deze inhoud is uitgeschakeld voor jou omdat deze momenteel door een andere gebruiker wordt bewerkt",
"form.unsaved": "De huidige wijzigingen zijn nog niet opgeslagen",
"form.preview": "Bekijk wijzigingen",
"form.preview.draft": "Bekijk concept",
"hide": "Verberg",
"hour": "Uur",
@ -481,8 +481,8 @@
"license.status.missing.bubble": "Klaar om je website te lanceren?",
"license.status.missing.info": "Geen geldige licentie",
"license.status.missing.label": "Activeer je licentie",
"license.status.unknown.info": "The license status is unknown",
"license.status.unknown.label": "Unknown",
"license.status.unknown.info": "De licentiestatus is onbekend",
"license.status.unknown.label": "Onbekend",
"license.manage": "Beheer je licenties",
"license.purchased": "Gekocht",
"license.success": "Bedankt dat je Kirby ondersteunt",
@ -495,9 +495,9 @@
"lock.unsaved": "Niet opgeslagen wijzigingen",
"lock.unsaved.empty": "Er zijn geen niet opgeslagen wijzigingen meer",
"lock.unsaved.files": "Unsaved files",
"lock.unsaved.pages": "Unsaved pages",
"lock.unsaved.users": "Unsaved accounts",
"lock.unsaved.files": "Niet opgeslagen bestanden",
"lock.unsaved.pages": "Niet opgeslagen pagina's",
"lock.unsaved.users": "Niet opgeslagen accounts",
"lock.isLocked": "Niet opgeslagen wijzigingen door {email}",
"lock.unlock": "Ontgrendelen",
"lock.unlock.submit": "Niet-opgeslagen wijzigingen ontgrendelen en overschrijven met <strong>{email}</strong>",
@ -589,7 +589,7 @@
"page.create": "Maak aan als {status}",
"page.delete.confirm": "Weet je zeker dat je pagina <strong>{title}</strong> wilt verwijderen?",
"page.delete.confirm.subpages": "<strong>Deze pagina heeft subpagina's</strong>. <br>Alle subpagina's zullen ook worden verwijderd.",
"page.delete.confirm.title": "Voeg een paginatitel in om te bevestigen",
"page.delete.confirm.title": "Voer de paginatitel in om te bevestigen",
"page.duplicate.appendix": "Kopiëren",
"page.duplicate.files": "Kopieer bestanden",
"page.duplicate.pages": "Kopieer pagina's",
@ -604,7 +604,7 @@
"page.status.unlisted.description": "Deze pagina is alleen bereikbaar via URL",
"pages": "Paginas",
"pages.delete.confirm.selected": "Do you really want to delete the selected pages? This action cannot be undone.",
"pages.delete.confirm.selected": "Weet je zeker dat je de geselecteerde pagina's wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
"pages.empty": "Nog geen pagina's",
"pages.status.draft": "Concepten",
"pages.status.listed": "Gepubliceerd",
@ -622,7 +622,7 @@
"prev": "Vorige",
"preview": "Voorbeeld",
"publish": "Publish",
"publish": "Publiceren",
"published": "Gepubliceerd",
"remove": "Verwijder",
@ -644,9 +644,9 @@
"role.nobody.title": "Niemand",
"save": "Opslaan",
"saved": "Saved",
"saved": "Opgeslagen",
"search": "Zoeken",
"searching": "Searching",
"searching": "Zoeken",
"search.min": "Voer {min} tekens in om te zoeken",
"search.all": "Laat alle {count} resultaten zien",
"search.results.none": "Geen resultaten",
@ -679,9 +679,9 @@
"system.issues.git": "De .git map lijkt zichtbaar te zijn",
"system.issues.https": "We raden HTTPS aan voor al je sites",
"system.issues.kirby": "De kirby map lijkt zichtbaar te zijn",
"system.issues.local": "The site is running locally with relaxed security checks",
"system.issues.local": "De site draait lokaal met versoepelde beveiligingscontroles",
"system.issues.site": "De site map lijkt zichtbaar te zijn",
"system.issues.vue.compiler": "The Vue template compiler is enabled",
"system.issues.vue.compiler": "De Vue template compiler is ingeschakeld",
"system.issues.vulnerability.kirby": "De installatie is mogelijk getroffen door de volgende kwetsbaarheid ({ severity } ernst): { description }",
"system.issues.vulnerability.plugin": "De installatie is mogelijk getroffen door de volgende kwetsbaarheid in plugin { plugin } ({ severity } ernst): { description }",
"system.updateStatus": "Update status",
@ -698,10 +698,10 @@
"tel.placeholder": "+49123456789",
"template": "Template",
"theme": "Theme",
"theme.light": "Lights on",
"theme.dark": "Lights off",
"theme.automatic": "Match system default",
"theme": "Thema",
"theme.light": "Lichten aan",
"theme.dark": "Lichten uit",
"theme.automatic": "Systeemstandaard gebruiken",
"title": "Titel",
"today": "Vandaag",
@ -761,7 +761,7 @@
"user.changeLanguage": "Taal veranderen",
"user.changeName": "Gebruiker hernoemen",
"user.changePassword": "Wachtwoord wijzigen",
"user.changePassword.current": "Your current password",
"user.changePassword.current": "Je huidige wachtwoord",
"user.changePassword.new": "Nieuw wachtwoord",
"user.changePassword.new.confirm": "Bevestig het nieuwe wachtwoord...",
"user.changeRole": "Verander rol",
@ -773,13 +773,13 @@
"users": "Gebruikers",
"version": "Kirby-versie",
"version.changes": "Changed version",
"version.compare": "Compare versions",
"version.changes": "Gewijzigde versie",
"version.compare": "Vergelijk versies",
"version.current": "Huidige versie",
"version.latest": "Laatste versie",
"versionInformation": "Versie informatie",
"view": "View",
"view": "Bekijk",
"view.account": "Jouw account",
"view.installation": "Installatie",
"view.languages": "Talen",

View file

@ -20,7 +20,7 @@
"coordinates": "Coordenadas",
"copy": "Copiar",
"copy.all": "Copiar todos",
"copy.success": "{count} copiados!",
"copy.success": "Copiado",
"copy.success.multiple": "{count} copiados!",
"copy.url": "Copiar URL",
"create": "Criar",
@ -38,7 +38,7 @@
"days.tue": "Ter",
"days.wed": "Qua",
"debugging": "Depuração ",
"debugging": "Debugging ",
"delete": "Eliminar",
"delete.all": "Eliminar todos",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -5,11 +5,17 @@
$uri = parse_url('https://getkirby.com/' . ltrim($_SERVER['REQUEST_URI'], '/'), PHP_URL_PATH) ?? '/';
$uri = urldecode($uri);
// Emulate Apache's `mod_rewrite` functionality
if ($uri !== '/' && file_exists($_SERVER['DOCUMENT_ROOT'] . '/' . ltrim($uri, '/'))) {
// emulate Apache's `mod_rewrite` functionality, but prevent
// disclosure of the existence of files outside the document root
$path = $_SERVER['DOCUMENT_ROOT'] . '/' . ltrim($uri, '/');
if (
$uri !== '/' &&
file_exists($path) === true &&
substr(realpath($path), 0, strlen($_SERVER['DOCUMENT_ROOT'])) === $_SERVER['DOCUMENT_ROOT']
) {
return false;
}
$_SERVER['SCRIPT_NAME'] = '/index.php';
require $_SERVER['DOCUMENT_ROOT'] . '/' . $_SERVER['SCRIPT_NAME'];
require $_SERVER['DOCUMENT_ROOT'] . $_SERVER['SCRIPT_NAME'];

View file

@ -3,6 +3,7 @@
namespace Kirby\Cms;
use Closure;
use Exception as GlobalException;
use Generator;
use Kirby\Data\Data;
use Kirby\Email\Email as BaseEmail;
@ -318,9 +319,18 @@ class App
}
}
foreach (glob($this->root('blueprints') . '/' . $type . '/*.yml') as $blueprint) {
$name = F::name($blueprint);
$blueprints[$name] = $name;
try {
// protect against path traversal attacks
$root = $this->root('blueprints') . '/' . $type;
$realpath = Dir::realpath($root, $this->root('blueprints'));
foreach (glob($realpath . '/*.yml') as $blueprint) {
$name = F::name($blueprint);
$blueprints[$name] = $name;
}
} catch (GlobalException) {
// if the realpath operation failed, the following glob was skipped,
// keeping just the blueprints from extensions
}
ksort($blueprints);
@ -478,7 +488,7 @@ class App
}
// controller from site root
$controller = Controller::load($this->root('controllers') . '/' . $name . '.php');
$controller = Controller::load($this->root('controllers') . '/' . $name . '.php', $this->root('controllers'));
// controller from extension
$controller ??= $this->extension('controllers', $name);
@ -1184,7 +1194,7 @@ class App
string|null $path = null,
string|null $method = null
): Response|null {
if (($_ENV['KIRBY_RENDER'] ?? true) === false) {
if ((filter_var($_ENV['KIRBY_RENDER'] ?? true, FILTER_VALIDATE_BOOLEAN)) === false) {
return null;
}
@ -1292,11 +1302,36 @@ class App
// try to resolve image urls for pages and drafts
if ($page = $site->findPageOrDraft($id)) {
return $page->file($filename);
return $this->resolveFile($page->file($filename));
}
// try to resolve site files at least
return $site->file($filename);
return $this->resolveFile($site->file($filename));
}
/**
* Filters a resolved file object using the configuration
* @internal
*/
public function resolveFile(File|null $file): File|null
{
// shortcut for files that don't exist
if ($file === null) {
return null;
}
$option = $this->option('content.fileRedirects', true);
if ($option === true) {
return $file;
}
if ($option instanceof Closure) {
return $option($file) === true ? $file : null;
}
// option was set to `false` or an invalid value
return null;
}
/**

View file

@ -79,7 +79,7 @@ trait AppCaches
$prefix =
str_replace(['/', ':'], '_', $this->system()->indexUrl()) .
'/' .
str_replace('.', '/', $key);
str_replace(['/', '.'], ['_', '/'], $key);
$defaults = [
'active' => true,

View file

@ -105,10 +105,11 @@ class Collections
{
$kirby = App::instance();
// first check for collection file
$file = $kirby->root('collections') . '/' . $name . '.php';
// first check for collection file in the `collections` root
$root = $kirby->root('collections');
$file = $root . '/' . $name . '.php';
if (is_file($file) === true) {
if (F::exists($file, $root) === true) {
$collection = F::load($file, allowOutput: false);
if ($collection instanceof Closure) {

View file

@ -617,12 +617,20 @@ class File extends ModelWithContent
}
/**
* Simplified File URL that uses the parent
* Page URL and the filename as a more stable
* alternative for the media URLs.
* Clean file URL that uses the parent page URL
* and the filename as a more stable alternative
* for the media URLs if available. The `content.fileRedirects`
* option is used to disable this behavior or enable it
* on a per-file basis.
*/
public function previewUrl(): string|null
{
// check if the clean file URL is accessible,
// otherwise we need to fall back to the media URL
if ($this->kirby()->resolveFile($this) === null) {
return $this->url();
}
$parent = $this->parent();
$url = Url::to($this->id());
@ -651,6 +659,7 @@ class File extends ModelWithContent
return $url;
case 'user':
// there are no clean URL routes for user files
return $this->url();
default:
return $url;

View file

@ -57,7 +57,7 @@ class Language
}
static::$kirby = $props['kirby'] ?? null;
$this->code = trim($props['code']);
$this->code = basename(trim($props['code'])); // prevent path traversal
$this->default = ($props['default'] ?? false) === true;
$this->direction = ($props['direction'] ?? null) === 'rtl' ? 'rtl' : 'ltr';
$this->name = trim($props['name'] ?? $this->code);
@ -325,6 +325,7 @@ class Language
public static function loadRules(string $code): array
{
$kirby = App::instance();
$code = basename($code); // prevent path traversal
$code = Str::contains($code, '.') ? Str::before($code, '.') : $code;
$file = $kirby->root('i18n:rules') . '/' . $code . '.json';

View file

@ -95,11 +95,13 @@ class Media
string $filename
): Response|false {
$kirby = App::instance();
$index = $kirby->root('index');
$media = $kirby->root('media');
$root = match (true) {
// assets
is_string($model)
=> $kirby->root('media') . '/assets/' . $model . '/' . $hash,
=> $media . '/assets/' . $model . '/' . $hash,
// parent files for file model that already included hash
$model instanceof File
=> dirname($model->mediaRoot()),
@ -108,10 +110,13 @@ class Media
=> $model->mediaRoot() . '/' . $hash
};
$thumb = $root . '/' . $filename;
$job = $root . '/.jobs/' . $filename . '.json';
try {
// prevent path traversal
$root = Dir::realpath($root, $media);
$thumb = $root . '/' . $filename;
$job = $root . '/.jobs/' . $filename . '.json';
$options = Data::read($job);
} catch (Throwable) {
// send a customized error message to make clearer what happened here
@ -127,7 +132,12 @@ class Media
// this adds support for custom assets
$source = match (true) {
is_string($model) === true
=> $kirby->root('index') . '/' . $model . '/' . $options['filename'],
=> F::realpath(
$index . '/' . $model . '/' . $options['filename'],
$index
),
$model instanceof File
=> $model->root(),
default
=> $model->file($options['filename'])->root()
};

View file

@ -361,7 +361,7 @@ class Page extends ModelWithContent
}
/**
* Sorting number + Slug
* Returns the directory name (UID with optional sorting number)
*/
public function dirname(): string
{
@ -377,7 +377,8 @@ class Page extends ModelWithContent
}
/**
* Sorting number + Slug
* Returns the directory path relative to the `content` root
* (including optional sorting numbers and draft directories)
*/
public function diruri(): string
{

View file

@ -2,6 +2,7 @@
namespace Kirby\Cms;
use Kirby\Filesystem\F;
use Kirby\Http\Url as BaseUrl;
use Kirby\Toolkit\Str;
@ -63,10 +64,11 @@ class Url extends BaseUrl
$kirby = App::instance();
$page = $kirby->site()->page();
$path = $assetPath . '/' . $page->template() . '.' . $extension;
$file = $kirby->root('assets') . '/' . $path;
$root = $kirby->root('assets');
$file = $root . '/' . $path;
$url = $kirby->url('assets') . '/' . $path;
return file_exists($file) === true ? $url : null;
return F::exists($file, $root) === true ? $url : null;
}
/**

View file

@ -114,9 +114,14 @@ class Dir
/**
* Checks if the directory exists on disk
*/
public static function exists(string $dir): bool
public static function exists(string $dir, string|null $in = null): bool
{
return is_dir($dir) === true;
try {
static::realpath($dir, $in);
return true;
} catch (Exception) {
return false;
}
}
/**
@ -523,6 +528,33 @@ class Dir
return $result;
}
/**
* Returns the absolute path to the directory if the directory can be found.
* @since 4.7.1
*/
public static function realpath(string $dir, string|null $in = null): string
{
$realpath = realpath($dir);
if ($realpath === false || is_dir($realpath) === false) {
throw new Exception(sprintf('The directory does not exist at the given path: "%s"', $dir));
}
if ($in !== null) {
$parent = realpath($in);
if ($parent === false || is_dir($parent) === false) {
throw new Exception(sprintf('The parent directory does not exist: "%s"', $in));
}
if (substr($realpath, 0, strlen($parent)) !== $parent) {
throw new Exception('The directory is not within the parent directory');
}
}
return $realpath;
}
/**
* Removes a folder including all containing files and folders
*/

View file

@ -810,18 +810,24 @@ class Environment
}
// load the config for the host
if (empty($host) === false) {
if (
empty($host) === false &&
F::exists($path = $root . '/config.' . $host . '.php', $root) === true
) {
$configHost = F::load(
file: $root . '/config.' . $host . '.php',
file: $path,
fallback: [],
allowOutput: false
);
}
// load the config for the server IP
if (empty($addr) === false) {
if (
empty($addr) === false &&
F::exists($path = $root . '/config.' . $addr . '.php', $root) === true
) {
$configAddr = F::load(
file: $root . '/config.' . $addr . '.php',
file: $path,
fallback: [],
allowOutput: false
);

View file

@ -4,6 +4,7 @@ namespace Kirby\Panel\Lab;
use Kirby\Cms\App;
use Kirby\Filesystem\Dir;
use Kirby\Filesystem\F;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Str;
@ -32,7 +33,7 @@ class Category
) {
$this->root = $root ?? static::base() . '/' . $this->id;
if (file_exists($this->root . '/index.php') === true) {
if (F::exists($this->root . '/index.php', static::base()) === true) {
$this->props = array_merge(
require $this->root . '/index.php',
$this->props

View file

@ -30,6 +30,8 @@ class Docs
public function __construct(
protected string $name
) {
// protect against path traversal
$this->name = basename($name);
$this->kirby = App::instance();
$this->json = $this->read();
}

View file

@ -71,7 +71,7 @@ class Example
public function exists(): bool
{
return is_dir($this->root) === true;
return Dir::exists($this->root, $this->parent->root()) === true;
}
public function file(string $filename): string

View file

@ -231,8 +231,12 @@ abstract class Model
// for card layouts with `cover: true` provide
// crops based on the card ratio
if ($layout === 'cards') {
$ratio = explode('/', $settings['ratio'] ?? '1/1');
$ratio = $ratio[0] / $ratio[1];
$ratio = $settings['ratio'] ?? '1/1';
if (is_numeric($ratio) === false) {
$ratio = explode('/', $ratio);
$ratio = $ratio[0] / $ratio[1];
}
return $image->srcset([
$sizes[0] . 'w' => [

View file

@ -389,7 +389,8 @@ class FileSessionStore extends SessionStore
*/
protected function name(int $expiryTime, string $id): string
{
return $expiryTime . '.' . $id;
// protect against path traversal
return $expiryTime . '.' . basename($id);
}
/**

View file

@ -5,6 +5,7 @@ namespace Kirby\Template;
use Kirby\Cms\App;
use Kirby\Exception\InvalidArgumentException;
use Kirby\Exception\LogicException;
use Kirby\Filesystem\F;
use Kirby\Toolkit\A;
use Kirby\Toolkit\Tpl;
@ -187,7 +188,7 @@ class Snippet extends Tpl
$name = (string)$name;
$file = $root . '/' . $name . '.php';
if (file_exists($file) === false) {
if (F::exists($file, $root) === false) {
$file = $kirby->extensions('snippets')[$name] ?? null;
}

View file

@ -3,6 +3,7 @@
namespace Kirby\Toolkit;
use Closure;
use Exception;
use Kirby\Filesystem\F;
use ReflectionFunction;
@ -60,12 +61,24 @@ class Controller
return $this->function->call($bind, ...$args);
}
public static function load(string $file): static|null
public static function load(string $file, string|null $in = null): static|null
{
if (is_file($file) === false) {
return null;
}
// restrict file paths to the provided root
// to prevent path traversal
if ($in !== null) {
try {
$file = F::realpath($file, $in);
} catch (Exception) {
// don't expose whether the file exists
// (which would have returned `null` above)
return null;
}
}
$function = F::load($file);
if ($function instanceof Closure === false) {

View file

@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
throw new RuntimeException($err);
}
require_once __DIR__ . '/composer/autoload_real.php';

View file

@ -26,6 +26,12 @@ use Composer\Semver\VersionParser;
*/
class InstalledVersions
{
/**
* @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to
* @internal
*/
private static $selfDir = null;
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
@ -322,6 +328,18 @@ class InstalledVersions
self::$installedIsLocalDir = false;
}
/**
* @return string
*/
private static function getSelfDir()
{
if (self::$selfDir === null) {
self::$selfDir = strtr(__DIR__, '\\', '/');
}
return self::$selfDir;
}
/**
* @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
@ -336,7 +354,7 @@ class InstalledVersions
$copiedLocalDir = false;
if (self::$canGetVendors) {
$selfDir = strtr(__DIR__, '\\', '/');
$selfDir = self::getSelfDir();
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
$vendorDir = strtr($vendorDir, '\\', '/');
if (isset(self::$installedByVendor[$vendorDir])) {

View file

@ -343,6 +343,7 @@ return array(
'Kirby\\Uuid\\Uuid' => $baseDir . '/src/Uuid/Uuid.php',
'Kirby\\Uuid\\Uuids' => $baseDir . '/src/Uuid/Uuids.php',
'Laminas\\Escaper\\Escaper' => $vendorDir . '/laminas/laminas-escaper/src/Escaper.php',
'Laminas\\Escaper\\EscaperInterface' => $vendorDir . '/laminas/laminas-escaper/src/EscaperInterface.php',
'Laminas\\Escaper\\Exception\\ExceptionInterface' => $vendorDir . '/laminas/laminas-escaper/src/Exception/ExceptionInterface.php',
'Laminas\\Escaper\\Exception\\InvalidArgumentException' => $vendorDir . '/laminas/laminas-escaper/src/Exception/InvalidArgumentException.php',
'Laminas\\Escaper\\Exception\\RuntimeException' => $vendorDir . '/laminas/laminas-escaper/src/Exception/RuntimeException.php',

View file

@ -464,6 +464,7 @@ class ComposerStaticInit0bf5c8a9cfa251a218fc581ac888fe35
'Kirby\\Uuid\\Uuid' => __DIR__ . '/../..' . '/src/Uuid/Uuid.php',
'Kirby\\Uuid\\Uuids' => __DIR__ . '/../..' . '/src/Uuid/Uuids.php',
'Laminas\\Escaper\\Escaper' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Escaper.php',
'Laminas\\Escaper\\EscaperInterface' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/EscaperInterface.php',
'Laminas\\Escaper\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/ExceptionInterface.php',
'Laminas\\Escaper\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/InvalidArgumentException.php',
'Laminas\\Escaper\\Exception\\RuntimeException' => __DIR__ . '/..' . '/laminas/laminas-escaper/src/Exception/RuntimeException.php',

View file

@ -328,17 +328,17 @@
},
{
"name": "laminas/laminas-escaper",
"version": "2.16.0",
"version_normalized": "2.16.0.0",
"version": "2.17.0",
"version_normalized": "2.17.0.0",
"source": {
"type": "git",
"url": "https://github.com/laminas/laminas-escaper.git",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8"
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"reference": "9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8",
"url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/df1ef9503299a8e3920079a16263b578eaf7c3ba",
"reference": "df1ef9503299a8e3920079a16263b578eaf7c3ba",
"shasum": ""
},
"require": {
@ -356,7 +356,7 @@
"psalm/plugin-phpunit": "^0.19.2",
"vimeo/psalm": "^6.6.2"
},
"time": "2025-02-17T12:40:19+00:00",
"time": "2025-05-06T19:29:36+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -513,17 +513,17 @@
},
{
"name": "phpmailer/phpmailer",
"version": "v6.9.3",
"version_normalized": "6.9.3.0",
"version": "v6.10.0",
"version_normalized": "6.10.0.0",
"source": {
"type": "git",
"url": "https://github.com/PHPMailer/PHPMailer.git",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e"
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"reference": "2f5c94fe7493efc213f643c23b1b1c249d40f47e",
"url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144",
"shasum": ""
},
"require": {
@ -553,7 +553,7 @@
"symfony/polyfill-mbstring": "To support UTF-8 if the Mbstring PHP extension is not enabled (^1.2)",
"thenetworg/oauth2-azure": "Needed for Microsoft XOAUTH2 authentication"
},
"time": "2024-11-24T18:04:13+00:00",
"time": "2025-04-24T15:19:31+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -585,7 +585,7 @@
"description": "PHPMailer is a full-featured email creation and transfer class for PHP",
"support": {
"issues": "https://github.com/PHPMailer/PHPMailer/issues",
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.9.3"
"source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0"
},
"funding": [
{
@ -650,31 +650,31 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.1",
"version_normalized": "3.5.1.0",
"version": "v3.6.0",
"version_normalized": "3.6.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"time": "2024-09-25T14:20:29+00:00",
"time": "2024-09-25T14:21:43+00:00",
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
"url": "https://github.com/symfony/contracts",
"name": "symfony/contracts"
},
"branch-alias": {
"dev-main": "3.6-dev"
}
},
"installation-source": "dist",
@ -700,7 +700,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@ -720,8 +720,8 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"version": "v1.32.0",
"version_normalized": "1.32.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@ -746,8 +746,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"installation-source": "dist",
@ -782,7 +782,7 @@
"portable"
],
"support": {
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0"
},
"funding": [
{
@ -802,17 +802,17 @@
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"version": "v1.32.0",
"version_normalized": "1.32.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773"
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773",
"reference": "c36586dcf89a12315939e00ec9b4474adcb1d773",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
"shasum": ""
},
"require": {
@ -822,12 +822,12 @@
"suggest": {
"ext-intl": "For best performance"
},
"time": "2024-09-09T11:45:10+00:00",
"time": "2024-09-10T14:38:51+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"installation-source": "dist",
@ -868,7 +868,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0"
},
"funding": [
{
@ -888,8 +888,8 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"version": "v1.32.0",
"version_normalized": "1.32.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@ -911,8 +911,8 @@
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"installation-source": "dist",
@ -952,7 +952,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0"
},
"funding": [
{
@ -972,20 +972,21 @@
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.31.0",
"version_normalized": "1.31.0.0",
"version": "v1.32.0",
"version_normalized": "1.32.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
"reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
@ -994,12 +995,12 @@
"suggest": {
"ext-mbstring": "For best performance"
},
"time": "2024-09-09T11:45:10+00:00",
"time": "2024-12-23T08:48:59+00:00",
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"installation-source": "dist",
@ -1035,7 +1036,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0"
},
"funding": [
{
@ -1055,17 +1056,17 @@
},
{
"name": "symfony/yaml",
"version": "v6.4.18",
"version_normalized": "6.4.18.0",
"version": "v6.4.21",
"version_normalized": "6.4.21.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5"
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"reference": "bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5",
"url": "https://api.github.com/repos/symfony/yaml/zipball/f01987f45676778b474468aa266fe2eda1f2bc7e",
"reference": "f01987f45676778b474468aa266fe2eda1f2bc7e",
"shasum": ""
},
"require": {
@ -1079,7 +1080,7 @@
"require-dev": {
"symfony/console": "^5.4|^6.0|^7.0"
},
"time": "2025-01-07T09:44:41+00:00",
"time": "2025-04-04T09:48:44+00:00",
"bin": [
"Resources/bin/yaml-lint"
],
@ -1110,7 +1111,7 @@
"description": "Loads and dumps YAML files",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/yaml/tree/v6.4.18"
"source": "https://github.com/symfony/yaml/tree/v6.4.21"
},
"funding": [
{

View file

@ -1,8 +1,8 @@
<?php return array(
'root' => array(
'name' => 'getkirby/cms',
'pretty_version' => '4.7.0',
'version' => '4.7.0.0',
'pretty_version' => '4.8.0',
'version' => '4.8.0.0',
'reference' => null,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
@ -47,8 +47,8 @@
'dev_requirement' => false,
),
'getkirby/cms' => array(
'pretty_version' => '4.7.0',
'version' => '4.7.0.0',
'pretty_version' => '4.8.0',
'version' => '4.8.0.0',
'reference' => null,
'type' => 'kirby-cms',
'install_path' => __DIR__ . '/../../',
@ -65,9 +65,9 @@
'dev_requirement' => false,
),
'laminas/laminas-escaper' => array(
'pretty_version' => '2.16.0',
'version' => '2.16.0.0',
'reference' => '9cf1f5317ca65b4fd5c6a3c2855e24a187b288c8',
'pretty_version' => '2.17.0',
'version' => '2.17.0.0',
'reference' => 'df1ef9503299a8e3920079a16263b578eaf7c3ba',
'type' => 'library',
'install_path' => __DIR__ . '/../laminas/laminas-escaper',
'aliases' => array(),
@ -98,9 +98,9 @@
'dev_requirement' => false,
),
'phpmailer/phpmailer' => array(
'pretty_version' => 'v6.9.3',
'version' => '6.9.3.0',
'reference' => '2f5c94fe7493efc213f643c23b1b1c249d40f47e',
'pretty_version' => 'v6.10.0',
'version' => '6.10.0.0',
'reference' => 'bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144',
'type' => 'library',
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
'aliases' => array(),
@ -116,17 +116,17 @@
'dev_requirement' => false,
),
'symfony/deprecation-contracts' => array(
'pretty_version' => 'v3.5.1',
'version' => '3.5.1.0',
'reference' => '74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6',
'pretty_version' => 'v3.6.0',
'version' => '3.6.0.0',
'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-ctype' => array(
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'pretty_version' => 'v1.32.0',
'version' => '1.32.0.0',
'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-ctype',
@ -134,17 +134,17 @@
'dev_requirement' => false,
),
'symfony/polyfill-intl-idn' => array(
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'reference' => 'c36586dcf89a12315939e00ec9b4474adcb1d773',
'pretty_version' => 'v1.32.0',
'version' => '1.32.0.0',
'reference' => '9614ac4d8061dc257ecc64cba1b140873dce8ad3',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
'aliases' => array(),
'dev_requirement' => false,
),
'symfony/polyfill-intl-normalizer' => array(
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'pretty_version' => 'v1.32.0',
'version' => '1.32.0.0',
'reference' => '3833d7255cc303546435cb650316bff708a1c75c',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
@ -152,9 +152,9 @@
'dev_requirement' => false,
),
'symfony/polyfill-mbstring' => array(
'pretty_version' => 'v1.31.0',
'version' => '1.31.0.0',
'reference' => '85181ba99b2345b0ef10ce42ecac37612d9fd341',
'pretty_version' => 'v1.32.0',
'version' => '1.32.0.0',
'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
'aliases' => array(),
@ -167,9 +167,9 @@
),
),
'symfony/yaml' => array(
'pretty_version' => 'v6.4.18',
'version' => '6.4.18.0',
'reference' => 'bf598c9d9bb4a22f495a4e26e4c4fce2f8ecefc5',
'pretty_version' => 'v6.4.21',
'version' => '6.4.21.0',
'reference' => 'f01987f45676778b474468aa266fe2eda1f2bc7e',
'type' => 'library',
'install_path' => __DIR__ . '/../symfony/yaml',
'aliases' => array(),

View file

@ -30,7 +30,7 @@ use const ENT_SUBSTITUTE;
*
* @final
*/
class Escaper
class Escaper implements EscaperInterface
{
/**
* Entity Map mapping Unicode codepoints to any available named HTML entities.
@ -183,24 +183,13 @@ class Escaper
return $this->encoding;
}
/**
* Escape a string for the HTML Body context where there are very few characters
* of special meaning. Internally this will use htmlspecialchars().
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
/** @inheritDoc */
public function escapeHtml(string $string)
{
return htmlspecialchars($string, $this->htmlSpecialCharsFlags, $this->encoding);
}
/**
* Escape a string for the HTML Attribute context. We use an extended set of characters
* to escape that are not covered by htmlspecialchars() to cover cases where an attribute
* might be unquoted or quoted illegally (e.g. backticks are valid quotes for IE).
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
/** @inheritDoc */
public function escapeHtmlAttr(string $string)
{
$string = $this->toUtf8($string);
@ -214,17 +203,7 @@ class Escaper
return $this->fromUtf8($result);
}
/**
* Escape a string for the Javascript context. This does not use json_encode(). An extended
* set of characters are escaped beyond ECMAScript's rules for Javascript literal string
* escaping in order to prevent misinterpretation of Javascript as HTML leading to the
* injection of special characters and entities. The escaping used should be tolerant
* of cases where HTML escaping was not applied on top of Javascript escaping correctly.
* Backslash escaping is not used as it still leaves the escaped character as-is and so
* is not useful in a HTML context.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
/** @inheritDoc */
public function escapeJs(string $string)
{
$string = $this->toUtf8($string);
@ -238,24 +217,13 @@ class Escaper
return $this->fromUtf8($result);
}
/**
* Escape a string for the URI or Parameter contexts. This should not be used to escape
* an entire URI - only a subcomponent being inserted. The function is a simple proxy
* to rawurlencode() which now implements RFC 3986 since PHP 5.3 completely.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
/** @inheritDoc */
public function escapeUrl(string $string)
{
return rawurlencode($string);
}
/**
* Escape a string for the CSS context. CSS escaping can be applied to any string being
* inserted into CSS and escapes everything except alphanumerics.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
/** @inheritDoc */
public function escapeCss(string $string)
{
$string = $this->toUtf8($string);

View file

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Laminas\Escaper;
/**
* Interface for context specific methods for use in secure output escaping
*/
interface EscaperInterface
{
/**
* Escape a string for the HTML Body context where there are very few characters
* of special meaning. Internally this will use htmlspecialchars().
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
public function escapeHtml(string $string);
/**
* Escape a string for the HTML Attribute context. We use an extended set of characters
* to escape that are not covered by htmlspecialchars() to cover cases where an attribute
* might be unquoted or quoted illegally (e.g. backticks are valid quotes for IE).
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
public function escapeHtmlAttr(string $string);
/**
* Escape a string for the Javascript context. This does not use json_encode(). An extended
* set of characters are escaped beyond ECMAScript's rules for Javascript literal string
* escaping in order to prevent misinterpretation of Javascript as HTML leading to the
* injection of special characters and entities. The escaping used should be tolerant
* of cases where HTML escaping was not applied on top of Javascript escaping correctly.
* Backslash escaping is not used as it still leaves the escaped character as-is and so
* is not useful in a HTML context.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
public function escapeJs(string $string);
/**
* Escape a string for the URI or Parameter contexts. This should not be used to escape
* an entire URI - only a subcomponent being inserted. The function is a simple proxy
* to rawurlencode() which now implements RFC 3986 since PHP 5.3 completely.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
public function escapeUrl(string $string);
/**
* Escape a string for the CSS context. CSS escaping can be applied to any string being
* inserted into CSS and escapes everything except alphanumerics.
*
* @return ($string is non-empty-string ? non-empty-string : string)
*/
public function escapeCss(string $string);
}

View file

@ -3,25 +3,32 @@
/**
* Portuguese (European) PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Jonadabe <jonadabe@hotmail.com>
* @author João Vieira <mail@joaovieira.eu>
*/
$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.';
$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.';
$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.';
$PHPMAILER_LANG['authenticate'] = 'Erro SMTP: Falha na autenticação.';
$PHPMAILER_LANG['buggy_php'] = 'A sua versão do PHP tem um bug que pode causar mensagens corrompidas. Para resolver, utilize o envio por SMTP, desative a opção mail.add_x_header no ficheiro php.ini, mude para MacOS ou Linux, ou atualize o PHP para a versão 7.0.17+ ou 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'Erro SMTP: Não foi possível ligar ao servidor SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Erro SMTP: Dados não aceites.';
$PHPMAILER_LANG['empty_message'] = 'A mensagem de e-mail está vazia.';
$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder ao ficheiro: ';
$PHPMAILER_LANG['file_open'] = 'Erro ao abrir o ficheiro: ';
$PHPMAILER_LANG['from_failed'] = 'O envio falhou para o seguinte endereço do remetente: ';
$PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.';
$PHPMAILER_LANG['invalid_address'] = 'Endereço de e-mail inválido: ';
$PHPMAILER_LANG['invalid_header'] = 'Nome ou valor do cabeçalho inválido.';
$PHPMAILER_LANG['invalid_hostentry'] = 'Entrada de host inválida: ';
$PHPMAILER_LANG['invalid_host'] = 'Host inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = 'O cliente de e-mail não é suportado.';
$PHPMAILER_LANG['provide_address'] = 'Deve fornecer pelo menos um endereço de destinatário.';
$PHPMAILER_LANG['recipients_failed'] = 'Erro SMTP: Falha no envio para os seguintes destinatários: ';
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
$PHPMAILER_LANG['smtp_code'] = 'Código SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Informações adicionais SMTP: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Falha na função SMTP connect().';
$PHPMAILER_LANG['smtp_detail'] = 'Detalhes: ';
$PHPMAILER_LANG['smtp_error'] = 'Erro do servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';

View file

@ -580,6 +580,10 @@ class PHPMailer
* May be a callable to inject your own validator, but there are several built-in validators.
* The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option.
*
* If CharSet is UTF8, the validator is left at the default value,
* and you send to addresses that use non-ASCII local parts, then
* PHPMailer automatically changes to the 'eai' validator.
*
* @see PHPMailer::validateAddress()
*
* @var string|callable
@ -659,6 +663,14 @@ class PHPMailer
*/
protected $ReplyToQueue = [];
/**
* Whether the need for SMTPUTF8 has been detected. Set by
* preSend() if necessary.
*
* @var bool
*/
public $UseSMTPUTF8 = false;
/**
* The array of attachments.
*
@ -756,7 +768,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.9.3';
const VERSION = '6.10.0';
/**
* Error severity: message only, continue processing.
@ -1110,19 +1122,22 @@ class PHPMailer
$params = [$kind, $address, $name];
//Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
//Domain is assumed to be whatever is after the last @ symbol in the address
if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
if ('Reply-To' !== $kind) {
if (!array_key_exists($address, $this->RecipientsQueue)) {
$this->RecipientsQueue[$address] = $params;
if ($this->has8bitChars(substr($address, ++$pos))) {
if (static::idnSupported()) {
if ('Reply-To' !== $kind) {
if (!array_key_exists($address, $this->RecipientsQueue)) {
$this->RecipientsQueue[$address] = $params;
return true;
}
} elseif (!array_key_exists($address, $this->ReplyToQueue)) {
$this->ReplyToQueue[$address] = $params;
return true;
}
} elseif (!array_key_exists($address, $this->ReplyToQueue)) {
$this->ReplyToQueue[$address] = $params;
return true;
}
//We have an 8-bit domain, but we are missing the necessary extensions to support it
//Or we are already sending to this address
return false;
}
@ -1160,6 +1175,15 @@ class PHPMailer
*/
protected function addAnAddress($kind, $address, $name = '')
{
if (
self::$validator === 'php' &&
((bool) preg_match('/[\x80-\xFF]/', $address))
) {
//The caller has not altered the validator and is sending to an address
//with UTF-8, so assume that they want UTF-8 support instead of failing
$this->CharSet = self::CHARSET_UTF8;
self::$validator = 'eai';
}
if (!in_array($kind, ['to', 'cc', 'bcc', 'Reply-To'])) {
$error_message = sprintf(
'%s: %s',
@ -1362,6 +1386,7 @@ class PHPMailer
* * `pcre` Use old PCRE implementation;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
* * `eai` Use a pattern similar to the HTML5 spec for 'email' and to firefox, extended to support EAI (RFC6530).
* * `noregex` Don't use a regex: super fast, really dumb.
* Alternatively you may pass in a callable to inject your own validator, for example:
*
@ -1432,6 +1457,24 @@ class PHPMailer
'[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
$address
);
case 'eai':
/*
* This is the pattern used in the HTML5 spec for validation of 'email' type
* form input elements (as above), modified to accept Unicode email addresses.
* This is also more lenient than Firefox' html5 spec, in order to make the regex faster.
* 'eai' is an acronym for Email Address Internationalization.
* This validator is selected automatically if you attempt to use recipient addresses
* that contain Unicode characters in the local part.
*
* @see https://html.spec.whatwg.org/#e-mail-state-(type=email)
* @see https://en.wikipedia.org/wiki/International_email
*/
return (bool) preg_match(
'/^[-\p{L}\p{N}\p{M}.!#$%&\'*+\/=?^_`{|}~]+@[\p{L}\p{N}\p{M}](?:[\p{L}\p{N}\p{M}-]{0,61}' .
'[\p{L}\p{N}\p{M}])?(?:\.[\p{L}\p{N}\p{M}]' .
'(?:[-\p{L}\p{N}\p{M}]{0,61}[\p{L}\p{N}\p{M}])?)*$/usD',
$address
);
case 'php':
default:
return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
@ -1565,9 +1608,26 @@ class PHPMailer
$this->error_count = 0; //Reset errors
$this->mailHeader = '';
//The code below tries to support full use of Unicode,
//while remaining compatible with legacy SMTP servers to
//the greatest degree possible: If the message uses
//Unicode in the local parts of any addresses, it is sent
//using SMTPUTF8. If not, it it sent using
//punycode-encoded domains and plain SMTP.
if (
static::CHARSET_UTF8 === strtolower($this->CharSet) &&
($this->anyAddressHasUnicodeLocalPart($this->RecipientsQueue) ||
$this->anyAddressHasUnicodeLocalPart(array_keys($this->all_recipients)) ||
$this->anyAddressHasUnicodeLocalPart($this->ReplyToQueue) ||
$this->addressHasUnicodeLocalPart($this->From))
) {
$this->UseSMTPUTF8 = true;
}
//Dequeue recipient and Reply-To addresses with IDN
foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
$params[1] = $this->punyencodeAddress($params[1]);
if (!$this->UseSMTPUTF8) {
$params[1] = $this->punyencodeAddress($params[1]);
}
call_user_func_array([$this, 'addAnAddress'], $params);
}
if (count($this->to) + count($this->cc) + count($this->bcc) < 1) {
@ -2058,6 +2118,11 @@ class PHPMailer
if (!$this->smtpConnect($this->SMTPOptions)) {
throw new Exception($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
}
//If we have recipient addresses that need Unicode support,
//but the server doesn't support it, stop here
if ($this->UseSMTPUTF8 && !$this->smtp->getServerExt('SMTPUTF8')) {
throw new Exception($this->lang('no_smtputf8'), self::STOP_CRITICAL);
}
//Sender already validated in preSend()
if ('' === $this->Sender) {
$smtp_from = $this->From;
@ -2159,6 +2224,7 @@ class PHPMailer
$this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp);
$this->smtp->setSMTPUTF8($this->UseSMTPUTF8);
if ($this->Host === null) {
$this->Host = 'localhost';
}
@ -2356,6 +2422,7 @@ class PHPMailer
'smtp_detail' => 'Detail: ',
'smtp_error' => 'SMTP server error: ',
'variable_set' => 'Cannot set or reset variable: ',
'no_smtputf8' => 'Server does not support SMTPUTF8 needed to send to Unicode addresses',
];
if (empty($lang_path)) {
//Calculate an absolute path so it can work if CWD is not here
@ -2870,7 +2937,9 @@ class PHPMailer
$bodyEncoding = $this->Encoding;
$bodyCharSet = $this->CharSet;
//Can we do a 7-bit downgrade?
if (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
if ($this->UseSMTPUTF8) {
$bodyEncoding = static::ENCODING_8BIT;
} elseif (static::ENCODING_8BIT === $bodyEncoding && !$this->has8bitChars($this->Body)) {
$bodyEncoding = static::ENCODING_7BIT;
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$bodyCharSet = static::CHARSET_ASCII;
@ -3507,7 +3576,8 @@ class PHPMailer
/**
* Encode a header value (not including its label) optimally.
* Picks shortest of Q, B, or none. Result includes folding if needed.
* See RFC822 definitions for phrase, comment and text positions.
* See RFC822 definitions for phrase, comment and text positions,
* and RFC2047 for inline encodings.
*
* @param string $str The header value to encode
* @param string $position What context the string will be used in
@ -3516,6 +3586,11 @@ class PHPMailer
*/
public function encodeHeader($str, $position = 'text')
{
$position = strtolower($position);
if ($this->UseSMTPUTF8 && !("comment" === $position)) {
return trim(static::normalizeBreaks($str));
}
$matchcount = 0;
switch (strtolower($position)) {
case 'phrase':
@ -4180,7 +4255,7 @@ class PHPMailer
if ('smtp' === $this->Mailer && null !== $this->smtp) {
$lasterror = $this->smtp->getError();
if (!empty($lasterror['error'])) {
$msg .= $this->lang('smtp_error') . $lasterror['error'];
$msg .= ' ' . $this->lang('smtp_error') . $lasterror['error'];
if (!empty($lasterror['detail'])) {
$msg .= ' ' . $this->lang('smtp_detail') . $lasterror['detail'];
}
@ -4267,6 +4342,45 @@ class PHPMailer
return filter_var('https://' . $host, FILTER_VALIDATE_URL) !== false;
}
/**
* Check whether the supplied address uses Unicode in the local part.
*
* @return bool
*/
protected function addressHasUnicodeLocalPart($address)
{
return (bool) preg_match('/[\x80-\xFF].*@/', $address);
}
/**
* Check whether any of the supplied addresses use Unicode in the local part.
*
* @return bool
*/
protected function anyAddressHasUnicodeLocalPart($addresses)
{
foreach ($addresses as $address) {
if (is_array($address)) {
$address = $address[0];
}
if ($this->addressHasUnicodeLocalPart($address)) {
return true;
}
}
return false;
}
/**
* Check whether the message requires SMTPUTF8 based on what's known so far.
*
* @return bool
*/
public function needsSMTPUTF8()
{
return $this->UseSMTPUTF8;
}
/**
* Get an error message in the current language.
*

View file

@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.9.3';
const VERSION = '6.10.0';
/**
* Default POP3 port number.

View file

@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.9.3';
const VERSION = '6.10.0';
/**
* SMTP line break constant.
@ -159,6 +159,15 @@ class SMTP
*/
public $do_verp = false;
/**
* Whether to use SMTPUTF8.
*
* @see https://www.rfc-editor.org/rfc/rfc6531
*
* @var bool
*/
public $do_smtputf8 = false;
/**
* The timeout value for connection, in seconds.
* Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2.
@ -913,7 +922,15 @@ class SMTP
* $from. Returns true if successful or false otherwise. If True
* the mail transaction is started and then one or more recipient
* commands may be called followed by a data command.
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF>.
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF> and
* two extensions, namely XVERP and SMTPUTF8.
*
* The server's EHLO response is not checked. If use of either
* extensions is enabled even though the server does not support
* that, mail submission will fail.
*
* XVERP is documented at https://www.postfix.org/VERP_README.html
* and SMTPUTF8 is specified in RFC 6531.
*
* @param string $from Source address of this message
*
@ -922,10 +939,11 @@ class SMTP
public function mail($from)
{
$useVerp = ($this->do_verp ? ' XVERP' : '');
$useSmtputf8 = ($this->do_smtputf8 ? ' SMTPUTF8' : '');
return $this->sendCommand(
'MAIL FROM',
'MAIL FROM:<' . $from . '>' . $useVerp,
'MAIL FROM:<' . $from . '>' . $useSmtputf8 . $useVerp,
250
);
}
@ -1364,6 +1382,26 @@ class SMTP
return $this->do_verp;
}
/**
* Enable or disable use of SMTPUTF8.
*
* @param bool $enabled
*/
public function setSMTPUTF8($enabled = false)
{
$this->do_smtputf8 = $enabled;
}
/**
* Get SMTPUTF8 use.
*
* @return bool
*/
public function getSMTPUTF8()
{
return $this->do_smtputf8;
}
/**
* Set error messages and codes.
*

View file

@ -25,7 +25,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
"dev-main": "3.6-dev"
},
"thanks": {
"name": "symfony/contracts",

View file

@ -145,6 +145,10 @@ final class Idn
*/
public static function idn_to_ascii($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = [])
{
if (\PHP_VERSION_ID > 80400 && '' === $domainName) {
throw new \ValueError('idn_to_ascii(): Argument #1 ($domain) cannot be empty');
}
if (self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED);
}
@ -198,6 +202,10 @@ final class Idn
*/
public static function idn_to_utf8($domainName, $options = self::IDNA_DEFAULT, $variant = self::INTL_IDNA_VARIANT_UTS46, &$idna_info = [])
{
if (\PHP_VERSION_ID > 80400 && '' === $domainName) {
throw new \ValueError('idn_to_utf8(): Argument #1 ($domain) cannot be empty');
}
if (self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', \E_USER_DEPRECATED);
}

View file

@ -983,7 +983,7 @@ final class Mbstring
public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string
{
return self::mb_internal_trim('{[%s]+$}D', $string, $characters, $encoding, __FUNCTION__);
return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__);
}
private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string

View file

@ -133,11 +133,11 @@ if (!function_exists('mb_str_pad')) {
}
if (!function_exists('mb_ucfirst')) {
function mb_ucfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); }
}
if (!function_exists('mb_lcfirst')) {
function mb_lcfirst($string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); }
}
if (!function_exists('mb_trim')) {

View file

@ -16,7 +16,8 @@
}
],
"require": {
"php": ">=7.2"
"php": ">=7.2",
"ext-iconv": "*"
},
"provide": {
"ext-mbstring": "*"

View file

@ -1158,7 +1158,18 @@ class Parser
private function lexUnquotedString(int &$cursor): string
{
$offset = $cursor;
$cursor += strcspn($this->currentLine, '[]{},:', $cursor);
while ($cursor < strlen($this->currentLine)) {
if (in_array($this->currentLine[$cursor], ['[', ']', '{', '}', ',', ':'], true)) {
break;
}
if (\in_array($this->currentLine[$cursor], [' ', "\t"], true) && '#' === ($this->currentLine[$cursor + 1] ?? '')) {
break;
}
++$cursor;
}
if ($cursor === $offset) {
throw new ParseException('Malformed unquoted YAML string.');
@ -1235,7 +1246,7 @@ class Parser
$whitespacesConsumed = 0;
do {
$whitespaceOnlyTokenLength = strspn($this->currentLine, ' ', $cursor);
$whitespaceOnlyTokenLength = strspn($this->currentLine, " \t", $cursor);
$whitespacesConsumed += $whitespaceOnlyTokenLength;
$cursor += $whitespaceOnlyTokenLength;

177
package-lock.json generated
View file

@ -4,18 +4,16 @@
"requires": true,
"packages": {
"": {
"name": "julienmonnerie",
"devDependencies": {
"@splidejs/splide": "^4.1.4",
"@symfony/webpack-encore": "^5.0.1",
"autoprefixer": "^10.4.20",
"core-js": "^3.40.0",
"@symfony/webpack-encore": "^5.1.0",
"autoprefixer": "^10.4.21",
"core-js": "^3.43.0",
"postcss-loader": "^8.1.1",
"sass": "^1.83.4",
"sass-loader": "^16.0.4",
"swiped-events": "^1.2.0",
"sass": "^1.89.2",
"sass-loader": "^16.0.5",
"ts-loader": "^9.5.2",
"typescript": "^5.7.3",
"typescript": "^5.8.3",
"webpack-notifier": "^1.15.0"
}
},
@ -2250,9 +2248,9 @@
"dev": true
},
"node_modules/@symfony/webpack-encore": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-5.0.1.tgz",
"integrity": "sha512-2l9ssZCJDMKOXi1iggjn7HEaErdYvITvuheLvtXHAgR2mauV2FiE/pNFS+Bqz2sbj1g4pPcqJIl5AwFE9etOgg==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-5.1.0.tgz",
"integrity": "sha512-uSaRnssJj+ZHH9UcHRGI8kQzFb5hfCiPtBwP15vuKH5hTPGeJjQouDDo4UaPB3LuSYJXudKFiSDAnj/4d2z4aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2284,7 +2282,7 @@
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.9.0",
"@babel/preset-typescript": "^7.0.0",
"@symfony/stimulus-bridge": "^3.0.0",
"@symfony/stimulus-bridge": "^3.0.0 || ^4.0.0",
"@vue/babel-helper-vue-jsx-merge-props": "^1.0.0",
"@vue/babel-plugin-jsx": "^1.0.0",
"@vue/babel-preset-jsx": "^1.0.0",
@ -2872,9 +2870,9 @@
"license": "Python-2.0"
},
"node_modules/autoprefixer": {
"version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
"version": "10.4.21",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
"dev": true,
"funding": [
{
@ -2892,11 +2890,11 @@
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001646",
"browserslist": "^4.24.4",
"caniuse-lite": "^1.0.30001702",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.1",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
},
"bin": {
@ -3014,9 +3012,9 @@
}
},
"node_modules/browserslist": {
"version": "4.24.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz",
"integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==",
"version": "4.25.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
"dev": true,
"funding": [
{
@ -3034,10 +3032,10 @@
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1"
"update-browserslist-db": "^1.1.3"
},
"bin": {
"browserslist": "cli.js"
@ -3077,9 +3075,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001690",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
"integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
"version": "1.0.30001726",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz",
"integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==",
"dev": true,
"funding": [
{
@ -3228,9 +3226,9 @@
"dev": true
},
"node_modules/core-js": {
"version": "3.40.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
"integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
"version": "3.43.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.43.0.tgz",
"integrity": "sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@ -3670,9 +3668,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.75",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz",
"integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==",
"version": "1.5.179",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz",
"integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==",
"dev": true,
"license": "ISC"
},
@ -5851,9 +5849,9 @@
]
},
"node_modules/sass": {
"version": "1.83.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz",
"integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==",
"version": "1.89.2",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -5872,9 +5870,9 @@
}
},
"node_modules/sass-loader": {
"version": "16.0.4",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
"integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==",
"version": "16.0.5",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz",
"integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -6287,13 +6285,6 @@
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/swiped-events": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/swiped-events/-/swiped-events-1.2.0.tgz",
"integrity": "sha512-KRu67z1hb4sPxMdFIF2kaufYHTcWOb8NVLbIl2g5dPWZkEQ6D3wfSIVJ7iXbicTt9cO3e0vARqgx9fITtTZxQw==",
"dev": true,
"license": "MIT"
},
"node_modules/tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@ -6557,9 +6548,9 @@
}
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@ -6615,9 +6606,9 @@
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"dev": true,
"funding": [
{
@ -6636,7 +6627,7 @@
"license": "MIT",
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.0"
"picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
@ -8399,9 +8390,9 @@
"dev": true
},
"@symfony/webpack-encore": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-5.0.1.tgz",
"integrity": "sha512-2l9ssZCJDMKOXi1iggjn7HEaErdYvITvuheLvtXHAgR2mauV2FiE/pNFS+Bqz2sbj1g4pPcqJIl5AwFE9etOgg==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/@symfony/webpack-encore/-/webpack-encore-5.1.0.tgz",
"integrity": "sha512-uSaRnssJj+ZHH9UcHRGI8kQzFb5hfCiPtBwP15vuKH5hTPGeJjQouDDo4UaPB3LuSYJXudKFiSDAnj/4d2z4aQ==",
"dev": true,
"requires": {
"@nuxt/friendly-errors-webpack-plugin": "^2.5.1",
@ -8802,16 +8793,16 @@
"dev": true
},
"autoprefixer": {
"version": "10.4.20",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
"integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
"version": "10.4.21",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
"dev": true,
"requires": {
"browserslist": "^4.23.3",
"caniuse-lite": "^1.0.30001646",
"browserslist": "^4.24.4",
"caniuse-lite": "^1.0.30001702",
"fraction.js": "^4.3.7",
"normalize-range": "^0.1.2",
"picocolors": "^1.0.1",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
}
},
@ -8896,15 +8887,15 @@
}
},
"browserslist": {
"version": "4.24.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz",
"integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==",
"version": "4.25.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
"integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001688",
"electron-to-chromium": "^1.5.73",
"caniuse-lite": "^1.0.30001726",
"electron-to-chromium": "^1.5.173",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.1"
"update-browserslist-db": "^1.1.3"
}
},
"buffer-from": {
@ -8932,9 +8923,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001690",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
"integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
"version": "1.0.30001726",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz",
"integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==",
"dev": true
},
"chalk": {
@ -9040,9 +9031,9 @@
"dev": true
},
"core-js": {
"version": "3.40.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.40.0.tgz",
"integrity": "sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ==",
"version": "3.43.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.43.0.tgz",
"integrity": "sha512-N6wEbTTZSYOY2rYAn85CuvWWkCK6QweMn7/4Nr3w+gDBeBhk/x4EJeY6FPo4QzDoJZxVTv8U7CMvgWk6pOHHqA==",
"dev": true
},
"core-js-compat": {
@ -9305,9 +9296,9 @@
}
},
"electron-to-chromium": {
"version": "1.5.75",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz",
"integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==",
"version": "1.5.179",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.179.tgz",
"integrity": "sha512-UWKi/EbBopgfFsc5k61wFpV7WrnnSlSzW/e2XcBmS6qKYTivZlLtoll5/rdqRTxGglGHkmkW0j0pFNJG10EUIQ==",
"dev": true
},
"emoji-regex": {
@ -10779,9 +10770,9 @@
"dev": true
},
"sass": {
"version": "1.83.4",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz",
"integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==",
"version": "1.89.2",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz",
"integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==",
"dev": true,
"requires": {
"@parcel/watcher": "^2.4.1",
@ -10808,9 +10799,9 @@
}
},
"sass-loader": {
"version": "16.0.4",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
"integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==",
"version": "16.0.5",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz",
"integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
"dev": true,
"requires": {
"neo-async": "^2.6.2"
@ -11054,12 +11045,6 @@
}
}
},
"swiped-events": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/swiped-events/-/swiped-events-1.2.0.tgz",
"integrity": "sha512-KRu67z1hb4sPxMdFIF2kaufYHTcWOb8NVLbIl2g5dPWZkEQ6D3wfSIVJ7iXbicTt9cO3e0vARqgx9fITtTZxQw==",
"dev": true
},
"tapable": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@ -11233,9 +11218,9 @@
}
},
"typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true
},
"unicode-canonical-property-names-ecmascript": {
@ -11271,13 +11256,13 @@
"peer": true
},
"update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
"integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"dev": true,
"requires": {
"escalade": "^3.2.0",
"picocolors": "^1.1.0"
"picocolors": "^1.1.1"
}
},
"uri-js": {

View file

@ -7,15 +7,14 @@
],
"devDependencies": {
"@splidejs/splide": "^4.1.4",
"@symfony/webpack-encore": "^5.0.1",
"autoprefixer": "^10.4.20",
"core-js": "^3.40.0",
"@symfony/webpack-encore": "^5.1.0",
"autoprefixer": "^10.4.21",
"core-js": "^3.43.0",
"postcss-loader": "^8.1.1",
"sass": "^1.83.4",
"sass-loader": "^16.0.4",
"swiped-events": "^1.2.0",
"sass": "^1.89.2",
"sass-loader": "^16.0.5",
"ts-loader": "^9.5.2",
"typescript": "^5.7.3",
"typescript": "^5.8.3",
"webpack-notifier": "^1.15.0"
},
"private": true,

File diff suppressed because one or more lines are too long

View file

@ -4,12 +4,3 @@
* License : MIT
* Copyright: 2022 Naotoshi Fujita
*/
/*!
* swiped-events.js - v@version@
* Pure JavaScript swipe events
* https://github.com/john-doherty/swiped-events
* @inspiration https://stackoverflow.com/questions/16348031/disable-scrolling-when-touch-moving-certain-element
* @author John Doherty <www.johndoherty.info>
* @license MIT
*/