Add support for Number grouping(commafy) based on CLDR number grouping patterns like...
[lhc/web/wiklou.git] / includes / Sanitizer.php
index 113a85e..227fa7c 100644 (file)
@@ -39,6 +39,14 @@ class Sanitizer {
                 |&\#[xX]([0-9A-Fa-f]+);
                 |(&)/x';
 
+       /**
+        * Blacklist for evil uris like javascript:
+        * WARNING: DO NOT use this in any place that actually requires blacklisting
+        * for security reasons. There are NUMEROUS[1] ways to bypass blacklisting, the
+        * only way to be secure from javascript: uri based xss vectors is to whitelist
+        * things that you know are safe and deny everything else.
+        * [1]: http://ha.ckers.org/xss.html
+        */
        const EVIL_URI_PATTERN = '!(^|\s|\*/\s*)(javascript|vbscript)([^\w]|$)!i';
        const XMLNS_ATTRIBUTE_PATTERN = "/^xmlns:[:A-Z_a-z-.0-9]+$/";
 
@@ -64,7 +72,7 @@ class Sanitizer {
                'amp'      => 38,
                'and'      => 8743,
                'ang'      => 8736,
-               'apos'     => 39,
+               'apos'     => 39, // New in XHTML & HTML 5; avoid in output for compatibility with IE.
                'Aring'    => 197,
                'aring'    => 229,
                'asymp'    => 8776,
@@ -371,7 +379,7 @@ class Sanitizer {
                                'strike', 'strong', 'tt', 'var', 'div', 'center',
                                'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
                                'ruby', 'rt' , 'rb' , 'rp', 'p', 'span', 'abbr', 'dfn',
-                               'kbd', 'samp', 'thead', 'tbody', 'tfoot'
+                               'kbd', 'samp'
                        );
                        $htmlsingle = array(
                                'br', 'hr', 'li', 'dt', 'dd'
@@ -594,6 +602,89 @@ class Sanitizer {
                return $text;
        }
 
+       /**
+        * Take an array of attribute names and values and fix some deprecated values
+        * for the given element type.
+        * This does not validate properties, so you should ensure that you call
+        * validateTagAttributes AFTER this to ensure that the resulting style rule
+        * this may add is safe.
+        * 
+        * - Converts most presentational attributes like align into inline css
+        *
+        * @param $attribs Array
+        * @param $element String
+        * @return Array
+        */
+       static function fixDeprecatedAttributes( $attribs, $element ) {
+               global $wgHtml5, $wgCleanupPresentationalAttributes;
+               
+               // presentational attributes were removed from html5, we can leave them
+               // in when html5 is turned off
+               if ( !$wgHtml5 || !$wgCleanupPresentationalAttributes ) {
+                       return $attribs;
+               }
+               
+               $table = array( 'table' );
+               $cells = array( 'td', 'th' );
+               $colls = array( 'col', 'colgroup' );
+               $tblocks = array( 'tbody', 'tfoot', 'thead' );
+               $h = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' );
+               
+               $presentationalAttribs = array(
+                       'align' => array( 'text-align', array_merge( array( 'caption', 'hr', 'div', 'p', 'tr' ), $table, $cells, $colls, $tblocks, $h ) ),
+                       'clear' => array( 'clear', array( 'br' ) ),
+                       'height' => array( 'height', $cells ),
+                       'nowrap' => array( 'white-space', $cells ),
+                       'size' => array( 'height', array( 'hr' ) ),
+                       'type' => array( 'list-style-type', array( 'li', 'ol', 'ul' ) ),
+                       'valign' => array( 'vertical-align', array_merge( $cells, $colls, $tblocks ) ),
+                       'width' => array( 'width', array_merge( array( 'hr', 'pre' ), $table, $cells, $colls ) ),
+               );
+               
+               $style = "";
+               foreach ( $presentationalAttribs as $attribute => $info ) {
+                       list( $property, $elements ) = $info;
+                       
+                       // Skip if this attribute is not relevant to this element
+                       if ( !in_array( $element, $elements ) ) {
+                               continue;
+                       }
+                       
+                       // Skip if the attribute is not used
+                       if ( !array_key_exists( $attribute, $attribs ) ) {
+                               continue;
+                       }
+                       
+                       $value = $attribs[$attribute];
+                       
+                       // For nowrap the value should be nowrap instead of whatever text is in the value
+                       if ( $attribute === 'nowrap' ) {
+                               $value = 'nowrap';
+                       }
+                       
+                       // Size based properties should have px applied to them if they have no unit
+                       if ( in_array( $attribute, array( 'height', 'width', 'size' ) ) ) {
+                               if ( preg_match( '/^[\d.]+$/', $value ) ) {
+                                       $value = "{$value}px";
+                               }
+                       }
+                       
+                       $style .= " $property: $value;";
+                       
+                       unset( $attribs[$attribute] );
+               }
+               
+               if ( !empty($style) ) {
+                       // Prepend our style rules so that they can be overridden by user css
+                       if ( isset($attribs['style']) ) {
+                               $style .= " " . $attribs['style'];
+                       }
+                       $attribs['style'] = trim($style);
+               }
+               
+               return $attribs;
+       }
+
        /**
         * Take an array of attribute names and values and normalize or discard
         * illegal values for the given element type.
@@ -841,8 +932,9 @@ class Sanitizer {
                        return '';
                }
 
-               $stripped = Sanitizer::validateTagAttributes(
-                       Sanitizer::decodeTagAttributes( $text ), $element );
+               $decoded = Sanitizer::decodeTagAttributes( $text );
+               $decoded = Sanitizer::fixDeprecatedAttributes( $decoded, $element );
+               $stripped = Sanitizer::validateTagAttributes( $decoded, $element );
 
                $attribs = array();
                foreach( $stripped as $attribute => $value ) {
@@ -1617,6 +1709,8 @@ class Sanitizer {
         * to be liberal enough for wide use. Some invalid addresses will still
         * pass validation here.
         *
+        * @since 1.18
+        *
         * @param $addr String E-mail address
         * @return Bool
         */