Respect $wgScriptExtension in SearchEngine::getOpenSearchTemplate() and SearchEngine...
[lhc/web/wiklou.git] / includes / Sanitizer.php
index 210aeb1..4c99e82 100644 (file)
@@ -31,8 +31,7 @@
 define( 'MW_CHAR_REFS_REGEX',
        '/&([A-Za-z0-9\x80-\xff]+);
         |&\#([0-9]+);
-        |&\#x([0-9A-Za-z]+);
-        |&\#X([0-9A-Za-z]+);
+        |&\#[xX]([0-9A-Fa-f]+);
         |(&)/x' );
 
 /**
@@ -40,7 +39,7 @@ define( 'MW_CHAR_REFS_REGEX',
  * Allows some... latitude.
  * Used in Sanitizer::fixTagAttributes and Sanitizer::decodeTagAttributes
  */
-$attribFirst = '[:A-Z_a-z]';
+$attribFirst = '[:A-Z_a-z0-9]';
 $attrib = '[:A-Z_a-z-.0-9]';
 $space = '[\x09\x0a\x0d\x20]';
 define( 'MW_ATTRIBS_REGEX',
@@ -368,7 +367,7 @@ class Sanitizer {
                                'h2', 'h3', 'h4', 'h5', 'h6', 'cite', 'code', 'em', 's',
                                'strike', 'strong', 'tt', 'var', 'div', 'center',
                                'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre',
-                               'ruby', 'rt' , 'rb' , 'rp', 'p', 'span', 'u', 'abbr', 'dfn',
+                               'ruby', 'rt' , 'rb' , 'rp', 'p', 'span', 'abbr', 'dfn',
                                'kbd', 'samp'
                        );
                        $htmlsingle = array(
@@ -687,19 +686,6 @@ class Sanitizer {
                }
 
                if ( $wgAllowMicrodataAttributes ) {
-                       # There are some complicated validity constraints we need to
-                       # enforce here.  First of all, we don't want to allow non-standard
-                       # itemtypes.
-                       $allowedTypes = array(
-                               'http://microformats.org/profile/hcard',
-                               'http://microformats.org/profile/hcalendar#vevent',
-                               'http://n.whatwg.org/work',
-                       );
-                       if ( isset( $out['itemtype'] ) && !in_array( $out['itemtype'],
-                       $allowedTypes ) ) {
-                               # Kill everything
-                               unset( $out['itemscope'] );
-                       }
                        # itemtype, itemid, itemref don't make sense without itemscope
                        if ( !array_key_exists( 'itemscope', $out ) ) {
                                unset( $out['itemtype'] );
@@ -748,6 +734,13 @@ class Sanitizer {
                // Remove any comments; IE gets token splitting wrong
                $value = StringUtils::delimiterReplace( '/*', '*/', ' ', $value );
 
+               // Remove anything after a comment-start token, to guard against
+               // incorrect client implementations.
+               $commentPos = strpos( $value, '/*' );
+               if ( $commentPos !== false ) {
+                       $value = substr( $value, 0, $commentPos );
+               }
+
                // Decode escape sequences and line continuation
                // See the grammar in the CSS 2 spec, appendix D.
                static $decodeRegex;
@@ -796,51 +789,6 @@ class Sanitizer {
                }
        }
 
-       /** 
-       * Take an associative array of attribute name/value pairs
-       * and generate a css style representing all the style-related
-       * attributes. If there already a style attribute in the array,
-       * it is also included in the value returned.
-       */
-       static function styleFromAttributes( $attributes ) {
-               $styles = array();
-
-               foreach ( $attributes as $attribute => $value ) {
-                       if ( $attribute == 'bgcolor' ) {
-                               $styles[] = "background-color: $value";
-                       } else if ( $attribute == 'border' ) {
-                               $styles[] = "border-width: $value";
-                       } else if ( $attribute == 'align' ) {
-                               $styles[] = "text-align: $value";
-                       } else if ( $attribute == 'valign' ) {
-                               $styles[] = "vertical-align: $value";
-                       } else if ( $attribute == 'width' ) {
-                               if ( preg_match( '/\d+/', $value ) === false ) {
-                                     $value .= 'px';
-                               }
-
-                               $styles[] = "width: $value";
-                       } else if ( $attribute == 'height' ) {
-                               if ( preg_match( '/\d+/', $value ) === false ) {
-                                     $value .= 'px';
-                               }
-
-                               $styles[] = "height: $value";
-                       } else if ( $attribute == 'nowrap' ) {
-                               if ( $value ) {
-                                       $styles[] = "white-space: nowrap";
-                               }
-                       }
-               }
-
-               if ( isset( $attributes[ 'style' ] ) ) {
-                       $styles[] = $attributes[ 'style' ];
-               } 
-
-               if ( !$styles ) return '';
-               else return implode( '; ', $styles );
-       }
-
        /**
         * Take a tag soup fragment listing an HTML element's attributes
         * and normalize it to well-formed XML, discarding unwanted attributes.
@@ -858,66 +806,24 @@ class Sanitizer {
         *
         * @param $text String
         * @param $element String
-        * @param $defaults Array (optional) associative array of default attributes to splice in. 
-        *                      class and style attributes are combined. Otherwise, values from
-        *                      $attributes take precedence over values from $defaults.
         * @return String
         */
-       static function fixTagAttributes( $text, $element, $defaults = null ) {
+       static function fixTagAttributes( $text, $element ) {
                if( trim( $text ) == '' ) {
                        return '';
                }
 
-               $decoded = Sanitizer::decodeTagAttributes( $text );
-               $stripped = Sanitizer::validateTagAttributes( $decoded, $element );
-               $attribs = Sanitizer::collapseTagAttributes( $stripped, $defaults );
+               $stripped = Sanitizer::validateTagAttributes(
+                       Sanitizer::decodeTagAttributes( $text ), $element );
 
-               return $attribs;
-       }
-
-       /**
-        * Take an associative array or attribute name/value pairs
-        * and collapses it to well-formed XML.
-        * Does not filter attributes.
-        * Output is safe for further wikitext processing, with escaping of
-        * values that could trigger problems.
-        *
-        * - Double-quotes all attribute values
-        * - Prepends space if there are attributes.
-        *
-        * @param $attributes Array is an associative array of attribute name/value pairs. 
-        *                      Assumed to be sanitized already.
-        * @param $defaults Array (optional) associative array of default attributes to splice in. 
-        *                      class and style attributes are combined. Otherwise, values from
-        *                      $attributes take precedence over values from $defaults.
-        * @return String
-        */
-       static function collapseTagAttributes( $attributes, $defaults = null ) {
-               if ( $defaults ) {
-                       foreach( $defaults as $attribute => $value ) {
-                               if ( isset( $attributes[ $attribute ] ) ) {
-                                       if ( $attribute == 'class' ) {
-                                               $value .= ' '. $attributes[ $attribute ];
-                                       } else if ( $attribute == 'style' ) {
-                                               $value .= '; ' . $attributes[ $attribute ];
-                                       } else {
-                                               continue;
-                                       }
-                               }
-
-                               $attributes[ $attribute ] = $value;
-                       }
-               }
-
-               $chunks = array();
-
-               foreach( $attributes as $attribute => $value ) {
+               $attribs = array();
+               foreach( $stripped as $attribute => $value ) {
                        $encAttribute = htmlspecialchars( $attribute );
                        $encValue = Sanitizer::safeEncodeAttribute( $value );
 
-                       $chunks[] = "$encAttribute=\"$encValue\"";
+                       $attribs[] = "$encAttribute=\"$encValue\"";
                }
-               return count( $chunks ) ? ' ' . implode( ' ', $chunks ) : '';
+               return count( $attribs ) ? ' ' . implode( ' ', $attribs ) : '';
        }
 
        /**
@@ -1187,7 +1093,8 @@ class Sanitizer {
         * for XML and XHTML specifically. Any stray bits will be
         * &-escaped to result in a valid text fragment.
         *
-        * a. any named char refs must be known in XHTML
+        * a. named char refs can only be < > & ", others are
+        *   numericized (this way we're well-formed even without a DTD)
         * b. any numeric char refs must be legal chars, not invalid or forbidden
         * c. use &#x, not &#X
         * d. fix or reject non-valid attributes
@@ -1214,8 +1121,6 @@ class Sanitizer {
                        $ret = Sanitizer::decCharReference( $matches[2] );
                } elseif( $matches[3] != ''  ) {
                        $ret = Sanitizer::hexCharReference( $matches[3] );
-               } elseif( $matches[4] != '' ) {
-                       $ret = Sanitizer::hexCharReference( $matches[4] );
                }
                if( is_null( $ret ) ) {
                        return htmlspecialchars( $matches[0] );
@@ -1226,9 +1131,10 @@ class Sanitizer {
 
        /**
         * If the named entity is defined in the HTML 4.0/XHTML 1.0 DTD,
-        * return the named entity reference as is. If the entity is a
-        * MediaWiki-specific alias, returns the HTML equivalent. Otherwise,
-        * returns HTML-escaped text of pseudo-entity source (eg &foo;)
+        * return the equivalent numeric entity reference (except for the core <
+        * > & "). If the entity is a MediaWiki-specific alias, returns
+        * the HTML equivalent. Otherwise, returns HTML-escaped text of
+        * pseudo-entity source (eg &foo;)
         *
         * @param $name String
         * @return String
@@ -1237,8 +1143,11 @@ class Sanitizer {
                global $wgHtmlEntities, $wgHtmlEntityAliases;
                if ( isset( $wgHtmlEntityAliases[$name] ) ) {
                        return "&{$wgHtmlEntityAliases[$name]};";
-               } elseif( isset( $wgHtmlEntities[$name] ) ) {
+               } elseif ( in_array( $name,
+               array( 'lt', 'gt', 'amp', 'quot' ) ) ) {
                        return "&$name;";
+               } elseif ( isset( $wgHtmlEntities[$name] ) ) {
+                       return "&#{$wgHtmlEntities[$name]};";
                } else {
                        return "&$name;";
                }
@@ -1325,8 +1234,6 @@ class Sanitizer {
                        return  Sanitizer::decodeChar( intval( $matches[2] ) );
                } elseif( $matches[3] != ''  ) {
                        return  Sanitizer::decodeChar( hexdec( $matches[3] ) );
-               } elseif( $matches[4] != '' ) {
-                       return  Sanitizer::decodeChar( hexdec( $matches[4] ) );
                }
                # Last case should be an ampersand by itself
                return $matches[0];