#164 fix comment update

This commit is contained in:
isUnknown 2025-09-23 08:20:17 +02:00
parent 13ac9eb6bb
commit 2e0f28a13f
48 changed files with 3732 additions and 428 deletions

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": "*"

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",

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