From 8da9fca6c03fa8b2ca8bc83f8704e1219aa3904d Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Tue, 31 Jan 2006 03:44:08 +0000 Subject: [PATCH] Fixes and improvements to interwiki transclusion: * allow interwiki {{subst:...}} using action=raw fetches * Allowed non-MSIE browsers to access action=raw via the article alias. This is necessary to allow action=raw transclusion, since the only known URL is the article path, not the script path. * Specify a user agent in wfGetHttp() fetches, when using curl. * Added transcache table to tables.sql, it was in the updater but not there for some reason. * Fixed transcache expiry, added option * Allow interwiki transclusion outside the template namespace using leading colon syntax. Syntax is counterintuitive at times, e.g. to subst the wikipedia main page you would use {{subst::Wikipedia:Main_Page}} not {{subst:Wikipedia::Main_Page}}. --- includes/DefaultSettings.php | 4 + includes/HttpFunctions.php | 6 +- includes/Parser.php | 111 ++++++++++++---------- includes/RawPage.php | 4 +- maintenance/archives/patch-transcache.sql | 2 +- maintenance/mysql5/tables.sql | 10 ++ maintenance/tables.sql | 10 ++ 7 files changed, 94 insertions(+), 53 deletions(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 31ef6296ed..f6ff4f2e88 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1831,6 +1831,10 @@ $wgHTTPProxy = false; * Enable interwiki transcluding. Only when iw_trans=1. */ $wgEnableScaryTranscluding = false; +/** + * Expiry time for interwiki transclusion + */ +$wgTranscludeCacheExpiry = 3600; /** * Support blog-style "trackbacks" for articles. See diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index c7cc038afb..9dbfe0118d 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -9,20 +9,22 @@ * if $timeout is 'default', $wgHTTPTimeout is used */ function wfGetHTTP( $url, $timeout = 'default' ) { - global $wgHTTPTimeout, $wgHTTPProxy; + global $wgHTTPTimeout, $wgHTTPProxy, $wgVersion; # Use curl if available if ( function_exists( 'curl_init' ) ) { $c = curl_init( $url ); if ( wfIsLocalURL( $url ) ) { curl_setopt( $c, CURLOPT_PROXY, 'localhost:80' ); - } else if ($wgHTTPProxy) + } else if ($wgHTTPProxy) { curl_setopt($c, CURLOPT_PROXY, $wgHTTPProxy); + } if ( $timeout == 'default' ) { $timeout = $wgHTTPTimeout; } curl_setopt( $c, CURLOPT_TIMEOUT, $timeout ); + curl_setopt( $c, CURLOPT_USERAGENT, "MediaWiki/$wgVersion" ); ob_start(); curl_exec( $c ); $text = ob_get_contents(); diff --git a/includes/Parser.php b/includes/Parser.php index 580d63b18a..5d5c4b4a11 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -2359,6 +2359,8 @@ class Parser $found = false; $nowiki = false; $noparse = false; + $replaceHeadings = false; + $isHTML = false; $title = NULL; @@ -2531,8 +2533,6 @@ class Parser } # Load from database - $replaceHeadings = false; - $isHTML = false; $lastPathLevel = $this->mTemplatePath; if ( !$found ) { $ns = NS_TEMPLATE; @@ -2542,46 +2542,51 @@ class Parser } $title = Title::newFromText( $part1, $ns ); - if ($title) { - $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(); - if ( $this->incrementIncludeCount( $dbk ) ) { - if ( $title->getNamespace() == NS_SPECIAL && $this->mOptions->getAllowSpecialInclusion() ) { - # Capture special page output - $text = SpecialPage::capturePath( $title ); - if ( is_string( $text ) ) { - $found = true; - $noparse = true; - $isHTML = true; - $this->disableCache(); - } - } else { - $articleContent = $this->fetchTemplate( $title ); - if ( $articleContent !== false ) { - $found = true; - $text = $articleContent; - $replaceHeadings = true; + if ( !is_null( $title ) ) { + if ( !$title->isExternal() ) { + # Check for excessive inclusion + $dbk = $title->getPrefixedDBkey(); + if ( $this->incrementIncludeCount( $dbk ) ) { + if ( $title->getNamespace() == NS_SPECIAL && $this->mOptions->getAllowSpecialInclusion() ) { + # Capture special page output + $text = SpecialPage::capturePath( $title ); + if ( is_string( $text ) ) { + $found = true; + $noparse = true; + $isHTML = true; + $this->disableCache(); + } + } else { + $articleContent = $this->fetchTemplate( $title ); + if ( $articleContent !== false ) { + $found = true; + $text = $articleContent; + $replaceHeadings = true; + } } } - } - # If the title is valid but undisplayable, make a link to it - if ( $this->mOutputType == OT_HTML && !$found ) { - $text = '[['.$title->getPrefixedText().']]'; - $found = true; - } + # If the title is valid but undisplayable, make a link to it + if ( $this->mOutputType == OT_HTML && !$found ) { + $text = '[['.$title->getPrefixedText().']]'; + $found = true; + } - # Template cache array insertion - if( $found ) { - $this->mTemplates[$part1] = $text; - $text = $linestart . $text; + # Template cache array insertion + if( $found ) { + $this->mTemplates[$part1] = $text; + $text = $linestart . $text; + } + } elseif ( $title->isTrans() ) { + // Interwiki transclusion + if ( $this->mOutputType == OT_HTML ) { + $text = $this->interwikiTransclude( $title, 'render' ); + $isHTML = true; + $noparse = true; + } else { + $text = $this->interwikiTransclude( $title, 'raw' ); + } + $found = true; } } } @@ -2714,41 +2719,49 @@ class Parser } /** - * Translude an interwiki link. + * Transclude an interwiki link. */ - function scarytransclude($title, $interwiki) { - global $wgEnableScaryTranscluding; + function interwikiTransclude( $title, $action ) { + global $wgEnableScaryTranscluding, $wgCanonicalNamespaceNames; if (!$wgEnableScaryTranscluding) return wfMsg('scarytranscludedisabled'); - $articlename = "Template:" . $title->getDBkey(); - $url = str_replace('$1', urlencode($articlename), $interwiki); + // The namespace will actually only be 0 or 10, depending on whether there was a leading : + // But we'll handle it generally anyway + if ( $title->getNamespace() ) { + // Use the canonical namespace, which should work anywhere + $articleName = $wgCanonicalNamespaceNames[$title->getNamespace()] . ':' . $title->getDBkey(); + } else { + $articleName = $title->getDBkey(); + } + + $url = str_replace('$1', urlencode($articleName), Title::getInterwikiLink($title->getInterwiki())); + $url .= "?action=$action"; if (strlen($url) > 255) return wfMsg('scarytranscludetoolong'); - $text = $this->fetchScaryTemplateMaybeFromCache($url); - $this->mIWTransData[] = $text; - return ""; + return $this->fetchScaryTemplateMaybeFromCache($url); } function fetchScaryTemplateMaybeFromCache($url) { + global $wgTranscludeCacheExpiry; $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))) { + if ($time && time() < $time + $wgTranscludeCacheExpiry ) { return $text; } } - $text = wfGetHTTP($url . '?action=render'); + $text = wfGetHTTP($url); if (!$text) return wfMsg('scarytranscludefailed', $url); $dbw =& wfGetDB(DB_MASTER); - $dbw->replace('transcache', array(), array( + $dbw->replace('transcache', array('tc_url'), array( 'tc_url' => $url, 'tc_time' => time(), 'tc_contents' => $text)); diff --git a/includes/RawPage.php b/includes/RawPage.php index b5bc548bef..1093cf9e06 100644 --- a/includes/RawPage.php +++ b/includes/RawPage.php @@ -83,7 +83,9 @@ class RawPage { } else { $url = $_SERVER['PHP_SELF']; } - if( strcmp( $wgScript, $url ) ) { + + $ua = @$_SERVER['HTTP_USER_AGENT']; + if( strcmp( $wgScript, $url ) && strpos( $ua, 'MSIE' ) !== false ) { # Internet Explorer will ignore the Content-Type header if it # thinks it sees a file extension it recognizes. Make sure that # all raw requests are done through the script node, which will diff --git a/maintenance/archives/patch-transcache.sql b/maintenance/archives/patch-transcache.sql index 2bdc10cbc4..a244bff898 100644 --- a/maintenance/archives/patch-transcache.sql +++ b/maintenance/archives/patch-transcache.sql @@ -3,5 +3,5 @@ CREATE TABLE /*$wgDBprefix*/transcache ( tc_contents TEXT, tc_time INT NOT NULL, UNIQUE INDEX tc_url_idx(tc_url) -); +) TYPE=InnoDB; diff --git a/maintenance/mysql5/tables.sql b/maintenance/mysql5/tables.sql index f08e39ffd8..1186250716 100644 --- a/maintenance/mysql5/tables.sql +++ b/maintenance/mysql5/tables.sql @@ -851,6 +851,16 @@ CREATE TABLE /*$wgDBprefix*/objectcache ( ) TYPE=InnoDB, DEFAULT CHARSET=utf8; +-- +-- Cache of interwiki transclusion +-- +CREATE TABLE /*$wgDBprefix*/transcache ( + tc_url VARCHAR(255) NOT NULL, + tc_contents TEXT, + tc_time INT NOT NULL, + UNIQUE INDEX tc_url_idx(tc_url) +) TYPE=InnoDB, DEFAULT CHARSET=utf8; + -- For article validation CREATE TABLE /*$wgDBprefix*/validate ( val_user int(11) NOT NULL default '0', diff --git a/maintenance/tables.sql b/maintenance/tables.sql index 2aa58c4713..e902cd605e 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -838,6 +838,16 @@ CREATE TABLE /*$wgDBprefix*/objectcache ( ) TYPE=InnoDB; +-- +-- Cache of interwiki transclusion +-- +CREATE TABLE /*$wgDBprefix*/transcache ( + tc_url VARCHAR(255) NOT NULL, + tc_contents TEXT, + tc_time INT NOT NULL, + UNIQUE INDEX tc_url_idx(tc_url) +) TYPE=InnoDB; + -- For article validation CREATE TABLE /*$wgDBprefix*/validate ( val_user int(11) NOT NULL default '0', -- 2.20.1