Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\Component\Utility;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Utility\UrlHelper;
|
Chris@0
|
6 use PHPUnit\Framework\TestCase;
|
Chris@0
|
7
|
Chris@0
|
8 /**
|
Chris@0
|
9 * @group Utility
|
Chris@0
|
10 *
|
Chris@0
|
11 * @coversDefaultClass \Drupal\Component\Utility\UrlHelper
|
Chris@0
|
12 */
|
Chris@0
|
13 class UrlHelperTest extends TestCase {
|
Chris@0
|
14
|
Chris@0
|
15 /**
|
Chris@0
|
16 * Provides test data for testBuildQuery().
|
Chris@0
|
17 *
|
Chris@0
|
18 * @return array
|
Chris@0
|
19 */
|
Chris@0
|
20 public function providerTestBuildQuery() {
|
Chris@0
|
21 return [
|
Chris@0
|
22 [['a' => ' &#//+%20@۞'], 'a=%20%26%23//%2B%2520%40%DB%9E', 'Value was properly encoded.'],
|
Chris@0
|
23 [[' &#//+%20@۞' => 'a'], '%20%26%23%2F%2F%2B%2520%40%DB%9E=a', 'Key was properly encoded.'],
|
Chris@0
|
24 [['a' => '1', 'b' => '2', 'c' => '3'], 'a=1&b=2&c=3', 'Multiple values were properly concatenated.'],
|
Chris@0
|
25 [['a' => ['b' => '2', 'c' => '3'], 'd' => 'foo'], 'a%5Bb%5D=2&a%5Bc%5D=3&d=foo', 'Nested array was properly encoded.'],
|
Chris@0
|
26 [['foo' => NULL], 'foo', 'Simple parameters are properly added.'],
|
Chris@0
|
27 ];
|
Chris@0
|
28 }
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * Tests query building.
|
Chris@0
|
32 *
|
Chris@0
|
33 * @dataProvider providerTestBuildQuery
|
Chris@0
|
34 * @covers ::buildQuery
|
Chris@0
|
35 *
|
Chris@0
|
36 * @param array $query
|
Chris@0
|
37 * The array of query parameters.
|
Chris@0
|
38 * @param string $expected
|
Chris@0
|
39 * The expected query string.
|
Chris@0
|
40 * @param string $message
|
Chris@0
|
41 * The assertion message.
|
Chris@0
|
42 */
|
Chris@0
|
43 public function testBuildQuery($query, $expected, $message) {
|
Chris@0
|
44 $this->assertEquals(UrlHelper::buildQuery($query), $expected, $message);
|
Chris@0
|
45 }
|
Chris@0
|
46
|
Chris@0
|
47 /**
|
Chris@0
|
48 * Data provider for testValidAbsolute().
|
Chris@0
|
49 *
|
Chris@0
|
50 * @return array
|
Chris@0
|
51 */
|
Chris@0
|
52 public function providerTestValidAbsoluteData() {
|
Chris@0
|
53 $urls = [
|
Chris@0
|
54 'example.com',
|
Chris@0
|
55 'www.example.com',
|
Chris@0
|
56 'ex-ample.com',
|
Chris@0
|
57 '3xampl3.com',
|
Chris@0
|
58 'example.com/parenthesis',
|
Chris@0
|
59 'example.com/index.html#pagetop',
|
Chris@0
|
60 'example.com:8080',
|
Chris@0
|
61 'subdomain.example.com',
|
Chris@0
|
62 'example.com/index.php/node',
|
Chris@0
|
63 'example.com/index.php/node?param=false',
|
Chris@0
|
64 'user@www.example.com',
|
Chris@0
|
65 'user:pass@www.example.com:8080/login.php?do=login&style=%23#pagetop',
|
Chris@0
|
66 '127.0.0.1',
|
Chris@0
|
67 'example.org?',
|
Chris@0
|
68 'john%20doe:secret:foo@example.org/',
|
Chris@0
|
69 'example.org/~,$\'*;',
|
Chris@0
|
70 'caf%C3%A9.example.org',
|
Chris@0
|
71 '[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html',
|
Chris@0
|
72 ];
|
Chris@0
|
73
|
Chris@0
|
74 return $this->dataEnhanceWithScheme($urls);
|
Chris@0
|
75 }
|
Chris@0
|
76
|
Chris@0
|
77 /**
|
Chris@0
|
78 * Tests valid absolute URLs.
|
Chris@0
|
79 *
|
Chris@0
|
80 * @dataProvider providerTestValidAbsoluteData
|
Chris@0
|
81 * @covers ::isValid
|
Chris@0
|
82 *
|
Chris@0
|
83 * @param string $url
|
Chris@0
|
84 * The url to test.
|
Chris@0
|
85 * @param string $scheme
|
Chris@0
|
86 * The scheme to test.
|
Chris@0
|
87 */
|
Chris@0
|
88 public function testValidAbsolute($url, $scheme) {
|
Chris@0
|
89 $test_url = $scheme . '://' . $url;
|
Chris@0
|
90 $valid_url = UrlHelper::isValid($test_url, TRUE);
|
Chris@0
|
91 $this->assertTrue($valid_url, $test_url . ' is a valid URL.');
|
Chris@0
|
92 }
|
Chris@0
|
93
|
Chris@0
|
94 /**
|
Chris@0
|
95 * Provides data for testInvalidAbsolute().
|
Chris@0
|
96 *
|
Chris@0
|
97 * @return array
|
Chris@0
|
98 */
|
Chris@0
|
99 public function providerTestInvalidAbsolute() {
|
Chris@0
|
100 $data = [
|
Chris@0
|
101 '',
|
Chris@0
|
102 'ex!ample.com',
|
Chris@0
|
103 'ex%ample.com',
|
Chris@0
|
104 ];
|
Chris@0
|
105 return $this->dataEnhanceWithScheme($data);
|
Chris@0
|
106 }
|
Chris@0
|
107
|
Chris@0
|
108 /**
|
Chris@0
|
109 * Tests invalid absolute URLs.
|
Chris@0
|
110 *
|
Chris@0
|
111 * @dataProvider providerTestInvalidAbsolute
|
Chris@0
|
112 * @covers ::isValid
|
Chris@0
|
113 *
|
Chris@0
|
114 * @param string $url
|
Chris@0
|
115 * The url to test.
|
Chris@0
|
116 * @param string $scheme
|
Chris@0
|
117 * The scheme to test.
|
Chris@0
|
118 */
|
Chris@0
|
119 public function testInvalidAbsolute($url, $scheme) {
|
Chris@0
|
120 $test_url = $scheme . '://' . $url;
|
Chris@0
|
121 $valid_url = UrlHelper::isValid($test_url, TRUE);
|
Chris@0
|
122 $this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.');
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 /**
|
Chris@0
|
126 * Provides data for testValidRelative().
|
Chris@0
|
127 *
|
Chris@0
|
128 * @return array
|
Chris@0
|
129 */
|
Chris@0
|
130 public function providerTestValidRelativeData() {
|
Chris@0
|
131 $data = [
|
Chris@0
|
132 'paren(the)sis',
|
Chris@0
|
133 'index.html#pagetop',
|
Chris@0
|
134 'index.php/node',
|
Chris@0
|
135 'index.php/node?param=false',
|
Chris@0
|
136 'login.php?do=login&style=%23#pagetop',
|
Chris@0
|
137 ];
|
Chris@0
|
138
|
Chris@0
|
139 return $this->dataEnhanceWithPrefix($data);
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142 /**
|
Chris@0
|
143 * Tests valid relative URLs.
|
Chris@0
|
144 *
|
Chris@0
|
145 * @dataProvider providerTestValidRelativeData
|
Chris@0
|
146 * @covers ::isValid
|
Chris@0
|
147 *
|
Chris@0
|
148 * @param string $url
|
Chris@0
|
149 * The url to test.
|
Chris@0
|
150 * @param string $prefix
|
Chris@0
|
151 * The prefix to test.
|
Chris@0
|
152 */
|
Chris@0
|
153 public function testValidRelative($url, $prefix) {
|
Chris@0
|
154 $test_url = $prefix . $url;
|
Chris@0
|
155 $valid_url = UrlHelper::isValid($test_url);
|
Chris@0
|
156 $this->assertTrue($valid_url, $test_url . ' is a valid URL.');
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 /**
|
Chris@0
|
160 * Provides data for testInvalidRelative().
|
Chris@0
|
161 *
|
Chris@0
|
162 * @return array
|
Chris@0
|
163 */
|
Chris@0
|
164 public function providerTestInvalidRelativeData() {
|
Chris@0
|
165 $data = [
|
Chris@0
|
166 'ex^mple',
|
Chris@0
|
167 'example<>',
|
Chris@0
|
168 'ex%ample',
|
Chris@0
|
169 ];
|
Chris@0
|
170 return $this->dataEnhanceWithPrefix($data);
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 /**
|
Chris@0
|
174 * Tests invalid relative URLs.
|
Chris@0
|
175 *
|
Chris@0
|
176 * @dataProvider providerTestInvalidRelativeData
|
Chris@0
|
177 * @covers ::isValid
|
Chris@0
|
178 *
|
Chris@0
|
179 * @param string $url
|
Chris@0
|
180 * The url to test.
|
Chris@0
|
181 * @param string $prefix
|
Chris@0
|
182 * The prefix to test.
|
Chris@0
|
183 */
|
Chris@0
|
184 public function testInvalidRelative($url, $prefix) {
|
Chris@0
|
185 $test_url = $prefix . $url;
|
Chris@0
|
186 $valid_url = UrlHelper::isValid($test_url);
|
Chris@0
|
187 $this->assertFalse($valid_url, $test_url . ' is NOT a valid URL.');
|
Chris@0
|
188 }
|
Chris@0
|
189
|
Chris@0
|
190 /**
|
Chris@0
|
191 * Tests query filtering.
|
Chris@0
|
192 *
|
Chris@0
|
193 * @dataProvider providerTestFilterQueryParameters
|
Chris@0
|
194 * @covers ::filterQueryParameters
|
Chris@0
|
195 *
|
Chris@0
|
196 * @param array $query
|
Chris@0
|
197 * The array of query parameters.
|
Chris@0
|
198 * @param array $exclude
|
Chris@0
|
199 * A list of $query array keys to remove. Use "parent[child]" to exclude
|
Chris@0
|
200 * nested items.
|
Chris@0
|
201 * @param array $expected
|
Chris@0
|
202 * An array containing query parameters.
|
Chris@0
|
203 */
|
Chris@0
|
204 public function testFilterQueryParameters($query, $exclude, $expected) {
|
Chris@0
|
205 $filtered = UrlHelper::filterQueryParameters($query, $exclude);
|
Chris@0
|
206 $this->assertEquals($expected, $filtered, 'The query was not properly filtered.');
|
Chris@0
|
207 }
|
Chris@0
|
208
|
Chris@0
|
209 /**
|
Chris@0
|
210 * Provides data to self::testFilterQueryParameters().
|
Chris@0
|
211 *
|
Chris@0
|
212 * @return array
|
Chris@0
|
213 */
|
Chris@0
|
214 public static function providerTestFilterQueryParameters() {
|
Chris@0
|
215 return [
|
Chris@0
|
216 // Test without an exclude filter.
|
Chris@0
|
217 [
|
Chris@0
|
218 'query' => ['a' => ['b' => 'c']],
|
Chris@0
|
219 'exclude' => [],
|
Chris@0
|
220 'expected' => ['a' => ['b' => 'c']],
|
Chris@0
|
221 ],
|
Chris@0
|
222 // Exclude the 'b' element.
|
Chris@0
|
223 [
|
Chris@0
|
224 'query' => ['a' => ['b' => 'c', 'd' => 'e']],
|
Chris@0
|
225 'exclude' => ['a[b]'],
|
Chris@0
|
226 'expected' => ['a' => ['d' => 'e']],
|
Chris@0
|
227 ],
|
Chris@0
|
228 ];
|
Chris@0
|
229 }
|
Chris@0
|
230
|
Chris@0
|
231 /**
|
Chris@0
|
232 * Tests url parsing.
|
Chris@0
|
233 *
|
Chris@0
|
234 * @dataProvider providerTestParse
|
Chris@0
|
235 * @covers ::parse
|
Chris@0
|
236 *
|
Chris@0
|
237 * @param string $url
|
Chris@0
|
238 * URL to test.
|
Chris@0
|
239 * @param array $expected
|
Chris@0
|
240 * Associative array with expected parameters.
|
Chris@0
|
241 */
|
Chris@0
|
242 public function testParse($url, $expected) {
|
Chris@0
|
243 $parsed = UrlHelper::parse($url);
|
Chris@0
|
244 $this->assertEquals($expected, $parsed, 'The URL was not properly parsed.');
|
Chris@0
|
245 }
|
Chris@0
|
246
|
Chris@0
|
247 /**
|
Chris@0
|
248 * Provides data for self::testParse().
|
Chris@0
|
249 *
|
Chris@0
|
250 * @return array
|
Chris@0
|
251 */
|
Chris@0
|
252 public static function providerTestParse() {
|
Chris@0
|
253 return [
|
Chris@0
|
254 [
|
Chris@0
|
255 'http://www.example.com/my/path',
|
Chris@0
|
256 [
|
Chris@0
|
257 'path' => 'http://www.example.com/my/path',
|
Chris@0
|
258 'query' => [],
|
Chris@0
|
259 'fragment' => '',
|
Chris@0
|
260 ],
|
Chris@0
|
261 ],
|
Chris@0
|
262 [
|
Chris@0
|
263 'http://www.example.com/my/path?destination=home#footer',
|
Chris@0
|
264 [
|
Chris@0
|
265 'path' => 'http://www.example.com/my/path',
|
Chris@0
|
266 'query' => [
|
Chris@0
|
267 'destination' => 'home',
|
Chris@0
|
268 ],
|
Chris@0
|
269 'fragment' => 'footer',
|
Chris@0
|
270 ],
|
Chris@0
|
271 ],
|
Chris@0
|
272 'absolute fragment, no query' => [
|
Chris@0
|
273 'http://www.example.com/my/path#footer',
|
Chris@0
|
274 [
|
Chris@0
|
275 'path' => 'http://www.example.com/my/path',
|
Chris@0
|
276 'query' => [],
|
Chris@0
|
277 'fragment' => 'footer',
|
Chris@0
|
278 ],
|
Chris@0
|
279 ],
|
Chris@0
|
280 [
|
Chris@0
|
281 'http://',
|
Chris@0
|
282 [
|
Chris@0
|
283 'path' => '',
|
Chris@0
|
284 'query' => [],
|
Chris@0
|
285 'fragment' => '',
|
Chris@0
|
286 ],
|
Chris@0
|
287 ],
|
Chris@0
|
288 [
|
Chris@0
|
289 'https://',
|
Chris@0
|
290 [
|
Chris@0
|
291 'path' => '',
|
Chris@0
|
292 'query' => [],
|
Chris@0
|
293 'fragment' => '',
|
Chris@0
|
294 ],
|
Chris@0
|
295 ],
|
Chris@0
|
296 [
|
Chris@0
|
297 '/my/path?destination=home#footer',
|
Chris@0
|
298 [
|
Chris@0
|
299 'path' => '/my/path',
|
Chris@0
|
300 'query' => [
|
Chris@0
|
301 'destination' => 'home',
|
Chris@0
|
302 ],
|
Chris@0
|
303 'fragment' => 'footer',
|
Chris@0
|
304 ],
|
Chris@0
|
305 ],
|
Chris@0
|
306 'relative fragment, no query' => [
|
Chris@0
|
307 '/my/path#footer',
|
Chris@0
|
308 [
|
Chris@0
|
309 'path' => '/my/path',
|
Chris@0
|
310 'query' => [],
|
Chris@0
|
311 'fragment' => 'footer',
|
Chris@0
|
312 ],
|
Chris@0
|
313 ],
|
Chris@0
|
314 ];
|
Chris@0
|
315 }
|
Chris@0
|
316
|
Chris@0
|
317 /**
|
Chris@0
|
318 * Tests path encoding.
|
Chris@0
|
319 *
|
Chris@0
|
320 * @dataProvider providerTestEncodePath
|
Chris@0
|
321 * @covers ::encodePath
|
Chris@0
|
322 *
|
Chris@0
|
323 * @param string $path
|
Chris@0
|
324 * A path to encode.
|
Chris@0
|
325 * @param string $expected
|
Chris@0
|
326 * The expected encoded path.
|
Chris@0
|
327 */
|
Chris@0
|
328 public function testEncodePath($path, $expected) {
|
Chris@0
|
329 $encoded = UrlHelper::encodePath($path);
|
Chris@0
|
330 $this->assertEquals($expected, $encoded);
|
Chris@0
|
331 }
|
Chris@0
|
332
|
Chris@0
|
333 /**
|
Chris@0
|
334 * Provides data for self::testEncodePath().
|
Chris@0
|
335 *
|
Chris@0
|
336 * @return array
|
Chris@0
|
337 */
|
Chris@0
|
338 public static function providerTestEncodePath() {
|
Chris@0
|
339 return [
|
Chris@0
|
340 ['unencoded path with spaces', 'unencoded%20path%20with%20spaces'],
|
Chris@0
|
341 ['slashes/should/be/preserved', 'slashes/should/be/preserved'],
|
Chris@0
|
342 ];
|
Chris@0
|
343 }
|
Chris@0
|
344
|
Chris@0
|
345 /**
|
Chris@0
|
346 * Tests external versus internal paths.
|
Chris@0
|
347 *
|
Chris@0
|
348 * @dataProvider providerTestIsExternal
|
Chris@0
|
349 * @covers ::isExternal
|
Chris@0
|
350 *
|
Chris@0
|
351 * @param string $path
|
Chris@0
|
352 * URL or path to test.
|
Chris@0
|
353 * @param bool $expected
|
Chris@0
|
354 * Expected result.
|
Chris@0
|
355 */
|
Chris@0
|
356 public function testIsExternal($path, $expected) {
|
Chris@0
|
357 $isExternal = UrlHelper::isExternal($path);
|
Chris@0
|
358 $this->assertEquals($expected, $isExternal);
|
Chris@0
|
359 }
|
Chris@0
|
360
|
Chris@0
|
361 /**
|
Chris@0
|
362 * Provides data for self::testIsExternal().
|
Chris@0
|
363 *
|
Chris@0
|
364 * @return array
|
Chris@0
|
365 */
|
Chris@0
|
366 public static function providerTestIsExternal() {
|
Chris@0
|
367 return [
|
Chris@0
|
368 ['/internal/path', FALSE],
|
Chris@0
|
369 ['https://example.com/external/path', TRUE],
|
Chris@0
|
370 ['javascript://fake-external-path', FALSE],
|
Chris@0
|
371 // External URL without an explicit protocol.
|
Chris@0
|
372 ['//www.drupal.org/foo/bar?foo=bar&bar=baz&baz#foo', TRUE],
|
Chris@0
|
373 // Internal URL starting with a slash.
|
Chris@0
|
374 ['/www.drupal.org', FALSE],
|
Chris@0
|
375 // Simple external URLs.
|
Chris@0
|
376 ['http://example.com', TRUE],
|
Chris@0
|
377 ['https://example.com', TRUE],
|
Chris@0
|
378 ['http://drupal.org/foo/bar?foo=bar&bar=baz&baz#foo', TRUE],
|
Chris@0
|
379 ['//drupal.org', TRUE],
|
Chris@0
|
380 // Some browsers ignore or strip leading control characters.
|
Chris@0
|
381 ["\x00//www.example.com", TRUE],
|
Chris@0
|
382 ["\x08//www.example.com", TRUE],
|
Chris@0
|
383 ["\x1F//www.example.com", TRUE],
|
Chris@0
|
384 ["\n//www.example.com", TRUE],
|
Chris@0
|
385 // JSON supports decoding directly from UTF-8 code points.
|
Chris@0
|
386 [json_decode('"\u00AD"') . "//www.example.com", TRUE],
|
Chris@0
|
387 [json_decode('"\u200E"') . "//www.example.com", TRUE],
|
Chris@0
|
388 [json_decode('"\uE0020"') . "//www.example.com", TRUE],
|
Chris@0
|
389 [json_decode('"\uE000"') . "//www.example.com", TRUE],
|
Chris@0
|
390 // Backslashes should be normalized to forward.
|
Chris@0
|
391 ['\\\\example.com', TRUE],
|
Chris@0
|
392 // Local URLs.
|
Chris@0
|
393 ['node', FALSE],
|
Chris@0
|
394 ['/system/ajax', FALSE],
|
Chris@0
|
395 ['?q=foo:bar', FALSE],
|
Chris@0
|
396 ['node/edit:me', FALSE],
|
Chris@0
|
397 ['/drupal.org', FALSE],
|
Chris@0
|
398 ['<front>', FALSE],
|
Chris@0
|
399 ];
|
Chris@0
|
400 }
|
Chris@0
|
401
|
Chris@0
|
402 /**
|
Chris@0
|
403 * Tests bad protocol filtering and escaping.
|
Chris@0
|
404 *
|
Chris@0
|
405 * @dataProvider providerTestFilterBadProtocol
|
Chris@0
|
406 * @covers ::setAllowedProtocols
|
Chris@0
|
407 * @covers ::filterBadProtocol
|
Chris@0
|
408 *
|
Chris@0
|
409 * @param string $uri
|
Chris@0
|
410 * Protocol URI.
|
Chris@0
|
411 * @param string $expected
|
Chris@0
|
412 * Expected escaped value.
|
Chris@0
|
413 * @param array $protocols
|
Chris@0
|
414 * Protocols to allow.
|
Chris@0
|
415 */
|
Chris@0
|
416 public function testFilterBadProtocol($uri, $expected, $protocols) {
|
Chris@0
|
417 UrlHelper::setAllowedProtocols($protocols);
|
Chris@0
|
418 $this->assertEquals($expected, UrlHelper::filterBadProtocol($uri));
|
Chris@0
|
419 // Multiple calls to UrlHelper::filterBadProtocol() do not cause double
|
Chris@0
|
420 // escaping.
|
Chris@0
|
421 $this->assertEquals($expected, UrlHelper::filterBadProtocol(UrlHelper::filterBadProtocol($uri)));
|
Chris@0
|
422 }
|
Chris@0
|
423
|
Chris@0
|
424 /**
|
Chris@0
|
425 * Provides data for self::testTestFilterBadProtocol().
|
Chris@0
|
426 *
|
Chris@0
|
427 * @return array
|
Chris@0
|
428 */
|
Chris@0
|
429 public static function providerTestFilterBadProtocol() {
|
Chris@0
|
430 return [
|
Chris@0
|
431 ['javascript://example.com?foo&bar', '//example.com?foo&bar', ['http', 'https']],
|
Chris@0
|
432 // Test custom protocols.
|
Chris@0
|
433 ['http://example.com?foo&bar', '//example.com?foo&bar', ['https']],
|
Chris@0
|
434 // Valid protocol.
|
Chris@0
|
435 ['http://example.com?foo&bar', 'http://example.com?foo&bar', ['https', 'http']],
|
Chris@0
|
436 // Colon not part of the URL scheme.
|
Chris@0
|
437 ['/test:8888?foo&bar', '/test:8888?foo&bar', ['http']],
|
Chris@0
|
438 ];
|
Chris@0
|
439 }
|
Chris@0
|
440
|
Chris@0
|
441 /**
|
Chris@0
|
442 * Tests dangerous url protocol filtering.
|
Chris@0
|
443 *
|
Chris@0
|
444 * @dataProvider providerTestStripDangerousProtocols
|
Chris@0
|
445 * @covers ::setAllowedProtocols
|
Chris@0
|
446 * @covers ::stripDangerousProtocols
|
Chris@0
|
447 *
|
Chris@0
|
448 * @param string $uri
|
Chris@0
|
449 * Protocol URI.
|
Chris@0
|
450 * @param string $expected
|
Chris@0
|
451 * Expected escaped value.
|
Chris@0
|
452 * @param array $protocols
|
Chris@0
|
453 * Protocols to allow.
|
Chris@0
|
454 */
|
Chris@0
|
455 public function testStripDangerousProtocols($uri, $expected, $protocols) {
|
Chris@0
|
456 UrlHelper::setAllowedProtocols($protocols);
|
Chris@0
|
457 $stripped = UrlHelper::stripDangerousProtocols($uri);
|
Chris@0
|
458 $this->assertEquals($expected, $stripped);
|
Chris@0
|
459 }
|
Chris@0
|
460
|
Chris@0
|
461 /**
|
Chris@0
|
462 * Provides data for self::testStripDangerousProtocols().
|
Chris@0
|
463 *
|
Chris@0
|
464 * @return array
|
Chris@0
|
465 */
|
Chris@0
|
466 public static function providerTestStripDangerousProtocols() {
|
Chris@0
|
467 return [
|
Chris@0
|
468 ['javascript://example.com', '//example.com', ['http', 'https']],
|
Chris@0
|
469 // Test custom protocols.
|
Chris@0
|
470 ['http://example.com', '//example.com', ['https']],
|
Chris@0
|
471 // Valid protocol.
|
Chris@0
|
472 ['http://example.com', 'http://example.com', ['https', 'http']],
|
Chris@0
|
473 // Colon not part of the URL scheme.
|
Chris@0
|
474 ['/test:8888', '/test:8888', ['http']],
|
Chris@0
|
475 ];
|
Chris@0
|
476 }
|
Chris@0
|
477
|
Chris@0
|
478 /**
|
Chris@0
|
479 * Enhances test urls with schemes
|
Chris@0
|
480 *
|
Chris@0
|
481 * @param array $urls
|
Chris@0
|
482 * The list of urls.
|
Chris@0
|
483 *
|
Chris@0
|
484 * @return array
|
Chris@0
|
485 * A list of provider data with schemes.
|
Chris@0
|
486 */
|
Chris@0
|
487 protected function dataEnhanceWithScheme(array $urls) {
|
Chris@0
|
488 $url_schemes = ['http', 'https', 'ftp'];
|
Chris@0
|
489 $data = [];
|
Chris@0
|
490 foreach ($url_schemes as $scheme) {
|
Chris@0
|
491 foreach ($urls as $url) {
|
Chris@0
|
492 $data[] = [$url, $scheme];
|
Chris@0
|
493 }
|
Chris@0
|
494 }
|
Chris@0
|
495 return $data;
|
Chris@0
|
496 }
|
Chris@0
|
497
|
Chris@0
|
498 /**
|
Chris@0
|
499 * Enhances test urls with prefixes.
|
Chris@0
|
500 *
|
Chris@0
|
501 * @param array $urls
|
Chris@0
|
502 * The list of urls.
|
Chris@0
|
503 *
|
Chris@0
|
504 * @return array
|
Chris@0
|
505 * A list of provider data with prefixes.
|
Chris@0
|
506 */
|
Chris@0
|
507 protected function dataEnhanceWithPrefix(array $urls) {
|
Chris@0
|
508 $prefixes = ['', '/'];
|
Chris@0
|
509 $data = [];
|
Chris@0
|
510 foreach ($prefixes as $prefix) {
|
Chris@0
|
511 foreach ($urls as $url) {
|
Chris@0
|
512 $data[] = [$url, $prefix];
|
Chris@0
|
513 }
|
Chris@0
|
514 }
|
Chris@0
|
515 return $data;
|
Chris@0
|
516 }
|
Chris@0
|
517
|
Chris@0
|
518 /**
|
Chris@0
|
519 * Test detecting external urls that point to local resources.
|
Chris@0
|
520 *
|
Chris@0
|
521 * @param string $url
|
Chris@0
|
522 * The external url to test.
|
Chris@0
|
523 * @param string $base_url
|
Chris@0
|
524 * The base url.
|
Chris@0
|
525 * @param bool $expected
|
Chris@0
|
526 * TRUE if an external URL points to this installation as determined by the
|
Chris@0
|
527 * base url.
|
Chris@0
|
528 *
|
Chris@0
|
529 * @covers ::externalIsLocal
|
Chris@0
|
530 * @dataProvider providerTestExternalIsLocal
|
Chris@0
|
531 */
|
Chris@0
|
532 public function testExternalIsLocal($url, $base_url, $expected) {
|
Chris@0
|
533 $this->assertSame($expected, UrlHelper::externalIsLocal($url, $base_url));
|
Chris@0
|
534 }
|
Chris@0
|
535
|
Chris@0
|
536 /**
|
Chris@0
|
537 * Provider for local external url detection.
|
Chris@0
|
538 *
|
Chris@0
|
539 * @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocal()
|
Chris@0
|
540 */
|
Chris@0
|
541 public function providerTestExternalIsLocal() {
|
Chris@0
|
542 return [
|
Chris@0
|
543 // Different mixes of trailing slash.
|
Chris@0
|
544 ['http://example.com', 'http://example.com', TRUE],
|
Chris@0
|
545 ['http://example.com/', 'http://example.com', TRUE],
|
Chris@0
|
546 ['http://example.com', 'http://example.com/', TRUE],
|
Chris@0
|
547 ['http://example.com/', 'http://example.com/', TRUE],
|
Chris@0
|
548 // Sub directory of site.
|
Chris@0
|
549 ['http://example.com/foo', 'http://example.com/', TRUE],
|
Chris@0
|
550 ['http://example.com/foo/bar', 'http://example.com/foo', TRUE],
|
Chris@0
|
551 ['http://example.com/foo/bar', 'http://example.com/foo/', TRUE],
|
Chris@0
|
552 // Different sub-domain.
|
Chris@0
|
553 ['http://example.com', 'http://www.example.com/', FALSE],
|
Chris@0
|
554 ['http://example.com/', 'http://www.example.com/', FALSE],
|
Chris@0
|
555 ['http://example.com/foo', 'http://www.example.com/', FALSE],
|
Chris@0
|
556 // Different TLD.
|
Chris@0
|
557 ['http://example.com', 'http://example.ca', FALSE],
|
Chris@0
|
558 ['http://example.com', 'http://example.ca/', FALSE],
|
Chris@0
|
559 ['http://example.com/', 'http://example.ca/', FALSE],
|
Chris@0
|
560 ['http://example.com/foo', 'http://example.ca', FALSE],
|
Chris@0
|
561 ['http://example.com/foo', 'http://example.ca/', FALSE],
|
Chris@0
|
562 // Different site path.
|
Chris@0
|
563 ['http://example.com/foo', 'http://example.com/bar', FALSE],
|
Chris@0
|
564 ['http://example.com', 'http://example.com/bar', FALSE],
|
Chris@0
|
565 ['http://example.com/bar', 'http://example.com/bar/', FALSE],
|
Chris@17
|
566 // Ensure \ is normalised to / since some browsers do that.
|
Chris@17
|
567 ['http://www.example.ca\@example.com', 'http://example.com', FALSE],
|
Chris@17
|
568 // Some browsers ignore or strip leading control characters.
|
Chris@17
|
569 ["\x00//www.example.ca", 'http://example.com', FALSE],
|
Chris@0
|
570 ];
|
Chris@0
|
571 }
|
Chris@0
|
572
|
Chris@0
|
573 /**
|
Chris@0
|
574 * Test invalid url arguments.
|
Chris@0
|
575 *
|
Chris@0
|
576 * @param string $url
|
Chris@0
|
577 * The url to test.
|
Chris@0
|
578 * @param string $base_url
|
Chris@0
|
579 * The base url.
|
Chris@0
|
580 *
|
Chris@0
|
581 * @covers ::externalIsLocal
|
Chris@0
|
582 * @dataProvider providerTestExternalIsLocalInvalid
|
Chris@0
|
583 */
|
Chris@0
|
584 public function testExternalIsLocalInvalid($url, $base_url) {
|
Chris@14
|
585 if (method_exists($this, 'expectException')) {
|
Chris@14
|
586 $this->expectException(\InvalidArgumentException::class);
|
Chris@14
|
587 }
|
Chris@14
|
588 else {
|
Chris@14
|
589 $this->setExpectedException(\InvalidArgumentException::class);
|
Chris@14
|
590 }
|
Chris@0
|
591 UrlHelper::externalIsLocal($url, $base_url);
|
Chris@0
|
592 }
|
Chris@0
|
593
|
Chris@0
|
594 /**
|
Chris@0
|
595 * Provides invalid argument data for local external url detection.
|
Chris@0
|
596 *
|
Chris@0
|
597 * @see \Drupal\Tests\Component\Utility\UrlHelperTest::testExternalIsLocalInvalid()
|
Chris@0
|
598 */
|
Chris@0
|
599 public function providerTestExternalIsLocalInvalid() {
|
Chris@0
|
600 return [
|
Chris@0
|
601 ['http://example.com/foo', ''],
|
Chris@0
|
602 ['http://example.com/foo', 'bar'],
|
Chris@0
|
603 ['http://example.com/foo', 'http://'],
|
Chris@0
|
604 // Invalid destination urls.
|
Chris@0
|
605 ['', 'http://example.com/foo'],
|
Chris@0
|
606 ['bar', 'http://example.com/foo'],
|
Chris@0
|
607 ['/bar', 'http://example.com/foo'],
|
Chris@0
|
608 ['bar/', 'http://example.com/foo'],
|
Chris@0
|
609 ['http://', 'http://example.com/foo'],
|
Chris@0
|
610 ];
|
Chris@0
|
611 }
|
Chris@0
|
612
|
Chris@0
|
613 }
|