From 3059df16aa17b94dd4879457c24ab8c5fa3e237b Mon Sep 17 00:00:00 2001 From: "Uwe.Tews" Date: Fri, 26 Feb 2010 12:58:36 +0000 Subject: [PATCH] - cache modified check implemented --- change_log.txt | 3 + libs/Smarty.class.php | 535 ++++++++++++++++++++++-------------------- 2 files changed, 290 insertions(+), 248 deletions(-) diff --git a/change_log.txt b/change_log.txt index 1c54451a..707b9169 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,6 @@ +26/02/2010 +- cache modified check implemented + 24/02/2010 - bugfix on expressions in doublequoted string enclosed in backticks - added security property $static_classes for static class security diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index a85cc37a..eb83231e 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -1,55 +1,55 @@ -* @author Uwe Tews -* @package Smarty -* @version 3-SVN$Rev: 3286 $ -*/ + * Project: Smarty: the PHP compiling template engine + * File: Smarty.class.php + * SVN: $Id$ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For questions, help, comments, discussion, etc., please join the + * Smarty mailing list. Send a blank e-mail to + * smarty-discussion-subscribe@googlegroups.com + * + * @link http://www.smarty.net/ + * @copyright 2008 New Digital Group, Inc. + * @author Monte Ohrt + * @author Uwe Tews + * @package Smarty + * @version 3-SVN$Rev: 3286 $ + */ /** -* define shorthand directory separator constant -*/ + * define shorthand directory separator constant + */ if (!defined('DS')) { define('DS', DIRECTORY_SEPARATOR); } /** -* set SMARTY_DIR to absolute path to Smarty library files. -* Sets SMARTY_DIR only if user application has not already defined it. -*/ + * set SMARTY_DIR to absolute path to Smarty library files. + * Sets SMARTY_DIR only if user application has not already defined it. + */ if (!defined('SMARTY_DIR')) { define('SMARTY_DIR', dirname(__FILE__) . DS); } /** -* set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. -* Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. -*/ + * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. + * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. + */ if (!defined('SMARTY_SYSPLUGINS_DIR')) { define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS); } @@ -64,32 +64,32 @@ if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { } /** -* define variable scopes -*/ + * define variable scopes + */ define('SMARTY_LOCAL_SCOPE', 0); define('SMARTY_PARENT_SCOPE', 1); define('SMARTY_ROOT_SCOPE', 2); define('SMARTY_GLOBAL_SCOPE', 3); /** -* define caching modes -*/ + * define caching modes + */ define('SMARTY_CACHING_OFF', 0); define('SMARTY_CACHING_LIFETIME_CURRENT', 1); define('SMARTY_CACHING_LIFETIME_SAVED', 2); /** -* This determines how Smarty handles "" tags in templates. -* possible values: -*/ + * This determines how Smarty handles "" tags in templates. + * possible values: + */ define('SMARTY_PHP_PASSTHRU', 0); //-> print tags as plain text define('SMARTY_PHP_QUOTE', 1); //-> escape tags as entities define('SMARTY_PHP_REMOVE', 2); //-> escape tags as entities define('SMARTY_PHP_ALLOW', 3); //-> escape tags as entities /** -* register the class autoloader -*/ + * register the class autoloader + */ if (!defined('SMARTY_SPL_AUTOLOAD')) { define('SMARTY_SPL_AUTOLOAD', 0); } @@ -104,8 +104,8 @@ if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR } /** -* This is the main Smarty class -*/ + * This is the main Smarty class + */ class Smarty extends Smarty_Internal_Data { // smarty version const SMARTY_VERSION = 'Smarty3-SVN$Rev: 3286 $'; @@ -167,7 +167,7 @@ class Smarty extends Smarty_Internal_Data { // config var settings public $config_overwrite = true; //Controls whether variables with the same name overwrite each other. public $config_booleanize = true; //Controls whether config values of on/true/yes and off/false/no get converted to boolean - public $config_read_hidden = true; //Controls whether hidden config sections/vars are read from the file. + public $config_read_hidden = true; //Controls whether hidden config sections/vars are read from the file. // config vars public $config_vars = array(); // assigned tpl vars @@ -223,16 +223,17 @@ class Smarty extends Smarty_Internal_Data { // block data at template inheritance public $block_data = array(); // block tag hierarchy - public $_tag_stack = array(); + public $_tag_stack = array(); // plugins - public $_plugins = array(); + public $_plugins = array(); // generate deprecated function call notices? public $deprecation_notices = true; /** - * Class constructor, initializes basic smarty properties - */ - public function __construct() { + * Class constructor, initializes basic smarty properties + */ + public function __construct() + { // self reference needed by other classes methods $this->smarty = $this; @@ -242,7 +243,7 @@ class Smarty extends Smarty_Internal_Data { $this->start_time = $this->_get_time(); // set exception handler if (!empty($this->exception_handler)) - set_exception_handler($this->exception_handler); + set_exception_handler($this->exception_handler); // set default dirs $this->template_dir = array('.' . DS . 'templates' . DS); $this->compile_dir = '.' . DS . 'templates_c' . DS; @@ -253,8 +254,7 @@ class Smarty extends Smarty_Internal_Data { if (!$this->debugging && $this->debugging_ctrl == 'URL') { if (isset($_SERVER['QUERY_STRING'])) { $_query_string = $_SERVER['QUERY_STRING']; - } - else { + } else { $_query_string = ''; } if (false !== strpos($_query_string, $this->smarty_debug_id)) { @@ -262,18 +262,15 @@ class Smarty extends Smarty_Internal_Data { // enable debugging for this browser session setcookie('SMARTY_DEBUG', true); $this->debugging = true; - } - elseif (false !== strpos($_query_string, $this->smarty_debug_id . '=off')) { + } elseif (false !== strpos($_query_string, $this->smarty_debug_id . '=off')) { // disable debugging for this browser session setcookie('SMARTY_DEBUG', false); $this->debugging = false; - } - else { + } else { // enable debugging for this page $this->debugging = true; } - } - else { + } else { if (isset($_COOKIE['SMARTY_DEBUG'])) { $this->debugging = true; } @@ -285,24 +282,26 @@ class Smarty extends Smarty_Internal_Data { } /** - * Class destructor - */ - public function __destruct() { + * Class destructor + */ + public function __destruct() + { // restore to previous exception handler, if any if (!empty($this->exception_handler)) - restore_exception_handler(); + restore_exception_handler(); } /** - * fetches a rendered Smarty template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $ |null $parent next higher level of Smarty variables - * @return string rendered template output - */ - public function fetch($template, $cache_id = null, $compile_id = null, $parent = null) { + * fetches a rendered Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $ |null $parent next higher level of Smarty variables + * @return string rendered template output + */ + public function fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false) + { if (is_object($cache_id)) { $parent = $cache_id; $cache_id = null; @@ -316,45 +315,74 @@ class Smarty extends Smarty_Internal_Data { $_template = $this->createTemplate ($template, $cache_id, $compile_id, $parent); $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) ? $this->error_reporting : error_reporting() &~E_NOTICE); + // obtain data for cache modified check + if ($this->cache_modified_check && $this->caching && $display) { + $_isCached = $_template->isCached() && !$_template->has_nocache_code; + if ($_isCached) { + $_gmt_mtime = gmdate('D, d M Y H:i:s', $_template->getCachedTimestamp()) . ' GMT'; + } else { + $_gmt_mtime = ''; + } + } // return redered template if (isset($this->autoload_filters['output']) || isset($this->registered_filters['output'])) { $_output = Smarty_Internal_Filter_Handler::runFilter('output', $_template->getRenderedTemplate(), $this); - } - else { + } else { $_output = $_template->getRenderedTemplate(); } $_template->rendered_content = null; - error_reporting($_smarty_old_error_level); - return $_output; - } - - /** - * displays a Smarty template - * - * @param string $ |object $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - */ - public function display($template, $cache_id = null, $compile_id = null, $parent = null) { - // display template - echo $this->fetch ($template, $cache_id, $compile_id, $parent); - // debug output - if ($this->debugging) { - Smarty_Internal_Debug::display_debug($this); + error_reporting($_smarty_old_error_level); + // display or fetch + if ($display) { + if ($this->caching && $this->cache_modified_check) { + $_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + if ($_isCached && $_gmt_mtime == $_last_modified_date) { + if (php_sapi_name() == 'cgi') + header('Status: 304 Not Modified'); + else + header('HTTP/1.1 304 Not Modified'); + } else { + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->getCachedTimestamp()) . ' GMT'); + echo $_output; + } + } else { + echo $_output; + } + // debug output + if ($this->debugging) { + Smarty_Internal_Debug::display_debug($this); + } + return; + } else { + // return fetched content + return $_output; } - return true; } /** - * test if cache i valid - * - * @param string $ |object $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @return boolean cache status - */ - public function isCached($template, $cache_id = null, $compile_id = null) { + * displays a Smarty template + * + * @param string $ |object $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + */ + public function display($template, $cache_id = null, $compile_id = null, $parent = null) + { + // display template + $this->fetch ($template, $cache_id, $compile_id, $parent, true); + } + + /** + * test if cache i valid + * + * @param string $ |object $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @return boolean cache status + */ + public function isCached($template, $cache_id = null, $compile_id = null) + { if (!($template instanceof $this->template_class)) { $template = $this->createTemplate ($template, $cache_id, $compile_id, $this); } @@ -363,25 +391,27 @@ class Smarty extends Smarty_Internal_Data { } /** - * creates a data object - * - * @param object $parent next higher level of Smarty variables - * @returns object data object - */ - public function createData($parent = null) { + * creates a data object + * + * @param object $parent next higher level of Smarty variables + * @returns object data object + */ + public function createData($parent = null) + { return new Smarty_Data($parent, $this); } /** - * creates a template object - * - * @param string $template the resource handle of the template file - * @param object $parent next higher level of Smarty variables - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @returns object template object - */ - public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) { + * creates a template object + * + * @param string $template the resource handle of the template file + * @param object $parent next higher level of Smarty variables + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @returns object template object + */ + public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null) + { if (is_object($cache_id) || is_array($cache_id)) { $parent = $cache_id; $cache_id = null; @@ -389,8 +419,7 @@ class Smarty extends Smarty_Internal_Data { if (is_array($parent)) { $data = $parent; $parent = null; - } - else { + } else { $data = null; } if (!is_object($template)) { @@ -400,13 +429,11 @@ class Smarty extends Smarty_Internal_Data { if (isset($this->template_objects[$_templateId]) && $this->caching) { // return cached template object $tpl = $this->template_objects[$_templateId]; - } - else { + } else { // create new template object $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); } - } - else { + } else { // just return a copy of template class $tpl = $template; } @@ -421,55 +448,58 @@ class Smarty extends Smarty_Internal_Data { } /** - * Loads security class and enables security - */ - public function enableSecurity() { + * Loads security class and enables security + */ + public function enableSecurity() + { if (isset($this->security_class)) { $this->security_policy = new $this->security_class; $this->security_handler = new Smarty_Internal_Security_Handler($this); $this->security = true; - } - else { + } else { throw new Exception('Property security_class is not defined'); } } /** - * Disable security - */ - public function disableSecurity() { + * Disable security + */ + public function disableSecurity() + { $this->security = true; } /** - * Set template directory - * - * @param string $ |array $template_dir folder(s) of template sorces - */ - public function setTemplateDir($template_dir) { + * Set template directory + * + * @param string $ |array $template_dir folder(s) of template sorces + */ + public function setTemplateDir($template_dir) + { $this->template_dir = (array)$template_dir; return; } /** - * Adds template directory(s) to existing ones - * - * @param string $ |array $template_dir folder(s) of template sources - */ - public function addTemplateDir($template_dir) { + * Adds template directory(s) to existing ones + * + * @param string $ |array $template_dir folder(s) of template sources + */ + public function addTemplateDir($template_dir) + { $this->template_dir = array_merge((array)$this->template_dir, (array)$template_dir); $this->template_dir = array_unique($this->template_dir); return; } - /** - * Check if a template resource exists - * - * @param string $resource_name template name - * @return boolean status - */ - function templateExists($resource_name) { + * Check if a template resource exists + * + * @param string $resource_name template name + * @return boolean status + */ + function templateExists($resource_name) + { // create template object $tpl = new $this->template_class($resource_name, $this); // check if it does exists @@ -477,17 +507,18 @@ class Smarty extends Smarty_Internal_Data { } /** - * Takes unknown classes and loads plugin files for them - * class name format: Smarty_PluginType_PluginName - * plugin filename format: plugintype.pluginname.php - * - * @param string $plugin_name class plugin name to load - * @return string |boolean filepath of loaded file or false - */ - public function loadPlugin($plugin_name, $check = true) { + * Takes unknown classes and loads plugin files for them + * class name format: Smarty_PluginType_PluginName + * plugin filename format: plugintype.pluginname.php + * + * @param string $plugin_name class plugin name to load + * @return string |boolean filepath of loaded file or false + */ + public function loadPlugin($plugin_name, $check = true) + { // if function or class exists, exit silently (already loaded) if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) - return true; + return true; // Plugin name is expected to be: Smarty_[Type]_[Name] $_plugin_name = strtolower($plugin_name); $_name_parts = explode('_', $_plugin_name, 3); @@ -502,8 +533,7 @@ class Smarty extends Smarty_Internal_Data { if (file_exists($file)) { require_once($file); return $file; - } - else { + } else { return false; } } @@ -525,13 +555,14 @@ class Smarty extends Smarty_Internal_Data { } /** - * load a filter of specified type and name - * - * @param string $type filter type - * @param string $name filter name - * @return bool - */ - function loadFilter($type, $name) { + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + * @return bool + */ + function loadFilter($type, $name) + { $_plugin = "smarty_{$type}filter_{$name}"; $_filter_name = $_plugin; if ($this->loadPlugin($_plugin)) { @@ -547,72 +578,74 @@ class Smarty extends Smarty_Internal_Data { } /** - * Sets the exception handler for Smarty. - * - * @param mixed $handler function name or array with object/method names - * @return string previous exception handler - */ - public function setExceptionHandler($handler) { + * Sets the exception handler for Smarty. + * + * @param mixed $handler function name or array with object/method names + * @return string previous exception handler + */ + public function setExceptionHandler($handler) + { $this->exception_handler = $handler; return set_exception_handler($handler); } /** - * trigger Smarty error - * - * @param string $error_msg - * @param integer $error_type - */ - public function trigger_error($error_msg, $error_type = E_USER_WARNING) { + * trigger Smarty error + * + * @param string $error_msg + * @param integer $error_type + */ + public function trigger_error($error_msg, $error_type = E_USER_WARNING) + { throw new Exception("Smarty error: $error_msg"); } /** - * Return internal filter name - * - * @param callback $function_name - */ - public function _get_filter_name($function_name) { + * Return internal filter name + * + * @param callback $function_name + */ + public function _get_filter_name($function_name) + { if (is_array($function_name)) { $_class_name = (is_object($function_name[0]) ? get_class($function_name[0]) : $function_name[0]); return $_class_name . '_' . $function_name[1]; - } - else { + } else { return $function_name; } } /** - * Adds directory of plugin files - * - * @param object $smarty - * @param string $ |array $ plugins folder - * @return - */ - function addPluginsDir($plugins_dir) { + * Adds directory of plugin files + * + * @param object $smarty + * @param string $ |array $ plugins folder + * @return + */ + function addPluginsDir($plugins_dir) + { $this->plugins_dir = array_merge((array)$this->plugins_dir, (array)$plugins_dir); $this->plugins_dir = array_unique($this->plugins_dir); return; } /** - * Returns a single or all global variables - * - * @param object $smarty - * @param string $varname variable name or null - * @return string variable value or or array of variables - */ - function getGlobal($varname = null) { + * Returns a single or all global variables + * + * @param object $smarty + * @param string $varname variable name or null + * @return string variable value or or array of variables + */ + function getGlobal($varname = null) + { if (isset($varname)) { if (isset($this->global_tpl_vars[$varname])) { return $this->global_tpl_vars[$varname]->value; - } - else { + } else { return ''; } - } - else { + } else { $_result = array(); foreach ($this->global_tpl_vars AS $key => $var) { $_result[$key] = $var->value; @@ -622,47 +655,51 @@ class Smarty extends Smarty_Internal_Data { } /** - * return a reference to a registered object - * - * @param string $name object name - * @return object - */ - function getRegisteredObject($name) { + * return a reference to a registered object + * + * @param string $name object name + * @return object + */ + function getRegisteredObject($name) + { if (!isset($this->registered_objects[$name])) - throw new Exception("'$name' is not a registered object"); + throw new Exception("'$name' is not a registered object"); if (!is_object($this->registered_objects[$name][0])) - throw new Exception("registered '$name' is not an object"); + throw new Exception("registered '$name' is not an object"); return $this->registered_objects[$name][0]; } /** - * return name of debugging template - * - * @return string - */ - function getDebugTemplate() { + * return name of debugging template + * + * @return string + */ + function getDebugTemplate() + { return $this->debug_tpl; } /** - * set the debug template - * - * @param string $tpl_name - * @return bool - */ - function setDebugTemplate($tpl_name) { + * set the debug template + * + * @param string $tpl_name + * @return bool + */ + function setDebugTemplate($tpl_name) + { return $this->debug_tpl = $tpl_name; } /** - * lazy loads (valid) property objects - * - * @param string $name property name - */ - public function __get($name) { - if(in_array($name, array('register', 'unregister', 'utility', 'cache'))) { + * lazy loads (valid) property objects + * + * @param string $name property name + */ + public function __get($name) + { + if (in_array($name, array('register', 'unregister', 'utility', 'cache'))) { $class = "Smarty_Internal_" . ucfirst($name); $this->$name = new $class($this); return $this->$name; @@ -675,17 +712,18 @@ class Smarty extends Smarty_Internal_Data { } /** - * Takes unknown class methods and lazy loads sysplugin files for them - * class name format: Smarty_Method_MethodName - * plugin filename format: method.methodname.php - * - * @param string $name unknown methode name - * @param array $args aurgument array - */ - public function __call($name, $args) { + * Takes unknown class methods and lazy loads sysplugin files for them + * class name format: Smarty_Method_MethodName + * plugin filename format: method.methodname.php + * + * @param string $name unknown methode name + * @param array $args aurgument array + */ + public function __call($name, $args) + { static $camel_func; - if(!isset($camel_func)) - $camel_func = create_function('$c', 'return "_" . strtolower($c[1]);'); + if (!isset($camel_func)) + $camel_func = create_function('$c', 'return "_" . strtolower($c[1]);'); // PHP4 call to constructor? if (strtolower($name) == 'smarty') { throw new Exception('Please use parent::__construct() to call parent constuctor'); @@ -693,23 +731,23 @@ class Smarty extends Smarty_Internal_Data { } // see if this is a set/get for a property $first3 = strtolower(substr($name, 0, 3)); - if(in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') { + if (in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') { // try to keep case correct for future PHP 6.0 case-sensitive class methods // lcfirst() not available < PHP 5.3.0, so improvise $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); // convert camel case to underscored name $property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name); - if(!property_exists($this, $property_name)) { + if (!property_exists($this, $property_name)) { throw new Exception("property '$property_name' does not exist."); return false; } - if($first3 == 'get') - return $this->$property_name; + if ($first3 == 'get') + return $this->$property_name; else - return $this->$property_name = $args[0]; + return $this->$property_name = $args[0]; } // Smarty Backward Compatible wrapper - if(!isset($this->wrapper)) { + if (!isset($this->wrapper)) { $this->wrapper = new Smarty_Internal_Wrapper($this); } return $this->wrapper->convert($name, $args); @@ -731,7 +769,8 @@ class Smarty extends Smarty_Internal_Data { } } -function smartyAutoload($class) { +function smartyAutoload($class) +{ $_class = strtolower($class); if (substr($_class, 0, 16) === 'smarty_internal_' || $_class == 'smarty_security') { include SMARTY_SYSPLUGINS_DIR . $_class . '.php';