Made provideIPCIDRs() not add a '/' if there is no prefix length. Fixes bug 31234.
authorAaron Schulz <aaron@users.mediawiki.org>
Sat, 1 Oct 2011 04:54:44 +0000 (04:54 +0000)
committerAaron Schulz <aaron@users.mediawiki.org>
Sat, 1 Oct 2011 04:54:44 +0000 (04:54 +0000)
includes/IP.php
includes/resourceloader/ResourceLoader.php
tests/phpunit/includes/IPTest.php

index 152236f..2f262e3 100644 (file)
@@ -705,8 +705,11 @@ class IP {
         * @param $range String: IP address to normalize
         * @return string
         */
-       public static function sanitizeRange( $range ){
+       public static function sanitizeRange( $range ) {
                list( /*...*/, $bits ) = self::parseCIDR( $range );
+               if ( $bits === false ) {
+                       return $range; // wasn't actually a range
+               }
                list( $start, /*...*/ ) = self::parseRange( $range );
                $start = self::formatHex( $start );
                return "$start/$bits";
index b1c4b72..44d71d0 100644 (file)
@@ -353,7 +353,17 @@ class ResourceLoader {
         * @param $context ResourceLoaderContext: Context in which a response should be formed
         */
        public function respond( ResourceLoaderContext $context ) {
-               global $wgCacheEpoch;
+               global $wgCacheEpoch, $wgUseFileCache;
+
+               // Use file cache if enabled and available...
+               if ( $wgUseFileCache ) {
+                       $type = 'resources-' . ( $context->getOnly() === 'styles' ? 'css' : 'js' );
+                       $hash = sha1( $context->getHash() . implode( ',', $context->getModules() ) );
+                       $fileCache = ObjectFileCache::newFromKey( $hash, $type );
+                       if ( $this->tryRespondFromFileCache( $fileCache, $context ) ) {
+                               return; // output handled
+                       }
+               }
 
                // Buffer output to catch warnings. Normally we'd use ob_clean() on the
                // top-level output buffer to clear warnings, but that breaks when ob_gzhandler
@@ -432,6 +442,15 @@ class ResourceLoader {
                ob_end_clean();
                echo $response;
 
+               // Save response to file cache if enabled
+               if ( isset( $fileCache ) && !$private && !$exceptions && !$missing ) {
+                       $request = $context->getRequest();
+                       // Don't cache URLs that the user was not given by site
+                       if ( $request->getVal( 'fckey' ) == self::fileCacheKey( $request->getRequestURL() ) ) {
+                               $fileCache->saveText( $response );
+                       }
+               }
+
                wfProfileOut( __METHOD__ );
        }
 
@@ -519,6 +538,50 @@ class ResourceLoader {
                return false;
        }
 
+       /**
+        * Send out code for a response from file cache if possible
+        *
+        * @param $fileCache ObjectFileCache: Cache object for this request URL
+        * @param $context ResourceLoaderContext: Context in which to generate a response
+        * @return bool If this found a cache file and handled the response
+        */
+       protected function tryRespondFromFileCache(
+               ObjectFileCache $fileCache, ResourceLoaderContext $context
+       ) {
+               global $wgResourceLoaderMaxage;
+               // Buffer output to catch warnings.
+               ob_start();
+               // Get the maximum age the cache can be
+               $maxage = is_null( $context->getVersion() )
+                       ? $wgResourceLoaderMaxage['unversioned']['server']
+                       : $wgResourceLoaderMaxage['versioned']['server'];
+               // Minimum timestamp the cache file must have
+               $good = $fileCache->isCacheGood( wfTimestamp( TS_MW, time() - $maxage ) );
+               if ( !$good ) {
+                       try { // RL always hits the DB on file cache miss...
+                               wfGetDB( DB_SLAVE );
+                       } catch( DBConnectionError $e ) { // ...check if we need to fallback to cache
+                               $good = $fileCache->isCacheGood(); // cache existence check
+                       }
+               }
+               if ( $good ) {
+                       $ts = $fileCache->cacheTimestamp();
+                       // Send content type and cache headers
+                       $this->sendResponseHeaders( $context, $ts, false );
+                       // If there's an If-Modified-Since header, respond with a 304 appropriately
+                       if ( $this->tryRespondLastModified( $context, $ts ) ) {
+                               return; // output handled (buffers cleared)
+                       }
+                       $response = $fileCache->fetchText();
+                       // Remove the output buffer and output the response
+                       ob_end_clean();
+                       echo $response . "\n/* Cached {$ts} */";
+                       return true; // cache hit
+               }
+               ob_end_clean();
+               return false; // cache miss
+       }
+
        /**
         * Generates code for a response
         *
@@ -912,14 +975,29 @@ class ResourceLoader {
         */
        public static function makeLoaderURL( $modules, $lang, $skin, $user = null, $version = null, $debug = false, $only = null,
                        $printable = false, $handheld = false, $extraQuery = array() ) {
-               global $wgLoadScript;
+               global $wgLoadScript, $wgUseFileCache;
                $query = self::makeLoaderQuery( $modules, $lang, $skin, $user, $version, $debug,
                        $only, $printable, $handheld, $extraQuery
                );
-               
+
+               $url = wfAppendQuery( $wgLoadScript, $query );
+               // Avoid deliberate FS pollution with hand-made URLs
+               if ( $wgUseFileCache ) {
+                       $url .= '&fckey=' . self::fileCacheKey( $url . '&*' );
+               }
+
                // Prevent the IE6 extension check from being triggered (bug 28840)
-               // by appending a character that's invalid in Windows extensions ('*')
-               return wfExpandUrl( wfAppendQuery( $wgLoadScript, $query ) . '&*', PROTO_RELATIVE );
+               // by appending a character that's invalid in Windows extensions ('*')  
+               return $url . '&*';
+       }
+
+       /**
+        * Get a filecache key for a load.php URL
+        * @return string
+        */
+       protected static function fileCacheKey( $url ) {
+               global $wgSecretKey;
+               return sha1( preg_replace( '/&fckey=[^&]*/', '', $url ) . $wgSecretKey . wfWikiID() );
        }
 
        /**
index acc6ebd..74dd0ab 100644 (file)
@@ -482,4 +482,27 @@ class IPTest extends MediaWikiTestCase {
                );
        }
 
+       /**
+        * Test for IP::sanitizeRange()
+        * @dataProvider provideIPCIDRs
+        */
+       function testSanitizeRange( $input, $expected, $description ) {
+               $this->assertEquals( $expected, IP::sanitizeRange( $input ), $description );
+       }
+
+       /**
+        * Provider for IP::testSanitizeRange()
+        */
+       function provideIPCIDRs() {
+               return array(
+                       array( '35.56.31.252/16', '35.56.0.0/16', 'IPv4 range' ),
+                       array( '135.16.21.252/24', '135.16.21.0/24', 'IPv4 range' ),
+                       array( '5.36.71.252/32', '5.36.71.252/32', 'IPv4 silly range' ),
+                       array( '5.36.71.252', '5.36.71.252', 'IPv4 non-range' ),
+                       array( '0:1:2:3:4:c5:f6:7/96', '0:1:2:3:4:C5:0:0/96', 'IPv6 range' ),
+                       array( '0:1:2:3:4:5:6:7/120', '0:1:2:3:4:5:6:0/120', 'IPv6 range' ),
+                       array( '0:e1:2:3:4:5:e6:7/128', '0:E1:2:3:4:5:E6:7/128', 'IPv6 silly range' ),
+                       array( '0:1:A2:3:4:5:c6:7', '0:1:A2:3:4:5:c6:7', 'IPv6 non range' ),
+               );
+       }
 }