- global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php
-
- // Protocol-relative URLs are handled really badly by parse_url(). It's so bad that the easiest
- // way to handle them is to just prepend 'http:' and strip the protocol out later
- $wasRelative = substr( $url, 0, 2 ) == '//';
- if ( $wasRelative ) {
- $url = "http:$url";
- }
- wfSuppressWarnings();
- $bits = parse_url( $url );
- wfRestoreWarnings();
- // parse_url() returns an array without scheme for some invalid URLs, e.g.
- // parse_url("%0Ahttp://example.com") == array( 'host' => '%0Ahttp', 'path' => 'example.com' )
- if ( !$bits || !isset( $bits['scheme'] ) ) {
- return false;
- }
-
- // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it
- if ( in_array( $bits['scheme'] . '://', $wgUrlProtocols ) ) {
- $bits['delimiter'] = '://';
- } elseif ( in_array( $bits['scheme'] . ':', $wgUrlProtocols ) ) {
- $bits['delimiter'] = ':';
- // parse_url detects for news: and mailto: the host part of an url as path
- // We have to correct this wrong detection
- if ( isset( $bits['path'] ) ) {
- $bits['host'] = $bits['path'];
- $bits['path'] = '';
- }
- } else {
- return false;
- }
-
- /* Provide an empty host for eg. file:/// urls (see bug 28627) */
- if ( !isset( $bits['host'] ) ) {
- $bits['host'] = '';
-
- /* parse_url loses the third / for file:///c:/ urls (but not on variants) */
- if ( substr( $bits['path'], 0, 1 ) !== '/' ) {
- $bits['path'] = '/' . $bits['path'];
- }
- }
-
- // If the URL was protocol-relative, fix scheme and delimiter
- if ( $wasRelative ) {
- $bits['scheme'] = '';
- $bits['delimiter'] = '//';
- }
- return $bits;