1
0

Smarty 3.1.12 has been released.

3.1.12 has minor bug fixes and improvements. Smarty also received a security fix regarding the escapement of Smarty error messages. ie. an unrealistic but testable case where you call $smarty->display($_GET['id']); and the GET value is passed directly to the error message. To resolve any probable concern, error messages are now escaped.

For details please read the Smarty 3.1.12 Change Log.
This commit is contained in:
Ian
2012-09-26 08:59:16 +02:00
parent b22c4d315c
commit a34fd72449
18 changed files with 1124 additions and 1037 deletions

View File

@@ -1,4 +1,4 @@
Smarty 3.1.11 Smarty 3.1.12
Author: Monte Ohrt <monte at ohrt dot com > Author: Monte Ohrt <monte at ohrt dot com >
Author: Uwe Tews Author: Uwe Tews

View File

@@ -1,4 +1,48 @@
===== trunk ===== ===== Smarty-3.1.12 =====
14.09.2012
- bugfix template inheritance failed to compile with delimiters {/ and /} (Forum Topic 23008)
11.09.2012
- bugfix escape Smarty exception messages to avoid possible script execution
10.09.2012
- bugfix tag option flags and shorttag attributes did not work when rdel started with '=' (Forum Topic 22979)
31.08.2012
- bugfix resolving relative paths broke in some circumstances (Issue #114)
22.08.2012
- bugfix test MBString availability through mb_split, as it could've been compiled without regex support (--enable-mbregex).
Either we get MBstring's full package, or we pretend it's not there at all.
21.08.2012
- bugfix $auto_literal = false did not work with { block} tags in child templates
(problem was reintroduced after fix in 3.1.7)(Forum Topic 20581)
17.08.2012
- bugfix compiled code of nocache sections could contain wrong escaping (Forum Topic 22810)
15.08.2012
- bugfix template inheritance did produce wrong code if subtemplates with {block} was
included several times (from smarty-developers forum)
14.08.2012
- bugfix PHP5.2 compatibility compromised by SplFileInfo::getBasename() (Issue 110)
01.08.2012
- bugfix avoid PHP error on $smarty->configLoad(...) with invalid section specification (Forum Topic 22608)
30.07.2012
-bugfix {assign} in a nocache section should not overwrite existing variable values
during compilation (issue 109)
28.07.2012
- bugfix array access of config variables did not work (Forum Topic 22527)
19.07.2012
- bugfix the default plugin handler did create wrong compiled code for static class methods
from external script files (issue 108)
===== Smarty-3.1.11 ===== ===== Smarty-3.1.11 =====
30.06.2012 30.06.2012
- bugfix {block.. hide} did not work as nested child (Forum Topic 22216) - bugfix {block.. hide} did not work as nested child (Forum Topic 22216)

View File

@@ -2,7 +2,7 @@
/** /**
* Project: Smarty: the PHP compiling template engine * Project: Smarty: the PHP compiling template engine
* File: Smarty.class.php * File: Smarty.class.php
* SVN: $Id: Smarty.class.php 4614 2012-05-24 15:13:19Z rodneyrehm $ * SVN: $Id: Smarty.class.php 4658 2012-09-11 16:23:30Z uwe.tews@googlemail.com $
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@@ -28,7 +28,7 @@
* @author Uwe Tews * @author Uwe Tews
* @author Rodney Rehm * @author Rodney Rehm
* @package Smarty * @package Smarty
* @version 3.1-DEV * @version 3.1.12
*/ */
/** /**
@@ -57,7 +57,7 @@ if (!defined('SMARTY_PLUGINS_DIR')) {
define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS); define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS);
} }
if (!defined('SMARTY_MBSTRING')) { if (!defined('SMARTY_MBSTRING')) {
define('SMARTY_MBSTRING', function_exists('mb_strlen')); define('SMARTY_MBSTRING', function_exists('mb_split'));
} }
if (!defined('SMARTY_RESOURCE_CHAR_SET')) { if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
// UTF-8 can only be done properly when mbstring is available! // UTF-8 can only be done properly when mbstring is available!
@@ -113,7 +113,7 @@ class Smarty extends Smarty_Internal_TemplateBase {
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = 'Smarty-3.1.11'; const SMARTY_VERSION = 'Smarty-3.1.12';
/** /**
* define variable scopes * define variable scopes
@@ -1481,6 +1481,9 @@ if (Smarty::$_CHARSET !== 'UTF-8') {
* @package Smarty * @package Smarty
*/ */
class SmartyException extends Exception { class SmartyException extends Exception {
public function __construct($message) {
$this->message = htmlentities($message);
}
} }
/** /**

View File

@@ -39,10 +39,10 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); return htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
} else { } else {
if ($double_encode) { if ($double_encode) {
// php <5.3.2 - only handle double encoding // php <5.2.3 - only handle double encoding
return htmlspecialchars($string, ENT_QUOTES, $char_set); return htmlspecialchars($string, ENT_QUOTES, $char_set);
} else { } else {
// php <5.3.2 - prevent double encoding // php <5.2.3 - prevent double encoding
$string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
$string = htmlspecialchars($string, ENT_QUOTES, $char_set); $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
$string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string); $string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string);
@@ -58,10 +58,10 @@ function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $
$string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode); $string = htmlspecialchars($string, ENT_QUOTES, $char_set, $double_encode);
} else { } else {
if ($double_encode) { if ($double_encode) {
// php <5.3.2 - only handle double encoding // php <5.2.3 - only handle double encoding
$string = htmlspecialchars($string, ENT_QUOTES, $char_set); $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
} else { } else {
// php <5.3.2 - prevent double encoding // php <5.2.3 - prevent double encoding
$string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string); $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
$string = htmlspecialchars($string, ENT_QUOTES, $char_set); $string = htmlspecialchars($string, ENT_QUOTES, $char_set);
$string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string); $string = str_replace(array('%%%SMARTY_START%%%', '%%%SMARTY_END%%%'), array('&', ';'), $string);

View File

@@ -57,7 +57,7 @@ function smarty_modifiercompiler_escape($params, $compiler)
case 'htmlall': case 'htmlall':
if (Smarty::$_MBSTRING) { if (Smarty::$_MBSTRING) {
if ($_double_encode) { if ($_double_encode) {
// php >=5.3.2 - go native // php >=5.2.3 - go native
return 'mb_convert_encoding(htmlspecialchars(' return 'mb_convert_encoding(htmlspecialchars('
. $params[0] .', ENT_QUOTES, ' . $params[0] .', ENT_QUOTES, '
. var_export($char_set, true) . ', ' . var_export($char_set, true) . ', '
@@ -65,7 +65,7 @@ function smarty_modifiercompiler_escape($params, $compiler)
. '), "HTML-ENTITIES", ' . '), "HTML-ENTITIES", '
. var_export($char_set, true) . ')'; . var_export($char_set, true) . ')';
} else if ($double_encode) { } else if ($double_encode) {
// php <5.3.2 - only handle double encoding // php <5.2.3 - only handle double encoding
return 'mb_convert_encoding(htmlspecialchars(' return 'mb_convert_encoding(htmlspecialchars('
. $params[0] .', ENT_QUOTES, ' . $params[0] .', ENT_QUOTES, '
. var_export($char_set, true) . var_export($char_set, true)
@@ -78,13 +78,13 @@ function smarty_modifiercompiler_escape($params, $compiler)
// no MBString fallback // no MBString fallback
if ($_double_encode) { if ($_double_encode) {
// php >=5.3.2 - go native // php >=5.2.3 - go native
return 'htmlentities(' return 'htmlentities('
. $params[0] .', ENT_QUOTES, ' . $params[0] .', ENT_QUOTES, '
. var_export($char_set, true) . ', ' . var_export($char_set, true) . ', '
. var_export($double_encode, true) . ')'; . var_export($double_encode, true) . ')';
} else if ($double_encode) { } else if ($double_encode) {
// php <5.3.2 - only handle double encoding // php <5.2.3 - only handle double encoding
return 'htmlentities(' return 'htmlentities('
. $params[0] .', ENT_QUOTES, ' . $params[0] .', ENT_QUOTES, '
. var_export($char_set, true) . ')'; . var_export($char_set, true) . ')';

View File

@@ -178,7 +178,7 @@ class Smarty_Internal_CacheResource_File extends Smarty_CacheResource {
$_cacheDirs = new RecursiveDirectoryIterator($_dir); $_cacheDirs = new RecursiveDirectoryIterator($_dir);
$_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST); $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($_cache as $_file) { foreach ($_cache as $_file) {
if (substr($_file->getBasename(),0,1) == '.' || strpos($_file, '.svn') !== false) continue; if (substr(basename($_file->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue;
// directory ? // directory ?
if ($_file->isDir()) { if ($_file->isDir()) {
if (!$_cache->isDot()) { if (!$_cache->isDot()) {

View File

@@ -39,8 +39,12 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase {
if ($compiler->tag_nocache || $compiler->nocache) { if ($compiler->tag_nocache || $compiler->nocache) {
$_nocache = 'true'; $_nocache = 'true';
// create nocache var to make it know for further compiling // create nocache var to make it know for further compiling
if (isset($compiler->template->tpl_vars[trim($_attr['var'], "'")])) {
$compiler->template->tpl_vars[trim($_attr['var'], "'")]->nocache = true;
} else {
$compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_variable(null, true); $compiler->template->tpl_vars[trim($_attr['var'], "'")] = new Smarty_variable(null, true);
} }
}
// scope setup // scope setup
if (isset($_attr['scope'])) { if (isset($_attr['scope'])) {
$_attr['scope'] = trim($_attr['scope'], "'\""); $_attr['scope'] = trim($_attr['scope'], "'\"");

View File

@@ -78,7 +78,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
public static function saveBlockData($block_content, $block_tag, $template, $filepath) { public static function saveBlockData($block_content, $block_tag, $template, $filepath) {
$_rdl = preg_quote($template->smarty->right_delimiter); $_rdl = preg_quote($template->smarty->right_delimiter);
$_ldl = preg_quote($template->smarty->left_delimiter); $_ldl = preg_quote($template->smarty->left_delimiter);
if ($template->smarty->auto_literal) { if (!$template->smarty->auto_literal) {
$al = '\s*'; $al = '\s*';
} else { } else {
$al = ''; $al = '';
@@ -90,7 +90,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
$_name = trim($_match[3], '\'"'); $_name = trim($_match[3], '\'"');
if ($_match[8] != 'hide' || isset($template->block_data[$_name])) { // replace {$smarty.block.child} if ($_match[8] != 'hide' || isset($template->block_data[$_name])) { // replace {$smarty.block.child}
// do we have {$smart.block.child} in nested {block} tags? // do we have {$smart.block.child} in nested {block} tags?
if (0 != preg_match_all("!({$_ldl}{$al}block\s+)(name=)?(\w+|'.*'|\".*\")([\s\S]*?)(hide)?(\s*{$_rdl})([\s\S]*?)({$_ldl}{$al}\\\$smarty\.block\.child{$_rdl})([\s\S]*?{$_ldl}{$al}/block{$_rdl})!", $block_content, $_match2)) { if (0 != preg_match_all("!({$_ldl}{$al}block\s+)(name=)?(\w+|'.*'|\".*\")([\s\S]*?)(hide)?(\s*{$_rdl})([\s\S]*?)({$_ldl}{$al}\\\$smarty\.block\.child\s*{$_rdl})([\s\S]*?{$_ldl}{$al}/block\s*{$_rdl})!", $block_content, $_match2)) {
foreach ($_match2[3] as $key => $name) { foreach ($_match2[3] as $key => $name) {
// get it's replacement // get it's replacement
$_name2 = trim($name, '\'"'); $_name2 = trim($name, '\'"');
@@ -101,17 +101,17 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
$replacement = ''; $replacement = '';
} }
// replace {$smarty.block.child} tag // replace {$smarty.block.child} tag
$search = array("%({$_ldl}{$al}block[\s\S]*?{$name}[\s\S]*?{$_rdl})([\s\S]*?)({$_ldl}{$al}\\\$smarty\.block\.child{$_rdl})([\s\S]*?)({$_ldl}{$al}/block{$_rdl})%", "/<2F><><EFBFBD>child<6C><64><EFBFBD>/"); $search = array("!({$_ldl}{$al}block[\s\S]*?{$name}[\s\S]*?{$_rdl})([\s\S]*?)({$_ldl}{$al}\\\$smarty\.block\.child\s*{$_rdl})([\s\S]*?)({$_ldl}{$al}/block\s*{$_rdl})!", "/<2F><><EFBFBD>child<6C><64><EFBFBD>/");
$replace = array('\2<><32><EFBFBD>child<6C><64><EFBFBD>\4', $replacement); $replace = array('\2<><32><EFBFBD>child<6C><64><EFBFBD>\4', $replacement);
$block_content = preg_replace($search, $replace, $block_content); $block_content = preg_replace($search, $replace, $block_content);
} else { } else {
// remove hidden blocks // remove hidden blocks
$block_content = preg_replace("%({$_ldl}{$al}block[\s\S]*?{$name}[\s\S]*?{$_rdl}[\s\S]*?{$_ldl}{$al}/block{$_rdl})%", '', $block_content); $block_content = preg_replace("!({$_ldl}{$al}block[\s\S]*?{$name}[\s\S]*?{$_rdl}[\s\S]*?{$_ldl}{$al}/block\s*{$_rdl})!", '', $block_content);
} }
} }
} }
// do we have not nested {$smart.block.child} // do we have not nested {$smart.block.child}
if (0 != preg_match("/({$_ldl}{$al}\\\$smarty\.block\.child{$_rdl})/", $block_content, $_match2)) { if (0 != preg_match("!({$_ldl}{$al}\\\$smarty\.block\.child\s*{$_rdl})!", $block_content, $_match2)) {
// get child replacement for this block // get child replacement for this block
if (isset($template->block_data[$_name])) { if (isset($template->block_data[$_name])) {
$replacement = $template->block_data[$_name]['source']; $replacement = $template->block_data[$_name]['source'];
@@ -119,7 +119,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase {
} else { } else {
$replacement = ''; $replacement = '';
} }
$block_content = preg_replace("/({$_ldl}{$al}\\\$smarty\.block\.child{$_rdl})/", $replacement, $block_content); $block_content = preg_replace("!({$_ldl}{$al}\\\$smarty\.block\.child\s*{$_rdl})!", $replacement, $block_content);
} }
if (isset($template->block_data[$_name])) { if (isset($template->block_data[$_name])) {
if (strpos($template->block_data[$_name]['source'], '%%%%SMARTY_PARENT%%%%') !== false) { if (strpos($template->block_data[$_name]['source'], '%%%%SMARTY_PARENT%%%%') !== false) {

View File

@@ -51,6 +51,11 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase {
static $_is_stringy = array('string' => true, 'eval' => true); static $_is_stringy = array('string' => true, 'eval' => true);
$this->_rdl = preg_quote($compiler->smarty->right_delimiter); $this->_rdl = preg_quote($compiler->smarty->right_delimiter);
$this->_ldl = preg_quote($compiler->smarty->left_delimiter); $this->_ldl = preg_quote($compiler->smarty->left_delimiter);
if (!$compiler->smarty->auto_literal) {
$al = '\s*';
} else {
$al = '';
}
$filepath = $compiler->template->source->filepath; $filepath = $compiler->template->source->filepath;
$this->mbstring_overload = ini_get('mbstring.func_overload') & 2; $this->mbstring_overload = ini_get('mbstring.func_overload') & 2;
// check and get attributes // check and get attributes
@@ -78,11 +83,11 @@ class Smarty_Internal_Compile_Extends extends Smarty_Internal_CompileBase {
} }
$compiler->template->properties['file_dependency'][$template_sha1] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type); $compiler->template->properties['file_dependency'][$template_sha1] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type);
$_content = ($this->mbstring_overload ? mb_substr($compiler->template->source->content, $compiler->lex->counter - 1, 20000000, 'latin1') : substr($compiler->template->source->content, $compiler->lex->counter - 1)); $_content = ($this->mbstring_overload ? mb_substr($compiler->template->source->content, $compiler->lex->counter - 1, 20000000, 'latin1') : substr($compiler->template->source->content, $compiler->lex->counter - 1));
if (preg_match_all("!({$this->_ldl}block\s(.+?){$this->_rdl})!", $_content, $s) != if (preg_match_all("!({$this->_ldl}{$al}block\s(.+?)\s*{$this->_rdl})!", $_content, $s) !=
preg_match_all("!({$this->_ldl}/block{$this->_rdl})!", $_content, $c)) { preg_match_all("!({$this->_ldl}{$al}/block\s*{$this->_rdl})!", $_content, $c)) {
$compiler->trigger_template_error('unmatched {block} {/block} pairs'); $compiler->trigger_template_error('unmatched {block} {/block} pairs');
} }
preg_match_all("!{$this->_ldl}block\s(.+?){$this->_rdl}|{$this->_ldl}/block{$this->_rdl}|{$this->_ldl}\*([\S\s]*?)\*{$this->_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE); preg_match_all("!{$this->_ldl}{$al}block\s(.+?)\s*{$this->_rdl}|{$this->_ldl}{$al}/block\s*{$this->_rdl}|{$this->_ldl}\*([\S\s]*?)\*{$this->_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE);
$_result_count = count($_result[0]); $_result_count = count($_result[0]);
$_start = 0; $_start = 0;
while ($_start+1 < $_result_count) { while ($_start+1 < $_result_count) {

View File

@@ -80,7 +80,11 @@ class Smarty_Internal_Compile_Private_Special_Variable extends Smarty_Internal_C
return '@' . trim($_index[1], "'"); return '@' . trim($_index[1], "'");
case 'config': case 'config':
if (isset($_index[2])) {
return "(is_array(\$tmp = \$_smarty_tpl->getConfigVariable($_index[1])) ? \$tmp[$_index[2]] : null)";
} else {
return "\$_smarty_tpl->getConfigVariable($_index[1])"; return "\$_smarty_tpl->getConfigVariable($_index[1])";
}
case 'ldelim': case 'ldelim':
$_ldelim = $compiler->smarty->left_delimiter; $_ldelim = $compiler->smarty->left_delimiter;
return "'$_ldelim'"; return "'$_ldelim'";

View File

@@ -240,9 +240,8 @@ class Smarty_Internal_Config {
} }
// scan sections // scan sections
if (!empty($sections)) { if (!empty($sections)) {
$sections = array_flip((array) $sections); foreach ((array) $sections as $this_section) {
foreach ($_config_vars['sections'] as $this_section => $dummy) { if (isset($_config_vars['sections'][$this_section])) {
if (isset($sections[$this_section])) {
foreach ($_config_vars['sections'][$this_section]['vars'] as $variable => $value) { foreach ($_config_vars['sections'][$this_section]['vars'] as $variable => $value) {
if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) { if ($this->smarty->config_overwrite || !isset($scope_ptr->config_vars[$variable])) {
$scope_ptr->config_vars[$variable] = $value; $scope_ptr->config_vars[$variable] = $value;

View File

@@ -89,6 +89,11 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource {
$this->mbstring_overload = ini_get('mbstring.func_overload') & 2; $this->mbstring_overload = ini_get('mbstring.func_overload') & 2;
$_rdl = preg_quote($source->smarty->right_delimiter); $_rdl = preg_quote($source->smarty->right_delimiter);
$_ldl = preg_quote($source->smarty->left_delimiter); $_ldl = preg_quote($source->smarty->left_delimiter);
if (!$source->smarty->auto_literal) {
$al = '\s*';
} else {
$al = '';
}
$_components = array_reverse($source->components); $_components = array_reverse($source->components);
$_first = reset($_components); $_first = reset($_components);
$_last = end($_components); $_last = end($_components);
@@ -105,11 +110,11 @@ class Smarty_Internal_Resource_Extends extends Smarty_Resource {
// extend sources // extend sources
if ($_component != $_last) { if ($_component != $_last) {
if (preg_match_all("!({$_ldl}block\s(.+?){$_rdl})!", $_content, $_open) != if (preg_match_all("!({$_ldl}{$al}block\s(.+?)\s*{$_rdl})!", $_content, $_open) !=
preg_match_all("!({$_ldl}/block{$_rdl})!", $_content, $_close)) { preg_match_all("!({$_ldl}{$al}/block\s*{$_rdl})!", $_content, $_close)) {
throw new SmartyException("unmatched {block} {/block} pairs in template {$_component->type} '{$_component->name}'"); throw new SmartyException("unmatched {block} {/block} pairs in template {$_component->type} '{$_component->name}'");
} }
preg_match_all("!{$_ldl}block\s(.+?){$_rdl}|{$_ldl}/block{$_rdl}|{$_ldl}\*([\S\s]*?)\*{$_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE); preg_match_all("!{$_ldl}{$al}block\s(.+?)\s*{$_rdl}|{$_ldl}{$al}/block\s*{$_rdl}|{$_ldl}\*([\S\s]*?)\*{$_rdl}!", $_content, $_result, PREG_OFFSET_CAPTURE);
$_result_count = count($_result[0]); $_result_count = count($_result[0]);
$_start = 0; $_start = 0;
while ($_start+1 < $_result_count) { while ($_start+1 < $_result_count) {

View File

@@ -344,9 +344,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
foreach ($this->required_plugins['compiled'] as $tmp) { foreach ($this->required_plugins['compiled'] as $tmp) {
foreach ($tmp as $data) { foreach ($tmp as $data) {
$file = addslashes($data['file']); $file = addslashes($data['file']);
if (is_Array($data['function'])){
$plugins_string .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n";
} else {
$plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n"; $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$file}';\n";
} }
} }
}
$plugins_string .= '?>'; $plugins_string .= '?>';
} }
if (!empty($this->required_plugins['nocache'])) { if (!empty($this->required_plugins['nocache'])) {
@@ -355,9 +359,13 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase {
foreach ($this->required_plugins['nocache'] as $tmp) { foreach ($this->required_plugins['nocache'] as $tmp) {
foreach ($tmp as $data) { foreach ($tmp as $data) {
$file = addslashes($data['file']); $file = addslashes($data['file']);
if (is_Array($data['function'])){
$plugins_string .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) include '{$file}';\n");
} else {
$plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n"); $plugins_string .= addslashes("if (!is_callable('{$data['function']}')) include '{$file}';\n");
} }
} }
}
$plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n"; $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n";
} }
} }

View File

@@ -215,6 +215,8 @@ abstract class Smarty_Internal_TemplateCompilerBase {
} else { } else {
$code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code; $code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code;
} }
// unset content because template inheritance could have replace source with parent code
unset ($template->source->content);
return $code; return $code;
} }
@@ -592,8 +594,7 @@ abstract class Smarty_Internal_TemplateCompilerBase {
if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing &&
($this->nocache || $this->tag_nocache || $this->forceNocache == 2)) { ($this->nocache || $this->tag_nocache || $this->forceNocache == 2)) {
$this->template->has_nocache_code = true; $this->template->has_nocache_code = true;
$_output = str_replace("'", "\'", $content); $_output = addcslashes($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"; $_output = "<?php echo '/*%%SmartyNocache:{$this->nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n";
// make sure we include modifer plugins for nocache code // make sure we include modifer plugins for nocache code

View File

@@ -85,6 +85,7 @@ class Smarty_Internal_Templatelexer
$this->ldel = preg_quote($this->smarty->left_delimiter,'/'); $this->ldel = preg_quote($this->smarty->left_delimiter,'/');
$this->ldel_length = strlen($this->smarty->left_delimiter); $this->ldel_length = strlen($this->smarty->left_delimiter);
$this->rdel = preg_quote($this->smarty->right_delimiter,'/'); $this->rdel = preg_quote($this->smarty->right_delimiter,'/');
$this->rdel_length = strlen($this->smarty->right_delimiter);
$this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter; $this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter;
$this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter; $this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter;
$this->mbstring_overload = ini_get('mbstring.func_overload') & 2; $this->mbstring_overload = ini_get('mbstring.func_overload') & 2;
@@ -141,11 +142,12 @@ class Smarty_Internal_Templatelexer
21 => 0, 21 => 0,
22 => 0, 22 => 0,
23 => 0, 23 => 0,
24 => 0,
); );
if ($this->counter >= ($this->mbstring_overload ? mb_strlen($this->data,'latin1'): strlen($this->data))) { if ($this->counter >= ($this->mbstring_overload ? mb_strlen($this->data,'latin1'): strlen($this->data))) {
return false; // end of input return false; // end of input
} }
$yy_global_pattern = "/\G(".$this->ldel."[$]smarty\\.block\\.child".$this->rdel.")|\G(\\{\\})|\G(".$this->ldel."\\*([\S\s]*?)\\*".$this->rdel.")|\G(".$this->ldel."strip".$this->rdel.")|\G(".$this->ldel."\\s{1,}strip\\s{1,}".$this->rdel.")|\G(".$this->ldel."\/strip".$this->rdel.")|\G(".$this->ldel."\\s{1,}\/strip\\s{1,}".$this->rdel.")|\G(".$this->ldel."\\s*literal\\s*".$this->rdel.")|\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*setfilter\\s+)|\G(".$this->ldel."\\s{1,})|\G(".$this->ldel."\/)|\G(".$this->ldel.")|\G(<\\?(?:php\\w+|=|[a-zA-Z]+)?)|\G(\\?>)|\G(<%)|\G(%>)|\G([\S\s])/iS"; $yy_global_pattern = "/\G(".$this->ldel."[$]smarty\\.block\\.child".$this->rdel.")|\G(\\{\\})|\G(".$this->ldel."\\*([\S\s]*?)\\*".$this->rdel.")|\G(".$this->ldel."strip".$this->rdel.")|\G(".$this->ldel."\\s{1,}strip\\s{1,}".$this->rdel.")|\G(".$this->ldel."\/strip".$this->rdel.")|\G(".$this->ldel."\\s{1,}\/strip\\s{1,}".$this->rdel.")|\G(".$this->ldel."\\s*literal\\s*".$this->rdel.")|\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*setfilter\\s+)|\G(".$this->ldel."\\s{1,})|\G(".$this->ldel."\/)|\G(".$this->ldel.")|\G(<\\?(?:php\\w+|=|[a-zA-Z]+)?)|\G(\\?>)|\G(".$this->rdel.")|\G(<%)|\G(%>)|\G([\S\s])/iS";
do { 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)) { 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)) {
@@ -344,16 +346,21 @@ class Smarty_Internal_Templatelexer
function yy_r1_21($yy_subpatterns) function yy_r1_21($yy_subpatterns)
{ {
$this->token = Smarty_Internal_Templateparser::TP_ASPSTARTTAG; $this->token = Smarty_Internal_Templateparser::TP_TEXT;
} }
function yy_r1_22($yy_subpatterns) function yy_r1_22($yy_subpatterns)
{ {
$this->token = Smarty_Internal_Templateparser::TP_ASPENDTAG; $this->token = Smarty_Internal_Templateparser::TP_ASPSTARTTAG;
} }
function yy_r1_23($yy_subpatterns) function yy_r1_23($yy_subpatterns)
{ {
$this->token = Smarty_Internal_Templateparser::TP_ASPENDTAG;
}
function yy_r1_24($yy_subpatterns)
{
if ($this->mbstring_overload) { if ($this->mbstring_overload) {
$to = mb_strlen($this->data,'latin1'); $to = mb_strlen($this->data,'latin1');
} else { } else {
@@ -447,7 +454,7 @@ class Smarty_Internal_Templatelexer
if ($this->counter >= ($this->mbstring_overload ? mb_strlen($this->data,'latin1'): strlen($this->data))) { if ($this->counter >= ($this->mbstring_overload ? mb_strlen($this->data,'latin1'): strlen($this->data))) {
return false; // end of input 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(\\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"; $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 { 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)) { 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)) {
@@ -853,7 +860,14 @@ class Smarty_Internal_Templatelexer
function yy_r2_73($yy_subpatterns) function yy_r2_73($yy_subpatterns)
{ {
// resolve conflicts with shorttag and right_delimiter starting with '='
if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->rdel_length) == $this->smarty->right_delimiter) {
preg_match("/\s+/",$this->value,$match);
$this->value = $match[0];
$this->token = Smarty_Internal_Templateparser::TP_SPACE;
} else {
$this->token = Smarty_Internal_Templateparser::TP_ATTR; $this->token = Smarty_Internal_Templateparser::TP_ATTR;
}
} }
function yy_r2_74($yy_subpatterns) function yy_r2_74($yy_subpatterns)
{ {
@@ -1187,4 +1201,3 @@ class Smarty_Internal_Templatelexer
} }
} }
?>

View File

@@ -72,7 +72,7 @@ class Smarty_Internal_Utility {
$_compileDirs = new RecursiveDirectoryIterator($_dir); $_compileDirs = new RecursiveDirectoryIterator($_dir);
$_compile = new RecursiveIteratorIterator($_compileDirs); $_compile = new RecursiveIteratorIterator($_compileDirs);
foreach ($_compile as $_fileinfo) { foreach ($_compile as $_fileinfo) {
if (substr($_fileinfo->getBasename(),0,1) == '.' || strpos($_fileinfo, '.svn') !== false) continue; if (substr(basename($_file->getPathname()),0,1) == '.' || strpos($_fileinfo, '.svn') !== false) continue;
$_file = $_fileinfo->getFilename(); $_file = $_fileinfo->getFilename();
if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue;
if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { if ($_fileinfo->getPath() == substr($_dir, 0, -1)) {
@@ -136,7 +136,7 @@ class Smarty_Internal_Utility {
$_compileDirs = new RecursiveDirectoryIterator($_dir); $_compileDirs = new RecursiveDirectoryIterator($_dir);
$_compile = new RecursiveIteratorIterator($_compileDirs); $_compile = new RecursiveIteratorIterator($_compileDirs);
foreach ($_compile as $_fileinfo) { foreach ($_compile as $_fileinfo) {
if (substr($_fileinfo->getBasename(),0,1) == '.' || strpos($_fileinfo, '.svn') !== false) continue; if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_fileinfo, '.svn') !== false) continue;
$_file = $_fileinfo->getFilename(); $_file = $_fileinfo->getFilename();
if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue; if (!substr_compare($_file, $extention, - strlen($extention)) == 0) continue;
if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { if ($_fileinfo->getPath() == substr($_dir, 0, -1)) {
@@ -231,7 +231,7 @@ class Smarty_Internal_Utility {
} }
$_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($_compile as $_file) { foreach ($_compile as $_file) {
if (substr($_file->getBasename(), 0, 1) == '.' || strpos($_file, '.svn') !== false) if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false)
continue; continue;
$_filepath = (string) $_file; $_filepath = (string) $_file;

View File

@@ -159,16 +159,18 @@ abstract class Smarty_Resource {
$_path = str_replace('\\', '/', $_path); $_path = str_replace('\\', '/', $_path);
} }
$offset = 0;
// resolve simples // resolve simples
$_path = preg_replace('#(/\./(\./)*)|/{2,}#', '/', $_path); $_path = preg_replace('#(/\./(\./)*)|/{2,}#', '/', $_path);
// resolve parents // resolve parents
while (true) { while (true) {
$_parent = strpos($_path, '/../'); $_parent = strpos($_path, '/../', $offset);
if ($_parent === false) { if (!$_parent) {
break;
} else if ($_parent === 0) {
$_path = substr($_path, 3);
break; break;
} else if ($_path[$_parent - 1] === '.') {
$offset = $_parent + 3;
continue;
} }
$_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1); $_pos = strrpos($_path, '/', $_parent - strlen($_path) - 1);
@@ -226,7 +228,6 @@ abstract class Smarty_Resource {
if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) { if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) {
// don't we all just love windows? // don't we all just love windows?
$_path = str_replace('\\', '/', $file); $_path = str_replace('\\', '/', $file);
$_was_relative_prefix = $file[0] == '.' ? substr($file, 0, strpos($_path, '/')) : null;
$_path = DS . trim($file, '/'); $_path = DS . trim($file, '/');
$_was_relative = true; $_was_relative = true;
} else { } else {
@@ -240,12 +241,8 @@ abstract class Smarty_Resource {
} }
// revert to relative // revert to relative
if (isset($_was_relative)) { if (isset($_was_relative)) {
if (isset($_was_relative_prefix)){
$_path = $_was_relative_prefix . $_path;
} else {
$_path = substr($_path, 1); $_path = substr($_path, 1);
} }
}
// this is only required for directories // this is only required for directories
$file = rtrim($_path, '/\\'); $file = rtrim($_path, '/\\');