From 6b97d5cdd5b2b00651fd38030284beab5d39e8dd Mon Sep 17 00:00:00 2001 From: Uwe Tews Date: Thu, 12 Oct 2017 20:15:42 +0200 Subject: [PATCH] - unclosed block tag in double quted string must throw compiler exception. https://github.com/smarty-php/smarty/issues/391 https://github.com/smarty-php/smarty/issues/392 --- change_log.txt | 2 + lexer/smarty_internal_templatelexer.plex | 2 + lexer/smarty_internal_templateparser.y | 2 +- libs/Smarty.class.php | 2 +- .../smarty_internal_templatecompilerbase.php | 1102 +++++++++-------- .../smarty_internal_templatelexer.php | 31 +- .../smarty_internal_templateparser.php | 245 +--- 7 files changed, 641 insertions(+), 745 deletions(-) diff --git a/change_log.txt b/change_log.txt index f7fbc0df7..39fb52f4a 100644 --- a/change_log.txt +++ b/change_log.txt @@ -2,6 +2,8 @@ 12.10.2017 - bugfix $smarty.block.child and $smarty.block.parent could not be used like any $smarty special variable https://github.com/smarty-php/smarty/issues/393 + - unclosed block tag in double quoted string must throw compiler exception. + https://github.com/smarty-php/smarty/issues/391 https://github.com/smarty-php/smarty/issues/392 07.10.2017 - bugfix modification of 9.8.2017 did fail on some recursive diff --git a/lexer/smarty_internal_templatelexer.plex b/lexer/smarty_internal_templatelexer.plex index cbd136261..189569c94 100644 --- a/lexer/smarty_internal_templatelexer.plex +++ b/lexer/smarty_internal_templatelexer.plex @@ -510,6 +510,7 @@ class Smarty_Internal_Templatelexer double_quote { $this->token = Smarty_Internal_Templateparser::TP_QUOTE; $this->yypushstate(self::DOUBLEQUOTEDSTRING); + $this->compiler->enterDoubleQuote(); } singlequotestring { $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; @@ -693,6 +694,7 @@ class Smarty_Internal_Templatelexer double_quote { $this->token = Smarty_Internal_Templateparser::TP_QUOTE; $this->yypopstate(); + $this->compiler->leaveDoubleQuote(); } backtick dollar { $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; diff --git a/lexer/smarty_internal_templateparser.y b/lexer/smarty_internal_templateparser.y index d623639ef..b27354dfb 100644 --- a/lexer/smarty_internal_templateparser.y +++ b/lexer/smarty_internal_templateparser.y @@ -135,7 +135,7 @@ class Smarty_Internal_Templateparser public $template_prefix = array(); /** - * security object + * template prefix array * * @var \Smarty_Internal_ParseTree[] */ diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 521ba9147..9dcc2137d 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -108,7 +108,7 @@ class Smarty extends Smarty_Internal_TemplateBase /** * smarty version */ - const SMARTY_VERSION = '3.1.32-dev-24'; + const SMARTY_VERSION = '3.1.32-dev-25'; /** * define variable scopes diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 70c832a88..24f445777 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -1,5 +1,4 @@ smarty = $smarty; $this->nocache_hash = str_replace(array('.', - ','), '_', uniqid(rand(), true)); + ','), + '_', + uniqid(rand(), true)); } /** @@ -331,15 +295,18 @@ public function __construct(Smarty $smarty) * @return bool true if compiling succeeded, false if it failed * @throws \Exception */ - public function compileTemplate(Smarty_Internal_Template $template, $nocache = null, + public function compileTemplate(Smarty_Internal_Template $template, + $nocache = null, Smarty_Internal_TemplateCompilerBase $parent_compiler = null) { // get code frame of compiled template $_compiled_code = $template->smarty->ext->_codeFrame->create($template, - $this->compileTemplateSource($template, $nocache, + $this->compileTemplateSource($template, + $nocache, $parent_compiler), $this->postFilter($this->blockOrFunctionCode) . - join('', $this->mergedSubTemplatesCode), false, + join('', $this->mergedSubTemplatesCode), + false, $this); return $_compiled_code; } @@ -354,7 +321,8 @@ public function compileTemplate(Smarty_Internal_Template $template, $nocache = n * @return string * @throws \Exception */ - public function compileTemplateSource(Smarty_Internal_Template $template, $nocache = null, + public function compileTemplateSource(Smarty_Internal_Template $template, + $nocache = null, Smarty_Internal_TemplateCompilerBase $parent_compiler = null) { try { @@ -494,488 +462,231 @@ public function compileTag($tag, $args, $parameter = array()) } /** - * Compile Tag + * compile variable * - * @param string $tag tag name - * @param array $args array with tag attributes - * @param array $parameter array with compilation parameter + * @param string $variable * - * @throws SmartyCompilerException - * @throws SmartyException - * @return string compiled code + * @return string */ - private function compileTag2($tag, $args, $parameter) + public function compileVariable($variable) { - $plugin_type = ''; - // $args contains the attributes parsed and compiled by the lexer/parser - // assume that tag does compile into code, but creates no HTML output - $this->has_code = true; - $this->has_output = false; - // log tag/attributes - if (isset($this->smarty->_cache[ 'get_used_tags' ])) { - $this->template->_cache[ 'used_tags' ][] = array($tag, - $args); + if (strpos($variable, '(') == 0) { + // not a variable variable + $var = trim($variable, '\''); + $this->tag_nocache = $this->tag_nocache | + $this->template->ext->getTemplateVars->_getVariable($this->template, + $var, + null, + true, + false)->nocache; + // todo $this->template->compiled->properties['variables'][$var] = $this->tag_nocache | $this->nocache; } - // check nocache option flag - foreach ($args as $arg) { - if (!is_array($arg)) { - if ($arg === "'nocache'" || $arg === 'nocache') { - $this->tag_nocache = true; - } - } else { - foreach ($arg as $k => $v) { - if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) { - $this->tag_nocache = true; + return '$_smarty_tpl->tpl_vars[' . $variable . ']->value'; + } + + /** + * compile config variable + * + * @param string $variable + * + * @return string + */ + public function compileConfigVariable($variable) + { + // return '$_smarty_tpl->config_vars[' . $variable . ']'; + return '$_smarty_tpl->smarty->ext->configLoad->_getConfigVariable($_smarty_tpl, ' . $variable . ')'; + } + + /** + * compile PHP function call + * + * @param string $name + * @param array $parameter + * + * @return string + */ + 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 = strtolower($name); + $par = implode(',', $parameter); + $parHasFuction = strpos($par, '(') !== false; + if ($func_name === 'isset') { + if (count($parameter) === 0) { + $this->trigger_template_error('Illegal number of parameter in "isset()"'); + } + if ($parHasFuction) { + $pa = array(); + foreach ($parameter as $p) { + $pa[] = (strpos($p, '(') === false) ? ('isset(' . $p . ')') : ('(' . $p . ' !== null )'); + } + return "(" . implode(' && ', $pa) . ")"; + } else { + $isset_par = str_replace("')->value", "',null,true,false)->value", $par); } + return $name . "(" . $isset_par . ")"; + } else if (in_array($func_name, + array('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') { + if ($parHasFuction && version_compare(PHP_VERSION, '5.5.0', '<')) { + return '(' . $parameter[ 0 ] . ' == false )'; + } else { + 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 . "\""); } } - // compile the smarty tag (required compile classes to compile the tag are auto loaded) - if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { - if (isset($this->parent_compiler->tpl_function[ $tag ]) || - (isset ($this->template->smarty->ext->_tplFunction) && - $this->template->smarty->ext->_tplFunction->getTplFunction($this->template, $tag) !== false) - ) { - // template defined by {template} tag - $args[ '_attr' ][ 'name' ] = "'" . $tag . "'"; - $_output = $this->callTagCompiler('call', $args, $parameter); - } - } - if ($_output !== false) { - if ($_output !== true) { - // did we get compiled code - if ($this->has_code) { - // Does it create output? - if ($this->has_output) { - $_output .= "\n"; + } + + /** + * This method is called from parser to process a text content section + * - remove text from inheritance child templates as they may generate output + * - strip text if strip is enabled + * + * @param string $text + * + * @return null|\Smarty_Internal_ParseTree_Text + */ + public function processText($text) + { + if ((string)$text !== '') { + $store = array(); + $_store = 0; + if ($this->parser->strip) { + if (strpos($text, '<') !== false) { + // capture html elements not to be messed with + $_offset = 0; + if (preg_match_all('#(]*>.*?]*>)|(]*>.*?]*>)|(]*>.*?]*>)#is', + $text, + $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + foreach ($matches as $match) { + $store[] = $match[ 0 ][ 0 ]; + $_length = strlen($match[ 0 ][ 0 ]); + $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length); + $_offset += $_length - strlen($replace); + ++$_store; + } } - // return compiled code - return $_output; - } - } - // tag did not produce compiled code - return null; - } else { - // map_named attributes - if (isset($args[ '_attr' ])) { - foreach ($args[ '_attr' ] as $key => $attribute) { - if (is_array($attribute)) { - $args = array_merge($args, $attribute); + $expressions = array(// replace multiple spaces between tags by a single space + '#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2', + // remove newline between tags + '#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2', + // remove multiple spaces between attributes (but not in attribute values!) + '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5', + '#>[\040\011]+$#Ss' => '> ', + '#>[\040\011]*[\n]\s*$#Ss' => '>', + $this->stripRegEx => '',); + $text = preg_replace(array_keys($expressions), array_values($expressions), $text); + $_offset = 0; + if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', + $text, + $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + foreach ($matches as $match) { + $_length = strlen($match[ 0 ][ 0 ]); + $replace = $store[ $match[ 1 ][ 0 ] ]; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length); + $_offset += strlen($replace) - $_length; + ++$_store; + } } + } else { + $text = preg_replace($this->stripRegEx, '', $text); } } - // not an internal compiler tag - if (strlen($tag) < 6 || substr($tag, - 5) !== 'close') { - // check if tag is a registered object - if (isset($this->smarty->registered_objects[ $tag ]) && isset($parameter[ 'object_method' ])) { - $method = $parameter[ 'object_method' ]; - if (!in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ]) && - (empty($this->smarty->registered_objects[ $tag ][ 1 ]) || - in_array($method, $this->smarty->registered_objects[ $tag ][ 1 ])) - ) { - return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method); - } elseif (in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, - $method); - } else { - // throw exception - $this->trigger_template_error('not allowed method "' . $method . '" in registered object "' . - $tag . '"', null, true); - } - } - // check if tag is registered - foreach (array(Smarty::PLUGIN_COMPILER, - Smarty::PLUGIN_FUNCTION, - Smarty::PLUGIN_BLOCK,) as $plugin_type) { - if (isset($this->smarty->registered_plugins[ $plugin_type ][ $tag ])) { - // if compiler function plugin call it now - if ($plugin_type === Smarty::PLUGIN_COMPILER) { - $new_args = array(); - foreach ($args as $key => $mixed) { - if (is_array($mixed)) { - $new_args = array_merge($new_args, $mixed); - } else { - $new_args[ $key ] = $mixed; - } - } - if (!$this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 1 ]) { - $this->tag_nocache = true; - } - return call_user_func_array($this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 0 ], - array($new_args, - $this)); - } - // compile registered function or block function - if ($plugin_type === Smarty::PLUGIN_FUNCTION || $plugin_type === Smarty::PLUGIN_BLOCK) { - return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, - $tag); - } - } - } - // check plugins from plugins folder - foreach ($this->plugin_search_order as $plugin_type) { - if ($plugin_type === Smarty::PLUGIN_COMPILER && - $this->smarty->loadPlugin('smarty_compiler_' . $tag) && - (!isset($this->smarty->security_policy) || - $this->smarty->security_policy->isTrustedTag($tag, $this)) - ) { - $plugin = 'smarty_compiler_' . $tag; - if (is_callable($plugin)) { - // convert arguments format for old compiler plugins - $new_args = array(); - foreach ($args as $key => $mixed) { - if (is_array($mixed)) { - $new_args = array_merge($new_args, $mixed); - } else { - $new_args[ $key ] = $mixed; - } - } - - return $plugin($new_args, $this->smarty); - } - if (class_exists($plugin, false)) { - $plugin_object = new $plugin; - if (method_exists($plugin_object, 'compile')) { - return $plugin_object->compile($args, $this); - } - } - throw new SmartyException("Plugin \"{$tag}\" not callable"); - } else { - if ($function = $this->getPlugin($tag, $plugin_type)) { - if (!isset($this->smarty->security_policy) || - $this->smarty->security_policy->isTrustedTag($tag, $this) - ) { - return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter, - $tag, $function); - } - } - } - } - if (is_callable($this->smarty->default_plugin_handler_func)) { - $found = false; - // look for already resolved tags - foreach ($this->plugin_search_order as $plugin_type) { - if (isset($this->default_handler_plugins[ $plugin_type ][ $tag ])) { - $found = true; - break; - } - } - if (!$found) { - // call default handler - foreach ($this->plugin_search_order as $plugin_type) { - if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) { - $found = true; - break; - } - } - } - if ($found) { - // if compiler function plugin call it now - if ($plugin_type === Smarty::PLUGIN_COMPILER) { - $new_args = array(); - foreach ($args as $key => $mixed) { - if (is_array($mixed)) { - $new_args = array_merge($new_args, $mixed); - } else { - $new_args[ $key ] = $mixed; - } - } - return call_user_func_array($this->default_handler_plugins[ $plugin_type ][ $tag ][ 0 ], - array($new_args, - $this)); - } else { - return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, - $tag); - } - } - } - } else { - // compile closing tag of block function - $base_tag = substr($tag, 0, - 5); - // check if closing tag is a registered object - if (isset($this->smarty->registered_objects[ $base_tag ]) && isset($parameter[ 'object_method' ])) { - $method = $parameter[ 'object_method' ]; - if (in_array($method, $this->smarty->registered_objects[ $base_tag ][ 3 ])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, - $method); - } else { - // throw exception - $this->trigger_template_error('not allowed closing tag method "' . $method . - '" in registered object "' . $base_tag . '"', null, true); - } - } - // registered block tag ? - if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) || - isset($this->default_handler_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) - ) { - return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag); - } - // registered function tag ? - if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ])) { - return $this->callTagCompiler('private_registered_function', $args, $parameter, $tag); - } - // block plugin? - if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { - return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function); - } - // function plugin? - if ($function = $this->getPlugin($tag, Smarty::PLUGIN_FUNCTION)) { - if (!isset($this->smarty->security_policy) || - $this->smarty->security_policy->isTrustedTag($tag, $this) - ) { - return $this->callTagCompiler('private_function_plugin', $args, $parameter, $tag, $function); - } - } - // registered compiler plugin ? - if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ])) { - // if compiler function plugin call it now - $args = array(); - if (!$this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 1 ]) { - $this->tag_nocache = true; - } - return call_user_func_array($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 0 ], - array($args, - $this)); - } - if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) { - $plugin = 'smarty_compiler_' . $tag; - if (is_callable($plugin)) { - return $plugin($args, $this->smarty); - } - if (class_exists($plugin, false)) { - $plugin_object = new $plugin; - if (method_exists($plugin_object, 'compile')) { - return $plugin_object->compile($args, $this); - } - } - throw new SmartyException("Plugin \"{$tag}\" not callable"); - } - } - $this->trigger_template_error("unknown tag \"" . $tag . "\"", null, true); + return new Smarty_Internal_ParseTree_Text($text); } + return null; } /** - * compile variable + * lazy loads internal compile plugin for tag and calls the compile method + * compile objects cached for reuse. + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php * - * @param string $variable + * @param string $tag tag name + * @param array $args list of tag attributes + * @param mixed $param1 optional parameter + * @param mixed $param2 optional parameter + * @param mixed $param3 optional parameter * - * @return string + * @return string|bool compiled code or false */ - public function compileVariable($variable) + public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) { - if (strpos($variable, '(') == 0) { - // not a variable variable - $var = trim($variable, '\''); - $this->tag_nocache = $this->tag_nocache | - $this->template->ext->getTemplateVars->_getVariable($this->template, $var, null, true, - false)->nocache; - // todo $this->template->compiled->properties['variables'][$var] = $this->tag_nocache | $this->nocache; - } - return '$_smarty_tpl->tpl_vars[' . $variable . ']->value'; + /* @var Smarty_Internal_CompileBase $tagCompiler */ + $tagCompiler = $this->getTagCompiler($tag); + // compile this tag + return $tagCompiler === false ? false : $tagCompiler->compile($args, $this, $param1, $param2, $param3); } /** - * compile config variable + * lazy loads internal compile plugin for tag compile objects cached for reuse. * - * @param string $variable + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php * - * @return string + * @param string $tag tag name + * + * @return Smarty_Internal_CompileBase|bool tag compiler object or false if not found */ - public function compileConfigVariable($variable) + public function getTagCompiler($tag) { - // return '$_smarty_tpl->config_vars[' . $variable . ']'; - return '$_smarty_tpl->smarty->ext->configLoad->_getConfigVariable($_smarty_tpl, ' . $variable . ')'; + // re-use object if already exists + if (!isset(self::$_tag_objects[ $tag ])) { + // lazy load internal compiler plugin + $_tag = explode('_', $tag); + $_tag = array_map('ucfirst', $_tag); + $class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag); + if (class_exists($class_name) && + (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + self::$_tag_objects[ $tag ] = new $class_name; + } else { + self::$_tag_objects[ $tag ] = false; + } + } + return self::$_tag_objects[ $tag ]; } /** - * compile PHP function call + * Check for plugins and return function name * - * @param string $name - * @param array $parameter + * @param $plugin_name + * @param string $plugin_type type of plugin * - * @return string + * @return string call name of function */ - 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 = strtolower($name); - $par = implode(',', $parameter); - $parHasFuction = strpos($par, '(') !== false; - if ($func_name === 'isset') { - if (count($parameter) === 0) { - $this->trigger_template_error('Illegal number of parameter in "isset()"'); - } - if ($parHasFuction) { - $pa = array(); - foreach ($parameter as $p) { - $pa[] = (strpos($p, '(') === false) ? ('isset(' . $p . ')') : ('(' . $p . ' !== null )'); - } - return "(" . implode(' && ', $pa) . ")"; - } else { - $isset_par = str_replace("')->value", "',null,true,false)->value", $par); - } - return $name . "(" . $isset_par . ")"; - } elseif (in_array($func_name, array('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') { - if ($parHasFuction && version_compare(PHP_VERSION, '5.5.0', '<')) { - return '(' . $parameter[ 0 ] . ' == false )'; - } else { - 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 . "\""); - } - } - } - - /** - * This method is called from parser to process a text content section - * - remove text from inheritance child templates as they may generate output - * - strip text if strip is enabled - * - * @param string $text - * - * @return null|\Smarty_Internal_ParseTree_Text - */ - public function processText($text) - { - if ((string) $text !== '') { - $store = array(); - $_store = 0; - if ($this->parser->strip) { - if (strpos($text, '<') !== false) { - // capture html elements not to be messed with - $_offset = 0; - if (preg_match_all('#(]*>.*?]*>)|(]*>.*?]*>)|(]*>.*?]*>)#is', - $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { - foreach ($matches as $match) { - $store[] = $match[ 0 ][ 0 ]; - $_length = strlen($match[ 0 ][ 0 ]); - $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; - $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length); - - $_offset += $_length - strlen($replace); - ++ $_store; - } - } - $expressions = array(// replace multiple spaces between tags by a single space - '#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2', - // remove newline between tags - '#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2', - // remove multiple spaces between attributes (but not in attribute values!) - '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5', - '#>[\040\011]+$#Ss' => '> ', - '#>[\040\011]*[\n]\s*$#Ss' => '>', - $this->stripRegEx => '',); - - $text = preg_replace(array_keys($expressions), array_values($expressions), $text); - $_offset = 0; - if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $text, $matches, - PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { - foreach ($matches as $match) { - $_length = strlen($match[ 0 ][ 0 ]); - $replace = $store[ $match[ 1 ][ 0 ] ]; - $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length); - - $_offset += strlen($replace) - $_length; - ++ $_store; - } - } - } else { - $text = preg_replace($this->stripRegEx, '', $text); - } - } - return new Smarty_Internal_ParseTree_Text($text); - } - return null; - } - - /** - * lazy loads internal compile plugin for tag and calls the compile method - * compile objects cached for reuse. - * class name format: Smarty_Internal_Compile_TagName - * plugin filename format: Smarty_Internal_TagName.php - * - * @param string $tag tag name - * @param array $args list of tag attributes - * @param mixed $param1 optional parameter - * @param mixed $param2 optional parameter - * @param mixed $param3 optional parameter - * - * @return string|bool compiled code or false - */ - public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) - { - /* @var Smarty_Internal_CompileBase $tagCompiler */ - $tagCompiler = $this->getTagCompiler($tag); - // compile this tag - return $tagCompiler === false ? false : $tagCompiler->compile($args, $this, $param1, $param2, $param3); - } - - /** - * lazy loads internal compile plugin for tag compile objects cached for reuse. - * - * class name format: Smarty_Internal_Compile_TagName - * plugin filename format: Smarty_Internal_TagName.php - * - * @param string $tag tag name - * - * @return Smarty_Internal_CompileBase|bool tag compiler object or false if not found - */ - public function getTagCompiler($tag) - { - // re-use object if already exists - if (!isset(self::$_tag_objects[ $tag ])) { - // lazy load internal compiler plugin - $_tag = explode('_', $tag); - $_tag = array_map('ucfirst', $_tag); - $class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag); - if (class_exists($class_name) && - (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) - ) { - self::$_tag_objects[ $tag ] = new $class_name; - } else { - self::$_tag_objects[ $tag ] = false; - } - } - return self::$_tag_objects[ $tag ]; - } - - /** - * Check for plugins and return function name - * - * @param $plugin_name - * @param string $plugin_type type of plugin - * - * @return string call name of function - */ - public function getPlugin($plugin_name, $plugin_type) + public function getPlugin($plugin_name, $plugin_type) { $function = null; if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { if (isset($this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { $function = $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ]; - } elseif (isset($this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { + } else if (isset($this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ] = $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ]; $function = @@ -985,7 +696,7 @@ public function getPlugin($plugin_name, $plugin_type) if (isset($this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { $function = $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'function' ]; - } elseif (isset($this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { + } else if (isset($this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ] = $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ]; $function = @@ -996,13 +707,11 @@ public function getPlugin($plugin_name, $plugin_type) if ($plugin_type === 'modifier') { $this->modifier_plugins[ $plugin_name ] = true; } - return $function; } // loop through plugin dirs and find the plugin $function = 'smarty_' . $plugin_type . '_' . $plugin_name; $file = $this->smarty->loadPlugin($function, false); - if (is_string($file)) { if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'file' ] = @@ -1018,14 +727,12 @@ public function getPlugin($plugin_name, $plugin_type) if ($plugin_type === 'modifier') { $this->modifier_plugins[ $plugin_name ] = true; } - return $function; } if (is_callable($function)) { // plugin function is defined in the script return $function; } - return false; } @@ -1042,12 +749,13 @@ public function getPluginFromDefaultHandler($tag, $plugin_type) $callback = null; $script = null; $cacheable = true; - $result = call_user_func_array($this->smarty->default_plugin_handler_func, array($tag, - $plugin_type, - $this->template, - &$callback, - &$script, - &$cacheable,)); + $result = call_user_func_array($this->smarty->default_plugin_handler_func, + array($tag, + $plugin_type, + $this->template, + &$callback, + &$script, + &$cacheable,)); if ($result) { $this->tag_nocache = $this->tag_nocache || !$cacheable; if ($script !== null) { @@ -1072,13 +780,11 @@ public function getPluginFromDefaultHandler($tag, $plugin_type) $this->default_handler_plugins[ $plugin_type ][ $tag ] = array($callback, true, array()); - return true; } else { $this->trigger_template_error("Default plugin handler: Returned callback for \"{$tag}\" not callable"); } } - return false; } @@ -1141,7 +847,6 @@ public function processNocacheCode($content, $is_code) $this->modifier_plugins = array(); $this->suppressNocacheProcessing = false; $this->tag_nocache = false; - return $_output; } @@ -1207,7 +912,7 @@ public function convertScope($_attr, $validScopes) $_scopeName = trim($_attr[ 'scope' ], "'\""); if (is_numeric($_scopeName) && in_array($_scopeName, $validScopes)) { $_scope = $_scopeName; - } elseif (is_string($_scopeName)) { + } else if (is_string($_scopeName)) { $_scopeName = trim($_scopeName, "'\""); $_scope = isset($validScopes[ $_scopeName ]) ? $validScopes[ $_scopeName ] : false; } else { @@ -1253,23 +958,23 @@ public function trigger_template_error($args = null, $line = null, $tagline = nu if ($tagline === true) { // get line number of Tag $line = $lex->taglineno; - } elseif (!isset($line)) { + } else if (!isset($line)) { // get template source line which has error $line = $lex->line; } else { - $line = (int) $line; + $line = (int)$line; } - - if (in_array($this->template->source->type, array('eval', - 'string'))) { - $templateName = $this->template->source->type . ':' . trim(preg_replace('![\t\r\n]+!', ' ', + if (in_array($this->template->source->type, + array('eval', + 'string'))) { + $templateName = $this->template->source->type . ':' . trim(preg_replace('![\t\r\n]+!', + ' ', strlen($lex->data) > 40 ? substr($lex->data, 0, 40) . '...' : $lex->data)); } else { $templateName = $this->template->source->type . ':' . $this->template->source->filepath; } - // $line += $this->trace_line_offset; $match = preg_split("/\n/", $lex->data); $error_text = @@ -1317,6 +1022,56 @@ public function getVarExport($value) return preg_replace('/\s/', '', var_export($value, true)); } + /** + * enter double quoted string + * - save tag stack count + */ + public function enterDoubleQuote() + { + array_push($this->_tag_stack_count, $this->getTagStackCount()); + } + + /** + * Return tag stack count + * + * @return int + */ + public function getTagStackCount() + { + return count($this->_tag_stack); + } + + /** + * leave double quoted string + * - throw exception if block in string was not closed + * + * @throws \SmartyCompilerException + */ + public function leaveDoubleQuote() + { + if (array_pop($this->_tag_stack_count) !== $this->getTagStackCount()) { + $tag = $this->getOpenBlockTag(); + $this->trigger_template_error("unclosed \"{{$tag}}\" in doubled quoted string", + null, + true); + } + } + + /** + * Get name of current open block tag + * + * @return string|boolean + */ + public function getOpenBlockTag() + { + $tagCount = $this->getTagStackCount(); + if ($tagCount) { + return $this->_tag_stack[ $tagCount - 1 ][ 0 ]; + } else { + return false; + } + } + /** * Check if $value contains variable elements * @@ -1350,7 +1105,7 @@ public function isVariable($value) */ public function getNewPrefixVariable() { - ++ self::$prefixVariableNumber; + ++self::$prefixVariableNumber; return $this->getPrefixVariable(); } @@ -1391,4 +1146,291 @@ public function getPrefixCode() return $code; } + /** + * method to compile a Smarty template + * + * @param mixed $_content template source + * @param bool $isTemplateSource + * + * @return bool true if compiling succeeded, false if it failed + */ + abstract protected function doCompile($_content, $isTemplateSource = false); + + /** + * Compile Tag + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * + * @throws SmartyCompilerException + * @throws SmartyException + * @return string compiled code + */ + private function compileTag2($tag, $args, $parameter) + { + $plugin_type = ''; + // $args contains the attributes parsed and compiled by the lexer/parser + // assume that tag does compile into code, but creates no HTML output + $this->has_code = true; + $this->has_output = false; + // log tag/attributes + if (isset($this->smarty->_cache[ 'get_used_tags' ])) { + $this->template->_cache[ 'used_tags' ][] = array($tag, + $args); + } + // check nocache option flag + foreach ($args as $arg) { + if (!is_array($arg)) { + if ($arg === "'nocache'" || $arg === 'nocache') { + $this->tag_nocache = true; + } + } else { + foreach ($arg as $k => $v) { + if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) { + $this->tag_nocache = true; + } + } + } + } + // compile the smarty tag (required compile classes to compile the tag are auto loaded) + if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { + if (isset($this->parent_compiler->tpl_function[ $tag ]) || + (isset ($this->template->smarty->ext->_tplFunction) && + $this->template->smarty->ext->_tplFunction->getTplFunction($this->template, $tag) !== false) + ) { + // template defined by {template} tag + $args[ '_attr' ][ 'name' ] = "'" . $tag . "'"; + $_output = $this->callTagCompiler('call', $args, $parameter); + } + } + if ($_output !== false) { + if ($_output !== true) { + // did we get compiled code + if ($this->has_code) { + // Does it create output? + if ($this->has_output) { + $_output .= "\n"; + } + // return compiled code + return $_output; + } + } + // tag did not produce compiled code + return null; + } else { + // map_named attributes + if (isset($args[ '_attr' ])) { + foreach ($args[ '_attr' ] as $key => $attribute) { + if (is_array($attribute)) { + $args = array_merge($args, $attribute); + } + } + } + // not an internal compiler tag + if (strlen($tag) < 6 || substr($tag, -5) !== 'close') { + // check if tag is a registered object + if (isset($this->smarty->registered_objects[ $tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (!in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ]) && + (empty($this->smarty->registered_objects[ $tag ][ 1 ]) || + in_array($method, $this->smarty->registered_objects[ $tag ][ 1 ])) + ) { + return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method); + } else if (in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ])) { + return $this->callTagCompiler('private_object_block_function', + $args, + $parameter, + $tag, + $method); + } else { + // throw exception + $this->trigger_template_error('not allowed method "' . $method . '" in registered object "' . + $tag . '"', + null, + true); + } + } + // check if tag is registered + foreach (array(Smarty::PLUGIN_COMPILER, + Smarty::PLUGIN_FUNCTION, + Smarty::PLUGIN_BLOCK,) as $plugin_type) { + if (isset($this->smarty->registered_plugins[ $plugin_type ][ $tag ])) { + // if compiler function plugin call it now + if ($plugin_type === Smarty::PLUGIN_COMPILER) { + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + if (!$this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 1 ]) { + $this->tag_nocache = true; + } + return call_user_func_array($this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 0 ], + array($new_args, + $this)); + } + // compile registered function or block function + if ($plugin_type === Smarty::PLUGIN_FUNCTION || $plugin_type === Smarty::PLUGIN_BLOCK) { + return $this->callTagCompiler('private_registered_' . $plugin_type, + $args, + $parameter, + $tag); + } + } + } + // check plugins from plugins folder + foreach ($this->plugin_search_order as $plugin_type) { + if ($plugin_type === Smarty::PLUGIN_COMPILER && + $this->smarty->loadPlugin('smarty_compiler_' . $tag) && + (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + $plugin = 'smarty_compiler_' . $tag; + if (is_callable($plugin)) { + // convert arguments format for old compiler plugins + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + return $plugin($new_args, $this->smarty); + } + if (class_exists($plugin, false)) { + $plugin_object = new $plugin; + if (method_exists($plugin_object, 'compile')) { + return $plugin_object->compile($args, $this); + } + } + throw new SmartyException("Plugin \"{$tag}\" not callable"); + } else { + if ($function = $this->getPlugin($tag, $plugin_type)) { + if (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler('private_' . $plugin_type . '_plugin', + $args, + $parameter, + $tag, + $function); + } + } + } + } + if (is_callable($this->smarty->default_plugin_handler_func)) { + $found = false; + // look for already resolved tags + foreach ($this->plugin_search_order as $plugin_type) { + if (isset($this->default_handler_plugins[ $plugin_type ][ $tag ])) { + $found = true; + break; + } + } + if (!$found) { + // call default handler + foreach ($this->plugin_search_order as $plugin_type) { + if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) { + $found = true; + break; + } + } + } + if ($found) { + // if compiler function plugin call it now + if ($plugin_type === Smarty::PLUGIN_COMPILER) { + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + return call_user_func_array($this->default_handler_plugins[ $plugin_type ][ $tag ][ 0 ], + array($new_args, + $this)); + } else { + return $this->callTagCompiler('private_registered_' . $plugin_type, + $args, + $parameter, + $tag); + } + } + } + } else { + // compile closing tag of block function + $base_tag = substr($tag, 0, -5); + // check if closing tag is a registered object + if (isset($this->smarty->registered_objects[ $base_tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (in_array($method, $this->smarty->registered_objects[ $base_tag ][ 3 ])) { + return $this->callTagCompiler('private_object_block_function', + $args, + $parameter, + $tag, + $method); + } else { + // throw exception + $this->trigger_template_error('not allowed closing tag method "' . $method . + '" in registered object "' . $base_tag . '"', + null, + true); + } + } + // registered block tag ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) || + isset($this->default_handler_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) + ) { + return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag); + } + // registered function tag ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ])) { + return $this->callTagCompiler('private_registered_function', $args, $parameter, $tag); + } + // block plugin? + if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { + return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function); + } + // function plugin? + if ($function = $this->getPlugin($tag, Smarty::PLUGIN_FUNCTION)) { + if (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler('private_function_plugin', $args, $parameter, $tag, $function); + } + } + // registered compiler plugin ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ])) { + // if compiler function plugin call it now + $args = array(); + if (!$this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 1 ]) { + $this->tag_nocache = true; + } + return call_user_func_array($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 0 ], + array($args, + $this)); + } + if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) { + $plugin = 'smarty_compiler_' . $tag; + if (is_callable($plugin)) { + return $plugin($args, $this->smarty); + } + if (class_exists($plugin, false)) { + $plugin_object = new $plugin; + if (method_exists($plugin_object, 'compile')) { + return $plugin_object->compile($args, $this); + } + } + throw new SmartyException("Plugin \"{$tag}\" not callable"); + } + } + $this->trigger_template_error("unknown tag \"" . $tag . "\"", null, true); + } + } } diff --git a/libs/sysplugins/smarty_internal_templatelexer.php b/libs/sysplugins/smarty_internal_templatelexer.php index 53b929ea4..1501ab360 100644 --- a/libs/sysplugins/smarty_internal_templatelexer.php +++ b/libs/sysplugins/smarty_internal_templatelexer.php @@ -243,7 +243,7 @@ function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler) $this->dataLength = strlen($this->data); $this->counter = 0; if (preg_match('/^\xEF\xBB\xBF/i', $this->data, $match)) { - $this->counter += strlen($match[0]); + $this->counter += strlen($match[ 0 ]); } $this->line = 1; $this->smarty = $compiler->smarty; @@ -252,15 +252,14 @@ function __construct($source, Smarty_Internal_TemplateCompilerBase $compiler) $this->ldel_length = strlen($this->smarty->left_delimiter); $this->rdel = preg_quote($this->smarty->right_delimiter, '/'); $this->rdel_length = strlen($this->smarty->right_delimiter); - $this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter; - $this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter; + $this->smarty_token_names[ 'LDEL' ] = $this->smarty->left_delimiter; + $this->smarty_token_names[ 'RDEL' ] = $this->smarty->right_delimiter; $literals = $this->smarty->getLiterals(); if (!empty($literals)) { foreach ($literals as $key => $literal) { $literals[ $key ] = preg_quote($literal, '/'); } } - if ($this->smarty->auto_literal) { $literals[] = $this->ldel . '{1,}\\s+'; } @@ -374,10 +373,9 @@ public function yylex1() if ($this->counter >= $this->dataLength) { return false; // end of input } - do { if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) { - if (!isset($yymatches[0][1])) { + if (!isset($yymatches[ 0 ][ 1 ])) { $yymatches = preg_grep("/(.|\s)+/", $yymatches); } else { $yymatches = array_filter($yymatches); @@ -426,8 +424,8 @@ function yy_r1_1() function yy_r1_2() { preg_match("/[*]{$this->rdel}/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); - if (isset($match[0][1])) { - $to = $match[0][1] + strlen($match[0][0]); + if (isset($match[ 0 ][ 1 ])) { + $to = $match[ 0 ][ 1 ] + strlen($match[ 0 ][ 0 ]); } else { $this->compiler->trigger_template_error("missing or misspelled comment closing tag '*{$this->smarty->right_delimiter}'"); } @@ -485,10 +483,9 @@ public function yylex2() if ($this->counter >= $this->dataLength) { return false; // end of input } - do { if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) { - if (!isset($yymatches[0][1])) { + if (!isset($yymatches[ 0 ][ 1 ])) { $yymatches = preg_grep("/(.|\s)+/", $yymatches); } else { $yymatches = array_filter($yymatches); @@ -618,10 +615,9 @@ public function yylex3() if ($this->counter >= $this->dataLength) { return false; // end of input } - do { if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) { - if (!isset($yymatches[0][1])) { + if (!isset($yymatches[ 0 ][ 1 ])) { $yymatches = preg_grep("/(.|\s)+/", $yymatches); } else { $yymatches = array_filter($yymatches); @@ -678,6 +674,7 @@ function yy_r3_3() { $this->token = Smarty_Internal_Templateparser::TP_QUOTE; $this->yypushstate(self::DOUBLEQUOTEDSTRING); + $this->compiler->enterDoubleQuote(); } function yy_r3_4() @@ -816,7 +813,7 @@ function yy_r3_48() if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->rdel_length) == $this->smarty->right_delimiter) { preg_match("/\s+/", $this->value, $match); - $this->value = $match[0]; + $this->value = $match[ 0 ]; $this->token = Smarty_Internal_Templateparser::TP_SPACE; } else { $this->token = Smarty_Internal_Templateparser::TP_ATTR; @@ -906,10 +903,9 @@ public function yylex4() if ($this->counter >= $this->dataLength) { return false; // end of input } - do { if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) { - if (!isset($yymatches[0][1])) { + if (!isset($yymatches[ 0 ][ 1 ])) { $yymatches = preg_grep("/(.|\s)+/", $yymatches); } else { $yymatches = array_filter($yymatches); @@ -989,10 +985,9 @@ public function yylex5() if ($this->counter >= $this->dataLength) { return false; // end of input } - do { if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) { - if (!isset($yymatches[0][1])) { + if (!isset($yymatches[ 0 ][ 1 ])) { $yymatches = preg_grep("/(.|\s)+/", $yymatches); } else { $yymatches = array_filter($yymatches); @@ -1071,6 +1066,7 @@ function yy_r5_7() { $this->token = Smarty_Internal_Templateparser::TP_QUOTE; $this->yypopstate(); + $this->compiler->leaveDoubleQuote(); } function yy_r5_8() @@ -1095,7 +1091,6 @@ function yy_r5_11() { $this->token = Smarty_Internal_Templateparser::TP_TEXT; } - } \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_templateparser.php b/libs/sysplugins/smarty_internal_templateparser.php index f8ae717ce..03d70c45d 100644 --- a/libs/sysplugins/smarty_internal_templateparser.php +++ b/libs/sysplugins/smarty_internal_templateparser.php @@ -38,11 +38,10 @@ public function offsetGet($offset) public function offsetSet($offset, $value) { if ($offset === null) { - if (isset($value[0])) { + if (isset($value[ 0 ])) { $x = ($value instanceof TP_yyToken) ? $value->metadata : $value; $this->metadata = array_merge($this->metadata, $x); - return; } $offset = count($this->metadata); @@ -75,7 +74,6 @@ class TP_yyStackEntry } ; - #line 11 "../smarty/lexer/smarty_internal_templateparser.y" /** @@ -89,7 +87,6 @@ class TP_yyStackEntry class Smarty_Internal_Templateparser { #line 23 "../smarty/lexer/smarty_internal_templateparser.y" - const Err1 = 'Security error: Call to private object member not allowed'; const Err2 = 'Security error: Call to dynamic object member not allowed'; const Err3 = 'PHP in template not allowed. Use SmartyBC to enable it'; @@ -1570,8 +1567,8 @@ class Smarty_Internal_Templateparser 184 => 184, 185 => 185, 186 => 185, - 188 => 185, 187 => 187, + 188 => 188, 189 => 189, 190 => 190, 191 => 191, @@ -1711,7 +1708,6 @@ class Smarty_Internal_Templateparser */ private $internalError = false; /* Shifts left before out of the error */ private $_retvalue; /* The parser's stack */ - /** * constructor * @@ -1807,7 +1803,6 @@ public function yy_pop_parser_stack() $yymajor = $yytos->major; self::yy_destructor($yymajor, $yytos->minor); $this->yyidx--; - return $yymajor; } @@ -1852,10 +1847,10 @@ public function yy_get_expected_tokens($token) return array_unique($expected); } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][1]; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( $this->yystack[ $this->yyidx ]->stateno, - self::$yyRuleInfo[ $yyruleno ][0]); + self::$yyRuleInfo[ $yyruleno ][ 0 ]); if (isset(self::$yyExpectedTokens[ $nextstate ])) { $expected = array_merge($expected, self::$yyExpectedTokens[ $nextstate ]); if (isset($res4[ $nextstate ][ $token ])) { @@ -1878,7 +1873,7 @@ public function yy_get_expected_tokens($token) $this->yyidx++; $x = new TP_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[ $yyruleno ][0]; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; $this->yystack[ $this->yyidx ] = $x; continue 2; } else if ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { @@ -1902,7 +1897,6 @@ public function yy_get_expected_tokens($token) } while (true); $this->yyidx = $yyidx; $this->yystack = $stack; - return array_unique($expected); } @@ -1939,10 +1933,10 @@ public function yy_is_expected_token($token) return true; } $yyruleno = $yyact - self::YYNSTATE; - $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][1]; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][ 1 ]; $nextstate = $this->yy_find_reduce_action( $this->yystack[ $this->yyidx ]->stateno, - self::$yyRuleInfo[ $yyruleno ][0]); + self::$yyRuleInfo[ $yyruleno ][ 0 ]); if (isset($res2[ $nextstate ][ $token ])) { if ($res2[ $nextstate ][ $token ]) { $this->yyidx = $yyidx; @@ -1964,7 +1958,7 @@ public function yy_is_expected_token($token) $this->yyidx++; $x = new TP_yyStackEntry; $x->stateno = $nextstate; - $x->major = self::$yyRuleInfo[ $yyruleno ][0]; + $x->major = self::$yyRuleInfo[ $yyruleno ][ 0 ]; $this->yystack[ $this->yyidx ] = $x; continue 2; } else if ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { @@ -1992,14 +1986,12 @@ public function yy_is_expected_token($token) } while (true); $this->yyidx = $yyidx; $this->yystack = $stack; - return true; } public function yy_find_shift_action($iLookAhead) { $stateno = $this->yystack[ $this->yyidx ]->stateno; - /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ if (!isset(self::$yy_shift_ofst[ $stateno ])) { // no shift actions @@ -2023,10 +2015,8 @@ public function yy_find_shift_action($iLookAhead) $this->yyTokenName[ $iLookAhead ] . " => " . $this->yyTokenName[ $iFallback ] . "\n"); } - return $this->yy_find_shift_action($iFallback); } - return self::$yy_default[ $stateno ]; } else { return self::$yy_action[ $i ]; @@ -2036,7 +2026,6 @@ public function yy_find_shift_action($iLookAhead) public function yy_find_reduce_action($stateno, $iLookAhead) { /* $stateno = $this->yystack[$this->yyidx]->stateno; */ - if (!isset(self::$yy_reduce_ofst[ $stateno ])) { return self::$yy_default[ $stateno ]; } @@ -2057,7 +2046,6 @@ public function yy_find_reduce_action($stateno, $iLookAhead) } #line 220 "../smarty/lexer/smarty_internal_templateparser.y" - public function yy_shift($yyNewState, $yyMajor, $yypMinor) { $this->yyidx++; @@ -2070,10 +2058,8 @@ public function yy_shift($yyNewState, $yyMajor, $yypMinor) $this->yy_pop_parser_stack(); } #line 207 "../smarty/lexer/smarty_internal_templateparser.y" - $this->internalError = true; $this->compiler->trigger_template_error("Stack overflow in template parser"); - return; } $yytos = new TP_yyStackEntry; @@ -2097,7 +2083,6 @@ public function yy_shift($yyNewState, $yyMajor, $yypMinor) } #line 230 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r0() { $this->root_buffer->prepend_array($this, $this->template_prefix); @@ -2106,7 +2091,6 @@ function yy_r0() } #line 237 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r1() { if ($this->yystack[ $this->yyidx + 0 ]->minor != null) { @@ -2115,7 +2099,6 @@ function yy_r1() } #line 251 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r2() { if ($this->yystack[ $this->yyidx + 0 ]->minor != null) { @@ -2125,7 +2108,6 @@ function yy_r2() } #line 262 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r4() { if ($this->compiler->has_code) { @@ -2138,14 +2120,12 @@ function yy_r4() } #line 266 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r5() { $this->_retvalue = new Smarty_Internal_ParseTree_Text($this->yystack[ $this->yyidx + 0 ]->minor); } #line 277 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r6() { $code = $this->compiler->compileTag('private_php', @@ -2166,70 +2146,60 @@ function yy_r6() } #line 281 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r7() { $this->_retvalue = $this->compiler->processText($this->yystack[ $this->yyidx + 0 ]->minor); } #line 285 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r8() { $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; } #line 290 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r9() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 294 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r10() { $this->strip = true; } #line 299 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r11() { $this->strip = false; } #line 303 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r12() { $this->_retvalue = ''; } #line 307 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r13() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; } #line 323 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r14() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 329 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r18() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; } #line 339 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r19() { $var = @@ -2239,7 +2209,7 @@ function yy_r19() $this->_retvalue = $this->compiler->compileTag('private_print_expression', array('nocache'), array('value' => $this->compiler->compileVariable('\'' . - $match[1] . + $match[ 1 ] . '\''))); } else { $this->_retvalue = $this->compiler->compileTag('private_print_expression', @@ -2251,7 +2221,6 @@ function yy_r19() } #line 343 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r20() { $this->_retvalue = $this->compiler->compileTag('private_print_expression', @@ -2260,7 +2229,6 @@ function yy_r20() } #line 366 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r21() { $this->_retvalue = $this->compiler->compileTag('private_print_expression', @@ -2269,7 +2237,6 @@ function yy_r21() } #line 374 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r26() { $this->_retvalue = $this->compiler->compileTag('assign', @@ -2281,7 +2248,6 @@ function yy_r26() } #line 378 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r28() { $this->_retvalue = $this->compiler->compileTag('assign', @@ -2295,21 +2261,19 @@ function yy_r28() } #line 383 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r29() { $this->_retvalue = $this->compiler->compileTag('assign', array_merge(array(array('value' => $this->yystack[ $this->yyidx + -1 ]->minor), array('var' => $this->yystack[ $this->yyidx + - -3 ]->minor['var'])), + -3 ]->minor[ 'var' ])), $this->yystack[ $this->yyidx + 0 ]->minor), array('smarty_internal_index' => $this->yystack[ $this->yyidx + - -3 ]->minor['smarty_internal_index'])); + -3 ]->minor[ 'smarty_internal_index' ])); } #line 405 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r30() { $tag = @@ -2326,7 +2290,7 @@ function yy_r30() $this->compiler->compileTag('private_print_expression', array(), array('value' => $tag)); } else { if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { - $this->_retvalue = $this->compiler->compileTag($match[1], array("'nocache'")); + $this->_retvalue = $this->compiler->compileTag($match[ 1 ], array("'nocache'")); } else { $this->_retvalue = $this->compiler->compileTag($tag, array()); } @@ -2335,7 +2299,6 @@ function yy_r30() } #line 415 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r31() { if (defined($this->yystack[ $this->yyidx + -1 ]->minor)) { @@ -2353,7 +2316,6 @@ function yy_r31() } #line 428 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r32() { if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { @@ -2369,7 +2331,6 @@ function yy_r32() } #line 440 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r33() { if (defined($this->yystack[ $this->yyidx + -2 ]->minor)) { @@ -2391,7 +2352,6 @@ function yy_r33() } #line 445 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r34() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor, @@ -2401,7 +2361,6 @@ function yy_r34() } #line 450 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r35() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -4 ]->minor, @@ -2413,7 +2372,6 @@ function yy_r35() } #line 455 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r36() { $this->_retvalue = $this->compiler->compileTag('make_nocache', @@ -2423,7 +2381,6 @@ function yy_r36() } #line 460 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r37() { $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->lex->ldel_length)); @@ -2434,7 +2391,6 @@ function yy_r37() } #line 465 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r38() { $tag = trim(substr($this->yystack[ $this->yyidx + -2 ]->minor, $this->lex->ldel_length)); @@ -2445,7 +2401,6 @@ function yy_r38() } #line 476 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r39() { $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->lex->ldel_length)); @@ -2456,7 +2411,6 @@ function yy_r39() } #line 480 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r41() { $this->_retvalue = $this->compiler->compileTag('for', @@ -2473,14 +2427,12 @@ function yy_r41() } #line 488 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r42() { $this->_retvalue = '=' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 492 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r44() { $this->_retvalue = $this->compiler->compileTag('for', @@ -2493,7 +2445,6 @@ function yy_r44() } #line 497 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r45() { $this->_retvalue = $this->compiler->compileTag('for', @@ -2508,7 +2459,6 @@ function yy_r45() } #line 501 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r46() { $this->_retvalue = $this->compiler->compileTag('foreach', @@ -2520,7 +2470,6 @@ function yy_r46() } #line 504 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r47() { $this->_retvalue = $this->compiler->compileTag('foreach', @@ -2534,14 +2483,12 @@ function yy_r47() } #line 509 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r48() { $this->_retvalue = $this->compiler->compileTag('foreach', $this->yystack[ $this->yyidx + 0 ]->minor); } #line 513 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r49() { $this->_retvalue = $this->compiler->compileTag('setfilter', @@ -2553,7 +2500,6 @@ function yy_r49() } #line 519 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r50() { $this->_retvalue = $this->compiler->compileTag('setfilter', @@ -2567,7 +2513,6 @@ function yy_r50() } #line 528 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r51() { $tag = @@ -2582,14 +2527,12 @@ function yy_r51() } #line 532 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r52() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + 0 ]->minor . 'close', array()); } #line 537 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r53() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -1 ]->minor . 'close', @@ -2599,7 +2542,6 @@ function yy_r53() } #line 541 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r54() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -2 ]->minor . 'close', @@ -2609,7 +2551,6 @@ function yy_r54() } #line 549 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r55() { $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor . 'close', @@ -2621,7 +2562,6 @@ function yy_r55() } #line 555 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r56() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; @@ -2629,21 +2569,18 @@ function yy_r56() } #line 560 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r57() { $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); } #line 565 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r58() { $this->_retvalue = array(); } #line 576 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r59() { if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { @@ -2660,7 +2597,6 @@ function yy_r59() } #line 584 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r60() { $this->_retvalue = @@ -2669,14 +2605,12 @@ function yy_r60() } #line 596 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r62() { $this->_retvalue = '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\''; } #line 609 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r65() { $this->_retvalue = @@ -2684,7 +2618,6 @@ function yy_r65() } #line 614 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r67() { $this->yystack[ $this->yyidx + -2 ]->minor[] = $this->yystack[ $this->yyidx + 0 ]->minor; @@ -2692,7 +2625,6 @@ function yy_r67() } #line 621 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r68() { $this->_retvalue = array('var' => '\'' . substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . '\'', @@ -2700,7 +2632,6 @@ function yy_r68() } #line 645 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r70() { $this->_retvalue = array('var' => $this->yystack[ $this->yyidx + -2 ]->minor, @@ -2708,7 +2639,6 @@ function yy_r70() } #line 650 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r74() { $this->_retvalue = @@ -2717,7 +2647,6 @@ function yy_r74() } #line 664 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r75() { $this->_retvalue = @@ -2726,7 +2655,6 @@ function yy_r75() } #line 670 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r78() { $this->_retvalue = $this->compiler->compileTag('private_modifier', @@ -2738,16 +2666,14 @@ function yy_r78() } #line 674 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r79() { $this->_retvalue = - $this->yystack[ $this->yyidx + -1 ]->minor['pre'] . $this->yystack[ $this->yyidx + -2 ]->minor . - $this->yystack[ $this->yyidx + -1 ]->minor['op'] . $this->yystack[ $this->yyidx + 0 ]->minor . ')'; + $this->yystack[ $this->yyidx + -1 ]->minor[ 'pre' ] . $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + -1 ]->minor[ 'op' ] . $this->yystack[ $this->yyidx + 0 ]->minor . ')'; } #line 678 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r80() { $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . @@ -2755,14 +2681,12 @@ function yy_r80() } #line 682 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r81() { $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; } #line 686 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r82() { $this->_retvalue = @@ -2771,7 +2695,6 @@ function yy_r82() } #line 694 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r83() { $this->_retvalue = 'in_array(' . $this->yystack[ $this->yyidx + -2 ]->minor . ',(array)' . @@ -2779,7 +2702,6 @@ function yy_r83() } #line 698 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r84() { $this->_retvalue = $this->yystack[ $this->yyidx + -5 ]->minor . ' ? ' . $this->compiler->compileVariable('\'' . @@ -2791,7 +2713,6 @@ function yy_r84() } #line 713 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r85() { $this->_retvalue = @@ -2800,35 +2721,30 @@ function yy_r85() } #line 734 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r88() { $this->_retvalue = '!' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 738 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r93() { $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 742 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r94() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.'; } #line 747 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r95() { $this->_retvalue = '.' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 764 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r96() { if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { @@ -2842,14 +2758,12 @@ function yy_r96() } #line 768 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r98() { $this->_retvalue = "(" . $this->yystack[ $this->yyidx + -1 ]->minor . ")"; } #line 786 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r99() { $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . @@ -2857,30 +2771,28 @@ function yy_r99() } #line 797 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r103() { $prefixVar = $this->compiler->getNewPrefixVariable(); - if ($this->yystack[ $this->yyidx + -2 ]->minor['var'] == '\'smarty\'') { + if ($this->yystack[ $this->yyidx + -2 ]->minor[ 'var' ] == '\'smarty\'') { $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable', array(), $this->yystack[ $this->yyidx + - -2 ]->minor['smarty_internal_index']) . + -2 ]->minor[ 'smarty_internal_index' ]) . ';?>'); } else { $this->compiler->appendPrefixCode("compiler->compileVariable($this->yystack[ $this->yyidx + - -2 ]->minor['var']) . - $this->yystack[ $this->yyidx + -2 ]->minor['smarty_internal_index'] . + -2 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + -2 ]->minor[ 'smarty_internal_index' ] . ';?>'); } - $this->_retvalue = $prefixVar . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[0] . - $this->yystack[ $this->yyidx + 0 ]->minor[1]; + $this->_retvalue = $prefixVar . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . + $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; } #line 814 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r104() { $prefixVar = $this->compiler->getNewPrefixVariable(); @@ -2890,7 +2802,6 @@ function yy_r104() } #line 833 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r107() { if (!in_array(strtolower($this->yystack[ $this->yyidx + -2 ]->minor), array('self', 'parent')) && @@ -2900,11 +2811,11 @@ function yy_r107() if (isset($this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ])) { $this->_retvalue = $this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ] . '::' . - $this->yystack[ $this->yyidx + 0 ]->minor[0] . $this->yystack[ $this->yyidx + 0 ]->minor[1]; + $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; } else { $this->_retvalue = - $this->yystack[ $this->yyidx + -2 ]->minor . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[0] . - $this->yystack[ $this->yyidx + 0 ]->minor[1]; + $this->yystack[ $this->yyidx + -2 ]->minor . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[ 0 ] . + $this->yystack[ $this->yyidx + 0 ]->minor[ 1 ]; } } else { $this->compiler->trigger_template_error("static class '" . $this->yystack[ $this->yyidx + -2 ]->minor . @@ -2913,14 +2824,12 @@ function yy_r107() } #line 844 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r109() { $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; } #line 847 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r110() { $this->_retvalue = @@ -2928,26 +2837,24 @@ function yy_r110() } #line 860 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r111() { - if ($this->yystack[ $this->yyidx + 0 ]->minor['var'] == '\'smarty\'') { + if ($this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ] == '\'smarty\'') { $smarty_var = $this->compiler->compileTag('private_special_variable', array(), $this->yystack[ $this->yyidx + - 0 ]->minor['smarty_internal_index']); + 0 ]->minor[ 'smarty_internal_index' ]); $this->_retvalue = $smarty_var; } else { // used for array reset,next,prev,end,current - $this->last_variable = $this->yystack[ $this->yyidx + 0 ]->minor['var']; - $this->last_index = $this->yystack[ $this->yyidx + 0 ]->minor['smarty_internal_index']; - $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor['var']) . - $this->yystack[ $this->yyidx + 0 ]->minor['smarty_internal_index']; + $this->last_variable = $this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ]; + $this->last_index = $this->yystack[ $this->yyidx + 0 ]->minor[ 'smarty_internal_index' ]; + $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + 0 ]->minor[ 'smarty_internal_index' ]; } } #line 870 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r112() { $this->_retvalue = '$_smarty_tpl->tpl_vars[' . $this->yystack[ $this->yyidx + -2 ]->minor . ']->' . @@ -2955,7 +2862,6 @@ function yy_r112() } #line 874 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r114() { $this->_retvalue = @@ -2963,7 +2869,6 @@ function yy_r114() } #line 878 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r115() { $this->_retvalue = '(is_array($tmp = ' . @@ -2973,14 +2878,12 @@ function yy_r115() } #line 882 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r116() { $this->_retvalue = $this->compiler->compileConfigVariable($this->yystack[ $this->yyidx + -1 ]->minor); } #line 886 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r117() { $this->_retvalue = @@ -2989,7 +2892,6 @@ function yy_r117() } #line 889 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r118() { $this->_retvalue = array('var' => '\'' . @@ -2999,7 +2901,6 @@ function yy_r118() } #line 902 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r119() { $this->_retvalue = array('var' => $this->yystack[ $this->yyidx + -1 ]->minor, @@ -3007,14 +2908,12 @@ function yy_r119() } #line 908 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r121() { return; } #line 911 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r122() { $this->_retvalue = @@ -3023,14 +2922,12 @@ function yy_r122() } #line 915 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r123() { $this->_retvalue = '[' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor) . ']'; } #line 919 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r124() { $this->_retvalue = '[' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + -2 ]->minor) . '->' . @@ -3038,28 +2935,24 @@ function yy_r124() } #line 923 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r125() { $this->_retvalue = "['" . $this->yystack[ $this->yyidx + 0 ]->minor . "']"; } #line 928 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r126() { $this->_retvalue = '[' . $this->yystack[ $this->yyidx + 0 ]->minor . ']'; } #line 933 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r127() { $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; } #line 937 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r128() { $this->_retvalue = '[' . $this->compiler->compileTag('private_special_variable', @@ -3070,7 +2963,6 @@ function yy_r128() } #line 940 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r129() { $this->_retvalue = '[' . $this->compiler->compileTag('private_special_variable', @@ -3081,14 +2973,12 @@ function yy_r129() } #line 946 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r130() { $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; } #line 962 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r132() { $this->_retvalue = '[' . $this->compiler->compileVariable('\'' . @@ -3097,35 +2987,30 @@ function yy_r132() } #line 972 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r136() { $this->_retvalue = '[]'; } #line 976 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r137() { $this->_retvalue = '\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''; } #line 981 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r138() { $this->_retvalue = "''"; } #line 989 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r139() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 995 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r141() { $var = @@ -3135,45 +3020,40 @@ function yy_r141() } #line 1002 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r142() { $this->_retvalue = '(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; } #line 1011 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r143() { - if ($this->yystack[ $this->yyidx + -1 ]->minor['var'] == '\'smarty\'') { + if ($this->yystack[ $this->yyidx + -1 ]->minor[ 'var' ] == '\'smarty\'') { $this->_retvalue = $this->compiler->compileTag('private_special_variable', array(), $this->yystack[ $this->yyidx + - -1 ]->minor['smarty_internal_index']) . + -1 ]->minor[ 'smarty_internal_index' ]) . $this->yystack[ $this->yyidx + 0 ]->minor; } else { - $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor['var']) . - $this->yystack[ $this->yyidx + -1 ]->minor['smarty_internal_index'] . + $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor[ 'var' ]) . + $this->yystack[ $this->yyidx + -1 ]->minor[ 'smarty_internal_index' ] . $this->yystack[ $this->yyidx + 0 ]->minor; } } #line 1016 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r144() { $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; } #line 1021 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r145() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 1028 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r146() { if ($this->security && substr($this->yystack[ $this->yyidx + -1 ]->minor, 0, 1) == '_') { @@ -3184,7 +3064,6 @@ function yy_r146() } #line 1035 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r147() { if ($this->security) { @@ -3195,7 +3074,6 @@ function yy_r147() } #line 1042 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r148() { if ($this->security) { @@ -3206,7 +3084,6 @@ function yy_r148() } #line 1050 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r149() { if ($this->security) { @@ -3218,14 +3095,12 @@ function yy_r149() } #line 1058 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r150() { $this->_retvalue = '->' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 1066 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r151() { $this->_retvalue = $this->compiler->compilePHPFunctionCall($this->yystack[ $this->yyidx + -3 ]->minor, @@ -3233,7 +3108,6 @@ function yy_r151() } #line 1073 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r152() { if ($this->security && substr($this->yystack[ $this->yyidx + -3 ]->minor, 0, 1) == '_') { @@ -3244,7 +3118,6 @@ function yy_r152() } #line 1084 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r153() { if ($this->security) { @@ -3260,7 +3133,6 @@ function yy_r153() } #line 1101 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r154() { $this->_retvalue = @@ -3268,7 +3140,6 @@ function yy_r154() } #line 1105 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r157() { $this->_retvalue = array_merge($this->yystack[ $this->yyidx + -2 ]->minor, @@ -3277,7 +3148,6 @@ function yy_r157() } #line 1113 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r158() { $this->_retvalue = @@ -3285,14 +3155,12 @@ function yy_r158() } #line 1121 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r160() { $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); } #line 1140 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r161() { $this->_retvalue = @@ -3300,14 +3168,12 @@ function yy_r161() } #line 1145 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r165() { $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, '', 'method'); } #line 1150 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r166() { $this->_retvalue = @@ -3315,14 +3181,12 @@ function yy_r166() } #line 1155 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r167() { $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, ''); } #line 1160 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r168() { $this->_retvalue = @@ -3330,7 +3194,6 @@ function yy_r168() } #line 1166 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r169() { $this->_retvalue = array($this->yystack[ $this->yyidx + -2 ]->minor, @@ -3339,14 +3202,12 @@ function yy_r169() } #line 1170 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r170() { $this->_retvalue = ' ' . trim($this->yystack[ $this->yyidx + 0 ]->minor) . ' '; } #line 1189 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r171() { static $lops = array( @@ -3369,7 +3230,6 @@ function yy_r171() } #line 1202 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r172() { static $tlops = array( @@ -3385,7 +3245,6 @@ function yy_r172() } #line 1216 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r173() { static $scond = array( @@ -3399,21 +3258,18 @@ function yy_r173() } #line 1224 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r174() { $this->_retvalue = 'array(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; } #line 1232 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r176() { $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . ',' . $this->yystack[ $this->yyidx + 0 ]->minor; } #line 1236 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r178() { $this->_retvalue = @@ -3421,7 +3277,6 @@ function yy_r178() } #line 1252 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r179() { $this->_retvalue = @@ -3429,14 +3284,12 @@ function yy_r179() } #line 1257 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r182() { $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor->to_smarty_php($this); } #line 1262 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r183() { $this->yystack[ $this->yyidx + -1 ]->minor->append_subtree($this, $this->yystack[ $this->yyidx + 0 ]->minor); @@ -3444,21 +3297,18 @@ function yy_r183() } #line 1266 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r184() { $this->_retvalue = new Smarty_Internal_ParseTree_Dq($this, $this->yystack[ $this->yyidx + 0 ]->minor); } #line 1274 "../smarty/lexer/smarty_internal_templateparser.y" - function yy_r185() { $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)' . $this->yystack[ $this->yyidx + -1 ]->minor); } - #line 1282 "../smarty/lexer/smarty_internal_templateparser.y" - + #line 1278 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r187() { $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)$_smarty_tpl->tpl_vars[\'' . @@ -3466,16 +3316,27 @@ function yy_r187() '\']->value'); } - #line 1286 "../smarty/lexer/smarty_internal_templateparser.y" + #line 1285 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r188() + { + if ($this->template->caching && $this->compiler->tag_nocache) { + $this->compiler->tag_nocache_save = true; + } + $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)' . ($this->template->caching && + $this->compiler->tag_nocache ? + $this->compiler->newPrefixCode($this->yystack[ $this->yyidx + + -1 ]->minor) : + $this->yystack[ $this->yyidx + -1 ]->minor)); + } + #line 1289 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r189() { $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'); } - #line 1290 "../smarty/lexer/smarty_internal_templateparser.y" - + #line 1293 "../smarty/lexer/smarty_internal_templateparser.y" function yy_r190() { $this->_retvalue = new Smarty_Internal_ParseTree_Tag($this, $this->yystack[ $this->yyidx + 0 ]->minor); @@ -3496,7 +3357,6 @@ public function yy_reduce($yyruleno) $yyruleno, self::$yyRuleName[ $yyruleno ]); } - $this->_retvalue = $yy_lefthand_side = null; if (isset(self::$yyReduceMap[ $yyruleno ])) { // call the action @@ -3504,8 +3364,8 @@ public function yy_reduce($yyruleno) $this->{'yy_r' . self::$yyReduceMap[ $yyruleno ]}(); $yy_lefthand_side = $this->_retvalue; } - $yygoto = self::$yyRuleInfo[ $yyruleno ][0]; - $yysize = self::$yyRuleInfo[ $yyruleno ][1]; + $yygoto = self::$yyRuleInfo[ $yyruleno ][ 0 ]; + $yysize = self::$yyRuleInfo[ $yyruleno ][ 1 ]; $this->yyidx -= $yysize; for ($i = $yysize; $i; $i--) { // pop all of the right-hand side parameters @@ -3541,7 +3401,6 @@ public function yy_parse_failed() public function yy_syntax_error($yymajor, $TOKEN) { #line 200 "../smarty/lexer/smarty_internal_templateparser.y" - $this->internalError = true; $this->yymajor = $yymajor; $this->compiler->trigger_template_error(); @@ -3556,7 +3415,6 @@ public function yy_accept() $this->yy_pop_parser_stack(); } #line 193 "../smarty/lexer/smarty_internal_templateparser.y" - $this->successful = !$this->internalError; $this->internalError = false; $this->retvalue = $this->_retvalue; @@ -3565,7 +3423,6 @@ public function yy_accept() public function doParse($yymajor, $yytokenvalue) { $yyerrorhit = 0; /* True if yymajor has invoked an error */ - if ($this->yyidx === null || $this->yyidx < 0) { $this->yyidx = 0; $this->yyerrcnt = -1; @@ -3576,14 +3433,12 @@ public function doParse($yymajor, $yytokenvalue) $this->yystack[] = $x; } $yyendofinput = ($yymajor == 0); - if ($this->yyTraceFILE) { fprintf($this->yyTraceFILE, "%sInput %s\n", $this->yyTracePrompt, $this->yyTokenName[ $yymajor ]); } - do { $yyact = $this->yy_find_shift_action($yymajor); if ($yymajor < self::YYERRORSYMBOL &&