diff --git a/change_log.txt b/change_log.txt index 08189b93..982085f6 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,8 +1,4 @@ ===== 3.1.32 - dev === -22.10.2017 3.1.32-dev-28 - - bugfix Smarty version was not filled in header comment of compiled and cached files - - optimization replace internal Smarty::$ds property by DIRECTORY_SEPARATOR - 21.10.2017 - bugfix custom delimiters could fail since modification of version 3.1.32-dev-23 https://github.com/smarty-php/smarty/issues/394 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index c69715ea..e357bf27 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -100,7 +100,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.32-dev-28'; + const SMARTY_VERSION = '3.1.32-dev-27'; /** * define variable scopes */ @@ -544,6 +544,12 @@ class Smarty extends Smarty_Internal_TemplateBase * @var Smarty_Internal_Debug */ public $_debug = null; + /** + * Directory separator + * + * @var string + */ + public $ds = DIRECTORY_SEPARATOR; /** * template directory * @@ -936,7 +942,7 @@ class Smarty extends Smarty_Internal_TemplateBase $this->plugins_dir = (array)$this->plugins_dir; } foreach ($this->plugins_dir as $k => $v) { - $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true); + $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, "/\\") . $this->ds, true); } $this->_cache[ 'plugin_files' ] = array(); $this->_pluginsDirNormalized = true; @@ -1127,9 +1133,9 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function _realpath($path, $realpath = null) { - $nds = DIRECTORY_SEPARATOR === '/' ? '\\' : '/'; - // normalize DIRECTORY_SEPARATOR - $path = str_replace($nds, DIRECTORY_SEPARATOR, $path); + $nds = $this->ds == '/' ? '\\' : '/'; + // normalize $this->ds + $path = str_replace($nds, $this->ds, $path); preg_match('%^(?(?:[[:alpha:]]:[\\\\]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?(.*))$%u', $path, $parts); @@ -1138,13 +1144,13 @@ class Smarty extends Smarty_Internal_TemplateBase $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ]; } else { if ($realpath !== null && !$parts[ 'root' ]) { - $path = getcwd() . DIRECTORY_SEPARATOR . $path; + $path = getcwd() . $this->ds . $path; } } // remove noop 'DIRECTORY_SEPARATOR DIRECTORY_SEPARATOR' and 'DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR' patterns - $path = preg_replace('#([\\\\/]([.]?[\\\\/])+)#u', DIRECTORY_SEPARATOR, $path); + $path = preg_replace('#([\\\\/]([.]?[\\\\/])+)#u', $this->ds, $path); // resolve '..DIRECTORY_SEPARATOR' pattern, smallest first - if (strpos($path, '..' . DIRECTORY_SEPARATOR) != false && + if (strpos($path, '..' . $this->ds) != false && preg_match_all('#(([.]?[\\\\/])*([.][.])[\\\\/]([.]?[\\\\/])*)+#u', $path, $match) ) { $counts = array(); @@ -1155,7 +1161,7 @@ class Smarty extends Smarty_Internal_TemplateBase foreach ($counts as $count) { $path = preg_replace('#(([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count . '}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . '})(?=[^.])#u', - DIRECTORY_SEPARATOR, + $this->ds, $path); } } @@ -1401,7 +1407,7 @@ class Smarty extends Smarty_Internal_TemplateBase */ private function _normalizeDir($dirName, $dir) { - $this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . DIRECTORY_SEPARATOR, true); + $this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . $this->ds, true); if (!isset(Smarty::$_muted_directories[ $this->{$dirName} ])) { Smarty::$_muted_directories[ $this->{$dirName} ] = null; } @@ -1427,7 +1433,7 @@ class Smarty extends Smarty_Internal_TemplateBase } foreach ($dir as $k => $v) { if (!isset($processed[ $k ])) { - $dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true); + $dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . $this->ds, true); $processed[ $k ] = true; } } diff --git a/libs/sysplugins/smarty_internal_cacheresource_file.php b/libs/sysplugins/smarty_internal_cacheresource_file.php index 7abf6c05..5eb99fb1 100644 --- a/libs/sysplugins/smarty_internal_cacheresource_file.php +++ b/libs/sysplugins/smarty_internal_cacheresource_file.php @@ -29,14 +29,13 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource { $source = &$_template->source; $smarty = &$_template->smarty; - $_compile_dir_sep = $smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + $_compile_dir_sep = $smarty->use_sub_dirs ? $smarty->ds : '^'; $_filepath = sha1($source->uid . $smarty->_joined_template_dir); $cached->filepath = $smarty->getCacheDir(); if (isset($_template->cache_id)) { $cached->filepath .= preg_replace(array('![^\w|]+!', - '![|]+!'), - array('_', - $_compile_dir_sep), + '![|]+!'), array('_', + $_compile_dir_sep), $_template->cache_id) . $_compile_dir_sep; } if (isset($_template->compile_id)) { @@ -44,10 +43,9 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource } // if use_sub_dirs, break file into directories if ($smarty->use_sub_dirs) { - $cached->filepath .= $_filepath[ 0 ] . $_filepath[ 1 ] . DIRECTORY_SEPARATOR . $_filepath[ 2 ] . - $_filepath[ 3 ] . - DIRECTORY_SEPARATOR . - $_filepath[ 4 ] . $_filepath[ 5 ] . DIRECTORY_SEPARATOR; + $cached->filepath .= $_filepath[ 0 ] . $_filepath[ 1 ] . $smarty->ds . $_filepath[ 2 ] . $_filepath[ 3 ] . + $smarty->ds . + $_filepath[ 4 ] . $_filepath[ 5 ] . $smarty->ds; } $cached->filepath .= $_filepath; $basename = $source->handler->getBasename($source); @@ -88,8 +86,7 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource * * @return boolean true or false if the cached content does not exist */ - public function process(Smarty_Internal_Template $_smarty_tpl, - Smarty_Template_Cached $cached = null, + public function process(Smarty_Internal_Template $_smarty_tpl, Smarty_Template_Cached $cached = null, $update = false) { $_smarty_tpl->cached->valid = false; @@ -111,15 +108,14 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource */ public function writeCachedContent(Smarty_Internal_Template $_template, $content) { - if ($_template->smarty->ext->_writeFile->writeFile($_template->cached->filepath, - $content, + if ($_template->smarty->ext->_writeFile->writeFile($_template->cached->filepath, $content, $_template->smarty) === true ) { if (function_exists('opcache_invalidate') && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api"))) < 1 ) { opcache_invalidate($_template->cached->filepath, true); - } else if (function_exists('apc_compile_file')) { + } elseif (function_exists('apc_compile_file')) { apc_compile_file($_template->cached->filepath); } $cached = $_template->cached; diff --git a/libs/sysplugins/smarty_internal_compile_include_php.php b/libs/sysplugins/smarty_internal_compile_include_php.php index a799ea59..77586da8 100644 --- a/libs/sysplugins/smarty_internal_compile_include_php.php +++ b/libs/sysplugins/smarty_internal_compile_include_php.php @@ -57,6 +57,7 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase } // check and get attributes $_attr = $this->getAttributes($compiler, $args); + /** @var Smarty_Internal_Template $_smarty_tpl * used in evaluated code */ @@ -73,8 +74,8 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase $_dir = $compiler->smarty->trusted_dir; } if (!empty($_dir)) { - foreach ((array)$_dir as $_script_dir) { - $_path = $compiler->smarty->_realpath($_script_dir . DIRECTORY_SEPARATOR . $_file, true); + foreach ((array) $_dir as $_script_dir) { + $_path = $compiler->smarty->_realpath($_script_dir . $compiler->smarty->ds . $_file, true); if (file_exists($_path)) { $_filepath = $_path; break; @@ -85,9 +86,11 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase if ($_filepath == false) { $compiler->trigger_template_error("{include_php} file '{$_file}' is not readable", null, true); } + if (isset($compiler->smarty->security_policy)) { $compiler->smarty->security_policy->isTrustedPHPDir($_filepath); } + if (isset($_attr[ 'assign' ])) { // output will be stored in a smarty variable instead of being displayed $_assign = $_attr[ 'assign' ]; @@ -98,6 +101,7 @@ class Smarty_Internal_Compile_Include_Php extends Smarty_Internal_CompileBase $_once = ''; } } + if (isset($_assign)) { return "assign({$_assign},ob_get_clean());\n?>"; } else { diff --git a/libs/sysplugins/smarty_internal_compile_insert.php b/libs/sysplugins/smarty_internal_compile_insert.php index a72db298..02ef67c3 100644 --- a/libs/sysplugins/smarty_internal_compile_insert.php +++ b/libs/sysplugins/smarty_internal_compile_insert.php @@ -1,4 +1,5 @@ getAttributes($compiler, $args); //Does tag create output $compiler->has_output = isset($_attr[ 'assign' ]) ? false : true; + $nocacheParam = $compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache); if (!$nocacheParam) { // do not compile as nocache code @@ -64,6 +66,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase $_smarty_tpl = $compiler->template; $_name = null; $_script = null; + $_output = 'smarty instanceof SmartyBC ? $compiler->smarty->trusted_dir : null; } if (!empty($_dir)) { - foreach ((array)$_dir as $_script_dir) { - $_script_dir = rtrim($_script_dir, '/\\') . DIRECTORY_SEPARATOR; + foreach ((array) $_dir as $_script_dir) { + $_script_dir = rtrim($_script_dir, '/\\') . $compiler->smarty->ds; if (file_exists($_script_dir . $_script)) { $_filepath = $_script_dir . $_script; break; @@ -110,8 +113,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase require_once $_filepath; if (!is_callable($_function)) { $compiler->trigger_template_error(" {insert} function '{$_function}' is not callable in script file '{$_script}'", - null, - true); + null, true); } } else { $_filepath = 'null'; @@ -120,8 +122,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase if (!is_callable($_function)) { // try plugin if (!$_function = $compiler->getPlugin($_name, 'insert')) { - $compiler->trigger_template_error("{insert} no function or plugin found for '{$_name}'", - null, + $compiler->trigger_template_error("{insert} no function or plugin found for '{$_name}'", null, true); } } @@ -148,6 +149,7 @@ class Smarty_Internal_Compile_Insert extends Smarty_Internal_CompileBase $_output .= "echo {$_function}({$_params},\$_smarty_tpl);?>"; } } + return $_output; } } diff --git a/libs/sysplugins/smarty_internal_method_compilealltemplates.php b/libs/sysplugins/smarty_internal_method_compilealltemplates.php index d19fbeef..0abed212 100644 --- a/libs/sysplugins/smarty_internal_method_compilealltemplates.php +++ b/libs/sysplugins/smarty_internal_method_compilealltemplates.php @@ -31,10 +31,7 @@ class Smarty_Internal_Method_CompileAllTemplates * * @return integer number of template files recompiled */ - public function compileAllTemplates(Smarty $smarty, - $extension = '.tpl', - $force_compile = false, - $time_limit = 0, + public function compileAllTemplates(Smarty $smarty, $extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) { return $this->compileAll($smarty, $extension, $force_compile, $time_limit, $max_errors); @@ -52,11 +49,7 @@ class Smarty_Internal_Method_CompileAllTemplates * * @return int number of template files compiled */ - protected function compileAll(Smarty $smarty, - $extension, - $force_compile, - $time_limit, - $max_errors, + protected function compileAll(Smarty $smarty, $extension, $force_compile, $time_limit, $max_errors, $isConfig = false) { // switch off time limit @@ -76,11 +69,11 @@ class Smarty_Internal_Method_CompileAllTemplates if (substr(basename($_fileinfo->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) { continue; } - if (!substr_compare($_file, $extension, -strlen($extension)) == 0) { + if (!substr_compare($_file, $extension, - strlen($extension)) == 0) { continue; } - if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) { - $_file = substr($_fileinfo->getPath(), strlen($_dir)) . DIRECTORY_SEPARATOR . $_file; + if ($_fileinfo->getPath() !== substr($_dir, 0, - 1)) { + $_file = substr($_fileinfo->getPath(), strlen($_dir)) . $smarty->ds . $_file; } echo "\n
", $_dir, '---', $_file; flush(); @@ -99,7 +92,7 @@ class Smarty_Internal_Method_CompileAllTemplates $isConfig ? Smarty_Template_Config::load($_tpl) : Smarty_Template_Source::load($_tpl); if ($_tpl->mustCompile()) { $_tpl->compileTemplateSource(); - $_count++; + $_count ++; echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; flush(); } else { @@ -109,7 +102,7 @@ class Smarty_Internal_Method_CompileAllTemplates } catch (Exception $e) { echo "\n
------>Error: ", $e->getMessage(), "

\n"; - $_error_count++; + $_error_count ++; } // free memory unset($_tpl); diff --git a/libs/sysplugins/smarty_internal_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index 0f8c2478..a58771a1 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -17,30 +17,6 @@ */ class Smarty_Internal_Resource_File extends Smarty_Resource { - /** - * populate Source Object with meta data from Resource - * - * @param Smarty_Template_Source $source source object - * @param Smarty_Internal_Template $_template template object - * - * @throws \SmartyException - */ - public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) - { - $source->filepath = $this->buildFilepath($source, $_template); - if ($source->filepath !== false) { - if (isset($source->smarty->security_policy) && is_object($source->smarty->security_policy)) { - $source->smarty->security_policy->isTrustedResourceDir($source->filepath, $source->isConfig); - } - $source->exists = true; - $source->uid = sha1($source->filepath . ($source->isConfig ? $source->smarty->_joined_config_dir : - $source->smarty->_joined_template_dir)); - $source->timestamp = filemtime($source->filepath); - } else { - $source->timestamp = $source->exists = false; - } - } - /** * build template filepath by traversing the template_dir array * @@ -68,15 +44,15 @@ class Smarty_Internal_Resource_File extends Smarty_Resource throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); } // normalize path - $path = - $source->smarty->_realpath(dirname($_template->parent->source->filepath) . DIRECTORY_SEPARATOR . $file); + $path = $source->smarty->_realpath(dirname($_template->parent->source->filepath) . $source->smarty->ds . $file); // files relative to a template only get one shot return is_file($path) ? $path : false; } - // normalize DIRECTORY_SEPARATOR - if (strpos($file, DIRECTORY_SEPARATOR === '/' ? '\\' : '/') !== false) { - $file = str_replace(DIRECTORY_SEPARATOR === '/' ? '\\' : '/', DIRECTORY_SEPARATOR, $file); + // normalize $source->smarty->ds + if (strpos($file, $source->smarty->ds == '/' ? '\\' : '/') !== false) { + $file = str_replace($source->smarty->ds == '/' ? '\\' : '/', $source->smarty->ds, $file); } + $_directories = $source->smarty->getTemplateDir(null, $source->isConfig); // template_dir index? if ($file[ 0 ] == '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { @@ -88,9 +64,9 @@ class Smarty_Internal_Resource_File extends Smarty_Resource // try string indexes if (isset($_directories[ $index ])) { $_index_dirs[] = $_directories[ $index ]; - } else if (is_numeric($index)) { + } elseif (is_numeric($index)) { // try numeric index - $index = (int)$index; + $index = (int) $index; if (isset($_directories[ $index ])) { $_index_dirs[] = $_directories[ $index ]; } else { @@ -109,11 +85,12 @@ class Smarty_Internal_Resource_File extends Smarty_Resource $_directories = $_index_dirs; } } + // relative file name? foreach ($_directories as $_directory) { $path = $_directory . $file; if (is_file($path)) { - return (strpos($path, '.' . DIRECTORY_SEPARATOR) !== false) ? $source->smarty->_realpath($path) : $path; + return (strpos($path, '.' . $source->smarty->ds) !== false) ? $source->smarty->_realpath($path) : $path; } } if (!isset($_index_dirs)) { @@ -130,6 +107,29 @@ class Smarty_Internal_Resource_File extends Smarty_Resource return false; } + /** + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + */ + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) + { + $source->filepath = $this->buildFilepath($source, $_template); + + if ($source->filepath !== false) { + if (isset($source->smarty->security_policy) && is_object($source->smarty->security_policy)) { + $source->smarty->security_policy->isTrustedResourceDir($source->filepath, $source->isConfig); + } + $source->exists = true; + $source->uid = sha1($source->filepath . ($source->isConfig ? $source->smarty->_joined_config_dir : + $source->smarty->_joined_template_dir)); + $source->timestamp = filemtime($source->filepath); + } else { + $source->timestamp = $source->exists = false; + } + } + /** * populate Source Object with timestamp and exists from Resource * diff --git a/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php b/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php index 801aa300..38ad41cb 100644 --- a/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php +++ b/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php @@ -1,4 +1,5 @@ use_sub_dirs) { foreach ($_cache_id_parts as $id_part) { - $_dir .= $id_part . DIRECTORY_SEPARATOR; + $_dir .= $id_part . $smarty->ds; } } } @@ -51,8 +52,10 @@ class Smarty_Internal_Runtime_CacheResourceFile $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 ($tpl->source->exists) { $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath)); } else { @@ -68,7 +71,7 @@ class Smarty_Internal_Runtime_CacheResourceFile if (substr(basename($_file->getPathname()), 0, 1) == '.') { continue; } - $_filepath = (string)$_file; + $_filepath = (string) $_file; // directory ? if ($_file->isDir()) { if (!$_cache->isDot()) { @@ -77,7 +80,7 @@ class Smarty_Internal_Runtime_CacheResourceFile } } else { // delete only php files - if (substr($_filepath, -4) !== '.php') { + if (substr($_filepath, - 4) !== '.php') { continue; } $_parts = explode($_dir_sep, str_replace('\\', '/', substr($_filepath, $_dir_length))); @@ -102,7 +105,7 @@ class Smarty_Internal_Runtime_CacheResourceFile if ($_parts_count < $_cache_id_parts_count) { continue; } - for ($i = 0; $i < $_cache_id_parts_count; $i++) { + for ($i = 0; $i < $_cache_id_parts_count; $i ++) { if ($_parts[ $i ] != $_cache_id_parts[ $i ]) { continue 2; } @@ -127,7 +130,7 @@ class Smarty_Internal_Runtime_CacheResourceFile && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) ) { opcache_invalidate($_filepath, true); - } else if (function_exists('apc_delete_file')) { + } elseif (function_exists('apc_delete_file')) { apc_delete_file($_filepath); } } diff --git a/libs/sysplugins/smarty_internal_runtime_getincludepath.php b/libs/sysplugins/smarty_internal_runtime_getincludepath.php index 967c937a..e12b0c57 100644 --- a/libs/sysplugins/smarty_internal_runtime_getincludepath.php +++ b/libs/sysplugins/smarty_internal_runtime_getincludepath.php @@ -87,7 +87,7 @@ class Smarty_Internal_Runtime_GetIncludePath $_dirs = (array) explode(PATH_SEPARATOR, $_i_path); foreach ($_dirs as $_path) { if (is_dir($_path)) { - $this->_include_dirs[] = $smarty->_realpath($_path . DIRECTORY_SEPARATOR, true); + $this->_include_dirs[] = $smarty->_realpath($_path . $smarty->ds, true); } } return true; diff --git a/libs/sysplugins/smarty_internal_runtime_writefile.php b/libs/sysplugins/smarty_internal_runtime_writefile.php index d9206683..ffa0b51e 100644 --- a/libs/sysplugins/smarty_internal_runtime_writefile.php +++ b/libs/sysplugins/smarty_internal_runtime_writefile.php @@ -35,30 +35,34 @@ class Smarty_Internal_Runtime_WriteFile if ($_file_perms !== null) { $old_umask = umask(0); } + $_dirpath = dirname($_filepath); - // if subdirs, create dir structure + + // if subdirs, create dir structure if ($_dirpath !== '.') { - $i = 0; + $i=0; // loop if concurrency problem occurs // see https://bugs.php.net/bug.php?id=35326 while (!is_dir($_dirpath)) { - if (@mkdir($_dirpath, $_dir_perms, true)) { - break; - } - clearstatcache(); - if (++$i === 3) { - error_reporting($_error_reporting); - throw new SmartyException("unable to create directory {$_dirpath}"); - } - sleep(1); + if (@mkdir($_dirpath, $_dir_perms, true)) { + break; + } + clearstatcache(); + if (++$i === 3) { + error_reporting($_error_reporting); + throw new SmartyException("unable to create directory {$_dirpath}"); + } + sleep(1); } } + // write to tmp file, then move to overt file lock race condition - $_tmp_file = $_dirpath . DIRECTORY_SEPARATOR . str_replace(array('.', ','), '_', uniqid('wrt', true)); + $_tmp_file = $_dirpath . $smarty->ds . str_replace(array('.', ','), '_', uniqid('wrt', true)); if (!file_put_contents($_tmp_file, $_contents)) { error_reporting($_error_reporting); throw new SmartyException("unable to write file {$_tmp_file}"); } + /* * Windows' rename() fails if the destination exists, * Linux' rename() properly handles the overwrite. @@ -95,6 +99,7 @@ class Smarty_Internal_Runtime_WriteFile umask($old_umask); } error_reporting($_error_reporting); + return true; } } diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index 295c08a1..ea673ead 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -14,22 +14,12 @@ * @package Smarty * @subpackage TemplateResources * + * @method renderUncompiled(Smarty_Template_Source $source, Smarty_Internal_Template $_template) + * @method populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) * @method process(Smarty_Internal_Template $_smarty_tpl) */ abstract class Smarty_Resource { - /** - * resource types provided by the core - * - * @var array - */ - public static $sysplugins = array('file' => 'smarty_internal_resource_file.php', - 'string' => 'smarty_internal_resource_string.php', - 'extends' => 'smarty_internal_resource_extends.php', - 'stream' => 'smarty_internal_resource_stream.php', - 'eval' => 'smarty_internal_resource_eval.php', - 'php' => 'smarty_internal_resource_php.php'); - /** * Source is bypassing compiler * @@ -44,6 +34,18 @@ abstract class Smarty_Resource */ public $recompiled = false; + /** + * resource types provided by the core + * + * @var array + */ + public static $sysplugins = array('file' => 'smarty_internal_resource_file.php', + 'string' => 'smarty_internal_resource_string.php', + 'extends' => 'smarty_internal_resource_extends.php', + 'stream' => 'smarty_internal_resource_stream.php', + 'eval' => 'smarty_internal_resource_eval.php', + 'php' => 'smarty_internal_resource_php.php'); + /** * Flag if resource does implement populateCompiledFilepath() method * @@ -51,152 +53,6 @@ abstract class Smarty_Resource */ public $hasCompiledHandler = false; - /** - * modify template_resource according to resource handlers specifications - * - * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance - * @param string $template_resource template_resource to extract resource handler and name of - * - * @return string unique resource name - * @throws \SmartyException - */ - public static function getUniqueTemplateName($obj, $template_resource) - { - $smarty = $obj->_getSmartyObj(); - list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); - // TODO: optimize for Smarty's internal resource types - $resource = Smarty_Resource::load($smarty, $type); - // go relative to a given template? - $_file_is_dotted = $name[ 0 ] == '.' && ($name[ 1 ] == '.' || $name[ 1 ] == '/'); - if ($obj->_isTplObj() && $_file_is_dotted && - ($obj->source->type == 'file' || $obj->parent->source->type == 'extends') - ) { - $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . DIRECTORY_SEPARATOR . $name); - } - return $resource->buildUniqueResourceName($smarty, $name); - } - - /** - * extract resource_type and resource_name from template_resource and config_resource - * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including). - * - * @param string $resource_name template_resource or config_resource to parse - * @param string $default_resource the default resource_type defined in $smarty - * - * @return array with parsed resource name and type - */ - public static function parseResourceName($resource_name, $default_resource) - { - if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) { - $type = $match[ 1 ]; - $name = substr($resource_name, strlen($match[ 0 ])); - } else { - // no resource given, use default - // or single character before the colon is not a resource type, but part of the filepath - $type = $default_resource; - $name = $resource_name; - } - return array($name, $type); - } - - /** - * Load Resource Handler - * - * @param Smarty $smarty smarty object - * @param string $type name of the resource - * - * @throws SmartyException - * @return Smarty_Resource Resource Handler - */ - public static function load(Smarty $smarty, $type) - { - /* @var array \Smarty_Internal_Resource_File|\Smarty_Internal_Resource_Php|\Smarty_Internal_Resource_Extends|\Smarty_Internal_Resource_Eval|\Smarty_Internal_Resource_String|\Smarty_Internal_Resource_Stream|\Smarty_Internal_Resource_Registered */ - static $handlerCache = array(); - // try smarty's cache - if (isset($handlerCache[ $type ])) { - return $handlerCache[ $type ]; - } - // try registered resource - if (isset($smarty->registered_resources[ $type ])) { - return $handlerCache[ $type ] = - $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? - $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); - } - // try sysplugins dir - if (isset(self::$sysplugins[ $type ])) { - $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); - return $handlerCache[ $type ] = new $_resource_class(); - } - // try plugins dir - $_resource_class = 'Smarty_Resource_' . ucfirst($type); - if ($smarty->loadPlugin($_resource_class)) { - if (class_exists($_resource_class, false)) { - return $handlerCache[ $type ] = new $_resource_class(); - } else { - $smarty->registerResource($type, - array("smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", - "smarty_resource_{$type}_secure", "smarty_resource_{$type}_trusted")); - // give it another try, now that the resource is registered properly - return self::load($smarty, $type); - } - } - // try streams - $_known_stream = stream_get_wrappers(); - if (in_array($type, $_known_stream)) { - // is known stream - if (is_object($smarty->security_policy)) { - $smarty->security_policy->isTrustedStream($type); - } - return $handlerCache[ $type ] = new Smarty_Internal_Resource_Stream(); - } - // TODO: try default_(template|config)_handler - // give up - throw new SmartyException("Unknown resource type '{$type}'"); - } - - /** - * modify resource_name according to resource handlers specifications - * - * @param Smarty $smarty Smarty instance - * @param string $resource_name resource_name to make unique - * @param boolean $isConfig flag for config resource - * - * @return string unique resource name - */ - public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) - { - if ($isConfig) { - if (!isset($smarty->_joined_config_dir)) { - $smarty->getTemplateDir(null, true); - } - return get_class($this) . '#' . $smarty->_joined_config_dir . '#' . $resource_name; - } else { - if (!isset($smarty->_joined_template_dir)) { - $smarty->getTemplateDir(); - } - return get_class($this) . '#' . $smarty->_joined_template_dir . '#' . $resource_name; - } - } - - /** - * initialize Source Object for given resource - * wrapper for backward compatibility to versions < 3.1.22 - * Either [$_template] or [$smarty, $template_resource] must be specified - * - * @param Smarty_Internal_Template $_template template object - * @param Smarty $smarty smarty object - * @param string $template_resource resource identifier - * - * @return \Smarty_Template_Source Source Object - * @throws \SmartyException - */ - public static function source(Smarty_Internal_Template $_template = null, - Smarty $smarty = null, - $template_resource = null) - { - return Smarty_Template_Source::load($_template, $smarty, $template_resource); - } - /** * Load template's source into current template object * @@ -225,12 +81,30 @@ abstract class Smarty_Resource // intentionally left blank } - /* - * Check if resource must check time stamps when when loading complied or cached templates. - * Resources like 'extends' which use source components my disable timestamp checks on own resource. + /** + * modify resource_name according to resource handlers specifications * - * @return bool + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + if ($isConfig) { + if (!isset($smarty->_joined_config_dir)) { + $smarty->getTemplateDir(null, true); + } + return get_class($this) . '#' . $smarty->_joined_config_dir . '#' . $resource_name; + } else { + if (!isset($smarty->_joined_template_dir)) { + $smarty->getTemplateDir(); + } + return get_class($this) . '#' . $smarty->_joined_template_dir . '#' . $resource_name; + } + } + /** * Determine basename for compiled filename * @@ -243,9 +117,138 @@ abstract class Smarty_Resource return basename(preg_replace('![^\w]+!', '_', $source->name)); } + /** + * Load Resource Handler + * + * @param Smarty $smarty smarty object + * @param string $type name of the resource + * + * @throws SmartyException + * @return Smarty_Resource Resource Handler + */ + public static function load(Smarty $smarty, $type) + { + // try smarty's cache + if (isset($smarty->_cache[ 'resource_handlers' ][ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ]; + } + + // try registered resource + if (isset($smarty->registered_resources[ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = + $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? + $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); + } + + // try sysplugins dir + if (isset(self::$sysplugins[ $type ])) { + $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } + + // try plugins dir + $_resource_class = 'Smarty_Resource_' . ucfirst($type); + if ($smarty->loadPlugin($_resource_class)) { + if (class_exists($_resource_class, false)) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } else { + $smarty->registerResource($type, + array("smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", + "smarty_resource_{$type}_secure", "smarty_resource_{$type}_trusted")); + // give it another try, now that the resource is registered properly + return self::load($smarty, $type); + } + } + + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($type, $_known_stream)) { + // is known stream + if (is_object($smarty->security_policy)) { + $smarty->security_policy->isTrustedStream($type); + } + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new Smarty_Internal_Resource_Stream(); + } + + // TODO: try default_(template|config)_handler + + // give up + throw new SmartyException("Unknown resource type '{$type}'"); + } + + /** + * extract resource_type and resource_name from template_resource and config_resource + * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including). + * + * @param string $resource_name template_resource or config_resource to parse + * @param string $default_resource the default resource_type defined in $smarty + * + * @return array with parsed resource name and type + */ + public static function parseResourceName($resource_name, $default_resource) + { + if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) { + $type = $match[ 1 ]; + $name = substr($resource_name, strlen($match[ 0 ])); + } else { + // no resource given, use default + // or single character before the colon is not a resource type, but part of the filepath + $type = $default_resource; + $name = $resource_name; + } + return array($name, $type); + } + + /** + * modify template_resource according to resource handlers specifications + * + * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance + * @param string $template_resource template_resource to extract resource handler and name of + * + * @return string unique resource name + */ + public static function getUniqueTemplateName($obj, $template_resource) + { + $smarty = $obj->_getSmartyObj(); + list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); + // TODO: optimize for Smarty's internal resource types + $resource = Smarty_Resource::load($smarty, $type); + // go relative to a given template? + $_file_is_dotted = $name[ 0 ] == '.' && ($name[ 1 ] == '.' || $name[ 1 ] == '/'); + if ($obj->_isTplObj() && $_file_is_dotted && + ($obj->source->type == 'file' || $obj->parent->source->type == 'extends') + ) { + $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . $smarty->ds . $name); + } + return $resource->buildUniqueResourceName($smarty, $name); + } + + /* + * Check if resource must check time stamps when when loading complied or cached templates. + * Resources like 'extends' which use source components my disable timestamp checks on own resource. + * + * @return bool + */ public function checkTimestamps() { return true; } + + /** + * initialize Source Object for given resource + * wrapper for backward compatibility to versions < 3.1.22 + * Either [$_template] or [$smarty, $template_resource] must be specified + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty $smarty smarty object + * @param string $template_resource resource identifier + * + * @return Smarty_Template_Source Source Object + */ + public static function source(Smarty_Internal_Template $_template = null, Smarty $smarty = null, + $template_resource = null) + { + return Smarty_Template_Source::load($_template, $smarty, $template_resource); + } } diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php index 957b4669..1cd4d297 100644 --- a/libs/sysplugins/smarty_template_compiled.php +++ b/libs/sysplugins/smarty_template_compiled.php @@ -7,9 +7,11 @@ * @package Smarty * @subpackage TemplateResources * @author Rodney Rehm + * @property string $content compiled content */ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base { + /** * nocache hash * @@ -20,11 +22,11 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base /** * get a Compiled Object of this source * - * @param \Smarty_Internal_Template $_template template object + * @param Smarty_Internal_Template $_template template object * - * @return \Smarty_Template_Compiled compiled object + * @return Smarty_Template_Compiled compiled object */ - static function load(\Smarty_Internal_Template $_template) + static function load($_template) { $compiled = new Smarty_Template_Compiled(); if ($_template->source->handler->hasCompiledHandler) { @@ -38,31 +40,30 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base /** * populate Compiled Object with compiled filepath * - * @param \Smarty_Internal_Template $_template template object + * @param Smarty_Internal_Template $_template template object **/ - public function populateCompiledFilepath(\Smarty_Internal_Template $_template) + public function populateCompiledFilepath(Smarty_Internal_Template $_template) { $source = &$_template->source; $smarty = &$_template->smarty; $this->filepath = $smarty->getCompileDir(); if (isset($_template->compile_id)) { $this->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) . - ($smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'); + ($smarty->use_sub_dirs ? $smarty->ds : '^'); } - $uid = $source->uid; // if use_sub_dirs, break file into directories if ($smarty->use_sub_dirs) { - $this->filepath .= $uid[ 0 ] . $uid[ 1 ] . DIRECTORY_SEPARATOR . $uid[ 2 ] . - $uid[ 3 ] . DIRECTORY_SEPARATOR . $uid[ 4 ] . $uid[ 5 ] . DIRECTORY_SEPARATOR; + $this->filepath .= $source->uid[ 0 ] . $source->uid[ 1 ] . $smarty->ds . $source->uid[ 2 ] . + $source->uid[ 3 ] . $smarty->ds . $source->uid[ 4 ] . $source->uid[ 5 ] . $smarty->ds; } - $this->filepath .= $uid . '_'; + $this->filepath .= $source->uid . '_'; if ($source->isConfig) { - $this->filepath .= (int)$smarty->config_read_hidden + (int)$smarty->config_booleanize * 2 + - (int)$smarty->config_overwrite * 4; + $this->filepath .= (int) $smarty->config_read_hidden + (int) $smarty->config_booleanize * 2 + + (int) $smarty->config_overwrite * 4; } else { - $this->filepath .= (int)$smarty->merge_compiled_includes + (int)$smarty->escape_html * 2 + + $this->filepath .= (int) $smarty->merge_compiled_includes + (int) $smarty->escape_html * 2 + (($smarty->merge_compiled_includes && $source->type === 'extends') ? - (int)$smarty->extends_recursion * 4 : 0); + (int) $smarty->extends_recursion * 4 : 0); } $this->filepath .= '.' . $source->type; $basename = $source->handler->getBasename($source); @@ -73,26 +74,21 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base $this->filepath .= '.cache'; } $this->filepath .= '.php'; - if ($smarty->force_compile) { - // no need to obtain file status - $this->timestamp = $this->exists = false; - } else { - $this->timestamp = $this->exists = is_file($this->filepath); - if ($this->exists) { - $this->timestamp = filemtime($this->filepath); - } + $this->timestamp = $this->exists = is_file($this->filepath); + if ($this->exists) { + $this->timestamp = filemtime($this->filepath); } } /** * render compiled template code * - * @param \Smarty_Internal_Template $_template + * @param Smarty_Internal_Template $_template * * @return string * @throws Exception */ - public function render(\Smarty_Internal_Template $_template) + public function render(Smarty_Internal_Template $_template) { // checks if template exists if (!$_template->source->exists) { @@ -128,17 +124,17 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base /** * load compiled template or compile from source * - * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + * @param Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template * * @throws Exception */ - public function process(\Smarty_Internal_Template $_smarty_tpl) + public function process(Smarty_Internal_Template $_smarty_tpl) { $source = &$_smarty_tpl->source; $smarty = &$_smarty_tpl->smarty; if ($source->handler->recompiled) { $source->handler->process($_smarty_tpl); - } else if (!$source->handler->uncompiled) { + } elseif (!$source->handler->uncompiled) { if (!$this->exists || $smarty->force_compile || ($smarty->compile_check && $source->getTimeStamp() > $this->getTimeStamp()) ) { @@ -166,11 +162,11 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base /** * compile template from source * - * @param \Smarty_Internal_Template $_template + * @param Smarty_Internal_Template $_template * * @throws Exception */ - public function compileTemplateSource(\Smarty_Internal_Template $_template) + public function compileTemplateSource(Smarty_Internal_Template $_template) { $this->file_dependency = array(); $this->includes = array(); @@ -199,38 +195,15 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base unset($_template->compiler); } - /** - * Load fresh compiled template by including the PHP file - * HHVM requires a work around because of a PHP incompatibility - * - * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template - */ - private function loadCompiledTemplate(\Smarty_Internal_Template $_smarty_tpl) - { - if (function_exists('opcache_invalidate') - && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) - ) { - opcache_invalidate($this->filepath, true); - } else if (function_exists('apc_compile_file')) { - apc_compile_file($this->filepath); - } - if (defined('HHVM_VERSION')) { - eval("?>" . file_get_contents($this->filepath)); - } else { - include($this->filepath); - } - } - /** * Write compiled code by handler * - * @param \Smarty_Internal_Template $_template template object - * @param string $code compiled code + * @param Smarty_Internal_Template $_template template object + * @param string $code compiled code * - * @return bool success - * @throws \SmartyException + * @return boolean success */ - public function write(\Smarty_Internal_Template $_template, $code) + public function write(Smarty_Internal_Template $_template, $code) { if (!$_template->source->handler->recompiled) { if ($_template->smarty->ext->_writeFile->writeFile($this->filepath, $code, $_template->smarty) === true) { @@ -245,14 +218,36 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base return true; } + /** + * Load fresh compiled template by including the PHP file + * HHVM requires a work around because of a PHP incompatibility + * + * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + */ + private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl) + { + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) + ) { + opcache_invalidate($this->filepath, true); + } elseif (function_exists('apc_compile_file')) { + apc_compile_file($this->filepath); + } + if (defined('HHVM_VERSION')) { + eval("?>" . file_get_contents($this->filepath)); + } else { + include($this->filepath); + } + } + /** * Read compiled content from handler * - * @param \Smarty_Internal_Template $_template template object + * @param Smarty_Internal_Template $_template template object * * @return string content */ - public function read(\Smarty_Internal_Template $_template) + public function read(Smarty_Internal_Template $_template) { if (!$_template->source->handler->recompiled) { return file_get_contents($this->filepath);