From 3052406cfcabc4586ccca320a6396cf9f2c57c82 Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Mon, 29 Jun 2015 02:41:42 +0200 Subject: [PATCH] - fix $smarty->use_include_path option and optimize file path code --- libs/Smarty.class.php | 25 +++---- .../smarty_internal_extension_loadplugin.php | 71 ++++++++++++------- .../smarty_internal_get_include_path.php | 43 +++++++---- .../smarty_internal_resource_file.php | 30 +++----- libs/sysplugins/smarty_security.php | 6 ++ 5 files changed, 103 insertions(+), 72 deletions(-) diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 5aa2c106..debcc3a0 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -933,7 +933,7 @@ class Smarty extends Smarty_Internal_TemplateBase * Set template directory * * @param string|array $template_dir directory(s) of template sources - * @param bool $isConfig true for config_dir + * @param bool $isConfig true for config_dir * * @return \Smarty current Smarty instance for chaining */ @@ -952,7 +952,7 @@ class Smarty extends Smarty_Internal_TemplateBase * * @param string|array $template_dir directory(s) of template sources * @param string $key of the array element to assign the template dir to - * @param bool $isConfig true for config_dir + * @param bool $isConfig true for config_dir * * @return Smarty current Smarty instance for chaining */ @@ -973,8 +973,8 @@ class Smarty extends Smarty_Internal_TemplateBase /** * Get template directories * - * @param mixed $index index of directory to get, null to get all - * @param bool $isConfig true for config_dir + * @param mixed $index index of directory to get, null to get all + * @param bool $isConfig true for config_dir * * @return array list of template directories, or directory of $index */ @@ -989,7 +989,7 @@ class Smarty extends Smarty_Internal_TemplateBase } if ($this->_flags[$type] == false) { foreach ($this->{$type} as $k => $v) { - $this->{$type}[$k] = $this->_realpath($v . DS); + $this->{$type}[$k] = $this->_realpath($v . DS, $this->use_include_path); } $this->_flags[$type] = true; } @@ -1085,7 +1085,7 @@ class Smarty extends Smarty_Internal_TemplateBase $plugins_dir = (array) $this->plugins_dir; $this->plugins_dir = array(); foreach ($plugins_dir as $v) { - $this->plugins_dir[] = $this->_realpath($v . DS); + $this->plugins_dir[] = $this->_realpath($v . DS, $this->use_include_path); } $this->plugins_dir = array_unique($this->plugins_dir); } @@ -1175,7 +1175,7 @@ class Smarty extends Smarty_Internal_TemplateBase $rp = $this->_flags[$dirName]; if (is_array($dir)) { foreach ($dir as $k => $v) { - $path = $rp ? $this->_realpath($v . DS) : $v; + $path = $rp ? $this->_realpath($v . DS, $this->use_include_path) : $v; if (is_int($k)) { // indexes are not merged but appended $this->{$dirName}[] = $path; @@ -1185,7 +1185,7 @@ class Smarty extends Smarty_Internal_TemplateBase } } } else { - $path = $rp ? $this->_realpath($dir . DS) : $dir; + $path = $rp ? $this->_realpath($dir . DS, $this->use_include_path) : $dir; if ($key !== null) { // override directory at specified index $this->{$dirName}[$key] = $path; @@ -1384,18 +1384,19 @@ class Smarty extends Smarty_Internal_TemplateBase * - remove /./ and /../ * - make it absolute * - * @param string $path file path + * @param string $path file path + * @param bool $relative leave $path relative * * @return string */ - public function _realpath($path) + public function _realpath($path, $relative = false) { static $pattern = null; static $pattern2 = null; - if ($path[0] !== '/' && $path[1] !== ':') { + if (!$relative && $path[0] !== '/' && $path[1] !== ':') { $path = getcwd() . DS . $path; } - while (preg_match(isset($pattern) ? $pattern : $pattern = '#([.][\\\/])|[' . (DS == '/' ? '\\\\' : '/') . ']|[\\\/]{2,}#', $path)) { + while (preg_match(isset($pattern) ? $pattern : $pattern = '#([\\\/][.]+[\\\/])|[' . (DS == '/' ? '\\\\' : '/') . ']|[\\\/]{2,}#', $path)) { $path = preg_replace(isset($pattern2) ? $pattern2 : $pattern2 = '#([\\\/]+([.][\\\/]+)+)|([\\\/]+([^\\\/]+[\\\/]+){2}([.][.][\\\/]+){2})|([\\\/]+[^\\\/]+[\\\/]+[.][.][\\\/]+)|[\\\/]{2,}|[' . (DS == '/' ? '\\\\' : '/') . ']+#', DS, $path); } return $path; diff --git a/libs/sysplugins/smarty_internal_extension_loadplugin.php b/libs/sysplugins/smarty_internal_extension_loadplugin.php index 37ac1fdd..8c2cba22 100644 --- a/libs/sysplugins/smarty_internal_extension_loadplugin.php +++ b/libs/sysplugins/smarty_internal_extension_loadplugin.php @@ -29,43 +29,62 @@ class Smarty_Internal_Extension_LoadPlugin if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) { return true; } - // Plugin name is expected to be: Smarty_[Type]_[Name] - $_name_parts = explode('_', $plugin_name, 3); - // class name must have three parts to be valid plugin - // count($_name_parts) < 3 === !isset($_name_parts[2]) - if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') { + if (!preg_match('#^smarty_((internal)|([^_]+))_(.+)$#i', $plugin_name, $match)) { throw new SmartyException("plugin {$plugin_name} is not a valid name format"); } - // if type is "internal", get plugin from sysplugins - if (strtolower($_name_parts[1]) == 'internal') { + if (!empty($match[2])) { $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; - if (isset($smarty->_is_file_cache[$file]) ? $smarty->_is_file_cache[$file] : $smarty->_is_file_cache[$file] = is_file($file)) { - require_once($file); - return $file; + if (isset($smarty->_is_file_cache[$file])) { + if ($smarty->_is_file_cache[$file] !== false) { + return $smarty->_is_file_cache[$file]; + } else { + return false; + } } else { - return false; + if (is_file($file)) { + $smarty->_is_file_cache[$file] = $file; + require_once($file); + return $file; + } else { + $smarty->_is_file_cache[$file] = false; + return false; + } } } // plugin filename is expected to be: [type].[name].php - $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.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 = array($_plugin_dir . $_plugin_filename, $_plugin_dir . strtolower($_plugin_filename),); - foreach ($names as $file) { - if (isset($smarty->_is_file_cache[$file]) ? $smarty->_is_file_cache[$file] : $smarty->_is_file_cache[$file] = is_file($file)) { - require_once($file); - return $file; - } - if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { - // try PHP include_path - $file = Smarty_Internal_Get_Include_Path::getIncludePath($file); - if ($file !== false) { - require_once($file); - return $file; - } + $names[] = $_plugin_dir . $_plugin_filename; + if ($_different) { + $names[] = $_plugin_dir . $_lower_filename; + } + } + foreach ($names as $path) { + $file = $smarty->use_include_path ? $smarty->_realpath($path) : $path; + if (isset($smarty->_is_file_cache[$file])) { + if ($smarty->_is_file_cache[$file] !== false) { + return $smarty->_is_file_cache[$file]; } } + if (is_file($file)) { + $smarty->_is_file_cache[$file] = $file; + require_once($file); + return $file; + } + $smarty->_is_file_cache[$file] = $file; + } + 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; + } } // no plugin loaded return false; diff --git a/libs/sysplugins/smarty_internal_get_include_path.php b/libs/sysplugins/smarty_internal_get_include_path.php index d46ca702..c85de521 100644 --- a/libs/sysplugins/smarty_internal_get_include_path.php +++ b/libs/sysplugins/smarty_internal_get_include_path.php @@ -18,29 +18,42 @@ class Smarty_Internal_Get_Include_Path /** * Return full file path from PHP include_path * - * @param string $filepath filepath + * @param string[] $dirs + * @param string $file + * @param \Smarty $smarty + * + * @return bool|string full filepath or false * - * @return string|boolean full filepath or false */ - public static function getIncludePath($filepath) + public static function getIncludePath($dirs, $file, Smarty $smarty) { static $_include_path = null; - - if (function_exists('stream_resolve_include_path')) { - // available since PHP 5.3.2 - return stream_resolve_include_path($filepath); - } - + static $_has_stream_include = null; if ($_include_path === null) { - $_include_path = explode(PATH_SEPARATOR, get_include_path()); + $_include_path = (array) explode(PATH_SEPARATOR, get_include_path()); + foreach ($_include_path as $key => $_path) { + $_include_path[$key] = rtrim($_path, '/\\'); + } + $_has_stream_include = function_exists('stream_resolve_include_path'); } - - foreach ($_include_path as $_path) { - if (file_exists($_path . DS . $filepath)) { - return $_path . DS . $filepath; + // try PHP include_path + foreach ($dirs as $dir) { + 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); + } + } + foreach ($_include_path as $_i_path) { + if (is_file($_i_path . DS . $_d_path)) { + return $smarty->_realpath($_i_path . DS . $_d_path); + } + } } } - return false; } } diff --git a/libs/sysplugins/smarty_internal_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index ccc9ff4b..6d7abb3e 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -46,11 +46,7 @@ class Smarty_Internal_Resource_File extends Smarty_Resource return is_file($path) ? $path : false; } - if ($source->isConfig) { - $_directories = $source->smarty->getConfigDir(); - } else { - $_directories = $source->smarty->getTemplateDir(); - } + $_directories = $source->smarty->getTemplateDir(null, $source->isConfig); // template_dir index? if ($file[0] == '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { $index = $fileMatch[1]; @@ -83,25 +79,21 @@ class Smarty_Internal_Resource_File extends Smarty_Resource // relative file name? foreach ($_directories as $_directory) { - $_filepath = $_directory . $file; - $path = $source->smarty->_realpath($_filepath); + $path = $_directory . $file; if (is_file($path)) { - return $path; - } - if ($source->smarty->use_include_path && !preg_match('/^([\\\/]|[a-zA-Z]:[\\\/])/', $_directory)) { - // try PHP include_path - $_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath); - if ($_filepath !== false) { - $path = $source->smarty->_realpath($_filepath); - if (is_file($path)) { - return $path; - } - } + return $source->smarty->_realpath($path); } } // Could be relative to cwd $path = $source->smarty->_realpath($file); - return is_file($path) ? $path : false; + if (is_file($path)) { + return $path; + } + // Use include path ? + if ($source->smarty->use_include_path) { + return Smarty_Internal_Get_Include_Path::getIncludePath($_directories, $file, $source->smarty); + } + return false; } /** diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php index 57534b2d..e52ec497 100644 --- a/libs/sysplugins/smarty_security.php +++ b/libs/sysplugins/smarty_security.php @@ -490,6 +490,9 @@ class Smarty_Security unset($this->_resource_dir[$directory]); } foreach ($_dir as $directory) { + if ($this->smarty->use_include_path) { + $directory = $this->smarty->_realpath($directory); + } $this->_resource_dir[$directory] = true; } $this->_template_dir = $_dir; @@ -502,6 +505,9 @@ class Smarty_Security unset($this->_resource_dir[$directory]); } foreach ($_dir as $directory) { + if ($this->smarty->use_include_path) { + $directory = $this->smarty->_realpath($directory); + } $this->_resource_dir[$directory] = true; } $this->_config_dir = $_dir;