From f3950a45a76d6702e653f8da3550e29412a69840 Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Thu, 26 Oct 2017 04:37:05 +0200 Subject: [PATCH] - bugfix Smarty version was not filled in header comment of compiled and cached files - optimization replace internal Smarty::$ds property by DIRECTORY_SEPARATOR (reverted from commit 1e787d08f11d0a41028d847428068bf5f8d1c2ac) --- change_log.txt | 4 - libs/Smarty.class.php | 158 ++++++++------- .../smarty_internal_compile_include.php | 37 +++- .../smarty_internal_compile_insert.php | 16 +- ..._internal_method_clearcompiledtemplate.php | 31 ++- .../smarty_internal_resource_file.php | 18 +- ...smarty_internal_runtime_getincludepath.php | 19 +- .../smarty_internal_runtime_writefile.php | 29 +-- libs/sysplugins/smarty_resource.php | 191 +++++++++--------- libs/sysplugins/smarty_template_compiled.php | 50 ++--- 10 files changed, 296 insertions(+), 257 deletions(-) diff --git a/change_log.txt b/change_log.txt index 9ccfa3050..982085f6b 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,8 +1,4 @@ ===== 3.1.32 - dev === -26.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 4de846a06..e357bf272 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 * @@ -763,6 +769,27 @@ public function disableSecurity() return $this; } + /** + * Set template directory + * + * @param string|array $template_dir directory(s) of template sources + * @param bool $isConfig true for config_dir + * + * @return \Smarty current Smarty instance for chaining + */ + public function setTemplateDir($template_dir, $isConfig = false) + { + if ($isConfig) { + $this->config_dir = array(); + $this->_processedConfigDir = array(); + } else { + $this->template_dir = array(); + $this->_processedTemplateDir = array(); + } + $this->addTemplateDir($template_dir, null, $isConfig); + return $this; + } + /** * Add template directory(s) * @@ -832,24 +859,15 @@ public function getTemplateDir($index = null, $isConfig = false) } /** - * Set template directory + * Set config directory * - * @param string|array $template_dir directory(s) of template sources - * @param bool $isConfig true for config_dir + * @param $config_dir * - * @return \Smarty current Smarty instance for chaining + * @return Smarty current Smarty instance for chaining */ - public function setTemplateDir($template_dir, $isConfig = false) + public function setConfigDir($config_dir) { - if ($isConfig) { - $this->config_dir = array(); - $this->_processedConfigDir = array(); - } else { - $this->template_dir = array(); - $this->_processedTemplateDir = array(); - } - $this->addTemplateDir($template_dir, null, $isConfig); - return $this; + return $this->setTemplateDir($config_dir, true); } /** @@ -878,15 +896,17 @@ public function getConfigDir($index = null) } /** - * Set config directory + * Set plugins directory * - * @param $config_dir + * @param string|array $plugins_dir directory(s) of plugins * * @return Smarty current Smarty instance for chaining */ - public function setConfigDir($config_dir) + public function setPluginsDir($plugins_dir) { - return $this->setTemplateDir($config_dir, true); + $this->plugins_dir = (array)$plugins_dir; + $this->_pluginsDirNormalized = false; + return $this; } /** @@ -922,7 +942,7 @@ public function getPluginsDir() $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; @@ -931,16 +951,15 @@ public function getPluginsDir() } /** - * Set plugins directory * - * @param string|array $plugins_dir directory(s) of plugins + * @param string $compile_dir directory to store compiled templates in * - * @return Smarty current Smarty instance for chaining + * @return Smarty current Smarty instance for chaining */ - public function setPluginsDir($plugins_dir) + public function setCompileDir($compile_dir) { - $this->plugins_dir = (array)$plugins_dir; - $this->_pluginsDirNormalized = false; + $this->_normalizeDir('compile_dir', $compile_dir); + $this->_compileDirNormalized = true; return $this; } @@ -959,15 +978,16 @@ public function getCompileDir() } /** + * Set cache directory * - * @param string $compile_dir directory to store compiled templates in + * @param string $cache_dir directory to store cached templates in * * @return Smarty current Smarty instance for chaining */ - public function setCompileDir($compile_dir) + public function setCacheDir($cache_dir) { - $this->_normalizeDir('compile_dir', $compile_dir); - $this->_compileDirNormalized = true; + $this->_normalizeDir('cache_dir', $cache_dir); + $this->_cacheDirNormalized = true; return $this; } @@ -985,20 +1005,6 @@ public function getCacheDir() return $this->cache_dir; } - /** - * Set cache directory - * - * @param string $cache_dir directory to store cached templates in - * - * @return Smarty current Smarty instance for chaining - */ - public function setCacheDir($cache_dir) - { - $this->_normalizeDir('cache_dir', $cache_dir); - $this->_cacheDirNormalized = true; - return $this; - } - /** * creates a template object * @@ -1127,24 +1133,24 @@ public function _getTemplateId($template_name, */ 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); $path = $parts[ 'path' ]; - if ($parts[ 'root' ] === '\\') { + if ($parts[ 'root' ] == '\\') { $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 @@ public function _realpath($path, $realpath = null) foreach ($counts as $count) { $path = preg_replace('#(([\\\\/]([.]?[\\\\/])*[^\\\\/.]+){' . $count . '}[\\\\/]([.]?[\\\\/])*([.][.][\\\\/]([.]?[\\\\/])*){' . $count . '})(?=[^.])#u', - DIRECTORY_SEPARATOR, + $this->ds, $path); } } @@ -1204,23 +1210,23 @@ public function setEscapeHtml($escape_html) } /** - * Return auto_literal flag + * Set auto_literal flag * - * @return boolean + * @param boolean $auto_literal */ - public function getAutoLiteral() + public function setAutoLiteral($auto_literal = true) { - return $this->auto_literal; + $this->auto_literal = $auto_literal; } /** - * Set auto_literal flag + * Return auto_literal flag * - * @param boolean $auto_literal + * @return boolean */ - public function setAutoLiteral($auto_literal = true) + public function getAutoLiteral() { - $this->auto_literal = $auto_literal; + return $this->auto_literal; } /** @@ -1239,16 +1245,6 @@ public function setMergeCompiledIncludes($merge_compiled_includes) $this->merge_compiled_includes = $merge_compiled_includes; } - /** - * Get left delimiter - * - * @return string - */ - public function getLeftDelimiter() - { - return $this->left_delimiter; - } - /** * Set left delimiter * @@ -1260,13 +1256,13 @@ public function setLeftDelimiter($left_delimiter) } /** - * Get right delimiter + * Get left delimiter * - * @return string $right_delimiter + * @return string */ - public function getRightDelimiter() + public function getLeftDelimiter() { - return $this->right_delimiter; + return $this->left_delimiter; } /** @@ -1279,6 +1275,16 @@ public function setRightDelimiter($right_delimiter) $this->right_delimiter = $right_delimiter; } + /** + * Get right delimiter + * + * @return string $right_delimiter + */ + public function getRightDelimiter() + { + return $this->right_delimiter; + } + /** * @param boolean $debugging */ @@ -1401,7 +1407,7 @@ public function __set($name, $value) */ 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 @@ private function _normalizeTemplateConfig($isConfig) } 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_compile_include.php b/libs/sysplugins/smarty_internal_compile_include.php index 6fdbe258a..a81b0c740 100644 --- a/libs/sysplugins/smarty_internal_compile_include.php +++ b/libs/sysplugins/smarty_internal_compile_include.php @@ -20,6 +20,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase * caching mode to create nocache code but no cache file */ const CACHING_NOCACHE_CODE = 9999; + /** * Attribute definition: Overwrites base class. * @@ -27,6 +28,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase */ public $required_attributes = array('file'); + /** * Attribute definition: Overwrites base class. * @@ -34,6 +36,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase */ public $shorttag_order = array('file'); + /** * Attribute definition: Overwrites base class. * @@ -41,6 +44,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase */ public $option_flags = array('nocache', 'inline', 'caching'); + /** * Attribute definition: Overwrites base class. * @@ -48,6 +52,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase * @see Smarty_Internal_CompileBase */ public $optional_attributes = array('_any'); + /** * Valid scope names * @@ -72,6 +77,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $uid = $t_hash = null; // check and get attributes $_attr = $this->getAttributes($compiler, $args); + $fullResourceName = $source_resource = $_attr[ 'file' ]; $variable_template = false; $cache_tpl = false; @@ -84,11 +90,11 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $variable_template = true; } if (!$variable_template) { - if ($type !== 'string') { + if ($type != 'string') { $fullResourceName = "{$type}:{$name}"; $compiled = $compiler->parent_compiler->template->compiled; if (isset($compiled->includes[ $fullResourceName ])) { - $compiled->includes[ $fullResourceName ]++; + $compiled->includes[ $fullResourceName ] ++; $cache_tpl = true; } else { if ("{$compiler->template->source->type}:{$compiler->template->source->name}" == @@ -110,8 +116,10 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, } else { $variable_template = true; } + // scope setup $_scope = $compiler->convertScope($_attr, $this->valid_scopes); + // set flag to cache subtemplate object when called within loop or template name is variable. if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) { $_cache_tpl = 'true'; @@ -120,14 +128,18 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, } // assume caching is off $_caching = Smarty::CACHING_OFF; + $call_nocache = $compiler->tag_nocache || $compiler->nocache; + // caching was on and {include} is not in nocache mode if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) { $_caching = self::CACHING_NOCACHE_CODE; } + // flag if included template code should be merged into caller $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr[ 'inline' ] === true) && !$compiler->template->source->handler->recompiled; + if ($merge_compiled_includes) { // variable template name ? if ($variable_template) { @@ -138,6 +150,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $merge_compiled_includes = false; } } + /* * if the {include} tag provides individual parameter for caching or compile_id * the subtemplate must not be included into the common cache file and is treated like @@ -145,7 +158,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, * */ if ($_attr[ 'nocache' ] !== true && $_attr[ 'caching' ]) { - $_caching = $_new_caching = (int)$_attr[ 'caching' ]; + $_caching = $_new_caching = (int) $_attr[ 'caching' ]; $call_nocache = true; } else { $_new_caching = Smarty::CACHING_LIFETIME_CURRENT; @@ -169,6 +182,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, } else { $_compile_id = '$_smarty_tpl->compile_id'; } + // if subtemplate will be called in nocache mode do not merge if ($compiler->template->caching && $call_nocache) { $merge_compiled_includes = false; @@ -186,6 +200,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $_assign = $_attr[ 'assign' ]; } } + $has_compiled_template = false; if ($merge_compiled_includes) { $c_id = isset($_attr[ 'compile_id' ]) ? $_attr[ 'compile_id' ] : $compiler->template->compile_id; @@ -217,17 +232,17 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $_vars = 'array(' . join(',', $_pairs) . ')'; } $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache && - $_compile_id !== '$_smarty_tpl->compile_id'; + $_compile_id != '$_smarty_tpl->compile_id'; if ($has_compiled_template && !$call_nocache) { $_output = "makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n"); } - if (!empty($_attr) && $_caching === 9999 && $compiler->template->caching) { + if (!empty($_attr) && $_caching == 9999 && $compiler->template->caching) { $_vars_nc = "foreach ($_vars as \$ik => \$iv) {\n"; $_vars_nc .= "\$_smarty_tpl->tpl_vars[\$ik] = new Smarty_Variable(\$iv);\n"; $_vars_nc .= "}\n"; - $_output .= substr($compiler->processNocacheCode('\n", true), 6, -3); + $_output .= substr($compiler->processNocacheCode('\n", true), 6, - 3); } if (isset($_assign)) { $_output .= "ob_start();\n"; @@ -240,8 +255,10 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"); } $_output .= "?>\n"; + return $_output; } + if ($call_nocache) { $compiler->tag_nocache = true; } @@ -274,8 +291,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, * @return bool */ public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $compiler, - Smarty_Internal_Template $tpl, - $t_hash) + Smarty_Internal_Template $tpl, $t_hash) { $uid = $tpl->source->type . $tpl->source->uid; if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) { @@ -293,7 +309,7 @@ public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $co $tpl->mustCompile = true; $compiler->parent_compiler->mergedSubTemplatesData[ $uid ][ $t_hash ][ 'nocache_hash' ] = $tpl->compiled->nocache_hash; - if ($compiler->template->source->type === 'file') { + if ($compiler->template->source->type == 'file') { $sourceInfo = $compiler->template->source->filepath; } else { $basename = $compiler->template->source->handler->getBasename($compiler->template->source); @@ -315,8 +331,7 @@ public function compileInlineTemplate(Smarty_Internal_SmartyTemplateCompiler $co if ($tpl->compiled->has_nocache_code) { // replace nocache_hash $compiled_code = - str_replace("{$tpl->compiled->nocache_hash}", - $compiler->template->compiled->nocache_hash, + str_replace("{$tpl->compiled->nocache_hash}", $compiler->template->compiled->nocache_hash, $compiled_code); $compiler->template->compiled->has_nocache_code = true; } diff --git a/libs/sysplugins/smarty_internal_compile_insert.php b/libs/sysplugins/smarty_internal_compile_insert.php index 117ec4ef3..02ef67c3a 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 @@ -62,6 +66,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) $_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; @@ -108,8 +113,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) 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'; @@ -118,8 +122,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) 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); } } @@ -146,6 +149,7 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) $_output .= "echo {$_function}({$_params},\$_smarty_tpl);?>"; } } + return $_output; } } diff --git a/libs/sysplugins/smarty_internal_method_clearcompiledtemplate.php b/libs/sysplugins/smarty_internal_method_clearcompiledtemplate.php index 1d448e5f7..0ed9f95b7 100644 --- a/libs/sysplugins/smarty_internal_method_clearcompiledtemplate.php +++ b/libs/sysplugins/smarty_internal_method_clearcompiledtemplate.php @@ -35,12 +35,13 @@ public function clearCompiledTemplate(Smarty $smarty, $resource_name = null, $co { // clear template objects cache $smarty->_clearTemplateCache(); + $_compile_dir = $smarty->getCompileDir(); - if ($_compile_dir === '/') { //We should never want to delete this! + if ($_compile_dir == '/') { //We should never want to delete this! return 0; } $_compile_id = isset($compile_id) ? preg_replace('![^\w]+!', '_', $compile_id) : null; - $_dir_sep = $smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + $_dir_sep = $smarty->use_sub_dirs ? $smarty->ds : '^'; if (isset($resource_name)) { $_save_stat = $smarty->caching; $smarty->caching = false; @@ -48,7 +49,7 @@ public function clearCompiledTemplate(Smarty $smarty, $resource_name = null, $co $tpl = $smarty->createTemplate($resource_name); $smarty->caching = $_save_stat; if (!$tpl->source->handler->uncompiled && !$tpl->source->handler->recompiled && $tpl->source->exists) { - $_resource_part_1 = basename(str_replace('^', DIRECTORY_SEPARATOR, $tpl->compiled->filepath)); + $_resource_part_1 = basename(str_replace('^', $smarty->ds, $tpl->compiled->filepath)); $_resource_part_1_length = strlen($_resource_part_1); } else { return 0; @@ -74,10 +75,10 @@ public function clearCompiledTemplate(Smarty $smarty, $resource_name = null, $co } $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); foreach ($_compile as $_file) { - if (substr(basename($_file->getPathname()), 0, 1) === '.') { + if (substr(basename($_file->getPathname()), 0, 1) == '.') { continue; } - $_filepath = (string)$_file; + $_filepath = (string) $_file; if ($_file->isDir()) { if (!$_compile->isDot()) { // delete folder if empty @@ -85,22 +86,19 @@ public function clearCompiledTemplate(Smarty $smarty, $resource_name = null, $co } } else { // delete only php files - if (substr($_filepath, -4) !== '.php') { + if (substr($_filepath, - 4) !== '.php') { continue; } $unlink = false; if ((!isset($_compile_id) || (isset($_filepath[ $_compile_id_part_length ]) && $a = !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) && (!isset($resource_name) || (isset($_filepath[ $_resource_part_1_length ]) && - substr_compare($_filepath, - $_resource_part_1, - -$_resource_part_1_length, - $_resource_part_1_length) === + substr_compare($_filepath, $_resource_part_1, + - $_resource_part_1_length, $_resource_part_1_length) == 0) || (isset($_filepath[ $_resource_part_2_length ]) && - substr_compare($_filepath, - $_resource_part_2, - -$_resource_part_2_length, - $_resource_part_2_length) === 0)) + substr_compare($_filepath, $_resource_part_2, + - $_resource_part_2_length, + $_resource_part_2_length) == 0)) ) { if (isset($exp_time)) { if (is_file($_filepath) && time() - @filemtime($_filepath) >= $exp_time) { @@ -110,13 +108,14 @@ public function clearCompiledTemplate(Smarty $smarty, $resource_name = null, $co $unlink = true; } } + if ($unlink && is_file($_filepath) && @unlink($_filepath)) { - $_count++; + $_count ++; if (function_exists('opcache_invalidate') && (!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_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index f8b361a95..a58771a17 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -30,32 +30,32 @@ protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal { $file = $source->name; // absolute file ? - if ($file[ 0 ] === '/' || $file[ 1 ] === ':') { + if ($file[ 0 ] == '/' || $file[ 1 ] == ':') { $file = $source->smarty->_realpath($file, true); return is_file($file) ? $file : false; } // go relative to a given template? - if ($file[ 0 ] === '.' && $_template && $_template->_isSubTpl() && + if ($file[ 0 ] == '.' && $_template && $_template->_isSubTpl() && preg_match('#^[.]{1,2}[\\\/]#', $file) ) { - if ($_template->parent->source->type !== 'file' && $_template->parent->source->type !== 'extends' && + if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !isset($_template->parent->_cache[ 'allow_relative_path' ]) ) { 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)) { + if ($file[ 0 ] == '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { $file = $fileMatch[ 2 ]; $_indices = explode(',', $fileMatch[ 1 ]); $_index_dirs = array(); @@ -90,7 +90,7 @@ protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal 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)) { diff --git a/libs/sysplugins/smarty_internal_runtime_getincludepath.php b/libs/sysplugins/smarty_internal_runtime_getincludepath.php index 00dbf7b5c..e12b0c57c 100644 --- a/libs/sysplugins/smarty_internal_runtime_getincludepath.php +++ b/libs/sysplugins/smarty_internal_runtime_getincludepath.php @@ -21,42 +21,49 @@ class Smarty_Internal_Runtime_GetIncludePath * @var string */ public $_include_path = ''; + /** * include path directory cache * * @var array */ public $_include_dirs = array(); + /** * include path directory cache * * @var array */ public $_user_dirs = array(); + /** * stream cache * * @var string[] */ public $isFile = array(); + /** * stream cache * * @var string[] */ public $isPath = array(); + /** * stream cache * * @var int[] */ public $number = array(); + /** * status cache * * @var bool */ public $_has_stream_include = null; + /** * Number for array index * @@ -74,13 +81,13 @@ class Smarty_Internal_Runtime_GetIncludePath public function isNewIncludePath(Smarty $smarty) { $_i_path = get_include_path(); - if ($this->_include_path !== $_i_path) { + if ($this->_include_path != $_i_path) { $this->_include_dirs = array(); $this->_include_path = $_i_path; - $_dirs = (array)explode(PATH_SEPARATOR, $_i_path); + $_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; @@ -121,7 +128,7 @@ public function getIncludePath($dirs, $file, Smarty $smarty) } // try PHP include_path foreach ($dirs as $dir) { - $dir_n = isset($this->number[ $dir ]) ? $this->number[ $dir ] : $this->number[ $dir ] = $this->counter++; + $dir_n = isset($this->number[ $dir ]) ? $this->number[ $dir ] : $this->number[ $dir ] = $this->counter ++; if (isset($this->isFile[ $dir_n ][ $file ])) { if ($this->isFile[ $dir_n ][ $file ]) { return $this->isFile[ $dir_n ][ $file ]; @@ -136,9 +143,9 @@ public function getIncludePath($dirs, $file, Smarty $smarty) $dir = $this->_user_dirs[ $dir_n ]; } } else { - if ($dir[ 0 ] === '/' || $dir[ 1 ] === ':') { + if ($dir[ 0 ] == '/' || $dir[ 1 ] == ':') { $dir = str_ireplace(getcwd(), '.', $dir); - if ($dir[ 0 ] === '/' || $dir[ 1 ] === ':') { + if ($dir[ 0 ] == '/' || $dir[ 1 ] == ':') { $this->_user_dirs[ $dir_n ] = false; continue; } diff --git a/libs/sysplugins/smarty_internal_runtime_writefile.php b/libs/sysplugins/smarty_internal_runtime_writefile.php index d9206683e..ffa0b51e9 100644 --- a/libs/sysplugins/smarty_internal_runtime_writefile.php +++ b/libs/sysplugins/smarty_internal_runtime_writefile.php @@ -35,30 +35,34 @@ public function writeFile($_filepath, $_contents, Smarty $smarty) 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 @@ public function writeFile($_filepath, $_contents, Smarty $smarty) umask($old_umask); } error_reporting($_error_reporting); + return true; } } diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php index 4aaafa4d2..ea673ead1 100644 --- a/libs/sysplugins/smarty_resource.php +++ b/libs/sysplugins/smarty_resource.php @@ -20,29 +20,32 @@ */ 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 * * @var boolean */ public $uncompiled = false; + /** * Source must be recompiled on every occasion * * @var boolean */ 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 * @@ -50,6 +53,70 @@ abstract class Smarty_Resource */ public $hasCompiledHandler = false; + /** + * Load template's source into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + abstract public function getContent(Smarty_Template_Source $source); + + /** + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + */ + abstract public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null); + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + // intentionally left blank + } + + /** + * 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; + } + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename(preg_replace('![^\w]+!', '_', $source->name)); + } + /** * Load Resource Handler * @@ -65,17 +132,20 @@ public static function load(Smarty $smarty, $type) 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)) { @@ -89,6 +159,7 @@ public static function load(Smarty $smarty, $type) return self::load($smarty, $type); } } + // try streams $_known_stream = stream_get_wrappers(); if (in_array($type, $_known_stream)) { @@ -98,7 +169,9 @@ public static function load(Smarty $smarty, $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}'"); } @@ -141,15 +214,26 @@ public static function getUniqueTemplateName($obj, $template_resource) // 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 ] === '/'); + $_file_is_dotted = $name[ 0 ] == '.' && ($name[ 1 ] == '.' || $name[ 1 ] == '/'); if ($obj->_isTplObj() && $_file_is_dotted && - ($obj->source->type === 'file' || $obj->parent->source->type === 'extends') + ($obj->source->type == 'file' || $obj->parent->source->type == 'extends') ) { - $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . DIRECTORY_SEPARATOR . $name); + $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 @@ -161,87 +245,10 @@ public static function getUniqueTemplateName($obj, $template_resource) * * @return Smarty_Template_Source Source Object */ - public static function source(Smarty_Internal_Template $_template = null, - Smarty $smarty = null, + 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 - * - * @param Smarty_Template_Source $source source object - * - * @return string template source - * @throws SmartyException if source cannot be loaded - */ - abstract public function getContent(Smarty_Template_Source $source); - - /** - * populate Source Object with meta data from Resource - * - * @param Smarty_Template_Source $source source object - * @param Smarty_Internal_Template $_template template object - */ - abstract public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null); - - /** - * populate Source Object with timestamp and exists from Resource - * - * @param Smarty_Template_Source $source source object - */ - public function populateTimestamp(Smarty_Template_Source $source) - { - // intentionally left blank - } - - /** - * 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; - } - } - - /* - * 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 - */ - - /** - * Determine basename for compiled filename - * - * @param Smarty_Template_Source $source source object - * - * @return string resource's basename - */ - public function getBasename(Smarty_Template_Source $source) - { - return basename(preg_replace('![^\w]+!', '_', $source->name)); - } - - public function checkTimestamps() - { - return true; - } } diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php index b45cd8b12..1cd4d2978 100644 --- a/libs/sysplugins/smarty_template_compiled.php +++ b/libs/sysplugins/smarty_template_compiled.php @@ -11,6 +11,7 @@ */ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base { + /** * nocache hash * @@ -48,22 +49,21 @@ public function populateCompiledFilepath(Smarty_Internal_Template $_template) $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 : '^'); } // if use_sub_dirs, break file into directories if ($smarty->use_sub_dirs) { - $this->filepath .= $source->uid[ 0 ] . $source->uid[ 1 ] . DIRECTORY_SEPARATOR . $source->uid[ 2 ] . - $source->uid[ 3 ] . DIRECTORY_SEPARATOR . $source->uid[ 4 ] . $source->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 .= $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); @@ -134,7 +134,7 @@ public function process(Smarty_Internal_Template $_smarty_tpl) $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()) ) { @@ -218,21 +218,6 @@ public function write(Smarty_Internal_Template $_template, $code) return true; } - /** - * Read compiled content from handler - * - * @param Smarty_Internal_Template $_template template object - * - * @return string content - */ - public function read(Smarty_Internal_Template $_template) - { - if (!$_template->source->handler->recompiled) { - return file_get_contents($this->filepath); - } - return isset($this->content) ? $this->content : false; - } - /** * Load fresh compiled template by including the PHP file * HHVM requires a work around because of a PHP incompatibility @@ -245,7 +230,7 @@ private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl) && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) ) { opcache_invalidate($this->filepath, true); - } else if (function_exists('apc_compile_file')) { + } elseif (function_exists('apc_compile_file')) { apc_compile_file($this->filepath); } if (defined('HHVM_VERSION')) { @@ -254,4 +239,19 @@ private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl) include($this->filepath); } } + + /** + * Read compiled content from handler + * + * @param Smarty_Internal_Template $_template template object + * + * @return string content + */ + public function read(Smarty_Internal_Template $_template) + { + if (!$_template->source->handler->recompiled) { + return file_get_contents($this->filepath); + } + return isset($this->content) ? $this->content : false; + } }