Finishing up secure mode.

This commit is contained in:
andrey
2001-06-15 14:52:48 +00:00
parent b818436ac3
commit 6d66c568bd
5 changed files with 346 additions and 341 deletions

View File

@@ -210,12 +210,12 @@ function smarty_func_assign($args, &$smarty_obj)
extract($args);
if (empty($var)) {
trigger_error("assign: missing 'var' parameter");
$smarty_obj->_trigger_error_msg("assign: missing 'var' parameter");
return;
}
if (empty($value)) {
trigger_error("assign: missing 'value' parameter");
$smarty_obj->_trigger_error_msg("assign: missing 'value' parameter");
return;
}
@@ -423,12 +423,10 @@ function smarty_func_html_select_time()
Function: smarty_func_math
Purpose: allow math computations in template
\*======================================================================*/
function smarty_func_math() {
$args=func_get_arg(0);
function smarty_func_math($args, $smarty_obj) {
// be sure equation parameter is present
if(empty($args["equation"])) {
trigger_error("math: missing equation parameter");
$smarty_obj->_trigger_error_msg("math: missing equation parameter");
return;
}
@@ -436,7 +434,7 @@ function smarty_func_math() {
// make sure parenthesis are balanced
if(substr_count($equation,"(") != substr_count($equation,")")) {
trigger_error("math: unbalanced parenthesis");
$smarty_obj->_trigger_error_msg("math: unbalanced parenthesis");
return;
}
@@ -445,9 +443,10 @@ function smarty_func_math() {
foreach($match[0] as $curr_var) {
if(!in_array($curr_var,array_keys($args)) &&
!in_array($curr_var,array('int','abs','ceil','cos','exp','floor','log','log10',
'max','min','pi','pow','rand','round','sin','sqrt','srand','tan')) ) {
trigger_error("math: parameter $curr_var not passed as argument");
!in_array($curr_var,
array('int','abs','ceil','cos','exp','floor','log','log10',
'max','min','pi','pow','rand','round','sin','sqrt','srand','tan'))) {
$smarty_obj->_trigger_error_msg("math: parameter $curr_var not passed as argument");
return;
}
}
@@ -456,11 +455,11 @@ function smarty_func_math() {
if($key != "equation" && $key != "format") {
// make sure value is not empty
if(strlen($val)==0) {
trigger_error("math: parameter $key is empty");
$smarty_obj->_trigger_error_msg("math: parameter $key is empty");
return;
}
if(!is_numeric($val)) {
trigger_error("math: parameter $key: is not numeric");
$smarty_obj->_trigger_error_msg("math: parameter $key: is not numeric");
return;
}
$equation = preg_replace("/\b$key\b/",$val,$equation);
@@ -479,26 +478,28 @@ function smarty_func_math() {
Function: smarty_func_fetch
Purpose: fetch file, web or ftp data and display results
\*======================================================================*/
function smarty_func_fetch($args,&$smarty_obj) {
function smarty_func_fetch($args, &$smarty_obj) {
extract($args);
if(empty($file)) {
trigger_error("parameter 'file' cannot be empty");
if (empty($file)) {
$smarty_obj->_trigger_error_msg("parameter 'file' cannot be empty");
return;
}
if($smarty_obj->security && !preg_match("/^(http|ftp):\/\//",$file)) {
if ($smarty_obj->security && !preg_match('!^(http|ftp)://!', $file)) {
// make sure fetched file comes from secure directory
foreach($smarty_obj->secure_dir as $curr_dir) {
if(substr(realpath($file),0,strlen(realpath($curr_dir))) == realpath($curr_dir)) {
foreach ($smarty_obj->secure_dir as $curr_dir) {
if (substr(realpath($file), 0, strlen(realpath($curr_dir))) == realpath($curr_dir)) {
$resource_is_secure = true;
break;
}
}
if(!$resource_is_secure) {
trigger_error("(secure mode) fetching '$file' is not allowed");
if (!$resource_is_secure) {
$smarty_obj->_trigger_error_msg("(secure mode) fetching '$file' is not allowed");
return;
}
}
}
readfile($file);
}

View File

@@ -98,17 +98,19 @@ class Smarty
// SMARTY_PHP_REMOVE -> remove php tags
// SMARTY_PHP_ALLOW -> execute php tags
// default: SMARTY_PHP_PASSTHRU
var $security = false; // enable template security (default false)
var $secure_dir = array("./templates"); // array of directories considered secure
var $security_settings = array(
"ALLOW_PHP_HANDLING" => false,
"ALLOW_IF_FUNCS" => array('count','is_array'),
"ALLOW_INCLUDE_ANY" => false,
"ALLOW_PHP_TAGS" => false,
"ALLOW_MODIFIER_FUNCS" => array('count')
);
var $security = false; // enable template security (default false)
var $secure_dir = array("./templates"); // array of directories considered secure
var $security_settings = array(
'PHP_HANDLING' => false,
'IF_FUNCS' => array('array', 'list',
'isset', 'empty',
'count', 'in_array'),
'INCLUDE_ANY' => false,
'PHP_TAGS' => false,
'MODIFIER_FUNCS' => array('count')
);
var $left_delimiter = '{'; // template tag delimiters.
var $right_delimiter = '}';
@@ -121,8 +123,8 @@ class Smarty
'html_select_time' => 'smarty_func_html_select_time',
'math' => 'smarty_func_math',
'fetch' => 'smarty_func_fetch',
'counter' => 'smarty_func_counter',
'assign' => 'smarty_func_assign'
'counter' => 'smarty_func_counter',
'assign' => 'smarty_func_assign'
);
var $custom_mods = array( 'lower' => 'strtolower',
@@ -162,8 +164,8 @@ class Smarty
var $_conf_obj = null; // configuration object
var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; // md5 checksum of the string 'Smarty'
var $_version = '1.4.2'; // Smarty version number
var $_extract = false; // flag for custom functions
var $_extract = false; // flag for custom functions
/*======================================================================*\
Function: Smarty
Purpose: Constructor
@@ -205,7 +207,7 @@ class Smarty
if (!empty($tpl_var) && isset($value))
$this->_tpl_vars[$tpl_var] = $value;
}
$this->_extract = true;
$this->_extract = true;
}
@@ -230,7 +232,7 @@ class Smarty
$this->_tpl_vars[$tpl_var][] = $value;
}
}
$this->_extract = true;
$this->_extract = true;
}
@@ -426,8 +428,8 @@ class Smarty
/*======================================================================*\
Function: clear_compile_dir()
Purpose: clears compiled version of specified template resource,
or all compiled template files if one is not specified.
Purpose: clears compiled version of specified template resource,
or all compiled template files if one is not specified.
This function is for advanced use only, not normally needed.
\*======================================================================*/
function clear_compile_dir($tpl_file = null)
@@ -435,23 +437,23 @@ class Smarty
if (!is_dir($this->compile_dir))
return false;
if (isset($tpl_file)) {
// remove compiled template file if it exists
$tpl_file = urlencode($tpl_file).'.php';
if (isset($tpl_file)) {
// remove compiled template file if it exists
$tpl_file = urlencode($tpl_file).'.php';
if (file_exists($this->compile_dir.'/'.$tpl_file)) {
unlink($this->compile_dir.'/'.$tpl_file);
}
} else {
// remove everything in $compile_dir
$dir_handle = opendir($this->compile_dir);
while ($curr_file = readdir($dir_handle)) {
if ($curr_file == '.' || $curr_dir == '..' ||
!is_file($this->compile_dir.'/'.$curr_file)) {
}
} else {
// remove everything in $compile_dir
$dir_handle = opendir($this->compile_dir);
while ($curr_file = readdir($dir_handle)) {
if ($curr_file == '.' || $curr_dir == '..' ||
!is_file($this->compile_dir.'/'.$curr_file)) {
continue;
}
unlink($this->compile_dir.'/'.$curr_file);
}
closedir($dir_handle);
unlink($this->compile_dir.'/'.$curr_file);
}
closedir($dir_handle);
}
return true;
@@ -634,7 +636,7 @@ class Smarty
Purpose: fetch the template source and timestamp
\*======================================================================*/
function _fetch_template_source($tpl_path, &$template_source, &$template_timestamp)
{
{
// split tpl_path by the first colon
$tpl_path_parts = explode(':', $tpl_path, 2);
@@ -653,20 +655,20 @@ class Smarty
// relative pathname to $template_dir
$resource_name = $this->template_dir.'/'.$resource_name;
}
// if security is on, make sure template comes from a $secure_dir
if($this->security && !$this->security_settings["ALLOW_INCLUDE_ANY"]) {
$resource_is_secure = false;
foreach($this->secure_dir as $curr_dir) {
if(substr(realpath($resource_name),0,strlen(realpath($curr_dir))) == realpath($curr_dir)) {
$resource_is_secure = true;
break;
}
}
if(!$resource_is_secure) {
$this->_trigger_error_msg("(secure mode) including \"$resource_name\" is not allowed");
return false;
}
}
// if security is on, make sure template comes from a $secure_dir
if ($this->security && !$this->security_settings['INCLUDE_ANY']) {
$resource_is_secure = false;
foreach ($this->secure_dir as $curr_dir) {
if (substr(realpath($resource_name),0,strlen(realpath($curr_dir))) == realpath($curr_dir)) {
$resource_is_secure = true;
break;
}
}
if (!$resource_is_secure) {
$this->_trigger_error_msg("(secure mode) including \"$resource_name\" is not allowed");
return false;
}
}
if (file_exists($resource_name) && is_readable($resource_name)) {
$template_source = $this->_read_file($resource_name);
$template_timestamp = filemtime($resource_name);
@@ -721,8 +723,8 @@ class Smarty
$smarty_compiler->_version = $this->_version;
$smarty_compiler->prefilter_funcs = $this->prefilter_funcs;
$smarty_compiler->compiler_funcs = $this->compiler_funcs;
$smarty_compiler->security = $this->security;
$smarty_compiler->secure_dir = $this->secure_dir;
$smarty_compiler->security = $this->security;
$smarty_compiler->secure_dir = $this->secure_dir;
$smarty_compiler->security_settings = $this->security_settings;
if ($smarty_compiler->_compile_file($tpl_file, $template_source, $template_compiled))
@@ -818,10 +820,10 @@ class Smarty
$this->_trigger_error_msg("problem writing '$filename.'");
return false;
}
// flock doesn't seem to work on several windows platforms (98, NT4, NT5, ?),
// so we'll not use it at all in windows.
// flock doesn't seem to work on several windows platforms (98, NT4, NT5, ?),
// so we'll not use it at all in windows.
if ( strtoupper(substr(PHP_OS,0,3)) == 'WIN' || (flock($fd, LOCK_EX)) ) {
fwrite( $fd, $contents );
fclose($fd);

View File

@@ -43,7 +43,7 @@ class Smarty_Compiler extends Smarty {
// internal vars
var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part
var $_literal_blocks = array(); // keeps literal template blocks
var $_php_blocks = array(); // keeps php code blocks
var $_php_blocks = array(); // keeps php code blocks
var $_current_file = null; // the current template being compiled
var $_current_line_no = 1; // line number for error messages
@@ -54,18 +54,17 @@ class Smarty_Compiler extends Smarty {
\*======================================================================*/
function _compile_file($tpl_file, $template_source, &$template_compiled)
{
if($this->security) {
// do not allow php syntax to be executed unless specified
if($this->php_handling == SMARTY_PHP_ALLOW &&
!$this->security_settings["ALLOW_PHP_HANDLING"]) {
$this->php_handling = SMARTY_PHP_PASSTHRU;
}
}
if($this->security) {
// do not allow php syntax to be executed unless specified
if ($this->php_handling == SMARTY_PHP_ALLOW &&
!$this->security_settings['PHP_HANDLING']) {
$this->php_handling = SMARTY_PHP_PASSTHRU;
}
}
// run template source through functions registered in prefilter_funcs
if (is_array($this->prefilter_funcs) && count($this->prefilter_funcs) > 0) {
foreach($this->prefilter_funcs as $prefilter) {
foreach ($this->prefilter_funcs as $prefilter) {
if (function_exists($prefilter)) {
$template_source = $prefilter($template_source);
} else {
@@ -83,14 +82,14 @@ class Smarty_Compiler extends Smarty {
preg_match_all("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s", $template_source, $match);
$this->_literal_blocks = $match[1];
$template_source = preg_replace("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s",
$this->quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $template_source);
$this->quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $template_source);
/* Pull out the php code blocks. */
preg_match_all("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s", $template_source, $match);
$this->_php_blocks = $match[1];
$template_source = preg_replace("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s",
$this->quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $template_source);
$this->quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $template_source);
/* Gather all template tags. */
preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $template_source, $match);
$template_tags = $match[1];
@@ -150,7 +149,7 @@ class Smarty_Compiler extends Smarty {
for ($i = 0; $i < count($strip_tags); $i++)
$template_compiled = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
$this->quote_replace($strip_tags_modified[$i]),
$template_compiled, 1);
$template_compiled, 1);
}
// put header at the top of the compiled template
@@ -180,8 +179,8 @@ class Smarty_Compiler extends Smarty {
)
(?:\s+(.*))?
/xs', $template_tag, $match);
$tag_command = $match[1];
$tag_args = isset($match[2]) ? $match[2] : '';
$tag_command = $match[1];
$tag_args = isset($match[2]) ? $match[2] : '';
/* If the tag name matches a variable or section property definition,
we simply process it. */
@@ -209,12 +208,12 @@ class Smarty_Compiler extends Smarty {
case '/if':
return '<?php endif; ?>';
case 'capture':
return '<?php ob_start(); ?>';
case '/capture':
return '<?php $this->assign("return", ob_get_contents()); ob_end_clean(); ?>';
case 'capture':
return '<?php ob_start(); ?>';
case '/capture':
return '<?php $this->assign("return", ob_get_contents()); ob_end_clean(); ?>';
case 'ldelim':
return $this->left_delimiter;
@@ -248,23 +247,23 @@ class Smarty_Compiler extends Smarty {
return "<?php echo '".str_replace("'","\'",$literal_block)."'; ?>\n";
case 'php':
if($this->security && !$this->security_settings["ALLOW_PHP_TAGS"]) {
if ($this->security && !$this->security_settings['PHP_TAGS']) {
$this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING);
return;
}
return;
}
list (,$php_block) = each($this->_php_blocks);
$this->_current_line_no += substr_count($php_block, "\n");
return '<?php '.$php_block.' ?>';
case 'insert':
return $this->_compile_insert_tag($tag_args);
default:
if (isset($this->compiler_funcs[$tag_command])) {
return $this->_compile_compiler_tag($tag_command, $tag_args);
} else if (isset($this->custom_funcs[$tag_command])) {
return $this->_compile_custom_tag($tag_command, $tag_args);
} else {
if (isset($this->compiler_funcs[$tag_command])) {
return $this->_compile_compiler_tag($tag_command, $tag_args);
} else if (isset($this->custom_funcs[$tag_command])) {
return $this->_compile_custom_tag($tag_command, $tag_args);
} else {
$this->_syntax_error("unknown tag - '$tag_command'", E_USER_WARNING);
return;
}
@@ -273,20 +272,20 @@ class Smarty_Compiler extends Smarty {
/*======================================================================*\
Function: _compile_compiler_tag
Purpose: compile the custom compiler tag
Function: _compile_compiler_tag
Purpose: compile the custom compiler tag
\*======================================================================*/
function _compile_compiler_tag($tag_command, $tag_args)
{
$function = $this->compiler_funcs[$tag_command];
function _compile_compiler_tag($tag_command, $tag_args)
{
$function = $this->compiler_funcs[$tag_command];
if (!function_exists($function)) {
$this->_syntax_error("compiler function '$tag_command' is not implemented", E_USER_WARNING);
return;
}
if (!function_exists($function)) {
$this->_syntax_error("compiler function '$tag_command' is not implemented", E_USER_WARNING);
return;
}
return '<?php' . $function($tag_args, $this) . ' ?>';
}
return '<?php' . $function($tag_args, $this) . ' ?>';
}
/*======================================================================*\
@@ -348,21 +347,21 @@ class Smarty_Compiler extends Smarty {
$this->_syntax_error("missing 'file' attribute in config_load tag");
}
if (!empty($attrs['global']) && $attrs['global'])
$update_parent = true;
else
$update_parent = false;
if (!empty($attrs['global']) && $attrs['global'])
$update_parent = true;
else
$update_parent = false;
$output = "<?php\n" .
"\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file']."));\n";
"\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file']."));\n";
if (!empty($attrs['section'])) {
$output .= "\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
}
$output .= "\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
}
$output .= '?>';
@@ -382,21 +381,21 @@ class Smarty_Compiler extends Smarty {
$this->_syntax_error("missing 'file' attribute in include tag");
}
foreach ($attrs as $arg_name => $arg_value) {
if ($arg_name == 'file') {
$include_file = $arg_value;
foreach ($attrs as $arg_name => $arg_value) {
if ($arg_name == 'file') {
$include_file = $arg_value;
continue;
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
return "<?php " .
"\$_smarty_tpl_vars = \$this->_tpl_vars;\n" .
"\$this->_smarty_include(".$include_file.", array(".implode(',', (array)$arg_list)."), \$_smarty_config);\n" .
"\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
"unset(\$_smarty_tpl_vars); ?>";
return "<?php " .
"\$_smarty_tpl_vars = \$this->_tpl_vars;\n" .
"\$this->_smarty_include(".$include_file.", array(".implode(',', (array)$arg_list)."), \$_smarty_config);\n" .
"\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
"unset(\$_smarty_tpl_vars); ?>";
}
@@ -456,8 +455,8 @@ class Smarty_Compiler extends Smarty {
$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}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n";
$output .= "{$section_props}['first'] = ({$section_props}['index'] == 0);\n";
$output .= "{$section_props}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n";
$output .= "?>";
@@ -485,7 +484,7 @@ class Smarty_Compiler extends Smarty {
$is_arg_stack = array();
for ($i = 0; $i < count($tokens); $i++) {
$token = &$tokens[$i];
switch ($token) {
case 'eq':
@@ -561,14 +560,15 @@ class Smarty_Compiler extends Smarty {
current position for the next iteration. */
$i = $is_arg_start;
break;
default:
if($this->security
&& $tokens[$i+1] == '('
&& !preg_match("|[^a-zA-Z_-]|",$tokens[$i])
&& !in_array($tokens[$i],$this->security_settings["ALLOW_IF_FUNCS"])) {
$this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement");
}
break;
default:
if($this->security &&
$tokens[$i+1] == '(' &&
!preg_match("|[^a-zA-Z_]|",$tokens[$i]) &&
!in_array($tokens[$i], $this->security_settings['IF_FUNCS'])) {
$this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement");
}
break;
}
}
@@ -712,11 +712,11 @@ class Smarty_Compiler extends Smarty {
return $attrs;
}
/*======================================================================*\
Function: _parse_vars_props
Purpose: compile variables and section properties tokens into
PHP code
PHP code
\*======================================================================*/
function _parse_vars_props(&$tokens)
{
@@ -752,28 +752,28 @@ class Smarty_Compiler extends Smarty {
\*======================================================================*/
function _parse_var($var_expr)
{
$parts = explode('|', substr($var_expr, 1), 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$parts = explode('|', substr($var_expr, 1), 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
preg_match_all('!\[\w+(\.\w+)?\]|(->|\.)\w+|^\w+!', $var_ref, $match);
$indexes = $match[0];
preg_match_all('!\[\w+(\.\w+)?\]|(->|\.)\w+|^\w+!', $var_ref, $match);
$indexes = $match[0];
$var_name = array_shift($indexes);
$output = "\$this->_tpl_vars['$var_name']";
foreach ($indexes as $index) {
if ($index{0} == '[') {
$parts = explode('.', substr($index, 1, -1));
$section = $parts[0];
$section_prop = isset($parts[1]) ? $parts[1] : 'index';
$output .= "[\$this->_sections['$section']['properties']['$section_prop']]";
} else if ($index{0} == '.') {
$output .= "['" . substr($index, 1) . "']";
} else {
$output .= $index;
}
}
foreach ($indexes as $index) {
if ($index{0} == '[') {
$parts = explode('.', substr($index, 1, -1));
$section = $parts[0];
$section_prop = isset($parts[1]) ? $parts[1] : 'index';
$output .= "[\$this->_sections['$section']['properties']['$section_prop']]";
} else if ($index{0} == '.') {
$output .= "['" . substr($index, 1) . "']";
} else {
$output .= $index;
}
}
$this->_parse_modifiers($output, $modifiers);
@@ -788,8 +788,8 @@ class Smarty_Compiler extends Smarty {
function _parse_conf_var($conf_var_expr)
{
$parts = explode('|', $conf_var_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_name = substr($var_ref, 1, -1);
@@ -808,8 +808,8 @@ class Smarty_Compiler extends Smarty {
function _parse_section_prop($section_prop_expr)
{
$parts = explode('|', $section_prop_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
$section_name = $match[1];
@@ -855,13 +855,13 @@ class Smarty_Compiler extends Smarty {
* function name.
*/
if (!isset($mod_func_name)) {
if($this->security && !in_array($modifier_name,$this->security_settings["ALLOW_MODIFIER_FUNCS"])) {
$this->_syntax_error("(secure mode) modifier '$modifier_name' is not allowed", E_USER_WARNING);
continue;
} else {
$mod_func_name = $modifier_name;
}
}
if ($this->security && !in_array($modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
$this->_syntax_error("(secure mode) modifier '$modifier_name' is not allowed", E_USER_WARNING);
continue;
} else {
$mod_func_name = $modifier_name;
}
}
if (!function_exists($mod_func_name)) {
$this->_syntax_error("modifier '$modifier_name' is not implemented", E_USER_WARNING);

View File

@@ -98,17 +98,19 @@ class Smarty
// SMARTY_PHP_REMOVE -> remove php tags
// SMARTY_PHP_ALLOW -> execute php tags
// default: SMARTY_PHP_PASSTHRU
var $security = false; // enable template security (default false)
var $secure_dir = array("./templates"); // array of directories considered secure
var $security_settings = array(
"ALLOW_PHP_HANDLING" => false,
"ALLOW_IF_FUNCS" => array('count','is_array'),
"ALLOW_INCLUDE_ANY" => false,
"ALLOW_PHP_TAGS" => false,
"ALLOW_MODIFIER_FUNCS" => array('count')
);
var $security = false; // enable template security (default false)
var $secure_dir = array("./templates"); // array of directories considered secure
var $security_settings = array(
'PHP_HANDLING' => false,
'IF_FUNCS' => array('array', 'list',
'isset', 'empty',
'count', 'in_array'),
'INCLUDE_ANY' => false,
'PHP_TAGS' => false,
'MODIFIER_FUNCS' => array('count')
);
var $left_delimiter = '{'; // template tag delimiters.
var $right_delimiter = '}';
@@ -121,8 +123,8 @@ class Smarty
'html_select_time' => 'smarty_func_html_select_time',
'math' => 'smarty_func_math',
'fetch' => 'smarty_func_fetch',
'counter' => 'smarty_func_counter',
'assign' => 'smarty_func_assign'
'counter' => 'smarty_func_counter',
'assign' => 'smarty_func_assign'
);
var $custom_mods = array( 'lower' => 'strtolower',
@@ -162,8 +164,8 @@ class Smarty
var $_conf_obj = null; // configuration object
var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; // md5 checksum of the string 'Smarty'
var $_version = '1.4.2'; // Smarty version number
var $_extract = false; // flag for custom functions
var $_extract = false; // flag for custom functions
/*======================================================================*\
Function: Smarty
Purpose: Constructor
@@ -205,7 +207,7 @@ class Smarty
if (!empty($tpl_var) && isset($value))
$this->_tpl_vars[$tpl_var] = $value;
}
$this->_extract = true;
$this->_extract = true;
}
@@ -230,7 +232,7 @@ class Smarty
$this->_tpl_vars[$tpl_var][] = $value;
}
}
$this->_extract = true;
$this->_extract = true;
}
@@ -426,8 +428,8 @@ class Smarty
/*======================================================================*\
Function: clear_compile_dir()
Purpose: clears compiled version of specified template resource,
or all compiled template files if one is not specified.
Purpose: clears compiled version of specified template resource,
or all compiled template files if one is not specified.
This function is for advanced use only, not normally needed.
\*======================================================================*/
function clear_compile_dir($tpl_file = null)
@@ -435,23 +437,23 @@ class Smarty
if (!is_dir($this->compile_dir))
return false;
if (isset($tpl_file)) {
// remove compiled template file if it exists
$tpl_file = urlencode($tpl_file).'.php';
if (isset($tpl_file)) {
// remove compiled template file if it exists
$tpl_file = urlencode($tpl_file).'.php';
if (file_exists($this->compile_dir.'/'.$tpl_file)) {
unlink($this->compile_dir.'/'.$tpl_file);
}
} else {
// remove everything in $compile_dir
$dir_handle = opendir($this->compile_dir);
while ($curr_file = readdir($dir_handle)) {
if ($curr_file == '.' || $curr_dir == '..' ||
!is_file($this->compile_dir.'/'.$curr_file)) {
}
} else {
// remove everything in $compile_dir
$dir_handle = opendir($this->compile_dir);
while ($curr_file = readdir($dir_handle)) {
if ($curr_file == '.' || $curr_dir == '..' ||
!is_file($this->compile_dir.'/'.$curr_file)) {
continue;
}
unlink($this->compile_dir.'/'.$curr_file);
}
closedir($dir_handle);
unlink($this->compile_dir.'/'.$curr_file);
}
closedir($dir_handle);
}
return true;
@@ -634,7 +636,7 @@ class Smarty
Purpose: fetch the template source and timestamp
\*======================================================================*/
function _fetch_template_source($tpl_path, &$template_source, &$template_timestamp)
{
{
// split tpl_path by the first colon
$tpl_path_parts = explode(':', $tpl_path, 2);
@@ -653,20 +655,20 @@ class Smarty
// relative pathname to $template_dir
$resource_name = $this->template_dir.'/'.$resource_name;
}
// if security is on, make sure template comes from a $secure_dir
if($this->security && !$this->security_settings["ALLOW_INCLUDE_ANY"]) {
$resource_is_secure = false;
foreach($this->secure_dir as $curr_dir) {
if(substr(realpath($resource_name),0,strlen(realpath($curr_dir))) == realpath($curr_dir)) {
$resource_is_secure = true;
break;
}
}
if(!$resource_is_secure) {
$this->_trigger_error_msg("(secure mode) including \"$resource_name\" is not allowed");
return false;
}
}
// if security is on, make sure template comes from a $secure_dir
if ($this->security && !$this->security_settings['INCLUDE_ANY']) {
$resource_is_secure = false;
foreach ($this->secure_dir as $curr_dir) {
if (substr(realpath($resource_name),0,strlen(realpath($curr_dir))) == realpath($curr_dir)) {
$resource_is_secure = true;
break;
}
}
if (!$resource_is_secure) {
$this->_trigger_error_msg("(secure mode) including \"$resource_name\" is not allowed");
return false;
}
}
if (file_exists($resource_name) && is_readable($resource_name)) {
$template_source = $this->_read_file($resource_name);
$template_timestamp = filemtime($resource_name);
@@ -721,8 +723,8 @@ class Smarty
$smarty_compiler->_version = $this->_version;
$smarty_compiler->prefilter_funcs = $this->prefilter_funcs;
$smarty_compiler->compiler_funcs = $this->compiler_funcs;
$smarty_compiler->security = $this->security;
$smarty_compiler->secure_dir = $this->secure_dir;
$smarty_compiler->security = $this->security;
$smarty_compiler->secure_dir = $this->secure_dir;
$smarty_compiler->security_settings = $this->security_settings;
if ($smarty_compiler->_compile_file($tpl_file, $template_source, $template_compiled))
@@ -818,10 +820,10 @@ class Smarty
$this->_trigger_error_msg("problem writing '$filename.'");
return false;
}
// flock doesn't seem to work on several windows platforms (98, NT4, NT5, ?),
// so we'll not use it at all in windows.
// flock doesn't seem to work on several windows platforms (98, NT4, NT5, ?),
// so we'll not use it at all in windows.
if ( strtoupper(substr(PHP_OS,0,3)) == 'WIN' || (flock($fd, LOCK_EX)) ) {
fwrite( $fd, $contents );
fclose($fd);

View File

@@ -43,7 +43,7 @@ class Smarty_Compiler extends Smarty {
// internal vars
var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part
var $_literal_blocks = array(); // keeps literal template blocks
var $_php_blocks = array(); // keeps php code blocks
var $_php_blocks = array(); // keeps php code blocks
var $_current_file = null; // the current template being compiled
var $_current_line_no = 1; // line number for error messages
@@ -54,18 +54,17 @@ class Smarty_Compiler extends Smarty {
\*======================================================================*/
function _compile_file($tpl_file, $template_source, &$template_compiled)
{
if($this->security) {
// do not allow php syntax to be executed unless specified
if($this->php_handling == SMARTY_PHP_ALLOW &&
!$this->security_settings["ALLOW_PHP_HANDLING"]) {
$this->php_handling = SMARTY_PHP_PASSTHRU;
}
}
if($this->security) {
// do not allow php syntax to be executed unless specified
if ($this->php_handling == SMARTY_PHP_ALLOW &&
!$this->security_settings['PHP_HANDLING']) {
$this->php_handling = SMARTY_PHP_PASSTHRU;
}
}
// run template source through functions registered in prefilter_funcs
if (is_array($this->prefilter_funcs) && count($this->prefilter_funcs) > 0) {
foreach($this->prefilter_funcs as $prefilter) {
foreach ($this->prefilter_funcs as $prefilter) {
if (function_exists($prefilter)) {
$template_source = $prefilter($template_source);
} else {
@@ -83,14 +82,14 @@ class Smarty_Compiler extends Smarty {
preg_match_all("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s", $template_source, $match);
$this->_literal_blocks = $match[1];
$template_source = preg_replace("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s",
$this->quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $template_source);
$this->quote_replace($this->left_delimiter.'literal'.$this->right_delimiter), $template_source);
/* Pull out the php code blocks. */
preg_match_all("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s", $template_source, $match);
$this->_php_blocks = $match[1];
$template_source = preg_replace("!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s",
$this->quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $template_source);
$this->quote_replace($this->left_delimiter.'php'.$this->right_delimiter), $template_source);
/* Gather all template tags. */
preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $template_source, $match);
$template_tags = $match[1];
@@ -150,7 +149,7 @@ class Smarty_Compiler extends Smarty {
for ($i = 0; $i < count($strip_tags); $i++)
$template_compiled = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
$this->quote_replace($strip_tags_modified[$i]),
$template_compiled, 1);
$template_compiled, 1);
}
// put header at the top of the compiled template
@@ -180,8 +179,8 @@ class Smarty_Compiler extends Smarty {
)
(?:\s+(.*))?
/xs', $template_tag, $match);
$tag_command = $match[1];
$tag_args = isset($match[2]) ? $match[2] : '';
$tag_command = $match[1];
$tag_args = isset($match[2]) ? $match[2] : '';
/* If the tag name matches a variable or section property definition,
we simply process it. */
@@ -209,12 +208,12 @@ class Smarty_Compiler extends Smarty {
case '/if':
return '<?php endif; ?>';
case 'capture':
return '<?php ob_start(); ?>';
case '/capture':
return '<?php $this->assign("return", ob_get_contents()); ob_end_clean(); ?>';
case 'capture':
return '<?php ob_start(); ?>';
case '/capture':
return '<?php $this->assign("return", ob_get_contents()); ob_end_clean(); ?>';
case 'ldelim':
return $this->left_delimiter;
@@ -248,23 +247,23 @@ class Smarty_Compiler extends Smarty {
return "<?php echo '".str_replace("'","\'",$literal_block)."'; ?>\n";
case 'php':
if($this->security && !$this->security_settings["ALLOW_PHP_TAGS"]) {
if ($this->security && !$this->security_settings['PHP_TAGS']) {
$this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING);
return;
}
return;
}
list (,$php_block) = each($this->_php_blocks);
$this->_current_line_no += substr_count($php_block, "\n");
return '<?php '.$php_block.' ?>';
case 'insert':
return $this->_compile_insert_tag($tag_args);
default:
if (isset($this->compiler_funcs[$tag_command])) {
return $this->_compile_compiler_tag($tag_command, $tag_args);
} else if (isset($this->custom_funcs[$tag_command])) {
return $this->_compile_custom_tag($tag_command, $tag_args);
} else {
if (isset($this->compiler_funcs[$tag_command])) {
return $this->_compile_compiler_tag($tag_command, $tag_args);
} else if (isset($this->custom_funcs[$tag_command])) {
return $this->_compile_custom_tag($tag_command, $tag_args);
} else {
$this->_syntax_error("unknown tag - '$tag_command'", E_USER_WARNING);
return;
}
@@ -273,20 +272,20 @@ class Smarty_Compiler extends Smarty {
/*======================================================================*\
Function: _compile_compiler_tag
Purpose: compile the custom compiler tag
Function: _compile_compiler_tag
Purpose: compile the custom compiler tag
\*======================================================================*/
function _compile_compiler_tag($tag_command, $tag_args)
{
$function = $this->compiler_funcs[$tag_command];
function _compile_compiler_tag($tag_command, $tag_args)
{
$function = $this->compiler_funcs[$tag_command];
if (!function_exists($function)) {
$this->_syntax_error("compiler function '$tag_command' is not implemented", E_USER_WARNING);
return;
}
if (!function_exists($function)) {
$this->_syntax_error("compiler function '$tag_command' is not implemented", E_USER_WARNING);
return;
}
return '<?php' . $function($tag_args, $this) . ' ?>';
}
return '<?php' . $function($tag_args, $this) . ' ?>';
}
/*======================================================================*\
@@ -348,21 +347,21 @@ class Smarty_Compiler extends Smarty {
$this->_syntax_error("missing 'file' attribute in config_load tag");
}
if (!empty($attrs['global']) && $attrs['global'])
$update_parent = true;
else
$update_parent = false;
if (!empty($attrs['global']) && $attrs['global'])
$update_parent = true;
else
$update_parent = false;
$output = "<?php\n" .
"\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file']."));\n";
"\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file']."));\n";
if (!empty($attrs['section'])) {
$output .= "\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
}
$output .= "\$_smarty_config = array_merge((array)\$_smarty_config, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
if ($update_parent)
$output .= "\$_smarty_config_parent = array_merge((array)\$_smarty_config_parent, \$this->_conf_obj->get(".$attrs['file'].", ".$attrs['section']."));\n";
}
$output .= '?>';
@@ -382,21 +381,21 @@ class Smarty_Compiler extends Smarty {
$this->_syntax_error("missing 'file' attribute in include tag");
}
foreach ($attrs as $arg_name => $arg_value) {
if ($arg_name == 'file') {
$include_file = $arg_value;
foreach ($attrs as $arg_name => $arg_value) {
if ($arg_name == 'file') {
$include_file = $arg_value;
continue;
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
if (is_bool($arg_value))
$arg_value = $arg_value ? 'true' : 'false';
$arg_list[] = "'$arg_name' => $arg_value";
}
return "<?php " .
"\$_smarty_tpl_vars = \$this->_tpl_vars;\n" .
"\$this->_smarty_include(".$include_file.", array(".implode(',', (array)$arg_list)."), \$_smarty_config);\n" .
"\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
"unset(\$_smarty_tpl_vars); ?>";
return "<?php " .
"\$_smarty_tpl_vars = \$this->_tpl_vars;\n" .
"\$this->_smarty_include(".$include_file.", array(".implode(',', (array)$arg_list)."), \$_smarty_config);\n" .
"\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
"unset(\$_smarty_tpl_vars); ?>";
}
@@ -456,8 +455,8 @@ class Smarty_Compiler extends Smarty {
$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}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n";
$output .= "{$section_props}['first'] = ({$section_props}['index'] == 0);\n";
$output .= "{$section_props}['last'] = ({$section_props}['index'] == {$section_props}['loop']-1);\n";
$output .= "?>";
@@ -485,7 +484,7 @@ class Smarty_Compiler extends Smarty {
$is_arg_stack = array();
for ($i = 0; $i < count($tokens); $i++) {
$token = &$tokens[$i];
switch ($token) {
case 'eq':
@@ -561,14 +560,15 @@ class Smarty_Compiler extends Smarty {
current position for the next iteration. */
$i = $is_arg_start;
break;
default:
if($this->security
&& $tokens[$i+1] == '('
&& !preg_match("|[^a-zA-Z_-]|",$tokens[$i])
&& !in_array($tokens[$i],$this->security_settings["ALLOW_IF_FUNCS"])) {
$this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement");
}
break;
default:
if($this->security &&
$tokens[$i+1] == '(' &&
!preg_match("|[^a-zA-Z_]|",$tokens[$i]) &&
!in_array($tokens[$i], $this->security_settings['IF_FUNCS'])) {
$this->_syntax_error("(secure mode) '".$tokens[$i]."' not allowed in if statement");
}
break;
}
}
@@ -712,11 +712,11 @@ class Smarty_Compiler extends Smarty {
return $attrs;
}
/*======================================================================*\
Function: _parse_vars_props
Purpose: compile variables and section properties tokens into
PHP code
PHP code
\*======================================================================*/
function _parse_vars_props(&$tokens)
{
@@ -752,28 +752,28 @@ class Smarty_Compiler extends Smarty {
\*======================================================================*/
function _parse_var($var_expr)
{
$parts = explode('|', substr($var_expr, 1), 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$parts = explode('|', substr($var_expr, 1), 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
preg_match_all('!\[\w+(\.\w+)?\]|(->|\.)\w+|^\w+!', $var_ref, $match);
$indexes = $match[0];
preg_match_all('!\[\w+(\.\w+)?\]|(->|\.)\w+|^\w+!', $var_ref, $match);
$indexes = $match[0];
$var_name = array_shift($indexes);
$output = "\$this->_tpl_vars['$var_name']";
foreach ($indexes as $index) {
if ($index{0} == '[') {
$parts = explode('.', substr($index, 1, -1));
$section = $parts[0];
$section_prop = isset($parts[1]) ? $parts[1] : 'index';
$output .= "[\$this->_sections['$section']['properties']['$section_prop']]";
} else if ($index{0} == '.') {
$output .= "['" . substr($index, 1) . "']";
} else {
$output .= $index;
}
}
foreach ($indexes as $index) {
if ($index{0} == '[') {
$parts = explode('.', substr($index, 1, -1));
$section = $parts[0];
$section_prop = isset($parts[1]) ? $parts[1] : 'index';
$output .= "[\$this->_sections['$section']['properties']['$section_prop']]";
} else if ($index{0} == '.') {
$output .= "['" . substr($index, 1) . "']";
} else {
$output .= $index;
}
}
$this->_parse_modifiers($output, $modifiers);
@@ -788,8 +788,8 @@ class Smarty_Compiler extends Smarty {
function _parse_conf_var($conf_var_expr)
{
$parts = explode('|', $conf_var_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_name = substr($var_ref, 1, -1);
@@ -808,8 +808,8 @@ class Smarty_Compiler extends Smarty {
function _parse_section_prop($section_prop_expr)
{
$parts = explode('|', $section_prop_expr, 2);
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
$var_ref = $parts[0];
$modifiers = isset($parts[1]) ? $parts[1] : '';
preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
$section_name = $match[1];
@@ -855,13 +855,13 @@ class Smarty_Compiler extends Smarty {
* function name.
*/
if (!isset($mod_func_name)) {
if($this->security && !in_array($modifier_name,$this->security_settings["ALLOW_MODIFIER_FUNCS"])) {
$this->_syntax_error("(secure mode) modifier '$modifier_name' is not allowed", E_USER_WARNING);
continue;
} else {
$mod_func_name = $modifier_name;
}
}
if ($this->security && !in_array($modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
$this->_syntax_error("(secure mode) modifier '$modifier_name' is not allowed", E_USER_WARNING);
continue;
} else {
$mod_func_name = $modifier_name;
}
}
if (!function_exists($mod_func_name)) {
$this->_syntax_error("modifier '$modifier_name' is not implemented", E_USER_WARNING);