optimization

This commit is contained in:
Uwe Tews
2015-07-12 07:03:55 +02:00
parent 208628080f
commit 61253c1999
5 changed files with 319 additions and 174 deletions

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}