Skip to content

Commit 0666885

Browse files
committed
Add the checkTldDns option to the UrlValidator
fixes #39986
1 parent 51f68b1 commit 0666885

File tree

4 files changed

+74
-3
lines changed

4 files changed

+74
-3
lines changed

src/Symfony/Component/Validator/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ CHANGELOG
99
* Deprecate constraint `ExpressionLanguageSyntax`, use `ExpressionSyntax` instead
1010
* Add method `__toString()` to `ConstraintViolationInterface` & `ConstraintViolationListInterface`
1111
* Allow creating constraints with required arguments
12+
* Add the `checkTldDns` option to the `UrlValidator`, to enable/disable DNS check whether the top-level domain has a valid name server
1213

1314
6.0
1415
---

src/Symfony/Component/Validator/Constraints/Url.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,22 @@
2424
class Url extends Constraint
2525
{
2626
public const INVALID_URL_ERROR = '57c2f299-1154-4870-89bb-ef3b1f5ad229';
27+
public const INVALID_TLD_ERROR = '6c079631-e31d-4e2a-9075-65abeb7a0455';
2728

2829
protected const ERROR_NAMES = [
2930
self::INVALID_URL_ERROR => 'INVALID_URL_ERROR',
31+
self::INVALID_TLD_ERROR => 'INVALID_TLD_ERROR',
3032
];
3133

3234
/**
3335
* @deprecated since Symfony 6.1, use const ERROR_NAMES instead
3436
*/
3537
protected static $errorNames = self::ERROR_NAMES;
3638

37-
public $message = 'This value is not a valid URL.';
38-
public $protocols = ['http', 'https'];
39-
public $relativeProtocol = false;
39+
public string $message = 'This value is not a valid URL.';
40+
public array $protocols = ['http', 'https'];
41+
public mixed $relativeProtocol = false;
42+
public bool $checkTldDns = false;
4043
public $normalizer;
4144

4245
public function __construct(

src/Symfony/Component/Validator/Constraints/UrlValidator.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,17 @@ public function validate(mixed $value, Constraint $constraint)
8282

8383
return;
8484
}
85+
86+
if ($constraint->checkTldDns) {
87+
/* check whether TLD has a name server */
88+
$host = parse_url($value, \PHP_URL_HOST);
89+
$tld = substr($host, strrpos($host, '.') + 1);
90+
if (!$tld || !checkdnsrr($tld, 'NS')) {
91+
$this->context->buildViolation($constraint->message)
92+
->setParameter('{{ value }}', $this->formatValue($value))
93+
->setCode(Url::INVALID_TLD_ERROR)
94+
->addViolation();
95+
}
96+
}
8597
}
8698
}

src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,61 @@ public function getValidCustomUrls()
311311
['git://[::1]/'],
312312
];
313313
}
314+
315+
public function getInvalidTldUrls()
316+
{
317+
return [
318+
['http://www.example.com.'],
319+
['http://symfony.tldnotreal/blog/'],
320+
['http://localhost'],
321+
];
322+
}
323+
324+
/**
325+
* @dataProvider getInvalidTldUrls
326+
*/
327+
public function testInvalidTld($url)
328+
{
329+
$constraint = new Url([
330+
'message' => 'myMessage',
331+
'checkTldDns' => true,
332+
]);
333+
334+
$this->validator->validate($url, $constraint);
335+
336+
$this->buildViolation('myMessage')
337+
->setParameter('{{ value }}', '"'.$url.'"')
338+
->setCode(Url::INVALID_TLD_ERROR)
339+
->assertRaised();
340+
}
341+
342+
public function getValidUrlsWithValidTld()
343+
{
344+
return [
345+
['http://a.pl'],
346+
['http://www.example.com'],
347+
['http://www.example.museum'],
348+
['https://example.net:80/'],
349+
['http://www.example.coop/'],
350+
['http://xn--sopaulo-xwa.com.br/'],
351+
['http://العربية.idn.icann.org/'],
352+
['http://☎.com/'],
353+
];
354+
}
355+
356+
/**
357+
* @dataProvider getValidUrlsWithValidTld
358+
*/
359+
public function testValidTld($url)
360+
{
361+
$constraint = new Url([
362+
'checkTldDns' => true,
363+
]);
364+
365+
$this->validator->validate($url, $constraint);
366+
367+
$this->assertNoViolation();
368+
}
314369
}
315370

316371
class EmailProvider

0 commit comments

Comments
 (0)