From 61bc10203ff076ac0d1e799cabb1f05556c34bfd Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 1 Feb 2006 04:41:53 +0000 Subject: [PATCH] Various improvements to interwiki transclusion. Introduced {{raw:..}}, to force raw transclusion when subst: isn't in use. Referer header set in wfGetHTTP(), this could be for weak (honour-bound) detection of the external site, for statistics or license notices. --- RELEASE-NOTES | 1 + includes/HttpFunctions.php | 12 +++- includes/MagicWord.php | 1 + includes/Parser.php | 143 ++++++++++++++++++++++--------------- includes/Title.php | 16 ++++- languages/Language.php | 9 +-- 6 files changed, 119 insertions(+), 63 deletions(-) diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 695b7441b5..c7cf0fee40 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -258,6 +258,7 @@ Parser: character before doing anything with them. This prevents certain kinds of spam filter evasion. * (bug 4783) : Fix for "{{ns:0}} does not render" +* Improved support for interwiki transclusion Upload: * (bug 2527) Always set destination filename when new file is selected diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index 9dbfe0118d..2c2fd4c0cb 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -9,7 +9,7 @@ * if $timeout is 'default', $wgHTTPTimeout is used */ function wfGetHTTP( $url, $timeout = 'default' ) { - global $wgHTTPTimeout, $wgHTTPProxy, $wgVersion; + global $wgHTTPTimeout, $wgHTTPProxy, $wgVersion, $wgTitle, $wgCommandLineMode; # Use curl if available if ( function_exists( 'curl_init' ) ) { @@ -25,6 +25,16 @@ function wfGetHTTP( $url, $timeout = 'default' ) { } curl_setopt( $c, CURLOPT_TIMEOUT, $timeout ); curl_setopt( $c, CURLOPT_USERAGENT, "MediaWiki/$wgVersion" ); + + # Set the referer to $wgTitle, even in command-line mode + # This is useful for interwiki transclusion, where the foreign + # server wants to know what the referring page is. + # $_SERVER['REQUEST_URI'] gives a less reliable indication of the + # referring page. + if ( is_object( $wgTitle ) ) { + curl_setopt( $c, CURLOPT_REFERER, $wgTitle->getFullURL() ); + } + ob_start(); curl_exec( $c ); $text = ob_get_contents(); diff --git a/includes/MagicWord.php b/includes/MagicWord.php index 2c091654f8..9d0b3bf2fc 100644 --- a/includes/MagicWord.php +++ b/includes/MagicWord.php @@ -69,6 +69,7 @@ $magicWords = array( 'MAG_UC', 'MAG_FULLPAGENAME', 'MAG_FULLPAGENAMEE', + 'MAG_RAW', ); if ( ! defined( 'MEDIAWIKI_INSTALL' ) ) wfRunHooks( 'MagicWordMagicWords', array( &$magicWords ) ); diff --git a/includes/Parser.php b/includes/Parser.php index 5d5c4b4a11..13b5f2e188 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -2253,9 +2253,10 @@ class Parser * * @param string $tex The text to transform * @param array $args Key-value pairs representing template parameters to substitute + * @param bool $argsOnly Only do argument (triple-brace) expansion, not double-brace expansion * @access private */ - function replaceVariables( $text, $args = array() ) { + function replaceVariables( $text, $args = array(), $argsOnly = false ) { # Prevent too big inclusions if( strlen( $text ) > MAX_INCLUDE_SIZE ) { return $text; @@ -2268,7 +2269,9 @@ class Parser array_push( $this->mArgStack, $args ); $braceCallbacks = array(); - $braceCallbacks[2] = array( &$this, 'braceSubstitution' ); + if ( !$argsOnly ) { + $braceCallbacks[2] = array( &$this, 'braceSubstitution' ); + } if ( $this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI ) { $braceCallbacks[3] = array( &$this, 'argSubstitution' ); } @@ -2356,12 +2359,16 @@ class Parser $fname = 'Parser::braceSubstitution'; wfProfileIn( $fname ); - $found = false; - $nowiki = false; - $noparse = false; - $replaceHeadings = false; - $isHTML = false; + # Flags + $found = false; # $text has been filled + $nowiki = false; # wiki markup in $text should be escaped + $noparse = false; # Unsafe HTML tags should not be stripped, etc. + $noargs = false; # Don't replace triple-brace arguments in $text + $replaceHeadings = false; # Make the edit section links go to the template not the article + $isHTML = false; # $text is HTML, armour it against wikitext transformation + $forceRawInterwiki = false; # Force interwiki transclusion to be done in raw mode not rendered + # Title object, where $text came from $title = NULL; $linestart = ''; @@ -2378,6 +2385,7 @@ class Parser $text = $replaceWith; $found = true; $noparse = true; + $noargs = true; } } @@ -2395,10 +2403,11 @@ class Parser $text = $piece['text']; $found = true; $noparse = true; + $noargs = true; } } - # MSG, MSGNW and INT + # MSG, MSGNW, INT and RAW if ( !$found ) { # Check for MSGNW: $mwMsgnw =& MagicWord::get( MAG_MSGNW ); @@ -2409,7 +2418,13 @@ class Parser $mwMsg =& MagicWord::get( MAG_MSG ); $mwMsg->matchStartAndRemove( $part1 ); } - + + # Check for RAW: + $mwRaw =& MagicWord::get( MAG_RAW ); + if ( $mwRaw->matchStartAndRemove( $part1 ) ) { + $forceRawInterwiki = true; + } + # Check if it is an internal message $mwInt =& MagicWord::get( MAG_INT ); if ( $mwInt->matchStartAndRemove( $part1 ) ) { @@ -2515,12 +2530,13 @@ class Parser # Did we encounter this template already? If yes, it is in the cache # and we need to check for loops. - if ( !$found && isset( $this->mTemplates[$part1] ) ) { + if ( !$found && isset( $this->mTemplates[$piece['title']] ) ) { $found = true; # Infinite loop test if ( isset( $this->mTemplatePath[$part1] ) ) { $noparse = true; + $noargs = true; $found = true; $text = $linestart . '{{' . $part1 . '}}' . @@ -2528,7 +2544,7 @@ class Parser wfDebug( "$fname: template loop broken at '$part1'\n" ); } else { # set $text to cached message. - $text = $linestart . $this->mTemplates[$part1]; + $text = $linestart . $this->mTemplates[$piece['title']]; } } @@ -2553,6 +2569,7 @@ class Parser if ( is_string( $text ) ) { $found = true; $noparse = true; + $noargs = true; $isHTML = true; $this->disableCache(); } @@ -2571,23 +2588,26 @@ class Parser $text = '[['.$title->getPrefixedText().']]'; $found = true; } - - # Template cache array insertion - if( $found ) { - $this->mTemplates[$part1] = $text; - $text = $linestart . $text; - } } elseif ( $title->isTrans() ) { // Interwiki transclusion - if ( $this->mOutputType == OT_HTML ) { + if ( $this->mOutputType == OT_HTML && !$forceRawInterwiki ) { $text = $this->interwikiTransclude( $title, 'render' ); $isHTML = true; $noparse = true; } else { $text = $this->interwikiTransclude( $title, 'raw' ); + $replaceHeadings = true; } $found = true; } + + # Template cache array insertion + # Use the original $piece['title'] not the mangled $part1, so that + # modifiers such as RAW: produce separate cache entries + if( $found ) { + $this->mTemplates[$piece['title']] = $text; + $text = $linestart . $text; + } } } @@ -2595,51 +2615,60 @@ class Parser # Only for HTML output if ( $nowiki && $found && $this->mOutputType == OT_HTML ) { $text = wfEscapeWikiText( $text ); - } elseif ( ($this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI) && $found && !$noparse) { - # Clean up argument array - $assocArgs = array(); - $index = 1; - foreach( $args as $arg ) { - $eqpos = strpos( $arg, '=' ); - if ( $eqpos === false ) { - $assocArgs[$index++] = $arg; - } else { - $name = trim( substr( $arg, 0, $eqpos ) ); - $value = trim( substr( $arg, $eqpos+1 ) ); - if ( $value === false ) { - $value = ''; - } - if ( $name !== false ) { - $assocArgs[$name] = $value; + } elseif ( ($this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI) && $found ) { + if ( !$noargs ) { + # Clean up argument array + $assocArgs = array(); + $index = 1; + foreach( $args as $arg ) { + $eqpos = strpos( $arg, '=' ); + if ( $eqpos === false ) { + $assocArgs[$index++] = $arg; + } else { + $name = trim( substr( $arg, 0, $eqpos ) ); + $value = trim( substr( $arg, $eqpos+1 ) ); + if ( $value === false ) { + $value = ''; + } + if ( $name !== false ) { + $assocArgs[$name] = $value; + } } } - } - # Add a new element to the templace recursion path - $this->mTemplatePath[$part1] = 1; - - # If there are any tags, only include them - if ( in_string( '', $text ) && in_string( '', $text ) ) { - preg_match_all( '/(.*?)\n?<\/onlyinclude>/s', $text, $m ); - $text = ''; - foreach ($m[1] as $piece) - $text .= $piece; + # Add a new element to the templace recursion path + $this->mTemplatePath[$part1] = 1; } - # Remove sections and tags - $text = preg_replace( '/.*?<\/noinclude>/s', '', $text ); - $text = strtr( $text, array( '' => '' , '' => '' ) ); - if( $this->mOutputType == OT_HTML ) { - # Strip ,
, etc.
-				$text = $this->strip( $text, $this->mStripState );
-				$text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs );
-			}
-			$text = $this->replaceVariables( $text, $assocArgs );
+			if ( !$noparse ) {
+				# If there are any  tags, only include them
+				if ( in_string( '', $text ) && in_string( '', $text ) ) {
+					preg_match_all( '/(.*?)\n?<\/onlyinclude>/s', $text, $m );
+					$text = '';
+					foreach ($m[1] as $piece)
+						$text .= $piece;
+				}
+				# Remove  sections and  tags
+				$text = preg_replace( '/.*?<\/noinclude>/s', '', $text );
+				$text = strtr( $text, array( '' => '' , '' => '' ) );
+
+				if( $this->mOutputType == OT_HTML ) {
+					# Strip , 
, etc.
+					$text = $this->strip( $text, $this->mStripState );
+					$text = Sanitizer::removeHTMLtags( $text, array( &$this, 'replaceVariables' ), $assocArgs );
+				}
+				$text = $this->replaceVariables( $text, $assocArgs );
 
-			# If the template begins with a table or block-level
-			# element, it should be treated as beginning a new line.
-			if (!$piece['lineStart'] && preg_match('/^({\\||:|;|#|\*)/', $text)) {
-				$text = "\n" . $text;
+				# If the template begins with a table or block-level
+				# element, it should be treated as beginning a new line.
+				if (!$piece['lineStart'] && preg_match('/^({\\||:|;|#|\*)/', $text)) {
+					$text = "\n" . $text;
+				}
+			} elseif ( !$noargs ) {
+				# $noparse and !$noargs
+				# Just replace the arguments, not any double-brace items
+				# This is used for rendered interwiki transclusion
+				$text = $this->replaceVariables( $text, $assocArgs, true );
 			}
 		}
 		# Prune lower levels off the recursion check path
diff --git a/includes/Title.php b/includes/Title.php
index 40c0f52a9f..4cbaa14908 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -494,7 +494,7 @@ class Title {
 	function isTrans() {
 		global $wgTitleInterwikiCache, $wgDBname;
 
-		if ($this->mInterwiki == '' || !$this->isLocal())
+		if ($this->mInterwiki == '')
 			return false;
 		# Make sure key is loaded into cache
 		$this->getInterwikiLink( $this->mInterwiki );
@@ -752,6 +752,13 @@ class Title {
 
 		if ( $this->isExternal() ) {
 			$url = $this->getFullURL();
+			if ( $query ) {
+				// This is currently only used for edit section links in the 
+				// context of interwiki transclusion. In theory we should 
+				// append the query to the end of any existing query string,
+				// but interwiki transclusion is already broken in that case.
+				$url .= "?$query";
+			}
 		} else {
 			$dbkey = wfUrlencode( $this->getPrefixedDBkey() );
 			if ( $query == '' ) {
@@ -1344,6 +1351,13 @@ class Title {
 						# Do another namespace split...
 						continue;
 					}
+
+					# If there's an initial colon after the interwiki, that also 
+					# resets the default namespace
+					if ( $t !== '' && $t[0] == ':' ) {
+						$this->mNamespace = NS_MAIN;
+						$t = substr( $t, 1 );
+					}
 				}
 				# If there's no recognized interwiki or namespace,
 				# then let the colon expression be part of the title.
diff --git a/languages/Language.php b/languages/Language.php
index 33e96b4447..1df20e6a8a 100644
--- a/languages/Language.php
+++ b/languages/Language.php
@@ -253,10 +253,11 @@ $wgLanguageNamesEn =& $wgLanguageNames;
 	MAG_PLURAL               => array( 0,    'PLURAL:'                ),
 	MAG_FULLURL              => array( 0,    'FULLURL:'               ),
 	MAG_FULLURLE             => array( 0,    'FULLURLE:'              ),
-	MAG_LCFIRST		 => array( 0,    'LCFIRST:'               ),
-	MAG_UCFIRST		 => array( 0,    'UCFIRST:'               ),
-	MAG_LC			 => array( 0,    'LC:'                    ),
-	MAG_UC			 => array( 0,    'UC:'                    ),
+	MAG_LCFIRST              => array( 0,    'LCFIRST:'               ),
+	MAG_UCFIRST              => array( 0,    'UCFIRST:'               ),
+	MAG_LC                   => array( 0,    'LC:'                    ),
+	MAG_UC                   => array( 0,    'UC:'                    ),
+	MAG_RAW                  => array( 0,    'RAW:'                   ),
 );
 
 if (!$wgCachedMessageArrays) {
-- 
2.20.1