mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-04 18:34:27 +02:00
- optimization of capture and security handling
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
===== 3.1.30-dev ===== (xx.xx.xx)
|
||||
11.03.2014
|
||||
- optimization of capture and security handling
|
||||
|
||||
10.03.2014
|
||||
- optimization of resource processing
|
||||
|
||||
|
@@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase
|
||||
/**
|
||||
* smarty version
|
||||
*/
|
||||
const SMARTY_VERSION = '3.1.30-dev/55';
|
||||
const SMARTY_VERSION = '3.1.30-dev/56';
|
||||
|
||||
/**
|
||||
* define variable scopes
|
||||
|
@@ -32,51 +32,53 @@ class Smarty_Internal_Compile_Capture extends Smarty_Internal_CompileBase
|
||||
*/
|
||||
public $optional_attributes = array('name', 'assign', 'append');
|
||||
|
||||
/**
|
||||
* Compiles code for the {$smarty.capture.xxx}
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param \Smarty_Internal_TemplateCompilerBase$compiler compiler object
|
||||
* @param array $parameter array with compilation parameter
|
||||
*
|
||||
* @return string compiled code
|
||||
* @throws \SmartyCompilerException
|
||||
*/
|
||||
public static function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = null)
|
||||
{
|
||||
// make all lower case
|
||||
$parameter = array_map('strtolower', $parameter);
|
||||
$tag = trim($parameter[ 0 ], '"\'');
|
||||
$name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false;
|
||||
if (!$name) {
|
||||
$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
|
||||
}
|
||||
return "\$_smarty_tpl->ext->_capture->getBuffer(\$_smarty_tpl, '{$name}')";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles code for the {capture} tag
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param array $args array with attributes from parser
|
||||
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
|
||||
* @param null $parameter
|
||||
*
|
||||
* @return string compiled code
|
||||
*/
|
||||
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
||||
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = null)
|
||||
{
|
||||
// check and get attributes
|
||||
$_attr = $this->getAttributes($compiler, $args);
|
||||
$_attr = $this->getAttributes($compiler, $args, $parameter, 'capture');
|
||||
|
||||
$buffer = isset($_attr[ 'name' ]) ? $_attr[ 'name' ] : "'default'";
|
||||
$assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : 'null';
|
||||
$append = isset($_attr[ 'append' ]) ? $_attr[ 'append' ] : 'null';
|
||||
|
||||
$this->openTag($compiler, 'capture', array($buffer, $assign, $append, $compiler->nocache));
|
||||
$compiler->_cache[ 'capture_stack' ][] = array($compiler->nocache);
|
||||
// maybe nocache because of nocache variables
|
||||
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
|
||||
$_output =
|
||||
"<?php \$_smarty_tpl->smarty->_cache['capture_stack'][] = array($buffer, $assign, $append); ob_start(); ?>";
|
||||
$_output = "<?php \$_smarty_tpl->ext->_capture->open(\$_smarty_tpl, $buffer, $assign, $append);\n?>\n";
|
||||
|
||||
return $_output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles code for the {$smarty.capture.xxx}
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
|
||||
* @param array $parameter array with compilation parameter
|
||||
*
|
||||
* @return string compiled code
|
||||
* @throws \SmartyCompilerException
|
||||
*/
|
||||
public static function compileSpecialVariable($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
|
||||
{
|
||||
$tag = strtolower(trim($parameter[ 0 ], '"\''));
|
||||
$name = isset($parameter[ 1 ]) ? $compiler->getId($parameter[ 1 ]) : false;
|
||||
if (!$name) {
|
||||
$compiler->trigger_template_error("missing or illegal \$smarty.{$tag} name attribute", null, true);
|
||||
}
|
||||
return "(isset(\$_smarty_tpl->smarty->_cache['__smarty_capture']['{$name}']) ? \$_smarty_tpl->smarty->_cache['__smarty_capture']['{$name}'] : null)";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,29 +92,23 @@ class Smarty_Internal_Compile_CaptureClose extends Smarty_Internal_CompileBase
|
||||
/**
|
||||
* Compiles code for the {/capture} tag
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param array $args array with attributes from parser
|
||||
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
|
||||
* @param null $parameter
|
||||
*
|
||||
* @return string compiled code
|
||||
*/
|
||||
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
||||
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
|
||||
{
|
||||
// check and get attributes
|
||||
$_attr = $this->getAttributes($compiler, $args);
|
||||
$_attr = $this->getAttributes($compiler, $args, $parameter, '/capture');
|
||||
// must endblock be nocache?
|
||||
if ($compiler->nocache) {
|
||||
$compiler->tag_nocache = true;
|
||||
}
|
||||
list($buffer, $assign, $append, $compiler->nocache) = $this->closeTag($compiler, array('capture'));
|
||||
|
||||
$_output =
|
||||
"<?php list(\$_capture_buffer, \$_capture_assign, \$_capture_append) = array_pop(\$_smarty_tpl->smarty->_cache['capture_stack']);\n";
|
||||
$_output .= "if (!empty(\$_capture_buffer)) {\n";
|
||||
$_output .= " if (isset(\$_capture_assign)) \$_smarty_tpl->assign(\$_capture_assign, ob_get_contents());\n";
|
||||
$_output .= " if (isset( \$_capture_append)) \$_smarty_tpl->append( \$_capture_append, ob_get_contents());\n";
|
||||
$_output .= "\$_smarty_tpl->smarty->_cache['__smarty_capture'][\$_capture_buffer]=ob_get_clean();\n";
|
||||
$_output .= "} else \$_smarty_tpl->capture_error();?>";
|
||||
list($compiler->nocache) = array_pop($compiler->_cache[ 'capture_stack' ]);
|
||||
|
||||
return $_output;
|
||||
return "<?php \$_smarty_tpl->ext->_capture->close(\$_smarty_tpl);\n?>\n";
|
||||
}
|
||||
}
|
||||
|
155
libs/sysplugins/smarty_internal_runtime_capture.php
Normal file
155
libs/sysplugins/smarty_internal_runtime_capture.php
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Runtime Extension Capture
|
||||
*
|
||||
* @package Smarty
|
||||
* @subpackage PluginsInternal
|
||||
* @author Uwe Tews
|
||||
*/
|
||||
class Smarty_Internal_Runtime_Capture
|
||||
{
|
||||
/**
|
||||
* Flag that this instance will not be cached
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $isPrivateExtension = true;
|
||||
|
||||
/**
|
||||
* Stack of capture parameter
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $captureStack = array();
|
||||
|
||||
/**
|
||||
* Current open capture sections
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $captureCount = 0;
|
||||
|
||||
/**
|
||||
* Count stack
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
private $countStack = array();
|
||||
|
||||
/**
|
||||
* Flag if callbacks are registered
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $isRegistered = false;
|
||||
|
||||
/**
|
||||
* Open capture section
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
* @param string $buffer capture name
|
||||
* @param string $assign variable name
|
||||
* @param string $append variable name
|
||||
*/
|
||||
public function open(Smarty_Internal_Template $_template, $buffer, $assign, $append)
|
||||
{
|
||||
if (!$this->isRegistered) {
|
||||
$this->register($_template);
|
||||
}
|
||||
$this->captureStack[] = array($buffer, $assign, $append);
|
||||
$this->captureCount ++;
|
||||
ob_start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register callbacks in template class
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
*/
|
||||
private function register(Smarty_Internal_Template $_template)
|
||||
{
|
||||
$_template->startRenderCallbacks[] = array($this, 'startRender');
|
||||
$_template->endRenderCallbacks[] = array($this, 'endRender');
|
||||
$this->startRender($_template);
|
||||
$this->isRegistered = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start render callback
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
*/
|
||||
public function startRender(Smarty_Internal_Template $_template)
|
||||
{
|
||||
$this->countStack[] = $this->captureCount;
|
||||
$this->captureCount = 0;
|
||||
$_template->_cache[ 'capture' ] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close capture section
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
*
|
||||
* @throws \SmartyException
|
||||
*/
|
||||
public function close(Smarty_Internal_Template $_template)
|
||||
{
|
||||
if ($this->captureCount) {
|
||||
list($buffer, $assign, $append) = array_pop($this->captureStack);
|
||||
$this->captureCount --;
|
||||
if (isset($assign)) {
|
||||
$_template->assign($assign, ob_get_contents());
|
||||
}
|
||||
if (isset($append)) {
|
||||
$_template->append($append, ob_get_contents());
|
||||
}
|
||||
$_template->_cache[ 'capture' ][ $buffer ] = ob_get_clean();
|
||||
} else {
|
||||
$this->error($_template);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Error exception on not matching {capture}{/capture}
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
*
|
||||
* @throws \SmartyException
|
||||
*/
|
||||
public function error(Smarty_Internal_Template $_template)
|
||||
{
|
||||
throw new SmartyException("Not matching {capture}{/capture} in \"{$_template->template_resource}\"");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return content of named capture buffer
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
* @param $name
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getBuffer(Smarty_Internal_Template $_template, $name)
|
||||
{
|
||||
return isset($_template->_cache[ 'capture' ][ $name ]) ? $_template->_cache[ 'capture' ][ $name ] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* End render callback
|
||||
*
|
||||
* @param \Smarty_Internal_Template $_template
|
||||
*
|
||||
* @throws \SmartyException
|
||||
*/
|
||||
public function endRender(Smarty_Internal_Template $_template)
|
||||
{
|
||||
if ($this->captureCount) {
|
||||
$this->error($_template);
|
||||
} else {
|
||||
$this->captureCount = array_pop($this->countStack);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -87,6 +87,21 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
|
||||
*/
|
||||
public $isRenderingCache = false;
|
||||
|
||||
/**
|
||||
* Callbacks called before rendering template
|
||||
*
|
||||
* @var callback[]
|
||||
*/
|
||||
public $startRenderCallbacks = array();
|
||||
|
||||
/**
|
||||
* Callbacks called after rendering template
|
||||
*
|
||||
* @var callback[]
|
||||
*/
|
||||
public $endRenderCallbacks = array();
|
||||
|
||||
|
||||
/**
|
||||
* Create template data object
|
||||
* Some of the global Smarty settings copied to template scope
|
||||
@@ -120,6 +135,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
|
||||
$this->template_resource = $template_resource;
|
||||
$this->source = Smarty_Template_Source::load($this);
|
||||
parent::__construct();
|
||||
if ($smarty->security_policy && method_exists($smarty->security_policy, 'registerCallBacks')) {
|
||||
$smarty->security_policy->registerCallBacks($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -387,15 +387,21 @@ class Smarty_Internal_TestInstall
|
||||
'smarty_internal_compile_make_nocache.php' => true,
|
||||
'smarty_internal_compile_nocache.php' => true,
|
||||
'smarty_internal_compile_private_block_plugin.php' => true,
|
||||
'smarty_internal_compile_private_compiler_plugin.php' => true,
|
||||
'smarty_internal_compile_private_foreachsection.php' => true,
|
||||
'smarty_internal_compile_private_function_plugin.php' => true,
|
||||
'smarty_internal_compile_private_modifier.php' => true,
|
||||
'smarty_internal_compile_private_modifiercompiler_plugin.php' => true,
|
||||
'smarty_internal_compile_private_modifier_plugin.php' => true,
|
||||
'smarty_internal_compile_private_object.php' => true,
|
||||
'smarty_internal_compile_private_object_block_function.php' => true,
|
||||
'smarty_internal_compile_private_object_function.php' => true,
|
||||
'smarty_internal_compile_private_php.php' => true,
|
||||
'smarty_internal_compile_private_print_expression.php' => true,
|
||||
'smarty_internal_compile_private_registered_block.php' => true,
|
||||
'smarty_internal_compile_private_registered_compiler.php' => true,
|
||||
'smarty_internal_compile_private_registered_function.php' => true,
|
||||
'smarty_internal_compile_private_registered_modifier.php' => true,
|
||||
'smarty_internal_compile_private_special_variable.php' => true,
|
||||
'smarty_internal_compile_rdelim.php' => true,
|
||||
'smarty_internal_compile_section.php' => true,
|
||||
@@ -469,7 +475,9 @@ class Smarty_Internal_TestInstall
|
||||
'smarty_internal_resource_registered.php' => true,
|
||||
'smarty_internal_resource_stream.php' => true,
|
||||
'smarty_internal_resource_string.php' => true,
|
||||
'smarty_internal_runtime_assignindexed.php' => true,
|
||||
'smarty_internal_runtime_cachemodify.php' => true,
|
||||
'smarty_internal_runtime_capture.php' => true,
|
||||
'smarty_internal_runtime_codeframe.php' => true,
|
||||
'smarty_internal_runtime_filterhandler.php' => true,
|
||||
'smarty_internal_runtime_foreach.php' => true,
|
||||
|
@@ -625,33 +625,7 @@ class Smarty_Security
|
||||
$this->_checkDir($this->smarty->_realpath($filepath, true), $this->_php_resource_dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start template processing
|
||||
*
|
||||
* @param $template
|
||||
*
|
||||
* @throws SmartyException
|
||||
*/
|
||||
public function startTemplate($template)
|
||||
{
|
||||
if ($this->max_template_nesting > 0 && $this->_current_template_nesting ++ >= $this->max_template_nesting) {
|
||||
throw new SmartyException("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit template processing
|
||||
*
|
||||
* @internal param $template
|
||||
*/
|
||||
public function exitTemplate()
|
||||
{
|
||||
if ($this->max_template_nesting > 0) {
|
||||
$this->_current_template_nesting --;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if file is inside a valid directory
|
||||
*
|
||||
@@ -716,4 +690,39 @@ class Smarty_Security
|
||||
}
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Start template processing
|
||||
*
|
||||
* @param $template
|
||||
*
|
||||
* @throws SmartyException
|
||||
*/
|
||||
public function startTemplate($template)
|
||||
{
|
||||
if ($this->max_template_nesting > 0 && $this->_current_template_nesting ++ >= $this->max_template_nesting) {
|
||||
throw new SmartyException("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit template processing
|
||||
*
|
||||
*/
|
||||
public function endTemplate()
|
||||
{
|
||||
if ($this->max_template_nesting > 0) {
|
||||
$this->_current_template_nesting --;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register callback functions call at start/end of template rendering
|
||||
*
|
||||
* @param \Smarty_Internal_Template $template
|
||||
*/
|
||||
public function registerCallBacks(Smarty_Internal_Template $template)
|
||||
{
|
||||
$template->startRenderCallbacks[] = array($this, 'startTemplate');
|
||||
$template->endRenderCallbacks[] = array($this, 'endTemplate');
|
||||
}
|
||||
}
|
||||
|
@@ -121,23 +121,14 @@ abstract class Smarty_Template_Resource_Base
|
||||
if (empty($unifunc) || !function_exists($unifunc)) {
|
||||
throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'");
|
||||
}
|
||||
if (isset($smarty->security_policy)) {
|
||||
$smarty->security_policy->startTemplate($_template);
|
||||
if ($_template->startRenderCallbacks) {
|
||||
foreach ($_template->startRenderCallbacks as $callback) {
|
||||
call_user_func($callback, $_template);
|
||||
}
|
||||
}
|
||||
//
|
||||
// render compiled or saved template code
|
||||
//
|
||||
if (!isset($_template->_cache[ 'capture_stack' ])) {
|
||||
$_template->_cache[ 'capture_stack' ] = array();
|
||||
}
|
||||
$_saved_capture_level = count($_template->_cache[ 'capture_stack' ]);
|
||||
$unifunc($_template);
|
||||
// any unclosed {capture} tags ?
|
||||
if ($_saved_capture_level != count($_template->_cache[ 'capture_stack' ])) {
|
||||
$_template->capture_error();
|
||||
}
|
||||
if (isset($smarty->security_policy)) {
|
||||
$smarty->security_policy->exitTemplate();
|
||||
foreach ($_template->endRenderCallbacks as $callback) {
|
||||
call_user_func($callback, $_template);
|
||||
}
|
||||
$_template->isRenderingCache = false;
|
||||
return null;
|
||||
@@ -148,7 +139,7 @@ abstract class Smarty_Template_Resource_Base
|
||||
ob_end_clean();
|
||||
}
|
||||
if (isset($smarty->security_policy)) {
|
||||
$smarty->security_policy->exitTemplate();
|
||||
$smarty->security_policy->endTemplate();
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
Reference in New Issue
Block a user