Index: trunk/phase3/tests/phpunit/includes/GlobalFunctions/wfExpandUrl.php |
— | — | @@ -5,8 +5,23 @@ |
6 | 6 | |
7 | 7 | class wfExpandUrl extends MediaWikiTestCase { |
8 | 8 | /** @dataProvider provideExpandableUrls */ |
9 | | - public function testWfExpandUrl( $fullUrl, $shortUrl, $message ) { |
10 | | - $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl ), $message ); |
| 9 | + public function testWfExpandUrl( $fullUrl, $shortUrl, $defaultProto, $server, $httpsMode, $message ) { |
| 10 | + // Fake $wgServer |
| 11 | + global $wgServer; |
| 12 | + $oldServer = $wgServer; |
| 13 | + $wgServer = $server; |
| 14 | + |
| 15 | + // Fake $_SERVER['HTTPS'] if needed |
| 16 | + if ( $httpsMode ) { |
| 17 | + $_SERVER['HTTPS'] = 'on'; |
| 18 | + } else { |
| 19 | + unset( $_SERVER['HTTPS'] ); |
| 20 | + } |
| 21 | + |
| 22 | + $this->assertEquals( $fullUrl, wfExpandUrl( $shortUrl, $defaultProto ), $message ); |
| 23 | + |
| 24 | + // Restore $wgServer |
| 25 | + $wgServer = $oldServer; |
11 | 26 | } |
12 | 27 | |
13 | 28 | /** |
— | — | @@ -15,13 +30,37 @@ |
16 | 31 | * @return array |
17 | 32 | */ |
18 | 33 | public function provideExpandableUrls() { |
19 | | - global $wgServer; |
20 | | - return array( |
21 | | - array( "$wgServer/wiki/FooBar", '/wiki/FooBar', 'Testing expanding URL beginning with /' ), |
22 | | - array( 'http://example.com', 'http://example.com', 'Testing fully qualified http URLs (no need to expand)' ), |
23 | | - array( 'https://example.com', 'https://example.com', 'Testing fully qualified https URLs (no need to expand)' ), |
24 | | - # Would be nice to support this, see fixme on wfExpandUrl() |
25 | | - array( "wiki/FooBar", 'wiki/FooBar', "Test non-expandable relative URLs" ), |
26 | | - ); |
| 34 | + $modes = array( 'http', 'https' ); |
| 35 | + $servers = array( 'http' => 'http://example.com', 'https' => 'https://example.com', 'protocol-relative' => '//example.com' ); |
| 36 | + $defaultProtos = array( 'http' => PROT_HTTP, 'https' => PROT_HTTPS, 'protocol-relative' => PROT_RELATIVE, 'current' => PROT_CURRENT ); |
| 37 | + |
| 38 | + $retval = array(); |
| 39 | + foreach ( $modes as $mode ) { |
| 40 | + $httpsMode = $mode == 'https'; |
| 41 | + foreach ( $servers as $serverDesc => $server ) { |
| 42 | + foreach ( $defaultProtos as $protoDesc => $defaultProto ) { |
| 43 | + $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 )" ); |
| 44 | + $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 )" ); |
| 45 | + # Would be nice to support this, see fixme on wfExpandUrl() |
| 46 | + $retval[] = array( "wiki/FooBar", 'wiki/FooBar', $defaultProto, $server, $httpsMode, "Test non-expandable relative URLs (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" ); |
| 47 | + |
| 48 | + // Determine expected protocol |
| 49 | + $p = $protoDesc . ':'; // default case |
| 50 | + if ( $protoDesc == 'protocol-relative' ) { |
| 51 | + $p = ''; |
| 52 | + } else if ( $protoDesc == 'current' ) { |
| 53 | + $p = "$mode:"; |
| 54 | + } else { |
| 55 | + $p = $protoDesc . ':'; |
| 56 | + } |
| 57 | + // Determine expected server name |
| 58 | + $srv = $serverDesc == 'protocol-relative' ? $p . $server : $server; |
| 59 | + |
| 60 | + $retval[] = array( "$p//wikipedia.org", '//wikipedia.org', $defaultProto, $server, $httpsMode, "Test protocol-relative URL (defaultProto: $protoDesc, wgServer: $server, current request protocol: $mode )" ); |
| 61 | + $retval[] = array( "$srv/wiki/FooBar", '/wiki/FooBar', $defaultProto, $server, $httpsMode, "Testing expanding URL beginning with / (defaultProto: $protoDesc , wgServer: $server, current request protocol: $mode )" ); |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + return $retval; |
27 | 66 | } |
28 | 67 | } |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -428,24 +428,44 @@ |
429 | 429 | return $url; |
430 | 430 | } |
431 | 431 | |
| 432 | +define( 'PROT_HTTP', 'http://' ); |
| 433 | +define( 'PROT_HTTPS', 'https://' ); |
| 434 | +define( 'PROT_RELATIVE', '//' ); |
| 435 | +define( 'PROT_CURRENT', null ); |
| 436 | + |
432 | 437 | /** |
433 | 438 | * Expand a potentially local URL to a fully-qualified URL. Assumes $wgServer |
434 | 439 | * is correct. |
| 440 | + * |
| 441 | + * The meaning of the PROT_* constants is as follows: |
| 442 | + * PROT_HTTP: Output a URL starting with http:// |
| 443 | + * PROT_HTTPS: Output a URL starting with https:// |
| 444 | + * PROT_RELATIVE: Output a URL starting with // (protocol-relative URL) |
| 445 | + * PROT_CURRENT: Output a URL starting with either http:// or https:// , depending on which protocol was used for the current incoming request |
435 | 446 | * |
436 | 447 | * @todo this won't work with current-path-relative URLs |
437 | 448 | * like "subdir/foo.html", etc. |
438 | 449 | * |
439 | 450 | * @param $url String: either fully-qualified or a local path + query |
| 451 | + * @param $defaultProto Mixed: one of the PROT_* constants. Determines the protocol to use if $url or $wgServer is protocol-relative |
440 | 452 | * @return string Fully-qualified URL |
441 | 453 | */ |
442 | | -function wfExpandUrl( $url ) { |
| 454 | +function wfExpandUrl( $url, $defaultProto = PROT_CURRENT ) { |
443 | 455 | global $wgServer; |
| 456 | + if ( $defaultProto === PROT_CURRENT ) { |
| 457 | + $defaultProto = WebRequest::detectProtocol() . '://'; |
| 458 | + } |
| 459 | + |
| 460 | + // Analyze $wgServer to obtain its protocol |
| 461 | + $bits = wfParseUrl( $wgServer ); |
| 462 | + $serverHasProto = $bits && $bits['scheme'] != ''; |
| 463 | + $defaultProtoWithoutSlashes = substr( $defaultProto, 0, -2 ); |
| 464 | + |
444 | 465 | if( substr( $url, 0, 2 ) == '//' ) { |
445 | | - $bits = wfParseUrl( $wgServer ); |
446 | | - $scheme = $bits && $bits['scheme'] !== '' ? $bits['scheme'] : 'http'; |
447 | | - return $scheme . ':' . $url; |
| 466 | + return $defaultProtoWithoutSlashes . $url; |
448 | 467 | } elseif( substr( $url, 0, 1 ) == '/' ) { |
449 | | - return $wgServer . $url; |
| 468 | + // If $wgServer is protocol-relative, prepend $defaultProtoWithoutSlashes, otherwise leave it alone |
| 469 | + return ( $serverHasProto ? '' : $defaultProtoWithoutSlashes ) . $wgServer . $url; |
450 | 470 | } else { |
451 | 471 | return $url; |
452 | 472 | } |
Index: trunk/phase3/includes/WebRequest.php |
— | — | @@ -131,13 +131,7 @@ |
132 | 132 | * @return string |
133 | 133 | */ |
134 | 134 | public static function detectServer() { |
135 | | - if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on') { |
136 | | - $proto = 'https'; |
137 | | - $stdPort = 443; |
138 | | - } else { |
139 | | - $proto = 'http'; |
140 | | - $stdPort = 80; |
141 | | - } |
| 135 | + list( $proto, $stdPort ) = self::detectProtocolAndStdPort(); |
142 | 136 | |
143 | 137 | $varNames = array( 'HTTP_HOST', 'SERVER_NAME', 'HOSTNAME', 'SERVER_ADDR' ); |
144 | 138 | $host = 'localhost'; |
— | — | @@ -164,6 +158,15 @@ |
165 | 159 | |
166 | 160 | return $proto . '://' . IP::combineHostAndPort( $host, $port, $stdPort ); |
167 | 161 | } |
| 162 | + |
| 163 | + public static function detectProtocolAndStdPort() { |
| 164 | + return ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) ? array( 'https', 443 ) : array( 'http', 80 ); |
| 165 | + } |
| 166 | + |
| 167 | + public static function detectProtocol() { |
| 168 | + list( $proto, $stdPort ) = self::detectProtocolAndStdPort(); |
| 169 | + return $proto; |
| 170 | + } |
168 | 171 | |
169 | 172 | /** |
170 | 173 | * Check for title, action, and/or variant data in the URL |