Skip to content

Commit 4753467

Browse files
author
Israel J. Carberry
committed
[Validator] Adds support to check specific DNS record type for URL
1 parent e0f6cdf commit 4753467

File tree

4 files changed

+111
-3
lines changed

4 files changed

+111
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ CHANGELOG
66

77
* not setting the `strict` option of the `Choice` constraint to `true` is
88
deprecated and will throw an exception in Symfony 4.0
9+
* setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of constant values and will throw an exception in Symfony 4.0
910

1011
3.3.0
1112
-----

Constraints/Url.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121
*/
2222
class Url extends Constraint
2323
{
24+
const CHECK_DNS_TYPE_ANY = 'ANY';
25+
const CHECK_DNS_TYPE_NONE = false;
26+
const CHECK_DNS_TYPE_A = 'A';
27+
const CHECK_DNS_TYPE_A6 = 'A6';
28+
const CHECK_DNS_TYPE_AAAA = 'AAAA';
29+
const CHECK_DNS_TYPE_CNAME = 'CNAME';
30+
const CHECK_DNS_TYPE_MX = 'MX';
31+
const CHECK_DNS_TYPE_NAPTR = 'NAPTR';
32+
const CHECK_DNS_TYPE_NS = 'NS';
33+
const CHECK_DNS_TYPE_PTR = 'PTR';
34+
const CHECK_DNS_TYPE_SOA = 'SOA';
35+
const CHECK_DNS_TYPE_SRV = 'SRV';
36+
const CHECK_DNS_TYPE_TXT = 'TXT';
37+
2438
const INVALID_URL_ERROR = '57c2f299-1154-4870-89bb-ef3b1f5ad229';
2539

2640
protected static $errorNames = array(
@@ -30,5 +44,5 @@ class Url extends Constraint
3044
public $message = 'This value is not a valid URL.';
3145
public $dnsMessage = 'The host could not be resolved.';
3246
public $protocols = array('http', 'https');
33-
public $checkDNS = false;
47+
public $checkDNS = self::CHECK_DNS_TYPE_NONE;
3448
}

Constraints/UrlValidator.php

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Validator\Constraint;
1515
use Symfony\Component\Validator\ConstraintValidator;
16+
use Symfony\Component\Validator\Exception\InvalidOptionsException;
1617
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
1718

1819
/**
@@ -72,9 +73,32 @@ public function validate($value, Constraint $constraint)
7273
}
7374

7475
if ($constraint->checkDNS) {
76+
// backwards compatibility
77+
if ($constraint->checkDNS === true) {
78+
$constraint->checkDNS = Url::CHECK_DNS_TYPE_ANY;
79+
@trigger_error(sprintf('Use of the boolean TRUE for the "checkDNS" option in %s is deprecated. Use Url::CHECK_DNS_TYPE_ANY instead.', Url::class), E_USER_DEPRECATED);
80+
}
81+
82+
if (!in_array($constraint->checkDNS, array(
83+
Url::CHECK_DNS_TYPE_ANY,
84+
Url::CHECK_DNS_TYPE_A,
85+
Url::CHECK_DNS_TYPE_A6,
86+
Url::CHECK_DNS_TYPE_AAAA,
87+
Url::CHECK_DNS_TYPE_CNAME,
88+
Url::CHECK_DNS_TYPE_MX,
89+
Url::CHECK_DNS_TYPE_NAPTR,
90+
Url::CHECK_DNS_TYPE_NS,
91+
Url::CHECK_DNS_TYPE_PTR,
92+
Url::CHECK_DNS_TYPE_SOA,
93+
Url::CHECK_DNS_TYPE_SRV,
94+
Url::CHECK_DNS_TYPE_TXT,
95+
))) {
96+
throw new InvalidOptionsException(sprintf('Invalid value for option "checkDNS" in constraint %s', get_class($constraint)), array('checkDNS'));
97+
}
98+
7599
$host = parse_url($value, PHP_URL_HOST);
76100

77-
if (!is_string($host) || !checkdnsrr($host, 'ANY')) {
101+
if (!is_string($host) || !checkdnsrr($host, $constraint->checkDNS)) {
78102
$this->context->buildViolation($constraint->dnsMessage)
79103
->setParameter('{{ value }}', $this->formatValue($host))
80104
->setCode(Url::INVALID_URL_ERROR)

Tests/Constraints/UrlValidatorTest.php

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public function testCheckDns($violation)
203203
DnsMock::withMockedHosts(array('example.com' => array(array('type' => $violation ? '' : 'A'))));
204204

205205
$constraint = new Url(array(
206-
'checkDNS' => true,
206+
'checkDNS' => 'ANY',
207207
'dnsMessage' => 'myMessage',
208208
));
209209

@@ -223,6 +223,75 @@ public function getCheckDns()
223223
{
224224
return array(array(true), array(false));
225225
}
226+
227+
/**
228+
* @dataProvider getCheckDnsTypes
229+
* @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
230+
*/
231+
public function testCheckDnsByType($type)
232+
{
233+
DnsMock::withMockedHosts(array('example.com' => array(array('type' => $type))));
234+
235+
$constraint = new Url(array(
236+
'checkDNS' => $type,
237+
'dnsMessage' => 'myMessage',
238+
));
239+
240+
$this->validator->validate('http://example.com', $constraint);
241+
242+
$this->assertNoViolation();
243+
}
244+
245+
public function getCheckDnsTypes()
246+
{
247+
return array(
248+
array('ANY'),
249+
array('A'),
250+
array('A6'),
251+
array('AAAA'),
252+
array('CNAME'),
253+
array('MX'),
254+
array('NAPTR'),
255+
array('NS'),
256+
array('PTR'),
257+
array('SOA'),
258+
array('SRV'),
259+
array('TXT'),
260+
);
261+
}
262+
263+
/**
264+
* @group legacy
265+
*/
266+
public function testCheckDnsWithBoolean()
267+
{
268+
DnsMock::withMockedHosts(array('example.com' => array(array('type' => 'A'))));
269+
270+
$constraint = new Url(array(
271+
'checkDNS' => true,
272+
'dnsMessage' => 'myMessage',
273+
));
274+
275+
$this->validator->validate('http://example.com', $constraint);
276+
277+
$this->assertNoViolation();
278+
}
279+
280+
/**
281+
* @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException
282+
* @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
283+
*/
284+
public function testCheckDnsWithInvalidType()
285+
{
286+
DnsMock::withMockedHosts(array('example.com' => array(array('type' => 'A'))));
287+
288+
$constraint = new Url(array(
289+
'checkDNS' => 'BOGUS',
290+
'dnsMessage' => 'myMessage',
291+
));
292+
293+
$this->validator->validate('http://example.com', $constraint);
294+
}
226295
}
227296

228297
class EmailProvider

0 commit comments

Comments
 (0)