Use dedicated cookie for skipping CDN cache after initiating DB changes
[lhc/web/wiklou.git] / includes / MediaWiki.php
index bb0f1e4..c00be95 100644 (file)
@@ -36,6 +36,11 @@ class MediaWiki {
         */
        private $config;
 
+       /**
+        * @var String Cache what action this request is
+        */
+       private $action;
+
        /**
         * @param IContextSource|null $context
         */
@@ -141,13 +146,11 @@ class MediaWiki {
         * @return string Action
         */
        public function getAction() {
-               static $action = null;
-
-               if ( $action === null ) {
-                       $action = Action::getActionName( $this->context );
+               if ( $this->action === null ) {
+                       $this->action = Action::getActionName( $this->context );
                }
 
-               return $action;
+               return $this->action;
        }
 
        /**
@@ -241,8 +244,37 @@ class MediaWiki {
                // Handle any other redirects.
                // Redirect loops, titleless URL, $wgUsePathInfo URLs, and URLs with a variant
                } elseif ( !$this->tryNormaliseRedirect( $title ) ) {
+                       // Prevent information leak via Special:MyPage et al (T109724)
+                       if ( $title->isSpecialPage() ) {
+                               $specialPage = SpecialPageFactory::getPage( $title->getDBKey() );
+                               if ( $specialPage instanceof RedirectSpecialPage
+                                       && $this->config->get( 'HideIdentifiableRedirects' )
+                                       && $specialPage->personallyIdentifiableTarget()
+                               ) {
+                                       list( , $subpage ) = SpecialPageFactory::resolveAlias( $title->getDBKey() );
+                                       $target = $specialPage->getRedirect( $subpage );
+                                       // target can also be true. We let that case fall through to normal processing.
+                                       if ( $target instanceof Title ) {
+                                               $query = $specialPage->getRedirectQuery() ?: array();
+                                               $request = new DerivativeRequest( $this->context->getRequest(), $query );
+                                               $request->setRequestURL( $this->context->getRequest()->getRequestURL() );
+                                               $this->context->setRequest( $request );
+                                               // Do not varnish cache these. May vary even for anons
+                                               $this->context->getOutput()->lowerCdnMaxage( 0 );
+                                               $this->context->setTitle( $target );
+                                               $wgTitle = $target;
+                                               // Reset action type cache. (Special pages have only view)
+                                               $this->action = null;
+                                               $title = $target;
+                                               $output->addJsConfigVars( array(
+                                                       'wgInternalRedirectTargetUrl' => $target->getFullURL( $query ),
+                                               ) );
+                                               $output->addModules( 'mediawiki.action.view.redirect' );
+                                       }
+                               }
+                       }
 
-                       // Special pages
+                       // Special pages ($title may have changed since if statement above)
                        if ( NS_SPECIAL == $title->getNamespace() ) {
                                // Actions that need to be made when we have a special pages
                                SpecialPageFactory::executePath( $title, $this->context );
@@ -516,13 +548,13 @@ class MediaWiki {
                                if ( $limit > 0 && $time > $limit ) {
                                        throw new DBTransactionError(
                                                $db,
-                                               wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->plain()
+                                               wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
                                        );
                                }
                        } );
                } );
                // Commit all changes
-               $factory->commitMasterChanges();
+               $factory->commitMasterChanges( __METHOD__ );
                // Record ChronologyProtector positions
                $factory->shutdown();
                wfDebug( __METHOD__ . ': all transactions committed' );
@@ -535,7 +567,9 @@ class MediaWiki {
                $request = $context->getRequest();
                if ( $request->wasPosted() && $factory->hasOrMadeRecentMasterChanges() ) {
                        $expires = time() + $config->get( 'DataCenterUpdateStickTTL' );
-                       $request->response()->setCookie( 'UseDC', 'master', $expires, array( 'prefix' => '' ) );
+                       $options = array( 'prefix' => '' );
+                       $request->response()->setCookie( 'UseDC', 'master', $expires, $options );
+                       $request->response()->setCookie( 'UseCDNCache', 'false', $expires, $options );
                }
 
                // Avoid letting a few seconds of slave lag cause a month of stale data
@@ -618,14 +652,10 @@ class MediaWiki {
                $trxProfiler = Profiler::instance()->getTransactionProfiler();
                $trxProfiler->setLogger( LoggerFactory::getInstance( 'DBPerformance' ) );
 
-               // Aside from rollback, master queries should not happen on GET requests.
-               // Periodic or "in passing" updates on GET should use the job queue.
-               if ( !$request->wasPosted()
-                       && in_array( $action, array( 'view', 'edit', 'history' ) )
-               ) {
-                       $trxProfiler->setExpectations( $wgTrxProfilerLimits['GET'], __METHOD__ );
-               } else {
+               if ( $request->wasPosted() ) {
                        $trxProfiler->setExpectations( $wgTrxProfilerLimits['POST'], __METHOD__ );
+               } else {
+                       $trxProfiler->setExpectations( $wgTrxProfilerLimits['GET'], __METHOD__ );
                }
 
                // If the user has forceHTTPS set to true, or if the user
@@ -713,7 +743,7 @@ class MediaWiki {
         */
        public function restInPeace( $mode = 'fast' ) {
                // Assure deferred updates are not in the main transaction
-               wfGetLBFactory()->commitMasterChanges();
+               wfGetLBFactory()->commitMasterChanges( __METHOD__ );
 
                // Ignore things like master queries/connections on GET requests
                // as long as they are in deferred updates (which catch errors).
@@ -736,7 +766,7 @@ class MediaWiki {
 
                // Commit and close up!
                $factory = wfGetLBFactory();
-               $factory->commitMasterChanges();
+               $factory->commitMasterChanges( __METHOD__ );
                $factory->shutdown( LBFactory::SHUTDOWN_NO_CHRONPROT );
 
                wfDebug( "Request ended normally\n" );