MediaWiki  REL1_21
HttpTest.php
Go to the documentation of this file.
00001 <?php
00005 class HttpTest extends MediaWikiTestCase {
00009         function testValidateCookieDomain( $expected, $domain, $origin = null ) {
00010                 if ( $origin ) {
00011                         $ok = Cookie::validateCookieDomain( $domain, $origin );
00012                         $msg = "$domain against origin $origin";
00013                 } else {
00014                         $ok = Cookie::validateCookieDomain( $domain );
00015                         $msg = "$domain";
00016                 }
00017                 $this->assertEquals( $expected, $ok, $msg );
00018         }
00019 
00020         public static function cookieDomains() {
00021                 return array(
00022                         array( false, "org" ),
00023                         array( false, ".org" ),
00024                         array( true, "wikipedia.org" ),
00025                         array( true, ".wikipedia.org" ),
00026                         array( false, "co.uk" ),
00027                         array( false, ".co.uk" ),
00028                         array( false, "gov.uk" ),
00029                         array( false, ".gov.uk" ),
00030                         array( true, "supermarket.uk" ),
00031                         array( false, "uk" ),
00032                         array( false, ".uk" ),
00033                         array( false, "127.0.0." ),
00034                         array( false, "127." ),
00035                         array( false, "127.0.0.1." ),
00036                         array( true, "127.0.0.1" ),
00037                         array( false, "333.0.0.1" ),
00038                         array( true, "example.com" ),
00039                         array( false, "example.com." ),
00040                         array( true, ".example.com" ),
00041 
00042                         array( true, ".example.com", "www.example.com" ),
00043                         array( false, "example.com", "www.example.com" ),
00044                         array( true, "127.0.0.1", "127.0.0.1" ),
00045                         array( false, "127.0.0.1", "localhost" ),
00046                 );
00047         }
00048 
00054         function testIsValidUri( $expect, $URI, $message = '' ) {
00055                 $this->assertEquals(
00056                         $expect,
00057                         (bool)Http::isValidURI( $URI ),
00058                         $message
00059                 );
00060         }
00061 
00065         public static function provideURI() {
00067                 return array(
00068                         array( false, '¿non sens before!! http://a', 'Allow anything before URI' ),
00069 
00070                         # (http|https) - only two schemes allowed
00071                         array( true, 'http://www.example.org/' ),
00072                         array( true, 'https://www.example.org/' ),
00073                         array( true, 'http://www.example.org', 'URI without directory' ),
00074                         array( true, 'http://a', 'Short name' ),
00075                         array( true, 'http://étoile', 'Allow UTF-8 in hostname' ), # 'étoile' is french for 'star'
00076                         array( false, '\\host\directory', 'CIFS share' ),
00077                         array( false, 'gopher://host/dir', 'Reject gopher scheme' ),
00078                         array( false, 'telnet://host', 'Reject telnet scheme' ),
00079 
00080                         # :\/\/ - double slashes
00081                         array( false, 'http//example.org', 'Reject missing colon in protocol' ),
00082                         array( false, 'http:/example.org', 'Reject missing slash in protocol' ),
00083                         array( false, 'http:example.org', 'Must have two slashes' ),
00084                         # Following fail since hostname can be made of anything
00085                         array( false, 'http:///example.org', 'Must have exactly two slashes, not three' ),
00086 
00087                         # (\w+:{0,1}\w*@)? - optional user:pass
00088                         array( true, 'http://user@host', 'Username provided' ),
00089                         array( true, 'http://user:@host', 'Username provided, no password' ),
00090                         array( true, 'http://user:pass@host', 'Username and password provided' ),
00091 
00092                         # (\S+) - host part is made of anything not whitespaces
00093                         array( false, 'http://!"èèè¿¿¿~~\'', 'hostname is made of any non whitespace' ),
00094                         array( false, 'http://exam:ple.org/', 'hostname can not use colons!' ),
00095 
00096                         # (:[0-9]+)? - port number
00097                         array( true, 'http://example.org:80/' ),
00098                         array( true, 'https://example.org:80/' ),
00099                         array( true, 'http://example.org:443/' ),
00100                         array( true, 'https://example.org:443/' ),
00101 
00102                         # Part after the hostname is / or / with something else
00103                         array( true, 'http://example/#' ),
00104                         array( true, 'http://example/!' ),
00105                         array( true, 'http://example/:' ),
00106                         array( true, 'http://example/.' ),
00107                         array( true, 'http://example/?' ),
00108                         array( true, 'http://example/+' ),
00109                         array( true, 'http://example/=' ),
00110                         array( true, 'http://example/&' ),
00111                         array( true, 'http://example/%' ),
00112                         array( true, 'http://example/@' ),
00113                         array( true, 'http://example/-' ),
00114                         array( true, 'http://example//' ),
00115                         array( true, 'http://example/&' ),
00116 
00117                         # Fragment
00118                         array( true, 'http://exam#ple.org', ), # This one is valid, really!
00119                         array( true, 'http://example.org:80#anchor' ),
00120                         array( true, 'http://example.org/?id#anchor' ),
00121                         array( true, 'http://example.org/?#anchor' ),
00122 
00123                         array( false, 'http://a ¿non !!sens after', 'Allow anything after URI' ),
00124                 );
00125         }
00126 
00135         function testRelativeRedirections() {
00136                 $h = MWHttpRequestTester::factory( 'http://oldsite/file.ext' );
00137 
00138                 # Forge a Location header
00139                 $h->setRespHeaders( 'location', array(
00140                                 'http://newsite/file.ext',
00141                                 '/newfile.ext',
00142                         )
00143                 );
00144                 # Verify we correctly fix the Location
00145                 $this->assertEquals(
00146                         'http://newsite/newfile.ext',
00147                         $h->getFinalUrl(),
00148                         "Relative file path Location: interpreted as full URL"
00149                 );
00150 
00151                 $h->setRespHeaders( 'location', array(
00152                                 'https://oldsite/file.ext'
00153                         )
00154                 );
00155                 $this->assertEquals(
00156                         'https://oldsite/file.ext',
00157                         $h->getFinalUrl(),
00158                         "Location to the HTTPS version of the site"
00159                 );
00160 
00161                 $h->setRespHeaders( 'location', array(
00162                                 '/anotherfile.ext',
00163                                 'http://anotherfile/hoster.ext',
00164                                 'https://anotherfile/hoster.ext'
00165                         )
00166                 );
00167                 $this->assertEquals(
00168                         'https://anotherfile/hoster.ext',
00169                         $h->getFinalUrl( "Relative file path Location: should keep the latest host and scheme!" )
00170                 );
00171         }
00172 }
00173 
00177 class MWHttpRequestTester extends MWHttpRequest {
00178 
00179         // function derived from the MWHttpRequest factory function but 
00180         // returns appropriate tester class here
00181         public static function factory( $url, $options = null ) {
00182                 if ( !Http::$httpEngine ) {
00183                         Http::$httpEngine = function_exists( 'curl_init' ) ? 'curl' : 'php';
00184                 } elseif ( Http::$httpEngine == 'curl' && !function_exists( 'curl_init' ) ) {
00185                         throw new MWException( __METHOD__ . ': curl (http://php.net/curl) is not installed, but' .
00186                                 'Http::$httpEngine is set to "curl"' );
00187                 }
00188 
00189                 switch ( Http::$httpEngine ) {
00190                         case 'curl':
00191                                 return new CurlHttpRequestTester( $url, $options );
00192                         case 'php':
00193                                 if ( !wfIniGetBool( 'allow_url_fopen' ) ) {
00194                                         throw new MWException( __METHOD__ . ': allow_url_fopen needs to be enabled for pure PHP' .
00195                                                 ' http requests to work. If possible, curl should be used instead. See http://php.net/curl.' );
00196                                 }
00197                                 return new PhpHttpRequestTester( $url, $options );
00198                         default:
00199                 }
00200         }
00201 }
00202 
00203 class CurlHttpRequestTester extends CurlHttpRequest {
00204         function setRespHeaders( $name, $value ) {
00205                 $this->respHeaders[$name] = $value;
00206         }
00207 }
00208 
00209 class PhpHttpRequestTester extends PhpHttpRequest {
00210         function setRespHeaders( $name, $value ) {
00211                 $this->respHeaders[$name] = $value;
00212         }
00213 }