Skip to content

Commit b415918

Browse files
committed
Fix non-conforming URL validation
Json schema spec says URLs are validated as per RFC-3986, but PHP's FILTER_VALIDATE_URL can't cope with relative path references, which are explicitly allowed. See https://tools.ietf.org/html/rfc3986#section-4.2 for further information.
1 parent ffb35e9 commit b415918

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/JsonSchema/Constraints/FormatConstraint.php

+20-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,26 @@ public function check(&$element, $schema = null, JsonPointer $path = null, $i =
8181

8282
case 'uri':
8383
if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
84-
$this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
84+
// FILTER_VALIDATE_URL does not conform to RFC-3986, and cannot handle relative URLs, but
85+
// the json-schema spec uses RFC-3986, so need a bit of hackery to properly validate them.
86+
// See https://tools.ietf.org/html/rfc3986#section-4.2 for additional information.
87+
if (substr($element, 0, 2) === '//') { // network-path reference
88+
$validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
89+
} elseif (substr($element, 0, 1) === '/') { // absolute-path reference
90+
$validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
91+
} elseif (strlen($element)) { // relative-path reference
92+
$pathParts = explode('/', $element, 2)[0];
93+
if ($pathParts[0] !== '.' && strpos($pathParts, ':') !== false) {
94+
$validURL = null;
95+
} else {
96+
$validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
97+
}
98+
} else {
99+
$validURL = null;
100+
}
101+
if ($validURL === null) {
102+
$this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
103+
}
85104
}
86105
break;
87106

tests/Constraints/FormatTest.php

+4
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ public function getValidFormats()
126126
array('555 320 1212', 'phone'),
127127

128128
array('http://bluebox.org', 'uri'),
129+
array('//bluebox.org', 'uri'),
130+
array('/absolutePathReference/', 'uri'),
131+
array('relativePathReference/', 'uri'),
129132

130133
array('[email protected]', 'email'),
131134

@@ -175,6 +178,7 @@ public function getInvalidFormats()
175178
array('1 123 4424', 'phone'),
176179

177180
array('htt:/bluebox.org', 'uri'),
181+
array('', 'uri'),
178182

179183
array('info@somewhere', 'email'),
180184

0 commit comments

Comments
 (0)