]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blobdiff - includes/Sanitizer.php
Mediawiki 1.15.2
[autoinstalls/mediawiki.git] / includes / Sanitizer.php
index 5d58b036551ec89b6a432dc4f6004add2be9f644..0b70e002f6906bbeaa1c44969a60fbe0a417b0a0 100644 (file)
@@ -658,24 +658,48 @@ class Sanitizer {
         * @return mixed
         */
        static function checkCss( $value ) {
-               $stripped = Sanitizer::decodeCharReferences( $value );
+               $value = Sanitizer::decodeCharReferences( $value );
 
                // Remove any comments; IE gets token splitting wrong
-               $stripped = StringUtils::delimiterReplace( '/*', '*/', ' ', $stripped );
-
-               $value = $stripped;
-
-               // ... and continue checks
-               $stripped = preg_replace( '!\\\\([0-9A-Fa-f]{1,6})[ \\n\\r\\t\\f]?!e',
-                       'codepointToUtf8(hexdec("$1"))', $stripped );
-               $stripped = str_replace( '\\', '', $stripped );
-               if( preg_match( '/(?:expression|tps*:\/\/|url\\s*\().*/is',
-                               $stripped ) ) {
-                       # haxx0r
+               $value = StringUtils::delimiterReplace( '/*', '*/', ' ', $value );
+
+               // Decode escape sequences and line continuation
+               // See the grammar in the CSS 2 spec, appendix D, Mozilla implements it accurately.
+               // IE 8 doesn't implement it at all, but there's no way to introduce url() into
+               // IE that doesn't hit Mozilla also.
+               static $decodeRegex;
+               if ( !$decodeRegex ) {
+                       $space = '[\\x20\\t\\r\\n\\f]';
+                       $nl = '(?:\\n|\\r\\n|\\r|\\f)';
+                       $backslash = '\\\\';
+                       $decodeRegex = "/ $backslash 
+                               (?:
+                                       ($nl) |  # 1. Line continuation
+                                       ([0-9A-Fa-f]{1,6})$space? |  # 2. character number
+                                       (.) # 3. backslash cancelling special meaning
+                               )/xu";
+               }
+               $decoded = preg_replace_callback( $decodeRegex, 
+                       array( __CLASS__, 'cssDecodeCallback' ), $value );
+               if ( preg_match( '!expression|https?://|url\s*\(!i', $decoded ) ) {
+                       // Not allowed
                        return false;
+               } else {
+                       // Allowed, return CSS with comments stripped
+                       return $value;
                }
+       }
 
-               return $value;
+       static function cssDecodeCallback( $matches ) {
+               if ( $matches[1] !== '' ) {
+                       return '';
+               } elseif ( $matches[2] !== '' ) {
+                       return codepointToUtf8( hexdec( $matches[2] ) );
+               } elseif ( $matches[3] !== '' ) {
+                       return $matches[3];
+               } else {
+                       throw new MWException( __METHOD__.': invalid match' );
+               }
        }
 
        /**