define( 'HTTP_PROTOCOLS', 'http:\/\/|https:\/\/' );
# Everything except bracket, space, or control characters
define( 'EXT_LINK_URL_CLASS', '[^][<>"\\x00-\\x20\\x7F]' );
-# Including space
-define( 'EXT_LINK_TEXT_CLASS', '[^\]\\x00-\\x1F\\x7F]' );
+# Including space, but excluding newlines
+define( 'EXT_LINK_TEXT_CLASS', '[^\]\\x0a\\x0d]' );
define( 'EXT_IMAGE_FNAME_CLASS', '[A-Za-z0-9_.,~%\\-+&;#*?!=()@\\x80-\\xFF]' );
define( 'EXT_IMAGE_EXTENSIONS', 'gif|png|jpg|jpeg' );
-define( 'EXT_LINK_BRACKETED', '/\[(\b(' . wfUrlProtocols() . ')'.EXT_LINK_URL_CLASS.'+) *('.EXT_LINK_TEXT_CLASS.'*?)\]/S' );
+define( 'EXT_LINK_BRACKETED', '/\[(\b(' . wfUrlProtocols() . ')'.
+ EXT_LINK_URL_CLASS.'+) *('.EXT_LINK_TEXT_CLASS.'*?)\]/S' );
define( 'EXT_IMAGE_REGEX',
'/^('.HTTP_PROTOCOLS.')'. # Protocol
'('.EXT_LINK_URL_CLASS.'+)\\/'. # Hostname and path
* will be stripped in addition to other tags. This is important
* for section editing, where these comments cause confusion when
* counting the sections in the wikisource
+ *
+ * @param array dontstrip contains tags which should not be stripped;
+ * used to prevent stipping of <gallery> when saving (fixes bug 2700)
*
* @private
*/
- function strip( $text, &$state, $stripcomments = false ) {
+ function strip( $text, &$state, $stripcomments = false , $dontstrip = array () ) {
$render = ($this->mOutputType == OT_HTML);
# Replace any instances of the placeholders
$elements[] = 'math';
}
-
+ # Removing $dontstrip tags from $elements list (currently only 'gallery', fixing bug 2700)
+ foreach ( $elements AS $k => $v ) {
+ if ( !in_array ( $v , $dontstrip ) ) continue;
+ unset ( $elements[$k] );
+ }
+
$matches = array();
$text = Parser::extractTagsAndParams( $elements, $text, $matches, $uniq_prefix );
-
+
foreach( $matches as $marker => $data ) {
list( $element, $content, $params, $tag ) = $data;
if( $render ) {
$output = MathRenderer::renderMath( $content );
break;
case 'gallery':
- $output = $this->renderImageGallery( $content );
+ $output = $this->renderImageGallery( $content, $params );
break;
default:
if( isset( $this->mTagHooks[$tagName] ) ) {
$output = call_user_func_array( $this->mTagHooks[$tagName],
array( $content, $params, $this ) );
} else {
- wfDebugDieBacktrace( "Invalid call hook $element" );
+ throw new MWException( "Invalid call hook $element" );
}
}
} else {
$state[$element][$marker] = $output;
}
}
-
+
# Unstrip comments unless explicitly told otherwise.
# (The comments are always stripped prior to this point, so as to
# not invoke any extension tags / parser hooks contained within
$text = preg_replace( '/(^|\n)-----*/', '\\1<hr />', $text );
$text = $this->stripToc( $text );
+ $this->stripNoGallery( $text );
$text = $this->doHeadings( $text );
if($this->mOptions->getUseDynamicDates()) {
$df =& DateFormatter::getInstance();
# Normalize any HTML entities in input. They will be
# re-escaped by makeExternalLink().
$url = Sanitizer::decodeCharReferences( $url );
+
+ # Escape any control characters introduced by the above step
+ $url = preg_replace( '/[\][<>"\\x00-\\x20\\x7F]/e', "urlencode('\\0')", $url );
# Process the trail (i.e. everything after this link up until start of the next link),
# replacing any non-bracketed links
# Normalize any HTML entities in input. They will be
# re-escaped by makeExternalLink() or maybeMakeExternalImage()
$url = Sanitizer::decodeCharReferences( $url );
+
+ # Escape any control characters introduced by the above step
+ $url = preg_replace( '/[\][<>"\\x00-\\x20\\x7F]/e', "urlencode('\\0')", $url );
# Is this an external image?
$text = $this->maybeMakeExternalImage( $url );
$useLinkPrefixExtension = $wgContLang->linkPrefixExtension();
if( is_null( $this->mTitle ) ) {
- wfDebugDieBacktrace( 'nooo' );
+ throw new MWException( 'nooo' );
}
$nottalk = !$this->mTitle->isTalkPage();
$sortkey = $text;
}
$sortkey = Sanitizer::decodeCharReferences( $sortkey );
+ $sortkey = str_replace( "\n", '', $sortkey );
$sortkey = $wgContLang->convertCategoryKey( $sortkey );
$this->mOutput->addCategory( $nt->getDBkey(), $sortkey );
wfProfileIn( "$fname-paragraph" );
# No prefix (not in list)--go to paragraph mode
// XXX: use a stack for nestable elements like span, table and div
- $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<center|<\\/tr|<\\/td|<\\/th)/iS', $t );
+ $openmatch = preg_match('/(<table|<blockquote|<h1|<h2|<h3|<h4|<h5|<h6|<pre|<tr|<p|<ul|<ol|<li|<\\/center|<\\/tr|<\\/td|<\\/th)/iS', $t );
$closematch = preg_match(
'/(<\\/table|<\\/blockquote|<\\/h1|<\\/h2|<\\/h3|<\\/h4|<\\/h5|<\\/h6|'.
- '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/center)/iS', $t );
+ '<td|<th|<div|<\\/div|<hr|<\\/pre|<\\/p|'.$this->mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<center)/iS', $t );
if ( $openmatch or $closematch ) {
$paragraphStack = false;
# TODO bug 5718: paragraph closed
}
break;
default:
- wfDebugDieBacktrace( "State machine error in $fname" );
+ throw new MWException( "State machine error in $fname" );
}
}
if( $stack > 0 ) {
return $varCache[$index] = $wgContLang->formatNum( wfNumberOfUsers() );
case MAG_NUMBEROFPAGES:
return $varCache[$index] = $wgContLang->formatNum( wfNumberOfPages() );
+ case MAG_NUMBEROFADMINS:
+ return $varCache[$index] = $wgContLang->formatNum( wfNumberOfAdmins() );
case MAG_CURRENTTIMESTAMP:
return $varCache[$index] = wfTimestampNow();
case MAG_CURRENTVERSION:
return $wgScriptPath;
case MAG_DIRECTIONMARK:
return $wgContLang->getDirMark();
+ case MAG_CONTENTLANGUAGE:
+ global $wgContLanguageCode;
+ return $wgContLanguageCode;
default:
$ret = null;
if ( wfRunHooks( 'ParserGetVariableValueSwitch', array( &$this, &$varCache, &$index, &$ret ) ) )
'text' => substr($text, $pieceStart, $pieceEnd - $pieceStart),
'title' => trim($openingBraceStack[$lastOpeningBrace]['title']),
'parts' => $openingBraceStack[$lastOpeningBrace]['parts'],
- 'lineStart' => (($pieceStart > 0) && ($text[$pieceStart-1] == '\n')),
+ 'lineStart' => (($pieceStart > 0) && ($text[$pieceStart-1] == "\n")),
);
# finally we can call a user callback and replace piece of text
$replaceWith = call_user_func( $matchingCallback, $cbArgs );
$text = $linestart . $wgContLang->getNsText( intval( $part1 ) );
$found = true;
} else {
- $index = Namespace::getCanonicalIndex( strtolower( $part1 ) );
+ $param = str_replace( ' ', '_', strtolower( $part1 ) );
+ $index = Namespace::getCanonicalIndex( strtolower( $param ) );
if ( !is_null( $index ) ) {
$text = $linestart . $wgContLang->getNsText( $index );
$found = true;
if ( !$found && $argc >= 2 ) {
$mwPluralForm =& MagicWord::get( MAG_PLURAL );
if ( $mwPluralForm->matchStartAndRemove( $part1 ) ) {
- if ($argc==2) {$args[2]=$args[1];}
- $text = $linestart . $lang->convertPlural( $part1, $args[0], $args[1], $args[2]);
+ while ( count($args) < 5 ) { $args[] = $args[count($args)-1]; }
+ $text = $linestart . $lang->convertPlural( $part1, $args[0], $args[1],
+ $args[2], $args[3], $args[4]);
$found = true;
}
}
$mwWordsToCheck = array( MAG_NUMBEROFPAGES => 'wfNumberOfPages',
MAG_NUMBEROFUSERS => 'wfNumberOfUsers',
MAG_NUMBEROFARTICLES => 'wfNumberOfArticles',
- MAG_NUMBEROFFILES => 'wfNumberOfFiles' );
+ MAG_NUMBEROFFILES => 'wfNumberOfFiles',
+ MAG_NUMBEROFADMINS => 'wfNumberOfAdmins' );
foreach( $mwWordsToCheck as $word => $func ) {
$mwCurrentWord =& MagicWord::get( $word );
if( $mwCurrentWord->matchStartAndRemove( $part1 ) ) {
$mwRawSuffix =& MagicWord::get( MAG_RAWSUFFIX );
- if( $mwRawSuffix->match( $args[0] ) ) {
+ if( isset( $args[0] ) && $mwRawSuffix->match( $args[0] ) ) {
# Raw and unformatted
$text = $linestart . call_user_func( $func );
} else {
}
}
}
+
+ # PAGESINNAMESPACE
+ if( !$found ) {
+ $mwPagesInNs =& MagicWord::get( MAG_PAGESINNAMESPACE );
+ if( $mwPagesInNs->matchStartAndRemove( $part1 ) ) {
+ $found = true;
+ $count = wfPagesInNs( intval( $part1 ) );
+ $mwRawSuffix =& MagicWord::get( MAG_RAWSUFFIX );
+ if( isset( $args[0] ) && $mwRawSuffix->match( $args[0] ) ) {
+ $text = $linestart . $count;
+ } else {
+ $text = $linestart . $wgContLang->formatNum( $count );
+ }
+ }
+ }
# #LANGUAGE:
if( !$found ) {
$colonPos = strpos( $part1, ':' );
if ( $colonPos !== false ) {
$function = strtolower( substr( $part1, 1, $colonPos - 1 ) );
+ if ( !isset( $this->mFunctionHooks[$function] ) ) {
+ foreach ($this->mFunctionHooks as $key => $value) {
+ if( is_int( $key ) ) {
+ $mwExtension =& MagicWord::get( $key );
+ if( $mwExtension->matchVariableStartToEnd( $function ) ) {
+ $function = $key;
+ break;
+ }
+ }
+ }
+ }
if ( isset( $this->mFunctionHooks[$function] ) ) {
$funcArgs = array_map( 'trim', $args );
$funcArgs = array_merge( array( &$this, trim( substr( $part1, $colonPos + 1 ) ) ), $funcArgs );
}
$title = Title::newFromText( $part1, $ns );
+
if ( !is_null( $title ) ) {
+ $checkVariantLink = sizeof($wgContLang->getVariants())>1;
+ # Check for language variants if the template is not found
+ if($checkVariantLink && $title->getArticleID() == 0){
+ $wgContLang->findVariantLink($part1, $title);
+ }
+
if ( !$title->isExternal() ) {
# Check for excessive inclusion
$dbk = $title->getPrefixedDBkey();
}
}
+ /**
+ * Detect __NOGALLERY__ magic word and set a placeholder
+ */
+ function stripNoGallery( &$text ) {
+ # if the string __NOGALLERY__ (not case-sensitive) occurs in the HTML,
+ # do not add TOC
+ $mw = MagicWord::get( MAG_NOGALLERY );
+ $this->mOutput->mNoGallery = $mw->matchAndRemove( $text ) ;
+ }
+
/**
* Detect __TOC__ magic word and set a placeholder
*/
$url = wfMsg( $urlmsg, $id);
$sk =& $this->mOptions->getSkin();
$la = $sk->getExternalLinkAttributes( $url, $keyword.$id );
- $text .= "<a href='{$url}'{$la}>{$keyword}{$id}</a>{$x}";
+ $text .= "<a href=\"{$url}\"{$la}>{$keyword}{$id}</a>{$x}";
}
/* Check if the next RFC keyword is preceed by [[ */
"\r\n" => "\n",
);
$text = str_replace( array_keys( $pairs ), array_values( $pairs ), $text );
- $text = $this->strip( $text, $stripState, true );
+ $text = $this->strip( $text, $stripState, true, array( 'gallery' ) );
$text = $this->pstPass2( $text, $stripState, $user );
$text = $this->unstrip( $text, $stripState );
$text = $this->unstripNoWiki( $text, $stripState );
$text = $this->replaceVariables( $text );
# Strip out <nowiki> etc. added via replaceVariables
- $text = $this->strip( $text, $stripState );
+ $text = $this->strip( $text, $stripState, false, array( 'gallery' ) );
# Signatures
$sigText = $this->getUserSig( $user );
}
}
+ // Make sure nickname doesnt get a sig in a sig
+ $nickname = $this->cleanSigInSig( $nickname );
+
# If we're still here, make it a link to the user page
$userpage = $user->getUserPage();
return( '[[' . $userpage->getPrefixedText() . '|' . wfEscapeWikiText( $nickname ) . ']]' );
/**
* Clean up signature text
*
- * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures
+ * 1) Strip ~~~, ~~~~ and ~~~~~ out of signatures @see cleanSigInSig
* 2) Substitute all transclusions
*
* @param string $text
$substText = '{{' . $substWord->getSynonym( 0 );
$text = preg_replace( $substRegex, $substText, $text );
- $text = preg_replace( '/~{3,5}/', '', $text );
+ $text = $this->cleanSigInSig( $text );
$text = $this->replaceVariables( $text );
$this->clearState();
return $text;
}
+
+ /**
+ * Strip ~~~, ~~~~ and ~~~~~ out of signatures
+ * @param string $text
+ * @return string Signature text with /~{3,5}/ removed
+ */
+ function cleanSigInSig( $text ) {
+ $text = preg_replace( '/~{3,5}/', '', $text );
+ return $text;
+ }
/**
* Set up some variables which are usually set up in parse()
*
* @public
*
- * @param string $name The function name. Function names are case-insensitive.
+ * @param mixed $id The magic word ID, or (deprecated) the function name. Function names are case-insensitive.
* @param mixed $callback The callback function (and object) to use
*
* @return The old callback function for this name, if any
*/
- function setFunctionHook( $name, $callback ) {
- $name = strtolower( $name );
- $oldVal = @$this->mFunctionHooks[$name];
- $this->mFunctionHooks[$name] = $callback;
+ function setFunctionHook( $id, $callback ) {
+ if( is_string( $id ) ) {
+ $id = strtolower( $id );
+ }
+ $oldVal = @$this->mFunctionHooks[$id];
+ $this->mFunctionHooks[$id] = $callback;
return $oldVal;
}
* labeled 'The number "1"' and
* 'A tree'.
*/
- function renderImageGallery( $text ) {
+ function renderImageGallery( $text, $params ) {
$ig = new ImageGallery();
$ig->setShowBytes( false );
$ig->setShowFilename( false );
$ig->setParsing();
- $lines = explode( "\n", $text );
+ $ig->useSkin( $this->mOptions->getSkin() );
+ if( isset( $params['caption'] ) )
+ $ig->setCaption( $params['caption'] );
+
+ $lines = explode( "\n", $text );
foreach ( $lines as $line ) {
# match lines like these:
# Image:someimage.jpg|This is some image
(=+) # Should this be limited to 6?
.+? # Section title...
\\2 # Ending = count must match start
- (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok
+ (?:$comment|<\/?noinclude>|[ \\t]+)* # Trailing whitespace ok
$
|
<h([1-6])\b.*?>
$mExternalLinks, # External link URLs, in the key only
$mHTMLtitle, # Display HTML title
$mSubtitle, # Additional subtitle
- $mNewSection; # Show a new section link?
+ $mNewSection, # Show a new section link?
+ $mNoGallery; # No gallery on category page? (__NOGALLERY__)
function ParserOutput( $text = '', $languageLinks = array(), $categoryLinks = array(),
$containsOldMagic = false, $titletext = '' )
$this->mHTMLtitle = "" ;
$this->mSubtitle = "" ;
$this->mNewSection = false;
+ $this->mNoGallery = false;
}
function getText() { return $this->mText; }
function &getTemplates() { return $this->mTemplates; }
function &getImages() { return $this->mImages; }
function &getExternalLinks() { return $this->mExternalLinks; }
+ function getNoGallery() { return $this->mNoGallery; }
function containsOldMagic() { return $this->mContainsOldMagic; }
function setText( $text ) { return wfSetVar( $this->mText, $text ); }
return (int)$count;
}
+/**
+ * Return the total number of admins
+ *
+ * @return integer
+ */
+function wfNumberOfAdmins() {
+ static $admins = -1;
+ wfProfileIn( 'wfNumberOfAdmins' );
+ if( $admins == -1 ) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ $admins = $dbr->selectField( 'user_groups', 'COUNT(*)', array( 'ug_group' => 'sysop' ), 'wfNumberOfAdmins' );
+ }
+ wfProfileOut( 'wfNumberOfAdmins' );
+ return (int)$admins;
+}
+
+/**
+ * Count the number of pages in a particular namespace
+ *
+ * @param $ns Namespace
+ * @return integer
+ */
+function wfPagesInNs( $ns ) {
+ static $pageCount = array();
+ wfProfileIn( 'wfPagesInNs' );
+ if( !isset( $pageCount[$ns] ) ) {
+ $dbr =& wfGetDB( DB_SLAVE );
+ $pageCount[$ns] = $dbr->selectField( 'page', 'COUNT(*)', array( 'page_namespace' => $ns ), 'wfPagesInNs' );
+ }
+ wfProfileOut( 'wfPagesInNs' );
+ return (int)$pageCount[$ns];
+}
+
/**
* Get various statistics from the database
* @private