2015-08-18 00:00:26 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Validator\Constraints ;
use Symfony\Component\Validator\Constraint ;
use Symfony\Component\Validator\ConstraintValidator ;
2018-11-23 12:29:20 +00:00
use Symfony\Component\Validator\Exception\InvalidOptionsException ;
2015-08-18 00:00:26 +00:00
use Symfony\Component\Validator\Exception\UnexpectedTypeException ;
/**
* @ author Bernhard Schussek < bschussek @ gmail . com >
*/
class UrlValidator extends ConstraintValidator
{
const PATTERN = ' ~^
( % s ) :// # protocol
2018-11-23 12:29:20 +00:00
(([ \ . \pL\pN - ] +: ) ? ([ \ . \pL\pN - ] + ) @ ) ? # basic auth
2015-08-18 00:00:26 +00:00
(
2018-11-23 12:29:20 +00:00
([ \pL\pN\pS\ - \ . ]) + ( \ . ? ([ \pL\pN ] | xn\ - \ - [ \pL\pN - ] + ) + \ . ? ) # a domain name
2017-02-03 00:28:38 +00:00
| # or
\d { 1 , 3 } \ . \d { 1 , 3 } \ . \d { 1 , 3 } \ . \d { 1 , 3 } # an IP address
| # or
2015-08-18 00:00:26 +00:00
\ [
( ? : ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 6 })( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? ::: ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 5 })( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 4 })( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 1 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 3 })( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 2 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 2 })( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 3 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : )( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 4 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: )( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ])) \ . ){ 3 }( ? : ( ? : 25 [ 0 - 5 ] | ( ? : [ 1 - 9 ] | 1 [ 0 - 9 ] | 2 [ 0 - 4 ]) ? [ 0 - 9 ]))))))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 5 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: )( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) | ( ? : ( ? : ( ? : ( ? : ( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 })) : ){ 0 , 6 }( ? : ( ? : [ 0 - 9 a - f ]{ 1 , 4 }))) ? :: ))))
2017-02-03 00:28:38 +00:00
\ ] # an IPv6 address
2015-08-18 00:00:26 +00:00
)
( : [ 0 - 9 ] + ) ? # a port (optional)
2017-04-13 14:53:35 +00:00
( ? :/ ( ? : [ \pL\pN\ -. _\ ~! $ & \ ' () *+ ,; =:@ ] |%% [ 0 - 9 A - Fa - f ]{ 2 }) * ) * # a path
( ? : \ ? ( ? : [ \pL\pN\ -. _\ ~! $ & \ ' () *+ ,; =:@/ ? ] |%% [ 0 - 9 A - Fa - f ]{ 2 }) * ) ? # a query (optional)
( ? : \ # (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
2015-08-18 00:00:26 +00:00
$ ~ ixu ' ;
/**
* { @ inheritdoc }
*/
public function validate ( $value , Constraint $constraint )
{
if ( ! $constraint instanceof Url ) {
throw new UnexpectedTypeException ( $constraint , __NAMESPACE__ . '\Url' );
}
2018-11-23 12:29:20 +00:00
if ( null === $value || '' === $value ) {
2015-08-18 00:00:26 +00:00
return ;
}
2018-11-23 12:29:20 +00:00
if ( ! is_scalar ( $value ) && ! ( \is_object ( $value ) && method_exists ( $value , '__toString' ))) {
2015-08-18 00:00:26 +00:00
throw new UnexpectedTypeException ( $value , 'string' );
}
$value = ( string ) $value ;
2015-11-17 21:42:33 +00:00
if ( '' === $value ) {
return ;
}
2015-08-18 00:00:26 +00:00
$pattern = sprintf ( static :: PATTERN , implode ( '|' , $constraint -> protocols ));
if ( ! preg_match ( $pattern , $value )) {
2018-11-23 12:29:20 +00:00
$this -> context -> buildViolation ( $constraint -> message )
-> setParameter ( '{{ value }}' , $this -> formatValue ( $value ))
-> setCode ( Url :: INVALID_URL_ERROR )
-> addViolation ();
2015-08-18 00:00:26 +00:00
return ;
}
if ( $constraint -> checkDNS ) {
2018-11-23 12:29:20 +00:00
// backwards compatibility
if ( true === $constraint -> checkDNS ) {
$constraint -> checkDNS = Url :: CHECK_DNS_TYPE_ANY ;
@ 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 );
}
if ( ! \in_array ( $constraint -> checkDNS , array (
Url :: CHECK_DNS_TYPE_ANY ,
Url :: CHECK_DNS_TYPE_A ,
Url :: CHECK_DNS_TYPE_A6 ,
Url :: CHECK_DNS_TYPE_AAAA ,
Url :: CHECK_DNS_TYPE_CNAME ,
Url :: CHECK_DNS_TYPE_MX ,
Url :: CHECK_DNS_TYPE_NAPTR ,
Url :: CHECK_DNS_TYPE_NS ,
Url :: CHECK_DNS_TYPE_PTR ,
Url :: CHECK_DNS_TYPE_SOA ,
Url :: CHECK_DNS_TYPE_SRV ,
Url :: CHECK_DNS_TYPE_TXT ,
), true )) {
throw new InvalidOptionsException ( sprintf ( 'Invalid value for option "checkDNS" in constraint %s' , \get_class ( $constraint )), array ( 'checkDNS' ));
}
2015-08-18 00:00:26 +00:00
$host = parse_url ( $value , PHP_URL_HOST );
2018-11-23 12:29:20 +00:00
if ( ! \is_string ( $host ) || ! checkdnsrr ( $host , $constraint -> checkDNS )) {
$this -> context -> buildViolation ( $constraint -> dnsMessage )
-> setParameter ( '{{ value }}' , $this -> formatValue ( $host ))
-> setCode ( Url :: INVALID_URL_ERROR )
-> addViolation ();
2015-08-18 00:00:26 +00:00
}
}
}
}