summaryrefslogtreecommitdiff
path: root/includes/Wiki.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/Wiki.php')
-rw-r--r--includes/Wiki.php161
1 files changed, 125 insertions, 36 deletions
diff --git a/includes/Wiki.php b/includes/Wiki.php
index a4a89032..ae75bf33 100644
--- a/includes/Wiki.php
+++ b/includes/Wiki.php
@@ -85,8 +85,6 @@ class MediaWiki {
} elseif ( $curid ) {
// URLs like this are generated by RC, because rc_title isn't always accurate
$ret = Title::newFromID( $curid );
- } elseif ( $title == '' && $action != 'delete' ) {
- $ret = Title::newMainPage();
} else {
$ret = Title::newFromURL( $title );
// Alias NS_MEDIA page URLs to NS_FILE...we only use NS_MEDIA
@@ -102,8 +100,12 @@ class MediaWiki {
$wgContLang->findVariantLink( $title, $ret );
}
}
- // For non-special titles, check for implicit titles
- if ( is_null( $ret ) || !$ret->isSpecialPage() ) {
+
+ // If title is not provided, always allow oldid and diff to set the title.
+ // If title is provided, allow oldid and diff to override the title, unless
+ // we are talking about a special page which might use these parameters for
+ // other purposes.
+ if ( $ret === null || !$ret->isSpecialPage() ) {
// We can have urls with just ?diff=,?oldid= or even just ?diff=
$oldid = $request->getInt( 'oldid' );
$oldid = $oldid ? $oldid : $request->getInt( 'diff' );
@@ -114,6 +116,11 @@ class MediaWiki {
}
}
+ // Use the main page as default title if nothing else has been provided
+ if ( $ret === null && strval( $title ) === '' && $action !== 'delete' ) {
+ $ret = Title::newMainPage();
+ }
+
if ( $ret === null || ( $ret->getDBkey() == '' && $ret->getInterwiki() == '' ) ) {
$ret = SpecialPage::getTitleFor( 'Badtitle' );
}
@@ -126,7 +133,7 @@ class MediaWiki {
* @return Title
*/
public function getTitle() {
- if( $this->context->getTitle() === null ){
+ if ( $this->context->getTitle() === null ) {
$this->context->setTitle( $this->parseTitle() );
}
return $this->context->getTitle();
@@ -169,6 +176,7 @@ class MediaWiki {
* - special pages
* - normal pages
*
+ * @throws MWException|PermissionsError|BadTitleError|HttpError
* @return void
*/
private function performRequest() {
@@ -177,7 +185,7 @@ class MediaWiki {
wfProfileIn( __METHOD__ );
$request = $this->context->getRequest();
- $title = $this->context->getTitle();
+ $requestTitle = $title = $this->context->getTitle();
$output = $this->context->getOutput();
$user = $this->context->getUser();
@@ -226,7 +234,7 @@ class MediaWiki {
if ( $title->getInterwiki() != '' ) {
$rdfrom = $request->getVal( 'rdfrom' );
if ( $rdfrom ) {
- $url = $title->getFullURL( 'rdfrom=' . urlencode( $rdfrom ) );
+ $url = $title->getFullURL( array( 'rdfrom' => $rdfrom ) );
} else {
$query = $request->getValues();
unset( $query['title'] );
@@ -246,7 +254,7 @@ class MediaWiki {
// Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant
} elseif ( $request->getVal( 'action', 'view' ) == 'view' && !$request->wasPosted()
&& ( $request->getVal( 'title' ) === null ||
- $title->getPrefixedDBKey() != $request->getVal( 'title' ) )
+ $title->getPrefixedDBkey() != $request->getVal( 'title' ) )
&& !count( $request->getValueNames( array( 'action', 'title' ) ) )
&& wfRunHooks( 'TestCanonicalRedirect', array( $request, $title, $output ) ) )
{
@@ -301,12 +309,13 @@ class MediaWiki {
global $wgArticle;
$wgArticle = new DeprecatedGlobal( 'wgArticle', $article, '1.18' );
- $this->performAction( $article );
+ $this->performAction( $article, $requestTitle );
} elseif ( is_string( $article ) ) {
$output->redirect( $article );
} else {
wfProfileOut( __METHOD__ );
- throw new MWException( "Shouldn't happen: MediaWiki::initializeArticle() returned neither an object nor a URL" );
+ throw new MWException( "Shouldn't happen: MediaWiki::initializeArticle()"
+ . " returned neither an object nor a URL" );
}
}
@@ -330,8 +339,18 @@ class MediaWiki {
wfProfileIn( __METHOD__ );
$title = $this->context->getTitle();
- $article = Article::newFromTitle( $title, $this->context );
- $this->context->setWikiPage( $article->getPage() );
+ if ( $this->context->canUseWikiPage() ) {
+ // Try to use request context wiki page, as there
+ // is already data from db saved in per process
+ // cache there from this->getAction() call.
+ $page = $this->context->getWikiPage();
+ $article = Article::newFromWikiPage( $page, $this->context );
+ } else {
+ // This case should not happen, but just in case.
+ $article = Article::newFromTitle( $title, $this->context );
+ $this->context->setWikiPage( $article->getPage() );
+ }
+
// NS_MEDIAWIKI has no redirects.
// It is also used for CSS/JS, so performance matters here...
if ( $title->getNamespace() == NS_MEDIAWIKI ) {
@@ -345,10 +364,10 @@ class MediaWiki {
// Check for redirects ...
$action = $request->getVal( 'action', 'view' );
$file = ( $title->getNamespace() == NS_FILE ) ? $article->getFile() : null;
- if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
- && !$request->getVal( 'oldid' ) && // ... and are not old revisions
- !$request->getVal( 'diff' ) && // ... and not when showing diff
- $request->getVal( 'redirect' ) != 'no' && // ... unless explicitly told not to
+ if ( ( $action == 'view' || $action == 'render' ) // ... for actions that show content
+ && !$request->getVal( 'oldid' ) && // ... and are not old revisions
+ !$request->getVal( 'diff' ) && // ... and not when showing diff
+ $request->getVal( 'redirect' ) != 'no' && // ... unless explicitly told not to
// ... and the article is not a non-redirect image page with associated file
!( is_object( $file ) && $file->exists() && !$file->getRedirected() ) )
{
@@ -395,8 +414,9 @@ class MediaWiki {
* Perform one of the "standard" actions
*
* @param $page Page
+ * @param $requestTitle The original title, before any redirects were applied
*/
- private function performAction( Page $page ) {
+ private function performAction( Page $page, Title $requestTitle ) {
global $wgUseSquid, $wgSquidMaxage;
wfProfileIn( __METHOD__ );
@@ -415,11 +435,12 @@ class MediaWiki {
$act = $this->getAction();
- $action = Action::factory( $act, $page );
+ $action = Action::factory( $act, $page, $this->context );
+
if ( $action instanceof Action ) {
# Let Squid cache things if we can purge them.
if ( $wgUseSquid &&
- in_array( $request->getFullRequestURL(), $title->getSquidURLs() )
+ in_array( $request->getFullRequestURL(), $requestTitle->getSquidURLs() )
) {
$output->setSquidMaxage( $wgSquidMaxage );
}
@@ -468,7 +489,7 @@ class MediaWiki {
$resp->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
$resp->header( 'X-Database-Lag: ' . intval( $lag ) );
$resp->header( 'Content-Type: text/plain' );
- if( $wgShowHostnames ) {
+ if ( $wgShowHostnames ) {
echo "Waiting for $host: $lag seconds lagged\n";
} else {
echo "Waiting for a database server: $lag seconds lagged\n";
@@ -510,6 +531,51 @@ class MediaWiki {
$action = $this->getAction();
$wgTitle = $title;
+ // If the user has forceHTTPS set to true, or if the user
+ // is in a group requiring HTTPS, or if they have the HTTPS
+ // preference set, redirect them to HTTPS.
+ // Note: Do this after $wgTitle is setup, otherwise the hooks run from
+ // isLoggedIn() will do all sorts of weird stuff.
+ if (
+ (
+ $request->getCookie( 'forceHTTPS', '' ) ||
+ // check for prefixed version for currently logged in users
+ $request->getCookie( 'forceHTTPS' ) ||
+ // Avoid checking the user and groups unless it's enabled.
+ (
+ $this->context->getUser()->isLoggedIn()
+ && $this->context->getUser()->requiresHTTPS()
+ )
+ ) &&
+ $request->detectProtocol() == 'http'
+ ) {
+ $oldUrl = $request->getFullRequestURL();
+ $redirUrl = str_replace( 'http://', 'https://', $oldUrl );
+
+ if ( $request->wasPosted() ) {
+ // This is weird and we'd hope it almost never happens. This
+ // means that a POST came in via HTTP and policy requires us
+ // redirecting to HTTPS. It's likely such a request is going
+ // to fail due to post data being lost, but let's try anyway
+ // and just log the instance.
+ //
+ // @todo @fixme See if we could issue a 307 or 308 here, need
+ // to see how clients (automated & browser) behave when we do
+ wfDebugLog( 'RedirectedPosts', "Redirected from HTTP to HTTPS: $oldUrl" );
+ }
+
+ // Setup dummy Title, otherwise OutputPage::redirect will fail
+ $title = Title::newFromText( NS_MAIN, 'REDIR' );
+ $this->context->setTitle( $title );
+ $output = $this->context->getOutput();
+ // Since we only do this redir to change proto, always send a vary header
+ $output->addVaryHeader( 'X-Forwarded-Proto' );
+ $output->redirect( $redirUrl );
+ $output->output();
+ wfProfileOut( __METHOD__ );
+ return;
+ }
+
if ( $wgUseFileCache && $title->getNamespace() >= 0 ) {
wfProfileIn( 'main-try-filecache' );
if ( HTMLFileCache::useFileCache( $this->context ) ) {
@@ -555,9 +621,6 @@ class MediaWiki {
// Execute a job from the queue
$this->doJobs();
- // Log message usage, if $wgAdaptiveMessageCache is set to true
- MessageCache::logMessages();
-
// Log profiling data, e.g. in the database or UDP
wfLogProfilingData();
@@ -573,33 +636,59 @@ class MediaWiki {
* Do a job from the job queue
*/
private function doJobs() {
- global $wgJobRunRate;
+ global $wgJobRunRate, $wgPhpCli, $IP;
if ( $wgJobRunRate <= 0 || wfReadOnly() ) {
return;
}
+
if ( $wgJobRunRate < 1 ) {
$max = mt_getrandmax();
if ( mt_rand( 0, $max ) > $max * $wgJobRunRate ) {
- return;
+ return; // the higher $wgJobRunRate, the less likely we return here
}
$n = 1;
} else {
$n = intval( $wgJobRunRate );
}
- while ( $n-- && false != ( $job = Job::pop() ) ) {
- $output = $job->toString() . "\n";
- $t = - microtime( true );
- $success = $job->run();
- $t += microtime( true );
- $t = round( $t * 1000 );
- if ( !$success ) {
- $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
- } else {
- $output .= "Success, Time: $t ms\n";
+ if ( !wfShellExecDisabled() && is_executable( $wgPhpCli ) ) {
+ // Start a background process to run some of the jobs.
+ // This will be asynchronous on *nix though not on Windows.
+ wfProfileIn( __METHOD__ . '-exec' );
+ $retVal = 1;
+ $cmd = wfShellWikiCmd( "$IP/maintenance/runJobs.php", array( '--maxjobs', $n ) );
+ wfShellExec( "$cmd &", $retVal );
+ wfProfileOut( __METHOD__ . '-exec' );
+ } else {
+ try {
+ // Fallback to running the jobs here while the user waits
+ $group = JobQueueGroup::singleton();
+ do {
+ $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue
+ if ( $job ) {
+ $output = $job->toString() . "\n";
+ $t = - microtime( true );
+ wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
+ $success = $job->run();
+ wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
+ $group->ack( $job ); // done
+ $t += microtime( true );
+ $t = round( $t * 1000 );
+ if ( $success === false ) {
+ $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n";
+ } else {
+ $output .= "Success, Time: $t ms\n";
+ }
+ wfDebugLog( 'jobqueue', $output );
+ }
+ } while ( --$n && $job );
+ } catch ( MWException $e ) {
+ // We don't want exceptions thrown during job execution to
+ // be reported to the user since the output is already sent.
+ // Instead we just log them.
+ MWExceptionHandler::logException( $e );
}
- wfDebugLog( 'jobqueue', $output );
}
}
}