30 if ( !extension_loaded(
'zlib') ){
31 $this->useGzipCompression =
false;
32 }
else if ( isset($params[
'useGzipCompression']) ){
33 $this->useGzipCompression = $params[
'useGzipCompression'];
36 if ( isset($params[
'threshold']) ) $this->threshold = $params[
'threshold'];
37 if ( isset($params[
'lifeTime']) ) $this->lifeTime = $params[
'lifeTime'];
38 if ( isset($params[
'tableName']) ) $this->tableName = $params[
'tableName'];
39 if ( isset($params[
'ignoredTables']) ) $this->ignoredTables = explode(
',', $params[
'ignoredTables']);
40 if ( isset($params[
'observedTables']) ) $this->observedTables = explode(
',', $params[
'observedTables']);
41 if ( isset($params[
'exemptActions']) ) $this->exemptActions = explode(
',', $params[
'exemptActions']);
42 if ( isset($params[
'stripKeys']) ) $this->stripKeys = explode(
',', $params[
'stripKeys']);
49 if ( !isset($this->userId) ){
50 $del = $this->app->getDelegate();
52 if ( $del and method_exists($del,
'getOutputCacheUserId') ){
53 $this->userId = $del->getOutputCacheUserId();
55 if ( !isset($this->userId) ){
57 if ( class_exists(
'Dataface_AuthenticationTool') ){
62 if ( !isset($this->userId) ) $this->userId =
'';
73 import(
'Dataface/AuthenticationTool.php');
74 $query =& $this->app->getQuery();
78 $Language = ( isset($params[
'lang']) ? $params[
'lang'] : $this->app->_conf[
'lang']);
82 $TimeStamp = ( isset($params[
'time']) ? $params[
'time'] : time()-
$this->lifeTime);
86 where `PageID` = '".addslashes($PageID).
"'
87 and `Language` = '".addslashes($Language).
"'
88 and `UserID` = '".addslashes($UserID).
"'
109 $query =&
$app->getQuery();
110 if ( in_array($query[
'-action'], $this->exemptActions) )
return null;
113 $DataColumn =
'Data_gz';
115 $DataColumn =
'Data';
118 $res = mysql_query(
"select `".addslashes($DataColumn).
"`, UNIX_TIMESTAMP(`LastModified`) as `TimeStamp`, `Dependencies`, `Headers` from `".addslashes($this->tableName).
"`
122 throw new Exception(mysql_error($this->app->db()), E_USER_ERROR);
125 if ( mysql_num_rows($res) == 0 )
return null;
129 $tables = explode(
',',$dependencies);
131 if ( count($tables) == 0 ) $tables = null;
135 if ( is_resource($res) ) mysql_free_result($res);
153 SELECT COUNT(*) FROM `".addslashes($this->tableName).
"` ".
156 throw new Exception(mysql_error($this->app->db()), E_USER_ERROR);
158 list($num) = mysql_fetch_row($res);
159 mysql_free_result($res);
193 $query =&
$app->getQuery();
194 if ( in_array($query[
'-action'], $this->exemptActions) ){
198 if ( floatval($this->threshold) * floatval(100) > rand(0,100) ){
199 register_shutdown_function(array(&$this,
'cleanCache'));
202 if ( isset($params[
'randomize']) and $params[
'randomize'] > 1 ){
203 $this->randomize = $params[
'randomize'];
205 if ( $numVersions < $params[
'randomize'] ){
207 if ( floatval(100)*floatval($numVersions)/floatval($params[
'randomize']) > rand(0,100) ){
222 $output = $this->
getPage($params);
228 if ( isset($output) ){
231 $etag = md5($output);
234 if (!$this->app->sessionEnabled() and @
$_SERVER[
'REQUEST_URI'] and strpos(
$_SERVER[
'REQUEST_URI'],
'?') === false ){
235 session_cache_limiter(
'public');
238 header(
'Connection: close');
239 header(
"Last-Modified: ".gmdate(
"D, d M Y H:i:s", $this->lastModified).
" GMT");
240 header(
'Pragma: public');
241 header(
'Content-Length: '.strlen($output));
245 header(
"Last-Modified: ".gmdate(
"D, d M Y H:i:s", $this->lastModified).
" GMT");
246 header(
"Etag: $etag");
247 if (@strtotime(
$_SERVER[
'HTTP_IF_MODIFIED_SINCE']) == $this->lastModified ||
248 @trim(
$_SERVER[
'HTTP_IF_NONE_MATCH']) == $etag) {
249 header(
"HTTP/1.1 304 Not Modified");
257 if ( function_exists(
'headers_list')){
258 $hlist = headers_list();
260 foreach ($hlist as $h){
261 if ( preg_match(
'/^(?:Content-Type|Content-Language|Content-Location|Content-Disposition|P3P):/i', $h ) ) {
262 list($hname,$hval) = array_map(
'trim',explode(
':',$h));
263 $harr[$hname] = $hval;
267 foreach ( $this->headers as $h){
268 list($hname,$hval) = array_map(
'trim',explode(
':',$h));
269 if ( !isset($harr[$hname]) ){
270 header($hname.
': '.$hval);
277 header(
"Content-Encoding: gzip");
285 ob_start(array(&$this,
'ob_flush'));
286 ob_implicit_flush(0);
291 if ( !$data )
return false;
292 $params = array(
'randomize'=>$this->randomize,
'data'=>$data,
'tables'=>$this->app->tableNamesUsed);
296 if ( !$this->app->sessionEnabled() and @
$_SERVER[
'REQUEST_URI'] and strpos(
$_SERVER[
'REQUEST_URI'],
'?') === false ){
299 session_cache_limiter(
'public');
301 header(
'Connection: close');
302 header(
"Last-Modified: ".gmdate(
"D, d M Y H:i:s", time()).
" GMT");
303 header(
'Pragma: public');
304 header(
'Content-Length: '.strlen($data));
306 header(
"Last-Modified: ".gmdate(
"D, d M Y H:i:s", time()).
" GMT");
307 header(
"Etag: $etag");
308 if (@strtotime(
$_SERVER[
'HTTP_IF_MODIFIED_SINCE']) == time() ||
309 @trim(
$_SERVER[
'HTTP_IF_NONE_MATCH']) == $etag) {
310 header(
"HTTP/1.1 304 Not Modified");
321 $page_url =
$_SERVER[
'REQUEST_URI'];
322 foreach ($this->stripKeys as $key){
323 $page_url = preg_replace(
'/&?'.preg_quote($key,
'/').
'=[^&]*/',
'', $page_url);
326 $PageID = ( isset($params[
'id']) ? $params[
'id'] : md5($page_url));
354 if ( !isset($params[
'data']) )
throw new Exception(
'Missing parameter "data"', E_USER_ERROR);
355 $Data = $params[
'data'];
356 $Language = ( isset($params[
'lang']) ? $params[
'lang'] : $this->app->_conf[
'lang']);
364 $Expires = (isset($params[
'expires']) ? $params[
'expires'] : time() +
$this->lifeTime);
365 $tables = (isset($params[
'tables']) ? $params[
'tables'] :
'');
366 $Dependencies = (is_array($tables) ? implode(
',',$tables) : $tables);
368 if ( $this->useGzipCompression && extension_loaded(
'zlib') ){
376 $size = strlen($Data);
385 $Data_gz =
"\x1f\x8b\x08\x00\x00\x00\x00\x00".
386 substr(gzcompress($Data,9),0, $size);
391 if ( isset($params[
'randomize']) and $params[
'randomize'] ){
402 DELETE FROM `".addslashes($this->tableName).
"`
404 `PageID`='".addslashes($PageID).
"' AND
405 `Language`='".addslashes($Language).
"' AND
406 `UserID`='".addslashes($UserID).
"' AND
408 SELECT `GenID` FROM `".addslashes($this->tableName).
"`
410 `PageID`='".addslashes($PageID).
"' AND
411 `Language`='".addslashes($Language).
"' AND
412 `UserID`='".addslashes($UserID).
"'
415 LIMIT ".(intval($params[
'randomize']) - 1).
"
416 )", $this->app->db() );
419 throw new Exception(mysql_error($this->app->db()), E_USER_ERROR);
437 if ( function_exists(
'headers_list') ){
442 if ( preg_match(
'/^(?:Content-Type|Content-Language|Content-Location|Content-Disposition|P3P):/i', $h ) ) {
454 replace delayed INTO `".addslashes($this->tableName).
"`
455 (`PageID`,`Language`,`UserID`,`Dependencies`,`Expires`,`Data`,`Data_gz`, `Headers`)
457 ('".addslashes($PageID).
"',
458 '".addslashes($Language).
"',
459 '".addslashes($UserID).
"',
460 '".addslashes($Dependencies).
"',
461 FROM_UNIXTIME('".addslashes($Expires).
"'),
462 '".addslashes($Data).
"',
463 '".addslashes($Data_gz).
"',
464 '".addslashes(serialize(
$headers)).
"'
467 $res = mysql_query($sql, $this->app->db());
470 throw new Exception(mysql_error($this->app->db()), E_USER_ERROR);
473 if ( @$this->app->_conf[
'_output_cache'][
'cachedir'] ){
474 $filename = DATAFACE_SITE_PATH.
'/'.$this->app->_conf[
'_output_cache'][
'cachedir'];
476 $filename = $filename.
'/'.$dir;
477 if ( !file_exists($filename)){
478 mkdir($filename, 0777);
482 $filename .=
'/'.$PageID.
'-'.md5($Language.
'-'.$UserID);
483 if ( file_exists($filename) ){
487 $fh = fopen($filename,
'w');
493 $fh = fopen($filename.
'.gz',
'w');
495 fwrite($fh, $Data_gz);
514 for ($i = 0; $i < 4; $i ++) {
515 $out .= chr($Val % 256);
516 $Val = floor($Val / 256);
527 $res = mysql_query(
"create table IF NOT EXISTS `".addslashes($this->tableName).
"`(
528 `GenID` INT(11) auto_increment,
529 `PageID` VARCHAR(64),
531 `UserID` VARCHAR(32),
533 `LastModified` TIMESTAMP,
538 PRIMARY KEY (`GenID`),
539 INDEX `LookupIndex` (`Language`,`UserID`,`PageID`)
540 )", $this->app->db());
542 return PEAR::raiseError(
'Could not create cache table: '.mysql_error($this->app->db()));
554 $res = mysql_query(
"SHOW TABLES LIKE '".addslashes($this->tableName).
"'", $this->app->db());
556 throw new Exception(mysql_error($this->app->db()), E_USER_ERROR);
558 return (mysql_num_rows($res) > 0);
565 $res = mysql_query(
"delete low_priority from `".addslashes($this->tableName).
"` where `Expires` < NOW()", $this->app->db());
574 return stristr(@
$_SERVER[
'HTTP_ACCEPT_ENCODING'],
'gzip');
584 $this->tableModificationTimes =& $mod_times;
601 if ( !isset($tables) ) $tables = array_keys($this->tableModificationTimes);
602 if ( !is_array($tables) ){
603 $tables = explode(
',', $tables);
605 $tables = array_merge($this->observedTables, $tables);
606 foreach ($tables as
$table ){
607 if ( isset( $this->ignoredTables[$table] ) )
continue;
608 if ( !isset($this->tableModificationTimes[$table]) )
continue;
609 if ( $this->tableModificationTimes[$table] > $time )
return true;