diff --git a/NEWS b/NEWS index 46b72ca8..cbf7369f 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,6 @@ + - added 'total' and 'iteration' section properties. (Andrei) + - added 'start' and 'max' section attributes/properties. (Andrei) + - fixed a bug in security checking of functions inside {if} tags. (Andrei) - fixed a bug in Config_File that would incorrectly booleanize values that weren't really booleans. (Andrei) diff --git a/Smarty.class.php b/Smarty.class.php index ab912926..4ef52f60 100644 --- a/Smarty.class.php +++ b/Smarty.class.php @@ -60,9 +60,9 @@ class Smarty var $compile_dir = './templates_c'; // name of directory for compiled templates var $config_dir = './configs'; // directory where config files are located - var $debugging = false; // enable debugging console true/false - var $debug_tpl = 'file:debug.tpl'; // path to debug console template - + var $debugging = false; // enable debugging console true/false + var $debug_tpl = 'file:debug.tpl'; // path to debug console template + var $global_assign = array( 'HTTP_SERVER_VARS' => array( 'SCRIPT_NAME' ) ); // variables from the GLOBALS array // that are implicitly assigned @@ -104,7 +104,7 @@ class Smarty var $security = false; // enable template security (default false) - var $secure_dir = array("./templates"); // array of directories considered secure + var $secure_dir = array('./templates'); // array of directories considered secure var $security_settings = array( 'PHP_HANDLING' => false, 'IF_FUNCS' => array('array', 'list', @@ -578,7 +578,7 @@ class Smarty if ($display) { if (isset($results)) { echo $results; } - if ($this->debugging) { echo $this->_generate_debug_output(); } + if ($this->debugging) { echo $this->_generate_debug_output(); } return; } else { if (isset($results)) { return $results; } @@ -586,8 +586,8 @@ class Smarty } /*======================================================================*\ - Function: _generate_debug_output() - Purpose: generate debug output + Function: _generate_debug_output() + Purpose: generate debug output \*======================================================================*/ function _generate_debug_output() { @@ -599,12 +599,12 @@ function _generate_debug_output() { include($compile_path); if ($this->show_info_include) { echo "\n\n"; - } + } $results = ob_get_contents(); ob_end_clean(); - return $results; -} - + return $results; +} + /*======================================================================*\ Function: _process_template() Purpose: diff --git a/Smarty_Compiler.class.php b/Smarty_Compiler.class.php index 7120f714..411c3024 100644 --- a/Smarty_Compiler.class.php +++ b/Smarty_Compiler.class.php @@ -421,43 +421,64 @@ class Smarty_Compiler extends Smarty { foreach ($attrs as $attr_name => $attr_value) { switch ($attr_name) { case 'loop': - $output .= "{$section_props}['loop'] = is_array($attr_value) ? count($attr_value) : $attr_value;\n"; + $output .= "{$section_props}['loop'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\n"; break; case 'show': if (is_bool($attr_value)) - $attr_value = $attr_value ? 'true' : 'false'; + $show_attr_value = $attr_value ? 'true' : 'false'; + else + $show_attr_value = $attr_value; + break; + + case 'name': $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; break; + case 'max': + $output .= "{$section_props}['$attr_name'] = max(0, (int)$attr_value);\n"; + break; + + case 'start': + $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; + break; + default: - $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + $this->_syntax_error("unknown section attribute - '$attr_name'"); break; } } - if (isset($attrs['loop'])) { - $loop_check_code = "{$section_props}['loop'] > 0 && "; - } else { + if (!isset($attrs['loop'])) $output .= "{$section_props}['loop'] = 1;\n"; - } - if (isset($attrs['show'])) { - $show_check_code = "{$section_props}['show'] && "; - } else { - $output .= "{$section_props}['show'] = {$section_props}['loop'] > 0;\n"; - } + if (!isset($attrs['max'])) + $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; - $output .= "if ($loop_check_code $show_check_code true): "; + if (!isset($attrs['start'])) + $output .= "{$section_props}['start'] = 0;\n"; + else + $output .= "if ({$section_props}['start'] < 0)\n" . + " {$section_props}['start'] = max(0, (int)({$section_props}['loop'] + {$section_props}['start']));\n"; + if (isset($attrs['show'])) + $show_attr_code .= "$show_attr_value &&"; + $output .= "{$section_props}['show'] = $show_attr_code {$section_props}['loop'] > 0 && {$section_props}['max'] > 0 && {$section_props}['start'] < {$section_props}['loop'];\n"; + + $output .= "if ({$section_props}['show'])\n" . + " {$section_props}['total'] = min({$section_props}['loop'] - {$section_props}['start'], {$section_props}['max']);\n" . + "else\n" . + " {$section_props}['total'] = 0;\n"; + + $output .= "if ({$section_props}['show']):\n"; $output .= " - for ({$section_props}['index'] = 0; - {$section_props}['index'] < {$section_props}['loop']; - {$section_props}['index']++):\n"; + for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; + {$section_props}['index'] < {$section_props}['loop'] && {$section_props}['iteration'] <= {$section_props}['max']; + {$section_props}['index']++, {$section_props}['iteration']++):\n"; $output .= "{$section_props}['rownum'] = {$section_props}['index'] + 1;\n"; $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - 1;\n"; $output .= "{$section_props}['index_next'] = {$section_props}['index'] + 1;\n"; - $output .= "{$section_props}['first'] = ({$section_props}['index'] == 0);\n"; + $output .= "{$section_props}['first'] = ({$section_props}['index'] == {$section_props}['start']);\n"; $output .= "{$section_props}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n"; $output .= "?>"; @@ -566,7 +587,7 @@ class Smarty_Compiler extends Smarty { default: if($this->security && $tokens[$i+1] == '(' && - !preg_match("|[^a-zA-Z_]|",$tokens[$i]) && + preg_match('!^[a-zA-Z_]\w+$!', $tokens[$i]) && !in_array($tokens[$i], $this->security_settings['IF_FUNCS'])) { $this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement"); } diff --git a/demo/index.php b/demo/index.php index 5acebb36..9b751fc5 100644 --- a/demo/index.php +++ b/demo/index.php @@ -5,7 +5,6 @@ require("Smarty.class.php"); $smarty = new Smarty; $smarty->compile_check = true; -$smarty->debugging = true; $smarty->assign("now", time()); diff --git a/index.php b/index.php index 5acebb36..9b751fc5 100644 --- a/index.php +++ b/index.php @@ -5,7 +5,6 @@ require("Smarty.class.php"); $smarty = new Smarty; $smarty->compile_check = true; -$smarty->debugging = true; $smarty->assign("now", time()); diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index ab912926..4ef52f60 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -60,9 +60,9 @@ class Smarty var $compile_dir = './templates_c'; // name of directory for compiled templates var $config_dir = './configs'; // directory where config files are located - var $debugging = false; // enable debugging console true/false - var $debug_tpl = 'file:debug.tpl'; // path to debug console template - + var $debugging = false; // enable debugging console true/false + var $debug_tpl = 'file:debug.tpl'; // path to debug console template + var $global_assign = array( 'HTTP_SERVER_VARS' => array( 'SCRIPT_NAME' ) ); // variables from the GLOBALS array // that are implicitly assigned @@ -104,7 +104,7 @@ class Smarty var $security = false; // enable template security (default false) - var $secure_dir = array("./templates"); // array of directories considered secure + var $secure_dir = array('./templates'); // array of directories considered secure var $security_settings = array( 'PHP_HANDLING' => false, 'IF_FUNCS' => array('array', 'list', @@ -578,7 +578,7 @@ class Smarty if ($display) { if (isset($results)) { echo $results; } - if ($this->debugging) { echo $this->_generate_debug_output(); } + if ($this->debugging) { echo $this->_generate_debug_output(); } return; } else { if (isset($results)) { return $results; } @@ -586,8 +586,8 @@ class Smarty } /*======================================================================*\ - Function: _generate_debug_output() - Purpose: generate debug output + Function: _generate_debug_output() + Purpose: generate debug output \*======================================================================*/ function _generate_debug_output() { @@ -599,12 +599,12 @@ function _generate_debug_output() { include($compile_path); if ($this->show_info_include) { echo "\n\n"; - } + } $results = ob_get_contents(); ob_end_clean(); - return $results; -} - + return $results; +} + /*======================================================================*\ Function: _process_template() Purpose: diff --git a/libs/Smarty_Compiler.class.php b/libs/Smarty_Compiler.class.php index 7120f714..411c3024 100644 --- a/libs/Smarty_Compiler.class.php +++ b/libs/Smarty_Compiler.class.php @@ -421,43 +421,64 @@ class Smarty_Compiler extends Smarty { foreach ($attrs as $attr_name => $attr_value) { switch ($attr_name) { case 'loop': - $output .= "{$section_props}['loop'] = is_array($attr_value) ? count($attr_value) : $attr_value;\n"; + $output .= "{$section_props}['loop'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\n"; break; case 'show': if (is_bool($attr_value)) - $attr_value = $attr_value ? 'true' : 'false'; + $show_attr_value = $attr_value ? 'true' : 'false'; + else + $show_attr_value = $attr_value; + break; + + case 'name': $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; break; + case 'max': + $output .= "{$section_props}['$attr_name'] = max(0, (int)$attr_value);\n"; + break; + + case 'start': + $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n"; + break; + default: - $output .= "{$section_props}['$attr_name'] = $attr_value;\n"; + $this->_syntax_error("unknown section attribute - '$attr_name'"); break; } } - if (isset($attrs['loop'])) { - $loop_check_code = "{$section_props}['loop'] > 0 && "; - } else { + if (!isset($attrs['loop'])) $output .= "{$section_props}['loop'] = 1;\n"; - } - if (isset($attrs['show'])) { - $show_check_code = "{$section_props}['show'] && "; - } else { - $output .= "{$section_props}['show'] = {$section_props}['loop'] > 0;\n"; - } + if (!isset($attrs['max'])) + $output .= "{$section_props}['max'] = {$section_props}['loop'];\n"; - $output .= "if ($loop_check_code $show_check_code true): "; + if (!isset($attrs['start'])) + $output .= "{$section_props}['start'] = 0;\n"; + else + $output .= "if ({$section_props}['start'] < 0)\n" . + " {$section_props}['start'] = max(0, (int)({$section_props}['loop'] + {$section_props}['start']));\n"; + if (isset($attrs['show'])) + $show_attr_code .= "$show_attr_value &&"; + $output .= "{$section_props}['show'] = $show_attr_code {$section_props}['loop'] > 0 && {$section_props}['max'] > 0 && {$section_props}['start'] < {$section_props}['loop'];\n"; + + $output .= "if ({$section_props}['show'])\n" . + " {$section_props}['total'] = min({$section_props}['loop'] - {$section_props}['start'], {$section_props}['max']);\n" . + "else\n" . + " {$section_props}['total'] = 0;\n"; + + $output .= "if ({$section_props}['show']):\n"; $output .= " - for ({$section_props}['index'] = 0; - {$section_props}['index'] < {$section_props}['loop']; - {$section_props}['index']++):\n"; + for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1; + {$section_props}['index'] < {$section_props}['loop'] && {$section_props}['iteration'] <= {$section_props}['max']; + {$section_props}['index']++, {$section_props}['iteration']++):\n"; $output .= "{$section_props}['rownum'] = {$section_props}['index'] + 1;\n"; $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - 1;\n"; $output .= "{$section_props}['index_next'] = {$section_props}['index'] + 1;\n"; - $output .= "{$section_props}['first'] = ({$section_props}['index'] == 0);\n"; + $output .= "{$section_props}['first'] = ({$section_props}['index'] == {$section_props}['start']);\n"; $output .= "{$section_props}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n"; $output .= "?>"; @@ -566,7 +587,7 @@ class Smarty_Compiler extends Smarty { default: if($this->security && $tokens[$i+1] == '(' && - !preg_match("|[^a-zA-Z_]|",$tokens[$i]) && + preg_match('!^[a-zA-Z_]\w+$!', $tokens[$i]) && !in_array($tokens[$i], $this->security_settings['IF_FUNCS'])) { $this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement"); }