*/
function wfUrlencode( $s ) {
static $needle;
+ if ( is_null( $s ) ) {
+ $needle = null;
+ return;
+ }
+
if ( is_null( $needle ) ) {
$needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) || ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false ) ) {
/**
* Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer
* is correct.
+ *
+ * The meaning of the PROTO_* constants is as follows:
+ * PROTO_HTTP: Output a URL starting with http://
+ * PROTO_HTTPS: Output a URL starting with https://
+ * PROTO_RELATIVE: Output a URL starting with // (protocol-relative URL)
+ * PROTO_CURRENT: Output a URL starting with either http:// or https:// , depending on which protocol was used for the current incoming request
*
* @todo this won't work with current-path-relative URLs
* like "subdir/foo.html", etc.
*
* @param $url String: either fully-qualified or a local path + query
+ * @param $defaultProto Mixed: one of the PROTO_* constants. Determines the protocol to use if $url or $wgServer is protocol-relative
* @return string Fully-qualified URL
*/
-function wfExpandUrl( $url ) {
+function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
global $wgServer;
+ if ( $defaultProto === PROTO_CURRENT ) {
+ $defaultProto = WebRequest::detectProtocol() . '://';
+ }
+
+ // Analyze $wgServer to obtain its protocol
+ $bits = wfParseUrl( $wgServer );
+ $serverHasProto = $bits && $bits['scheme'] != '';
+ $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 );
+
if( substr( $url, 0, 2 ) == '//' ) {
- $bits = wfParseUrl( $wgServer );
- $scheme = $bits ? $bits['scheme'] : 'http';
- return $scheme . ':' . $url;
+ return $defaultProtoWithoutSlashes . $url;
} elseif( substr( $url, 0, 1 ) == '/' ) {
- return $wgServer . $url;
+ // If $wgServer is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone
+ return ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $wgServer . $url;
} else {
return $url;
}
/**
* Returns a regular expression of url protocols
*
+ * @param $includeProtocolRelative bool If false, remove '//' from the returned protocol list.
+ * DO NOT USE this directy, use wfUrlProtocolsWithoutProtRel() instead
* @return String
*/
-function wfUrlProtocols() {
+function wfUrlProtocols( $includeProtocolRelative = true ) {
global $wgUrlProtocols;
- static $retval = null;
- if ( !is_null( $retval ) ) {
- return $retval;
+ // Cache return values separately based on $includeProtocolRelative
+ static $retval = array( true => null, false => null );
+ if ( !is_null( $retval[$includeProtocolRelative] ) ) {
+ return $retval[$includeProtocolRelative];
}
// Support old-style $wgUrlProtocols strings, for backwards compatibility
if ( is_array( $wgUrlProtocols ) ) {
$protocols = array();
foreach ( $wgUrlProtocols as $protocol ) {
- $protocols[] = preg_quote( $protocol, '/' );
+ // Filter out '//' if !$includeProtocolRelative
+ if ( $includeProtocolRelative || $protocol !== '//' ) {
+ $protocols[] = preg_quote( $protocol, '/' );
+ }
}
- $retval = implode( '|', $protocols );
+ $retval[$includeProtocolRelative] = implode( '|', $protocols );
} else {
- $retval = $wgUrlProtocols;
+ // Ignore $includeProtocolRelative in this case
+ // This case exists for pre-1.6 compatibility, and we can safely assume
+ // that '//' won't appear in a pre-1.6 config because protocol-relative
+ // URLs weren't supported until 1.18
+ $retval[$includeProtocolRelative] = $wgUrlProtocols;
}
- return $retval;
+ return $retval[$includeProtocolRelative];
+}
+
+/**
+ * Like wfUrlProtocols(), but excludes '//' from the protocol list. Use this if
+ * you need a regex that matches all URL protocols but does not match protocol-
+ * relative URLs
+ */
+function wfUrlProtocolsWithoutProtRel() {
+ return wfUrlProtocols( false );
}
/**
* parse_url() work-alike, but non-broken. Differences:
*
* 1) Does not raise warnings on bad URLs (just returns false)
- * 2) Handles protocols that don't use :// (e.g., mailto: and news:) correctly
- * 3) Adds a "delimiter" element to the array, either '://' or ':' (see (2))
+ * 2) Handles protocols that don't use :// (e.g., mailto: and news: , as well as protocol-relative URLs) correctly
+ * 3) Adds a "delimiter" element to the array, either '://', ':' or '//' (see (2))
*
* @param $url String: a URL to parse
* @return Array: bits of the URL in an associative array, per PHP docs
*/
function wfParseUrl( $url ) {
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();
- if ( !$bits ) {
+ // 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;
}
$bits['path'] = '/' . $bits['path'];
}
}
+
+ // If the URL was protocol-relative, fix scheme and delimiter
+ if ( $wasRelative ) {
+ $bits['scheme'] = '';
+ $bits['delimiter'] = '//';
+ }
return $bits;
}
* Old function when $wgBetterDirectionality existed
* Removed in core, kept in extensions for backwards compat.
*
- * @deprecated since 1.19
+ * @deprecated since 1.18
* @return Language
*/
function wfUILang() {
$args = func_get_args();
array_shift( $args );
return wfMsgReplaceArgs(
- MessageCache::singleton()->parse( wfMsgGetKey( $key ), null, /* can't be set to false */ true )->getText(),
+ MessageCache::singleton()->parse( wfMsgGetKey( $key ), null,
+ /* can't be set to false */ true, /* interface */ true )->getText(),
$args );
}
*
* @param $name String
* @param $p Array: parameters
- * @deprecated since 1.18, warnings in 1.19, removal in 1.20
+ * @deprecated since 1.18, warnings in 1.18, removal in 1.20
*/
function wfCreateObject( $name, $p ) {
wfDeprecated( __FUNCTION__ );
return RepoGroup::singleton()->getLocalRepo()->newFile( $title );
}
+/**
+ * Stream a file to the browser. Back-compat alias for StreamFile::stream()
+ * @deprecated since 1.19
+ */
+function wfStreamFile( $fname, $headers = array() ) {
+ StreamFile::stream( $fname, $headers );
+}
+
/**
* Should low-performance queries be disabled?
*
/**
* Used to be used for outputting text in the installer/updater
- * @deprecated since 1.18, warnings in 1.19, remove in 1.20
+ * @deprecated since 1.18, warnings in 1.18, remove in 1.20
*/
function wfOut( $s ) {
wfDeprecated( __METHOD__ );