return $url;
}
+define( 'PROT_HTTP', 'http://' );
+define( 'PROT_HTTPS', 'https://' );
+define( 'PROT_RELATIVE', '//' );
+define( 'PROT_CURRENT', null );
+
/**
* Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer
* is correct.
+ *
+ * The meaning of the PROT_* constants is as follows:
+ * PROT_HTTP: Output a URL starting with http://
+ * PROT_HTTPS: Output a URL starting with https://
+ * PROT_RELATIVE: Output a URL starting with // (protocol-relative URL)
+ * PROT_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 PROT_* 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 = PROT_CURRENT ) {
global $wgServer;
+ if ( $defaultProto === PROT_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'] !== '' ? $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;
}
* @return string
*/
public static function detectServer() {
- if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on') {
- $proto = 'https';
- $stdPort = 443;
- } else {
- $proto = 'http';
- $stdPort = 80;
- }
+ list( $proto, $stdPort ) = self::detectProtocolAndStdPort();
$varNames = array( 'HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR' );
$host = 'localhost';
return $proto . '://' . IP::combineHostAndPort( $host, $port, $stdPort );
}
+
+ public static function detectProtocolAndStdPort() {
+ return ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) ? array( 'https', 443 ) : array( 'http', 80 );
+ }
+
+ public static function detectProtocol() {
+ list( $proto, $stdPort ) = self::detectProtocolAndStdPort();
+ return $proto;
+ }
/**
* Check for title, action, and/or variant data in the URL
class wfExpandUrl extends MediaWikiTestCase {
/** @dataProvider provideExpandableUrls */
- public function testWfExpandUrl( $fullUrl, $shortUrl, $message ) {
- $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl ), $message );
+ public function testWfExpandUrl( $fullUrl, $shortUrl, $defaultProto, $server, $httpsMode, $message ) {
+ // Fake $wgServer
+ global $wgServer;
+ $oldServer = $wgServer;
+ $wgServer = $server;
+
+ // Fake $_SERVER['HTTPS'] if needed
+ if ( $httpsMode ) {
+ $_SERVER['HTTPS'] = 'on';
+ } else {
+ unset( $_SERVER['HTTPS'] );
+ }
+
+ $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl, $defaultProto ), $message );
+
+ // Restore $wgServer
+ $wgServer = $oldServer;
}
/**
* @return array
*/
public function provideExpandableUrls() {
- global $wgServer;
- return array(
- array( "$wgServer/wiki/FooBar", '/wiki/FooBar', 'Testing expanding URL beginning with /' ),
- array( 'http://example.com', 'http://example.com', 'Testing fully qualified http URLs (no need to expand)' ),
- array( 'https://example.com', 'https://example.com', 'Testing fully qualified https URLs (no need to expand)' ),
- # Would be nice to support this, see fixme on wfExpandUrl()
- array( "wiki/FooBar", 'wiki/FooBar', "Test non-expandable relative URLs" ),
- );
+ $modes = array( 'http', 'https' );
+ $servers = array( 'http' => 'http://example.com', 'https' => 'https://example.com', 'protocol-relative' => '//example.com' );
+ $defaultProtos = array( 'http' => PROT_HTTP, 'https' => PROT_HTTPS, 'protocol-relative' => PROT_RELATIVE, 'current' => PROT_CURRENT );
+
+ $retval = array();
+ foreach ( $modes as $mode ) {
+ $httpsMode = $mode == 'https';
+ foreach ( $servers as $serverDesc => $server ) {
+ foreach ( $defaultProtos as $protoDesc => $defaultProto ) {
+ $retval[] = array( 'http://example.com', 'http://example.com', $defaultProto, $server, $httpsMode, "Testing fully qualified http URLs (no need to expand) (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" );
+ $retval[] = array( 'https://example.com', 'https://example.com', $defaultProto, $server, $httpsMode, "Testing fully qualified https URLs (no need to expand) (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" );
+ # Would be nice to support this, see fixme on wfExpandUrl()
+ $retval[] = array( "wiki/FooBar", 'wiki/FooBar', $defaultProto, $server, $httpsMode, "Test non-expandable relative URLs (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" );
+
+ // Determine expected protocol
+ $p = $protoDesc . ':'; // default case
+ if ( $protoDesc == 'protocol-relative' ) {
+ $p = '';
+ } else if ( $protoDesc == 'current' ) {
+ $p = "$mode:";
+ } else {
+ $p = $protoDesc . ':';
+ }
+ // Determine expected server name
+ $srv = $serverDesc == 'protocol-relative' ? $p . $server : $server;
+
+ $retval[] = array( "$p//wikipedia.org", '//wikipedia.org', $defaultProto, $server, $httpsMode, "Test protocol-relative URL (defaultProto: $protoDesc, wgServer: $server, current request protocol: $mode )" );
+ $retval[] = array( "$srv/wiki/FooBar", '/wiki/FooBar', $defaultProto, $server, $httpsMode, "Testing expanding URL beginning with / (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" );
+ }
+ }
+ }
+ return $retval;
}
}