1
0

Smarty update to 3.1.9 - see changeLog

This commit is contained in:
Ian
2012-06-09 10:43:58 +02:00
parent 7294e9679c
commit 612a7260fc
17 changed files with 1528 additions and 1358 deletions

View File

@ -2,7 +2,7 @@
/**
* Project: Smarty: the PHP compiling template engine
* File: Smarty.class.php
* SVN: $Id: Smarty.class.php 4551 2012-02-06 20:45:10Z rodneyrehm $
* SVN: $Id: Smarty.class.php 4614 2012-05-24 15:13:19Z rodneyrehm $
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,7 +28,7 @@
* @author Uwe Tews
* @author Rodney Rehm
* @package Smarty
* @version 3.1.8
* @version 3.1.9
*/
/**
@ -113,7 +113,7 @@ class Smarty extends Smarty_Internal_TemplateBase {
/**
* smarty version
*/
const SMARTY_VERSION = 'Smarty-3.1.8';
const SMARTY_VERSION = 'Smarty-3.1.9';
/**
* define variable scopes
@ -190,6 +190,10 @@ class Smarty extends Smarty_Internal_TemplateBase {
*/
public static $_UTF8_MODIFIER = 'u';
/**
* Flag denoting if operating system is windows
*/
public static $_IS_WINDOWS = false;
/**#@+
* variables
@ -1464,6 +1468,9 @@ class Smarty extends Smarty_Internal_TemplateBase {
}
}
// Check if we're running on windows
Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
if (Smarty::$_CHARSET !== 'UTF-8') {
Smarty::$_UTF8_MODIFIER = '';

View File

@ -150,6 +150,8 @@ function smarty_function_html_options_optoutput($key, $value, $selected, $id, $c
trigger_error("html_options: value is an object of class '". get_class($value) ."' without __toString() method", E_USER_NOTICE);
return '';
}
} else {
$value = smarty_function_escape_special_chars((string) $value);
}
$_html_result .= $_html_class . $_html_id . '>' . $value . '</option>' . "\n";
$idx++;

View File

@ -35,7 +35,7 @@ function smarty_modifier_date_format($string, $format=null, $default_date='', $f
* Include the {@link shared.make_timestamp.php} plugin
*/
require_once(SMARTY_PLUGINS_DIR . 'shared.make_timestamp.php');
if ($string != '') {
if ($string != '' && $string != '0000-00-00' && $string != '0000-00-00 00:00:00') {
$timestamp = smarty_make_timestamp($string);
} elseif ($default_date != '') {
$timestamp = smarty_make_timestamp($default_date);

View File

@ -100,9 +100,11 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource {
public function writeCachedContent(Smarty_Internal_Template $_template, $content)
{
if (Smarty_Internal_Write_File::writeFile($_template->cached->filepath, $content, $_template->smarty) === true) {
$_template->cached->timestamp = filemtime($_template->cached->filepath);
$_template->cached->timestamp = @filemtime($_template->cached->filepath);
$_template->cached->exists = !!$_template->cached->timestamp;
return true;
if ($_template->cached->exists) {
return true;
}
}
return false;
}

View File

@ -58,7 +58,14 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase {
if (isset($parameter['smarty_internal_index'])) {
$output = "<?php \$_smarty_tpl->createLocalArrayVariable($_attr[var], $_nocache, $_scope);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];";
} else {
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);";
// implement Smarty2's behaviour of variables assigned by reference
if ($compiler->template->smarty instanceof SmartyBC) {
$output = "<?php if (isset(\$_smarty_tpl->tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
$output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache; \$_smarty_tpl->tpl_vars[$_attr[var]]->scope = $_scope;";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);";
} else {
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_variable($_attr[value], $_nocache, $_scope);";
}
}
if ($_scope == Smarty::SCOPE_PARENT) {
$output .= "\nif (\$_smarty_tpl->parent != null) \$_smarty_tpl->parent->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";

View File

@ -199,7 +199,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
$compiler->template->has_nocache_code = true;
}
foreach($_tpl->required_plugins as $key => $tmp1) {
if ($compiler->nocache) {
if ($compiler->nocache && $compiler->template->caching) {
$code = 'nocache';
} else {
$code = $key;
@ -260,7 +260,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase {
// reset flags
$compiler->parser->current_buffer = $saved_data[1];
$compiler->nocache = $saved_data[2];
//$compiler->smarty->merge_compiled_includes = $saved_data[3];
$compiler->smarty->merge_compiled_includes = $saved_data[3];
// reset flag for {block} tag
$compiler->inheritance = false;
// $_output content has already nocache code processed

View File

@ -26,8 +26,7 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
* @param array $parameter array with compilation parameter
* @return string compiled code
*/
public function compile($args, $compiler, $parameter)
{
public function compile($args, $compiler, $parameter) {
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$output = $parameter['value'];
@ -36,40 +35,92 @@ class Smarty_Internal_Compile_Private_Modifier extends Smarty_Internal_CompileBa
$modifier = $single_modifier[0];
$single_modifier[0] = $output;
$params = implode(',', $single_modifier);
// check for registered modifier
if (isset($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$modifier])) {
$function = $compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$modifier][0];
if (!is_array($function)) {
$output = "{$function}({$params})";
} else {
if (is_object($function[0])) {
$output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' . $modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')';
} else {
$output = $function[0] . '::' . $function[1] . '(' . $params . ')';
}
}
} else if (isset($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0])) {
$output = call_user_func($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0], $single_modifier, $compiler->smarty);
// check for plugin modifiercompiler
} else if ($compiler->smarty->loadPlugin('smarty_modifiercompiler_' . $modifier)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) {
$plugin = 'smarty_modifiercompiler_' . $modifier;
$output = $plugin($single_modifier, $compiler);
}
// check for plugin modifier
} else if ($function = $compiler->getPlugin($modifier, Smarty::PLUGIN_MODIFIER)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) {
$output = "{$function}({$params})";
}
// check if trusted PHP function
} else if (is_callable($modifier)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)) {
$output = "{$modifier}({$params})";
}
// check if we know already the type of modifier
if (isset($compiler->known_modifier_type[$modifier])) {
$modifier_types = array($compiler->known_modifier_type[$modifier]);
} else {
$modifier_types = array(1, 2, 3, 4, 5, 6);
}
foreach ($modifier_types as $type) {
switch ($type) {
case 1:
// registered modifier
if (isset($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$modifier])) {
$function = $compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][$modifier][0];
if (!is_array($function)) {
$output = "{$function}({$params})";
} else {
if (is_object($function[0])) {
$output = '$_smarty_tpl->smarty->registered_plugins[Smarty::PLUGIN_MODIFIER][\'' . $modifier . '\'][0][0]->' . $function[1] . '(' . $params . ')';
} else {
$output = $function[0] . '::' . $function[1] . '(' . $params . ')';
}
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 2:
// registered modifier compiler
if (isset($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0])) {
$output = call_user_func($compiler->smarty->registered_plugins[Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0], $single_modifier, $compiler->smarty);
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 3:
// modifiercompiler plugin
if ($compiler->smarty->loadPlugin('smarty_modifiercompiler_' . $modifier)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) {
$plugin = 'smarty_modifiercompiler_' . $modifier;
$output = $plugin($single_modifier, $compiler);
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 4:
// modifier plugin
if ($function = $compiler->getPlugin($modifier, Smarty::PLUGIN_MODIFIER)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) {
$output = "{$function}({$params})";
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 5:
// PHP function
if (is_callable($modifier)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)) {
$output = "{$modifier}({$params})";
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 6:
// default plugin handler
if (isset($compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier]) || (is_callable($compiler->smarty->default_plugin_handler_func) && $compiler->getPluginFromDefaultHandler($modifier, Smarty::PLUGIN_MODIFIER))) {
$function = $compiler->default_handler_plugins[Smarty::PLUGIN_MODIFIER][$modifier][0];
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy) || $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)) {
$output = "{$function}({$params})";
}
if (isset($compiler->template->required_plugins['nocache'][$modifier][Smarty::PLUGIN_MODIFIER]['file']) || isset($compiler->template->required_plugins['compiled'][$modifier][Smarty::PLUGIN_MODIFIER]['file'])) {
// was a plugin
$compiler->known_modifier_type[$modifier] = 4;
} else {
$compiler->known_modifier_type[$modifier] = $type;
}
break 2;
}
}
}
if (!isset($compiler->known_modifier_type[$modifier])) {
$compiler->trigger_template_error("unknown modifier \"" . $modifier . "\"", $compiler->lex->taglineno);
}
}

View File

@ -266,6 +266,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
// get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $this->tpl_vars;
$tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
} elseif ($parent_scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = &$this->tpl_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
@ -305,6 +306,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
// get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL ) {
$tpl->tpl_vars = $this->tpl_vars;
$tpl->tpl_vars['smarty'] = clone $this->tpl_vars['smarty'];
} elseif ($parent_scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = &$this->tpl_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
@ -442,7 +444,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
$mtime = $this->source->timestamp;
} else {
// file and php types can be checked without loading the respective resource handlers
$mtime = filemtime($_file_to_check[0]);
$mtime = @filemtime($_file_to_check[0]);
}
} elseif ($_file_to_check[2] == 'string') {
continue;
@ -450,7 +452,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
$source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]);
$mtime = $source->timestamp;
}
if ($mtime > $_file_to_check[1]) {
if (!$mtime || $mtime > $_file_to_check[1]) {
$is_valid = false;
break;
}

View File

@ -319,7 +319,7 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data {
break;
default:
header('HTTP/1.1 304 Not Modified');
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
break;
}
} else {

View File

@ -112,6 +112,11 @@ abstract class Smarty_Internal_TemplateCompilerBase {
* @var array
*/
public $modifier_plugins = array();
/**
* type of already compiled modifier
* @var array
*/
public $known_modifier_type = array();
/**
* Initialize compiler
@ -156,7 +161,7 @@ abstract class Smarty_Internal_TemplateCompilerBase {
$_content = $template->source->content;
// run prefilter if required
if (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) {
$template->source->content = $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template);
$_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template);
}
// on empty template just return header
if ($_content == '') {
@ -563,7 +568,7 @@ abstract class Smarty_Internal_TemplateCompilerBase {
($this->nocache || $this->tag_nocache || $this->forceNocache == 2)) {
$this->template->has_nocache_code = true;
$_output = str_replace("'", "\'", $content);
$_output = str_replace('\\\\', '\\\\\\', $_output);
$_output = str_replace('\\\\', '\\\\\\\\', $_output);
$_output = str_replace("^#^", "'", $_output);
$_output = "<?php echo '/*%%SmartyNocache:{$this->nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n";
// make sure we include modifer plugins for nocache code

View File

@ -442,11 +442,12 @@ class Smarty_Internal_Templatelexer
74 => 0,
75 => 0,
76 => 0,
77 => 0,
);
if ($this->counter >= ($this->mbstring_overload ? mb_strlen($this->data,'latin1'): strlen($this->data))) {
return false; // end of input
}
$yy_global_pattern = "/\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G(".$this->ldel."\\s{1,}\/)|\G(".$this->ldel."\\s*(if|elseif|else if|while)\\s+)|\G(".$this->ldel."\\s*for\\s+)|\G(".$this->ldel."\\s*foreach(?![^\s]))|\G(".$this->ldel."\\s{1,})|\G(\\s{1,}".$this->rdel.")|\G(".$this->ldel."\/)|\G(".$this->ldel.")|\G(".$this->rdel.")|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*===\\s*)|\G(\\s*!==\\s*)|\G(\\s*==\\s*|\\s+eq\\s+)|\G(\\s*!=\\s*|\\s*<>\\s*|\\s+(ne|neq)\\s+)|\G(\\s*>=\\s*|\\s+(ge|gte)\\s+)|\G(\\s*<=\\s*|\\s+(le|lte)\\s+)|\G(\\s*>\\s*|\\s+gt\\s+)|\G(\\s*<\\s*|\\s+lt\\s+)|\G(\\s+mod\\s+)|\G(!\\s*|not\\s+)|\G(\\s*&&\\s*|\\s*and\\s+)|\G(\\s*\\|\\|\\s*|\\s*or\\s+)|\G(\\s*xor\\s+)|\G(\\s+is\\s+odd\\s+by\\s+)|\G(\\s+is\\s+not\\s+odd\\s+by\\s+)|\G(\\s+is\\s+odd)|\G(\\s+is\\s+not\\s+odd)|\G(\\s+is\\s+even\\s+by\\s+)|\G(\\s+is\\s+not\\s+even\\s+by\\s+)|\G(\\s+is\\s+even)|\G(\\s+is\\s+not\\s+even)|\G(\\s+is\\s+div\\s+by\\s+)|\G(\\s+is\\s+not\\s+div\\s+by\\s+)|\G(\\((int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)\\)\\s*)|\G(\\s*\\(\\s*)|\G(\\s*\\))|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*->\\s*)|\G(\\s*=>\\s*)|\G(\\s*=\\s*)|\G(\\+\\+|--)|\G(\\s*(\\+|-)\\s*)|\G(\\s*(\\*|\/|%)\\s*)|\G(\\$)|\G(\\s*;)|\G(::)|\G(\\s*:\\s*)|\G(@)|\G(#)|\G(\")|\G(`)|\G(\\|)|\G(\\.)|\G(\\s*,\\s*)|\G(\\s*&\\s*)|\G(\\s*\\?\\s*)|\G(0[xX][0-9a-fA-F]+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G(\\s+)|\G([\S\s])/iS";
$yy_global_pattern = "/\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G(".$this->ldel."\\s{1,}\/)|\G(".$this->ldel."\\s*(if|elseif|else if|while)\\s+)|\G(".$this->ldel."\\s*for\\s+)|\G(".$this->ldel."\\s*foreach(?![^\s]))|\G(".$this->ldel."\\s{1,})|\G(\\s{1,}".$this->rdel.")|\G(".$this->ldel."\/)|\G(".$this->ldel.")|\G(".$this->rdel.")|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*===\\s*)|\G(\\s*!==\\s*)|\G(\\s*==\\s*|\\s+eq\\s+)|\G(\\s*!=\\s*|\\s*<>\\s*|\\s+(ne|neq)\\s+)|\G(\\s*>=\\s*|\\s+(ge|gte)\\s+)|\G(\\s*<=\\s*|\\s+(le|lte)\\s+)|\G(\\s*>\\s*|\\s+gt\\s+)|\G(\\s*<\\s*|\\s+lt\\s+)|\G(\\s+mod\\s+)|\G(!\\s*|not\\s+)|\G(\\s*&&\\s*|\\s*and\\s+)|\G(\\s*\\|\\|\\s*|\\s*or\\s+)|\G(\\s*xor\\s+)|\G(\\s+is\\s+odd\\s+by\\s+)|\G(\\s+is\\s+not\\s+odd\\s+by\\s+)|\G(\\s+is\\s+odd)|\G(\\s+is\\s+not\\s+odd)|\G(\\s+is\\s+even\\s+by\\s+)|\G(\\s+is\\s+not\\s+even\\s+by\\s+)|\G(\\s+is\\s+even)|\G(\\s+is\\s+not\\s+even)|\G(\\s+is\\s+div\\s+by\\s+)|\G(\\s+is\\s+not\\s+div\\s+by\\s+)|\G(\\((int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)\\)\\s*)|\G(\\s*\\(\\s*)|\G(\\s*\\))|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*->\\s*)|\G(\\s*=>\\s*)|\G(\\s*=\\s*)|\G(\\+\\+|--)|\G(\\s*(\\+|-)\\s*)|\G(\\s*(\\*|\/|%)\\s*)|\G(\\$)|\G(\\s*;)|\G(::)|\G(\\s*:\\s*)|\G(@)|\G(#)|\G(\")|\G(`)|\G(\\|)|\G(\\.)|\G(\\s*,\\s*)|\G(\\s*&\\s*)|\G(\\s*\\?\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s?=\\s?)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G(\\s+)|\G([\S\s])/iS";
do {
if ($this->mbstring_overload ? preg_match($yy_global_pattern, mb_substr($this->data, $this->counter,2000000000,'latin1'), $yymatches) : preg_match($yy_global_pattern,$this->data, $yymatches, null, $this->counter)) {
@ -852,21 +853,26 @@ class Smarty_Internal_Templatelexer
function yy_r2_73($yy_subpatterns)
{
$this->token = Smarty_Internal_Templateparser::TP_ID;
$this->token = Smarty_Internal_Templateparser::TP_ATTR;
}
function yy_r2_74($yy_subpatterns)
{
$this->token = Smarty_Internal_Templateparser::TP_INTEGER;
$this->token = Smarty_Internal_Templateparser::TP_ID;
}
function yy_r2_75($yy_subpatterns)
{
$this->token = Smarty_Internal_Templateparser::TP_SPACE;
$this->token = Smarty_Internal_Templateparser::TP_INTEGER;
}
function yy_r2_76($yy_subpatterns)
{
$this->token = Smarty_Internal_Templateparser::TP_SPACE;
}
function yy_r2_77($yy_subpatterns)
{
$this->token = Smarty_Internal_Templateparser::TP_TEXT;
}

View File

@ -87,6 +87,7 @@ class Smarty_Internal_Utility {
$_tpl = $smarty->createTemplate($_template_file,null,null,null,false);
if ($_tpl->mustCompile()) {
$_tpl->compileTemplateSource();
$_count++;
echo ' compiled in ', microtime(true) - $_start_time, ' seconds';
flush();
} else {
@ -150,6 +151,7 @@ class Smarty_Internal_Utility {
$_config = new Smarty_Internal_Config($_config_file, $smarty);
if ($_config->mustCompile()) {
$_config->compileConfigSource();
$_count++;
echo ' compiled in ', microtime(true) - $_start_time, ' seconds';
flush();
} else {
@ -299,7 +301,7 @@ class Smarty_Internal_Utility {
echo "Smarty Installation test...\n";
echo "Testing template directory...\n";
}
$_stream_resolve_include_path = function_exists('stream_resolve_include_path');
// test if all registered template_dir are accessible
@ -315,7 +317,7 @@ class Smarty_Internal_Utility {
} else {
$template_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_template_dir);
}
if ($template_dir !== false) {
if ($errors === null) {
echo "$template_dir is OK.\n";
@ -436,7 +438,7 @@ class Smarty_Internal_Utility {
} else {
$plugin_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_plugin_dir);
}
if ($plugin_dir !== false) {
if ($errors === null) {
echo "$plugin_dir is OK.\n";
@ -568,7 +570,7 @@ class Smarty_Internal_Utility {
} else {
$config_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_config_dir);
}
if ($config_dir !== false) {
if ($errors === null) {
echo "$config_dir is OK.\n";

View File

@ -44,12 +44,30 @@ class Smarty_Internal_Write_File {
throw new SmartyException("unable to write file {$_tmp_file}");
return false;
}
/*
* Windows' rename() fails if the destination exists,
* Linux' rename() properly handles the overwrite.
* Simply unlink()ing a file might cause other processes
* currently reading that file to fail, but linux' rename()
* seems to be smart enough to handle that for us.
*/
if (Smarty::$_IS_WINDOWS) {
// remove original file
@unlink($_filepath);
// rename tmp file
$success = @rename($_tmp_file, $_filepath);
} else {
// rename tmp file
$success = @rename($_tmp_file, $_filepath);
if (!$success) {
// remove original file
@unlink($_filepath);
// rename tmp file
$success = @rename($_tmp_file, $_filepath);
}
}
// remove original file
@unlink($_filepath);
// rename tmp file
$success = rename($_tmp_file, $_filepath);
if (!$success) {
error_reporting($_error_reporting);
throw new SmartyException("unable to write file {$_filepath}");

View File

@ -144,7 +144,50 @@ abstract class Smarty_Resource {
$compiled->filepath = $_compile_dir . $_filepath . '.' . $compiled->source->type . $_basename . $_cache . '.php';
}
/**
* Normalize Paths "foo/../bar" to "bar"
*
* @param string $_path path to normalize
* @param boolean $ds respect windows directory separator
* @return string normalized path
*/
protected function normalizePath($_path, $ds=true)
{
if ($ds) {
// don't we all just love windows?
$_path = str_replace('\\', '/', $_path);
}
// resolve simples
$_path = preg_replace('#(/\./(\./)*)|/{2,}#', '/', $_path);
// resolve parents
while (true) {
$_parent = strpos($_path, '/../');
if ($_parent === false) {
break;
} else if ($_parent === 0) {
$_path = substr($_path, 3);
break;
}
$_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1);
if ($_pos === false) {
// don't we all just love windows?
$_pos = $_parent;
}
$_path = substr_replace($_path, '', $_pos, $_parent + 3 - $_pos);
}
if ($ds && DS != '/') {
// don't we all just love windows?
$_path = str_replace('/', '\\', $_path);
}
return $_path;
}
/**
* build template filepath by traversing the template_dir array
*
@ -181,32 +224,16 @@ abstract class Smarty_Resource {
// resolve relative path
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
$_was_relative_prefix = $file[0] == '.' ? substr($file, 0, strpos($file, '|')) : null;
$_path = DS . trim($file, '/\\');
// don't we all just love windows?
$_path = str_replace('\\', '/', $file);
$_was_relative_prefix = $file[0] == '.' ? substr($file, 0, strpos($_path, '/')) : null;
$_path = DS . trim($file, '/');
$_was_relative = true;
} else {
$_path = $file;
}
// don't we all just love windows?
$_path = str_replace('\\', '/', $_path);
// resolve simples
$_path = preg_replace('#(/\./(\./)*)|/{2,}#', '/', $_path);
// resolve parents
while (true) {
$_parent = strpos($_path, '/../');
if ($_parent === false) {
break;
} else if ($_parent === 0) {
$_path = substr($_path, 3);
break;
}
$_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1);
if ($_pos === false) {
// don't we all just love windows?
$_pos = $_parent;
}
$_path = substr_replace($_path, '', $_pos, $_parent + 3 - $_pos);
// don't we all just love windows?
$_path = str_replace('\\', '/', $file);
}
$_path = $this->normalizePath($_path, false);
if (DS != '/') {
// don't we all just love windows?
$_path = str_replace('/', '\\', $_path);
@ -254,7 +281,7 @@ abstract class Smarty_Resource {
}
}
}
$_stream_resolve_include_path = function_exists('stream_resolve_include_path');
// relative file name?
@ -262,7 +289,7 @@ abstract class Smarty_Resource {
foreach ($_directories as $_directory) {
$_filepath = $_directory . $file;
if ($this->fileExists($source, $_filepath)) {
return $_filepath;
return $this->normalizePath($_filepath);
}
if ($source->smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_directory)) {
// try PHP include_path
@ -271,10 +298,10 @@ abstract class Smarty_Resource {
} else {
$_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath);
}
if ($_filepath !== false) {
if ($this->fileExists($source, $_filepath)) {
return $_filepath;
return $this->normalizePath($_filepath);
}
}
}
@ -493,6 +520,9 @@ abstract class Smarty_Resource {
// check runtime cache
$_cache_key = 'template|' . $unique_resource_name;
if ($smarty->compile_id) {
$_cache_key .= '|'.$smarty->compile_id;
}
if (isset(self::$sources[$_cache_key])) {
return self::$sources[$_cache_key];
}