diff --git a/change_log.txt b/change_log.txt index fde5f333..b62cfa3d 100644 --- a/change_log.txt +++ b/change_log.txt @@ -7,6 +7,7 @@ - move getStreamVariable() into extension - move $smarty->append() and $smarty->appendByRef() into extension - optimize autoloader + - optimize file path normalization 27.06.2015 - bugfix resolve naming conflict between custom Smarty delimiter '<%' and PHP ASP tags https://github.com/smarty-php/smarty/issues/64 diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 2334032c..5aa2c106 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/17'; + const SMARTY_VERSION = '3.1.28-dev/18'; /** * define variable scopes @@ -1390,14 +1390,13 @@ class Smarty extends Smarty_Internal_TemplateBase */ public function _realpath($path) { + static $pattern = null; + static $pattern2 = null; if ($path[0] !== '/' && $path[1] !== ':') { $path = getcwd() . DS . $path; } - //return realpath($path) . DS; - $first = true; - while ($first || strrpos($path, '.' . DS) !== false) { - $path = preg_replace('#([\\\/]([^\\\/]+[\\\/]){2}([.][.][\\\/]){2})|([\\\/][^\\\/]+[\\\/][.][.][\\\/])|([\\\/]+([.][\\\/]+)*)#', DS, $path); - $first = false; + 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_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php index 1c49654a..ff28c229 100644 --- a/libs/sysplugins/smarty_internal_resource_file.php +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -17,13 +17,6 @@ */ class Smarty_Internal_Resource_File extends Smarty_Resource { - /** - * Inverse DS - * - * @var string - */ - private $invDS = ''; - /** * build template filepath by traversing the template_dir array * @@ -36,21 +29,19 @@ class Smarty_Internal_Resource_File extends Smarty_Resource protected function buildFilepath(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { $file = $source->name; - $this->invDS = (DS == '/') ? '\\\\' : '/'; - preg_match('#(^(?P[\\\/]|[a-zA-Z]:[\\\/])|(\[(?P[^\]]+)\])|(?P\.[\\\/]))|((?P\.[\\\/])|(?P[' . $this->invDS . ']))#', $file, $fileMatch); - // save basename - if (!empty($fileMatch['absolute'])) { - $file = $this->normalizePath($file); + // absolute file ? + if ($file[0] == '/' || $file[1] == ':' ) { + $file = $source->smarty->_realpath($file); return is_file($file) ? $file : false; } // go relative to a given template? - if (!empty($fileMatch['rel']) && $_template && $_template->parent instanceof Smarty_Internal_Template) { + if ($file[0] == '.' && $_template && $_template->parent instanceof Smarty_Internal_Template && preg_match('#^[.]{1,2}[\\\/]#', $file)) { if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && !$_template->parent->allow_relative_path) { throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); } $path = dirname($_template->parent->source->filepath) . DS . $file; // normalize path - $path = $this->normalizePath($path); + $path = $source->smarty->_realpath($path); // files relative to a template only get one shot return is_file($path) ? $path : false; } @@ -61,8 +52,8 @@ class Smarty_Internal_Resource_File extends Smarty_Resource $_directories = $source->smarty->getTemplateDir(); } // template_dir index? - if (!empty($fileMatch['index'])) { - $index = $fileMatch['index']; + if ($file[0] == '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { + $index = $fileMatch[1]; $_directory = null; // try string indexes if (isset($_directories[$index])) { @@ -79,9 +70,8 @@ class Smarty_Internal_Resource_File extends Smarty_Resource } } if ($_directory) { - preg_match('#\](.+)$#', $file, $fileMatch); - $path = $_directory . $fileMatch[1]; - $path = $this->normalizePath($path); + $path = $_directory . $fileMatch[2]; + $path = $source->smarty->_realpath($path); if (is_file($path)) { return $path; } @@ -91,11 +81,10 @@ class Smarty_Internal_Resource_File extends Smarty_Resource } } - $normalize = !empty($fileMatch['rel']) || !empty($fileMatch['rel2']) || !empty($fileMatch['ds']); // relative file name? foreach ($_directories as $_directory) { $_filepath = $_directory . $file; - $path = $normalize ? $this->normalizePath($_filepath) : $_filepath; + $path = $source->smarty->_realpath($_filepath); if (is_file($path)) { return $path; } @@ -107,7 +96,7 @@ class Smarty_Internal_Resource_File extends Smarty_Resource $_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath); } if ($_filepath !== false) { - $path = $this->normalizePath($_filepath); + $path = $source->smarty->_realpath($_filepath); if (is_file($path)) { return $path; } @@ -115,28 +104,10 @@ class Smarty_Internal_Resource_File extends Smarty_Resource } } // Could be relative to cwd - $path = $this->normalizePath(getcwd() . DS . $file); + $path = $source->smarty->_realpath($file); return is_file($path) ? $path : false; } - /** - * Normalize path - * - remove /./ and /../ - * - make it absolute - * - * @param string $path file path - * - * @return string - */ - public function normalizePath($path) - { - $first = true; - while (strrpos($path, '.' . DS) !== false || ($first && strrpos($path, $this->invDS[0]) !== false)) { - $path = preg_replace('#([\\\/]+([.][\\\/]+)+)|([\\\/]+([^\\\/]+[\\\/]+){2}([.][.][\\\/]+){2})|([\\\/]+[^\\\/]+[\\\/]+[.][.][\\\/]+)|[' . $this->invDS . ']+#', DS, $path); - $first = false; - } - return $path; - } /** * test is file exists and save timestamp