Fixed issues with careless use of Sanitizer::decodeCharReferences(), added a parser...
[lhc/web/wiklou.git] / includes / Parser.php
index f7e5f50..45ef8a1 100644 (file)
@@ -411,10 +411,13 @@ class Parser
         *  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
@@ -433,10 +436,15 @@ class Parser
                        $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 ) {
@@ -485,7 +493,7 @@ class Parser
                                $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
@@ -835,6 +843,7 @@ class Parser
                $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();
@@ -1136,6 +1145,9 @@ class Parser
                        # 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
@@ -1219,6 +1231,9 @@ class Parser
                                # 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 );
@@ -1527,6 +1542,7 @@ class Parser
                                                $sortkey = $text;
                                        }
                                        $sortkey = Sanitizer::decodeCharReferences( $sortkey );
+                                       $sortkey = str_replace( "\n", '', $sortkey );
                                        $sortkey = $wgContLang->convertCategoryKey( $sortkey );
                                        $this->mOutput->addCategory( $nt->getDBkey(), $sortkey );
 
@@ -2234,6 +2250,8 @@ class Parser
                                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:
@@ -2779,12 +2797,13 @@ class Parser
                        $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 {
@@ -2795,6 +2814,21 @@ class Parser
                                }
                        }
                }
+               
+               # 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 ) {
@@ -2871,7 +2905,14 @@ class Parser
                        }
                        $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();
@@ -3149,6 +3190,16 @@ class Parser
                }
        }
 
+       /**
+        * 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
         */
@@ -3584,7 +3635,7 @@ class Parser
                        "\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 );
@@ -3618,7 +3669,7 @@ class Parser
                $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 );
@@ -4283,7 +4334,7 @@ class Parser
                                (=+) # 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.*?>
@@ -4401,7 +4452,8 @@ class ParserOutput
                $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 = '' )
@@ -4420,6 +4472,7 @@ class ParserOutput
                $this->mHTMLtitle = "" ;
                $this->mSubtitle = "" ;
                $this->mNewSection = false;
+               $this->mNoGallery = false;
        }
 
        function getText()                   { return $this->mText; }
@@ -4432,6 +4485,7 @@ class ParserOutput
        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 ); }
@@ -4640,6 +4694,39 @@ function wfNumberOfPages() {
        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