Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using PHP functions as modifiers now triggers a deprecation notice. #814

Merged
merged 2 commits into from
Sep 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed
- Include docs and demo in the releases [#799](https://github.com/smarty-php/smarty/issues/799)
- Using PHP functions as modifiers now triggers a deprecation notice because we will drop support for this in the next major release [#813](https://github.com/smarty-php/smarty/issues/813)

### Fixed
- Output buffer is now cleaned for internal PHP errors as well, not just for Exceptions [#514](https://github.com/smarty-php/smarty/issues/514)
Expand Down
36 changes: 36 additions & 0 deletions libs/plugins/modifier.count.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifier
*/
/**
* Smarty count modifier plugin
* Type: modifier
* Name: count
* Purpose: counts all elements in an array or in a Countable object
* Input:
* - Countable|array: array or object to count
* - mode: int defaults to 0 for normal count mode, if set to 1 counts recursive
*
* @param mixed $arrayOrObject input array/object
* @param int $mode count mode
*
* @return int
*/
function smarty_modifier_count($arrayOrObject, $mode = 0)
{
/*
* @see https://www.php.net/count
* > 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.
*/

if ($arrayOrObject instanceof Countable || is_array($arrayOrObject)) {
return count($arrayOrObject, (int) $mode);
} elseif ($arrayOrObject === null) {
return 0;
}
return 1;
}
23 changes: 23 additions & 0 deletions libs/plugins/modifiercompiler.nl2br.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty nl2br modifier plugin
* Type: modifier
* Name: nl2br
* Purpose: insert HTML line breaks before all newlines in a string
*
* @link https://www.smarty.net/docs/en/language.modifier.nl2br.tpl nl2br (Smarty online manual)
*
* @param array $params parameters
*
* @return string with compiled code
*/
function smarty_modifiercompiler_nl2br($params) {
return 'nl2br((string) ' . $params[0] . ', (bool) ' . ($params[1] ?? true) . ')';
}
23 changes: 23 additions & 0 deletions libs/plugins/modifiercompiler.round.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty round modifier plugin
* Type: modifier
* Name: round
* Purpose: Returns the rounded value of num to specified precision (number of digits after the decimal point)
*
* @link https://www.smarty.net/docs/en/language.modifier.round.tpl round (Smarty online manual)
*
* @param array $params parameters
*
* @return string with compiled code
*/
function smarty_modifiercompiler_round($params) {
return 'round((float) ' . $params[0] . ', (int) ' . ($params[1] ?? 0) . ', (int) ' . ($params[2] ?? PHP_ROUND_HALF_UP) . ')';
}
23 changes: 23 additions & 0 deletions libs/plugins/modifiercompiler.str_repeat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty str_repeat modifier plugin
* Type: modifier
* Name: str_repeat
* Purpose: returns string repeated times times
*
* @link https://www.smarty.net/docs/en/language.modifier.str_repeat.tpl str_repeat (Smarty online manual)
*
* @param array $params parameters
*
* @return string with compiled code
*/
function smarty_modifiercompiler_str_repeat($params) {
return 'str_repeat((string) ' . $params[0] . ', (int) ' . $params[1] . ')';
}
23 changes: 23 additions & 0 deletions libs/plugins/modifiercompiler.strlen.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/**
* Smarty plugin
*
* @package Smarty
* @subpackage PluginsModifierCompiler
*/
/**
* Smarty strlen modifier plugin
* Type: modifier
* Name: strlen
* Purpose: return the length of the given string
*
* @link https://www.smarty.net/docs/en/language.modifier.strlen.tpl strlen (Smarty online manual)
*
* @param array $params parameters
*
* @return string with compiled code
*/
function smarty_modifiercompiler_strlen($params) {
return 'strlen((string) ' . $params[0] . ')';
}
3 changes: 3 additions & 0 deletions libs/sysplugins/smarty_internal_compile_private_modifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
if (!is_object($compiler->smarty->security_policy)
|| $compiler->smarty->security_policy->isTrustedPhpModifier($modifier, $compiler)
) {
trigger_error('Using php-function "' . $modifier . '" as a modifier is deprecated and will be ' .
'removed in a future release. Use Smarty::registerPlugin to explicitly register ' .
'a custom modifier.', E_USER_DEPRECATED);
$output = "{$modifier}({$params})";
}
$compiler->known_modifier_type[ $modifier ] = $type;
Expand Down
4 changes: 2 additions & 2 deletions libs/sysplugins/smarty_security.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class Smarty_Security
*
* @var array
*/
public $php_modifiers = array('escape', 'count', 'nl2br',);
public $php_modifiers = array('escape', 'count', 'sizeof', 'nl2br',);

/**
* This is an array of allowed tags.
Expand Down Expand Up @@ -328,7 +328,7 @@ public function isTrustedStaticClassAccess($class_name, $params, $compiler)
*
* @param string $modifier_name
* @param object $compiler compiler object
*
* @deprecated
* @return boolean true if modifier is trusted
*/
public function isTrustedPhpModifier($modifier_name, $compiler)
Expand Down
19 changes: 11 additions & 8 deletions tests/UnitTests/SecurityTests/SecurityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public function testSecurityLoaded()
*/
public function testTrustedPHPFunction()
{
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{count($foo)}'));
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
}

/**
Expand All @@ -63,9 +63,9 @@ public function testTrustedPHPFunction()
public function testNotTrustedPHPFunction()
{
$this->expectException('SmartyException');
$this->expectExceptionMessage('PHP function \'count\' not allowed by security setting');
$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]}{count($foo)}');
$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}');
}

/**
Expand All @@ -75,38 +75,41 @@ 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]}{count($foo)}'));
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{sizeof($foo)}'));
}

/**
* test trusted modifier
* @deprecated
*/
public function testTrustedModifier()
{
$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@count}'));
$this->assertEquals("5", @$this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}'));
}

/**
* test not trusted modifier
* @runInSeparateProcess
* @preserveGlobalState disabled
* @deprecated
*/
public function testNotTrustedModifier()
{
$this->expectException('SmartyException');
$this->expectExceptionMessage('modifier \'count\' 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|@count}');
@$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|@count}'));
@$this->assertEquals("5", $this->smarty->fetch('string:{assign var=foo value=[1,2,3,4,5]}{$foo|@sizeof}'));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ public function testRegisterBlockFunctionModifier1()
{
$this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->assign('value', 1);
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|strtoupper}'));
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|upper}'));
}

public function testRegisterBlockFunctionModifier2()
{
$this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->assign('value', 1);
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|default:""|strtoupper}'));
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|default:""|upper}'));
}

public function testRegisterBlockFunctionWrapper()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ public function testRegisteredObjectBlockFunction()

public function testRegisteredObjectBlockFunctionModifier1()
{
$tpl = $this->smarty->createTemplate('eval:{objecttest->myblock}hello world{/objecttest->myblock|strtoupper}');
$tpl = $this->smarty->createTemplate('eval:{objecttest->myblock}hello world{/objecttest->myblock|upper}');
$this->assertEquals(strtoupper('block test'), $this->smarty->fetch($tpl));
}

public function testRegisteredObjectBlockFunctionModifier2()
{
$tpl = $this->smarty->createTemplate('eval:{objecttest->myblock}hello world{/objecttest->myblock|default:""|strtoupper}');
$tpl = $this->smarty->createTemplate('eval:{objecttest->myblock}hello world{/objecttest->myblock|default:""|upper}');
$this->assertEquals(strtoupper('block test'), $this->smarty->fetch($tpl));
}
// TODO
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function setUp(): void
$this->smarty->addPluginsDir("../../../__shared/PHPunitplugins/");
$this->smarty->addTemplateDir("../../../__shared/templates/");
$this->smarty->addTemplateDir("./templates_tmp");
$this->smarty->registerPlugin('modifier', 'var_export', 'var_export');
}

public function testInit()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function setUp(): void
$this->smarty->addPluginsDir("../../../__shared/PHPunitplugins/");
$this->smarty->addTemplateDir("../../../__shared/templates/");
$this->smarty->addTemplateDir("./templates_tmp");
$this->smarty->registerPlugin('modifier', 'var_export', 'var_export');
}

public function testInit()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public function setUp(): void
$this->smarty->addPluginsDir("../../../__shared/PHPunitplugins/");
$this->smarty->addTemplateDir("../../../__shared/templates/");
$this->smarty->addTemplateDir("./templates_tmp");
$this->smarty->registerPlugin('modifier', 'var_export', 'var_export');
}

public function testInit()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Smarty PHPunit tests of modifier
*/

/**
* class for modifier tests
*
* @runTestsInSeparateProcess
* @preserveGlobalState disabled
* @backupStaticAttributes enabled
*/
class PluginModifierCountTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(dirname(__FILE__));
}

public function testArray()
{
$tpl = $this->smarty->createTemplate('string:count:{$v|count}');
$tpl->assign("v", array(1, 2, 3));
$this->assertEquals("count:3", $this->smarty->fetch($tpl));
}

public function testEmptyArray()
{
$tpl = $this->smarty->createTemplate('string:count:{$v|count}');
$tpl->assign("v", array());
$this->assertEquals("count:0", $this->smarty->fetch($tpl));
}

public function testNull()
{
$tpl = $this->smarty->createTemplate('string:count:{$v|count}');
$tpl->assign("v", null);
$this->assertEquals("count:0", $this->smarty->fetch($tpl));
}

public function testString()
{
$tpl = $this->smarty->createTemplate('string:count:{$v|count}');
$tpl->assign("v", "string");
$this->assertEquals("count:1", $this->smarty->fetch($tpl));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class PluginModifierExplodeTest extends \PHPUnit_Smarty
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
$this->smarty->registerPlugin('modifier', 'json_encode', 'json_encode');
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Smarty PHPunit tests of modifier
*/

/**
* class for modifier tests
*
* @runTestsInSeparateProcess
* @preserveGlobalState disabled
* @backupStaticAttributes enabled
*/
class PluginModifierNl2brTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(dirname(__FILE__));
}

public function testDefault()
{
$tpl = $this->smarty->createTemplate('string:{$v|nl2br}');
$tpl->assign("v", "Line1\nLine2");
$this->assertEquals("Line1<br />\nLine2", $this->smarty->fetch($tpl));
}

public function testNoXHTML()
{
$tpl = $this->smarty->createTemplate('string:{$v|nl2br:false}');
$tpl->assign("v", "Line1\nLine2");
$this->assertEquals("Line1<br>\nLine2", $this->smarty->fetch($tpl));
}
}
Loading