|
13 | 13 |
|
14 | 14 | use function array_filter, array_keys, array_map, array_values, count, explode, |
15 | 15 | gzdecode, gzinflate, gzuncompress, implode, is_array, is_numeric, is_scalar, is_string, |
16 | | - json_decode, json_encode, rawurldecode, rawurlencode, simplexml_load_string, strtolower, trim, |
17 | | - ucfirst; |
| 16 | + json_decode, json_encode, parse_url, preg_match, preg_replace_callback, rawurldecode, rawurlencode, |
| 17 | + simplexml_load_string, strtolower, trim, ucfirst, urlencode; |
18 | 18 |
|
19 | 19 | const PSR7_INCLUDES = true; |
20 | 20 |
|
@@ -511,3 +511,37 @@ function uriWithQueryValue(UriInterface $uri, string $key, string $value = null) |
511 | 511 | return $uri->withQuery(implode('&', $result)); |
512 | 512 | } |
513 | 513 |
|
| 514 | +/** |
| 515 | + * UTF-8 aware \parse_url() replacement. |
| 516 | + * |
| 517 | + * The internal function produces broken output for non ASCII domain names |
| 518 | + * (IDN) when used with locales other than "C". |
| 519 | + * |
| 520 | + * On the other hand, cURL understands IDN correctly only when UTF-8 locale |
| 521 | + * is configured ("C.UTF-8", "en_US.UTF-8", etc.). |
| 522 | + * |
| 523 | + * @see https://bugs.php.net/bug.php?id=52923 |
| 524 | + * @see https://www.php.net/manual/en/function.parse-url.php#114817 |
| 525 | + * @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING |
| 526 | + * |
| 527 | + * @link https://github.com/guzzle/psr7/blob/c0dcda9f54d145bd4d062a6d15f54931a67732f9/src/Uri.php#L89-L130 |
| 528 | + */ |
| 529 | +function parseUrl(string $url):?array{ |
| 530 | + // If IPv6 |
| 531 | + $prefix = ''; |
| 532 | + /** @noinspection RegExpRedundantEscape */ |
| 533 | + if(preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)){ |
| 534 | + /** @var array{0:string, 1:string, 2:string} $matches */ |
| 535 | + $prefix = $matches[1]; |
| 536 | + $url = $matches[2]; |
| 537 | + } |
| 538 | + |
| 539 | + $encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', fn($matches) => urlencode($matches[0]), $url); |
| 540 | + $result = parse_url($prefix.$encodedUrl); |
| 541 | + |
| 542 | + if($result === false){ |
| 543 | + return null; |
| 544 | + } |
| 545 | + |
| 546 | + return array_map('urldecode', $result); |
| 547 | +} |
0 commit comments