diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index c94bfe40..a5ee9fd2 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -111,7 +111,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.28-dev/27'; + const SMARTY_VERSION = '3.1.28-dev/28'; /** * define variable scopes @@ -737,20 +737,6 @@ class Smarty extends Smarty_Internal_TemplateBase */ public $_parserdebug = false; - /** - * Cache of is_file results of loadPlugin() - * - * @var array - */ - public $_is_file_cache = array(); - - /** - * Cache of internal flags - * - * @var array - */ - public $_flags = array(); - /**#@-*/ /** @@ -793,6 +779,7 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false) { + $this->_cache['core'] = array(); if ($cache_id !== null && is_object($cache_id)) { $parent = $cache_id; $cache_id = null; @@ -943,7 +930,8 @@ class Smarty extends Smarty_Internal_TemplateBase $joined = 'joined_' . $type; $this->{$type} = (array) $template_dir; $this->{$joined} = join(' # ', $this->{$type}); - $this->_flags[$type] = false; + $this->_cache[$type . '_new'] = true; + $this->_cache[$type] = false; return $this; } @@ -960,10 +948,11 @@ class Smarty extends Smarty_Internal_TemplateBase { $type = $isConfig ? 'config_dir' : 'template_dir'; $joined = 'joined_' . $type; - if (!isset($this->_flags[$type])) { + if (!isset($this->_cache[$type])) { $this->{$type} = (array) $this->{$type}; $this->{$joined} = join(' # ', $this->{$type}); - $this->_flags[$type] = false; + $this->_cache[$type . '_new'] = true; + $this->_cache[$type] = false; } $this->{$joined} .= ' # ' . join(' # ', (array) $template_dir); $this->_addDir($type, $template_dir, $key); @@ -981,17 +970,18 @@ class Smarty extends Smarty_Internal_TemplateBase public function getTemplateDir($index = null, $isConfig = false) { $type = $isConfig ? 'config_dir' : 'template_dir'; - if (!isset($this->_flags[$type])) { + if (!isset($this->_cache[$type])) { $joined = 'joined_' . $type; $this->{$type} = (array) $this->{$type}; $this->{$joined} = join(' # ', $this->{$type}); - $this->_flags[$type] = false; + $this->_cache[$type] = false; } - if ($this->_flags[$type] == false) { + if ($this->_cache[$type] == false) { foreach ($this->{$type} as $k => $v) { $this->{$type}[$k] = $this->_realpath($v . DS, true); } - $this->_flags[$type] = true; + $this->_cache[$type . '_new'] = true; + $this->_cache[$type] = true; } if ($index !== null) { return isset($this->{$type}[$index]) ? $this->{$type}[$index] : null; @@ -1046,8 +1036,8 @@ class Smarty extends Smarty_Internal_TemplateBase public function setPluginsDir($plugins_dir) { $this->plugins_dir = (array) $plugins_dir; - if (isset($this->_flags['plugins_dir'])) { - unset($this->_flags['plugins_dir']); + if (isset($this->_cache['plugins_dir'])) { + unset($this->_cache['plugins_dir']); } return $this; } @@ -1065,8 +1055,8 @@ class Smarty extends Smarty_Internal_TemplateBase $this->plugins_dir = array(SMARTY_PLUGINS_DIR); } $this->plugins_dir = array_merge((array) $this->plugins_dir, (array) $plugins_dir); - if (isset($this->_flags['plugins_dir'])) { - unset($this->_flags['plugins_dir']); + if (isset($this->_cache['plugins_dir'])) { + unset($this->_cache['plugins_dir']); } return $this; } @@ -1078,7 +1068,7 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function getPluginsDir() { - if (!isset($this->_flags['plugins_dir'])) { + if (!isset($this->_cache['plugins_dir'])) { if (!isset($this->plugins_dir)) { $this->plugins_dir = array(SMARTY_PLUGINS_DIR); } else { @@ -1089,8 +1079,8 @@ class Smarty extends Smarty_Internal_TemplateBase } $this->plugins_dir = array_unique($this->plugins_dir); } - $this->_is_file_cache = array(); - $this->_flags['plugins_dir'] = true; + $this->_cache['plugin_files'] = array(); + $this->_cache['plugins_dir'] = true; } return $this->plugins_dir; } @@ -1108,7 +1098,7 @@ class Smarty extends Smarty_Internal_TemplateBase if (!isset(Smarty::$_muted_directories[$this->compile_dir])) { Smarty::$_muted_directories[$this->compile_dir] = null; } - $this->_flags['compile_dir'] = true; + $this->_cache['compile_dir'] = true; return $this; } @@ -1119,12 +1109,12 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function getCompileDir() { - if (!isset($this->_flags['compile_dir'])) { + if (!isset($this->_cache['compile_dir'])) { $this->compile_dir = $this->_realpath($this->compile_dir . DS, true); if (!isset(Smarty::$_muted_directories[$this->compile_dir])) { Smarty::$_muted_directories[$this->compile_dir] = null; } - $this->_flags['compile_dir'] = true; + $this->_cache['compile_dir'] = true; } return $this->compile_dir; } @@ -1142,7 +1132,7 @@ class Smarty extends Smarty_Internal_TemplateBase if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { Smarty::$_muted_directories[$this->cache_dir] = null; } - $this->_flags['cache_dir'] = true; + $this->_cache['cache_dir'] = true; return $this; } @@ -1153,12 +1143,12 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function getCacheDir() { - if (!isset($this->_flags['cache_dir'])) { + if (!isset($this->_cache['cache_dir'])) { $this->cache_dir = $this->_realpath($this->cache_dir . DS, true); if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { Smarty::$_muted_directories[$this->cache_dir] = null; } - $this->_flags['cache_dir'] = true; + $this->_cache['cache_dir'] = true; } return $this->cache_dir; } @@ -1172,7 +1162,7 @@ class Smarty extends Smarty_Internal_TemplateBase */ private function _addDir($dirName, $dir, $key = null) { - $rp = $this->_flags[$dirName]; + $rp = $this->_cache[$dirName]; if (is_array($dir)) { foreach ($dir as $k => $v) { $path = $rp ? $this->_realpath($v . DS, true) : $v; @@ -1393,13 +1383,16 @@ class Smarty extends Smarty_Internal_TemplateBase { static $pattern = null; static $pattern2 = null; - if ($realpath !== null && $path[0] !== '/' && $path[1] !== ':') { + if ($pattern == null) { + $pattern = '#[' . (DS == '/' ? '\\\\' : '/') . ']|([\\\/]([\\\/]|([.]+[\\\/])))#'; + $pattern2 = '#([\\\/]+[^\\\/]+[\\\/]+[.]([\\\/]+[.])*[.][\\\/]+([.][\\\/]+)*)|([\\\/]+([.][\\\/]+)+)|[\\\/]{2,}|[' . + (DS == '/' ? '\\\\' : '/') . ']+#'; + } + if ($realpath === true && $path[0] !== '/' && $path[1] !== ':') { $path = getcwd() . DS . $path; } - while (preg_match(isset($pattern) ? $pattern : $pattern = '#([\\\/][.]+[\\\/])|[' . (DS == '/' ? '\\\\' : '/') . - ']|[\\\/]{2,}#', $path)) { - $path = preg_replace(isset($pattern2) ? $pattern2 : $pattern2 = '#([\\\/]+([.][\\\/]+)+)|([\\\/]+([^\\\/]+[\\\/]+){2}([.][.][\\\/]+){2})|([\\\/]+[^\\\/]+[\\\/]+[.][.][\\\/]+)|[\\\/]{2,}|[' . - (DS == '/' ? '\\\\' : '/') . ']+#', DS, $path); + while (preg_match($pattern, $path)) { + $path = preg_replace($pattern2, DS, $path); } if ($realpath === false && ($path[0] == '/' || $path[1] == ':')) { $path = str_ireplace(getcwd(), '.', $path); diff --git a/libs/sysplugins/smarty_internal_data.php b/libs/sysplugins/smarty_internal_data.php index f7efa82d..b27f8478 100644 --- a/libs/sysplugins/smarty_internal_data.php +++ b/libs/sysplugins/smarty_internal_data.php @@ -22,18 +22,21 @@ class Smarty_Internal_Data * @var string */ public $template_class = 'Smarty_Internal_Template'; + /** * template variables * * @var array */ public $tpl_vars = array(); + /** * parent template (if any) * * @var Smarty_Internal_Template */ public $parent = null; + /** * configuration settings * @@ -41,6 +44,13 @@ class Smarty_Internal_Data */ public $config_vars = array(); + /** + * universal cache + * + * @var array() + */ + public $_cache = array(); + /** * assigns a Smarty variable * @@ -48,7 +58,8 @@ class Smarty_Internal_Data * @param mixed $value the value to assign * @param boolean $nocache if true any output of this variable will be not cached * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function assign($tpl_var, $value = null, $nocache = false) { @@ -74,7 +85,8 @@ class Smarty_Internal_Data * @param mixed $value the value to assign * @param boolean $nocache if true any output of this variable will be not cached * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function assignGlobal($varname, $value = null, $nocache = false) { @@ -97,7 +109,8 @@ class Smarty_Internal_Data * @param $value * @param boolean $nocache if true any output of this variable will be not cached * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function assignByRef($tpl_var, &$value, $nocache = false) { @@ -117,7 +130,8 @@ class Smarty_Internal_Data * @param boolean $merge flag if array elements shall be merged * @param boolean $nocache if true any output of this variable will be not cached * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function append($tpl_var, $value = null, $merge = false, $nocache = false) { @@ -132,7 +146,8 @@ class Smarty_Internal_Data * @param mixed &$value the referenced value to append * @param boolean $merge flag if array elements shall be merged * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function appendByRef($tpl_var, &$value, $merge = false) { @@ -159,7 +174,8 @@ class Smarty_Internal_Data * * @param string|array $tpl_var the template variable(s) to clear * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function clearAssign($tpl_var) { @@ -177,7 +193,8 @@ class Smarty_Internal_Data /** * clear all the assigned template variables. * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function clearAllAssign() { @@ -192,7 +209,8 @@ class Smarty_Internal_Data * @param string $config_file filename * @param mixed $sections array of section names, single section or null * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function configLoad($config_file, $sections = null) { @@ -247,7 +265,8 @@ class Smarty_Internal_Data * * @param string $varname variable name or null * - * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for chaining + * @return Smarty_Internal_Data current Smarty_Internal_Data (or Smarty or Smarty_Internal_Template) instance for + * chaining */ public function clearConfig($varname = null) { diff --git a/libs/sysplugins/smarty_internal_extension_loadplugin.php b/libs/sysplugins/smarty_internal_extension_loadplugin.php index 1f05b7ba..1b3316ba 100644 --- a/libs/sysplugins/smarty_internal_extension_loadplugin.php +++ b/libs/sysplugins/smarty_internal_extension_loadplugin.php @@ -34,19 +34,19 @@ class Smarty_Internal_Extension_LoadPlugin } if (!empty($match[2])) { $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; - if (isset($smarty->_is_file_cache[$file])) { - if ($smarty->_is_file_cache[$file] !== false) { - return $smarty->_is_file_cache[$file]; + if (isset($smarty->_cache['plugin_files'][$file])) { + if ($smarty->_cache['plugin_files'][$file] !== false) { + return $smarty->_cache['plugin_files'][$file]; } else { return false; } } else { if (is_file($file)) { - $smarty->_is_file_cache[$file] = $file; + $smarty->_cache['plugin_files'][$file] = $file; require_once($file); return $file; } else { - $smarty->_is_file_cache[$file] = false; + $smarty->_cache['plugin_files'][$file] = false; return false; } } @@ -54,36 +54,50 @@ class Smarty_Internal_Extension_LoadPlugin // plugin filename is expected to be: [type].[name].php $_plugin_filename = "{$match[1]}.{$match[4]}.php"; $_lower_filename = strtolower($_plugin_filename); - $_different = $_lower_filename != $_plugin_filename; - // loop through plugin dirs and find the plugin - $names = array(); - foreach ($smarty->getPluginsDir() as $_plugin_dir) { - $names[] = $_plugin_dir . $_plugin_filename; - if ($_different) { - $names[] = $_plugin_dir . $_lower_filename; - } - } - foreach ($names as $path) { - $file = $smarty->use_include_path ? $smarty->_realpath($path, false) : $path; - if (isset($smarty->_is_file_cache[$file])) { - if ($smarty->_is_file_cache[$file] !== false) { - return $smarty->_is_file_cache[$file]; + if (isset($smarty->_cache['plugin_files'])) { + if (isset($smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename])) { + if (!$smarty->use_include_path || + $smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename] !== false + ) { + return $smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename]; } } - if (is_file($file)) { - $smarty->_is_file_cache[$file] = $file; - require_once($file); - return $file; + if (!$smarty->use_include_path || Smarty_Internal_Get_Include_Path::isNewIncludePath($smarty)) { + unset($smarty->_cache['plugin_files']['include_path']); + } else { + if (isset($smarty->_cache['plugin_files']['include_path'][$_lower_filename])) { + return $smarty->_cache['plugin_files']['include_path'][$_lower_filename]; + } + } + } + $_file_names = array($_plugin_filename); + if ($_lower_filename != $_plugin_filename) { + $_file_names[] = $_lower_filename; + } + $_p_dirs = $smarty->getPluginsDir(); + if (!isset($smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename])) { + // loop through plugin dirs and find the plugin + foreach ($_p_dirs as $_plugin_dir) { + foreach ($_file_names as $name) { + $file = $_plugin_dir . $name; + if (is_file($file)) { + $smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename] = $file; + require_once($file); + return $file; + } + $smarty->_cache['plugin_files']['plugins_dir'][$_lower_filename] = false; + } } - $smarty->_is_file_cache[$file] = false; } if ($smarty->use_include_path) { - // try PHP include_path - $path = Smarty_Internal_Get_Include_Path::getIncludePath($names, null, $smarty); - if ($path !== false) { - $smarty->_is_file_cache[$path] = $path; - require_once($path); - return $path; + foreach ($_file_names as $_file_name) { + // try PHP include_path + $file = Smarty_Internal_Get_Include_Path::getIncludePath($_p_dirs, $_file_name, $smarty); + $smarty->_cache['plugin_files']['include_path'][$_lower_filename] = $file; + if ($file !== false) { + require_once($file); + return $file; + } } } // no plugin loaded diff --git a/libs/sysplugins/smarty_internal_get_include_path.php b/libs/sysplugins/smarty_internal_get_include_path.php index ba971e25..0b0da79f 100644 --- a/libs/sysplugins/smarty_internal_get_include_path.php +++ b/libs/sysplugins/smarty_internal_get_include_path.php @@ -15,6 +15,110 @@ */ class Smarty_Internal_Get_Include_Path { + /** + * include path cache + * + * @var string + */ + static $_include_path = ''; + + /** + * include path directory cache + * + * @var array + */ + static $_include_dirs = array(); + + /** + * include path directory cache + * + * @var array + */ + static $_user_dirs = array(); + + /** + * stream cache + * + * @var array + */ + static $stream = array(); + + /** + * stream cache + * + * @var array + */ + static $isFile = array(); + + /** + * stream cache + * + * @var array + */ + static $isPath = array(); + + /** + * stream cache + * + * @var array + */ + static $number = array(); + + /** + * status cache + * + * @var null + */ + static $_has_stream_include = null; + + /** + * Numger for array index + * + * @var int + */ + static $counter = 0; + + /** + * Check if include path was updated + * + * @return bool + * + */ + public static function isNewIncludePath(Smarty $smarty) + { + if (!isset(self::$_has_stream_include)) { + self::$_has_stream_include = ($smarty->use_include_path === 2) && + function_exists('stream_resolve_include_path'); + } + $_i_path = get_include_path(); + if (self::$_include_path != $_i_path) { + self::$_include_dirs = array(); + self::$_include_path = $_i_path; + $_dirs = (array) explode(PATH_SEPARATOR, $_i_path); + foreach ($_dirs as $_path) { + if ($_path[0] != '/' && isset($dir[1]) && $dir[1] != ':') { + $_path = $smarty->_realpath($_path . DS, true); + } + if (is_dir($_path)) { + self::$_include_dirs[] = $smarty->_realpath($_path . DS, true); + } + } + return true; + } + return false; + } + + /** + * return array with include path directories + * + * @return array + */ + public static function getIncludePathDirs(Smarty $smarty) + { + Smarty_Internal_Get_Include_Path::isNewIncludePath($smarty); + return self::$_include_dirs; + } + /** * Return full file path from PHP include_path * @@ -27,37 +131,50 @@ class Smarty_Internal_Get_Include_Path */ public static function getIncludePath($dirs, $file, Smarty $smarty) { - static $_include_path = ''; - static $_include_dirs = array(); - static $_has_stream_include = null; - $_i_path = get_include_path(); - if ($_include_path != $_i_path) { - $_include_path = $_i_path; - $_dirs = (array) explode(PATH_SEPARATOR, $_i_path); - $_include_dirs = array(); - foreach ($_dirs as $_path) { - $_include_dirs[] = rtrim($_path, '/\\'); - } - $_has_stream_include = function_exists('stream_resolve_include_path'); - } + self::isNewIncludePath($smarty); // try PHP include_path foreach ($dirs as $dir) { - if ($dir[0] == '/' || $dir[1] == ':') { - $dir = $smarty->_realpath($dir, false); - } - if ($dir[0] != '/' && $dir[1] != ':') { - $_d_path = $dir . (isset($file) ? $file : ''); - if ($_has_stream_include) { - // available since PHP 5.3.2 - $path = stream_resolve_include_path($_d_path); - if ($path !== false && is_file($path)) { - return $smarty->_realpath($path, true); - } + $dir_n = isset(self::$number[$dir]) ? self::$number[$dir] : self::$number[$dir] = self::$counter ++; + if (isset(self::$isFile[$dir_n][$file])) { + if (self::$isFile[$dir_n][$file]) { + return self::$isFile[$dir_n][$file]; + } else { + continue; } - foreach ($_include_dirs as $_i_path) { - if (is_file($_i_path . DS . $_d_path)) { - return $smarty->_realpath($_i_path . DS . $_d_path, true); + } + if (isset(self::$_user_dirs[$dir_n])) { + if (false === self::$_user_dirs[$dir_n]) { + continue; + } else { + $_u_dir = self::$_user_dirs[$dir_n]; + } + } else { + if ($dir[0] == '/' || $dir[1] == ':') { + $_u_dir = str_ireplace(getcwd(), '.', $dir); + if ($_u_dir[0] == '/' || $_u_dir[1] == ':') { + self::$_user_dirs[$dir_n] = false; + continue; } + self::$_user_dirs[$dir_n] = $_u_dir; + } else { + $_u_dir = self::$_user_dirs[$dir_n] = $dir; + } + } + $_d_path = $_u_dir . (isset($file) ? $file : ''); + if (self::$_has_stream_include) { + // available since PHP 5.3.2 + self::$stream[$_d_path] = isset(self::$stream[$_d_path]) ? self::$stream[$_d_path] : ($path = stream_resolve_include_path($_d_path)) ? is_file($path) : false; + if (self::$stream[$_d_path]) { + return self::$isFile[$dir_n][$file] = self::$stream[$_d_path]; + } + } + foreach (self::$_include_dirs as $key => $_i_path) { + $path = self::$isPath[$key][$dir_n] = isset(self::$isPath[$key][$dir_n]) ? self::$isPath[$key][$dir_n] : is_dir($_i_path . + $_u_dir) ? $_i_path . + substr($_u_dir, 2) : false; + $_file = self::$isFile[$dir_n][$file] = ($path && is_file($path . $file)) ? $path . $file : false; + if ($_file) { + return $_file; } } } diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php index c916bf5f..33a46c6a 100644 --- a/libs/sysplugins/smarty_security.php +++ b/libs/sysplugins/smarty_security.php @@ -239,11 +239,11 @@ class Smarty_Security protected $_trusted_dir = null; /** - * Cache for $_include_path lookup + * Cache for include path status * - * @var string + * @var bool */ - protected $_include_path = ''; + protected $_include_path_status = false; /** * Cache for $_include_array lookup @@ -271,7 +271,9 @@ class Smarty_Security */ public function isTrustedPhpFunction($function_name, $compiler) { - if (isset($this->php_functions) && (empty($this->php_functions) || in_array($function_name, $this->php_functions))) { + if (isset($this->php_functions) && + (empty($this->php_functions) || in_array($function_name, $this->php_functions)) + ) { return true; } @@ -291,7 +293,9 @@ class Smarty_Security */ public function isTrustedStaticClass($class_name, $compiler) { - if (isset($this->static_classes) && (empty($this->static_classes) || in_array($class_name, $this->static_classes))) { + if (isset($this->static_classes) && + (empty($this->static_classes) || in_array($class_name, $this->static_classes)) + ) { return true; } @@ -329,7 +333,9 @@ class Smarty_Security // fall back return $this->isTrustedStaticClass($class_name, $compiler); } - if (isset($allowed[$class_name]) && (empty($allowed[$class_name]) || in_array($name, $allowed[$class_name]))) { + if (isset($allowed[$class_name]) && + (empty($allowed[$class_name]) || in_array($name, $allowed[$class_name])) + ) { return true; } } @@ -348,7 +354,9 @@ class Smarty_Security */ public function isTrustedPhpModifier($modifier_name, $compiler) { - if (isset($this->php_modifiers) && (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers))) { + if (isset($this->php_modifiers) && + (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers)) + ) { return true; } @@ -434,7 +442,9 @@ class Smarty_Security } else { $compiler->trigger_template_error("modifier '{$modifier_name}' disabled by security setting", $compiler->lex->taglineno); } - } elseif (in_array($modifier_name, $this->allowed_modifiers) && !in_array($modifier_name, $this->disabled_modifiers)) { + } elseif (in_array($modifier_name, $this->allowed_modifiers) && + !in_array($modifier_name, $this->disabled_modifiers) + ) { return true; } else { $compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting", $compiler->lex->taglineno); @@ -498,27 +508,23 @@ class Smarty_Security */ public function isTrustedResourceDir($filepath, $isConfig = null) { - if ($this->smarty->use_include_path) { - $_include_path = get_include_path(); - } else { - $_include_path = ''; - } - if ($this->_include_path != $_include_path) { + if ($this->_include_path_status !== $this->smarty->use_include_path) { foreach ($this->_include_dir as $directory) { unset($this->_resource_dir[$directory]); } if ($this->smarty->use_include_path) { $this->_include_dir = array(); - $_dirs = (array) explode(PATH_SEPARATOR, get_include_path()); - foreach ($_dirs as $_dir) { - $directory = $this->smarty->_realpath($_dir . DS, true); + $_dirs = Smarty_Internal_Get_Include_Path::getIncludePathDirs($this->smarty); + foreach ($_dirs as $directory) { $this->_include_dir[] = $directory; $this->_resource_dir[$directory] = true; } } - $this->_include_path = $_include_path; + $this->_include_path_status = $this->smarty->use_include_path; } - if ($isConfig !== true) { + if ($isConfig !== true && + (!isset($this->smarty->_cache['template_dir_new']) || $this->smarty->_cache['template_dir_new']) + ) { $_dir = $this->smarty->getTemplateDir(); if ($this->_template_dir !== $_dir) { foreach ($this->_template_dir as $directory) { @@ -529,8 +535,11 @@ class Smarty_Security } $this->_template_dir = $_dir; } + $this->smarty->_cache['template_dir_new'] = false; } - if ($isConfig !== false) { + if ($isConfig !== false && + (!isset($this->smarty->_cache['config_dir_new']) || $this->smarty->_cache['config_dir_new']) + ) { $_dir = $this->smarty->getConfigDir(); if ($this->_config_dir !== $_dir) { foreach ($this->_config_dir as $directory) { @@ -541,6 +550,7 @@ class Smarty_Security } $this->_config_dir = $_dir; } + $this->smarty->_cache['config_dir_new'] = false; } if ($this->_secure_dir !== (array) $this->secure_dir) { foreach ($this->_secure_dir as $directory) { @@ -552,30 +562,8 @@ class Smarty_Security } $this->_secure_dir = (array) $this->secure_dir; } - - $_filepath = $filepath; - $directory = dirname($_filepath) . DS; - $_directory = array(); - while (true) { - // remember the directory to add it to _resource_dir in case we're successful - $_directory[$directory] = true; - // test if the directory is trusted - if (isset($this->_resource_dir[$directory])) { - // merge sub directories of current $directory into _resource_dir to speed up subsequent lookup - $this->_resource_dir = array_merge($this->_resource_dir, $_directory); - - return true; - } - // abort if we've reached root - if (!preg_match('#[\\\/][^\\\/]+[\\\/]$#', $directory)) { - break; - } - // bubble up one level - $directory = preg_replace('#[\\\/][^\\\/]+[\\\/]$#', DS, $directory); - } - - // give up - throw new SmartyException("directory '{$_filepath}' not allowed by security setting"); + $this->_resource_dir = $this->_checkDir($filepath, $this->_resource_dir); + return true; } /** @@ -630,28 +618,8 @@ class Smarty_Security } } - $_filepath = $this->smarty->_realpath($filepath, true); - $directory = dirname($_filepath) . DS; - $_directory = array(); - while (true) { - // remember the directory to add it to _resource_dir in case we're successful - $_directory[] = $directory; - // test if the directory is trusted - if (isset($this->_php_resource_dir[$directory])) { - // merge sub directories of current $directory into _resource_dir to speed up subsequent lookup - $this->_php_resource_dir = array_merge($this->_php_resource_dir, $_directory); - - return true; - } - // abort if we've reached root - if (($pos = strrpos($directory, DS)) === false || !isset($directory[2])) { - break; - } - // bubble up one level - $directory = substr($directory, 0, $pos); - } - - throw new SmartyException("directory '{$_filepath}' not allowed by security setting"); + $this->_php_resource_dir = $this->_checkDir($this->smarty->_realpath($filepath, true), $this->_php_resource_dir); + return true; } /** @@ -680,6 +648,41 @@ class Smarty_Security } } + /** + * Check if file is inside a valid directory + * + * @param string $filepath + * @param array $dirs valid directories + * + * @return array + * @throws \SmartyException + */ + private function _checkDir($filepath, $dirs) + { + $directory = dirname($filepath) . DS; + $_directory = array(); + while (true) { + // remember the directory to add it to _resource_dir in case we're successful + $_directory[$directory] = true; + // test if the directory is trusted + if (isset($dirs[$directory])) { + // merge sub directories of current $directory into _resource_dir to speed up subsequent lookup + $dirs = array_merge($dirs, $_directory); + + return $dirs; + } + // abort if we've reached root + if (!preg_match('#[\\\/][^\\\/]+[\\\/]$#', $directory)) { + break; + } + // bubble up one level + $directory = preg_replace('#[\\\/][^\\\/]+[\\\/]$#', DS, $directory); + } + + // give up + throw new SmartyException("directory '{$filepath}' not allowed by security setting"); + } + /** * Loads security class and enables security * @@ -709,5 +712,4 @@ class Smarty_Security } return; } - }