* 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 ==
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.
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
$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>";
var $mathml = '';
var $conservativeness = 0;
- function __construct( $tex ) {
+ function __construct( $tex, $params=array() ) {
$this->tex = $tex;
+ $this->params = $params;
}
function setOutputMode( $mode ) {
*/
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() {
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();
}
$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 );
$ig->setShowBytes( false );
$ig->setShowFilename( false );
$ig->setParsing();
+ $ig->setAttributes( Sanitizer::validateTagAttributes( $params, 'table' ) );
$ig->useSkin( $this->mOptions->getSkin() );
$ig->mRevisionId = $this->mRevisionId;
*
* - 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
* @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] ) ) {
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.
# 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,
'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;
}