MediaWiki
REL1_24
|
00001 <?php 00030 class AjaxResponse { 00035 private $mCacheDuration; 00036 00041 private $mContentType; 00042 00047 private $mDisabled; 00048 00053 private $mLastModified; 00054 00059 private $mResponseCode; 00060 00065 private $mVary; 00066 00071 private $mText; 00072 00076 private $mConfig; 00077 00082 function __construct( $text = null, Config $config = null ) { 00083 $this->mCacheDuration = null; 00084 $this->mVary = null; 00085 $this->mConfig = $config ?: ConfigFactory::getDefaultInstance()->makeConfig( 'main' ); 00086 00087 $this->mDisabled = false; 00088 $this->mText = ''; 00089 $this->mResponseCode = '200 OK'; 00090 $this->mLastModified = false; 00091 $this->mContentType = 'application/x-wiki'; 00092 00093 if ( $text ) { 00094 $this->addText( $text ); 00095 } 00096 } 00097 00102 function setCacheDuration( $duration ) { 00103 $this->mCacheDuration = $duration; 00104 } 00105 00110 function setVary( $vary ) { 00111 $this->mVary = $vary; 00112 } 00113 00118 function setResponseCode( $code ) { 00119 $this->mResponseCode = $code; 00120 } 00121 00126 function setContentType( $type ) { 00127 $this->mContentType = $type; 00128 } 00129 00133 function disable() { 00134 $this->mDisabled = true; 00135 } 00136 00141 function addText( $text ) { 00142 if ( !$this->mDisabled && $text ) { 00143 $this->mText .= $text; 00144 } 00145 } 00146 00150 function printText() { 00151 if ( !$this->mDisabled ) { 00152 print $this->mText; 00153 } 00154 } 00155 00159 function sendHeaders() { 00160 if ( $this->mResponseCode ) { 00161 $n = preg_replace( '/^ *(\d+)/', '\1', $this->mResponseCode ); 00162 header( "Status: " . $this->mResponseCode, true, (int)$n ); 00163 } 00164 00165 header ( "Content-Type: " . $this->mContentType ); 00166 00167 if ( $this->mLastModified ) { 00168 header ( "Last-Modified: " . $this->mLastModified ); 00169 } else { 00170 header ( "Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . " GMT" ); 00171 } 00172 00173 if ( $this->mCacheDuration ) { 00174 # If squid caches are configured, tell them to cache the response, 00175 # and tell the client to always check with the squid. Otherwise, 00176 # tell the client to use a cached copy, without a way to purge it. 00177 00178 if ( $this->mConfig->get( 'UseSquid' ) ) { 00179 # Expect explicit purge of the proxy cache, but require end user agents 00180 # to revalidate against the proxy on each visit. 00181 # Surrogate-Control controls our Squid, Cache-Control downstream caches 00182 00183 if ( $this->mConfig->get( 'UseESI' ) ) { 00184 header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' ); 00185 header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' ); 00186 } else { 00187 header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' ); 00188 } 00189 00190 } else { 00191 # Let the client do the caching. Cache is not purged. 00192 header ( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" ); 00193 header ( "Cache-Control: s-maxage={$this->mCacheDuration}," . 00194 "public,max-age={$this->mCacheDuration}" ); 00195 } 00196 00197 } else { 00198 # always expired, always modified 00199 header ( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); // Date in the past 00200 header ( "Cache-Control: no-cache, must-revalidate" ); // HTTP/1.1 00201 header ( "Pragma: no-cache" ); // HTTP/1.0 00202 } 00203 00204 if ( $this->mVary ) { 00205 header ( "Vary: " . $this->mVary ); 00206 } 00207 } 00208 00217 function checkLastModified( $timestamp ) { 00218 global $wgCachePages, $wgCacheEpoch, $wgUser; 00219 $fname = 'AjaxResponse::checkLastModified'; 00220 00221 if ( !$timestamp || $timestamp == '19700101000000' ) { 00222 wfDebug( "$fname: CACHE DISABLED, NO TIMESTAMP\n", 'log' ); 00223 return false; 00224 } 00225 00226 if ( !$wgCachePages ) { 00227 wfDebug( "$fname: CACHE DISABLED\n", 'log' ); 00228 return false; 00229 } 00230 00231 $timestamp = wfTimestamp( TS_MW, $timestamp ); 00232 $lastmod = wfTimestamp( TS_RFC2822, max( $timestamp, $wgUser->getTouched(), $wgCacheEpoch ) ); 00233 00234 if ( !empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) ) { 00235 # IE sends sizes after the date like this: 00236 # Wed, 20 Aug 2003 06:51:19 GMT; length=5202 00237 # this breaks strtotime(). 00238 $modsince = preg_replace( '/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"] ); 00239 $modsinceTime = strtotime( $modsince ); 00240 $ismodsince = wfTimestamp( TS_MW, $modsinceTime ? $modsinceTime : 1 ); 00241 wfDebug( "$fname: -- client send If-Modified-Since: " . $modsince . "\n", 'log' ); 00242 wfDebug( "$fname: -- we might send Last-Modified : $lastmod\n", 'log' ); 00243 00244 if ( ( $ismodsince >= $timestamp ) 00245 && $wgUser->validateCache( $ismodsince ) && 00246 $ismodsince >= $wgCacheEpoch 00247 ) { 00248 ini_set( 'zlib.output_compression', 0 ); 00249 $this->setResponseCode( "304 Not Modified" ); 00250 $this->disable(); 00251 $this->mLastModified = $lastmod; 00252 00253 wfDebug( "$fname: CACHED client: $ismodsince ; user: {$wgUser->getTouched()} ; " . 00254 "page: $timestamp ; site $wgCacheEpoch\n", 'log' ); 00255 00256 return true; 00257 } else { 00258 wfDebug( "$fname: READY client: $ismodsince ; user: {$wgUser->getTouched()} ; " . 00259 "page: $timestamp ; site $wgCacheEpoch\n", 'log' ); 00260 $this->mLastModified = $lastmod; 00261 } 00262 } else { 00263 wfDebug( "$fname: client did not send If-Modified-Since header\n", 'log' ); 00264 $this->mLastModified = $lastmod; 00265 } 00266 return false; 00267 } 00268 00274 function loadFromMemcached( $mckey, $touched ) { 00275 global $wgMemc; 00276 00277 if ( !$touched ) { 00278 return false; 00279 } 00280 00281 $mcvalue = $wgMemc->get( $mckey ); 00282 if ( $mcvalue ) { 00283 # Check to see if the value has been invalidated 00284 if ( $touched <= $mcvalue['timestamp'] ) { 00285 wfDebug( "Got $mckey from cache\n" ); 00286 $this->mText = $mcvalue['value']; 00287 00288 return true; 00289 } else { 00290 wfDebug( "$mckey has expired\n" ); 00291 } 00292 } 00293 00294 return false; 00295 } 00296 00302 function storeInMemcached( $mckey, $expiry = 86400 ) { 00303 global $wgMemc; 00304 00305 $wgMemc->set( $mckey, 00306 array( 00307 'timestamp' => wfTimestampNow(), 00308 'value' => $this->mText 00309 ), $expiry 00310 ); 00311 00312 return true; 00313 } 00314 }