r69986 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r69985‎ | r69986 | r69987 >
Date:03:57, 27 July 2010
Author:tstarling
Status:ok
Tags:
Comment:
* Merged r69932 from REL1_16: API cache header fix. The base was quite different. Several parameters which introduce user dependencies were only introduced in 1.16, so the getCacheMode() is simpler in these cases. setCacheControl() and modifications to setCacheMaxAge() were merged from r62486.
* MFT r69932: XVO header parsing fix
Modified paths:
  • /branches/REL1_15/phase3/RELEASE-NOTES (modified) (history)
  • /branches/REL1_15/phase3/includes/OutputPage.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiExpandTemplates.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiMain.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiOpenSearch.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiParse.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQuery.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllCategories.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllLinks.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllUsers.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllimages.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllmessages.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryAllpages.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryBacklinks.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryBase.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryCategories.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryCategoryInfo.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryCategoryMembers.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryDuplicateFiles.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryExtLinksUsage.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryExternalLinks.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryImageInfo.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryImages.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryInfo.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryLangLinks.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryLinks.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryLogEvents.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryProtectedTitles.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryRandom.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryRecentChanges.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryRevisions.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQuerySearch.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQuerySiteinfo.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryUserContributions.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryUsers.php (modified) (history)
  • /branches/REL1_15/phase3/includes/api/ApiQueryWatchlist.php (modified) (history)

Diff [purge]

Index: branches/REL1_15/phase3/RELEASE-NOTES
@@ -3,10 +3,8 @@
44 Security reminder: MediaWiki does not require PHP's register_globals
55 setting since version 1.2.0. If you have it on, turn it *off* if you can.
66
7 -== MediaWiki 1.15.4 ==
 7+== MediaWiki 1.15.5 ==
88
9 -2010-05-28
10 -
119 This is a security and maintenance release.
1210
1311 MediaWiki is now using a "continuous integration" development model with
@@ -20,6 +18,14 @@
2119 Those wishing to use the latest code instead of a branch release can obtain
2220 it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
2321
 22+== Changes since 1.15.4 ==
 23+
 24+* (bug xxxxx) Fixed Cache-Control headers sent from API modules, to protect
 25+ user privacy in the case where an attacker can access the wiki through the
 26+ same HTTP proxy as a logged-in user.
 27+* Fixed a minor cookie header parsing issue causing incorrect Cache-Control
 28+ headers to be sent.
 29+
2430 == Changes since 1.15.3 ==
2531
2632 * (bug 23534) Fixed SQL query error in API list=allusers.
Index: branches/REL1_15/phase3/includes/OutputPage.php
@@ -733,7 +733,7 @@
734734 $cvCookies = $this->getCacheVaryCookies();
735735 foreach ( $cvCookies as $cookieName ) {
736736 # Check for a simple string match, like the way squid does it
737 - if ( strpos( $cookieHeader, $cookieName ) ) {
 737+ if ( strpos( $cookieHeader, $cookieName ) !== false ) {
738738 wfDebug( __METHOD__.": found $cookieName\n" );
739739 return true;
740740 }
Property changes on: branches/REL1_15/phase3/includes/OutputPage.php
___________________________________________________________________
Added: svn:mergeinfo
741741 Merged /trunk/phase3/includes/specials/OutputPage.php:r48993
742742 Merged /trunk/phase3/includes/OutputPage.php:r48836,48886,48892,48989,48992,49002,49051,49068,49086,49191-49192,49212,49682,49685,49730,49775,49954,49956,49999,50041,50054,50070,50132,50134,50169,50215,50218,50328,50470,50580,51587,54828,69771
Index: branches/REL1_15/phase3/includes/api/ApiQueryRandom.php
@@ -121,6 +121,10 @@
122122 return $vals;
123123 }
124124
 125+ public function getCacheMode( $params ) {
 126+ return 'public';
 127+ }
 128+
125129 public function getAllowedParams() {
126130 return array (
127131 'namespace' => array(
@@ -161,4 +165,4 @@
162166 public function getVersion() {
163167 return __CLASS__ . ': $Id: ApiQueryRandom.php overlordq$';
164168 }
165 -}
\ No newline at end of file
 169+}
Index: branches/REL1_15/phase3/includes/api/ApiQuerySiteinfo.php
@@ -373,6 +373,9 @@
374374 return $this->getResult()->addValue( 'query', $property, $data );
375375 }
376376
 377+ public function getCacheMode( $params ) {
 378+ return 'public';
 379+ }
377380
378381 public function getAllowedParams() {
379382 return array(
@@ -441,4 +444,4 @@
442445 public function getVersion() {
443446 return __CLASS__ . ': $Id$';
444447 }
445 -}
\ No newline at end of file
 448+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryLangLinks.php
@@ -92,6 +92,10 @@
9393 $db->freeResult($res);
9494 }
9595
 96+ public function getCacheMode( $params ) {
 97+ return 'public';
 98+ }
 99+
96100 public function getAllowedParams() {
97101 return array(
98102 'limit' => array(
@@ -126,4 +130,4 @@
127131 public function getVersion() {
128132 return __CLASS__ . ': $Id$';
129133 }
130 -}
\ No newline at end of file
 134+}
Index: branches/REL1_15/phase3/includes/api/ApiParse.php
@@ -38,6 +38,9 @@
3939 }
4040
4141 public function execute() {
 42+ // The data is hot but user-dependent, like page views, so we set vary cookies
 43+ $this->getMain()->setCacheMode( 'anon-public-user-private' );
 44+
4245 // Get parameters
4346 $params = $this->extractRequestParams();
4447 $text = $params['text'];
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllpages.php
@@ -43,6 +43,10 @@
4444 $this->run();
4545 }
4646
 47+ public function getCacheMode( $params ) {
 48+ return 'public';
 49+ }
 50+
4751 public function executeGenerator($resultPageSet) {
4852 if ($resultPageSet->isResolvingRedirects())
4953 $this->dieUsage('Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params');
@@ -270,4 +274,4 @@
271275 public function getVersion() {
272276 return __CLASS__ . ': $Id$';
273277 }
274 -}
\ No newline at end of file
 278+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryImageInfo.php
@@ -239,6 +239,10 @@
240240 return $retval;
241241 }
242242
 243+ public function getCacheMode( $params ) {
 244+ return 'public';
 245+ }
 246+
243247 private function getContinueStr($img)
244248 {
245249 return $img->getOriginalTitle()->getText() .
Index: branches/REL1_15/phase3/includes/api/ApiMain.php
@@ -121,7 +121,9 @@
122122
123123
124124 private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames;
125 - private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode, $mSquidMaxage;
 125+ private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode;
 126+ private $mCacheMode = 'private';
 127+ private $mCacheControl = array();
126128
127129 /**
128130 * Constructs an instance of ApiMain that utilizes the module and format specified by $request.
@@ -164,7 +166,6 @@
165167
166168 $this->mRequest = & $request;
167169
168 - $this->mSquidMaxage = -1; // flag for executeActionWithErrorHandling()
169170 $this->mCommit = false;
170171 }
171172
@@ -199,10 +200,92 @@
200201 * Set how long the response should be cached.
201202 */
202203 public function setCacheMaxAge($maxage) {
203 - $this->mSquidMaxage = $maxage;
 204+ $this->setCacheControl( array(
 205+ 'max-age' => $maxage,
 206+ 's-maxage' => $maxage
 207+ ) );
204208 }
205209
206210 /**
 211+ * Set the type of caching headers which will be sent.
 212+ *
 213+ * @param $mode One of:
 214+ * - 'public': Cache this object in public caches, if the maxage or smaxage
 215+ * parameter is set, or if setCacheMaxAge() was called. If a maximum age is
 216+ * not provided by any of these means, the object will be private.
 217+ * - 'private': Cache this object only in private client-side caches.
 218+ * - 'anon-public-user-private': Make this object cacheable for logged-out
 219+ * users, but private for logged-in users. IMPORTANT: If this is set, it must be
 220+ * set consistently for a given URL, it cannot be set differently depending on
 221+ * things like the contents of the database, or whether the user is logged in.
 222+ *
 223+ * If the wiki does not allow anonymous users to read it, the mode set here
 224+ * will be ignored, and private caching headers will always be sent. In other words,
 225+ * the "public" mode is equivalent to saying that the data sent is as public as a page
 226+ * view.
 227+ *
 228+ * For user-dependent data, the private mode should generally be used. The
 229+ * anon-public-user-private mode should only be used where there is a particularly
 230+ * good performance reason for caching the anonymous response, but where the
 231+ * response to logged-in users may differ, or may contain private data.
 232+ *
 233+ * If this function is never called, then the default will be the private mode.
 234+ */
 235+ public function setCacheMode( $mode ) {
 236+ if ( !in_array( $mode, array( 'private', 'public', 'anon-public-user-private' ) ) ) {
 237+ wfDebug( __METHOD__.": unrecognised cache mode \"$mode\"\n" );
 238+ // Ignore for forwards-compatibility
 239+ return;
 240+ }
 241+
 242+ if ( !in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) {
 243+ // Private wiki, only private headers
 244+ if ( $mode !== 'private' ) {
 245+ wfDebug( __METHOD__.": ignoring request for $mode cache mode, private wiki\n" );
 246+ return;
 247+ }
 248+ }
 249+
 250+ wfDebug( __METHOD__.": setting cache mode $mode\n" );
 251+ $this->mCacheMode = $mode;
 252+ }
 253+
 254+ /**
 255+ * @deprecated Private caching is now the default, so there is usually no
 256+ * need to call this function. If there is a need, you can use
 257+ * $this->setCacheMode('private')
 258+ */
 259+ public function setCachePrivate() {
 260+ $this->setCacheMode( 'private' );
 261+ }
 262+
 263+ /**
 264+ * Set directives (key/value pairs) for the Cache-Control header.
 265+ * Boolean values will be formatted as such, by including or omitting
 266+ * without an equals sign.
 267+ *
 268+ * Cache control values set here will only be used if the cache mode is not
 269+ * private, see setCacheMode().
 270+ */
 271+ public function setCacheControl( $directives ) {
 272+ $this->mCacheControl = $directives + $this->mCacheControl;
 273+ }
 274+
 275+ /**
 276+ * Make sure Vary: Cookie and friends are set. Use this when the output of a request
 277+ * may be cached for anons but may not be cached for logged-in users.
 278+ *
 279+ * WARNING: This function must be called CONSISTENTLY for a given URL. This means that a
 280+ * given URL must either always or never call this function; if it sometimes does and
 281+ * sometimes doesn't, stuff will break.
 282+ *
 283+ * @deprecated Use setCacheMode( 'anon-public-user-private' )
 284+ */
 285+ public function setVaryCookie() {
 286+ $this->setCacheMode( 'anon-public-user-private' );
 287+ }
 288+
 289+ /**
207290 * Create an instance of an output formatter by its name
208291 */
209292 public function createPrinterByName($format) {
@@ -251,7 +334,7 @@
252335 $errCode = $this->substituteResultWithError($e);
253336
254337 // Error results should not be cached
255 - $this->setCacheMaxAge(0);
 338+ $this->setCacheMode( 'private' );
256339
257340 $headerStr = 'MediaWiki-API-Error: ' . $errCode;
258341 if ($e->getCode() === 0)
@@ -267,28 +350,81 @@
268351 $this->printResult(true);
269352 }
270353
271 - if($this->mSquidMaxage == -1)
272 - {
273 - # Nobody called setCacheMaxAge(), use the (s)maxage parameters
274 - $smaxage = $this->getParameter('smaxage');
275 - $maxage = $this->getParameter('maxage');
276 - }
277 - else
278 - $smaxage = $maxage = $this->mSquidMaxage;
 354+ // Send cache headers after any code which might generate an error, to
 355+ // avoid sending public cache headers for errors.
 356+ $this->sendCacheHeaders();
279357
280 - // Set the cache expiration at the last moment, as any errors may change the expiration.
281 - // if $this->mSquidMaxage == 0, the expiry time is set to the first second of unix epoch
282 - $exp = min($smaxage, $maxage);
283 - $expires = ($exp == 0 ? 1 : time() + $exp);
284 - header('Expires: ' . wfTimestamp(TS_RFC2822, $expires));
285 - header('Cache-Control: s-maxage=' . $smaxage . ', must-revalidate, max-age=' . $maxage);
286 -
287358 if($this->mPrinter->getIsHtml())
288359 echo wfReportTime();
289360
290361 ob_end_flush();
291362 }
292363
 364+ protected function sendCacheHeaders() {
 365+ if ( $this->mCacheMode == 'private' ) {
 366+ header( 'Cache-Control: private' );
 367+ return;
 368+ }
 369+
 370+ if ( $this->mCacheMode == 'anon-public-user-private' ) {
 371+ global $wgOut;
 372+ header( 'Vary: Accept-Encoding, Cookie' );
 373+ header( $wgOut->getXVO() );
 374+ if ( session_id() != '' || $wgOut->haveCacheVaryCookies() ) {
 375+ // Logged in, mark this request private
 376+ header( 'Cache-Control: private' );
 377+ return;
 378+ }
 379+ // Logged out, send normal public headers below
 380+ } else /* if public */ {
 381+ // Give a debugging message if the user object is unstubbed on a public request
 382+ global $wgUser;
 383+ if ( !( $wgUser instanceof StubUser ) ) {
 384+ wfDebug( __METHOD__." \$wgUser is unstubbed on a public request!\n" );
 385+ }
 386+ }
 387+
 388+ // If nobody called setCacheMaxAge(), use the (s)maxage parameters
 389+ if ( !isset( $this->mCacheControl['s-maxage'] ) ) {
 390+ $this->mCacheControl['s-maxage'] = $this->getParameter( 'smaxage' );
 391+ }
 392+ if ( !isset( $this->mCacheControl['max-age'] ) ) {
 393+ $this->mCacheControl['max-age'] = $this->getParameter( 'maxage' );
 394+ }
 395+
 396+ if ( !$this->mCacheControl['s-maxage'] && !$this->mCacheControl['max-age'] ) {
 397+ // Public cache not requested
 398+ // Sending a Vary header in this case is harmless, and protects us
 399+ // against conditional calls of setCacheMaxAge().
 400+ header( 'Cache-Control: private' );
 401+ return;
 402+ }
 403+
 404+ $this->mCacheControl['public'] = true;
 405+
 406+ // Send an Expires header
 407+ $maxAge = min( $this->mCacheControl['s-maxage'], $this->mCacheControl['max-age'] );
 408+ $expiryUnixTime = ( $maxAge == 0 ? 1 : time() + $maxAge );
 409+ header( 'Expires: ' . wfTimestamp( TS_RFC2822, $expiryUnixTime ) );
 410+
 411+ // Construct the Cache-Control header
 412+ $ccHeader = '';
 413+ $separator = '';
 414+ foreach ( $this->mCacheControl as $name => $value ) {
 415+ if ( is_bool( $value ) ) {
 416+ if ( $value ) {
 417+ $ccHeader .= $separator . $name;
 418+ $separator = ', ';
 419+ }
 420+ } else {
 421+ $ccHeader .= $separator . "$name=$value";
 422+ $separator = ', ';
 423+ }
 424+ }
 425+
 426+ header( "Cache-Control: $ccHeader" );
 427+ }
 428+
293429 /**
294430 * Replace the result data with the information about an exception.
295431 * Returns the error code
Index: branches/REL1_15/phase3/includes/api/ApiOpenSearch.php
@@ -53,6 +53,7 @@
5454
5555 // Open search results may be stored for a very long time
5656 $this->getMain()->setCacheMaxAge(1200);
 57+ $this->getMain()->setCacheMode( 'public' );
5758
5859 $srchres = PrefixSearch::titleSearch( $search, $limit, $namespaces );
5960
Index: branches/REL1_15/phase3/includes/api/ApiQueryWatchlist.php
@@ -345,4 +345,4 @@
346346 public function getVersion() {
347347 return __CLASS__ . ': $Id$';
348348 }
349 -}
\ No newline at end of file
 349+}
Index: branches/REL1_15/phase3/includes/api/ApiExpandTemplates.php
@@ -42,6 +42,9 @@
4343 }
4444
4545 public function execute() {
 46+ // Cache may vary on $wgUser because ParserOptions gets data from it
 47+ $this->getMain()->setCacheMode( 'anon-public-user-private' );
 48+
4649 // Get parameters
4750 $params = $this->extractRequestParams();
4851
Index: branches/REL1_15/phase3/includes/api/ApiQueryBase.php
@@ -47,6 +47,17 @@
4848 }
4949
5050 /**
 51+ * Get the cache mode for the data generated by this module. Override this
 52+ * in the module subclass.
 53+ *
 54+ * Public caching will only be allowed if *all* the modules that supply
 55+ * data for a given request return a cache mode of public.
 56+ */
 57+ public function getCacheMode( $params ) {
 58+ return 'private';
 59+ }
 60+
 61+ /**
5162 * Blank the internal arrays with query parameters
5263 */
5364 protected function resetQueryParams() {
Index: branches/REL1_15/phase3/includes/api/ApiQueryRevisions.php
@@ -411,6 +411,17 @@
412412 return $vals;
413413 }
414414
 415+ public function getCacheMode( $params ) {
 416+ if ( isset( $params['token'] ) ) {
 417+ return 'private';
 418+ }
 419+ if ( !is_null( $params['prop'] ) && in_array( 'parsedcomment', $params['prop'] ) ) {
 420+ // formatComment() calls wfMsg() among other things
 421+ return 'anon-public-user-private';
 422+ }
 423+ return 'public';
 424+ }
 425+
415426 public function getAllowedParams() {
416427 return array (
417428 'prop' => array (
Index: branches/REL1_15/phase3/includes/api/ApiQueryExternalLinks.php
@@ -81,6 +81,10 @@
8282 $db->freeResult($res);
8383 }
8484
 85+ public function getCacheMode( $params ) {
 86+ return 'public';
 87+ }
 88+
8589 public function getAllowedParams() {
8690 return array(
8791 'limit' => array(
@@ -115,4 +119,4 @@
116120 public function getVersion() {
117121 return __CLASS__ . ': $Id$';
118122 }
119 -}
\ No newline at end of file
 123+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryCategoryInfo.php
@@ -97,6 +97,10 @@
9898 $db->freeResult($res);
9999 }
100100
 101+ public function getCacheMode( $params ) {
 102+ return 'public';
 103+ }
 104+
101105 public function getAllowedParams() {
102106 return array (
103107 'continue' => null,
@@ -120,4 +124,4 @@
121125 public function getVersion() {
122126 return __CLASS__ . ': $Id$';
123127 }
124 -}
\ No newline at end of file
 128+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryUsers.php
@@ -138,6 +138,10 @@
139139 return $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'user');
140140 }
141141
 142+ public function getCacheMode( $params ) {
 143+ return 'public';
 144+ }
 145+
142146 public function getAllowedParams() {
143147 return array (
144148 'prop' => array (
Index: branches/REL1_15/phase3/includes/api/ApiQueryUserContributions.php
@@ -287,6 +287,12 @@
288288 wfTimestamp(TS_ISO_8601, $row->rev_timestamp);
289289 }
290290
 291+ public function getCacheMode( $params ) {
 292+ // This module provides access to patrol flags if
 293+ // the requester is logged in
 294+ return 'anon-public-user-private';
 295+ }
 296+
291297 public function getAllowedParams() {
292298 return array (
293299 'limit' => array (
@@ -372,4 +378,4 @@
373379 public function getVersion() {
374380 return __CLASS__ . ': $Id$';
375381 }
376 -}
\ No newline at end of file
 382+}
Index: branches/REL1_15/phase3/includes/api/ApiQuerySearch.php
@@ -122,6 +122,10 @@
123123 }
124124 }
125125
 126+ public function getCacheMode( $params ) {
 127+ return 'public';
 128+ }
 129+
126130 public function getAllowedParams() {
127131 return array (
128132 'search' => null,
Index: branches/REL1_15/phase3/includes/api/ApiQueryRecentChanges.php
@@ -353,6 +353,20 @@
354354 }
355355 }
356356
 357+ public function getCacheMode( $params ) {
 358+ if ( isset( $params['show'] ) ) {
 359+ foreach ( $params['show'] as $show ) {
 360+ if ( $show === 'patrolled' || $show === '!patrolled' ) {
 361+ return 'private';
 362+ }
 363+ }
 364+ }
 365+ if ( isset( $params['token'] ) ) {
 366+ return 'private';
 367+ }
 368+ return 'public';
 369+ }
 370+
357371 public function getAllowedParams() {
358372 return array (
359373 'start' => array (
@@ -455,4 +469,4 @@
456470 public function getVersion() {
457471 return __CLASS__ . ': $Id$';
458472 }
459 -}
\ No newline at end of file
 473+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllCategories.php
@@ -44,6 +44,10 @@
4545 $this->run();
4646 }
4747
 48+ public function getCacheMode( $params ) {
 49+ return 'public';
 50+ }
 51+
4852 public function executeGenerator($resultPageSet) {
4953 $this->run($resultPageSet);
5054 }
@@ -177,4 +181,4 @@
178182 public function getVersion() {
179183 return __CLASS__ . ': $Id$';
180184 }
181 -}
\ No newline at end of file
 185+}
Index: branches/REL1_15/phase3/includes/api/ApiQuery.php
@@ -209,11 +209,17 @@
210210 $this->InstantiateModules($modules, 'list', $this->mQueryListModules);
211211 $this->InstantiateModules($modules, 'meta', $this->mQueryMetaModules);
212212
 213+ $cacheMode = 'public';
 214+
213215 //
214216 // If given, execute generator to substitute user supplied data with generated data.
215217 //
216 - if (isset ($this->params['generator'])) {
217 - $this->executeGeneratorModule($this->params['generator'], $modules);
 218+ if ( isset ( $this->params['generator'] ) ) {
 219+ $generator = $this->newGenerator( $this->params['generator'] );
 220+ $params = $generator->extractRequestParams();
 221+ $cacheMode = $this->mergeCacheMode( $cacheMode,
 222+ $generator->getCacheMode( $params ) );
 223+ $this->executeGeneratorModule( $generator, $modules );
218224 } else {
219225 // Append custom fields and populate page/revision information
220226 $this->addCustomFldsToPageSet($modules, $this->mPageSet);
@@ -229,14 +235,38 @@
230236 // Execute all requested modules.
231237 //
232238 foreach ($modules as $module) {
 239+ $params = $module->extractRequestParams();
 240+ $cacheMode = $this->mergeCacheMode(
 241+ $cacheMode, $module->getCacheMode( $params ) );
233242 $module->profileIn();
234243 $module->execute();
235244 wfRunHooks('APIQueryAfterExecute', array(&$module));
236245 $module->profileOut();
237246 }
 247+
 248+ // Set the cache mode
 249+ $this->getMain()->setCacheMode( $cacheMode );
238250 }
239251
240252 /**
 253+ * Update a cache mode string, applying the cache mode of a new module to it.
 254+ * The cache mode may increase in the level of privacy, but public modules
 255+ * added to private data do not decrease the level of privacy.
 256+ */
 257+ protected function mergeCacheMode( $cacheMode, $modCacheMode ) {
 258+ if ( $modCacheMode === 'anon-public-user-private' ) {
 259+ if ( $cacheMode !== 'private' ) {
 260+ $cacheMode = 'anon-public-user-private';
 261+ }
 262+ } elseif ( $modCacheMode === 'public' ) {
 263+ // do nothing, if it's public already it will stay public
 264+ } else { // private
 265+ $cacheMode = 'private';
 266+ }
 267+ return $cacheMode;
 268+ }
 269+
 270+ /**
241271 * Query modules may optimize data requests through the $this->getPageSet() object
242272 * by adding extra fields from the page table.
243273 * This function will gather all the extra request fields from the modules.
@@ -409,13 +439,9 @@
410440 }
411441
412442 /**
413 - * For generator mode, execute generator, and use its output as new
414 - * ApiPageSet
415 - * @param $generatorName string Module name
416 - * @param $modules array of module objects
 443+ * Create a generator object of the given type and return it
417444 */
418 - protected function executeGeneratorModule($generatorName, $modules) {
419 -
 445+ public function newGenerator( $generatorName ) {
420446 // Find class that implements requested generator
421447 if (isset ($this->mQueryListModules[$generatorName])) {
422448 $className = $this->mQueryListModules[$generatorName];
@@ -432,9 +458,20 @@
433459 $generator = new $className ($this, $generatorName);
434460 if (!$generator instanceof ApiQueryGeneratorBase)
435461 $this->dieUsage("Module $generatorName cannot be used as a generator", "badgenerator");
436 -
437462 $generator->setGeneratorMode();
 463+ return $generator;
 464+ }
438465
 466+ /**
 467+ * For generator mode, execute generator, and use its output as new
 468+ * ApiPageSet
 469+ * @param $generatorName string Module name
 470+ * @param $modules array of module objects
 471+ */
 472+ protected function executeGeneratorModule( $generator, $modules ) {
 473+ // Generator results
 474+ $resultPageSet = new ApiPageSet( $this, $this->redirects, $this->convertTitles );
 475+
439476 // Add any additional fields modules may need
440477 $generator->requestExtraData($this->mPageSet);
441478 $this->addCustomFldsToPageSet($modules, $resultPageSet);
@@ -584,4 +621,4 @@
585622 $vers[] = $psModule->getVersion();
586623 return $vers;
587624 }
588 -}
\ No newline at end of file
 625+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryLinks.php
@@ -64,6 +64,10 @@
6565 $this->run();
6666 }
6767
 68+ public function getCacheMode( $params ) {
 69+ return 'public';
 70+ }
 71+
6872 public function executeGenerator($resultPageSet) {
6973 $this->run($resultPageSet);
7074 }
@@ -206,4 +210,4 @@
207211 public function getVersion() {
208212 return __CLASS__ . ': $Id$';
209213 }
210 -}
\ No newline at end of file
 214+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryExtLinksUsage.php
@@ -41,6 +41,10 @@
4242 $this->run();
4343 }
4444
 45+ public function getCacheMode( $params ) {
 46+ return 'public';
 47+ }
 48+
4549 public function executeGenerator($resultPageSet) {
4650 $this->run($resultPageSet);
4751 }
@@ -211,4 +215,4 @@
212216 public function getVersion() {
213217 return __CLASS__ . ': $Id$';
214218 }
215 -}
\ No newline at end of file
 219+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryBacklinks.php
@@ -92,6 +92,10 @@
9393 $this->run();
9494 }
9595
 96+ public function getCacheMode( $params ) {
 97+ return 'public';
 98+ }
 99+
96100 public function executeGenerator($resultPageSet) {
97101 $this->run($resultPageSet);
98102 }
Index: branches/REL1_15/phase3/includes/api/ApiQueryCategories.php
@@ -43,6 +43,10 @@
4444 $this->run();
4545 }
4646
 47+ public function getCacheMode( $params ) {
 48+ return 'public';
 49+ }
 50+
4751 public function executeGenerator($resultPageSet) {
4852 $this->run($resultPageSet);
4953 }
Index: branches/REL1_15/phase3/includes/api/ApiQueryCategoryMembers.php
@@ -43,6 +43,10 @@
4444 $this->run();
4545 }
4646
 47+ public function getCacheMode( $params ) {
 48+ return 'public';
 49+ }
 50+
4751 public function executeGenerator($resultPageSet) {
4852 $this->run($resultPageSet);
4953 }
@@ -264,4 +268,4 @@
265269 public function getVersion() {
266270 return __CLASS__ . ': $Id$';
267271 }
268 -}
\ No newline at end of file
 272+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllUsers.php
@@ -181,6 +181,10 @@
182182 $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'u');
183183 }
184184
 185+ public function getCacheMode( $params ) {
 186+ return 'public';
 187+ }
 188+
185189 public function getAllowedParams() {
186190 return array (
187191 'from' => null,
Property changes on: branches/REL1_15/phase3/includes/api/ApiQueryAllUsers.php
___________________________________________________________________
Modified: svn:mergeinfo
188192 Merged /branches/REL1_16/phase3/includes/api/ApiQueryAllUsers.php:r69932
189193 Merged /trunk/phase3/includes/api/ApiQueryAllUsers.php:r69339,69347,69350,69369,69379,69776,69931
Index: branches/REL1_15/phase3/includes/api/ApiQueryInfo.php
@@ -499,6 +499,26 @@
500500 }
501501 }
502502
 503+ public function getCacheMode( $params ) {
 504+ $publicProps = array(
 505+ 'protection',
 506+ 'talkid',
 507+ 'subjectid',
 508+ 'url',
 509+ );
 510+ if ( !is_null( $params['prop'] ) ) {
 511+ foreach ( $params['prop'] as $prop ) {
 512+ if ( !in_array( $prop, $publicProps ) ) {
 513+ return 'private';
 514+ }
 515+ }
 516+ }
 517+ if ( !is_null( $params['token'] ) ) {
 518+ return 'private';
 519+ }
 520+ return 'public';
 521+ }
 522+
503523 public function getAllowedParams() {
504524 return array (
505525 'prop' => array (
@@ -509,7 +529,9 @@
510530 'talkid',
511531 'subjectid',
512532 'url',
513 - 'readable',
 533+ 'readable', # private
 534+ // If you add more properties here, please consider whether they
 535+ // need to be added to getCacheMode()
514536 )),
515537 'token' => array (
516538 ApiBase :: PARAM_DFLT => NULL,
Index: branches/REL1_15/phase3/includes/api/ApiQueryDuplicateFiles.php
@@ -43,6 +43,10 @@
4444 $this->run();
4545 }
4646
 47+ public function getCacheMode( $params ) {
 48+ return 'public';
 49+ }
 50+
4751 public function executeGenerator($resultPageSet) {
4852 $this->run($resultPageSet);
4953 }
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllimages.php
@@ -44,6 +44,10 @@
4545 $this->run();
4646 }
4747
 48+ public function getCacheMode( $params ) {
 49+ return 'public';
 50+ }
 51+
4852 public function executeGenerator($resultPageSet) {
4953 if ($resultPageSet->isResolvingRedirects())
5054 $this->dieUsage('Use "gaifilterredir=nonredirects" option instead of "redirects" when using allimages as a generator', 'params');
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllmessages.php
@@ -104,6 +104,16 @@
105105 $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'message');
106106 }
107107
 108+ public function getCacheMode( $params ) {
 109+ if ( is_null( $params['lang'] ) ) {
 110+ // Language not specified, will be fetched from preferences
 111+ return 'anon-public-user-private';
 112+ } else {
 113+ // OK to cache
 114+ return 'public';
 115+ }
 116+ }
 117+
108118 public function getAllowedParams() {
109119 return array (
110120 'messages' => array (
@@ -138,4 +148,4 @@
139149 public function getVersion() {
140150 return __CLASS__ . ': $Id$';
141151 }
142 -}
\ No newline at end of file
 152+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryImages.php
@@ -121,6 +121,10 @@
122122 $db->freeResult($res);
123123 }
124124
 125+ public function getCacheMode( $params ) {
 126+ return 'public';
 127+ }
 128+
125129 public function getAllowedParams() {
126130 return array(
127131 'limit' => array(
@@ -157,4 +161,4 @@
158162 public function getVersion() {
159163 return __CLASS__ . ': $Id$';
160164 }
161 -}
\ No newline at end of file
 165+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryLogEvents.php
@@ -251,6 +251,10 @@
252252 }
253253
254254
 255+ public function getCacheMode( $params ) {
 256+ return 'public';
 257+ }
 258+
255259 public function getAllowedParams() {
256260 global $wgLogTypes;
257261 return array (
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllLinks.php
@@ -43,6 +43,10 @@
4444 $this->run();
4545 }
4646
 47+ public function getCacheMode( $params ) {
 48+ return 'public';
 49+ }
 50+
4751 public function executeGenerator($resultPageSet) {
4852 $this->run($resultPageSet);
4953 }
@@ -198,4 +202,4 @@
199203 public function getVersion() {
200204 return __CLASS__ . ': $Id$';
201205 }
202 -}
\ No newline at end of file
 206+}
Index: branches/REL1_15/phase3/includes/api/ApiQueryProtectedTitles.php
@@ -118,6 +118,10 @@
119119 $resultPageSet->populateFromTitles($titles);
120120 }
121121
 122+ public function getCacheMode( $params ) {
 123+ return 'public';
 124+ }
 125+
122126 public function getAllowedParams() {
123127 global $wgRestrictionLevels;
124128 return array (
@@ -188,4 +192,4 @@
189193 public function getVersion() {
190194 return __CLASS__ . ': $Id$';
191195 }
192 -}
\ No newline at end of file
 196+}
Property changes on: branches/REL1_15/phase3/includes/api
___________________________________________________________________
Modified: svn:mergeinfo
193197 Merged /branches/REL1_16/phase3/includes/api:r69932
194198 Merged /trunk/phase3/includes/api:r69339,69347,69350,69369,69379,69776,69931

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r62486Search suggestion API requests make up a substantial portion of our total apa...tstarling23:52, 14 February 2010
r69932* MFT r69776, and followups r69784, r69928, r69931, and superseded base revis...tstarling08:03, 26 July 2010

Status & tagging log