summaryrefslogtreecommitdiff
path: root/includes/Sanitizer.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/Sanitizer.php')
-rw-r--r--includes/Sanitizer.php50
1 files changed, 37 insertions, 13 deletions
diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php
index 5d58b036..0b70e002 100644
--- a/includes/Sanitizer.php
+++ b/includes/Sanitizer.php
@@ -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' );
+ }
}
/**