diff --git a/README b/README index c7215ab1..9304219b 100644 --- a/README +++ b/README @@ -120,7 +120,7 @@ $smarty->unregisterObject($object_name) $smarty->unregisterFilter($type, $function_name) $smarty->unregisterResource($resource_type) -$smarty->compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) +$smarty->compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) $smarty->clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) $smarty->testInstall() diff --git a/SMARTY_3.1_NOTES.txt b/SMARTY_3.1_NOTES.txt index e56e56f6..57709f0d 100644 --- a/SMARTY_3.1_NOTES.txt +++ b/SMARTY_3.1_NOTES.txt @@ -199,7 +199,7 @@ Relative paths are available with {include file="..."} and $smarty->fetch('./foo.tpl') cannot be relative to a template, an exception is thrown. - Adressing a specific $template_dir + Addressing a specific $template_dir Smarty 3.1 introduces the $template_dir index notation. $smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"} diff --git a/change_log.txt b/change_log.txt index 0abde7bd..a4a5e290 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,10 +1,43 @@ -==== Smarty-3.1.13 ===== +===== trunk ===== +27.06.2013 +- bugfix removed PHP 5.5 deprecated preg_replace /e option in modifier capitalize (forum topic 24389) + +17.06.2013 +- fixed spelling in sources and documentation (from smarty-developers forum Veres Lajos) +- enhancement added constant SMARTY::CLEAR_EXPIRED for the change of 26.05.2013 (forum topic 24310) +- bugfix added smarty_security.php to composer.json (Issue 135) + +26.05.2013 +- enhancement an expire_time of -1 in clearCache() and clearAllCache() will delete outdated cache files + by their individual cache_lifetime used at creation (forum topic 24310) + +21.05.2013 +- bugfix modifier strip_tags:true was compiled into wrong code (Forum Topic 24287) +- bugfix /n after ?> in Smarty.class.php did start output buffering (Issue 138) + +25.04.2013 +- bugfix escape and wordrap modifier could be compiled into wrong code when used in {nocache}{/nocache} + section but caching is disabled (Forum Topic 24260) + +05.04.2013 +- bugfix post filter must not run when compiling inheritance child blocks (Forum Topic 24094) +- bugfix after the fix for Issue #130 compiler exceptions got double escaped (Forum Topic 24199) + +28.02.2013 +- bugfix nocache blocks could be lost when using CACHING_LIFETIME_SAVED (Issue #133) +- bugfix Compile ID gets nulled when compiling child blocks (Issue #134) + + +24.01.2013 +- bugfix wrong tag type in smarty_internal_templatecompilerbase.php could cause wrong plugin search order (Forum Topic 24028) + +===== Smarty-3.1.13 ===== 13.01.2013 - enhancement allow to disable exception message escaping by SmartyException::$escape = false; (Issue #130) 09.01.2013 -- bugfix compilation did fail when a prefilter did modify an {extends} tag (Forum Topic 23966) +- bugfix compilation did fail when a prefilter did modify an {extends} tag c - bugfix template inheritance could fail if nested {block} tags in childs did contain {$smarty.block.child} (Issue #127) - bugfix template inheritance could fail if {block} tags in childs did have similar name as used plugins (Issue #128) - added abstract method declaration doCompile() in Smarty_Internal_TemplateCompilerBase (Forum Topic 23969) @@ -418,7 +451,7 @@ 03/09/2011 - bugfix createTemplate() must default to cache_id and compile_id of Smarty object - bugfix Smarty_CacheResource_KeyValueStore must include $source->uid in cache filepath to keep templates with same - name but different folders seperated + name but different folders separated - added cacheresource.apc.php example in demo folder 02/09/2011 @@ -609,7 +642,7 @@ - changed ./ and ../ behaviour 14/02/2011 -- added {block ... hide} option to supress block if no child is defined +- added {block ... hide} option to suppress block if no child is defined 13/02/2011 - update handling of recursive subtemplate calls @@ -723,7 +756,7 @@ - bugfix on compiler object destruction. compiler_object property was by mistake unset. 09/03/2011 --bugfix a variable filter should run before modifers on an output tag (see change of 23/07/2010) +-bugfix a variable filter should run before modifiers on an output tag (see change of 23/07/2010) 08/03/2011 - bugfix loading config file without section should load only defaults @@ -1027,10 +1060,10 @@ request_use_auto_globals - bugfix passing scope attributes in doublequoted strings did not work at {include} {assign} and {append} 25/07/2010 -- another bugfix of change from 23/07/2010 when compiling modifer +- another bugfix of change from 23/07/2010 when compiling modifier 24/07/2010 -- bugfix of change from 23/07/2010 when compiling modifer +- bugfix of change from 23/07/2010 when compiling modifier 23/07/2010 - changed execution order. A variable filter does now run before modifiers on output of variables @@ -1337,7 +1370,7 @@ request_use_auto_globals - bugfix on {if} tags 01/12/2010 -- changed back modifer handling in parser. Some restrictions still apply: +- changed back modifier handling in parser. Some restrictions still apply: if modifiers are used in side {if...} expression or in mathematical expressions parentheses must be used. - bugfix the {function..} tag did not accept the name attribute in double quotes @@ -1949,7 +1982,7 @@ NOTICE: existing compiled template and cache files must be deleted - fixed exceptions in function plugins - fixed notice error in Smarty.class.php - allow chained objects to span multiple lines -- fixed error in modifers +- fixed error in modifiers 03/20/2009 - moved /plugins folder into /libs folder @@ -1957,7 +1990,7 @@ NOTICE: existing compiled template and cache files must be deleted - autoappend a directory separator if the xxxxx_dir definition have no trailing one 03/19/2009 -- allow array definition as modifer parameter +- allow array definition as modifier parameter - changed modifier to use multi byte string funktions. 03/17/2009 diff --git a/demo/plugins/resource.mysqls.php b/demo/plugins/resource.mysqls.php index f9fe1c2f..e22bed0a 100644 --- a/demo/plugins/resource.mysqls.php +++ b/demo/plugins/resource.mysqls.php @@ -7,7 +7,7 @@ * MySQL as the storage resource for Smarty's templates and configs. * * Note that this MySQL implementation fetches the source and timestamps in - * a single database query, instead of two seperate like resource.mysql.php does. + * a single database query, instead of two separate like resource.mysql.php does. * * Table definition: *
CREATE TABLE IF NOT EXISTS `templates` ( diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index af99a23c..6c452fde 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -128,6 +128,11 @@ class Smarty extends Smarty_Internal_TemplateBase { const CACHING_OFF = 0; const CACHING_LIFETIME_CURRENT = 1; const CACHING_LIFETIME_SAVED = 2; + /** + * define constant for clearing cache files be saved expiration datees + */ + const CLEAR_EXPIRED = -1; + /** * define compile check modes */ @@ -1323,9 +1328,9 @@ class Smarty extends Smarty_Internal_TemplateBase { * @param int $max_errors * @return integer number of template files recompiled */ - public function compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) + public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) { - return Smarty_Internal_Utility::compileAllTemplates($extention, $force_compile, $time_limit, $max_errors, $this); + return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this); } /** @@ -1337,9 +1342,9 @@ class Smarty extends Smarty_Internal_TemplateBase { * @param int $max_errors * @return integer number of template files recompiled */ - public function compileAllConfig($extention = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) + public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) { - return Smarty_Internal_Utility::compileAllConfig($extention, $force_compile, $time_limit, $max_errors, $this); + return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this); } /** @@ -1525,4 +1530,4 @@ function smartyAutoload($class) } } -?> +?> \ No newline at end of file diff --git a/libs/plugins/modifier.capitalize.php b/libs/plugins/modifier.capitalize.php index a78e3632..580e3d5c 100644 --- a/libs/plugins/modifier.capitalize.php +++ b/libs/plugins/modifier.capitalize.php @@ -30,7 +30,7 @@ function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = fals $upper_string = mb_convert_case( $string, MB_CASE_TITLE, Smarty::$_CHARSET ); } else { // uppercase word breaks - $upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!eS" . Smarty::$_UTF8_MODIFIER, "stripslashes('\\1').mb_convert_case(stripslashes('\\2'),MB_CASE_UPPER, '" . addslashes(Smarty::$_CHARSET) . "')", $string); + $upper_string = preg_replace_callback("!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER, create_function ('$matches', 'return stripslashes($matches[1]).mb_convert_case(stripslashes($matches[2]),MB_CASE_UPPER, "' . addslashes(Smarty::$_CHARSET) . '");'), $string); } // check uc_digits case if (!$uc_digits) { @@ -40,7 +40,7 @@ function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = fals } } } - $upper_string = preg_replace("!((^|\s)['\"])(\w)!e" . Smarty::$_UTF8_MODIFIER, "stripslashes('\\1').mb_convert_case(stripslashes('\\3'),MB_CASE_UPPER, '" . addslashes(Smarty::$_CHARSET) . "')", $upper_string); + $upper_string = preg_replace_callback("!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, create_function ('$matches', 'return stripslashes($matches[1]).mb_convert_case(stripslashes($matches[3]),MB_CASE_UPPER, "' . addslashes(Smarty::$_CHARSET) . '");'), $upper_string); return $upper_string; } @@ -49,7 +49,7 @@ function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = fals $string = strtolower($string); } // uppercase (including hyphenated words) - $upper_string = preg_replace("!(^|[^\p{L}'])([\p{Ll}])!eS" . Smarty::$_UTF8_MODIFIER, "stripslashes('\\1').ucfirst(stripslashes('\\2'))", $string); + $upper_string = preg_replace_callback("!(^|[^\p{L}'])([\p{Ll}])!S" . Smarty::$_UTF8_MODIFIER, create_function ('$matches', 'return stripslashes($matches[1]).ucfirst(stripslashes($matches[2]));'), $string); // check uc_digits case if (!$uc_digits) { if (preg_match_all("!\b([\p{L}]*[\p{N}]+[\p{L}]*)\b!" . Smarty::$_UTF8_MODIFIER, $string, $matches, PREG_OFFSET_CAPTURE)) { @@ -58,7 +58,7 @@ function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = fals } } } - $upper_string = preg_replace("!((^|\s)['\"])(\w)!e" . Smarty::$_UTF8_MODIFIER, "stripslashes('\\1').strtoupper(stripslashes('\\3'))", $upper_string); + $upper_string = preg_replace_callback("!((^|\s)['\"])(\w)!" . Smarty::$_UTF8_MODIFIER, create_function ('$matches', 'return stripslashes($matches[1]).ucfirst(stripslashes($matches[3]));'), $upper_string); return $upper_string; } diff --git a/libs/plugins/modifiercompiler.escape.php b/libs/plugins/modifiercompiler.escape.php index f50028bd..f5b4f433 100644 --- a/libs/plugins/modifiercompiler.escape.php +++ b/libs/plugins/modifiercompiler.escape.php @@ -112,7 +112,7 @@ function smarty_modifiercompiler_escape($params, $compiler) } // could not optimize |escape call, so fallback to regular plugin - if ($compiler->tag_nocache | $compiler->nocache) { + if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) { $compiler->template->required_plugins['nocache']['escape']['modifier']['file'] = SMARTY_PLUGINS_DIR .'modifier.escape.php'; $compiler->template->required_plugins['nocache']['escape']['modifier']['function'] = 'smarty_modifier_escape'; } else { diff --git a/libs/plugins/modifiercompiler.strip_tags.php b/libs/plugins/modifiercompiler.strip_tags.php index 296a3a2d..68a9e75d 100644 --- a/libs/plugins/modifiercompiler.strip_tags.php +++ b/libs/plugins/modifiercompiler.strip_tags.php @@ -20,14 +20,9 @@ */ function smarty_modifiercompiler_strip_tags($params, $compiler) { - if (!isset($params[1])) { - $params[1] = true; - } - if ($params[1] === true) { - return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})"; + if (!isset($params[1]) || $params[1] === true || trim($params[1],'"') == 'true') { + return "preg_replace('!<[^>]*?>!', ' ', {$params[0]})"; } else { return 'strip_tags(' . $params[0] . ')'; } } - -?> \ No newline at end of file diff --git a/libs/plugins/modifiercompiler.wordwrap.php b/libs/plugins/modifiercompiler.wordwrap.php index f6845ad3..9f21e224 100644 --- a/libs/plugins/modifiercompiler.wordwrap.php +++ b/libs/plugins/modifiercompiler.wordwrap.php @@ -31,7 +31,7 @@ function smarty_modifiercompiler_wordwrap($params, $compiler) } $function = 'wordwrap'; if (Smarty::$_MBSTRING) { - if ($compiler->tag_nocache | $compiler->nocache) { + if ($compiler->template->caching && ($compiler->tag_nocache | $compiler->nocache)) { $compiler->template->required_plugins['nocache']['wordwrap']['modifier']['file'] = SMARTY_PLUGINS_DIR .'shared.mb_wordwrap.php'; $compiler->template->required_plugins['nocache']['wordwrap']['modifier']['function'] = 'smarty_mb_wordwrap'; } else { diff --git a/libs/sysplugins/smarty_cacheresource.php b/libs/sysplugins/smarty_cacheresource.php index ca18add5..a6852998 100644 --- a/libs/sysplugins/smarty_cacheresource.php +++ b/libs/sysplugins/smarty_cacheresource.php @@ -224,7 +224,7 @@ class Smarty_Template_Cached { public $timestamp = false; /** - * Source Existance + * Source Existence * @var boolean */ public $exists = false; diff --git a/libs/sysplugins/smarty_internal_cacheresource_file.php b/libs/sysplugins/smarty_internal_cacheresource_file.php index 04194b39..fca897d9 100644 --- a/libs/sysplugins/smarty_internal_cacheresource_file.php +++ b/libs/sysplugins/smarty_internal_cacheresource_file.php @@ -1,266 +1,275 @@ source->filepath); - $_cache_id = isset($_template->cache_id) ? preg_replace('![^\w\|]+!', '_', $_template->cache_id) : null; - $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; - $_filepath = $_template->source->uid; - // if use_sub_dirs, break file into directories - if ($_template->smarty->use_sub_dirs) { - $_filepath = substr($_filepath, 0, 2) . DS + * This class does contain all necessary methods for the HTML cache on file system + * + * Implements the file system as resource for the HTML cache Version ussing nocache inserts. + * + * @package Smarty + * @subpackage Cacher + */ + class Smarty_Internal_CacheResource_File extends Smarty_CacheResource { + + /** + * populate Cached Object with meta data from Resource + * + * @param Smarty_Template_Cached $cached cached object + * @param Smarty_Internal_Template $_template template object + * @return void + */ + public function populate(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template) + { + $_source_file_path = str_replace(':', '.', $_template->source->filepath); + $_cache_id = isset($_template->cache_id) ? preg_replace('![^\w\|]+!', '_', $_template->cache_id) : null; + $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; + $_filepath = $_template->source->uid; + // if use_sub_dirs, break file into directories + if ($_template->smarty->use_sub_dirs) { + $_filepath = substr($_filepath, 0, 2) . DS . substr($_filepath, 2, 2) . DS . substr($_filepath, 4, 2) . DS . $_filepath; - } - $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; - if (isset($_cache_id)) { - $_cache_id = str_replace('|', $_compile_dir_sep, $_cache_id) . $_compile_dir_sep; - } else { - $_cache_id = ''; - } - if (isset($_compile_id)) { - $_compile_id = $_compile_id . $_compile_dir_sep; - } else { - $_compile_id = ''; - } - $_cache_dir = $_template->smarty->getCacheDir(); - if ($_template->smarty->cache_locking) { - // create locking file name - // relative file name? - if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_cache_dir)) { - $_lock_dir = rtrim(getcwd(), '/\\') . DS . $_cache_dir; + } + $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; + if (isset($_cache_id)) { + $_cache_id = str_replace('|', $_compile_dir_sep, $_cache_id) . $_compile_dir_sep; } else { - $_lock_dir = $_cache_dir; + $_cache_id = ''; } - $cached->lock_id = $_lock_dir.sha1($_cache_id.$_compile_id.$_template->source->uid).'.lock'; - } - $cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) . '.php'; - $cached->timestamp = @filemtime($cached->filepath); - $cached->exists = !!$cached->timestamp; - } - - /** - * populate Cached Object with timestamp and exists from Resource - * - * @param Smarty_Template_Cached $cached cached object - * @return void - */ - public function populateTimestamp(Smarty_Template_Cached $cached) - { - $cached->timestamp = @filemtime($cached->filepath); - $cached->exists = !!$cached->timestamp; - } - - /** - * Read the cached template and process its header - * - * @param Smarty_Internal_Template $_template template object - * @param Smarty_Template_Cached $cached cached object - * @return booelan true or false if the cached content does not exist - */ - public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null) - { - $_smarty_tpl = $_template; - return @include $_template->cached->filepath; - } - - /** - * Write the rendered template output to cache - * - * @param Smarty_Internal_Template $_template template object - * @param string $content content to cache - * @return boolean success - */ - public function writeCachedContent(Smarty_Internal_Template $_template, $content) - { - if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) { - $_template->cached->timestamp = @filemtime($_template->cached->filepath); - $_template->cached->exists = !!$_template->cached->timestamp; - if ($_template->cached->exists) { - return true; - } - } - return false; - } - - /** - * Empty cache - * - * @param Smarty_Internal_Template $_template template object - * @param integer $exp_time expiration time (number of seconds, not timestamp) - * @return integer number of cache files deleted - */ - public function clearAll(Smarty $smarty, $exp_time = null) - { - return $this->clear($smarty, null, null, null, $exp_time); - } - - /** - * Empty cache for a specific template - * - * @param Smarty $_template template object - * @param string $resource_name template name - * @param string $cache_id cache id - * @param string $compile_id compile id - * @param integer $exp_time expiration time (number of seconds, not timestamp) - * @return integer number of cache files deleted - */ - public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) - { - $_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null; - $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; - $_dir_sep = $smarty->use_sub_dirs ? '/' : '^'; - $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0; - $_dir = $smarty->getCacheDir(); - $_dir_length = strlen($_dir); - if (isset($_cache_id)) { - $_cache_id_parts = explode('|', $_cache_id); - $_cache_id_parts_count = count($_cache_id_parts); - if ($smarty->use_sub_dirs) { - foreach ($_cache_id_parts as $id_part) { - $_dir .= $id_part . DS; - } - } - } - if (isset($resource_name)) { - $_save_stat = $smarty->caching; - $smarty->caching = true; - $tpl = new $smarty->template_class($resource_name, $smarty); - $smarty->caching = $_save_stat; - - // remove from template cache - $tpl->source; // have the template registered before unset() - if ($smarty->allow_ambiguous_resources) { - $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; + if (isset($_compile_id)) { + $_compile_id = $_compile_id . $_compile_dir_sep; } else { - $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; + $_compile_id = ''; } - if (isset($_templateId[150])) { - $_templateId = sha1($_templateId); - } - unset($smarty->template_objects[$_templateId]); - - if ($tpl->source->exists) { - $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath)); - } else { - return 0; - } - } - $_count = 0; - $_time = time(); - if (file_exists($_dir)) { - $_cacheDirs = new RecursiveDirectoryIterator($_dir); - $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST); - foreach ($_cache as $_file) { - if (substr(basename($_file->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; - // directory ? - if ($_file->isDir()) { - if (!$_cache->isDot()) { - // delete folder if empty - @rmdir($_file->getPathname()); - } + $_cache_dir = $_template->smarty->getCacheDir(); + if ($_template->smarty->cache_locking) { + // create locking file name + // relative file name? + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_cache_dir)) { + $_lock_dir = rtrim(getcwd(), '/\\') . DS . $_cache_dir; } else { - $_parts = explode($_dir_sep, str_replace('\\', '/', substr((string)$_file, $_dir_length))); - $_parts_count = count($_parts); - // check name - if (isset($resource_name)) { - if ($_parts[$_parts_count-1] != $_resourcename_parts) { - continue; - } - } - // check compile id - if (isset($_compile_id) && (!isset($_parts[$_parts_count-2 - $_compile_id_offset]) || $_parts[$_parts_count-2 - $_compile_id_offset] != $_compile_id)) { - continue; - } - // check cache id - if (isset($_cache_id)) { - // count of cache id parts - $_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset : $_parts_count - 1 - $_compile_id_offset; - if ($_parts_count < $_cache_id_parts_count) { - continue; - } - for ($i = 0; $i < $_cache_id_parts_count; $i++) { - if ($_parts[$i] != $_cache_id_parts[$i]) continue 2; - } - } - // expired ? - if (isset($exp_time) && $_time - @filemtime($_file) < $exp_time) { - continue; - } - $_count += @unlink((string) $_file) ? 1 : 0; + $_lock_dir = $_cache_dir; + } + $cached->lock_id = $_lock_dir.sha1($_cache_id.$_compile_id.$_template->source->uid).'.lock'; + } + $cached->filepath = $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($_source_file_path) . '.php'; + $cached->timestamp = @filemtime($cached->filepath); + $cached->exists = !!$cached->timestamp; + } + + /** + * populate Cached Object with timestamp and exists from Resource + * + * @param Smarty_Template_Cached $cached cached object + * @return void + */ + public function populateTimestamp(Smarty_Template_Cached $cached) + { + $cached->timestamp = @filemtime($cached->filepath); + $cached->exists = !!$cached->timestamp; + } + + /** + * Read the cached template and process its header + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty_Template_Cached $cached cached object + * @return booelan true or false if the cached content does not exist + */ + public function process(Smarty_Internal_Template $_template, Smarty_Template_Cached $cached=null) + { + $_smarty_tpl = $_template; + return @include $_template->cached->filepath; + } + + /** + * Write the rendered template output to cache + * + * @param Smarty_Internal_Template $_template template object + * @param string $content content to cache + * @return boolean success + */ + public function writeCachedContent(Smarty_Internal_Template $_template, $content) + { + if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) { + $_template->cached->timestamp = @filemtime($_template->cached->filepath); + $_template->cached->exists = !!$_template->cached->timestamp; + if ($_template->cached->exists) { + return true; } } + return false; } - return $_count; - } - /** - * Check is cache is locked for this template - * - * @param Smarty $smarty Smarty object - * @param Smarty_Template_Cached $cached cached object - * @return booelan true or false if cache is locked - */ - public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached) - { - if (version_compare(PHP_VERSION, '5.3.0', '>=')) { - clearstatcache(true, $cached->lock_id); - } else { - clearstatcache(); + /** + * Empty cache + * + * @param Smarty_Internal_Template $_template template object + * @param integer $exp_time expiration time (number of seconds, not timestamp) + * @return integer number of cache files deleted + */ + public function clearAll(Smarty $smarty, $exp_time = null) + { + return $this->clear($smarty, null, null, null, $exp_time); } - $t = @filemtime($cached->lock_id); - return $t && (time() - $t < $smarty->locking_timeout); - } - /** - * Lock cache for this template - * - * @param Smarty $smarty Smarty object - * @param Smarty_Template_Cached $cached cached object - */ - public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached) - { - $cached->is_locked = true; - touch($cached->lock_id); - } + /** + * Empty cache for a specific template + * + * @param Smarty $_template template object + * @param string $resource_name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer $exp_time expiration time (number of seconds, not timestamp) + * @return integer number of cache files deleted + */ + public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) + { + $_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null; + $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; + $_dir_sep = $smarty->use_sub_dirs ? '/' : '^'; + $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0; + $_dir = $smarty->getCacheDir(); + $_dir_length = strlen($_dir); + if (isset($_cache_id)) { + $_cache_id_parts = explode('|', $_cache_id); + $_cache_id_parts_count = count($_cache_id_parts); + if ($smarty->use_sub_dirs) { + foreach ($_cache_id_parts as $id_part) { + $_dir .= $id_part . DS; + } + } + } + if (isset($resource_name)) { + $_save_stat = $smarty->caching; + $smarty->caching = true; + $tpl = new $smarty->template_class($resource_name, $smarty); + $smarty->caching = $_save_stat; - /** - * Unlock cache for this template - * - * @param Smarty $smarty Smarty object - * @param Smarty_Template_Cached $cached cached object - */ - public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached) - { - $cached->is_locked = false; - @unlink($cached->lock_id); + // remove from template cache + $tpl->source; // have the template registered before unset() + if ($smarty->allow_ambiguous_resources) { + $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; + } else { + $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; + } + if (isset($_templateId[150])) { + $_templateId = sha1($_templateId); + } + unset($smarty->template_objects[$_templateId]); + + if ($tpl->source->exists) { + $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath)); + } else { + return 0; + } + } + $_count = 0; + $_time = time(); + if (file_exists($_dir)) { + $_cacheDirs = new RecursiveDirectoryIterator($_dir); + $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($_cache as $_file) { + if (substr(basename($_file->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; + // directory ? + if ($_file->isDir()) { + if (!$_cache->isDot()) { + // delete folder if empty + @rmdir($_file->getPathname()); + } + } else { + $_parts = explode($_dir_sep, str_replace('\\', '/', substr((string)$_file, $_dir_length))); + $_parts_count = count($_parts); + // check name + if (isset($resource_name)) { + if ($_parts[$_parts_count-1] != $_resourcename_parts) { + continue; + } + } + // check compile id + if (isset($_compile_id) && (!isset($_parts[$_parts_count-2 - $_compile_id_offset]) || $_parts[$_parts_count-2 - $_compile_id_offset] != $_compile_id)) { + continue; + } + // check cache id + if (isset($_cache_id)) { + // count of cache id parts + $_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset : $_parts_count - 1 - $_compile_id_offset; + if ($_parts_count < $_cache_id_parts_count) { + continue; + } + for ($i = 0; $i < $_cache_id_parts_count; $i++) { + if ($_parts[$i] != $_cache_id_parts[$i]) continue 2; + } + } + // expired ? + if (isset($exp_time)) { + if ($exp_time < 0) { + preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_file), $match); + if ($_time < (@filemtime($_file) + $match[1])) { + continue; + } + } else { + if ($_time - @filemtime($_file) < $exp_time) { + continue; + } + } + } + $_count += @unlink((string) $_file) ? 1 : 0; + } + } + } + return $_count; + } + + /** + * Check is cache is locked for this template + * + * @param Smarty $smarty Smarty object + * @param Smarty_Template_Cached $cached cached object + * @return booelan true or false if cache is locked + */ + public function hasLock(Smarty $smarty, Smarty_Template_Cached $cached) + { + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + clearstatcache(true, $cached->lock_id); + } else { + clearstatcache(); + } + $t = @filemtime($cached->lock_id); + return $t && (time() - $t < $smarty->locking_timeout); + } + + /** + * Lock cache for this template + * + * @param Smarty $smarty Smarty object + * @param Smarty_Template_Cached $cached cached object + */ + public function acquireLock(Smarty $smarty, Smarty_Template_Cached $cached) + { + $cached->is_locked = true; + touch($cached->lock_id); + } + + /** + * Unlock cache for this template + * + * @param Smarty $smarty Smarty object + * @param Smarty_Template_Cached $cached cached object + */ + public function releaseLock(Smarty $smarty, Smarty_Template_Cached $cached) + { + $cached->is_locked = false; + @unlink($cached->lock_id); + } } -} ?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_compile_block.php b/libs/sysplugins/smarty_internal_compile_block.php index f760e551..847b04a9 100644 --- a/libs/sysplugins/smarty_internal_compile_block.php +++ b/libs/sysplugins/smarty_internal_compile_block.php @@ -84,7 +84,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { $al = ''; } if (0 == preg_match("!({$_ldl}{$al}block\s+)(name=)?(\w+|'.*'|\".*\")(\s*?)?((append|prepend|nocache)?(\s*)?(hide)?)?(\s*{$_rdl})!", $block_tag, $_match)) { - $error_text = 'Syntax Error in template "' . $template->source->filepath . '" "' . htmlspecialchars($block_tag) . '" illegal options'; + $error_text = 'Syntax Error in template "' . $template->source->filepath . '" "' . $block_tag . '" illegal options'; throw new SmartyCompilerException($error_text); } else { $_name = trim($_match[3], '\'"'); @@ -179,7 +179,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { return ''; } $_tpl = new Smarty_Internal_template('string:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id, - $compiler->template->compile_id = null, $compiler->template->caching, $compiler->template->cache_lifetime); + $compiler->template->compile_id, $compiler->template->caching, $compiler->template->cache_lifetime); $_tpl->variable_filters = $compiler->template->variable_filters; $_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash']; $_tpl->source->filepath = $compiler->template->block_data[$_name]['file']; @@ -190,6 +190,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { $_tpl->compiler->forceNocache = 1; } $_tpl->compiler->suppressHeader = true; + $_tpl->compiler->suppressFilter = true; $_tpl->compiler->suppressTemplatePropertyHeader = true; $_tpl->compiler->suppressMergedTemplates = true; if (strpos($compiler->template->block_data[$_name]['source'], '%%%%SMARTY_PARENT%%%%') !== false) { diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 29017edb..b6dd87fc 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -467,10 +467,15 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { } } if ($cache) { + // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc + if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && + $this->properties['cache_lifetime'] >= 0 && + (time() > ($this->cached->timestamp + $this->properties['cache_lifetime']))) { + $is_valid = false; + } $this->cached->valid = $is_valid; } else { - $this->mustCompile = !$is_valid; - } + $this->mustCompile = !$is_valid; } // store data in reusable Smarty_Template_Compiled if (!$cache) { $this->compiled->_properties = $properties; diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 11fc2144..8b5140cd 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -106,6 +106,12 @@ abstract class Smarty_Internal_TemplateCompilerBase { */ public $suppressTemplatePropertyHeader = false; + /** + * suppress pre and post filter + * @var bool + */ + public $suppressFilter = false; + /** * flag if compiled template file shall we written * @var bool @@ -184,7 +190,7 @@ abstract class Smarty_Internal_TemplateCompilerBase { // get template source $_content = $template->source->content; // run prefilter if required - if (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) { + if ((isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) && !$this->suppressFilter) { $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template); } // on empty template just return header @@ -209,13 +215,9 @@ abstract class Smarty_Internal_TemplateCompilerBase { foreach ($this->merged_templates as $code) { $merged_code .= $code; } - // run postfilter if required on merged code - if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { - $merged_code = Smarty_Internal_Filter_Handler::runFilter('post', $merged_code, $template); - } } // run postfilter if required on compiled template code - if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { + if ((isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) && !$this->suppressFilter) { $_compiled_code = Smarty_Internal_Filter_Handler::runFilter('post', $_compiled_code, $template); } if ($this->suppressTemplatePropertyHeader) { @@ -331,7 +333,7 @@ abstract class Smarty_Internal_TemplateCompilerBase { } // check plugins from plugins folder foreach ($this->smarty->plugin_search_order as $plugin_type) { - if ($plugin_type == Smarty::PLUGIN_BLOCK && $this->smarty->loadPlugin('smarty_compiler_' . $tag) && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this))) { + if ($plugin_type == Smarty::PLUGIN_COMPILER && $this->smarty->loadPlugin('smarty_compiler_' . $tag) && (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this))) { $plugin = 'smarty_compiler_' . $tag; if (is_callable($plugin)) { // convert arguments format for old compiler plugins @@ -605,7 +607,7 @@ abstract class Smarty_Internal_TemplateCompilerBase { $_output = addcslashes($content,'\'\\'); $_output = str_replace("^#^", "'", $_output); $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n"; - // make sure we include modifer plugins for nocache code + // make sure we include modifier plugins for nocache code foreach ($this->modifier_plugins as $plugin_name => $dummy) { if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) { $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier']; @@ -641,7 +643,7 @@ abstract class Smarty_Internal_TemplateCompilerBase { $line = $this->lex->line; } $match = preg_split("/\n/", $this->lex->data); - $error_text = 'Syntax Error in template "' . $this->template->source->filepath . '" on line ' . $line . ' "' . htmlspecialchars(trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1]))) . '" '; + $error_text = 'Syntax Error in template "' . $this->template->source->filepath . '" on line ' . $line . ' "' . trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" '; if (isset($args)) { // individual error message $error_text .= $args; diff --git a/libs/sysplugins/smarty_internal_utility.php b/libs/sysplugins/smarty_internal_utility.php index f19ca01f..0bec8db1 100644 --- a/libs/sysplugins/smarty_internal_utility.php +++ b/libs/sysplugins/smarty_internal_utility.php @@ -58,7 +58,7 @@ class Smarty_Internal_Utility { * @param Smarty $smarty Smarty instance * @return integer number of template files compiled */ - public static function compileAllTemplates($extention, $force_compile, $time_limit, $max_errors, Smarty $smarty) + public static function compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) { // switch off time limit if (function_exists('set_time_limit')) { @@ -74,7 +74,7 @@ class Smarty_Internal_Utility { foreach ($_compile as $_fileinfo) { $_file = $_fileinfo->getFilename(); if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; - if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; + if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { $_template_file = $_file; } else { @@ -122,7 +122,7 @@ class Smarty_Internal_Utility { * @param Smarty $smarty Smarty instance * @return integer number of config files compiled */ - public static function compileAllConfig($extention, $force_compile, $time_limit, $max_errors, Smarty $smarty) + public static function compileAllConfig($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) { // switch off time limit if (function_exists('set_time_limit')) { @@ -138,7 +138,7 @@ class Smarty_Internal_Utility { foreach ($_compile as $_fileinfo) { $_file = $_fileinfo->getFilename(); if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; - if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; + if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { $_config_file = $_file; } else { @@ -308,7 +308,7 @@ class Smarty_Internal_Utility { foreach($smarty->getTemplateDir() as $template_dir) { $_template_dir = $template_dir; $template_dir = realpath($template_dir); - // resolve include_path or fail existance + // resolve include_path or fail existence if (!$template_dir) { if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) { // try PHP include_path @@ -429,7 +429,7 @@ class Smarty_Internal_Utility { foreach($smarty->getPluginsDir() as $plugin_dir) { $_plugin_dir = $plugin_dir; $plugin_dir = realpath($plugin_dir); - // resolve include_path or fail existance + // resolve include_path or fail existence if (!$plugin_dir) { if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { // try PHP include_path @@ -561,7 +561,7 @@ class Smarty_Internal_Utility { foreach($smarty->getConfigDir() as $config_dir) { $_config_dir = $config_dir; $config_dir = realpath($config_dir); - // resolve include_path or fail existance + // resolve include_path or fail existence if (!$config_dir) { if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) { // try PHP include_path diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index 55f1497f..0a563dfc 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -584,7 +584,7 @@ abstract class Smarty_Resource { * @author Rodney Rehm * * @property integer $timestamp Source Timestamp - * @property boolean $exists Source Existance + * @property boolean $exists Source Existence * @property boolean $template Extended Template reference * @property string $content Source Content */ @@ -811,7 +811,7 @@ class Smarty_Template_Compiled { public $timestamp = null; /** - * Compiled Existance + * Compiled Existence * @var boolean */ public $exists = false; diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php index f8b31d96..58f33787 100644 --- a/libs/sysplugins/smarty_security.php +++ b/libs/sysplugins/smarty_security.php @@ -77,7 +77,7 @@ class Smarty_Security { 'nl2br', ); /** - * This is an array of trusted PHP modifers. + * This is an array of trusted PHP modifiers. * * If empty all modifiers are allowed. * To disable all modifier set $modifiers = null.