Index: branches/REL1_15/extensions/GlobalBlocking/ApiQueryGlobalBlocks.php |
— | — | @@ -36,7 +36,6 @@ |
37 | 37 | } |
38 | 38 | |
39 | 39 | public function execute() { |
40 | | - global $wgUser; |
41 | 40 | $params = $this->extractRequestParams(); |
42 | 41 | |
43 | 42 | $prop = array_flip($params['prop']); |
Index: branches/REL1_15/phase3/includes/api/ApiQueryRecentChanges.php |
— | — | @@ -116,8 +116,12 @@ |
117 | 117 | |
118 | 118 | // Check permissions |
119 | 119 | global $wgUser; |
120 | | - if((isset($show['patrolled']) || isset($show['!patrolled'])) && !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol()) |
121 | | - $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied'); |
| 120 | + if(isset($show['patrolled']) || isset($show['!patrolled'])) { |
| 121 | + $this->getMain()->setVaryCookie(); |
| 122 | + if(!$wgUser->useRCPatrol() && !$wgUser->useNPPatrol()) { |
| 123 | + $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied'); |
| 124 | + } |
| 125 | + } |
122 | 126 | |
123 | 127 | /* Add additional conditions to query depending upon parameters. */ |
124 | 128 | $this->addWhereIf('rc_minor = 0', isset ($show['!minor'])); |
— | — | @@ -321,6 +325,9 @@ |
322 | 326 | |
323 | 327 | if(!is_null($this->token)) |
324 | 328 | { |
| 329 | + // Don't cache tokens |
| 330 | + $this->getMain()->setCachePrivate(); |
| 331 | + |
325 | 332 | $tokenFunctions = $this->getTokenFunctions(); |
326 | 333 | foreach($this->token as $t) |
327 | 334 | { |
Index: branches/REL1_15/phase3/includes/api/ApiWatch.php |
— | — | @@ -41,6 +41,7 @@ |
42 | 42 | |
43 | 43 | public function execute() { |
44 | 44 | global $wgUser; |
| 45 | + $this->getMain()->setCachePrivate(); |
45 | 46 | if(!$wgUser->isLoggedIn()) |
46 | 47 | $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin'); |
47 | 48 | $params = $this->extractRequestParams(); |
Index: branches/REL1_15/phase3/includes/api/ApiLogout.php |
— | — | @@ -42,6 +42,7 @@ |
43 | 43 | |
44 | 44 | public function execute() { |
45 | 45 | global $wgUser; |
| 46 | + $this->getMain()->setCachePrivate(); |
46 | 47 | $oldName = $wgUser->getName(); |
47 | 48 | $wgUser->logout(); |
48 | 49 | |
Index: branches/REL1_15/phase3/includes/api/ApiParse.php |
— | — | @@ -115,8 +115,10 @@ |
116 | 116 | if(!$titleObj) |
117 | 117 | $titleObj = Title::newFromText("API"); |
118 | 118 | $wgTitle = $titleObj; |
119 | | - if($params['pst'] || $params['onlypst']) |
| 119 | + if($params['pst'] || $params['onlypst']) { |
120 | 120 | $text = $wgParser->preSaveTransform($text, $titleObj, $wgUser, $popts); |
| 121 | + $this->getMain()->setVaryCookie(); |
| 122 | + } |
121 | 123 | if($params['onlypst']) |
122 | 124 | { |
123 | 125 | // Build a result and bail out |
Index: branches/REL1_15/phase3/includes/api/ApiPurge.php |
— | — | @@ -42,6 +42,7 @@ |
43 | 43 | */ |
44 | 44 | public function execute() { |
45 | 45 | global $wgUser; |
| 46 | + $this->getMain()->setCachePrivate(); |
46 | 47 | $params = $this->extractRequestParams(); |
47 | 48 | if(!$wgUser->isAllowed('purge')) |
48 | 49 | $this->dieUsageMsg(array('cantpurge')); |
Index: branches/REL1_15/phase3/includes/api/ApiQueryDeletedrevs.php |
— | — | @@ -42,6 +42,7 @@ |
43 | 43 | public function execute() { |
44 | 44 | |
45 | 45 | global $wgUser; |
| 46 | + $this->getMain()->setVaryCookie(); |
46 | 47 | // Before doing anything at all, let's check permissions |
47 | 48 | if(!$wgUser->isAllowed('deletedhistory')) |
48 | 49 | $this->dieUsage('You don\'t have permission to view deleted revision information', 'permissiondenied'); |
Index: branches/REL1_15/phase3/includes/api/ApiQueryBlocks.php |
— | — | @@ -115,6 +115,8 @@ |
116 | 116 | "ipb_range_end >= '$upper'" |
117 | 117 | )); |
118 | 118 | } |
| 119 | + // Make sure private data (deleted blocks) isn't cached |
| 120 | + $this->getMain()->setVaryCookie(); |
119 | 121 | if(!$wgUser->isAllowed('hideuser')) |
120 | 122 | $this->addWhereFld('ipb_deleted', 0); |
121 | 123 | |
Index: branches/REL1_15/phase3/includes/api/ApiQueryAllmessages.php |
— | — | @@ -47,9 +47,11 @@ |
48 | 48 | { |
49 | 49 | global $wgLang; |
50 | 50 | $wgLang = Language::factory($params['lang']); |
| 51 | + } else if ( is_null( $params['lang'] ) ) { |
| 52 | + // Language not determined by URL but by user preferences, so don't cache |
| 53 | + $this->getMain()->setVaryCookie(); |
51 | 54 | } |
52 | 55 | |
53 | | - |
54 | 56 | //Determine which messages should we print |
55 | 57 | $messages_target = array(); |
56 | 58 | if( $params['messages'] == '*' ) { |
Index: branches/REL1_15/phase3/includes/api/ApiQueryWatchlistRaw.php |
— | — | @@ -53,6 +53,7 @@ |
54 | 54 | |
55 | 55 | $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist'); |
56 | 56 | |
| 57 | + $this->getMain()->setVaryCookie(); |
57 | 58 | if (!$wgUser->isLoggedIn()) |
58 | 59 | $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin'); |
59 | 60 | $params = $this->extractRequestParams(); |
— | — | @@ -178,4 +179,4 @@ |
179 | 180 | public function getVersion() { |
180 | 181 | return __CLASS__ . ': $Id$'; |
181 | 182 | } |
182 | | -} |
\ No newline at end of file |
| 183 | +} |
Index: branches/REL1_15/phase3/includes/api/ApiQueryUserInfo.php |
— | — | @@ -40,6 +40,7 @@ |
41 | 41 | } |
42 | 42 | |
43 | 43 | public function execute() { |
| 44 | + $this->getMain()->setCachePrivate(); |
44 | 45 | $params = $this->extractRequestParams(); |
45 | 46 | $result = $this->getResult(); |
46 | 47 | $r = array(); |
Index: branches/REL1_15/phase3/includes/api/ApiMain.php |
— | — | @@ -121,7 +121,7 @@ |
122 | 122 | |
123 | 123 | |
124 | 124 | private $mPrinter, $mModules, $mModuleNames, $mFormats, $mFormatNames; |
125 | | - private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode, $mSquidMaxage; |
| 125 | + private $mResult, $mAction, $mShowVersions, $mEnableWrite, $mRequest, $mInternalMode, $mSquidMaxage, $mVaryCookie; |
126 | 126 | |
127 | 127 | /** |
128 | 128 | * Constructs an instance of ApiMain that utilizes the module and format specified by $request. |
— | — | @@ -166,6 +166,7 @@ |
167 | 167 | |
168 | 168 | $this->mSquidMaxage = -1; // flag for executeActionWithErrorHandling() |
169 | 169 | $this->mCommit = false; |
| 170 | + $this->mVaryCookie = false; |
170 | 171 | } |
171 | 172 | |
172 | 173 | /** |
— | — | @@ -203,6 +204,35 @@ |
204 | 205 | } |
205 | 206 | |
206 | 207 | /** |
| 208 | + * Make sure Vary: Cookie and friends are set. Use this when the output of a request |
| 209 | + * may be cached for anons but may not be cached for logged-in users. |
| 210 | + * |
| 211 | + * WARNING: This function must be called CONSISTENTLY for a given URL. This means that a |
| 212 | + * given URL must either always or never call this function; if it sometimes does and |
| 213 | + * sometimes doesn't, stuff will break. |
| 214 | + */ |
| 215 | + public function setVaryCookie() { |
| 216 | + $this->mVaryCookie = true; |
| 217 | + } |
| 218 | + |
| 219 | + /** |
| 220 | + * Actually output the Vary: Cookie header and its friends, if flagged with setVaryCookie(). |
| 221 | + * Outputs the appropriate X-Vary-Options header and Cache-Control: private if needed. |
| 222 | + */ |
| 223 | + private function outputVaryCookieHeader() { |
| 224 | + global $wgUseXVO, $wgOut; |
| 225 | + if ( $this->mVaryCookie ) { |
| 226 | + header( 'Vary: Cookie' ); |
| 227 | + if ( $wgUseXVO ) { |
| 228 | + header( $wgOut->getXVO() ); |
| 229 | + if ( $wgOut->haveCacheVaryCookies() ) { |
| 230 | + $this->setCacheControl( array( 'private' => true ) ); |
| 231 | + } |
| 232 | + } |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + /** |
207 | 237 | * Create an instance of an output formatter by its name |
208 | 238 | */ |
209 | 239 | public function createPrinterByName($format) { |
— | — | @@ -212,6 +242,14 @@ |
213 | 243 | } |
214 | 244 | |
215 | 245 | /** |
| 246 | + * Make sure Cache-Control: private is set. Use this when the output of a request |
| 247 | + * is for the current recipient only and should not be cached in any shared cache. |
| 248 | + */ |
| 249 | + public function setCachePrivate() { |
| 250 | + $this->setCacheControl( array( 'private' => true ) ); |
| 251 | + } |
| 252 | + |
| 253 | + /** |
216 | 254 | * Execute api request. Any errors will be handled if the API was called by the remote client. |
217 | 255 | */ |
218 | 256 | public function execute() { |
— | — | @@ -252,6 +290,7 @@ |
253 | 291 | |
254 | 292 | // Error results should not be cached |
255 | 293 | $this->setCacheMaxAge(0); |
| 294 | + $this->setCachePrivate(); |
256 | 295 | |
257 | 296 | $headerStr = 'MediaWiki-API-Error: ' . $errCode; |
258 | 297 | if ($e->getCode() === 0) |
— | — | @@ -266,6 +305,11 @@ |
267 | 306 | $this->mPrinter->safeProfileOut(); |
268 | 307 | $this->printResult(true); |
269 | 308 | } |
| 309 | + |
| 310 | + // If this wiki is private, don't cache anything ever |
| 311 | + if ( in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) ) { |
| 312 | + $this->setCachePrivate(); |
| 313 | + } |
270 | 314 | |
271 | 315 | if($this->mSquidMaxage == -1) |
272 | 316 | { |
— | — | @@ -282,6 +326,7 @@ |
283 | 327 | $expires = ($exp == 0 ? 1 : time() + $exp); |
284 | 328 | header('Expires: ' . wfTimestamp(TS_RFC2822, $expires)); |
285 | 329 | header('Cache-Control: s-maxage=' . $smaxage . ', must-revalidate, max-age=' . $maxage); |
| 330 | + $this->outputVaryCookieHeader(); |
286 | 331 | |
287 | 332 | if($this->mPrinter->getIsHtml()) |
288 | 333 | echo wfReportTime(); |
— | — | @@ -388,7 +433,9 @@ |
389 | 434 | } |
390 | 435 | |
391 | 436 | global $wgUser; |
392 | | - if ($module->isReadMode() && !$wgUser->isAllowed('read')) |
| 437 | + if ( $module->isReadMode() && |
| 438 | + !in_array( 'read', User::getGroupPermissions( array( '*' ) ), true ) && |
| 439 | + !$wgUser->isAllowed('read')) |
393 | 440 | $this->dieUsageMsg(array('readrequired')); |
394 | 441 | if ($module->isWriteMode()) { |
395 | 442 | if (!$this->mEnableWrite) |
Index: branches/REL1_15/phase3/includes/api/ApiQueryWatchlist.php |
— | — | @@ -56,6 +56,7 @@ |
57 | 57 | |
58 | 58 | $this->selectNamedDB('watchlist', DB_SLAVE, 'watchlist'); |
59 | 59 | |
| 60 | + $this->getMain()->setVaryCookie(); |
60 | 61 | if (!$wgUser->isLoggedIn()) |
61 | 62 | $this->dieUsage('You must be logged-in to have a watchlist', 'notloggedin'); |
62 | 63 | |
— | — | @@ -148,7 +149,9 @@ |
149 | 150 | } |
150 | 151 | |
151 | 152 | // Check permissions |
152 | | - global $wgUser; |
| 153 | + global $wgUser |
| 154 | + $this->getMain()->setVaryCookie(); |
| 155 | + |
153 | 156 | if((isset($show['patrolled']) || isset($show['!patrolled'])) && !$wgUser->useRCPatrol() && !$wgUser->useNPPatrol()) |
154 | 157 | $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied'); |
155 | 158 | |
Index: branches/REL1_15/phase3/includes/api/ApiPatrol.php |
— | — | @@ -42,6 +42,7 @@ |
43 | 43 | */ |
44 | 44 | public function execute() { |
45 | 45 | global $wgUser, $wgUseRCPatrol, $wgUseNPPatrol; |
| 46 | + $this->getMain()->setCachePrivate(); |
46 | 47 | $params = $this->extractRequestParams(); |
47 | 48 | |
48 | 49 | if(!isset($params['token'])) |
Index: branches/REL1_15/phase3/includes/api/ApiQueryRevisions.php |
— | — | @@ -352,6 +352,9 @@ |
353 | 353 | |
354 | 354 | if(!is_null($this->token)) |
355 | 355 | { |
| 356 | + // Don't cache tokens |
| 357 | + $this->getMain()->setCachePrivate(); |
| 358 | + |
356 | 359 | $tokenFunctions = $this->getTokenFunctions(); |
357 | 360 | foreach($this->token as $t) |
358 | 361 | { |
Index: branches/REL1_15/phase3/includes/api/ApiQueryInfo.php |
— | — | @@ -282,6 +282,9 @@ |
283 | 283 | } |
284 | 284 | |
285 | 285 | if (!is_null($this->params['token'])) { |
| 286 | + // Don't cache tokens |
| 287 | + $this->getMain()->setCachePrivate(); |
| 288 | + |
286 | 289 | $tokenFunctions = $this->getTokenFunctions(); |
287 | 290 | $pageInfo['starttimestamp'] = wfTimestamp(TS_ISO_8601, time()); |
288 | 291 | foreach($this->params['token'] as $t) |
Index: branches/REL1_15/phase3/includes/api/ApiQueryUserContributions.php |
— | — | @@ -203,6 +203,8 @@ |
204 | 204 | $this->fld_patrolled) |
205 | 205 | { |
206 | 206 | global $wgUser; |
| 207 | + // Don't cache private data |
| 208 | + $this->getMain()->setVaryCookie(); |
207 | 209 | if(!$wgUser->useRCPatrol() && !$wgUser->useNPPatrol()) |
208 | 210 | $this->dieUsage("You need the patrol right to request the patrolled flag", 'permissiondenied'); |
209 | 211 | // Use a redundant join condition on both |