* (bug 10508) Allow HTML attributes on <gallery>

* (bug 1962) Allow HTML attributes on <math>
This commit is contained in:
Brion Vibber 2007-07-13 17:25:06 +00:00
parent 5855402233
commit 4d3446a8e3
5 changed files with 117 additions and 12 deletions

View file

@ -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 <gallery>
* (bug 1962) Allow HTML attributes on <math>
== Bugfixes since 1.10 ==

View file

@ -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 &lt;table&gt; 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 = '<table class="gallery" cellspacing="0" cellpadding="0">';
$attribs = Sanitizer::mergeAttributes(
array(
'class' => 'gallery',
'cellspacing' => '0',
'cellpadding' => '0' ),
$this->mAttribs );
$s = Xml::openElement( 'table', $attribs );
if( $this->mCaption )
$s .= "\n\t<caption>{$this->mCaption}</caption>";

View file

@ -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 "<math xmlns='http://www.w3.org/1998/Math/MathML'>{$this->mathml}</math>";
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 '<span class="texhtml">'.$this->html.'</span>';
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 "<img class='tex' src=\"$url\" alt=\"$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();
}

View file

@ -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;

View file

@ -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 <math> 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;
}