From 4d3446a8e3e580df1b496bff95e692ac46ff66e0 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Fri, 13 Jul 2007 17:25:06 +0000 Subject: [PATCH] * (bug 10508) Allow HTML attributes on * (bug 1962) Allow HTML attributes on --- RELEASE-NOTES | 3 ++ includes/ImageGallery.php | 23 ++++++++++++++- includes/Math.php | 39 +++++++++++++++++++------ includes/Parser.php | 4 ++- includes/Sanitizer.php | 60 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 117 insertions(+), 12 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index ceb49b2a2f..1c3aef7a47 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -132,6 +132,9 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN * Allow showing a one-off preview on first edit with "preview=yes" * (bug 9151) Remove timed redirects on "Return to X" pages for accessibility. * Link to user logs in toolbox when viewing a user page +* (bug 10508) Allow HTML attributes on +* (bug 1962) Allow HTML attributes on + == Bugfixes since 1.10 == diff --git a/includes/ImageGallery.php b/includes/ImageGallery.php index aa8c323941..8d7c36d80f 100644 --- a/includes/ImageGallery.php +++ b/includes/ImageGallery.php @@ -32,6 +32,8 @@ class ImageGallery private $mPerRow = 4; // How many images wide should the gallery be? private $mWidths = 120, $mHeights = 120; // How wide/tall each thumbnail should be + + private $mAttribs = array(); /** * Create a new image gallery object. @@ -181,6 +183,19 @@ class ImageGallery function setShowFilename( $f ) { $this->mShowFilename = ( $f == true); } + + /** + * Set arbitrary attributes to go on the HTML gallery output element. + * Should be suitable for a <table> element. + * + * Note -- if taking from user input, you should probably run through + * Sanitizer::validateAttributes() first. + * + * @param array of HTML attribute pairs + */ + function setAttributes( $attribs ) { + $this->mAttribs = $attribs; + } /** * Return a HTML representation of the image gallery @@ -197,7 +212,13 @@ class ImageGallery $sk = $this->getSkin(); - $s = ''; + $attribs = Sanitizer::mergeAttributes( + array( + 'class' => 'gallery', + 'cellspacing' => '0', + 'cellpadding' => '0' ), + $this->mAttribs ); + $s = Xml::openElement( 'table', $attribs ); if( $this->mCaption ) $s .= "\n\t"; diff --git a/includes/Math.php b/includes/Math.php index c2dd0413ba..2771d04cbb 100644 --- a/includes/Math.php +++ b/includes/Math.php @@ -20,8 +20,9 @@ class MathRenderer { var $mathml = ''; var $conservativeness = 0; - function __construct( $tex ) { + function __construct( $tex, $params=array() ) { $this->tex = $tex; + $this->params = $params; } function setOutputMode( $mode ) { @@ -233,24 +234,44 @@ class MathRenderer { */ function _doRender() { if( $this->mode == MW_MATH_MATHML && $this->mathml != '' ) { - return "{$this->mathml}"; + return Xml::tags( 'math', + $this->_attribs( 'math', + array( 'xmlns' => 'http://www.w3.org/1998/Math/MathML' ) ), + $this->mathml ); } if (($this->mode == MW_MATH_PNG) || ($this->html == '') || (($this->mode == MW_MATH_SIMPLE) && ($this->conservativeness != 2)) || (($this->mode == MW_MATH_MODERN || $this->mode == MW_MATH_MATHML) && ($this->conservativeness == 0))) { return $this->_linkToMathImage(); } else { - return ''.$this->html.''; + return Xml::tags( 'span', + $this->_attribs( 'span', + array( 'class' => 'texhtml' ) ), + $this->html ); } } + + function _attribs( $tag, $defaults=array(), $overrides=array() ) { + $attribs = Sanitizer::validateTagAttributes( $this->params, $tag ); + $attribs = Sanitizer::mergeAttributes( $defaults, $attribs ); + $attribs = Sanitizer::mergeAttributes( $attribs, $overrides ); + return $attribs; + } function _linkToMathImage() { global $wgMathPath; - $url = htmlspecialchars( "$wgMathPath/" . substr($this->hash, 0, 1) + $url = "$wgMathPath/" . substr($this->hash, 0, 1) .'/'. substr($this->hash, 1, 1) .'/'. substr($this->hash, 2, 1) - . "/{$this->hash}.png" ); - $alt = trim(str_replace("\n", ' ', htmlspecialchars( $this->tex ))); - return "\"$alt\""; + . "/{$this->hash}.png"; + + return Xml::element( 'img', + $this->_attribs( + 'img', + array( + 'class' => 'tex', + 'alt' => $this->tex ), + array( + 'src' => $url ) ) ); } function _getHashPath() { @@ -262,9 +283,9 @@ class MathRenderer { return $path; } - public static function renderMath( $tex ) { + public static function renderMath( $tex, $params=array() ) { global $wgUser; - $math = new MathRenderer( $tex ); + $math = new MathRenderer( $tex, $params ); $math->setOutputMode( $wgUser->getOption('math')); return $math->render(); } diff --git a/includes/Parser.php b/includes/Parser.php index 34959437a5..04cd9ed741 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -592,7 +592,8 @@ class Parser $output = Xml::escapeTagsOnly( $content ); break; case 'math': - $output = $wgContLang->armourMath( MathRenderer::renderMath( $content ) ); + $output = $wgContLang->armourMath( + MathRenderer::renderMath( $content, $params ) ); break; case 'gallery': $output = $this->renderImageGallery( $content, $params ); @@ -4381,6 +4382,7 @@ class Parser $ig->setShowBytes( false ); $ig->setShowFilename( false ); $ig->setParsing(); + $ig->setAttributes( Sanitizer::validateTagAttributes( $params, 'table' ) ); $ig->useSkin( $this->mOptions->getSkin() ); $ig->mRevisionId = $this->mRevisionId; diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index 7d33bd8002..ffe10f9c48 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -566,6 +566,7 @@ class Sanitizer { * * - Discards attributes not on a whitelist for the given element * - Unsafe style attributes are discarded + * - Invalid id attributes are reencoded * * @param array $attribs * @param string $element @@ -575,7 +576,27 @@ class Sanitizer { * @todo Check for unique id attribute :P */ static function validateTagAttributes( $attribs, $element ) { - $whitelist = array_flip( Sanitizer::attributeWhitelist( $element ) ); + return Sanitizer::validateAttributes( $attribs, + Sanitizer::attributeWhitelist( $element ) ); + } + + /** + * Take an array of attribute names and values and normalize or discard + * illegal values for the given whitelist. + * + * - Discards attributes not the given whitelist + * - Unsafe style attributes are discarded + * - Invalid id attributes are reencoded + * + * @param array $attribs + * @param array $whitelist list of allowed attribute names + * @return array + * + * @todo Check for legal values where the DTD limits things. + * @todo Check for unique id attribute :P + */ + static function validateAttributes( $attribs, $whitelist ) { + $whitelist = array_flip( $whitelist ); $out = array(); foreach( $attribs as $attribute => $value ) { if( !isset( $whitelist[$attribute] ) ) { @@ -601,6 +622,33 @@ class Sanitizer { return $out; } + /** + * Merge two sets of HTML attributes. + * Conflicting items in the second set will override those + * in the first, except for 'class' attributes which will be + * combined. + * + * @todo implement merging for other attributes such as style + * @param array $a + * @param array $b + * @return array + */ + static function mergeAttributes( $a, $b ) { + $out = array_merge( $a, $b ); + if( isset( $a['class'] ) + && isset( $b['class'] ) + && $a['class'] !== $b['class'] ) { + + $out['class'] = implode( ' ', + array_unique( + preg_split( '/\s+/', + $a['class'] . ' ' . $b['class'], + -1, + PREG_SPLIT_NO_EMPTY ) ) ); + } + return $out; + } + /** * Pick apart some CSS and check it for forbidden or unsafe structures. * Returns a sanitized string, or false if it was just too evil. @@ -1159,6 +1207,11 @@ class Sanitizer { # 11.2.6 'td' => array_merge( $common, $tablecell, $tablealign ), 'th' => array_merge( $common, $tablecell, $tablealign ), + + # 13.2 + # Not usually allowed, but may be used for extension-style hooks + # such as when it is rasterized + 'img' => array_merge( $common, array( 'alt' ) ), # 15.2.1 'tt' => $common, @@ -1185,6 +1238,11 @@ class Sanitizer { 'rb' => $common, 'rt' => $common, #array_merge( $common, array( 'rbspan' ) ), 'rp' => $common, + + # MathML root element, where used for extensions + # 'title' may not be 100% valid here; it's XHTML + # http://www.w3.org/TR/REC-MathML/ + 'math' => array( 'class', 'style', 'id', 'title' ), ); return $whitelist; } -- 2.20.1