Yurik has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/85641


Change subject: Removed X-CS dependency in HTML content rewriting
......................................................................

Removed X-CS dependency in HTML content rewriting

* onMobileFrontendBeforeDOM() will now always produce the same result, 
regardless of the X-CS, to allow future removal of cache variance.
* All <a> tags with href containing host or with class='image' will now point 
to the Zero special page with two query params: to=URL & from=CurrentTitle
* The Zero special page adds varying on X-CS and X-Subdomain
* If special page has valid 'to' & 'from' params, it will show confirmation 
page in case X-CS-based configuration demands it, or silently redirects.

Change-Id: I012c43d2f5b9a2cfb4132f682c3fd76e48650811
---
M includes/PageRenderingHooks.php
M includes/ZeroSpecialPage.php
2 files changed, 255 insertions(+), 278 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ZeroRatedMobileAccess 
refs/changes/41/85641/1

diff --git a/includes/PageRenderingHooks.php b/includes/PageRenderingHooks.php
index 2bf1c15..5ae80f0 100644
--- a/includes/PageRenderingHooks.php
+++ b/includes/PageRenderingHooks.php
@@ -4,7 +4,6 @@
 use BaseTemplate;
 use DOMElement;
 use DOMXPath;
-use FormatJson;
 use Html;
 use Language;
 use MinervaTemplate;
@@ -13,6 +12,7 @@
 use RawMessage;
 use ResourceLoader;
 use SkinTemplate;
+use SpecialPage;
 use Title;
 use WebRequest;
 
@@ -31,13 +31,13 @@
 
        // TODO: Clean up HTML concatenation. Review for any non-escaped user 
input.
 
-       private static $originParent = '.wikipedia.org/';
        private static $zerodotParent = '.zero.wikipedia.org/';
        private static $mdotParent = '.m.wikipedia.org/';
-
+       public static $formatMobileUrl = '//%s.m.wikipedia.org/wiki/Main_Page';
+       public static $formatZeroUrl = '//%s.zero.wikipedia.org/wiki/Main_Page';
 
        /**
-        * GetMobileUrl hook handler
+        * GetMobileUrl hook handler - replaces *.m.* with *.zero.* if the 
current site is zero.
         *
         * @param $subdomainTokenReplacement string
         * @return bool
@@ -51,6 +51,7 @@
        }
 
        /**
+        * Rewrite DOM to replace content's external and image links with links 
to the special redirect page.
         * @param MobileContext $context
         * @param \MobileFormatter $formatter
         * @return bool
@@ -60,16 +61,17 @@
                if ( !self::isZeroSite() ) {
                        return true;
                }
-
                $config = self::getConfig();
-               if ( $config === null || $context->getTitle()->isSpecial( 
'ZeroRatedMobileAccess' ) ) {
+               if ( $config === null ) {
+                       return true;
+               }
+               $currentTitle = $context->getTitle();
+               if ( $currentTitle->isSpecial( 'ZeroRatedMobileAccess' ) ) {
                        return true;
                }
 
-               global $wgRequest;
-
                wfProfileIn( __METHOD__ );
-               $isFilePage = $context->getTitle()->inNamespace( NS_FILE );
+               $isFilePage = $currentTitle->inNamespace( NS_FILE );
                $doc = $formatter->getDoc();
                $xpath = new DOMXpath( $doc );
 
@@ -97,32 +99,24 @@
                        }
                }
 
-               if ( !$config['showImages'] ) {
-                       $zeroRatedLinks = $xpath->query( "//a[@class='image']" 
);
-                       /* @var $zeroRatedLink DOMElement */
-                       foreach ( $zeroRatedLinks as $zeroRatedLink ) {
-                               $zeroRatedLinkHref = 
$zeroRatedLink->getAttribute( 'href' );
-                               if ( $zeroRatedLinkHref && substr( 
$zeroRatedLinkHref, 0, 1 ) !== '#' ) {
-                                       $zeroPartnerUrl = 
$wgRequest->appendQuery(
-                                               
'renderZeroRatedBanner=true&renderwarning=yes&returnto='
-                                               . urlencode( wfAppendQuery( 
$zeroRatedLinkHref, 'acceptbilling=yes' ) )
-                                       );
-                                       if ( $zeroPartnerUrl ) {
-                                               $zeroRatedLink->setAttribute( 
'href', $zeroPartnerUrl );
-                                       }
-                               }
+               /* @var $link DOMElement */
+               foreach ( $xpath->query( '//a' ) as $link ) {
+                       $href = $link->getAttribute( 'href' );
+                       if ( !$href ) {
+                               continue; // Missing HREF
                        }
-               }
-
-               $zeroRatedExternalLinks = $xpath->query( 
"//a[contains(@class,'external')]" );
-               /* @var $zeroRatedExternalLink DOMElement */
-               foreach ( $zeroRatedExternalLinks as $zeroRatedExternalLink ) {
-                       $zeroRatedExternalLinkHref = 
$zeroRatedExternalLink->getAttribute( 'href' );
-                       if ( $zeroRatedExternalLinkHref && substr( 
$zeroRatedExternalLinkHref, 0, 1 ) !== '#' ) {
-                               $zeroRatedExternalLink->setAttribute(
-                                       'href',
-                                       
'?renderZeroRatedRedirect=true&returnto=' . urlencode( 
$zeroRatedExternalLinkHref ) );
+                       $ch0 = substr( $href, 0, 1 );
+                       if ( $ch0 === '#' ) {
+                               continue; // Anchor is never checked
                        }
+                       $ch1 = substr( $href, 1, 1 );
+                       $class = $link->getAttribute( 'class' );
+                       // Any link to image (class=image), or any non-local 
link will be redirected
+                       // Local links start with either '?...' or '/...', but 
not '//...'
+                       if ( $class !== 'image' && ( $ch0 === '?' || ( $ch0 === 
'/' && $ch1 !== '/' ) ) ) {
+                               continue;
+                       }
+                       $link->setAttribute( 'href', self::makeRedir( $href, 
$currentTitle ) );
                }
 
                wfProfileOut( __METHOD__ );
@@ -130,6 +124,7 @@
        }
 
        /**
+        * Invoked by MinervaTemplate to add banners
         * @param MinervaTemplate $template
         * @return bool
         */
@@ -140,41 +135,28 @@
                // TODO: alias $template->data where appropriate
                $bannersSupported = array_key_exists( 'banners', 
$template->data );
 
-               $config = self::getConfig();
-               if ( $config === null ) {
-                       if ( self::isZeroSubdomain() && $bannersSupported ) {
-                               $unsupported = self::renderUnknownCarrier( 
$req, $title, false );
-                               $template->set( 'banners', array( $unsupported 
) );
+               $banner = self::createBanner( $title, $req );
+               if ( $banner ) {
+                       if ( $bannersSupported ) {
+                               $template->set( 'banners', array( $banner ) );
                        }
-                       return true;
-               }
-
-               $redirectWarningQPS = 'renderZeroRatedRedirect=true&returnto=';
-
-               $warning = self::renderWarning( $config, $req, $title, false );
-
-               // TODO: If clearer way to put this, make it clearer
-               // trump all existing banners when in a banner-rendering context
-               if ( $bannersSupported ) {
-                       if ( isset( $warning ) ) {
-                               $template->set( 'banners', array( $warning ) );
-                               self::emptyLangLinks( $template );
-                       } else {
-                               $template->set( 'banners', array( 
self::renderBanner( $config, null, null, false ) ) );
-                               self::rewriteLangLinks( $template, $config, 
$redirectWarningQPS, $req );
+                       if ( self::getConfigId() !== null ) {
+                               if ( $bannersSupported ) {
+                                       self::rewriteLangLinks( $template, 
$title );
+                               }
+                               self::addWarning( $template, 'mobile-license', 
$title,
+                                       wfMessage( 
'mobile-frontend-footer-license' )->parse() );
+                               self::addWarning( $template, 'privacy', $title,
+                                       $template->getSkin()->footerLink( 
'mobile-frontend-privacy-link-text', 'privacypage' ) );
+                               self::addWarning( $template, 'terms-use', 
$title,
+                                       wfMessage( 
'mobile-frontend-terms-use-text' )->parse() );
                        }
                }
-
-               $skin = new SkinTemplate();
-
-               self::addWarning( $template, 'mobile-license', $req, wfMessage( 
'mobile-frontend-footer-license' )->parse() );
-               self::addWarning( $template, 'privacy', $req, 
$skin->footerLink( 'mobile-frontend-privacy-link-text', 'privacypage' ) );
-               self::addWarning( $template, 'terms-use', $req, wfMessage( 
'mobile-frontend-terms-use-text' )->parse() );
-
                return true;
        }
 
        /**
+        * Invoked by SkinMobileWML only to add banners
         * @param SkinTemplate $sk
         * @param $notice
         * @return bool
@@ -184,26 +166,10 @@
                SkinTemplate $sk,
                &$notice
        ) {
-               global $wgRequest;
-
-               $config = self::getConfig();
-               $title = $sk->getTitle();
-
-               if ( $config === null ) {
-                       if ( self::isZeroSubdomain() ) {
-                               $notice = self::renderUnknownCarrier( 
$wgRequest, $title, true );
-                       }
-                       return true;
+               $banner = self::createBanner( $sk->getTitle(), 
$sk->getRequest(), true );
+               if ( $banner ) {
+                       $notice = $banner;
                }
-
-               $warning = self::renderWarning( $config, $wgRequest, $title, 
true );
-
-               if ( isset( $warning ) ) {
-                       $notice = $warning;
-               } else {
-                       $notice = self::renderBanner( $config, null, null, true 
);
-               }
-
                return true;
        }
 
@@ -252,55 +218,29 @@
                $out->addVaryHeader( 'X-Subdomain' );
                $out->addVaryHeader( 'X-Images' );
 
+
+               // @FIXME: These should be removed in a month once cache clears 
up
+               if ( $wgRequest->getCheck( 'renderZeroRatedBanner' ) ||
+                       $wgRequest->getCheck( 'renderwarning' ) ||
+                       $wgRequest->getCheck( 'renderZeroRatedRedirect' ) )
+               {
+                       $url = $wgRequest->getVal( 'returnto' );
+                       if ( $url ) {
+                               if ( !$wgRequest->getCheck( 'acceptbilling' ) ) 
{
+                                       $url = self::makeRedir( $url, 
$out->getTitle() );
+                               }
+                               $out->redirect( $url );
+                               $out->output();
+                       }
+               }
+
                // @FIXME: Should not be added for non-zero sites
                $out->addModuleStyles( 'mobile.zero.styles' );
                $out->addModules( 'mobile.zero.scripts' );
 
-               $config = self::getConfig();
-               $isFilePage = $out->getTitle()->inNamespace( NS_FILE );
-               $showBanner = $config !== null || $wgRequest->getFuzzyBool( 
'renderZeroRatedBanner' );
-               if ( !$showBanner && self::isZeroSubdomain() ) {
-                       $out->clearHTML();
-                       $out->setPageTitle( null );
-                       wfProfileOut( __METHOD__ );
-                       return true;
-               }
-
-               $acceptBilling = $wgRequest->getVal( 'acceptbilling' );
-               // @BUG: weird code, need to check what was originally intended
-               if ( $config !== null && ( $acceptBilling === 'no' || 
$acceptBilling === 'yes' ) ) {
-                       $targetUrl = $wgRequest->getVal( 'returnto' );
-                       if ( $targetUrl ) {
-                               $out->redirect( $targetUrl, '301' );
-                               $out->output();
-                               // @BUG? Is "return false" needed here?
-                       }
-               }
-
-               $showWarning = false;
-               if ( $isFilePage ) {
-                       $showWarning = $config === null || 
!$config['showImages'];
-               } else {
-                       $showWarningFlag = $wgRequest->getVal( 'renderwarning' 
);
-                       if ( $showWarningFlag === 'yes' ) {
-                               $showWarning = true;
-                       }
-               }
-
-               if ( $showBanner && $config !== null ) {
-                       $options['toggle_view_desktop'] = 
'&renderZeroRatedBanner=true&renderwarning=yes&returnto=';
-                       $options['supported_languages'] = $config['showLangs'];
-               }
-
-               if ( ( $showBanner && $showWarning && $acceptBilling !== 'yes' )
-                       || $wgRequest->getFuzzyBool( 'renderZeroRatedRedirect' )
-               ) {
-                       $out->clearHTML();
-                       $out->setPageTitle( null );
-               } elseif ( $showBanner && $config !== null ) {
-                       $imgHeader = self::disableImages() ? 'X-Images: no' : 
'X-Images: yes';
-                       $wgRequest->response()->header( $imgHeader );
-               }
+//             $options['toggle_view_desktop'] = 
'&renderZeroRatedBanner=true&renderwarning=yes&returnto=';
+// fixme: never used?
+//             $options['supported_languages'] = $config['showLangs'];
 
                wfProfileOut( __METHOD__ );
                return true;
@@ -345,20 +285,47 @@
        }
 
        /**
+        * @param Title $title
+        * @param WebRequest $request
+        * @param bool $wap
+        * @return string with banner html
+        */
+       public static function createBanner( Title $title, WebRequest $request, 
$wap = false ) {
+               $config = self::getConfig();
+               if ( $config === null ) {
+                       // @fixme logic: In case of no X-CS, should we ignore 
all redirect attempts?
+                       if ( self::isZeroSubdomain() ) {
+                               return self::renderUnknownCarrier( $request, 
$title, $wap );
+                       }
+               } else {
+                       if ( $title->isSpecial( 'ZeroRatedMobileAccess' ) ) {
+                               $redir = self::getRedirectInfo();
+                               if ( array_key_exists( 'warn', $redir ) ) {
+                                       return self::renderWarning( $redir, 
$wap );
+                               } elseif ( array_key_exists( 'redirect', $redir 
) ) {
+                                       return '';
+                               }
+                       }
+                       return self::renderBanner( $config, null, null, $wap, 
$title );
+               }
+               return '';
+       }
+
+       /**
         * @param $config
         * @param Language $lang
         * @param string $sitename
         * @param bool $wap
+        * @param Title $currentTitle
         * @return string
         */
-       public static function renderBanner( $config, $lang = null, $sitename = 
null, $wap = false ) {
+       public static function renderBanner( $config, $lang = null, $sitename = 
null, $wap = false, Title $currentTitle = null ) {
                $bannerText = self::getBannerText( $config, $lang, $sitename );
                if ( $bannerText !== false ) {
-                       global $wgRequest;
-                       $billingURL = $wgRequest->appendQuery(
-                               
'renderZeroRatedBanner=true&renderwarning=yes&returnto='
-                               . urlencode( $config['bannerUrl'] )
-                       );
+                       $billingURL = $config['bannerUrl'];
+                       if ( $currentTitle !== null ) {
+                               $billingURL = self::makeRedir( $billingURL, 
$currentTitle );
+                       }
                        $carrierLink = Html::rawElement( 'a', array( 'href' => 
$billingURL ), $bannerText );
                        if ( !$config['bannerWarning'] ) {
                                preg_match( '/<a href="(.+)">/', $carrierLink, 
$match );
@@ -412,70 +379,19 @@
 
        /**
         * Provide an interstitial warning for links that may cause charges.
-        *
-        * @param $config
-        * @param $request
-        * @param Title $title
+        * @param $redir
         * @param bool $wap
         * @return null|string Warning banner if applicable, else null
         */
-       private static function renderWarning( $config, WebRequest $request, 
Title $title, $wap = false ) {
-
-               $isFilePage = $title->inNamespace( NS_FILE );
-               $acceptBilling = $request->getVal( 'acceptbilling' );
-
-               $showWarning = false;
-               if ( $isFilePage ) {
-                       $showWarning = !$config['showImages'];
-               } else {
-                       $showWarningFlag = $request->getVal( 'renderwarning' );
-                       if ( $showWarningFlag === 'yes' ) {
-                               $showWarning = true;
-                       }
-               }
-
-               if ( $showWarning && $acceptBilling !== 'yes' ) {
-                       $domainReplacement = self::isZeroSubdomain() ? 
self::$zerodotParent : self::$mdotParent;
-                       $question = self::renderQuestion(
-                               str_replace(
-                                       self::$originParent,
-                                       $domainReplacement,
-                                       wfExpandUrl( $request->appendQuery( 
'acceptbilling=yes' ), PROTO_CURRENT )
-                               ),
-                               false,
-                               $wap
-                       );
-               } elseif ( $request->getFuzzyBool( 'renderZeroRatedRedirect' ) 
) {
-                       $question = self::renderQuestion(
-                               $request->appendQuery(
-                                       
'acceptbilling=yes&renderZeroRatedBanner=true&returnto='
-                                       . urlencode( $request->getVal( 
'returnto' ) ) ),
-                               true, // isWarning
-                               $wap
-                       );
-               }
-
-               return isset( $question ) ? $question : null;
-       }
-
-
-       /**
-        * @param string $acceptUrl If user agrees, send them here
-        * @param bool $isWarning Adds mw-mf-banner-warning CSS class if true
-        * @param bool $wap
-        * @return string
-        */
-       private static function renderQuestion( $acceptUrl, $isWarning = false, 
$wap = false ) {
-               global $wgRequest;
-               $referrer = $wgRequest->getHeader( 'referer' );
-               $acceptBillingYes = Html::rawElement( 'a',
-                       array( 'href' => $acceptUrl ),
+       private static function renderWarning( $redir, $wap = false ) {
+               $accept = Html::rawElement( 'a',
+                       array( 'href' => $redir['to'] ),
                        wfMessage( 
'zero-rated-mobile-access-banner-text-data-charges-yes' )->escaped() );
-               $acceptBillingNo = Html::rawElement( 'a',
-                       array( 'href' => $wgRequest->appendQuery( 
'acceptbilling=no&returnto=' . urlencode( $referrer ) ) ),
+               $reject = Html::rawElement( 'a',
+                       array( 'href' => $redir['from']->getFullURL() ),
                        wfMessage( 
'zero-rated-mobile-access-banner-text-data-charges-no' )->escaped() );
                $question = wfMessage( 
'zero-rated-mobile-access-banner-text-data-charges' )
-                       ->rawParams( $acceptBillingYes, $acceptBillingNo 
)->escaped();
+                       ->rawParams( $accept, $reject )->escaped();
                if ( $wap ) {
                        return Html::rawElement( 'p', null, $question );
                } else {
@@ -486,7 +402,7 @@
                                $question
                        );
                        $cssClass = 'mw-mf-banner mw-mf-banner-undismissable';
-                       if ( $isWarning ) {
+                       if ( $redir['warn'] !== 'file' ) {
                                $cssClass .= ' mw-mf-banner-warning';
                        }
 
@@ -501,52 +417,28 @@
         * If a particular language could cause a charge, send user to an 
interstitial.
         *
         * @param BaseTemplate $template
-        * @param $config array containing carrier's configuration
-        * @param $qps string Query path separator
-        * @param WebRequest $request
+        * @param Title $currentTitle
         * @return bool
         */
-       private static function rewriteLangLinks( BaseTemplate $template, 
$config, $qps, WebRequest $request ) {
+       private static function rewriteLangLinks( BaseTemplate $template, Title 
$currentTitle ) {
 
                if ( isset( $template->data['language_urls'] )
                        && 0 < count( $template->data['language_urls'] )
                ) {
                        $languageUrls = $template->data['language_urls'];
-                       $freeLangs = $config['whitelistedLangs'];
+                       $isZeroSubdomain = self::isZeroSubdomain();
                        foreach ( $languageUrls as &$lang ) {
-                               if ( preg_match( 
'#^//([-a-zA-Z_]+)\.(zero|m)\.#', $lang['href'], $match ) ) {
-                                       $link = $lang['href'];
-                                       $isFree = ( 0 === count( $freeLangs ) 
|| in_array( $match[1], $freeLangs ) );
-                                       if ( !$isFree ) {
-                                               if ( self::isZeroSubdomain() ) {
-                                                       $link = str_replace( 
self::$zerodotParent, self::$mdotParent, $link );
-                                               }
-                                               $lang['href'] = 
$request->appendQuery( $qps . urlencode( $link ) );
-                                       }
+                               $link = $lang['href'];
+                               if ( $isZeroSubdomain ) {
+                                       $link = str_replace( 
self::$zerodotParent, self::$mdotParent, $link );
                                }
+                               $lang['href'] = self::makeRedir( $link, 
$currentTitle );
                        }
                        $template->set( 'language_urls', $languageUrls );
                }
 
                return true;
        }
-
-       /**
-        * Empty out the Read in Another Language list
-        *
-        * @param BaseTemplate $template
-        * @return bool
-        */
-       private static function emptyLangLinks( $template ) {
-               if ( isset( $template->data['language_urls'] )
-                       && 0 < count( $template->data['language_urls'] )
-               ) {
-                       $template->set( 'language_urls', array() );
-               }
-
-               return true;
-       }
-
 
        /**
         * @param $config
@@ -731,6 +623,89 @@
                return $isZero;
        }
 
+       public static function getRedirectInfo() {
+               static $result = null;
+               if ( $result === null ) {
+                       $result = array();
+                       $config = self::getConfig();
+                       global $wgRequest;
+                       $from = $wgRequest->getVal( 'from' );
+                       $toUrl = $wgRequest->getVal( 'to' );
+                       if ( $toUrl === null || $from === null ) {
+                               // This is not a redirect, see if we need to 
redirect to the Main Page
+                               if ( $config === null || 
!$config['showZeroPage'] ) {
+                                       $result = array( 'redirect' => 
self::getMainPage(), 'code' => '302' );
+                               }
+                               return $result;
+                       }
+                       $fromTitle = Title::newFromText( $from );
+                       if ( !$fromTitle ) {
+                               PageRenderingHooks::logDebug( 'invalidParams' );
+                               return $result;
+                       }
+                       if ( $config === null ) {
+                               PageRenderingHooks::logDebug( '!config' );
+                               $result = array( 'redirect' => $toUrl, 'code' 
=> '302' );
+                       } else {
+                               $redir = false;
+                               $urlBits = wfParseUrl( $toUrl );
+                               $toHost = is_array( $urlBits ) && 
array_key_exists( 'host', $urlBits ) ? $urlBits['host'] : false;
+                               if ( $toHost ) {
+                                       $toHost = strtolower( $toHost );
+                                       // fixme: need to check $host against 
local wikipedia host name
+                                       // fixme: this is a very rare case - a 
full URL to the local host
+                                       // if ( strcasecmp( $toHost, 
getCurrentWikiHostName ) === 0 ) {
+                                       //      $toHost = false;
+                                       // }
+                               }
+                               if ( $toHost ) {
+                                       // Match 
(optional-language.)(subdomain.site).org
+                                       if ( preg_match( 
'/^([^.]+\.)?([^.]+\.[^.]+)\.org$/', $toHost, $matches ) ) {
+                                               // Another language in wikipedia
+                                               $lang = $matches[1];
+                                               $site = $matches[2];
+                                               // see if the site is 
whitelisted, and if it is, make sure the language is.
+                                               if ( in_array( $site, 
$config['sites'] ) ) {
+                                                       if ( $lang ) {
+                                                               $freeLangs = 
$config['whitelistedLangs'];
+                                                               $redir = count( 
$freeLangs ) == 0 || in_array( rtrim( $lang, '.' ), $freeLangs );
+                                                       } else {
+                                                               $redir = true; 
// there is no language, but the site is whitelisted, so don't warn
+                                                       }
+                                               }
+                                       }
+                                       // else - external link, always warn
+                               } else {
+                                       // there was no host - must be a local 
link to an image
+                                       $redir = $config['showImages'];
+                               }
+                               if ( $redir ) {
+                                       $result = array( 'redirect' => $toUrl, 
'code' => '302' );
+                               } else {
+                                       $result = array(
+                                               'warn' => ( $toHost ? 
'external' : 'file' ),
+                                               'from' => $fromTitle, 'to' => 
$toUrl );
+                               }
+                       }
+               }
+               return $result;
+       }
+
+       /**
+        * Format URL to the zero or m main page for the specific language (or 
current if null)
+        * @param null|string $langCode
+        * @param bool $forceMobile if true, will always use m. even on zero. 
sites
+        * @return string
+        */
+       public static function getMainPage( $langCode = null, $forceMobile = 
false ) {
+               if ( $langCode === null ) {
+                       global $wgLang;
+                       $langCode = $wgLang->getCode();
+               }
+               $langUrlFormat = !$forceMobile && self::isZeroSubdomain() ? 
self::$formatZeroUrl : self::$formatMobileUrl;
+               return sprintf( $langUrlFormat, $langCode );
+       }
+
        /**
         * Find a message in a dictionary for the given language,
         * or use language fallbacks if message is not defined.
@@ -766,28 +741,53 @@
        }
 
        /**
+        * Create redirect URL to be inserted by DOM processing instead of all 
external links
+        * and other Zero-related redirects.
+        * @param string $url to redirect to in case the user accepts (or if 
its free for the user)
+        * @param Title $currentTitle Title of the page being processed. *MUST* 
be the same each call.
+        * @return String
+        */
+       public static function makeRedir( $url, Title $currentTitle ) {
+               static $redirPage = false;
+               if ( $redirPage === false ) {
+                       $redirPage = SpecialPage::getTitleFor( 
'ZeroRatedMobileAccess' );
+               }
+               static $query = false;
+               if ( $query === false ) {
+                       $query = 'from=' . $currentTitle->getPrefixedURL() . 
'&to=';
+               }
+               return $redirPage->getLinkURL( $query . wfUrlencode( $url ) );
+       }
+
+       /**
         * Adds parameters to URLs. Helper for onMinervaPreRender( BaseTemplate 
&$template )
         * @param BaseTemplate $template
         * @param string $templateValName The name of the template
-        * @param WebRequest $request The request object that will contain the 
request path.
+        * @param Title $title current page title
         * @param string $link The full link, usually parsed wikitext.
         */
-       private static function addWarning( BaseTemplate $template, 
$templateValName, WebRequest $request, $link ) {
-               if ( preg_match( '/href=[\'"](.*?)[\'"]/', $link, $match ) ) {
-                       $link = str_replace(
-                               $match[1],
-                               $request->appendQuery( 
'&renderZeroRatedRedirect=true&returnto=' ) . urlencode( $match[1] ),
-                               $link
-                       );
+       private static function addWarning( BaseTemplate $template, 
$templateValName, Title $title, $link ) {
+               if ( preg_match( '/href=([\'"])(.*?)\1/', $link, $match ) ) {
+                       $href = $match[2];
+                       $ch0 = substr( $href, 0, 1 );
+                       $ch1 = substr( $href, 1, 1 );
+                       // Local links start with either '#...', '?...' or 
'/...', but not '//...'
+                       if ( $ch0 !== '#' && $ch0 !== '?' && ( $ch0 !== '/' || 
$ch1 === '/' ) ) {
+                               $link = str_replace(
+                                       $href,
+                                       self::makeRedir( $href, $title ),
+                                       $link
+                               );
+                               $template->set( $templateValName, $link );
+                       }
                }
-               $template->set( $templateValName, $link );
        }
 
        /**
         * Output debug info into Zero log
         * @param string $dbg Debug message
         */
-       private static function logDebug( $dbg ) {
+       static function logDebug( $dbg ) {
                static $printedHeaders = false;
                global $wgRequest;
                $dbg .= "\t" . $wgRequest->getIP() . "\t" . 
$wgRequest->getFullRequestURL();
diff --git a/includes/ZeroSpecialPage.php b/includes/ZeroSpecialPage.php
index 4b6d0d0..c4db65b 100644
--- a/includes/ZeroSpecialPage.php
+++ b/includes/ZeroSpecialPage.php
@@ -2,8 +2,10 @@
 
 namespace Extensions\ZeroRatedMobileAccess;
 use Language;
+use Title;
 use UnlistedSpecialPage;
 use Html;
+use WebRequest;
 
 /**
  * Default startup page for ZeroRatedMobileAccess extension that shows the 
list of available languages.
@@ -19,9 +21,6 @@
                parent::__construct( 'ZeroRatedMobileAccess' );
        }
 
-       private static $formatMobileUrl = '//%s.m.wikipedia.org/wiki/Main_Page';
-       private static $formatZeroUrl = 
'//%s.zero.wikipedia.org/wiki/Main_Page';
-
        /**
         * Show the special page
         *
@@ -29,21 +28,26 @@
         */
        public function execute( $par ) {
                $out = $this->getOutput();
+
+               // todo: vary-headers should be removed from the mobile frontend
                $this->setHeaders();
-               $config = PageRenderingHooks::getConfig();
+               $out->addVaryHeader( 'X-CS' );
+               $out->addVaryHeader( 'X-Subdomain' );
+               // fixme: needs lower varnish caching time
 
-               if ( $config === null ) {
+               $redir = PageRenderingHooks::getRedirectInfo();
+               if ( array_key_exists( 'redirect', $redir ) ) {
+                       $out->redirect( $redir['redirect'], $redir['code'] );
                        return;
                }
-
-               if ( !$config['showZeroPage'] ) {
-                       $out->redirect( self::getMainPage(), '301' );
-                       return;
-               }
-
                $out->setPageTitle( null );
-               $output = $this->renderSpecialPage( $config );
-               $out->addHTML( $output );
+               if ( !array_key_exists( 'warn', $redir ) ) {
+                       $config = PageRenderingHooks::getConfig();
+                       if ( $config !== null ) {
+                               $output = $this->renderSpecialPage( $config );
+                               $out->addHTML( $output );
+                       }
+               }
        }
 
        /**
@@ -51,7 +55,6 @@
         * @return string
         */
        private function renderSpecialPage( $config ) {
-               global $wgRequest;
                $output = '';
                $languageNames = Language::fetchLanguageNames();
 
@@ -67,7 +70,7 @@
                                continue;
                        }
                        $languageLink = Html::element( 'a',
-                               array( 'href' => self::getMainPage( 
$languageCode ) ),
+                               array( 'href' => 
PageRenderingHooks::getMainPage( $languageCode ) ),
                                wfMessage( 
'zero-rated-mobile-access-home-page-selection',
                                        ucfirst( $languageNames[$languageCode] 
) )->inLanguage( $languageCode )
                        );
@@ -88,42 +91,16 @@
                );
 
                $freeLangs = $config['whitelistedLangs'];
+               $title = $this->getTitle();
                foreach ( $languageNames as $languageCode => $languageName ) {
-                       $isFree = ( 0 === count( $freeLangs ) || in_array( 
$languageCode, $freeLangs ) );
-                       if ( !$isFree || !PageRenderingHooks::disableImages() ) 
{
-                               // send user to the m subdomain
-                               $languageUrl = sprintf( self::$formatMobileUrl, 
$languageCode );
-                               if ( !$isFree ) {
-                                       // offer upgraded ux
-                                       $languageUrl = $wgRequest->appendQuery(
-                                               
'renderZeroRatedBanner=true&renderwarning=yes&returnto='
-                                               . urlencode( $languageUrl ) );
-                               }
-                       } else {
-                               // send low bandwidth user to whitelisted zero 
subdomain
-                               $languageUrl = sprintf( self::$formatZeroUrl, 
$languageCode );
+                       $isFree = count( $freeLangs ) === 0 || in_array( 
$languageCode, $freeLangs );
+                       $url = PageRenderingHooks::getMainPage( $languageCode, 
!$isFree );
+                       if ( !$isFree ) {
+                               $url = PageRenderingHooks::makeRedir( $url, 
$title );
                        }
-
-                       $output .= Html::element( 'option',
-                               array( 'value' => $languageUrl ),
-                               $languageName
-                       );
+                       $output .= Html::element( 'option', array( 'value' => 
$url ), $languageName );
                }
                $output .= Html::closeElement( 'select' );
                return $output;
-       }
-
-       /**
-        * Format URL to the zero or m main page for the specific language (or 
current if null)
-        * @param null|string $langCode
-        * @return string
-        */
-       private static function getMainPage( $langCode = null ) {
-               if ( $langCode === null ) {
-                       global $wgLang;
-                       $langCode = $wgLang->getCode();
-               }
-               $langUrlFormat = PageRenderingHooks::isZeroSubdomain() ? 
self::$formatZeroUrl : self::$formatMobileUrl;
-               return sprintf( $langUrlFormat, $langCode );
        }
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/85641
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I012c43d2f5b9a2cfb4132f682c3fd76e48650811
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ZeroRatedMobileAccess
Gerrit-Branch: master
Gerrit-Owner: Yurik <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to