fix: Variablenwerte für Links/Bilder lehnen //host, /\host und Steuerzeichen ab
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
5064409f9a
commit
c6daae131d
@@ -27,7 +27,10 @@ final class VariableValue
|
|||||||
/** Control characters except the line feed. */
|
/** Control characters except the line feed. */
|
||||||
private const CONTROL = '/[\x00-\x09\x0B-\x1F\x7F]/';
|
private const CONTROL = '/[\x00-\x09\x0B-\x1F\x7F]/';
|
||||||
|
|
||||||
private const URL = '/^(?:https?:\/\/[^\s<>"]+|\/[^\s<>"]*|mailto:[^\s<>"]+|tel:[^\s<>"]+)$/iD';
|
/** Every control character: Divi's esc_url_raw strips them, so the read-back would differ. */
|
||||||
|
private const URL_CONTROL = '/[\x00-\x1F\x7F]/';
|
||||||
|
|
||||||
|
private const URL = '/^(?:https?:\/\/[^\s<>"]+|\/(?![\/\\\\])[^\s<>"]*|mailto:[^\s<>"]+|tel:[^\s<>"]+)$/iD';
|
||||||
|
|
||||||
private const WEB_URL = '/^https?:\/\/[^\s<>"]+$/iD';
|
private const WEB_URL = '/^https?:\/\/[^\s<>"]+$/iD';
|
||||||
|
|
||||||
@@ -74,7 +77,8 @@ final class VariableValue
|
|||||||
|
|
||||||
private static function links(string $value): ?string
|
private static function links(string $value): ?string
|
||||||
{
|
{
|
||||||
if (mb_strlen($value) > self::URL_MAX || preg_match(self::URL, $value) !== 1) {
|
if (mb_strlen($value) > self::URL_MAX || preg_match(self::URL, $value) !== 1
|
||||||
|
|| preg_match(self::URL_CONTROL, $value) === 1) {
|
||||||
return 'Link: eine http(s)://- oder /-URL, mailto: oder tel: mit höchstens 2000 Zeichen.';
|
return 'Link: eine http(s)://- oder /-URL, mailto: oder tel: mit höchstens 2000 Zeichen.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +88,8 @@ final class VariableValue
|
|||||||
private static function images(string $value): ?string
|
private static function images(string $value): ?string
|
||||||
{
|
{
|
||||||
$valid = preg_match('/^\d+$/D', $value) === 1
|
$valid = preg_match('/^\d+$/D', $value) === 1
|
||||||
|| (mb_strlen($value) <= self::URL_MAX && preg_match(self::WEB_URL, $value) === 1);
|
|| (mb_strlen($value) <= self::URL_MAX && preg_match(self::WEB_URL, $value) === 1
|
||||||
|
&& preg_match(self::URL_CONTROL, $value) !== 1);
|
||||||
|
|
||||||
return $valid ? null : 'Bild: eine Anhang-ID (Ziffern) oder eine http(s)://-URL mit höchstens 2000 Zeichen.';
|
return $valid ? null : 'Bild: eine Anhang-ID (Ziffern) oder eine http(s)://-URL mit höchstens 2000 Zeichen.';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ final class VariableValueTest extends TestCase
|
|||||||
'links relative without slash' => ['links', 'kontakt/'],
|
'links relative without slash' => ['links', 'kontakt/'],
|
||||||
'links with space' => ['links', 'https://example.com/a b'],
|
'links with space' => ['links', 'https://example.com/a b'],
|
||||||
'links mailto empty' => ['links', 'mailto:'],
|
'links mailto empty' => ['links', 'mailto:'],
|
||||||
|
'links protocol-relative' => ['links', '//evil.example/x'],
|
||||||
|
'links backslash host' => ['links', '/\\evil.example/x'],
|
||||||
|
'links control character' => ['links', "https://example.com/a\x01b"],
|
||||||
|
'links delete character' => ['links', "/kontakt\x7F"],
|
||||||
|
'images control character' => ['images', "https://example.com/a\x00.jpg"],
|
||||||
'links too long' => ['links', 'https://example.com/' . str_repeat('a', 2000)],
|
'links too long' => ['links', 'https://example.com/' . str_repeat('a', 2000)],
|
||||||
'images negative' => ['images', '-5'],
|
'images negative' => ['images', '-5'],
|
||||||
'images relative path' => ['images', '/wp-content/a.jpg'],
|
'images relative path' => ['images', '/wp-content/a.jpg'],
|
||||||
|
|||||||
Reference in New Issue
Block a user