X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FHtml.php;h=48b30c7802d8eba18eb493feb7e2bd367cfa1175;hb=4a2085523fce81ba4d75eb6946f5c7ae069bb1d2;hp=890beb0e0d767cad0ccddb5ece7ed7318c8c8a6e;hpb=29906d505b9b3d5f0fd1e6534f077b7fe2c623dc;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/Html.php b/includes/Html.php index 890beb0e0d..48b30c7802 100644 --- a/includes/Html.php +++ b/includes/Html.php @@ -38,8 +38,6 @@ * * $wgMimeType: If this is set to an xml MIME type then output should be * valid XHTML5. - * $wgWellFormedXml: If this is set to true, then all output should be - * well-formed XML (quotes on attributes, self-closing tags, etc.). * * This class is meant to be confined to utility functions that are called from * trusted code paths. It does not do enforcement of policy like not allowing @@ -48,13 +46,12 @@ * @since 1.16 */ class Html { - // List of void elements from HTML5, section 8.1.2 as of 2011-08-12 + // List of void elements from HTML5, section 8.1.2 as of 2016-09-19 private static $voidElements = [ 'area', 'base', 'br', 'col', - 'command', 'embed', 'hr', 'img', @@ -158,8 +155,8 @@ class Html { * * @param string $contents The raw HTML contents of the element: *not* * escaped! - * @param array $attrs Associative array of attributes, e.g., array( - * 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for + * @param array $attrs Associative array of attributes, e.g., [ + * 'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param string[] $modifiers classes to add to the button * @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers @@ -178,8 +175,8 @@ class Html { * * @param string $contents The raw HTML contents of the element: *not* * escaped! - * @param array $attrs Associative array of attributes, e.g., array( - * 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for + * @param array $attrs Associative array of attributes, e.g., [ + * 'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param string[] $modifiers classes to add to the button * @see http://tools.wmflabs.org/styleguide/desktop/index.html for guidance on available modifiers @@ -199,26 +196,21 @@ class Html { * This is quite similar to Xml::tags(), but it implements some useful * HTML-specific logic. For instance, there is no $allowShortTag * parameter: the closing tag is magically omitted if $element has an empty - * content model. If $wgWellFormedXml is false, then a few bytes will be - * shaved off the HTML output as well. + * content model. * * @param string $element The element's name, e.g., 'a' - * @param array $attribs Associative array of attributes, e.g., array( - * 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for + * @param array $attribs Associative array of attributes, e.g., [ + * 'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @param string $contents The raw HTML contents of the element: *not* * escaped! * @return string Raw HTML */ public static function rawElement( $element, $attribs = [], $contents = '' ) { - global $wgWellFormedXml; $start = self::openElement( $element, $attribs ); if ( in_array( $element, self::$voidElements ) ) { - if ( $wgWellFormedXml ) { - // Silly XML. - return substr( $start, 0, -1 ) . '/>'; - } - return $start; + // Silly XML. + return substr( $start, 0, -1 ) . '/>'; } else { return "$start$contents" . self::closeElement( $element ); } @@ -328,8 +320,8 @@ class Html { * to the input array (currently per the HTML 5 draft as of 2009-09-06). * * @param string $element Name of the element, e.g., 'a' - * @param array $attribs Associative array of attributes, e.g., array( - * 'href' => 'http://www.mediawiki.org/' ). See expandAttributes() for + * @param array $attribs Associative array of attributes, e.g., [ + * 'href' => 'http://www.mediawiki.org/' ]. See expandAttributes() for * further documentation. * @return array An array of attributes functionally identical to $attribs */ @@ -346,7 +338,6 @@ class Html { 'height' => '150', 'width' => '300', ], - 'command' => [ 'type' => 'command' ], 'form' => [ 'action' => 'GET', 'autocomplete' => 'on', @@ -439,12 +430,10 @@ class Html { /** * Given an associative array of element attributes, generate a string - * to stick after the element name in HTML output. Like array( 'href' => - * 'http://www.mediawiki.org/' ) becomes something like + * to stick after the element name in HTML output. Like [ 'href' => + * 'http://www.mediawiki.org/' ] becomes something like * ' href="http://www.mediawiki.org"'. Again, this is like * Xml::expandAttributes(), but it implements some HTML-specific logic. - * For instance, it will omit quotation marks if $wgWellFormedXml is false, - * and will treat boolean attributes specially. * * Attributes that can contain space-separated lists ('class', 'accesskey' and 'rel') array * values are allowed as well, which will automagically be normalized @@ -454,42 +443,40 @@ class Html { * * @par Numerical array * @code - * Html::element( 'em', array( - * 'class' => array( 'foo', 'bar' ) - * ) ); + * Html::element( 'em', [ + * 'class' => [ 'foo', 'bar' ] + * ] ); * // gives '' * @endcode * * @par Associative array * @code - * Html::element( 'em', array( - * 'class' => array( 'foo', 'bar', 'foo' => false, 'quux' => true ) - * ) ); + * Html::element( 'em', [ + * 'class' => [ 'foo', 'bar', 'foo' => false, 'quux' => true ] + * ] ); * // gives '' * @endcode * - * @param array $attribs Associative array of attributes, e.g., array( - * 'href' => 'http://www.mediawiki.org/' ). Values will be HTML-escaped. + * @param array $attribs Associative array of attributes, e.g., [ + * 'href' => 'http://www.mediawiki.org/' ]. Values will be HTML-escaped. * A value of false means to omit the attribute. For boolean attributes, - * you can omit the key, e.g., array( 'checked' ) instead of - * array( 'checked' => 'checked' ) or such. + * you can omit the key, e.g., [ 'checked' ] instead of + * [ 'checked' => 'checked' ] or such. * * @throws MWException If an attribute that doesn't allow lists is set to an array * @return string HTML fragment that goes between element name and '>' * (starting with a space if at least one attribute is output) */ public static function expandAttributes( array $attribs ) { - global $wgWellFormedXml; - $ret = ''; foreach ( $attribs as $key => $value ) { - // Support intuitive array( 'checked' => true/false ) form + // Support intuitive [ 'checked' => true/false ] form if ( $value === false || is_null( $value ) ) { continue; } - // For boolean attributes, support array( 'foo' ) instead of - // requiring array( 'foo' => 'meaningless' ). + // For boolean attributes, support [ 'foo' ] instead of + // requiring [ 'foo' => 'meaningless' ]. if ( is_int( $key ) && in_array( strtolower( $value ), self::$boolAttribs ) ) { $key = $value; } @@ -546,7 +533,7 @@ class Html { } } elseif ( $v ) { // If the value is truthy but not a string this is likely - // an array( 'foo' => true ), falsy values don't add strings + // an [ 'foo' => true ], falsy values don't add strings $newValue[] = $k; } } @@ -564,31 +551,10 @@ class Html { throw new MWException( "HTML attribute $key can not contain a list of values" ); } - // See the "Attributes" section in the HTML syntax part of HTML5, - // 9.1.2.3 as of 2009-08-10. Most attributes can have quotation - // marks omitted, but not all. (Although a literal " is not - // permitted, we don't check for that, since it will be escaped - // anyway.) - - // See also research done on further characters that need to be - // escaped: http://code.google.com/p/html5lib/issues/detail?id=93 - $badChars = "\\x00- '=<>`/\x{00a0}\x{1680}\x{180e}\x{180F}\x{2000}\x{2001}" - . "\x{2002}\x{2003}\x{2004}\x{2005}\x{2006}\x{2007}\x{2008}\x{2009}" - . "\x{200A}\x{2028}\x{2029}\x{202F}\x{205F}\x{3000}"; - if ( $wgWellFormedXml || $value === '' || preg_match( "![$badChars]!u", $value ) ) { - $quote = '"'; - } else { - $quote = ''; - } + $quote = '"'; if ( in_array( $key, self::$boolAttribs ) ) { - // In HTML5, we can leave the value empty. If we don't need - // well-formed XML, we can omit the = entirely. - if ( !$wgWellFormedXml ) { - $ret .= " $key"; - } else { - $ret .= " $key=\"\""; - } + $ret .= " $key=\"\""; } else { // Apparently we need to entity-encode \n, \r, \t, although the // spec doesn't mention that. Since we're doing strtr() anyway, @@ -599,22 +565,18 @@ class Html { // don't because we're stubborn and like our marginal savings on // byte size from not having to encode unnecessary quotes. // The only difference between this transform and the one by - // Sanitizer::encodeAttribute() is '<' is only encoded here if - // $wgWellFormedXml is set, and ' is not encoded. + // Sanitizer::encodeAttribute() is ' is not encoded. $map = [ '&' => '&', '"' => '"', '>' => '>', + // '<' allegedly allowed per spec + // but breaks some tools if not escaped. + "<" => '<', "\n" => ' ', "\r" => ' ', "\t" => ' ' ]; - if ( $wgWellFormedXml ) { - // This is allowed per spec: - // But reportedly it breaks some XML tools? - // @todo FIXME: Is this really true? - $map['<'] = '<'; - } $ret .= " $key=$quote" . strtr( $value, $map ) . $quote; } } @@ -631,11 +593,9 @@ class Html { * @return string Raw HTML */ public static function inlineScript( $contents ) { - global $wgWellFormedXml; - $attrs = []; - if ( $wgWellFormedXml && preg_match( '/[<&]/', $contents ) ) { + if ( preg_match( '/[<&]/', $contents ) ) { $contents = "/**/"; } @@ -665,9 +625,18 @@ class Html { * @return string Raw HTML */ public static function inlineStyle( $contents, $media = 'all' ) { - global $wgWellFormedXml; + // Don't escape '>' since that is used + // as direct child selector. + // Remember, in css, there is no "x" for hexadecimal escapes, and + // the space immediately after an escape sequence is swallowed. + $contents = strtr( $contents, [ + '<' => '\3C ', + // CDATA end tag for good measure, but the main security + // is from escaping the '<'. + ']]>' => '\5D\5D\3E ' + ] ); - if ( $wgWellFormedXml && preg_match( '/[<&]/', $contents ) ) { + if ( preg_match( '/[<&]/', $contents ) ) { $contents = "/**/"; } @@ -975,13 +944,7 @@ class Html { $attribs['version'] = $wgHtml5Version; } - $html = self::openElement( 'html', $attribs ); - - if ( $html ) { - $html .= "\n"; - } - - $ret .= $html; + $ret .= self::openElement( 'html', $attribs ); return $ret; } @@ -1046,11 +1009,11 @@ class Html { * * @par Example: * @code - * Html::srcSet( array( + * Html::srcSet( [ * '1x' => 'standard.jpeg', * '1.5x' => 'large.jpeg', * '3x' => 'extra-large.jpeg', - * ) ); + * ] ); * // gives 'standard.jpeg 1x, large.jpeg 1.5x, extra-large.jpeg 2x' * @endcode * @@ -1060,9 +1023,21 @@ class Html { static function srcSet( array $urls ) { $candidates = []; foreach ( $urls as $density => $url ) { - // Cast density to float to strip 'x'. - $candidates[] = $url . ' ' . (float)$density . 'x'; + // Cast density to float to strip 'x', then back to string to serve + // as array index. + $density = (string)(float)$density; + $candidates[$density] = $url; } + + // Remove duplicates that are the same as a smaller value + ksort( $candidates, SORT_NUMERIC ); + $candidates = array_unique( $candidates ); + + // Append density info to the url + foreach ( $candidates as $density => $url ) { + $candidates[$density] = $url . ' ' . $density . 'x'; + } + return implode( ", ", $candidates ); } }