mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 18:04:26 +02:00
Removed PHP functions and checks for the already removed php modifiers. Re-implemented functions as regular functions. Probably should compile these directly.
This commit is contained in:
@@ -8,10 +8,6 @@ template engine. Every `{if}` must be paired with a matching `{/if}`.
|
|||||||
functions are recognized, such as *\|\|*, *or*, *&&*, *and*,
|
functions are recognized, such as *\|\|*, *or*, *&&*, *and*,
|
||||||
*is\_array()*, etc.
|
*is\_array()*, etc.
|
||||||
|
|
||||||
If securty is enabled, only PHP functions from `$php_functions` property
|
|
||||||
of the securty policy are allowed. See the
|
|
||||||
[Security](#advanced.features.security) section for details.
|
|
||||||
|
|
||||||
The following is a list of recognized qualifiers, which must be
|
The following is a list of recognized qualifiers, which must be
|
||||||
separated from surrounding elements by spaces. Note that items listed in
|
separated from surrounding elements by spaces. Note that items listed in
|
||||||
\[brackets\] are optional. PHP equivalents are shown where applicable.
|
\[brackets\] are optional. PHP equivalents are shown where applicable.
|
||||||
|
@@ -53,19 +53,6 @@ instance of the Smarty\_Security class. These are the possible settings:
|
|||||||
static classes. To disable access to all static classes set
|
static classes. To disable access to all static classes set
|
||||||
\$static\_classes = null.
|
\$static\_classes = null.
|
||||||
|
|
||||||
- `$php_functions` is an array of PHP functions that are considered
|
|
||||||
trusted and can be used from within template. To disable access to
|
|
||||||
all PHP functions set \$php\_functions = null. An empty array (
|
|
||||||
\$php\_functions = array() ) will allow all PHP functions. The
|
|
||||||
default is array(\'isset\', \'empty\', \'count\', \'sizeof\',
|
|
||||||
\'in\_array\', \'is\_array\',\'time\',\'nl2br\').
|
|
||||||
|
|
||||||
- `$php_modifiers` is an array of PHP functions that are considered
|
|
||||||
trusted and can be used from within template as modifier. To disable
|
|
||||||
access to all PHP modifier set \$php\_modifier = null. An empty
|
|
||||||
array ( \$php\_modifier = array() ) will allow all PHP functions.
|
|
||||||
The default is array(\'escape\',\'count\').
|
|
||||||
|
|
||||||
- `$streams` is an array of streams that are considered trusted and
|
- `$streams` is an array of streams that are considered trusted and
|
||||||
can be used from within template. To disable access to all streams
|
can be used from within template. To disable access to all streams
|
||||||
set \$streams = null. An empty array ( \$streams = array() ) will
|
set \$streams = null. An empty array ( \$streams = array() ) will
|
||||||
@@ -105,10 +92,7 @@ Smarty\_Security class or create an instance of it.
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class My_Security_Policy extends \Smarty\Security {
|
class My_Security_Policy extends \Smarty\Security {
|
||||||
// disable all PHP functions
|
public $allow_constants = false;
|
||||||
public $php_functions = null;
|
|
||||||
// allow everthing as modifier
|
|
||||||
public $php_modifiers = array();
|
|
||||||
}
|
}
|
||||||
$smarty = new Smarty();
|
$smarty = new Smarty();
|
||||||
// enable security
|
// enable security
|
||||||
@@ -119,10 +103,7 @@ Smarty\_Security class or create an instance of it.
|
|||||||
<?php
|
<?php
|
||||||
$smarty = new Smarty();
|
$smarty = new Smarty();
|
||||||
$my_security_policy = new \Smarty\Security($smarty);
|
$my_security_policy = new \Smarty\Security($smarty);
|
||||||
// disable all PHP functions
|
$my_security_policy->allow_constants = false;
|
||||||
$my_security_policy->php_functions = null;
|
|
||||||
// allow everthing as modifier
|
|
||||||
$my_security_policy->php_modifiers = array();
|
|
||||||
// enable security
|
// enable security
|
||||||
$smarty->enableSecurity($my_security_policy);
|
$smarty->enableSecurity($my_security_policy);
|
||||||
?>
|
?>
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
namespace Smarty\Compile;
|
namespace Smarty\Compile;
|
||||||
|
|
||||||
use Smarty\Compiler\Template;
|
use Smarty\Compiler\Template;
|
||||||
|
use Smarty\CompilerException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Smarty Internal Plugin Compile Registered Function Class
|
* Smarty Internal Plugin Compile Registered Function Class
|
||||||
@@ -28,6 +29,13 @@ class FunctionCallCompiler extends Base {
|
|||||||
*/
|
*/
|
||||||
public $optional_attributes = ['_any'];
|
public $optional_attributes = ['_any'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shorttag attribute order defined by its names
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $shorttag_order = ['var1', 'var2', 'var3'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles code for the execution of a registered function
|
* Compiles code for the execution of a registered function
|
||||||
*
|
*
|
||||||
@@ -42,12 +50,14 @@ class FunctionCallCompiler extends Base {
|
|||||||
* @throws \Smarty\Exception
|
* @throws \Smarty\Exception
|
||||||
*/
|
*/
|
||||||
public function compile($args, Template $compiler, $parameter = [], $tag = null, $function = null) {
|
public function compile($args, Template $compiler, $parameter = [], $tag = null, $function = null) {
|
||||||
|
|
||||||
// check and get attributes
|
// check and get attributes
|
||||||
$_attr = $this->getAttributes($compiler, $args);
|
$_attr = $this->getAttributes($compiler, $args);
|
||||||
unset($_attr['nocache']);
|
unset($_attr['nocache']);
|
||||||
|
|
||||||
|
if (!$functionHandler = $compiler->smarty->getFunctionHandler($function)) {
|
||||||
$functionHandler = $compiler->smarty->getFunctionHandler($function);
|
throw new CompilerException("Cannot compile unknown function $function.");
|
||||||
|
}
|
||||||
|
|
||||||
// not cacheable?
|
// not cacheable?
|
||||||
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
|
$compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
|
||||||
@@ -65,6 +75,6 @@ class FunctionCallCompiler extends Base {
|
|||||||
if (!empty($parameter['modifierlist'])) {
|
if (!empty($parameter['modifierlist'])) {
|
||||||
$output = $compiler->compileModifier($parameter['modifierlist'], $output);
|
$output = $compiler->compileModifier($parameter['modifierlist'], $output);
|
||||||
}
|
}
|
||||||
return "<?php echo {$output};?>\n";
|
return $output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -529,77 +529,6 @@ class Template extends BaseCompiler {
|
|||||||
return '$_smarty_tpl->getConfigVariable(' . $variable . ')';
|
return '$_smarty_tpl->getConfigVariable(' . $variable . ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* compile PHP function call
|
|
||||||
*
|
|
||||||
* @param string $name
|
|
||||||
* @param array $parameter
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
* @throws \Smarty\CompilerException
|
|
||||||
*/
|
|
||||||
public function compilePHPFunctionCall($name, $parameter) {
|
|
||||||
if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) {
|
|
||||||
if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0
|
|
||||||
|| strcasecmp($name, 'array') === 0 || is_callable($name)
|
|
||||||
) {
|
|
||||||
$func_name = smarty_strtolower_ascii($name);
|
|
||||||
|
|
||||||
if ($func_name === 'isset') {
|
|
||||||
if (count($parameter) === 0) {
|
|
||||||
$this->trigger_template_error('Illegal number of parameter in "isset()"');
|
|
||||||
}
|
|
||||||
|
|
||||||
$pa = [];
|
|
||||||
foreach ($parameter as $p) {
|
|
||||||
$pa[] = $this->syntaxMatchesVariable($p) ? 'isset(' . $p . ')' : '(' . $p . ' !== null )';
|
|
||||||
}
|
|
||||||
return '(' . implode(' && ', $pa) . ')';
|
|
||||||
|
|
||||||
} elseif (in_array(
|
|
||||||
$func_name,
|
|
||||||
[
|
|
||||||
'empty',
|
|
||||||
'reset',
|
|
||||||
'current',
|
|
||||||
'end',
|
|
||||||
'prev',
|
|
||||||
'next',
|
|
||||||
]
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (count($parameter) !== 1) {
|
|
||||||
$this->trigger_template_error("Illegal number of parameter in '{$func_name()}'");
|
|
||||||
}
|
|
||||||
if ($func_name === 'empty') {
|
|
||||||
return $func_name . '(' .
|
|
||||||
str_replace("')->value", "',null,true,false)->value", $parameter[0]) . ')';
|
|
||||||
} else {
|
|
||||||
return $func_name . '(' . $parameter[0] . ')';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return $name . '(' . implode(',', $parameter) . ')';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->trigger_template_error("unknown function '{$name}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines whether the passed string represents a valid (PHP) variable.
|
|
||||||
* This is important, because `isset()` only works on variables and `empty()` can only be passed
|
|
||||||
* a variable prior to php5.5
|
|
||||||
*
|
|
||||||
* @param $string
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function syntaxMatchesVariable($string) {
|
|
||||||
static $regex_pattern = '/^\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*((->)[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*|\[.*]*\])*$/';
|
|
||||||
return 1 === preg_match($regex_pattern, trim($string));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called from parser to process a text content section if strip is enabled
|
* This method is called from parser to process a text content section if strip is enabled
|
||||||
* - remove text from inheritance child templates as they may generate output
|
* - remove text from inheritance child templates as they may generate output
|
||||||
@@ -1278,7 +1207,11 @@ class Template extends BaseCompiler {
|
|||||||
// check if tag is a function
|
// check if tag is a function
|
||||||
if ($this->smarty->getFunctionHandler($base_tag)) {
|
if ($this->smarty->getFunctionHandler($base_tag)) {
|
||||||
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
|
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
|
||||||
return $this->functionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag);
|
return (new \Smarty\Compile\PrintExpressionCompiler())->compile(
|
||||||
|
[],
|
||||||
|
$this,
|
||||||
|
['value' => $this->compileFunctionCall($base_tag, $args, $parameter)]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,4 +1416,8 @@ class Template extends BaseCompiler {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function compileFunctionCall(string $base_tag, array $args, array $parameter = []) {
|
||||||
|
return $this->functionCallCompiler->compile($args, $this, $parameter, $base_tag, $base_tag);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -69,8 +69,10 @@ class DefaultExtension extends Base {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch ($functionName) {
|
switch ($functionName) {
|
||||||
|
case 'count': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Count(); break;
|
||||||
case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break;
|
case 'counter': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Counter(); break;
|
||||||
case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break;
|
case 'cycle': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Cycle(); break;
|
||||||
|
case 'empty': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\EmptyHandler(); break;
|
||||||
case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break;
|
case 'fetch': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Fetch(); break;
|
||||||
case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break;
|
case 'html_checkboxes': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlCheckboxes(); break;
|
||||||
case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break;
|
case 'html_image': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlImage(); break;
|
||||||
@@ -79,8 +81,12 @@ class DefaultExtension extends Base {
|
|||||||
case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
|
case 'html_select_date': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectDate(); break;
|
||||||
case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
|
case 'html_select_time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlSelectTime(); break;
|
||||||
case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
|
case 'html_table': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\HtmlTable(); break;
|
||||||
|
case 'in_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\InArray(); break;
|
||||||
|
case 'is_array': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\IsArray(); break;
|
||||||
|
case 'isset': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\IssetHandler(); break;
|
||||||
case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
|
case 'mailto': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Mailto(); break;
|
||||||
case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
|
case 'math': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Math(); break;
|
||||||
|
case 'time': $this->functionHandlers[$functionName] = new \Smarty\FunctionHandler\Time(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->functionHandlers[$functionName] ?? null;
|
return $this->functionHandlers[$functionName] ?? null;
|
||||||
|
36
src/FunctionHandler/Count.php
Normal file
36
src/FunctionHandler/Count.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* count(Countable|array $value, int $mode = COUNT_NORMAL): int
|
||||||
|
* If the optional mode parameter is set to COUNT_RECURSIVE (or 1), count() will recursively count the array.
|
||||||
|
* This is particularly useful for counting all the elements of a multidimensional array.
|
||||||
|
*
|
||||||
|
* Returns the number of elements in value. Prior to PHP 8.0.0, if the parameter was neither an array nor an object that
|
||||||
|
* implements the Countable interface, 1 would be returned, unless value was null, in which case 0 would be returned.
|
||||||
|
*/
|
||||||
|
class Count extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
|
||||||
|
$params = array_values($params ?? []);
|
||||||
|
|
||||||
|
if (count($params) < 1 || count($params) > 2) {
|
||||||
|
throw new Exception("Invalid number of arguments for in_array. in_arrays expects 2 or 3 parameters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = $params[0];
|
||||||
|
|
||||||
|
if ($value instanceof \Countable) {
|
||||||
|
return $value->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
$mode = count($params) == 2 ? (int) $params[1] : COUNT_NORMAL;
|
||||||
|
return count((array) $value, $mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
src/FunctionHandler/EmptyHandler.php
Normal file
27
src/FunctionHandler/EmptyHandler.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* empty(mixed $var): bool
|
||||||
|
*
|
||||||
|
* Returns true if var does not exist or has a value that is empty or equal to zero, aka falsey, see conversion to
|
||||||
|
* boolean. Otherwise returns false.
|
||||||
|
*
|
||||||
|
* No warning is generated if the variable does not exist. That means empty() is essentially the concise equivalent
|
||||||
|
* to !isset($var) || $var == false.
|
||||||
|
*/
|
||||||
|
class EmptyHandler extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
|
||||||
|
if (count($params) !== 1) {
|
||||||
|
throw new Exception("Invalid number of arguments for empty. empty expects exactly 1 parameter.");
|
||||||
|
}
|
||||||
|
return empty(reset($params));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
src/FunctionHandler/InArray.php
Normal file
30
src/FunctionHandler/InArray.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in_array(mixed $needle, array $haystack, bool $strict = false): bool
|
||||||
|
* Returns true if needle is found in the array, false otherwise
|
||||||
|
*/
|
||||||
|
class InArray extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
|
||||||
|
$params = array_values($params ?? []);
|
||||||
|
|
||||||
|
if (count($params) < 2 || count($params) > 3) {
|
||||||
|
throw new Exception("Invalid number of arguments for in_array. in_arrays expects 2 or 3 parameters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// default to false, true if param 3 is set to true
|
||||||
|
$needle = $params[0];
|
||||||
|
$haystack = (array) $params[1];
|
||||||
|
$strict = count($params) == 3 && $params[2];
|
||||||
|
|
||||||
|
return in_array($needle, $haystack, $strict);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/FunctionHandler/IsArray.php
Normal file
21
src/FunctionHandler/IsArray.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_array(mixed $value): bool
|
||||||
|
* Returns true if value is an array, false otherwise.
|
||||||
|
*/
|
||||||
|
class IsArray extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
if (count($params) !== 1) {
|
||||||
|
throw new Exception("Invalid number of arguments for is_array. is_array expects exactly 1 parameter.");
|
||||||
|
}
|
||||||
|
return is_array(reset($params));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
src/FunctionHandler/IssetHandler.php
Normal file
30
src/FunctionHandler/IssetHandler.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a variable is declared and is different than null
|
||||||
|
* `isset(mixed $var, mixed ...$vars): bool`
|
||||||
|
*
|
||||||
|
* Returns true if var exists and has any value other than null. false otherwise.
|
||||||
|
*/
|
||||||
|
class IssetHandler extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
|
||||||
|
if (count($params) === 0) {
|
||||||
|
throw new Exception("Invalid number of arguments for isset. isset expects at least 1 parameter.");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($params as $param) {
|
||||||
|
if (!isset($param)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/FunctionHandler/Time.php
Normal file
21
src/FunctionHandler/Time.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Smarty\FunctionHandler;
|
||||||
|
|
||||||
|
use Smarty\Exception;
|
||||||
|
use Smarty\Template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* is_array(mixed $value): bool
|
||||||
|
* Returns true if value is an array, false otherwise.
|
||||||
|
*/
|
||||||
|
class Time extends Base {
|
||||||
|
|
||||||
|
public function handle($params, Template $template) {
|
||||||
|
if (count($params) > 0) {
|
||||||
|
throw new Exception("Invalid number of arguments for time. time expects no parameters.");
|
||||||
|
}
|
||||||
|
return time();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1037,7 +1037,7 @@ objectelement(res)::= PTR method(f). {
|
|||||||
// function
|
// function
|
||||||
//
|
//
|
||||||
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
|
function(res) ::= ns1(f) OPENP params(p) CLOSEP. {
|
||||||
res = $this->compiler->compilePHPFunctionCall(f, p);
|
res = $this->compiler->compileFunctionCall(f, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1071,7 +1071,7 @@ params(res) ::= expr(e). {
|
|||||||
res = array(e);
|
res = array(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// kein parameter
|
// no parameter
|
||||||
params(res) ::= . {
|
params(res) ::= . {
|
||||||
res = array();
|
res = array();
|
||||||
}
|
}
|
||||||
|
@@ -94,24 +94,6 @@ class Security {
|
|||||||
*/
|
*/
|
||||||
public $trusted_static_properties = [];
|
public $trusted_static_properties = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an array of trusted PHP functions.
|
|
||||||
* If empty all functions are allowed.
|
|
||||||
* To disable all PHP functions set $php_functions = null.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $php_functions = ['isset', 'empty', 'count', 'sizeof', 'in_array', 'is_array', 'time',];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is an array of trusted PHP modifiers.
|
|
||||||
* If empty all modifiers are allowed.
|
|
||||||
* To disable all modifier set $php_modifiers = null.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public $php_modifiers = ['escape', 'count', 'sizeof', 'nl2br',];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an array of allowed tags.
|
* This is an array of allowed tags.
|
||||||
* If empty no restriction by allowed_tags.
|
* If empty no restriction by allowed_tags.
|
||||||
@@ -216,27 +198,6 @@ class Security {
|
|||||||
*/
|
*/
|
||||||
protected $_secure_dir = [];
|
protected $_secure_dir = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache for $php_resource_dir lookup
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $_php_resource_dir = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache for $trusted_dir lookup
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $_trusted_dir = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache for $_include_array lookup
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $_include_dir = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Smarty $smarty
|
* @param Smarty $smarty
|
||||||
*/
|
*/
|
||||||
@@ -244,24 +205,6 @@ class Security {
|
|||||||
$this->smarty = $smarty;
|
$this->smarty = $smarty;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if PHP function is trusted.
|
|
||||||
*
|
|
||||||
* @param string $function_name
|
|
||||||
* @param object $compiler compiler object
|
|
||||||
*
|
|
||||||
* @return boolean true if function is trusted
|
|
||||||
*/
|
|
||||||
public function isTrustedPhpFunction($function_name, $compiler) {
|
|
||||||
if (isset($this->php_functions)
|
|
||||||
&& (empty($this->php_functions) || in_array($function_name, $this->php_functions))
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$compiler->trigger_template_error("PHP function '{$function_name}' not allowed by security setting");
|
|
||||||
return false; // should not, but who knows what happens to the compiler in the future?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if static class is trusted.
|
* Check if static class is trusted.
|
||||||
*
|
*
|
||||||
@@ -317,25 +260,6 @@ class Security {
|
|||||||
return false; // should not, but who knows what happens to the compiler in the future?
|
return false; // should not, but who knows what happens to the compiler in the future?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if PHP modifier is trusted.
|
|
||||||
*
|
|
||||||
* @param string $modifier_name
|
|
||||||
* @param object $compiler compiler object
|
|
||||||
*
|
|
||||||
* @return boolean true if modifier is trusted
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function isTrustedPhpModifier($modifier_name, $compiler) {
|
|
||||||
if (isset($this->php_modifiers)
|
|
||||||
&& (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers))
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting");
|
|
||||||
return false; // should not, but who knows what happens to the compiler in the future?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if tag is trusted.
|
* Check if tag is trusted.
|
||||||
*
|
*
|
||||||
|
@@ -64,7 +64,7 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
|
|||||||
*/
|
*/
|
||||||
public static function setUpBeforeClass(): void
|
public static function setUpBeforeClass(): void
|
||||||
{
|
{
|
||||||
error_reporting(E_ALL & ~E_STRICT);
|
error_reporting(E_ALL & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED);
|
||||||
self::$init = true;
|
self::$init = true;
|
||||||
self::$pluginsdir =self::getSmartyPluginsDir();
|
self::$pluginsdir =self::getSmartyPluginsDir();
|
||||||
}
|
}
|
||||||
|
@@ -40,32 +40,9 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
/**
|
/**
|
||||||
* test trusted PHP function
|
* test trusted PHP function
|
||||||
*/
|
*/
|
||||||
public function testTrustedPHPFunction()
|
public function testTrustedFunction()
|
||||||
{
|
{
|
||||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
|
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* test not trusted PHP function
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function testNotTrustedPHPFunction()
|
|
||||||
{
|
|
||||||
$this->expectException(\Smarty\Exception::class);
|
|
||||||
$this->expectExceptionMessage('PHP function \'sizeof\' not allowed by security setting');
|
|
||||||
$this->smarty->security_policy->php_functions = array('null');
|
|
||||||
$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* test not trusted PHP function at disabled security
|
|
||||||
*/
|
|
||||||
public function testDisabledTrustedPHPFunction()
|
|
||||||
{
|
|
||||||
$this->smarty->security_policy->php_functions = array('null');
|
|
||||||
$this->smarty->disableSecurity();
|
|
||||||
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +51,7 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
*/
|
*/
|
||||||
public function testTrustedModifier()
|
public function testTrustedModifier()
|
||||||
{
|
{
|
||||||
$this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}'));
|
$this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,21 +64,9 @@ class SecurityTest extends PHPUnit_Smarty
|
|||||||
{
|
{
|
||||||
$this->expectException(\Smarty\Exception::class);
|
$this->expectException(\Smarty\Exception::class);
|
||||||
$this->expectExceptionMessage('modifier \'sizeof\' not allowed by security setting');
|
$this->expectExceptionMessage('modifier \'sizeof\' not allowed by security setting');
|
||||||
$this->smarty->security_policy->php_modifiers = array('null');
|
|
||||||
@$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}');
|
@$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* test not trusted modifier at disabled security
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
public function testDisabledTrustedModifier()
|
|
||||||
{
|
|
||||||
$this->smarty->security_policy->php_modifiers = array('null');
|
|
||||||
$this->smarty->disableSecurity();
|
|
||||||
@$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test allowed tags
|
* test allowed tags
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||||
|
class CountTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void {
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax() {
|
||||||
|
$this->assertEquals('3', $this->smarty->fetch("string:{count([1,2,3])}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNonRecursive() {
|
||||||
|
$this->assertEquals('3', $this->smarty->fetch("string:{count([1,2,[3,4]])}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testRecursive() {
|
||||||
|
$this->assertEquals('5', $this->smarty->fetch("string:{count([1,2,[3,4]], 1)}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters() {
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{count()}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||||
|
class EmptyTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void {
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax() {
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$noSuch)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyStringIsEmpty() {
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if empty('')}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFalseIsEmpty() {
|
||||||
|
$this->smarty->assign('test', false);
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntZeroIsEmpty() {
|
||||||
|
$this->smarty->assign('test', 0);
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStringZeroIsEmpty() {
|
||||||
|
$this->smarty->assign('test', '0');
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if empty(\$test)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntThreeIsNotEmpty() {
|
||||||
|
$this->smarty->assign('test', 3);
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if empty(\$test)}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters() {
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{empty(3, 'foo')}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class InArrayTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax()
|
||||||
|
{
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if in_array(3,[3])}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNotInArray()
|
||||||
|
{
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if in_array(2,[3])}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters()
|
||||||
|
{
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{in_array('foo')}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||||
|
class IsArrayTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void {
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax() {
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if is_array([3])}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntNotIsArray() {
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if is_array(2)}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStringNotIsArray() {
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if is_array('foo')}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters() {
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{is_array(3, 'foo')}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||||
|
class IssetTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void {
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax() {
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if isset(\$noSuch)}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEmptyStringIsset() {
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset('')}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFalseIsset() {
|
||||||
|
$this->smarty->assign('test', false);
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntZeroIsset() {
|
||||||
|
$this->smarty->assign('test', 0);
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultivar() {
|
||||||
|
$this->smarty->assign('test', 0);
|
||||||
|
$this->smarty->assign('test2', 'pizza');
|
||||||
|
$this->assertEquals("yay", $this->smarty->fetch("string:{if isset(\$test, \$test2)}yay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMultivarOneNotset() {
|
||||||
|
$this->smarty->assign('test', 0);
|
||||||
|
$this->assertEquals("nay", $this->smarty->fetch("string:{if isset(\$test, \$test2)}yay{else}nay{/if}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters() {
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{empty(3, 'foo')}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace UnitTests\TemplateSource\TagTests\PluginFunction;
|
||||||
|
class TimeTest extends \PHPUnit_Smarty {
|
||||||
|
|
||||||
|
public function setUp(): void {
|
||||||
|
$this->setUpSmarty(__DIR__);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBasicSyntax() {
|
||||||
|
$this->assertStringMatchesFormat('%d', $this->smarty->fetch("string:{time()}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvalidParameters() {
|
||||||
|
$this->expectException(\Smarty\Exception::class);
|
||||||
|
$this->expectExceptionMessage('Invalid number of arguments');
|
||||||
|
$this->assertEquals("", $this->smarty->fetch("string:{time(3, 'foo')}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user