From 5fc6bb9f16db3756bd48a48ab90355e26ec599cc Mon Sep 17 00:00:00 2001 From: Happy-melon Date: Mon, 4 Apr 2011 23:09:21 +0000 Subject: [PATCH] Fix for catchable fatals thrown on invalid titles, follow-up to miscellaneous Context commit pulled out of a hat (let's go for r85252). We must always have a Title object, even on invalid titles, for the purposes of not melting the Skin. The previous method was to make that a barely-existent half-title from SpecialPage::getTitleFor( 'Badtitle' ), where that is a special page which is not actually defined, but exists in the localisation alias lists. Instead, subclass Title as an explicit BadTitle which we can test for. The badtitle error page, which has empty string for its name in all forms, would probably be quite a good test of our JavaScript error checking. --- includes/AutoLoader.php | 1 + includes/Title.php | 34 +++++++++++++++++++++++++++++++ includes/Wiki.php | 24 +++++++++++++--------- languages/messages/MessagesEn.php | 1 - 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 6bf28544d4..7743a6c268 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -22,6 +22,7 @@ $wgAutoloadLocalClasses = array( 'AuthPlugin' => 'includes/AuthPlugin.php', 'AuthPluginUser' => 'includes/AuthPlugin.php', 'Autopromote' => 'includes/Autopromote.php', + 'BadTitle' => 'includes/Title.php', 'BacklinkCache' => 'includes/BacklinkCache.php', 'Block' => 'includes/Block.php', 'CacheDependency' => 'includes/CacheDependency.php', diff --git a/includes/Title.php b/includes/Title.php index 051998c0ef..45a31a3485 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -4215,3 +4215,37 @@ class Title { return $unprefixed; } } + +/** + * A BadTitle is generated in MediaWiki::parseTitle() if the title is invalid; the + * software uses this to display an error page. Internally it's basically a Title + * for an empty special page + */ +class BadTitle extends Title { + public function __construct(){ + $this->mTextform = ''; + $this->mUrlform = ''; + $this->mDbkeyform = ''; + $this->mNamespace = NS_SPECIAL; // Stops talk page link, etc, being shown + } + + public function exists(){ + return false; + } + + public function getPrefixedText(){ + return ''; + } + + public function getText(){ + return ''; + } + + public function getPrefixedURL(){ + return ''; + } + + public function getPrefixedDBKey(){ + return ''; + } +} \ No newline at end of file diff --git a/includes/Wiki.php b/includes/Wiki.php index b8c966b9fc..3bf94d24a6 100644 --- a/includes/Wiki.php +++ b/includes/Wiki.php @@ -137,8 +137,9 @@ class MediaWiki { $ret = Title::newFromURL( $title ); // check variant links so that interwiki links don't have to worry // about the possible different language variants - if ( count( $wgContLang->getVariants() ) > 1 && !is_null( $ret ) && $ret->getArticleID() == 0 ) + if ( count( $wgContLang->getVariants() ) > 1 && !is_null( $ret ) && $ret->getArticleID() == 0 ){ $wgContLang->findVariantLink( $title, $ret ); + } } // For non-special titles, check for implicit titles if ( is_null( $ret ) || $ret->getNamespace() != NS_SPECIAL ) { @@ -151,6 +152,10 @@ class MediaWiki { $ret = $rev ? $rev->getTitle() : $ret; } } + + if( $ret === null || ( $ret->getDBkey() == '' && $ret->getInterwiki() == '' ) ){ + $ret = new BadTitle; + } return $ret; } @@ -178,8 +183,7 @@ class MediaWiki { wfProfileIn( __METHOD__ ); // Invalid titles. Bug 21776: The interwikis must redirect even if the page name is empty. - if ( is_null( $this->context->title ) || ( ( $this->context->title->getDBkey() == '' ) && ( $this->context->title->getInterwiki() == '' ) ) ) { - $this->context->title = SpecialPage::getTitleFor( 'Badtitle' ); + if ( $this->context->title instanceof BadTitle ) { // Die now before we mess up $wgArticle and the skin stops working throw new ErrorPageError( 'badtitle', 'badtitletext' ); @@ -193,12 +197,12 @@ class MediaWiki { unset( $query['title'] ); $url = $this->context->title->getFullURL( $query ); } - /* Check for a redirect loop */ + // Check for a redirect loop if ( !preg_match( '/^' . preg_quote( $this->getVal( 'Server' ), '/' ) . '/', $url ) && $this->context->title->isLocal() ) { // 301 so google et al report the target as the actual url. $this->context->output->redirect( $url, 301 ); } else { - $this->context->title = SpecialPage::getTitleFor( 'Badtitle' ); + $this->context->title = new BadTitle; wfProfileOut( __METHOD__ ); throw new ErrorPageError( 'badtitle', 'badtitletext' ); } @@ -244,14 +248,14 @@ class MediaWiki { } // Special pages } else if ( NS_SPECIAL == $this->context->title->getNamespace() ) { - /* actions that need to be made when we have a special pages */ + // actions that need to be made when we have a special pages SpecialPage::executePath( $this->context->title, $this->context ); } else { - /* No match to special cases */ + // No match to special cases wfProfileOut( __METHOD__ ); return false; } - /* Did match a special case */ + // Did match a special case wfProfileOut( __METHOD__ ); return true; } @@ -514,10 +518,10 @@ class MediaWiki { break; case 'submit': if ( session_id() == '' ) { - /* Send a cookie so anons get talk message notifications */ + // Send a cookie so anons get talk message notifications wfSetupSession(); } - /* Continue... */ + // Continue... case 'edit': if ( wfRunHooks( 'CustomEditor', array( $article, $this->context->user ) ) ) { $internal = $this->context->request->getVal( 'internaledit' ); diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 7ccbb0f1e8..eee59383c1 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -382,7 +382,6 @@ $specialPageAliases = array( 'Allmessages' => array( 'AllMessages' ), 'Allpages' => array( 'AllPages' ), 'Ancientpages' => array( 'AncientPages' ), - 'Badtitle' => array( 'Badtitle' ), 'Blankpage' => array( 'BlankPage' ), 'Block' => array( 'Block', 'BlockIP', 'BlockUser' ), 'Blockme' => array( 'BlockMe' ), -- 2.20.1