var $mTagHooks;
# Cleared with clearState():
- var $mOutput, $mAutonumber, $mDTopen, $mStripState = array();
+ var $mOutput, $mAutonumber, $mDTopen, $mStripState = array(), $mCurrentParams = array();
var $mVariables, $mIncludeCount, $mArgStack, $mLastSection, $mInPre;
var $mInterwikiLinkHolders, $mLinkHolders;
// in this path. Used for loop detection.
var $mIWTransData = array();
- var $mAssocArgs = array();
/**#@-*/
* @access public
*/
function Parser() {
- global $wgContLang;
$this->mTemplates = array();
$this->mTemplatePath = array();
$this->mTagHooks = array();
$this->mStripState = array();
$this->mArgStack = array();
$this->mInPre = false;
+ $this->mCurrentParams = array();
$this->mInterwikiLinkHolders = array(
'texts' => array(),
'titles' => array()
wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
$text = Sanitizer::normalizeCharReferences( $text );
- global $wgUseTidy;
+
if ($wgUseTidy) {
$text = Parser::tidy($text);
}
}
# math
- $text = Parser::extractTags('math', $text, $math_content, $uniq_prefix);
- foreach( $math_content as $marker => $content ){
- if( $render ) {
- if( $this->mOptions->getUseTeX() ) {
+ if( $this->mOptions->getUseTeX() ) {
+ $text = Parser::extractTags('math', $text, $math_content, $uniq_prefix);
+ foreach( $math_content as $marker => $content ){
+ if( $render ) {
$math_content[$marker] = renderMath( $content );
} else {
- $math_content[$marker] = '<math>'.$content.'<math>';
+ $math_content[$marker] = '<math>'.$content.'</math>';
}
- } else {
- $math_content[$marker] = '<math>'.$content.'</math>';
}
}
$text = Parser::extractTagsAndParams( $tag, $text, $ext_content[$tag],
$ext_tags[$tag], $ext_params[$tag], $uniq_prefix );
foreach( $ext_content[$tag] as $marker => $content ) {
+ $content = $this->replaceVariables( $content, $this->mCurrentParams );
$full_tag = $ext_tags[$tag][$marker];
$params = $ext_params[$tag][$marker];
if ( $render ) {
$fc = substr ( $x , 0 , 1 ) ;
if ( preg_match( '/^(:*)\{\|(.*)$/', $x, $matches ) ) {
$indent_level = strlen( $matches[1] );
+
+ $attributes = $this->unstripForHTML( $matches[2] );
+
$t[$k] = str_repeat( '<dl><dd>', $indent_level ) .
- '<table' . Sanitizer::fixTagAttributes ( $matches[2], 'table' ) . '>' ;
+ '<table' . Sanitizer::fixTagAttributes ( $attributes, 'table' ) . '>' ;
array_push ( $td , false ) ;
array_push ( $ltd , '' ) ;
array_push ( $tr , false ) ;
array_push ( $tr , false ) ;
array_push ( $td , false ) ;
array_push ( $ltd , '' ) ;
- array_push ( $ltr , Sanitizer::fixTagAttributes ( $x, 'tr' ) ) ;
+ $attributes = $this->unstripForHTML( $x );
+ array_push ( $ltr , Sanitizer::fixTagAttributes ( $attributes, 'tr' ) ) ;
}
else if ( '|' == $fc || '!' == $fc || '|+' == substr ( $x , 0 , 2 ) ) { # Caption
# $x is a table row
}
if ( count ( $y ) == 1 )
$y = "{$z}<{$l}>{$y[0]}" ;
- else $y = $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($y[0], $l).">{$y[1]}" ;
+ else {
+ $attributes = $this->unstripForHTML( $y[0] );
+ $y = "{$z}<{$l}".Sanitizer::fixTagAttributes($attributes, $l).">{$y[1]}" ;
+ }
$t[$k] .= $y ;
array_push ( $td , true ) ;
}
$text = strtr( $text, array( '<noinclude>' => '', '</noinclude>' => '') );
$text = preg_replace( '/<includeonly>.*?<\/includeonly>/s', '', $text );
- $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ) );
+ $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'attributeStripCallback' ) );
$text = $this->replaceVariables( $text, $args );
$text = preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text );
# replaceInternalLinks may sometimes leave behind
# absolute URLs, which have to be masked to hide them from replaceExternalLinks
- $text = str_replace("http-noparse://","http://",$text);
+ $text = str_replace(UNIQ_PREFIX."NOPARSE", "", $text);
$text = $this->doMagicLinks( $text );
$text = $this->doTableStuff( $text );
function doExponent( $text ) {
$fname = 'Parser::doExponent';
wfProfileIn( $fname );
- $text = preg_replace('/\^\^(.*)\^\^/','<small><sup>\\1</sup></small>', $text);
+ $text = preg_replace('/\^\^(.*?)\^\^/','<small><sup>\\1</sup></small>', $text);
wfProfileOut( $fname );
return $text;
}
$found = false;
while (isset ($a[$k+1]) ) {
#look at the next 'line' to see if we can close it there
- $next_line = array_shift(array_splice( $a, $k + 1, 1) );
+ $spliced = array_splice( $a, $k + 1, 1 );
+ $next_line = array_shift( $spliced );
if( preg_match("/^(.*?]].*?)]](.*)$/sD", $next_line, $m) ) {
# the first ]] closes the inner link, the second the image
$found = true;
$text = $this->replaceInternalLinks($text);
# cloak any absolute URLs inside the image markup, so replaceExternalLinks() won't touch them
- $s .= $prefix . str_replace('http://', 'http-noparse://', $this->makeImage( $nt, $text ) ) . $trail;
+ $s .= $prefix . preg_replace("/\b($wgUrlProtocols)/", UNIQ_PREFIX."NOPARSE$1", $this->makeImage( $nt, $text) ) . $trail;
$wgLinkCache->addImageLinkObj( $nt );
wfProfileOut( "$fname-image" );
$s .= $prefix . $sk->makeKnownLinkObj( $nt, $text, '', $trail );
continue;
}
- if( !$nt->isExternal() && $nt->isAlwaysKnown() ) {
- /**
- * Skip lookups for special pages and self-links.
- * External interwiki links are not included here because
- * the HTTP urls would break output in the next parse step;
- * they will have placeholders kept.
- */
- $s .= $sk->makeKnownLinkObj( $nt, $text, '', $trail, $prefix );
- } else {
- /**
- * Add a link placeholder
- * Later, this will be replaced by a real link, after the existence or
- * non-existence of all the links is known
- */
- $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix );
- }
+ $s .= $this->makeLinkHolder( $nt, $text, '', $trail, $prefix );
}
wfProfileOut( $fname );
return $s;
}
}
- # LOCALURL and LOCALURLE
+ # LOCALURL and FULLURL
if ( !$found ) {
- $mwLocal = MagicWord::get( MAG_LOCALURL );
- $mwLocalE = MagicWord::get( MAG_LOCALURLE );
+ $mwLocal =& MagicWord::get( MAG_LOCALURL );
+ $mwLocalE =& MagicWord::get( MAG_LOCALURLE );
+ $mwFull =& MagicWord::get( MAG_FULLURL );
+ $mwFullE =& MagicWord::get( MAG_FULLURLE );
+
if ( $mwLocal->matchStartAndRemove( $part1 ) ) {
$func = 'getLocalURL';
} elseif ( $mwLocalE->matchStartAndRemove( $part1 ) ) {
$func = 'escapeLocalURL';
+ } elseif ( $mwFull->matchStartAndRemove( $part1 ) ) {
+ $func = 'getFullURL';
+ } elseif ( $mwFullE->matchStartAndRemove( $part1 ) ) {
+ $func = 'escapeFullURL';
} else {
- $func = '';
+ $func = false;
}
- if ( $func !== '' ) {
+ if ( $func !== false ) {
$title = Title::newFromText( $part1 );
if ( !is_null( $title ) ) {
if ( $argc > 0 ) {
}
}
+ # PLURAL
+ if ( !$found && $argc >= 2 ) {
+ $mwPluralForm =& MagicWord::get( MAG_PLURAL );
+ if ( $mwPluralForm->matchStartAndRemove( $part1 ) ) {
+ if ($argc==2) {$args[2]=$args[1];}
+ $text = $linestart . $wgContLang->convertPlural( $part1, $args[0], $args[1], $args[2]);
+ $found = true;
+ }
+ }
+
# Template table test
# Did we encounter this template already? If yes, it is in the cache
$text = wfEscapeWikiText( $text );
} elseif ( ($this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI) && $found && !$noparse) {
# Clean up argument array
- $this->mAssocArgs = array();
+ $assocArgs = array();
$index = 1;
foreach( $args as $arg ) {
$eqpos = strpos( $arg, '=' );
if ( $eqpos === false ) {
- $this->mAssocArgs[$index++] = $arg;
+ $assocArgs[$index++] = $arg;
} else {
$name = trim( substr( $arg, 0, $eqpos ) );
$value = trim( substr( $arg, $eqpos+1 ) );
$value = '';
}
if ( $name !== false ) {
- $this->mAssocArgs[$name] = $value;
+ $assocArgs[$name] = $value;
}
}
}
$text = preg_replace( '/<noinclude>.*?<\/noinclude>/s', '', $text );
$text = strtr( $text, array( '<includeonly>' => '' , '</includeonly>' => '' ) );
# Strip <nowiki>, <pre>, etc.
+ $this->mCurrentParams = $assocArgs;
$text = $this->strip( $text, $this->mStripState );
- $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $this->mAssocArgs );
+ $text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs );
}
- $text = $this->replaceVariables( $text, $this->mAssocArgs );
+ $text = $this->replaceVariables( $text, $assocArgs );
# Resume the link cache and register the inclusion as a link
if ( $this->mOutputType == OT_HTML && !is_null( $title ) ) {
$pdbk = $pdbks[$key] = $title->getPrefixedDBkey();
# Check if it's in the link cache already
- if ( $wgLinkCache->getGoodLinkID( $pdbk ) ) {
+ if ( $title->isAlwaysKnown() || $wgLinkCache->getGoodLinkID( $pdbk ) ) {
$colours[$pdbk] = 1;
} elseif ( $wgLinkCache->isBadLink( $pdbk ) ) {
$colours[$pdbk] = 0;
$part = explode( '|', $options);
$mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
+ $mwManualThumb =& MagicWord::get( MAG_IMG_MANUALTHUMB );
$mwLeft =& MagicWord::get( MAG_IMG_LEFT );
$mwRight =& MagicWord::get( MAG_IMG_RIGHT );
$mwNone =& MagicWord::get( MAG_IMG_NONE );
$manual_thumb = '' ;
foreach( $part as $key => $val ) {
- $val_parts = explode ( '=' , $val , 2 ) ;
- $left_part = array_shift ( $val_parts ) ;
if ( $wgUseImageResize && ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
$thumb=true;
- } elseif ( $wgUseImageResize && count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
+ } elseif ( ! is_null( $match = $mwManualThumb->matchVariableStartToEnd($val) ) ) {
# use manually specified thumbnail
$thumb=true;
- $manual_thumb = array_shift ( $val_parts ) ;
+ $manual_thumb = $match;
} elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
# remember to set an alignment, don't render immediately
$align = 'right';
function disableCache() {
$this->mOutput->mCacheTime = -1;
}
+
+ /**
+ * Callback from the Sanitizer for expanding items found in HTML attribute
+ * values, so they can be safely tested and escaped.
+ * @param string $text
+ * @param array $args
+ * @return string
+ * @access private
+ */
+ function attributeStripCallback( &$text, $args ) {
+ $text = $this->replaceVariables( $text, $args );
+ $text = $this->unstripForHTML( $text );
+ return $text;
+ }
+
+ function unstripForHTML( $text ) {
+ $text = $this->unstrip( $text, $this->mStripState );
+ $text = $this->unstripNoWiki( $text, $this->mStripState );
+ return $text;
+ }
}
/**