From 2d61f91edf69ff303d32434d6049586b58506806 Mon Sep 17 00:00:00 2001 From: River Tarnell Date: Sun, 3 Jul 2005 07:15:53 +0000 Subject: [PATCH] - proxy support for wfGetHTTP() - support for interwiki transcludes (disabled by default, keyed on iw_trans) --- includes/DefaultSettings.php | 10 + includes/HttpFunctions.php | 6 +- includes/Parser.php | 238 +++++++++++------- includes/Title.php | 23 +- languages/Language.php | 106 ++++---- .../archives/patch-interwiki-trans.sql | 2 + maintenance/archives/patch-transcache.sql | 7 + maintenance/updaters.inc | 2 + 8 files changed, 249 insertions(+), 145 deletions(-) create mode 100644 maintenance/archives/patch-interwiki-trans.sql create mode 100644 maintenance/archives/patch-transcache.sql diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 25265efa90..eac5b68490 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1556,4 +1556,14 @@ $wgAllowSpecialInclusion = true; */ $wgHTTPTimeout = 3; +/** + * Proxy to use for CURL requests. + */ +$wgHTTPProxy = false; + +/** + * Enable interwiki transcluding. Only when iw_trans=1. + */ +$wgEnableScaryTransclude = false; + ?> diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index f292a41bf3..ed93aaa3b5 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -6,7 +6,7 @@ * if $timeout is 'default', $wgHTTPTimeout is used */ function wfGetHTTP( $url, $timeout = 'default' ) { - global $wgServer, $wgHTTPTimeout; + global $wgServer, $wgHTTPTimeout, $wgHTTPProxy; # Use curl if available @@ -14,7 +14,9 @@ function wfGetHTTP( $url, $timeout = 'default' ) { $c = curl_init( $url ); if ( wfIsLocalURL( $url ) ) { curl_setopt( $c, CURLOPT_PROXY, 'localhost:80' ); - } + } else if ($wgHTTPProxy) + curl_setopt($c, CURLOPT_PROXY, $wgHTTPProxy); + if ( $timeout == 'default' ) { $timeout = $wgHTTPTimeout; } diff --git a/includes/Parser.php b/includes/Parser.php index f2d61ad99a..f7e9415b48 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -8,6 +8,7 @@ /** */ require_once( 'Sanitizer.php' ); +require_once( 'HttpFunctions.php' ); /** * Update this version number when the ParserOutput format @@ -63,7 +64,7 @@ define( 'EXT_IMAGE_REGEX', /** * PHP Parser - * + * * Processes wiki markup * *
@@ -110,11 +111,13 @@ class Parser
 	    $mTemplatePath;	// stores an unsorted hash of all the templates already loaded
 		                // in this path. Used for loop detection.
 
+	var $mIWTransData = array();
+
 	/**#@-*/
 
 	/**
 	 * Constructor
-	 * 
+	 *
 	 * @access public
 	 */
 	function Parser() {
@@ -179,11 +182,11 @@ class Parser
 		$this->mOutputType = OT_HTML;
 
 		$this->mStripState = NULL;
-		
+
 		//$text = $this->strip( $text, $this->mStripState );
 		// VOODOO MAGIC FIX! Sometimes the above segfaults in PHP5.
 		$x =& $this->mStripState;
-		
+
 		wfRunHooks( 'ParserBeforeStrip', array( &$this, &$text, &$x ) );
 		$text = $this->strip( $text, $x );
 		wfRunHooks( 'ParserAfterStrip', array( &$this, &$text, &$x ) );
@@ -191,7 +194,7 @@ class Parser
 		$text = $this->internalParse( $text );
 
 		$text = $this->unstrip( $text, $this->mStripState );
-		
+
 		# Clean up special characters, only run once, next-to-last before doBlockLevels
 		$fixtags = array(
 			# french spaces, last one Guillemet-left
@@ -203,14 +206,14 @@ class Parser
 			'/<\\/center *>/i' => '',
 		);
 		$text = preg_replace( array_keys($fixtags), array_values($fixtags), $text );
-		
+
 		# only once and last
 		$text = $this->doBlockLevels( $text, $linestart );
 
 		$this->replaceLinkHolders( $text );
 
-		# the position of the convert() call should not be changed. it 
-		# assumes that the links are all replaces and the only thing left 
+		# the position of the convert() call should not be changed. it
+		# assumes that the links are all replaces and the only thing left
 		# is the  mark.
 		$text = $wgContLang->convert($text);
 		$this->mOutput->setTitleText($wgContLang->getParsedTitle());
@@ -218,7 +221,7 @@ class Parser
 		$text = $this->unstripNoWiki( $text, $this->mStripState );
 
 		wfRunHooks( 'ParserBeforeTidy', array( &$this, &$text ) );
-		
+
 		$text = Sanitizer::normalizeCharReferences( $text );
 		global $wgUseTidy;
 		if ($wgUseTidy) {
@@ -242,12 +245,12 @@ class Parser
 		return dechex(mt_rand(0, 0x7fffffff)) . dechex(mt_rand(0, 0x7fffffff));
 	}
 
-	/** 
+	/**
 	 * Replaces all occurrences of <$tag>content in the text
 	 * with a random marker and returns the new text. the output parameter
 	 * $content will be an associative array filled with data on the form
 	 * $unique_marker => content.
-	 * 
+	 *
 	 * If $content is already set, the additional entries will be appended
 	 * If $tag is set to STRIP_COMMENTS, the function will extract
 	 * 
@@ -262,11 +265,11 @@ class Parser
 		}
 		$n = 1;
 		$stripped = '';
-	
+
 		if ( !$tags ) {
 			$tags = array( );
 		}
-		
+
 		if ( !$params ) {
 			$params = array( );
 		}
@@ -287,13 +290,13 @@ class Parser
 			}
 			$attributes = $p[1];
 			$inside     = $p[2];
-			
+
 			$marker = $rnd . sprintf('%08X', $n++);
 			$stripped .= $marker;
-			
+
 			$tags[$marker] = "<$tag$attributes>";
 			$params[$marker] = Sanitizer::decodeTagAttributes( $attributes );
-			
+
 			$q = preg_split( $end, $inside, 2 );
 			$content[$marker] = $q[0];
 			if( count( $q ) < 1 ) {
@@ -317,11 +320,11 @@ class Parser
 	function extractTags( $tag, $text, &$content, $uniq_prefix = '' ) {
 		$dummy_tags = array();
 		$dummy_params = array();
-		
+
 		return Parser::extractTagsAndParams( $tag, $text, $content,
 			$dummy_tags, $dummy_params, $uniq_prefix );
 	}
-	
+
 	/**
 	 * Strips and renders nowiki, pre, math, hiero
 	 * If $render is set, performs necessary rendering operations on plugins
@@ -555,7 +558,7 @@ class Parser
 		}
 		return $correctedtext;
 	}
-	
+
 	/**
 	 * Spawn an external HTML tidy process and get corrected markup back from it.
 	 *
@@ -612,7 +615,7 @@ class Parser
 		global $wgTidyConf;
 		$fname = 'Parser::internalTidy';
 		wfProfileIn( $fname );
-		
+
 		tidy_load_config( $wgTidyConf );
 		tidy_set_encoding( 'utf8' );
 		tidy_parse_string( $text );
@@ -764,20 +767,28 @@ class Parser
 		}
 		$text = $this->doAllQuotes( $text );
 		$text = $this->replaceInternalLinks( $text );
-		$text = $this->replaceExternalLinks( $text );		
-		
+		$text = $this->replaceExternalLinks( $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 = $this->doMagicLinks( $text );
 		$text = $this->doTableStuff( $text );
 		$text = $this->formatHeadings( $text, $isMain );
 
+		$regex = '//';
+		$text = preg_replace_callback($regex, array(&$this, 'scarySubstitution'), $text);
+
 		wfProfileOut( $fname );
 		return $text;
 	}
 
+	function scarySubstitution($matches) {
+#		return "[[".$matches[0]."]]";
+		return $this->mIWTransData[(int)$matches[0]];
+	}
+
 	/**
 	 * Replace special strings like "ISBN xxx" and "RFC xxx" with
 	 * magic external links.
@@ -1018,7 +1029,7 @@ class Parser
 		wfProfileIn( $fname );
 
 		$sk =& $this->mOptions->getSkin();
-		
+
 		$bits = preg_split( EXT_LINK_BRACKETED, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
 
 		$s = $this->replaceFreeExternalLinks( array_shift( $bits ) );
@@ -1098,7 +1109,7 @@ class Parser
 		global $wgContLang;
 		$fname = 'Parser::replaceFreeExternalLinks';
 		wfProfileIn( $fname );
-		
+
 		$bits = preg_split( '/(\b(?:'.URL_PROTOCOLS.'):)/S', $text, -1, PREG_SPLIT_DELIM_CAPTURE );
 		$s = array_shift( $bits );
 		$i = 0;
@@ -1170,7 +1181,7 @@ class Parser
 		}
 		return $text;
 	}
-	
+
 	/**
 	 * Process [[ ]] wikilinks
 	 *
@@ -1186,7 +1197,7 @@ class Parser
 		static $tc = FALSE;
 		# the % is needed to support urlencoded titles as well
 		if ( !$tc ) { $tc = Title::legalChars() . '#%'; }
-		
+
 		$sk =& $this->mOptions->getSkin();
 
 		#split the entire text string on occurences of [[
@@ -1228,7 +1239,7 @@ class Parser
 
 		$checkVariantLink = sizeof($wgContLang->getVariants())>1;
 		$useSubpages = $this->areSubpagesAllowed();
-		
+
 		# Loop for each link
 		for ($k = 0; isset( $a[$k] ); $k++) {
 			$line = $a[$k];
@@ -1249,7 +1260,7 @@ class Parser
 			}
 
 			$might_be_img = false;
-			
+
 			if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
 				$text = $m[2];
 				# If we get a ] at the beginning of $m[3] that means we have a link that's something like:
@@ -1297,7 +1308,7 @@ class Parser
 				# Strip off leading ':'
 				$link = substr($link, 1);
 			}
-			
+
 			$nt =& Title::newFromText( $this->unstripNoWiki($link, $this->mStripState) );
 			if( !$nt ) {
 				$s .= $prefix . '[[' . $line;
@@ -1313,7 +1324,7 @@ class Parser
 
 			$ns = $nt->getNamespace();
 			$iw = $nt->getInterWiki();
-			
+
 			if ($might_be_img) { # if this is actually an invalid link
 				if ($ns == NS_IMAGE && $noforce) { #but might be an image
 					$found = false;
@@ -1353,7 +1364,7 @@ class Parser
 			$wasblank = ( '' == $text );
 			if( $wasblank ) $text = $link;
 
-			
+
 			# Link not escaped by : , create the various objects
 			if( $noforce ) {
 
@@ -1364,7 +1375,7 @@ class Parser
 					$s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
 					continue;
 				}
-				
+
 				if ( $ns == NS_IMAGE ) {
 					wfProfileIn( "$fname-image" );
 					if ( !wfIsBadImage( $nt->getDBkey() ) ) {
@@ -1373,18 +1384,18 @@ class Parser
 						# but it might be hard to fix that, and it doesn't matter ATM
 						$text = $this->replaceExternalLinks($text);
 						$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;
 						$wgLinkCache->addImageLinkObj( $nt );
-						
+
 						wfProfileOut( "$fname-image" );
 						continue;
 					}
 					wfProfileOut( "$fname-image" );
 
 				}
-				
+
 				if ( $ns == NS_CATEGORY ) {
 					wfProfileIn( "$fname-category" );
 					$t = $wgContLang->convertHtml( $nt->getText() );
@@ -1406,13 +1417,13 @@ class Parser
 					$sortkey = $wgContLang->convertCategoryKey( $sortkey );
 					$wgLinkCache->addCategoryLinkObj( $nt, $sortkey );
 					$this->mOutput->addCategoryLink( $t );
-					
+
 					/**
 					 * Strip the whitespace Category links produce, see bug 87
 					 * @todo We might want to use trim($tmp, "\n") here.
 					 */
 					$s .= trim($prefix . $trail, "\n") == '' ? '': $prefix . $trail;
-					
+
 					wfProfileOut( "$fname-category" );
 					continue;
 				}
@@ -1445,7 +1456,7 @@ class Parser
 			} else {
 				/**
 				 * Add a link placeholder
-				 * Later, this will be replaced by a real link, after the existence or 
+				 * 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 );
@@ -1457,8 +1468,8 @@ class Parser
 
 	/**
 	 * Make a link placeholder. The text returned can be later resolved to a real link with
-	 * replaceLinkHolders(). This is done for two reasons: firstly to avoid further 
-	 * parsing of interwiki links, and secondly to allow all extistence checks and 
+	 * replaceLinkHolders(). This is done for two reasons: firstly to avoid further
+	 * parsing of interwiki links, and secondly to allow all extistence checks and
 	 * article length checks (for stub links) to be bundled into a single query.
 	 *
 	 */
@@ -1469,7 +1480,7 @@ class Parser
 		} else {
 			# Separate the link trail from the rest of the link
 			list( $inside, $trail ) = Linker::splitTrail( $trail );
-			
+
 			if ( $nt->isExternal() ) {
 				$nr = array_push( $this->mInterwikiLinkHolders['texts'], $prefix.$text.$inside );
 				$this->mInterwikiLinkHolders['titles'][] = $nt;
@@ -1496,7 +1507,7 @@ class Parser
 		global $wgNamespacesWithSubpages;
 		return !empty($wgNamespacesWithSubpages[$this->mTitle->getNamespace()]);
 	}
-	
+
 	/**
 	 * Handle link to subpage if necessary
 	 * @param string $target the source of the link
@@ -1516,10 +1527,10 @@ class Parser
 		$fname = 'Parser::maybeDoSubpageLink';
 		wfProfileIn( $fname );
 		$ret = $target; # default return value is no change
-			
-		# Some namespaces don't allow subpages, 
+
+		# Some namespaces don't allow subpages,
 		# so only perform processing if subpages are allowed
-		if( $this->areSubpagesAllowed() ) {		
+		if( $this->areSubpagesAllowed() ) {
 			# Look at the first character
 			if( $target != '' && $target{0} == '/' ) {
 				# / at end means we don't want the slash to be shown
@@ -1529,7 +1540,7 @@ class Parser
 				} else {
 					$noslash = substr( $target, 1 );
 				}
-				
+
 				$ret = $this->mTitle->getPrefixedText(). '/' . trim($noslash);
 				if( '' === $text ) {
 					$text = $target;
@@ -1853,14 +1864,14 @@ class Parser
 	 */
 	function getVariableValue( $index ) {
 		global $wgContLang, $wgSitename, $wgServer, $wgServerName, $wgArticle, $wgScriptPath;
-		
+
 		/**
 		 * Some of these require message or data lookups and can be
 		 * expensive to check many times.
 		 */
 		static $varCache = array();
 		if( isset( $varCache[$index] ) ) return $varCache[$index];
-		
+
 		switch ( $index ) {
 			case MAG_CURRENTMONTH:
 				return $varCache[$index] = $wgContLang->formatNum( date( 'm' ) );
@@ -1934,7 +1945,7 @@ class Parser
 	 *  OT_WIKI: only {{subst:}} templates
 	 *  OT_MSG: only magic variables
 	 *  OT_HTML: all templates and magic variables
-	 * 
+	 *
 	 * @param string $tex The text to transform
 	 * @param array $args Key-value pairs representing template parameters to substitute
 	 * @access private
@@ -1956,7 +1967,7 @@ class Parser
 
 		# Variable substitution
 		$text = preg_replace_callback( "/{{([$titleChars]*?)}}/", array( &$this, 'variableSubstitution' ), $text );
-		
+
 		if ( $this->mOutputType == OT_HTML || $this->mOutputType == OT_WIKI ) {
 			# Argument substitution
 			$text = preg_replace_callback( "/{{{([$titleChars]*?)}}}/", array( &$this, 'argSubstitution' ), $text );
@@ -2015,7 +2026,7 @@ class Parser
 		# merged with the next arg because the '|' character between belongs
 		# to the link syntax and not the template parameter syntax.
 		$argc = count($args);
-		
+
 		for ( $i = 0; $i < $argc-1; $i++ ) {
 			if ( substr_count ( $args[$i], '[[' ) != substr_count ( $args[$i], ']]' ) ) {
 				$args[$i] .= '|'.$args[$i+1];
@@ -2042,7 +2053,7 @@ class Parser
 		global $wgLinkCache, $wgContLang;
 		$fname = 'Parser::braceSubstitution';
 		wfProfileIn( $fname );
-		
+
 		$found = false;
 		$nowiki = false;
 		$noparse = false;
@@ -2191,6 +2202,12 @@ class Parser
 				$ns = $this->mTitle->getNamespace();
 			}
 			$title = Title::newFromText( $part1, $ns );
+
+			$interwiki = Title::getInterwikiLink($title->getInterwiki());
+			if ($interwiki != '' && $title->isTrans()) {
+				return $this->scarytransclude($title, $interwiki);
+			}
+
 			if ( !is_null( $title ) && !$title->isExternal() ) {
 				# Check for excessive inclusion
 				$dbk = $title->getPrefixedDBkey();
@@ -2275,14 +2292,14 @@ class Parser
 		}
 		# Prune lower levels off the recursion check path
 		$this->mTemplatePath = $lastPathLevel;
-		
+
 		if ( !$found ) {
 			wfProfileOut( $fname );
 			return $matches[0];
 		} else {
 			if ( $isHTML ) {
 				# Replace raw HTML by a placeholder
-				# Add a blank line preceding, to prevent it from mucking up 
+				# Add a blank line preceding, to prevent it from mucking up
 				# immediately preceding headings
 				$text = "\n\n" . $this->insertStripItem( $text, $this->mStripState );
 			} else {
@@ -2308,16 +2325,16 @@ class Parser
 						preg_match('/^(={1,6})(.*?)(={1,6})\s*?$/m', $hl, $m2);
 						$text .= $m2[1] . $m2[2] . "" . $m2[3];
-						
+
 						$nsec++;
 					}
 				}
 			}
 		}
-		
+
 		# Prune lower levels off the recursion check path
 		$this->mTemplatePath = $lastPathLevel;
-		
+
 		if ( !$found ) {
 			wfProfileOut( $fname );
 			return $matches[0];
@@ -2327,6 +2344,47 @@ class Parser
 		}
 	}
 
+	/**
+	 * Translude an interwiki link.
+	 */
+	function scarytransclude($title, $interwiki) {
+		global $wgEnableScaryTranscluding;
+
+		if (!$wgEnableScaryTranscluding)
+			return wfMsg('scarytranscludedisabled');
+
+		$articlename = "Template:" . $title->getDBkey();
+		$url = str_replace('$1', urlencode($articlename), $interwiki);
+		$text = $this->fetchScaryTemplateMaybeFromCache($url);
+		$this->mIWTransData[] = $text;
+		return "";
+	}
+
+	function fetchScaryTemplateMaybeFromCache($url) {
+		$dbr = wfGetDB(DB_SLAVE);
+		$obj = $dbr->selectRow('transcache', array('tc_time', 'tc_contents'),
+				array('tc_url' => $url));
+		if ($obj) {
+			$time = $obj->tc_time;
+			$text = $obj->tc_contents;
+			if ($time && $time < (time() + (60*60))) {
+				return $text;
+			}
+		}
+
+		$text = wfGetHTTP($url . '?action=render');
+		if (!$text)
+			return wfMsg('scarytranscludefailed');
+
+		$dbw = wfGetDB(DB_MASTER);
+		$dbw->replace('transcache', array(), array(
+			'tc_url' => $url,
+			'tc_time' => time(),
+			'tc_contents' => $text));
+		return $text;
+	}
+
+
 	/**
 	 * Triple brace replacement -- used for template arguments
 	 * @access private
@@ -2364,10 +2422,10 @@ class Parser
 	 * 2) Add an [edit] link to sections for logged in users who have enabled the option
 	 * 3) Add a Table of contents on the top for users who have enabled the option
 	 * 4) Auto-anchor headings
-	 *	
+	 *
 	 * It loops through all headlines, collects the necessary data, then splits up the
 	 * string and re-inserts the newly formatted headlines.
-	 * 
+	 *
 	 * @param string $text
 	 * @param boolean $isMain
 	 * @access private
@@ -2464,9 +2522,9 @@ class Parser
 				$prevtoclevel = $toclevel;
 			}
 			$level = $matches[1][$headlineCount];
-			
+
 			if( $doNumberHeadings || $doShowToc ) {
-				
+
 				if ( $level > $prevlevel ) {
 					# Increase TOC level
 					$toclevel++;
@@ -2500,7 +2558,7 @@ class Parser
 					# No change in level, end TOC line
 					$toc .= $sk->tocLineEnd();
 				}
-				
+
 				$levelCount[$toclevel] = $level;
 
 				# count number of headlines for each level
@@ -2524,7 +2582,7 @@ class Parser
 
 			# Remove link placeholders by the link text.
 			#     
-			# turns into 
+			# turns into
 			#     link text with suffix
 			$canonized_headline = preg_replace( '//e',
 							    "\$this->mLinkHolders['texts'][\$1]",
@@ -2676,7 +2734,7 @@ class Parser
 	 * @return string
 	 */
 	function magicRFC( $text, $keyword='RFC ', $urlmsg='rfcurl'  ) {
-		
+
 		$valid = '0123456789';
 		$internal = false;
 
@@ -2685,7 +2743,7 @@ class Parser
 			return $text;
 		}
 		$text = substr( array_shift( $a ), 1);
-		
+
 		/* Check if keyword is preceed by [[.
 		 * This test is made here cause of the array_shift above
 		 * that prevent the test to be done in the foreach.
@@ -2728,7 +2786,7 @@ class Parser
 				$la = $sk->getExternalLinkAttributes( $url, $keyword.$id );
 				$text .= "{$keyword}{$id}{$x}";
 			}
-			
+
 			/* Check if the next RFC keyword is preceed by [[ */
 			$internal = ( substr($x,-2) == '[[' );
 		}
@@ -2861,7 +2919,7 @@ class Parser
 
 	/**
 	 * Transform a MediaWiki message by replacing magic variables.
-	 * 
+	 *
 	 * @param string $text the text to transform
 	 * @param ParserOptions $options  options
 	 * @return string the text with variables substituted
@@ -2918,16 +2976,16 @@ class Parser
 		$pdbks = array();
 		$colours = array();
 		$sk = $this->mOptions->getSkin();
-		
+
 		if ( !empty( $this->mLinkHolders['namespaces'] ) ) {
 			wfProfileIn( $fname.'-check' );
 			$dbr =& wfGetDB( DB_SLAVE );
 			$page = $dbr->tableName( 'page' );
 			$threshold = $wgUser->getOption('stubthreshold');
-			
+
 			# Sort by namespace
 			asort( $this->mLinkHolders['namespaces'] );
-	
+
 			# Generate query
 			$query = false;
 			foreach ( $this->mLinkHolders['namespaces'] as $key => $val ) {
@@ -2961,7 +3019,7 @@ class Parser
 					} else {
 						$query .= ', ';
 					}
-				
+
 					$query .= $dbr->addQuotes( $this->mLinkHolders['dbkeys'][$key] );
 				}
 			}
@@ -2970,9 +3028,9 @@ class Parser
 				if ( $options & RLH_FOR_UPDATE ) {
 					$query .= ' FOR UPDATE';
 				}
-			
+
 				$res = $dbr->query( $query, $fname );
-				
+
 				# Fetch data and form into an associative array
 				# non-existent = broken
 				# 1 = known
@@ -2981,7 +3039,7 @@ class Parser
 					$title = Title::makeTitle( $s->page_namespace, $s->page_title );
 					$pdbk = $title->getPrefixedDBkey();
 					$wgLinkCache->addGoodLinkObj( $s->page_id, $title );
-					
+
 					if ( $threshold >  0 ) {
 						$size = $s->page_len;
 						if ( $s->page_is_redirect || $s->page_namespace != 0 || $size >= $threshold ) {
@@ -2995,7 +3053,7 @@ class Parser
 				}
 			}
 			wfProfileOut( $fname.'-check' );
-			
+
 			# Construct search and replace arrays
 			wfProfileIn( $fname.'-construct' );
 			$wgOutputReplace = array();
@@ -3023,7 +3081,7 @@ class Parser
 
 			# Do the thing
 			wfProfileIn( $fname.'-replace' );
-			
+
 			$text = preg_replace_callback(
 				'/()/',
 				"wfOutputReplaceMatches",
@@ -3042,18 +3100,18 @@ class Parser
 				$title = $this->mInterwikiLinkHolders['titles'][$key];
 				$wgOutputReplace[$key] = $sk->makeLinkObj( $title, $link );
 			}
-			
+
 			$text = preg_replace_callback(
 				'//',
 				"wfOutputReplaceMatches",
 				$text );
 			wfProfileOut( $fname.'-interwiki' );
 		}
-		
+
 		wfProfileOut( $fname );
 		return $colours;
 	}
-	
+
 	/**
 	 * Replace  link placeholders with plain text of links
 	 * (not HTML-formatted).
@@ -3071,11 +3129,11 @@ class Parser
 			'//',
 			array( &$this, 'replaceLinkHoldersTextCallback' ),
 			$text );
-		
+
 		wfProfileOut( $fname );
 		return $text;
 	}
-	
+
 	/**
 	 * @param array $matches
 	 * @return string
@@ -3112,7 +3170,7 @@ class Parser
 		global $wgUser, $wgTitle;
 		$parserOptions = ParserOptions::newFromUser( $wgUser );
 		$localParser = new Parser();
-	        
+
 		global $wgLinkCache;
 		$ig = new ImageGallery();
 		$ig->setShowBytes( false );
@@ -3137,10 +3195,10 @@ class Parser
 			} else {
 				$label = '';
 			}
-			
+
 			$html = $localParser->parse( $label , $wgTitle, $parserOptions );
 			$html = $html->mText;
-			
+
 			$ig->add( new Image( $nt ), $html );
 			$wgLinkCache->addImageLinkObj( $nt );
 		}
@@ -3153,7 +3211,7 @@ class Parser
 	function makeImage( &$nt, $options ) {
 		global $wgContLang, $wgUseImageResize;
 		global $wgUser, $wgThumbLimits;
-		
+
 		$align = '';
 
 		# Check if the options text is of the form "options|alt text"
@@ -3346,7 +3404,7 @@ class ParserOptions
 
 	/** Get user options */
 	function initialiseFromUser( &$userInput ) {
-		global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages, 
+		global $wgUseTeX, $wgUseDynamicDates, $wgInterwikiMagic, $wgAllowExternalImages,
 		       $wgAllowSpecialInclusion;
 		$fname = 'ParserOptions::initialiseFromUser';
 		wfProfileIn( $fname );
@@ -3396,12 +3454,12 @@ function wfNumberOfArticles() {
  */
 function wfNumberOfFiles() {
 	$fname = 'Parser::wfNumberOfFiles';
-	
+
 	wfProfileIn( $fname );
 	$dbr =& wfGetDB( DB_SLAVE );
 	$res = $dbr->selectField('image', 'COUNT(*)', array(), $fname );
 	wfProfileOut( $fname );
-	
+
 	return $res;
 }
 
@@ -3432,7 +3490,7 @@ function wfLoadSiteStats() {
 /**
  * Escape html tags
  * Basicly replacing " > and < with HTML entities ( ", >, <)
- *  
+ *
  * @param string $in Text that might contain HTML tags
  * @return string Escaped string
  */
diff --git a/includes/Title.php b/includes/Title.php
index c410de1beb..0761f91698 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -385,7 +385,7 @@ class Title {
 	 * @static (arguably)
 	 * @access public
 	 */
-	function getInterwikiLink( $key ) {
+	function getInterwikiLink( $key, $transludeonly = false ) {
 		global $wgMemc, $wgDBname, $wgInterwikiExpiry, $wgTitleInterwikiCache;
 		$fname = 'Title::getInterwikiLink';
 
@@ -407,7 +407,7 @@ class Title {
 
 		$dbr =& wfGetDB( DB_SLAVE );
 		$res = $dbr->select( 'interwiki',
-			array( 'iw_url', 'iw_local' ),
+			array( 'iw_url', 'iw_local', 'iw_trans' ),
 			array( 'iw_prefix' => $key ), $fname );
 		if( !$res ) {
 			wfProfileOut( $fname );
@@ -420,6 +420,7 @@ class Title {
 			$s = (object)false;
 			$s->iw_url = '';
 			$s->iw_local = 0;
+			$s->iw_trans = 0;
 		}
 		$wgMemc->set( $k, $s, $wgInterwikiExpiry );
 		$wgTitleInterwikiCache[$k] = $s;
@@ -449,6 +450,24 @@ class Title {
 		}
 	}
 
+	/**
+	 * Determine whether the object refers to a page within
+	 * this project and is transcludable.
+	 *
+	 * @return bool TRUE if this is transcludable
+	 * @access public
+	 */
+	function isTrans() {
+		global $wgTitleInterwikiCache, $wgDBname;
+
+		if ($this->mInterwiki == '' || !$this->isLocal())
+			return false;
+		# Make sure key is loaded into cache
+		$this->getInterwikiLink( $this->mInterwiki );
+		$k = $wgDBname.':interwiki:' . $this->mInterwiki;
+		return (bool)($wgTitleInterwikiCache[$k]->iw_trans);
+	}
+
 	/**
 	 * Update the page_touched field for an array of title objects
 	 * @todo Inefficient unless the IDs are already loaded into the
diff --git a/languages/Language.php b/languages/Language.php
index 5289fe458c..5409d26107 100644
--- a/languages/Language.php
+++ b/languages/Language.php
@@ -236,7 +236,7 @@ $wgLanguageNamesEn =& $wgLanguageNames;
 	MAG_NOCONTENTCONVERT     => array( 0,    '__NOCONTENTCONVERT__', '__NOCC__'),
 	MAG_CURRENTWEEK          => array( 1,    'CURRENTWEEK'            ),
 	MAG_CURRENTDOW           => array( 1,    'CURRENTDOW'             ),
-	MAG_REVISIONID           => array( 1,    'REVISIONID'             ),    
+	MAG_REVISIONID           => array( 1,    'REVISIONID'             ),
 );
 
 #-------------------------------------------------------------------
@@ -254,7 +254,7 @@ global $wgRightsText;
 # The navigation toolbar, int: is used here to make sure that the appropriate
 # messages are automatically pulled from the user-selected language file.
 
-/* 
+/*
 The sidebar for MonoBook is generated from this message, lines that do not
 begin with * or ** are discarded, furthermore lines that do begin with ** and
 do not contain | are also discarded, but don't depend on this behaviour for
@@ -624,19 +624,19 @@ You should log in and change your password now.",
 'passwordsent'	=> "A new password has been sent to the e-mail address
 registered for \"$1\".
 Please log in again after you receive it.",
-'eauthentsent'             =>  "A confirmation email has been sent to the nominated email address. 
-Before any other mail is sent to the account, you will have to follow the instructions in the email, 
+'eauthentsent'             =>  "A confirmation email has been sent to the nominated email address.
+Before any other mail is sent to the account, you will have to follow the instructions in the email,
 to confirm that the account is actually yours.",
 'loginend'		            => ' ',
 'mailerror'                 => "Error sending mail: $1",
 'acct_creation_throttle_hit' => 'Sorry, you have already created $1 accounts. You can\'t make any more.',
 'emailauthenticated'        => 'Your email address was authenticated on $1.',
-'emailnotauthenticated'     => 'Your email address is not yet authenticated. No email 
+'emailnotauthenticated'     => 'Your email address is not yet authenticated. No email
 will be sent for any of the following features.',
-'noemailprefs'              => 'No email address has been specified, the following 
+'noemailprefs'              => 'No email address has been specified, the following
 features will not work.',
 'emailconfirmlink' => 'Confirm your e-mail address',
-'invalidemailaddress'	=> 'The email address cannot be accepted as it appears to have an invalid 
+'invalidemailaddress'	=> 'The email address cannot be accepted as it appears to have an invalid
 format. Please enter a well-formatted address or empty that field.',
 
 # Edit page toolbar
@@ -828,7 +828,7 @@ $2 List redirects   Search for $3 $9",
     
     
     
-    
+
     
     
   
@@ -908,8 +908,8 @@ See [[Project:User preferences help]] for help deciphering the options.", # group editing 'groups-editgroup' => 'Edit group', 'groups-addgroup' => 'Add group', -'groups-editgroup-preamble' => 'If the name or description starts with a colon, the -remainder will be treated as a message name, and hence the text will be localised +'groups-editgroup-preamble' => 'If the name or description starts with a colon, the +remainder will be treated as a message name, and hence the text will be localised using the MediaWiki namespace', 'groups-editgroup-name' => 'Group name: ', 'groups-editgroup-description' => 'Group description (max 255 characters):
', @@ -933,7 +933,7 @@ Unselected groups will not be changed. You can deselect a group with CTRL + Left 'userrights-logcomment' => 'Changed group membership from $1 to $2', # Default group names and descriptions -# +# 'group-anon-name' => 'Anonymous', 'group-anon-desc' => 'Anonymous users', 'group-loggedin-name' => 'User', @@ -987,9 +987,9 @@ to upload files.", 'uploaderror' => 'Upload error', 'uploadtext' => " -Use the form below to upload new files, +Use the form below to upload new files, to view or search previously uploaded images -go to the [[Special:Imagelist|list of uploaded files]], +go to the [[Special:Imagelist|list of uploaded files]], uploads and deletions are also logged in the [[Special:Log|project log]]. You must also check the box affirming that you are not @@ -997,7 +997,7 @@ violating any copyrights by uploading the file. Press the \"Upload\" button to finish the upload. To include the image in a page, use a link in the form -'''[[{{ns:6}}:file.jpg]]''', +'''[[{{ns:6}}:file.jpg]]''', '''[[{{ns:6}}:file.png|alt text]]''' or '''[[{{ns:-2}}:file.ogg]]''' for directly linking to the file. ", @@ -1582,7 +1582,7 @@ title. Please merge them manually.'''", 'movereason' => 'Reason', 'revertmove' => 'revert', 'delete_and_move' => 'Delete and move', -'delete_and_move_text' => +'delete_and_move_text' => '==Deletion required== The destination article "[[$1]]" already exists. Do you want to delete it to make way for the move?', @@ -1776,7 +1776,7 @@ ta[\'ca-nstab-category\'] = new Array(\'c\',\'View the category page\'); 'newimages' => 'New images gallery', 'noimages' => 'Nothing to see.', -# short names for language variants used for language conversion links. +# short names for language variants used for language conversion links. # to disable showing a particular link, set it to 'disable', e.g. # 'variantname-zh-sg' => 'disable', 'variantname-zh-cn' => 'cn', @@ -2119,11 +2119,15 @@ will expire at $4. 'searchfulltext' => 'Search full text', 'createarticle' => 'Create article', +# Scary transclusion +'scarytranscludedisabled' => '[Interwiki transcluding is disabled]', +'scarytranscludefailed' => '[Template fetch failed; sorry]', + ); /* a fake language converter */ class fakeConverter { - var $mLang; + var $mLang; function fakeConverter($langobj) {$this->mLang = $langobj;} function convert($t, $i) {return $t;} function getVariants() { return array( strtolower( substr( get_class( $this->mLang ), 8 ) ) ); } @@ -2163,19 +2167,19 @@ class Language { } $this->mConverter = new fakeConverter($this); } - + /** * Exports the default user options as defined in * $wgDefaultUserOptionsEn, user preferences can override some of these * depending on what's in (Local|Default)Settings.php and some defines. - * + * * @return array */ function getDefaultUserOptions() { global $wgDefaultUserOptionsEn ; return $wgDefaultUserOptionsEn ; } - + /** * Exports $wgBookstoreListEn * @return array @@ -2184,7 +2188,7 @@ class Language { global $wgBookstoreListEn ; return $wgBookstoreListEn ; } - + /** * @return array */ @@ -2223,7 +2227,7 @@ class Language { $ns = $this->getNamespaces(); return isset( $ns[$index] ) ? $ns[$index] : false; } - + /** * A convenience function that returns the same thing as * getNsText() except with '_' changed to ' ', useful for @@ -2244,7 +2248,7 @@ class Language { */ function getNsIndex( $text ) { $ns = $this->getNamespaces(); - + foreach ( $ns as $i => $n ) { if ( strcasecmp( $n, $text ) == 0) return $i; @@ -2253,7 +2257,7 @@ class Language { } /** - * short names for language variants used for language conversion links. + * short names for language variants used for language conversion links. * * @param string $code * @return string @@ -2380,7 +2384,7 @@ class Language { (int)substr( $ts, 0, 4 ) ); #Year return date( 'YmdHis', $t ); } - + /** * This is meant to be used by time(), date(), and timeanddate() to get * the date preference they're supposed to use, it should be used in @@ -2405,7 +2409,7 @@ class Language { return $wgUser->getOption( 'date' ); } } - + /** * @access public * @param mixed $ts the time format which needs to be turned into a @@ -2420,17 +2424,17 @@ class Language { */ function date( $ts, $adj = false, $format = true, $timecorrection = false ) { global $wgAmericanDates, $wgUser; - + if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); } - + $datePreference = $this->dateFormat($format); - + if ($datePreference == '0') {$datePreference = $wgAmericanDates ? '0' : '2';} $month = $this->getMonthName( substr( $ts, 4, 2 ) ); $day = $this->formatNum( 0 + substr( $ts, 6, 2 ) ); $year = $this->formatNum( substr( $ts, 0, 4 ), true ); - + switch( $datePreference ) { case '2': return "$day $month $year"; case '3': return "$year $month $day"; @@ -2456,17 +2460,17 @@ class Language { if ( $adj ) { $ts = $this->userAdjust( $ts, $timecorrection ); } $datePreference = $this->dateFormat($format); - + if ($datePreference == '0') {$datePreference = $wgAmericanDates ? '0' : '2';} $t = substr( $ts, 8, 2 ) . ':' . substr( $ts, 10, 2 ); - + if ( $datePreference === 'ISO 8601' ) { $t .= ':' . substr( $ts, 12, 2 ); } return $this->formatNum( $t ); } - + /** * @access public * @param mixed $ts the time format which needs to be turned into a @@ -2481,9 +2485,9 @@ class Language { */ function timeanddate( $ts, $adj = false, $format = true, $timecorrection = false) { global $wgUser, $wgAmericanDates; - + $datePreference = $this->dateFormat($format); - + switch ( $datePreference ) { case 'ISO 8601': return $this->date( $ts, $adj, $datePreference, $timecorrection ) . ' ' . $this->time( $ts, $adj, $datePreference, $timecorrection ); @@ -2550,7 +2554,7 @@ class Language { # it with one to detect and convert another legacy encoding. return $s; } - + /** * Some languages have special punctuation to strip out * or characters which need to be converted for MySQL's @@ -2567,7 +2571,7 @@ class Language { # some languages, e.g. Chinese, need to do a conversion # in order for search results to be displayed correctly return $termsArray; - } + } /** * Get the first character of a string. In ASCII, return @@ -2659,8 +2663,8 @@ class Language { $mw->mCaseSensitive = $rawEntry[0]; $mw->mSynonyms = array_slice( $rawEntry, 1 ); } - - /** + + /** * Italic is unsuitable for some languages * * @access public @@ -2675,34 +2679,34 @@ class Language { /** * This function enables formatting of numbers, it should only come * into effect when the $wgTranslateNumerals variable is TRUE. - * + * * Normally we output all numbers in plain en_US style, that is * 293,291.235 for twohundredninetythreethousand-twohundredninetyone * point twohundredthirtyfive. However this is not sutable for all * languages, some such as Pakaran want ੨੯੩,੨੯੫.੨੩੫ and others such as * Icelandic just want to use commas instead of dots, and dots instead * of commas like "293.291,235". - * + * * An example of this function being called: * * wfMsg( 'message', $wgLang->formatNum( $num ) ) * - * + * * See LanguageGu.php for the Gujarati implementation and * LanguageIs.php for the , => . and . => , implementation. - * + * * @todo check if it's viable to use localeconv() for the decimal * seperator thing. * @access public * @param mixed $number the string to be formatted, should be an integer or - * a floating point number. + * a floating point number. * @param bool $year are we being passed a year? (turns off commafication) * @return mixed whatever we're fed if it's a year, a string otherwise. */ function formatNum( $number, $year = false ) { return $year ? $number : $this->commafy($number); } - + /** * Adds commas to a given number * @@ -2779,7 +2783,7 @@ class Language { function segmentForDiff( $text ) { return $text; } - + /** * and unsegment to show the result * @@ -2794,7 +2798,7 @@ class Language { function convert( $text, $isTitle = false) { return $this->mConverter->convert($text, $isTitle); } - + /** * Perform output conversion on a string, and encode for safe HTML output. * @param string $text @@ -2828,7 +2832,7 @@ class Language { /** * if a language supports multiple variants, it is * possible that non-existing link in one variant - * actually exists in another variant. this function + * actually exists in another variant. this function * tries to find it. See e.g. LanguageZh.php * * @param string $link the name of the link @@ -2854,17 +2858,17 @@ class Language { * for languages that support multiple variants, the title of an * article may be displayed differently in different variants. this * function returns the apporiate title defined in the body of the article. - * + * * @return string */ function getParsedTitle() { return $this->mConverter->getParsedTitle(); } - + /** * Enclose a string with the "no conversion" tag. This is used by * various functions in the Parser - * + * * @param string $text text to be tagged for no conversion * @return string the tagged text */ diff --git a/maintenance/archives/patch-interwiki-trans.sql b/maintenance/archives/patch-interwiki-trans.sql new file mode 100644 index 0000000000..2384a66a0e --- /dev/null +++ b/maintenance/archives/patch-interwiki-trans.sql @@ -0,0 +1,2 @@ +ALTER TABLE /*$wgDBprefix*/interwiki + ADD COLUMN iw_trans TINYINT(1) NOT NULL DEFAULT 0; diff --git a/maintenance/archives/patch-transcache.sql b/maintenance/archives/patch-transcache.sql new file mode 100644 index 0000000000..fcc1adadcc --- /dev/null +++ b/maintenance/archives/patch-transcache.sql @@ -0,0 +1,7 @@ +CREATE TABLE /*$wgDBprefix*/transcache ( + tc_url TEXT NOT NULL, + tc_contents TEXT, + tc_time INT NOT NULL, + UNIQUE INDEX tc_url_idx(tc_url(512)) +); + diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index 892e4bd494..82b1301929 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -24,6 +24,7 @@ $wgNewTables = array( array( 'logging', 'patch-logging.sql' ), array( 'validate', 'patch-validate.sql' ), array( 'user_newtalk', 'patch-usernewtalk2.sql' ), + array( 'transcache', 'patch-transcache.sql' ), ); $wgNewFields = array( @@ -47,6 +48,7 @@ $wgNewFields = array( array( 'image', 'img_media_type', 'patch-img_media_type.sql' ), array( 'validate', 'val_ip', 'patch-val_ip.sql' ), array( 'site_stats', 'ss_total_pages', 'patch-ss_total_articles.sql' ), + array( 'interwiki', 'iw_trans', 'patch-interwiki-trans.sql' ), ); function rename_table( $from, $to, $patch ) { -- 2.20.1