From c4bfa03be17aad8cb805fb24afe07ba0de2cc47e Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 24 May 2014 20:40:51 -0700 Subject: [PATCH] Fixes #495, #485, #486, #487 - Browser cache issues. --- class2.php | 172 +++++++++++++++++++++++++ e107_core/templates/footer_default.php | 77 +---------- e107_handlers/session_handler.php | 7 +- 3 files changed, 179 insertions(+), 77 deletions(-) diff --git a/class2.php b/class2.php index b6432f554..5e0e67489 100644 --- a/class2.php +++ b/class2.php @@ -2295,6 +2295,178 @@ class error_handler } } + + + +/** + * Manage Headers sent to browser. + * It is important to specify one of Expires or Cache-Control max-age, and one of Last-Modified or ETag, for all cacheable resources. + * It is redundant to specify both Expires and Cache-Control: max-age, or to specify both Last-Modified and ETag. + * Reference : http://css-tricks.com/snippets/php/intelligent-php-cache-control/ + * XXX Etag cannot be relied on as some hosts have Etag disabled. + * XXX session_cache_limiter('private') will override some of the things below and bring back our browser cache issues. + */ +class e_http_header +{ + private $content; + private $etag; + private $compress_output = false; + private $compression_level = 6; + private $compression_browser_support = false; + private $compression_server_support = false; + private $headers = array(); + + + function __construct() + { + if (strstr(varset($_SERVER['HTTP_ACCEPT_ENCODING'], ''), 'gzip')) + { + $this->compression_browser_support = true; + } + + if(ini_get("zlib.output_compression") == '' && function_exists("gzencode")) + { + $this->compression_server_support = true; + } + + $this->compress_output = varset(e107::getPref('compress_output'),false); + + } + + + function setContent($content) + { + $this->etag = md5($content); + $this->content = $content; + } + + function setHeader($header, $force=false, $response_code=null) + { + list($key,$val) = explode(':',$header,2); + $this->headers[$key] = $val; + header($header, $force, $response_code); + } + + function debug() + { + + echo "

Server Headers

"; + $server = getallheaders(); + ksort($server); + print_a($server); + echo "

e107 Headers

"; + ksort($this->headers); + print_a($this->headers); + var_dump($this->compress_output); + + $server = array(); + foreach($_SERVER as $k=>$v) + { + if(substr($k,0,4) == 'HTTP') + { + $server[$k] = $v; + } + } + echo "

_SERVER

"; + print_a($server); + + } + + + function send() + { + // Disable caching of html. + /* + $this->setHeader("Expires: 0", true); + $this->setHeader("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT", true); + $this->setHeader("Cache-Control: no-store, no-cache, must-revalidate", true); + $this->setHeader("Cache-Control: post-check=0, pre-check=0", false); + $this->setHeader("Pragma: no-cache"); + $this->setHeader("Cache-Control: max-age=0", false); + */ + // $this->setHeader("Cache-Control: public", true); + + + $canCache = e107::canCache(); + + // $this->setHeader("Cache-Control: must-revalidate", true); + + if($canCache && !deftrue('e_NOCACHE') && $_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['QUERY_STRING'] != 'logout') + { + // header("Cache-Control: must-revalidate", true); + if(e107::getPref('site_page_expires')) // TODO - allow per page + { + if (function_exists('date_default_timezone_set')) + { + date_default_timezone_set('UTC'); + } + $time = time()+ (integer) e107::getPref('site_page_expires'); + $this->setHeader('Expires: '.gmdate("D, d M Y H:i:s", $time).' GMT', true); + } + } + else + { + $canCache = false; + } + + + if($this->compress_out != false && $this->compression_server_support == true && $this->compression_browser_support == true) + { + // $this->setHeader("ETag: \"{$this->etag}-gzip\""); + $this->setHeader('ETag: "'.$this->etag.'-gzip"', true); + $page = gzencode($this->content, $this->compression_level); + $this->setHeader("Content-Encoding: gzip", true); + $this->setHeader("Content-Length: ".strlen($page), true); + + } + else + { + if($this->compression_browser_support ==true) + { + $this->setHeader('ETag: "'.$this->etag.'-gzip"', true); + } + else + { + $this->setHeader('ETag: "'.$this->etag.'"', true); + } + + $this->setHeader("Content-Length: ".strlen($this->content), true); + } + + $this->setHeader("X-Powered-By: e107", true); // no less secure than e107-specific html. + + if($this->compression_server_support == true) + { + $this->setHeader('Vary: Accept-Encoding'); + } + else + { + $this->setHeader('Vary: Accept'); + } + + // should come after the Etag header + if ($canCache && isset($_SERVER['HTTP_IF_NONE_MATCH'])) + { + $IF_NONE_MATCH = str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']); + if($IF_NONE_MATCH == $this->etag || ($IF_NONE_MATCH == ($this->etag."-gzip"))) + { + $this->setHeader('HTTP/1.1 304 Not Modified'); + exit(); + } + } + } + + + + + + +} + + + + + $sql->db_Mark_Time('(After class2)'); diff --git a/e107_core/templates/footer_default.php b/e107_core/templates/footer_default.php index 56f1f59fc..18ee31421 100644 --- a/e107_core/templates/footer_default.php +++ b/e107_core/templates/footer_default.php @@ -332,78 +332,11 @@ $e107->destruct(); // $page = ob_get_clean(); -$etag = md5($page); - -//header('Pragma:'); -// previously disabled or there is posted data -$canCache = e107::canCache(); - header("Cache-Control: must-revalidate", true); //XXX testing it here to check for improvement. -if($canCache && !deftrue('e_NOCACHE') && $_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['QUERY_STRING'] != 'logout') -{ - // header("Cache-Control: must-revalidate", true); - if(e107::getPref('site_page_expires')) // TODO - allow per page - { - if (function_exists('date_default_timezone_set')) - { - date_default_timezone_set('UTC'); - } - $time = time()+ (integer) e107::getPref('site_page_expires'); - header('Expires: '.gmdate("D, d M Y H:i:s", $time).' GMT', true); - } -} -else -{ - $canCache = false; -} - -$pref['compression_level'] = 6; -$browser_support = FALSE; -$server_support = FALSE; -if (strstr(varset($_SERVER['HTTP_ACCEPT_ENCODING'], ''), 'gzip')) -{ - $browser_support = true; -} -if(ini_get("zlib.output_compression") == '' && function_exists("gzencode")) -{ - $server_support = true; -} -if(varset($pref['compress_output'],false) && $server_support == true && $browser_support == true) -{ - $level = intval($pref['compression_level']); - header("ETag: \"{$etag}-gzip\""); - $page = gzencode($page, $level); - header("Content-Encoding: gzip", true); - header("Content-Length: ".strlen($page), true); - header('Vary: Accept-Encoding'); -} -else -{ - if($browser_support==TRUE) - { - header("ETag: \"{$etag}-gzip\""); - } - else - { - header("ETag: \"{$etag}\""); - } - - header("Content-Length: ".strlen($page), true); - header('Vary: Accept'); -} - -header("X-Powered-By: e107", true); // no less secure than e107-specific html. - - -// should come after the Etag header -if ($canCache && isset($_SERVER['HTTP_IF_NONE_MATCH'])) -{ - $IF_NONE_MATCH = str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']); - if($IF_NONE_MATCH == $etag || ($IF_NONE_MATCH == ($etag."-gzip"))) - { - header('HTTP/1.1 304 Not Modified'); - exit(); - } -} +// New - see class2.php +$ehd = new e_http_header; +$ehd->setContent($page); +$ehd->send(); +// $ehd->debug(); // real output echo $page; diff --git a/e107_handlers/session_handler.php b/e107_handlers/session_handler.php index af3f165e3..a44299cc4 100644 --- a/e107_handlers/session_handler.php +++ b/e107_handlers/session_handler.php @@ -467,12 +467,9 @@ class e_session if ($this->_sessionCacheLimiter) { - session_cache_limiter((string) $this->_sessionCacheLimiter); - } - elseif(!defined('e_NOCACHE') || !e_NOCACHE) - { - session_cache_limiter('private'); + session_cache_limiter((string) $this->_sessionCacheLimiter); //XXX Remove and have e_headers class handle it? } + session_start(); $this->_sessionStarted = true;