From d82d54bffdfc7b1053df5898f0b62dabca70a15f Mon Sep 17 00:00:00 2001 From: "Uwe.Tews@googlemail.com" Date: Mon, 17 Mar 2014 21:57:15 +0000 Subject: [PATCH] fix line endings --- libs/sysplugins/smarty_internal_parsetree.php | 786 ++++---- .../smarty_internal_templatebase.php | 1644 ++++++++-------- .../smarty_internal_templatecompilerbase.php | 1618 ++++++++-------- libs/sysplugins/smarty_internal_utility.php | 1646 ++++++++--------- 4 files changed, 2847 insertions(+), 2847 deletions(-) diff --git a/libs/sysplugins/smarty_internal_parsetree.php b/libs/sysplugins/smarty_internal_parsetree.php index 03518657..10920b90 100644 --- a/libs/sysplugins/smarty_internal_parsetree.php +++ b/libs/sysplugins/smarty_internal_parsetree.php @@ -1,393 +1,393 @@ -parser = $parser; - $this->data = $data; - $this->saved_block_nesting = $parser->block_nesting_level; - } - - /** - * Return buffer content - * - * @return string content - */ - public function to_smarty_php() - { - return $this->data; - } - - /** - * Return complied code that loads the evaluated outout of buffer content into a temporary variable - * - * @return string template code - */ - public function assign_to_var() - { - $var = sprintf('$_tmp%d', ++Smarty_Internal_Templateparser::$prefix_number); - $this->parser->compiler->prefix_code[] = sprintf('%s', $this->data, $var); - - return $var; - } - -} - -/** - * Code fragment inside a tag. - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_code extends _smarty_parsetree -{ - /** - * Create parse tree buffer for code fragment - * - * @param object $parser parser object - * @param string $data content - */ - public function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - /** - * Return buffer content in parentheses - * - * @return string content - */ - public function to_smarty_php() - { - return sprintf("(%s)", $this->data); - } - -} - -/** - * Double quoted string inside a tag. - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_doublequoted extends _smarty_parsetree -{ - /** - * Create parse tree buffer for double quoted string subtrees - * - * @param object $parser parser object - * @param _smarty_parsetree $subtree parsetree buffer - */ - public function __construct($parser, _smarty_parsetree $subtree) - { - $this->parser = $parser; - $this->subtrees[] = $subtree; - if ($subtree instanceof _smarty_tag) { - $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); - } - } - - /** - * Append buffer to subtree - * - * @param _smarty_parsetree $subtree parsetree buffer - */ - public function append_subtree(_smarty_parsetree $subtree) - { - $last_subtree = count($this->subtrees) - 1; - if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof _smarty_tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) { - if ($subtree instanceof _smarty_code) { - $this->subtrees[$last_subtree]->data .= 'data . ';?>'; - } elseif ($subtree instanceof _smarty_dq_content) { - $this->subtrees[$last_subtree]->data .= 'data . '";?>'; - } else { - $this->subtrees[$last_subtree]->data .= $subtree->data; - } - } else { - $this->subtrees[] = $subtree; - } - if ($subtree instanceof _smarty_tag) { - $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); - } - } - - /** - * Merge subtree buffer content together - * - * @return string compiled template code - */ - public function to_smarty_php() - { - $code = ''; - foreach ($this->subtrees as $subtree) { - if ($code !== "") { - $code .= "."; - } - if ($subtree instanceof _smarty_tag) { - $more_php = $subtree->assign_to_var(); - } else { - $more_php = $subtree->to_smarty_php(); - } - - $code .= $more_php; - - if (!$subtree instanceof _smarty_dq_content) { - $this->parser->compiler->has_variable_string = true; - } - } - - return $code; - } - -} - -/** - * Raw chars as part of a double quoted string. - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_dq_content extends _smarty_parsetree -{ - /** - * Create parse tree buffer with string content - * - * @param object $parser parser object - * @param string $data string section - */ - public function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - /** - * Return content as double quoted string - * - * @return string doubled quoted string - */ - public function to_smarty_php() - { - return '"' . $this->data . '"'; - } - -} - -/** - * Template element - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_template_buffer extends _smarty_parsetree -{ - /** - * Array of template elements - * - * @var array - */ - public $subtrees = Array(); - - /** - * Create root of parse tree for template elements - * - * @param object $parser parse object - */ - public function __construct($parser) - { - $this->parser = $parser; - } - - /** - * Append buffer to subtree - * - * @param _smarty_parsetree $subtree - */ - public function append_subtree(_smarty_parsetree $subtree) - { - $this->subtrees[] = $subtree; - } - - /** - * Sanitize and merge subtree buffers together - * - * @return string template code content - */ - public function to_smarty_php() - { - $code = ''; - for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) { - if ($key + 2 < $cnt) { - if ($this->subtrees[$key] instanceof _smarty_linebreak && $this->subtrees[$key + 1] instanceof _smarty_tag && $this->subtrees[$key + 1]->data == '' && $this->subtrees[$key + 2] instanceof _smarty_linebreak) { - $key = $key + 1; - continue; - } - if (substr($this->subtrees[$key]->data, -1) == '<' && $this->subtrees[$key + 1]->data == '' && substr($this->subtrees[$key + 2]->data, -1) == '?') { - $key = $key + 2; - continue; - } - } - if (substr($code, -1) == '<') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '?') { - $code = substr($code, 0, strlen($code) - 1) . '<?' . substr($subtree, 1); - } elseif ($this->parser->asp_tags && substr($subtree, 0, 1) == '%') { - $code = substr($code, 0, strlen($code) - 1) . '<%' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - if ($this->parser->asp_tags && substr($code, -1) == '%') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '>') { - $code = substr($code, 0, strlen($code) - 1) . '%>' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - if (substr($code, -1) == '?') { - $subtree = $this->subtrees[$key]->to_smarty_php(); - if (substr($subtree, 0, 1) == '>') { - $code = substr($code, 0, strlen($code) - 1) . '?>' . substr($subtree, 1); - } else { - $code .= $subtree; - } - continue; - } - $code .= $this->subtrees[$key]->to_smarty_php(); - } - - return $code; - } - -} - -/** - * template text - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_text extends _smarty_parsetree -{ - /** - * Create template text buffer - * - * @param object $parser parser object - * @param string $data text - */ - public function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - /** - * Return buffer content - * - * @return strint text - */ - public function to_smarty_php() - { - return $this->data; - } - -} - -/** - * template linebreaks - * - * @package Smarty - * @subpackage Compiler - * @ignore - */ -class _smarty_linebreak extends _smarty_parsetree -{ - /** - * Create buffer with linebreak content - * - * @param object $parser parser object - * @param string $data linebreak string - */ - public function __construct($parser, $data) - { - $this->parser = $parser; - $this->data = $data; - } - - /** - * Return linebrak - * - * @return string linebreak - */ - public function to_smarty_php() - { - return $this->data; - } - -} +parser = $parser; + $this->data = $data; + $this->saved_block_nesting = $parser->block_nesting_level; + } + + /** + * Return buffer content + * + * @return string content + */ + public function to_smarty_php() + { + return $this->data; + } + + /** + * Return complied code that loads the evaluated outout of buffer content into a temporary variable + * + * @return string template code + */ + public function assign_to_var() + { + $var = sprintf('$_tmp%d', ++Smarty_Internal_Templateparser::$prefix_number); + $this->parser->compiler->prefix_code[] = sprintf('%s', $this->data, $var); + + return $var; + } + +} + +/** + * Code fragment inside a tag. + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_code extends _smarty_parsetree +{ + /** + * Create parse tree buffer for code fragment + * + * @param object $parser parser object + * @param string $data content + */ + public function __construct($parser, $data) + { + $this->parser = $parser; + $this->data = $data; + } + + /** + * Return buffer content in parentheses + * + * @return string content + */ + public function to_smarty_php() + { + return sprintf("(%s)", $this->data); + } + +} + +/** + * Double quoted string inside a tag. + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_doublequoted extends _smarty_parsetree +{ + /** + * Create parse tree buffer for double quoted string subtrees + * + * @param object $parser parser object + * @param _smarty_parsetree $subtree parsetree buffer + */ + public function __construct($parser, _smarty_parsetree $subtree) + { + $this->parser = $parser; + $this->subtrees[] = $subtree; + if ($subtree instanceof _smarty_tag) { + $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); + } + } + + /** + * Append buffer to subtree + * + * @param _smarty_parsetree $subtree parsetree buffer + */ + public function append_subtree(_smarty_parsetree $subtree) + { + $last_subtree = count($this->subtrees) - 1; + if ($last_subtree >= 0 && $this->subtrees[$last_subtree] instanceof _smarty_tag && $this->subtrees[$last_subtree]->saved_block_nesting < $this->parser->block_nesting_level) { + if ($subtree instanceof _smarty_code) { + $this->subtrees[$last_subtree]->data .= 'data . ';?>'; + } elseif ($subtree instanceof _smarty_dq_content) { + $this->subtrees[$last_subtree]->data .= 'data . '";?>'; + } else { + $this->subtrees[$last_subtree]->data .= $subtree->data; + } + } else { + $this->subtrees[] = $subtree; + } + if ($subtree instanceof _smarty_tag) { + $this->parser->block_nesting_level = count($this->parser->compiler->_tag_stack); + } + } + + /** + * Merge subtree buffer content together + * + * @return string compiled template code + */ + public function to_smarty_php() + { + $code = ''; + foreach ($this->subtrees as $subtree) { + if ($code !== "") { + $code .= "."; + } + if ($subtree instanceof _smarty_tag) { + $more_php = $subtree->assign_to_var(); + } else { + $more_php = $subtree->to_smarty_php(); + } + + $code .= $more_php; + + if (!$subtree instanceof _smarty_dq_content) { + $this->parser->compiler->has_variable_string = true; + } + } + + return $code; + } + +} + +/** + * Raw chars as part of a double quoted string. + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_dq_content extends _smarty_parsetree +{ + /** + * Create parse tree buffer with string content + * + * @param object $parser parser object + * @param string $data string section + */ + public function __construct($parser, $data) + { + $this->parser = $parser; + $this->data = $data; + } + + /** + * Return content as double quoted string + * + * @return string doubled quoted string + */ + public function to_smarty_php() + { + return '"' . $this->data . '"'; + } + +} + +/** + * Template element + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_template_buffer extends _smarty_parsetree +{ + /** + * Array of template elements + * + * @var array + */ + public $subtrees = Array(); + + /** + * Create root of parse tree for template elements + * + * @param object $parser parse object + */ + public function __construct($parser) + { + $this->parser = $parser; + } + + /** + * Append buffer to subtree + * + * @param _smarty_parsetree $subtree + */ + public function append_subtree(_smarty_parsetree $subtree) + { + $this->subtrees[] = $subtree; + } + + /** + * Sanitize and merge subtree buffers together + * + * @return string template code content + */ + public function to_smarty_php() + { + $code = ''; + for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key++) { + if ($key + 2 < $cnt) { + if ($this->subtrees[$key] instanceof _smarty_linebreak && $this->subtrees[$key + 1] instanceof _smarty_tag && $this->subtrees[$key + 1]->data == '' && $this->subtrees[$key + 2] instanceof _smarty_linebreak) { + $key = $key + 1; + continue; + } + if (substr($this->subtrees[$key]->data, -1) == '<' && $this->subtrees[$key + 1]->data == '' && substr($this->subtrees[$key + 2]->data, -1) == '?') { + $key = $key + 2; + continue; + } + } + if (substr($code, -1) == '<') { + $subtree = $this->subtrees[$key]->to_smarty_php(); + if (substr($subtree, 0, 1) == '?') { + $code = substr($code, 0, strlen($code) - 1) . '<?' . substr($subtree, 1); + } elseif ($this->parser->asp_tags && substr($subtree, 0, 1) == '%') { + $code = substr($code, 0, strlen($code) - 1) . '<%' . substr($subtree, 1); + } else { + $code .= $subtree; + } + continue; + } + if ($this->parser->asp_tags && substr($code, -1) == '%') { + $subtree = $this->subtrees[$key]->to_smarty_php(); + if (substr($subtree, 0, 1) == '>') { + $code = substr($code, 0, strlen($code) - 1) . '%>' . substr($subtree, 1); + } else { + $code .= $subtree; + } + continue; + } + if (substr($code, -1) == '?') { + $subtree = $this->subtrees[$key]->to_smarty_php(); + if (substr($subtree, 0, 1) == '>') { + $code = substr($code, 0, strlen($code) - 1) . '?>' . substr($subtree, 1); + } else { + $code .= $subtree; + } + continue; + } + $code .= $this->subtrees[$key]->to_smarty_php(); + } + + return $code; + } + +} + +/** + * template text + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_text extends _smarty_parsetree +{ + /** + * Create template text buffer + * + * @param object $parser parser object + * @param string $data text + */ + public function __construct($parser, $data) + { + $this->parser = $parser; + $this->data = $data; + } + + /** + * Return buffer content + * + * @return strint text + */ + public function to_smarty_php() + { + return $this->data; + } + +} + +/** + * template linebreaks + * + * @package Smarty + * @subpackage Compiler + * @ignore + */ +class _smarty_linebreak extends _smarty_parsetree +{ + /** + * Create buffer with linebreak content + * + * @param object $parser parser object + * @param string $data linebreak string + */ + public function __construct($parser, $data) + { + $this->parser = $parser; + $this->data = $data; + } + + /** + * Return linebrak + * + * @return string linebreak + */ + public function to_smarty_php() + { + return $this->data; + } + +} diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php index 7447940b..4720716f 100644 --- a/libs/sysplugins/smarty_internal_templatebase.php +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -1,822 +1,822 @@ -template_class) { - $template = $this; - } - if (!empty($cache_id) && is_object($cache_id)) { - $parent = $cache_id; - $cache_id = null; - } - if ($parent === null && ($this instanceof Smarty || is_string($template))) { - $parent = $this; - } - // create template object if necessary - $_template = ($template instanceof $this->template_class) - ? $template - : $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); - // if called by Smarty object make sure we use current caching status - if ($this instanceof Smarty) { - $_template->caching = $this->caching; - } - // merge all variable scopes into template - if ($merge_tpl_vars) { - // save local variables - $save_tpl_vars = $_template->tpl_vars; - $save_config_vars = $_template->config_vars; - $ptr_array = array($_template); - $ptr = $_template; - while (isset($ptr->parent)) { - $ptr_array[] = $ptr = $ptr->parent; - } - $ptr_array = array_reverse($ptr_array); - $parent_ptr = reset($ptr_array); - $tpl_vars = $parent_ptr->tpl_vars; - $config_vars = $parent_ptr->config_vars; - while ($parent_ptr = next($ptr_array)) { - if (!empty($parent_ptr->tpl_vars)) { - $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars); - } - if (!empty($parent_ptr->config_vars)) { - $config_vars = array_merge($config_vars, $parent_ptr->config_vars); - } - } - if (!empty(Smarty::$global_tpl_vars)) { - $tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars); - } - $_template->tpl_vars = $tpl_vars; - $_template->config_vars = $config_vars; - } - // dummy local smarty variable - if (!isset($_template->tpl_vars['smarty'])) { - $_template->tpl_vars['smarty'] = new Smarty_Variable; - } - if (isset($this->smarty->error_reporting)) { - $_smarty_old_error_level = error_reporting($this->smarty->error_reporting); - } - // check URL debugging control - if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { - if (isset($_SERVER['QUERY_STRING'])) { - $_query_string = $_SERVER['QUERY_STRING']; - } else { - $_query_string = ''; - } - if (false !== strpos($_query_string, $this->smarty->smarty_debug_id)) { - if (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=on')) { - // enable debugging for this browser session - setcookie('SMARTY_DEBUG', true); - $this->smarty->debugging = true; - } elseif (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=off')) { - // disable debugging for this browser session - setcookie('SMARTY_DEBUG', false); - $this->smarty->debugging = false; - } else { - // enable debugging for this page - $this->smarty->debugging = true; - } - } else { - if (isset($_COOKIE['SMARTY_DEBUG'])) { - $this->smarty->debugging = true; - } - } - } - // must reset merge template date - $_template->smarty->merged_templates_func = array(); - // get rendered template - // disable caching for evaluated code - if ($_template->source->recompiled) { - $_template->caching = false; - } - // checks if template exists - if (!$_template->source->exists) { - if ($_template->parent instanceof Smarty_Internal_Template) { - $parent_resource = " in '{$_template->parent->template_resource}'"; - } else { - $parent_resource = ''; - } - throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}"); - } - // read from cache or render - if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || !$_template->cached->valid) { - // render template (not loaded and not in cache) - if (!$_template->source->uncompiled) { - $_smarty_tpl = $_template; - if ($_template->source->recompiled) { - $code = $_template->compiler->compileTemplate($_template); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_render($_template); - } - try { - ob_start(); - eval("?>" . $code); - unset($code); - } catch (Exception $e) { - ob_get_clean(); - throw $e; - } - } else { - if (!$_template->compiled->exists || ($_template->smarty->force_compile && !$_template->compiled->isCompiled)) { - $_template->compileTemplateSource(); - $code = file_get_contents($_template->compiled->filepath); - eval("?>" . $code); - unset($code); - $_template->compiled->loaded = true; - $_template->compiled->isCompiled = true; - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_render($_template); - } - if (!$_template->compiled->loaded) { - include($_template->compiled->filepath); - if ($_template->mustCompile) { - // recompile and load again - $_template->compileTemplateSource(); - $code = file_get_contents($_template->compiled->filepath); - eval("?>" . $code); - unset($code); - $_template->compiled->isCompiled = true; - } - $_template->compiled->loaded = true; - } else { - $_template->decodeProperties($_template->compiled->_properties, false); - } - try { - ob_start(); - if (empty($_template->properties['unifunc']) || !is_callable($_template->properties['unifunc'])) { - throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'"); - } - array_unshift($_template->_capture_stack,array()); - // - // render compiled template - // - $_template->properties['unifunc']($_template); - // any unclosed {capture} tags ? - if (isset($_template->_capture_stack[0][0])) { - $_template->capture_error(); - } - array_shift($_template->_capture_stack); - } catch (Exception $e) { - ob_get_clean(); - throw $e; - } - } - } else { - if ($_template->source->uncompiled) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_render($_template); - } - try { - ob_start(); - $_template->source->renderUncompiled($_template); - } catch (Exception $e) { - ob_get_clean(); - throw $e; - } - } else { - throw new SmartyException("Resource '$_template->source->type' must have 'renderUncompiled' method"); - } - } - $_output = ob_get_clean(); - if (!$_template->source->recompiled && empty($_template->properties['file_dependency'][$_template->source->uid])) { - $_template->properties['file_dependency'][$_template->source->uid] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type); - } - if ($_template->parent instanceof Smarty_Internal_Template) { - $_template->parent->properties['file_dependency'] = array_merge($_template->parent->properties['file_dependency'], $_template->properties['file_dependency']); - foreach ($_template->required_plugins as $code => $tmp1) { - foreach ($tmp1 as $name => $tmp) { - foreach ($tmp as $type => $data) { - $_template->parent->required_plugins[$code][$name][$type] = $data; - } - } - } - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_render($_template); - } - // write to cache when nessecary - if (!$_template->source->recompiled && ($_template->caching == Smarty::CACHING_LIFETIME_SAVED || $_template->caching == Smarty::CACHING_LIFETIME_CURRENT)) { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_cache($_template); - } - $_template->properties['has_nocache_code'] = false; - // get text between non-cached items - $cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output); - // get non-cached items - preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output, $cache_parts); - $output = ''; - // loop over items, stitch back together - foreach ($cache_split as $curr_idx => $curr_split) { - // escape PHP tags in template content - $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', "\n", $curr_split); - if (isset($cache_parts[0][$curr_idx])) { - $_template->properties['has_nocache_code'] = true; - // remove nocache tags from cache output - $output .= preg_replace("!/\*/?%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]); - } - } - if (!$no_output_filter && !$_template->has_nocache_code && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { - $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template); - } - // rendering (must be done before writing cache file because of {function} nocache handling) - $_smarty_tpl = $_template; - try { - ob_start(); - eval("?>" . $output); - $_output = ob_get_clean(); - } catch (Exception $e) { - ob_get_clean(); - throw $e; - } - // write cache file content - $_template->writeCachedContent($output); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_cache($_template); - } - } else { - // var_dump('renderTemplate', $_template->has_nocache_code, $_template->template_resource, $_template->properties['nocache_hash'], $_template->parent->properties['nocache_hash'], $_output); - if (!empty($_template->properties['nocache_hash']) && !empty($_template->parent->properties['nocache_hash'])) { - // replace nocache_hash - $_output = str_replace("{$_template->properties['nocache_hash']}", $_template->parent->properties['nocache_hash'], $_output); - $_template->parent->has_nocache_code = $_template->parent->has_nocache_code || $_template->has_nocache_code; - } - } - } else { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_cache($_template); - } - try { - ob_start(); - array_unshift($_template->_capture_stack,array()); - // - // render cached template - // - $_template->properties['unifunc']($_template); - // any unclosed {capture} tags ? - if (isset($_template->_capture_stack[0][0])) { - $_template->capture_error(); - } - array_shift($_template->_capture_stack); - $_output = ob_get_clean(); - } catch (Exception $e) { - ob_get_clean(); - throw $e; - } - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_cache($_template); - } - } - if ((!$this->caching || $_template->has_nocache_code || $_template->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { - $_output = Smarty_Internal_Filter_Handler::runFilter('output', $_output, $_template); - } - if (isset($this->error_reporting)) { - error_reporting($_smarty_old_error_level); - } - // display or fetch - if ($display) { - if ($this->caching && $this->cache_modified_check) { - $_isCached = $_template->isCached() && !$_template->has_nocache_code; - $_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); - if ($_isCached && $_template->cached->timestamp <= strtotime($_last_modified_date)) { - switch (PHP_SAPI) { - case 'cgi': // php-cgi < 5.3 - case 'cgi-fcgi': // php-cgi >= 5.3 - case 'fpm-fcgi': // php-fpm >= 5.3.3 - header('Status: 304 Not Modified'); - break; - - case 'cli': - if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) { - $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified'; - } - break; - - default: - header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); - break; - } - } else { - switch (PHP_SAPI) { - case 'cli': - if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) { - $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT'; - } - break; - - default: - header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT'); - break; - } - echo $_output; - } - } else { - echo $_output; - } - // debug output - if ($this->smarty->debugging) { - Smarty_Internal_Debug::display_debug($_template); - } - if ($merge_tpl_vars) { - // restore local variables - $_template->tpl_vars = $save_tpl_vars; - $_template->config_vars = $save_config_vars; - } - - return; - } else { - if ($merge_tpl_vars) { - // restore local variables - $_template->tpl_vars = $save_tpl_vars; - $_template->config_vars = $save_config_vars; - } - // return fetched content - return $_output; - } - } - - /** - * displays a Smarty template - * - * @param string $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - */ - public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) - { - // display template - $this->fetch($template, $cache_id, $compile_id, $parent, true); - } - - /** - * test if cache is valid - * - * @param string|object $template the resource handle of the template file or template object - * @param mixed $cache_id cache id to be used with this template - * @param mixed $compile_id compile id to be used with this template - * @param object $parent next higher level of Smarty variables - * @return boolean cache status - */ - public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) - { - if ($template === null && $this instanceof $this->template_class) { - return $this->cached->valid; - } - if (!($template instanceof $this->template_class)) { - if ($parent === null) { - $parent = $this; - } - $template = $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); - } - // return cache status of template - return $template->cached->valid; - } - - /** - * creates a data object - * - * @param object $parent next higher level of Smarty variables - * @returns Smarty_Data data object - */ - public function createData($parent = null) - { - return new Smarty_Data($parent, $this); - } - - /** - * Registers plugin to be used in templates - * - * @param string $type plugin type - * @param string $tag name of template tag - * @param callback $callback PHP callback to register - * @param boolean $cacheable if true (default) this fuction is cachable - * @param array $cache_attr caching attributes if any - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException when the plugin tag is invalid - */ - public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null) - { - if (isset($this->smarty->registered_plugins[$type][$tag])) { - throw new SmartyException("Plugin tag \"{$tag}\" already registered"); - } elseif (!is_callable($callback)) { - throw new SmartyException("Plugin \"{$tag}\" not callable"); - } else { - $this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr); - } - - return $this; - } - - /** - * Unregister Plugin - * - * @param string $type of plugin - * @param string $tag name of plugin - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unregisterPlugin($type, $tag) - { - if (isset($this->smarty->registered_plugins[$type][$tag])) { - unset($this->smarty->registered_plugins[$type][$tag]); - } - - return $this; - } - - /** - * Registers a resource to fetch a template - * - * @param string $type name of resource type - * @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource (deprecated) - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function registerResource($type, $callback) - { - $this->smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false); - - return $this; - } - - /** - * Unregisters a resource - * - * @param string $type name of resource type - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unregisterResource($type) - { - if (isset($this->smarty->registered_resources[$type])) { - unset($this->smarty->registered_resources[$type]); - } - - return $this; - } - - /** - * Registers a cache resource to cache a template's output - * - * @param string $type name of cache resource type - * @param Smarty_CacheResource $callback instance of Smarty_CacheResource to handle output caching - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function registerCacheResource($type, Smarty_CacheResource $callback) - { - $this->smarty->registered_cache_resources[$type] = $callback; - - return $this; - } - - /** - * Unregisters a cache resource - * - * @param string $type name of cache resource type - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unregisterCacheResource($type) - { - if (isset($this->smarty->registered_cache_resources[$type])) { - unset($this->smarty->registered_cache_resources[$type]); - } - - return $this; - } - - /** - * Registers object to be used in templates - * - * @param string $object name of template object - * @param object $object_impl the referenced PHP object to register - * @param array $allowed list of allowed methods (empty = all) - * @param boolean $smarty_args smarty argument format, else traditional - * @param array $block_methods list of block-methods - * @param array $block_functs list of methods that are block format - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException if any of the methods in $allowed or $block_methods are invalid - */ - public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) - { - // test if allowed methodes callable - if (!empty($allowed)) { - foreach ((array) $allowed as $method) { - if (!is_callable(array($object_impl, $method)) && !property_exists($object_impl, $method)) { - throw new SmartyException("Undefined method or property '$method' in registered object"); - } - } - } - // test if block methodes callable - if (!empty($block_methods)) { - foreach ((array) $block_methods as $method) { - if (!is_callable(array($object_impl, $method))) { - throw new SmartyException("Undefined method '$method' in registered object"); - } - } - } - // register the object - $this->smarty->registered_objects[$object_name] = - array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods); - - return $this; - } - - /** - * return a reference to a registered object - * - * @param string $name object name - * @return object - * @throws SmartyException if no such object is found - */ - public function getRegisteredObject($name) - { - if (!isset($this->smarty->registered_objects[$name])) { - throw new SmartyException("'$name' is not a registered object"); - } - if (!is_object($this->smarty->registered_objects[$name][0])) { - throw new SmartyException("registered '$name' is not an object"); - } - - return $this->smarty->registered_objects[$name][0]; - } - - /** - * unregister an object - * - * @param string $name object name - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unregisterObject($name) - { - if (isset($this->smarty->registered_objects[$name])) { - unset($this->smarty->registered_objects[$name]); - } - - return $this; - } - - /** - * Registers static classes to be used in templates - * - * @param string $class name of template class - * @param string $class_impl the referenced PHP class to register - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException if $class_impl does not refer to an existing class - */ - public function registerClass($class_name, $class_impl) - { - // test if exists - if (!class_exists($class_impl)) { - throw new SmartyException("Undefined class '$class_impl' in register template class"); - } - // register the class - $this->smarty->registered_classes[$class_name] = $class_impl; - - return $this; - } - - /** - * Registers a default plugin handler - * - * @param callable $callback class/method name - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException if $callback is not callable - */ - public function registerDefaultPluginHandler($callback) - { - if (is_callable($callback)) { - $this->smarty->default_plugin_handler_func = $callback; - } else { - throw new SmartyException("Default plugin handler '$callback' not callable"); - } - - return $this; - } - - /** - * Registers a default template handler - * - * @param callable $callback class/method name - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException if $callback is not callable - */ - public function registerDefaultTemplateHandler($callback) - { - if (is_callable($callback)) { - $this->smarty->default_template_handler_func = $callback; - } else { - throw new SmartyException("Default template handler '$callback' not callable"); - } - - return $this; - } - - /** - * Registers a default template handler - * - * @param callable $callback class/method name - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - * @throws SmartyException if $callback is not callable - */ - public function registerDefaultConfigHandler($callback) - { - if (is_callable($callback)) { - $this->smarty->default_config_handler_func = $callback; - } else { - throw new SmartyException("Default config handler '$callback' not callable"); - } - - return $this; - } - - /** - * Registers a filter function - * - * @param string $type filter type - * @param callback $callback - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function registerFilter($type, $callback) - { - $this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback; - - return $this; - } - - /** - * Unregisters a filter function - * - * @param string $type filter type - * @param callback $callback - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unregisterFilter($type, $callback) - { - $name = $this->_get_filter_name($callback); - if (isset($this->smarty->registered_filters[$type][$name])) { - unset($this->smarty->registered_filters[$type][$name]); - } - - return $this; - } - - /** - * Return internal filter name - * - * @param callback $function_name - * @return string internal filter name - */ - public function _get_filter_name($function_name) - { - if (is_array($function_name)) { - $_class_name = (is_object($function_name[0]) ? - get_class($function_name[0]) : $function_name[0]); - - return $_class_name . '_' . $function_name[1]; - } else { - return $function_name; - } - } - - /** - * load a filter of specified type and name - * - * @param string $type filter type - * @param string $name filter name - * @throws SmartyException if filter could not be loaded - */ - public function loadFilter($type, $name) - { - $_plugin = "smarty_{$type}filter_{$name}"; - $_filter_name = $_plugin; - if ($this->smarty->loadPlugin($_plugin)) { - if (class_exists($_plugin, false)) { - $_plugin = array($_plugin, 'execute'); - } - if (is_callable($_plugin)) { - $this->smarty->registered_filters[$type][$_filter_name] = $_plugin; - - return true; - } - } - throw new SmartyException("{$type}filter \"{$name}\" not callable"); - } - - /** - * unload a filter of specified type and name - * - * @param string $type filter type - * @param string $name filter name - * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining - */ - public function unloadFilter($type, $name) - { - $_filter_name = "smarty_{$type}filter_{$name}"; - if (isset($this->smarty->registered_filters[$type][$_filter_name])) { - unset ($this->smarty->registered_filters[$type][$_filter_name]); - } - - return $this; - } - - /** - * preg_replace callback to convert camelcase getter/setter to underscore property names - * - * @param string $match match string - * @return string replacemant - */ - private function replaceCamelcase($match) - { - return "_" . strtolower($match[1]); - } - - /** - * Handle unknown class methods - * - * @param string $name unknown method-name - * @param array $args argument array - */ - public function __call($name, $args) - { - static $_prefixes = array('set' => true, 'get' => true); - static $_resolved_property_name = array(); - static $_resolved_property_source = array(); - - // method of Smarty object? - if (method_exists($this->smarty, $name)) { - return call_user_func_array(array($this->smarty, $name), $args); - } - // see if this is a set/get for a property - $first3 = strtolower(substr($name, 0, 3)); - if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') { - if (isset($_resolved_property_name[$name])) { - $property_name = $_resolved_property_name[$name]; - } else { - // try to keep case correct for future PHP 6.0 case-sensitive class methods - // lcfirst() not available < PHP 5.3.0, so improvise - $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); - // convert camel case to underscored name - $property_name = preg_replace_callback('/([A-Z])/', array($this,'replaceCamelcase'), $property_name); - $_resolved_property_name[$name] = $property_name; - } - if (isset($_resolved_property_source[$property_name])) { - $_is_this = $_resolved_property_source[$property_name]; - } else { - $_is_this = null; - if (property_exists($this, $property_name)) { - $_is_this = true; - } elseif (property_exists($this->smarty, $property_name)) { - $_is_this = false; - } - $_resolved_property_source[$property_name] = $_is_this; - } - if ($_is_this) { - if ($first3 == 'get') - return $this->$property_name; - else - return $this->$property_name = $args[0]; - } elseif ($_is_this === false) { - if ($first3 == 'get') - return $this->smarty->$property_name; - else - return $this->smarty->$property_name = $args[0]; - } else { - throw new SmartyException("property '$property_name' does not exist."); - - return false; - } - } - if ($name == 'Smarty') { - throw new SmartyException("PHP5 requires you to call __construct() instead of Smarty()"); - } - // must be unknown - throw new SmartyException("Call of unknown method '$name'."); - } - -} +template_class) { + $template = $this; + } + if (!empty($cache_id) && is_object($cache_id)) { + $parent = $cache_id; + $cache_id = null; + } + if ($parent === null && ($this instanceof Smarty || is_string($template))) { + $parent = $this; + } + // create template object if necessary + $_template = ($template instanceof $this->template_class) + ? $template + : $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); + // if called by Smarty object make sure we use current caching status + if ($this instanceof Smarty) { + $_template->caching = $this->caching; + } + // merge all variable scopes into template + if ($merge_tpl_vars) { + // save local variables + $save_tpl_vars = $_template->tpl_vars; + $save_config_vars = $_template->config_vars; + $ptr_array = array($_template); + $ptr = $_template; + while (isset($ptr->parent)) { + $ptr_array[] = $ptr = $ptr->parent; + } + $ptr_array = array_reverse($ptr_array); + $parent_ptr = reset($ptr_array); + $tpl_vars = $parent_ptr->tpl_vars; + $config_vars = $parent_ptr->config_vars; + while ($parent_ptr = next($ptr_array)) { + if (!empty($parent_ptr->tpl_vars)) { + $tpl_vars = array_merge($tpl_vars, $parent_ptr->tpl_vars); + } + if (!empty($parent_ptr->config_vars)) { + $config_vars = array_merge($config_vars, $parent_ptr->config_vars); + } + } + if (!empty(Smarty::$global_tpl_vars)) { + $tpl_vars = array_merge(Smarty::$global_tpl_vars, $tpl_vars); + } + $_template->tpl_vars = $tpl_vars; + $_template->config_vars = $config_vars; + } + // dummy local smarty variable + if (!isset($_template->tpl_vars['smarty'])) { + $_template->tpl_vars['smarty'] = new Smarty_Variable; + } + if (isset($this->smarty->error_reporting)) { + $_smarty_old_error_level = error_reporting($this->smarty->error_reporting); + } + // check URL debugging control + if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { + if (isset($_SERVER['QUERY_STRING'])) { + $_query_string = $_SERVER['QUERY_STRING']; + } else { + $_query_string = ''; + } + if (false !== strpos($_query_string, $this->smarty->smarty_debug_id)) { + if (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=on')) { + // enable debugging for this browser session + setcookie('SMARTY_DEBUG', true); + $this->smarty->debugging = true; + } elseif (false !== strpos($_query_string, $this->smarty->smarty_debug_id . '=off')) { + // disable debugging for this browser session + setcookie('SMARTY_DEBUG', false); + $this->smarty->debugging = false; + } else { + // enable debugging for this page + $this->smarty->debugging = true; + } + } else { + if (isset($_COOKIE['SMARTY_DEBUG'])) { + $this->smarty->debugging = true; + } + } + } + // must reset merge template date + $_template->smarty->merged_templates_func = array(); + // get rendered template + // disable caching for evaluated code + if ($_template->source->recompiled) { + $_template->caching = false; + } + // checks if template exists + if (!$_template->source->exists) { + if ($_template->parent instanceof Smarty_Internal_Template) { + $parent_resource = " in '{$_template->parent->template_resource}'"; + } else { + $parent_resource = ''; + } + throw new SmartyException("Unable to load template {$_template->source->type} '{$_template->source->name}'{$parent_resource}"); + } + // read from cache or render + if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || !$_template->cached->valid) { + // render template (not loaded and not in cache) + if (!$_template->source->uncompiled) { + $_smarty_tpl = $_template; + if ($_template->source->recompiled) { + $code = $_template->compiler->compileTemplate($_template); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_render($_template); + } + try { + ob_start(); + eval("?>" . $code); + unset($code); + } catch (Exception $e) { + ob_get_clean(); + throw $e; + } + } else { + if (!$_template->compiled->exists || ($_template->smarty->force_compile && !$_template->compiled->isCompiled)) { + $_template->compileTemplateSource(); + $code = file_get_contents($_template->compiled->filepath); + eval("?>" . $code); + unset($code); + $_template->compiled->loaded = true; + $_template->compiled->isCompiled = true; + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_render($_template); + } + if (!$_template->compiled->loaded) { + include($_template->compiled->filepath); + if ($_template->mustCompile) { + // recompile and load again + $_template->compileTemplateSource(); + $code = file_get_contents($_template->compiled->filepath); + eval("?>" . $code); + unset($code); + $_template->compiled->isCompiled = true; + } + $_template->compiled->loaded = true; + } else { + $_template->decodeProperties($_template->compiled->_properties, false); + } + try { + ob_start(); + if (empty($_template->properties['unifunc']) || !is_callable($_template->properties['unifunc'])) { + throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'"); + } + array_unshift($_template->_capture_stack,array()); + // + // render compiled template + // + $_template->properties['unifunc']($_template); + // any unclosed {capture} tags ? + if (isset($_template->_capture_stack[0][0])) { + $_template->capture_error(); + } + array_shift($_template->_capture_stack); + } catch (Exception $e) { + ob_get_clean(); + throw $e; + } + } + } else { + if ($_template->source->uncompiled) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_render($_template); + } + try { + ob_start(); + $_template->source->renderUncompiled($_template); + } catch (Exception $e) { + ob_get_clean(); + throw $e; + } + } else { + throw new SmartyException("Resource '$_template->source->type' must have 'renderUncompiled' method"); + } + } + $_output = ob_get_clean(); + if (!$_template->source->recompiled && empty($_template->properties['file_dependency'][$_template->source->uid])) { + $_template->properties['file_dependency'][$_template->source->uid] = array($_template->source->filepath, $_template->source->timestamp, $_template->source->type); + } + if ($_template->parent instanceof Smarty_Internal_Template) { + $_template->parent->properties['file_dependency'] = array_merge($_template->parent->properties['file_dependency'], $_template->properties['file_dependency']); + foreach ($_template->required_plugins as $code => $tmp1) { + foreach ($tmp1 as $name => $tmp) { + foreach ($tmp as $type => $data) { + $_template->parent->required_plugins[$code][$name][$type] = $data; + } + } + } + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_render($_template); + } + // write to cache when nessecary + if (!$_template->source->recompiled && ($_template->caching == Smarty::CACHING_LIFETIME_SAVED || $_template->caching == Smarty::CACHING_LIFETIME_CURRENT)) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($_template); + } + $_template->properties['has_nocache_code'] = false; + // get text between non-cached items + $cache_split = preg_split("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output); + // get non-cached items + preg_match_all("!/\*%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!s", $_output, $cache_parts); + $output = ''; + // loop over items, stitch back together + foreach ($cache_split as $curr_idx => $curr_split) { + // escape PHP tags in template content + $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', "\n", $curr_split); + if (isset($cache_parts[0][$curr_idx])) { + $_template->properties['has_nocache_code'] = true; + // remove nocache tags from cache output + $output .= preg_replace("!/\*/?%%SmartyNocache:{$_template->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]); + } + } + if (!$no_output_filter && !$_template->has_nocache_code && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { + $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $_template); + } + // rendering (must be done before writing cache file because of {function} nocache handling) + $_smarty_tpl = $_template; + try { + ob_start(); + eval("?>" . $output); + $_output = ob_get_clean(); + } catch (Exception $e) { + ob_get_clean(); + throw $e; + } + // write cache file content + $_template->writeCachedContent($output); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($_template); + } + } else { + // var_dump('renderTemplate', $_template->has_nocache_code, $_template->template_resource, $_template->properties['nocache_hash'], $_template->parent->properties['nocache_hash'], $_output); + if (!empty($_template->properties['nocache_hash']) && !empty($_template->parent->properties['nocache_hash'])) { + // replace nocache_hash + $_output = str_replace("{$_template->properties['nocache_hash']}", $_template->parent->properties['nocache_hash'], $_output); + $_template->parent->has_nocache_code = $_template->parent->has_nocache_code || $_template->has_nocache_code; + } + } + } else { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($_template); + } + try { + ob_start(); + array_unshift($_template->_capture_stack,array()); + // + // render cached template + // + $_template->properties['unifunc']($_template); + // any unclosed {capture} tags ? + if (isset($_template->_capture_stack[0][0])) { + $_template->capture_error(); + } + array_shift($_template->_capture_stack); + $_output = ob_get_clean(); + } catch (Exception $e) { + ob_get_clean(); + throw $e; + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($_template); + } + } + if ((!$this->caching || $_template->has_nocache_code || $_template->source->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { + $_output = Smarty_Internal_Filter_Handler::runFilter('output', $_output, $_template); + } + if (isset($this->error_reporting)) { + error_reporting($_smarty_old_error_level); + } + // display or fetch + if ($display) { + if ($this->caching && $this->cache_modified_check) { + $_isCached = $_template->isCached() && !$_template->has_nocache_code; + $_last_modified_date = @substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); + if ($_isCached && $_template->cached->timestamp <= strtotime($_last_modified_date)) { + switch (PHP_SAPI) { + case 'cgi': // php-cgi < 5.3 + case 'cgi-fcgi': // php-cgi >= 5.3 + case 'fpm-fcgi': // php-fpm >= 5.3.3 + header('Status: 304 Not Modified'); + break; + + case 'cli': + if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) { + $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = '304 Not Modified'; + } + break; + + default: + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + break; + } + } else { + switch (PHP_SAPI) { + case 'cli': + if (/* ^phpunit */!empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS'])/* phpunit$ */) { + $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT'; + } + break; + + default: + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $_template->cached->timestamp) . ' GMT'); + break; + } + echo $_output; + } + } else { + echo $_output; + } + // debug output + if ($this->smarty->debugging) { + Smarty_Internal_Debug::display_debug($_template); + } + if ($merge_tpl_vars) { + // restore local variables + $_template->tpl_vars = $save_tpl_vars; + $_template->config_vars = $save_config_vars; + } + + return; + } else { + if ($merge_tpl_vars) { + // restore local variables + $_template->tpl_vars = $save_tpl_vars; + $_template->config_vars = $save_config_vars; + } + // return fetched content + return $_output; + } + } + + /** + * displays a Smarty template + * + * @param string $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + */ + public function display($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + // display template + $this->fetch($template, $cache_id, $compile_id, $parent, true); + } + + /** + * test if cache is valid + * + * @param string|object $template the resource handle of the template file or template object + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @return boolean cache status + */ + public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + if ($template === null && $this instanceof $this->template_class) { + return $this->cached->valid; + } + if (!($template instanceof $this->template_class)) { + if ($parent === null) { + $parent = $this; + } + $template = $this->smarty->createTemplate($template, $cache_id, $compile_id, $parent, false); + } + // return cache status of template + return $template->cached->valid; + } + + /** + * creates a data object + * + * @param object $parent next higher level of Smarty variables + * @returns Smarty_Data data object + */ + public function createData($parent = null) + { + return new Smarty_Data($parent, $this); + } + + /** + * Registers plugin to be used in templates + * + * @param string $type plugin type + * @param string $tag name of template tag + * @param callback $callback PHP callback to register + * @param boolean $cacheable if true (default) this fuction is cachable + * @param array $cache_attr caching attributes if any + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException when the plugin tag is invalid + */ + public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null) + { + if (isset($this->smarty->registered_plugins[$type][$tag])) { + throw new SmartyException("Plugin tag \"{$tag}\" already registered"); + } elseif (!is_callable($callback)) { + throw new SmartyException("Plugin \"{$tag}\" not callable"); + } else { + $this->smarty->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr); + } + + return $this; + } + + /** + * Unregister Plugin + * + * @param string $type of plugin + * @param string $tag name of plugin + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unregisterPlugin($type, $tag) + { + if (isset($this->smarty->registered_plugins[$type][$tag])) { + unset($this->smarty->registered_plugins[$type][$tag]); + } + + return $this; + } + + /** + * Registers a resource to fetch a template + * + * @param string $type name of resource type + * @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource (deprecated) + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function registerResource($type, $callback) + { + $this->smarty->registered_resources[$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false); + + return $this; + } + + /** + * Unregisters a resource + * + * @param string $type name of resource type + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unregisterResource($type) + { + if (isset($this->smarty->registered_resources[$type])) { + unset($this->smarty->registered_resources[$type]); + } + + return $this; + } + + /** + * Registers a cache resource to cache a template's output + * + * @param string $type name of cache resource type + * @param Smarty_CacheResource $callback instance of Smarty_CacheResource to handle output caching + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function registerCacheResource($type, Smarty_CacheResource $callback) + { + $this->smarty->registered_cache_resources[$type] = $callback; + + return $this; + } + + /** + * Unregisters a cache resource + * + * @param string $type name of cache resource type + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unregisterCacheResource($type) + { + if (isset($this->smarty->registered_cache_resources[$type])) { + unset($this->smarty->registered_cache_resources[$type]); + } + + return $this; + } + + /** + * Registers object to be used in templates + * + * @param string $object name of template object + * @param object $object_impl the referenced PHP object to register + * @param array $allowed list of allowed methods (empty = all) + * @param boolean $smarty_args smarty argument format, else traditional + * @param array $block_methods list of block-methods + * @param array $block_functs list of methods that are block format + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException if any of the methods in $allowed or $block_methods are invalid + */ + public function registerObject($object_name, $object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + { + // test if allowed methodes callable + if (!empty($allowed)) { + foreach ((array) $allowed as $method) { + if (!is_callable(array($object_impl, $method)) && !property_exists($object_impl, $method)) { + throw new SmartyException("Undefined method or property '$method' in registered object"); + } + } + } + // test if block methodes callable + if (!empty($block_methods)) { + foreach ((array) $block_methods as $method) { + if (!is_callable(array($object_impl, $method))) { + throw new SmartyException("Undefined method '$method' in registered object"); + } + } + } + // register the object + $this->smarty->registered_objects[$object_name] = + array($object_impl, (array) $allowed, (boolean) $smarty_args, (array) $block_methods); + + return $this; + } + + /** + * return a reference to a registered object + * + * @param string $name object name + * @return object + * @throws SmartyException if no such object is found + */ + public function getRegisteredObject($name) + { + if (!isset($this->smarty->registered_objects[$name])) { + throw new SmartyException("'$name' is not a registered object"); + } + if (!is_object($this->smarty->registered_objects[$name][0])) { + throw new SmartyException("registered '$name' is not an object"); + } + + return $this->smarty->registered_objects[$name][0]; + } + + /** + * unregister an object + * + * @param string $name object name + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unregisterObject($name) + { + if (isset($this->smarty->registered_objects[$name])) { + unset($this->smarty->registered_objects[$name]); + } + + return $this; + } + + /** + * Registers static classes to be used in templates + * + * @param string $class name of template class + * @param string $class_impl the referenced PHP class to register + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException if $class_impl does not refer to an existing class + */ + public function registerClass($class_name, $class_impl) + { + // test if exists + if (!class_exists($class_impl)) { + throw new SmartyException("Undefined class '$class_impl' in register template class"); + } + // register the class + $this->smarty->registered_classes[$class_name] = $class_impl; + + return $this; + } + + /** + * Registers a default plugin handler + * + * @param callable $callback class/method name + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException if $callback is not callable + */ + public function registerDefaultPluginHandler($callback) + { + if (is_callable($callback)) { + $this->smarty->default_plugin_handler_func = $callback; + } else { + throw new SmartyException("Default plugin handler '$callback' not callable"); + } + + return $this; + } + + /** + * Registers a default template handler + * + * @param callable $callback class/method name + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException if $callback is not callable + */ + public function registerDefaultTemplateHandler($callback) + { + if (is_callable($callback)) { + $this->smarty->default_template_handler_func = $callback; + } else { + throw new SmartyException("Default template handler '$callback' not callable"); + } + + return $this; + } + + /** + * Registers a default template handler + * + * @param callable $callback class/method name + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + * @throws SmartyException if $callback is not callable + */ + public function registerDefaultConfigHandler($callback) + { + if (is_callable($callback)) { + $this->smarty->default_config_handler_func = $callback; + } else { + throw new SmartyException("Default config handler '$callback' not callable"); + } + + return $this; + } + + /** + * Registers a filter function + * + * @param string $type filter type + * @param callback $callback + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function registerFilter($type, $callback) + { + $this->smarty->registered_filters[$type][$this->_get_filter_name($callback)] = $callback; + + return $this; + } + + /** + * Unregisters a filter function + * + * @param string $type filter type + * @param callback $callback + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unregisterFilter($type, $callback) + { + $name = $this->_get_filter_name($callback); + if (isset($this->smarty->registered_filters[$type][$name])) { + unset($this->smarty->registered_filters[$type][$name]); + } + + return $this; + } + + /** + * Return internal filter name + * + * @param callback $function_name + * @return string internal filter name + */ + public function _get_filter_name($function_name) + { + if (is_array($function_name)) { + $_class_name = (is_object($function_name[0]) ? + get_class($function_name[0]) : $function_name[0]); + + return $_class_name . '_' . $function_name[1]; + } else { + return $function_name; + } + } + + /** + * load a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + * @throws SmartyException if filter could not be loaded + */ + public function loadFilter($type, $name) + { + $_plugin = "smarty_{$type}filter_{$name}"; + $_filter_name = $_plugin; + if ($this->smarty->loadPlugin($_plugin)) { + if (class_exists($_plugin, false)) { + $_plugin = array($_plugin, 'execute'); + } + if (is_callable($_plugin)) { + $this->smarty->registered_filters[$type][$_filter_name] = $_plugin; + + return true; + } + } + throw new SmartyException("{$type}filter \"{$name}\" not callable"); + } + + /** + * unload a filter of specified type and name + * + * @param string $type filter type + * @param string $name filter name + * @return Smarty_Internal_Templatebase current Smarty_Internal_Templatebase (or Smarty or Smarty_Internal_Template) instance for chaining + */ + public function unloadFilter($type, $name) + { + $_filter_name = "smarty_{$type}filter_{$name}"; + if (isset($this->smarty->registered_filters[$type][$_filter_name])) { + unset ($this->smarty->registered_filters[$type][$_filter_name]); + } + + return $this; + } + + /** + * preg_replace callback to convert camelcase getter/setter to underscore property names + * + * @param string $match match string + * @return string replacemant + */ + private function replaceCamelcase($match) + { + return "_" . strtolower($match[1]); + } + + /** + * Handle unknown class methods + * + * @param string $name unknown method-name + * @param array $args argument array + */ + public function __call($name, $args) + { + static $_prefixes = array('set' => true, 'get' => true); + static $_resolved_property_name = array(); + static $_resolved_property_source = array(); + + // method of Smarty object? + if (method_exists($this->smarty, $name)) { + return call_user_func_array(array($this->smarty, $name), $args); + } + // see if this is a set/get for a property + $first3 = strtolower(substr($name, 0, 3)); + if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') { + if (isset($_resolved_property_name[$name])) { + $property_name = $_resolved_property_name[$name]; + } else { + // try to keep case correct for future PHP 6.0 case-sensitive class methods + // lcfirst() not available < PHP 5.3.0, so improvise + $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); + // convert camel case to underscored name + $property_name = preg_replace_callback('/([A-Z])/', array($this,'replaceCamelcase'), $property_name); + $_resolved_property_name[$name] = $property_name; + } + if (isset($_resolved_property_source[$property_name])) { + $_is_this = $_resolved_property_source[$property_name]; + } else { + $_is_this = null; + if (property_exists($this, $property_name)) { + $_is_this = true; + } elseif (property_exists($this->smarty, $property_name)) { + $_is_this = false; + } + $_resolved_property_source[$property_name] = $_is_this; + } + if ($_is_this) { + if ($first3 == 'get') + return $this->$property_name; + else + return $this->$property_name = $args[0]; + } elseif ($_is_this === false) { + if ($first3 == 'get') + return $this->smarty->$property_name; + else + return $this->smarty->$property_name = $args[0]; + } else { + throw new SmartyException("property '$property_name' does not exist."); + + return false; + } + } + if ($name == 'Smarty') { + throw new SmartyException("PHP5 requires you to call __construct() instead of Smarty()"); + } + // must be unknown + throw new SmartyException("Call of unknown method '$name'."); + } + +} diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index fcfb25ef..fa5de5e9 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -1,809 +1,809 @@ -nocache_hash = str_replace(array('.',','), '-', uniqid(rand(), true)); - } - - /** - * Method to compile a Smarty template - * - * @param Smarty_Internal_Template $template template object to compile - * @param bool $nocache true is shall be compiled in nocache mode - * @return bool true if compiling succeeded, false if it failed - */ - public function compileTemplate(Smarty_Internal_Template $template, $nocache = false) - { - if (empty($template->properties['nocache_hash'])) { - $template->properties['nocache_hash'] = $this->nocache_hash; - } else { - $this->nocache_hash = $template->properties['nocache_hash']; - } - // flag for nochache sections - $this->nocache = $nocache; - $this->tag_nocache = false; - // save template object in compiler class - $this->template = $template; - // reset has nocache code flag - $this->template->has_nocache_code = false; - $save_source = $this->template->source; - // template header code - $template_header = ''; - if (!$this->suppressHeader) { - $template_header .= "template->source->filepath . "\" */ ?>\n"; - } - - if (empty($this->template->source->components)) { - $this->sources = array($template->source); - } else { - // we have array of inheritance templates by extends: resource - $this->sources = array_reverse($template->source->components); - } - $loop = 0; - // the $this->sources array can get additional elements while compiling by the {extends} tag - while ($this->template->source = array_shift($this->sources)) { - $this->smarty->_current_file = $this->template->source->filepath; - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_compile($this->template); - } - $no_sources = count($this->sources); - if ($loop || $no_sources) { - $this->template->properties['file_dependency'][$this->template->source->uid] = array($this->template->source->filepath, $this->template->source->timestamp, $this->template->source->type); - } - $loop++; - if ($no_sources) { - $this->inheritance_child = true; - } else { - $this->inheritance_child = false; - } - do { - $_compiled_code = ''; - // flag for aborting current and start recompile - $this->abort_and_recompile = false; - // get template source - $_content = $this->template->source->content; - if ($_content != '') { - // run prefilter if required - if ((isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) && !$this->suppressFilter) { - $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template); - } - // call compiler - $_compiled_code = $this->doCompile($_content); - } - } while ($this->abort_and_recompile); - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_compile($this->template); - } - } - // restore source - $this->template->source = $save_source; - unset($save_source); - $this->smarty->_current_file = $this->template->source->filepath; - // free memory - unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex, $this->template); - self::$_tag_objects = array(); - // return compiled code to template object - $merged_code = ''; - if (!$this->suppressMergedTemplates && !empty($this->merged_templates)) { - foreach ($this->merged_templates as $code) { - $merged_code .= $code; - } - } - // run postfilter if required on compiled template code - if ((isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) && !$this->suppressFilter && $_compiled_code != '') { - $_compiled_code = Smarty_Internal_Filter_Handler::runFilter('post', $_compiled_code, $template); - } - if ($this->suppressTemplatePropertyHeader) { - $code = $_compiled_code . $merged_code; - } else { - $code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code; - } - // unset content because template inheritance could have replace source with parent code - unset ($template->source->content); - - return $code; - } - - /** - * Compile Tag - * - * This is a call back from the lexer/parser - * It executes the required compile plugin for the Smarty tag - * - * @param string $tag tag name - * @param array $args array with tag attributes - * @param array $parameter array with compilation parameter - * @return string compiled code - */ - public function compileTag($tag, $args, $parameter = array()) - { - // $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->get_used_tags) && $this->smarty->get_used_tags) { - $this->template->used_tags[] = array($tag, $args); - } - // check nocache option flag - if (in_array("'nocache'", $args) || in_array(array('nocache' => 'true'), $args) - || in_array(array('nocache' => '"true"'), $args) || in_array(array('nocache' => "'true'"), $args) - ) { - $this->tag_nocache = true; - } - // compile the smarty tag (required compile classes to compile the tag are autoloaded) - if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { - if (isset($this->smarty->template_functions[$tag])) { - // 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_methode'])) { - $methode = $parameter['object_methode']; - if (!in_array($methode, $this->smarty->registered_objects[$tag][3]) && - (empty($this->smarty->registered_objects[$tag][1]) || in_array($methode, $this->smarty->registered_objects[$tag][1])) - ) { - return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $methode); - } elseif (in_array($methode, $this->smarty->registered_objects[$tag][3])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); - } else { - return $this->trigger_template_error('unallowed methode "' . $methode . '" in registered object "' . $tag . '"', $this->lex->taglineno); - } - } - // 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; - } - $function = $this->smarty->registered_plugins[$plugin_type][$tag][0]; - if (!is_array($function)) { - return $function($new_args, $this); - } elseif (is_object($function[0])) { - return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this); - } else { - return call_user_func_array($function, 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->smarty->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->smarty->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->smarty->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 $mixed) { - $new_args = array_merge($new_args, $mixed); - } - $function = $this->default_handler_plugins[$plugin_type][$tag][0]; - if (!is_array($function)) { - return $function($new_args, $this); - } elseif (is_object($function[0])) { - return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this); - } else { - return call_user_func_array($function, 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_methode'])) { - $methode = $parameter['object_methode']; - if (in_array($methode, $this->smarty->registered_objects[$base_tag][3])) { - return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); - } else { - return $this->trigger_template_error('unallowed closing tag methode "' . $methode . '" in registered object "' . $base_tag . '"', $this->lex->taglineno); - } - } - // 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); - } - // block plugin? - if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { - return $this->callTagCompiler('private_block_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; - } - $function = $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0]; - if (!is_array($function)) { - return $function($args, $this); - } elseif (is_object($function[0])) { - return $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0][0]->$function[1]($args, $this); - } else { - return call_user_func_array($function, 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 . "\"", $this->lex->taglineno); - } - } - - /** - * lazy loads internal compile plugin for tag and calls the compile methode - * - * 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 compiled code - */ - public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) - { - // re-use object if already exists - if (isset(self::$_tag_objects[$tag])) { - // compile this tag - return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } - // lazy load internal compiler plugin - $class_name = 'Smarty_Internal_Compile_' . $tag; - if ($this->smarty->loadPlugin($class_name)) { - // check if tag allowed by security - if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) { - // use plugin if found - self::$_tag_objects[$tag] = new $class_name; - // compile this tag - return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } - } - // no internal compile plugin for this tag - return false; - } - - /** - * Check for plugins and return function name - * - * @param string $pugin_name name of plugin or function - * @param string $plugin_type type of plugin - * @return string call name of function - */ - public function getPlugin($plugin_name, $plugin_type) - { - $function = null; - if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { - if (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) { - $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function']; - } elseif (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) { - $this->template->required_plugins['nocache'][$plugin_name][$plugin_type] = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]; - $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function']; - } - } else { - if (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) { - $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function']; - } elseif (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) { - $this->template->required_plugins['compiled'][$plugin_name][$plugin_type] = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]; - $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function']; - } - } - if (isset($function)) { - 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->template->required_plugins['nocache'][$plugin_name][$plugin_type]['file'] = $file; - $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function'] = $function; - } else { - $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['file'] = $file; - $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function'] = $function; - } - 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; - } - - /** - * Check for plugins by default plugin handler - * - * @param string $tag name of tag - * @param string $plugin_type type of plugin - * @return boolean true if found - */ - 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) - ); - if ($result) { - $this->tag_nocache = $this->tag_nocache || !$cacheable; - if ($script !== null) { - if (is_file($script)) { - if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { - $this->template->required_plugins['nocache'][$tag][$plugin_type]['file'] = $script; - $this->template->required_plugins['nocache'][$tag][$plugin_type]['function'] = $callback; - } else { - $this->template->required_plugins['compiled'][$tag][$plugin_type]['file'] = $script; - $this->template->required_plugins['compiled'][$tag][$plugin_type]['function'] = $callback; - } - include_once $script; - } else { - $this->trigger_template_error("Default plugin handler: Returned script file \"{$script}\" for \"{$tag}\" not found"); - } - } - if (!is_string($callback) && !(is_array($callback) && is_string($callback[0]) && is_string($callback[1]))) { - $this->trigger_template_error("Default plugin handler: Returned callback for \"{$tag}\" must be a static function name or array of class and function name"); - } - if (is_callable($callback)) { - $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; - } - - /** - * Inject inline code for nocache template sections - * - * This method gets the content of each template element from the parser. - * If the content is compiled code and it should be not cached the code is injected - * into the rendered output. - * - * @param string $content content of template element - * @param boolean $is_code true if content is compiled code - * @return string content - */ - public function processNocacheCode($content, $is_code) - { - // If the template is not evaluated and we have a nocache section and or a nocache tag - if ($is_code && !empty($content)) { - // generate replacement code - if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && - ($this->nocache || $this->tag_nocache) - ) { - $this->template->has_nocache_code = true; - $_output = addcslashes($content, '\'\\'); - $_output = str_replace("^#^", "'", $_output); - $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n"; - // make sure we include modifier plugins for nocache code - foreach ($this->modifier_plugins as $plugin_name => $dummy) { - if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) { - $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier']; - } - } - } else { - $_output = $content; - } - } else { - $_output = $content; - } - $this->modifier_plugins = array(); - $this->suppressNocacheProcessing = false; - $this->tag_nocache = false; - - return $_output; - } - - /** - * push current file and line offset on stack for tracing {block} source lines - * - * @param string $file new filename - * @param string $uid uid of file - * @param string $debug false debug end_compile shall not be called - * @param int $line line offset to source - */ - public function pushTrace($file, $uid, $line, $debug = true) - { - if ($this->smarty->debugging && $debug) { - Smarty_Internal_Debug::end_compile($this->template); - } - array_push($this->trace_stack, array($this->smarty->_current_file, $this->trace_filepath, $this->trace_uid, $this->trace_line_offset)); - $this->trace_filepath = $this->smarty->_current_file = $file; - $this->trace_uid = $uid; - $this->trace_line_offset = $line ; - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_compile($this->template); - } - } - - /** - * restore file and line offset - * - */ - public function popTrace() - { - if ($this->smarty->debugging) { - Smarty_Internal_Debug::end_compile($this->template); - } - $r = array_pop($this->trace_stack); - $this->smarty->_current_file = $r[0]; - $this->trace_filepath = $r[1]; - $this->trace_uid = $r[2]; - $this->trace_line_offset = $r[3]; - if ($this->smarty->debugging) { - Smarty_Internal_Debug::start_compile($this->template); - } - } - - /** - * display compiler error messages without dying - * - * If parameter $args is empty it is a parser detected syntax error. - * In this case the parser is called to obtain information about expected tokens. - * - * If parameter $args contains a string this is used as error message - * - * @param string $args individual error message or null - * @param string $line line-number - * @throws SmartyCompilerException when an unexpected token is found - */ - public function trigger_template_error($args = null, $line = null) - { - // get template source line which has error - if (!isset($line)) { - $line = $this->lex->line; - } -// $line += $this->trace_line_offset; - $match = preg_split("/\n/", $this->lex->data); - $error_text = 'Syntax error in template "' . (empty($this->trace_filepath) ? $this->template->source->filepath : $this->trace_filepath) . '" on line ' . ($line + $this->trace_line_offset) . ' "' . trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" '; - if (isset($args)) { - // individual error message - $error_text .= $args; - } else { - // expected token from parser - $error_text .= ' - Unexpected "' . $this->lex->value . '"'; - if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) { - foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) { - $exp_token = $this->parser->yyTokenName[$token]; - if (isset($this->lex->smarty_token_names[$exp_token])) { - // token type from lexer - $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"'; - } else { - // otherwise internal token name - $expect[] = $this->parser->yyTokenName[$token]; - } - } - $error_text .= ', expected one of: ' . implode(' , ', $expect); - } - } - $e = new SmartyCompilerException($error_text); - $e->line = $line; - $e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])); - $e->desc = $args; - $e->template = $this->template->source->filepath; - throw $e; - } - -} +nocache_hash = str_replace(array('.',','), '-', uniqid(rand(), true)); + } + + /** + * Method to compile a Smarty template + * + * @param Smarty_Internal_Template $template template object to compile + * @param bool $nocache true is shall be compiled in nocache mode + * @return bool true if compiling succeeded, false if it failed + */ + public function compileTemplate(Smarty_Internal_Template $template, $nocache = false) + { + if (empty($template->properties['nocache_hash'])) { + $template->properties['nocache_hash'] = $this->nocache_hash; + } else { + $this->nocache_hash = $template->properties['nocache_hash']; + } + // flag for nochache sections + $this->nocache = $nocache; + $this->tag_nocache = false; + // save template object in compiler class + $this->template = $template; + // reset has nocache code flag + $this->template->has_nocache_code = false; + $save_source = $this->template->source; + // template header code + $template_header = ''; + if (!$this->suppressHeader) { + $template_header .= "template->source->filepath . "\" */ ?>\n"; + } + + if (empty($this->template->source->components)) { + $this->sources = array($template->source); + } else { + // we have array of inheritance templates by extends: resource + $this->sources = array_reverse($template->source->components); + } + $loop = 0; + // the $this->sources array can get additional elements while compiling by the {extends} tag + while ($this->template->source = array_shift($this->sources)) { + $this->smarty->_current_file = $this->template->source->filepath; + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_compile($this->template); + } + $no_sources = count($this->sources); + if ($loop || $no_sources) { + $this->template->properties['file_dependency'][$this->template->source->uid] = array($this->template->source->filepath, $this->template->source->timestamp, $this->template->source->type); + } + $loop++; + if ($no_sources) { + $this->inheritance_child = true; + } else { + $this->inheritance_child = false; + } + do { + $_compiled_code = ''; + // flag for aborting current and start recompile + $this->abort_and_recompile = false; + // get template source + $_content = $this->template->source->content; + if ($_content != '') { + // run prefilter if required + if ((isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) && !$this->suppressFilter) { + $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template); + } + // call compiler + $_compiled_code = $this->doCompile($_content); + } + } while ($this->abort_and_recompile); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_compile($this->template); + } + } + // restore source + $this->template->source = $save_source; + unset($save_source); + $this->smarty->_current_file = $this->template->source->filepath; + // free memory + unset($this->parser->root_buffer, $this->parser->current_buffer, $this->parser, $this->lex, $this->template); + self::$_tag_objects = array(); + // return compiled code to template object + $merged_code = ''; + if (!$this->suppressMergedTemplates && !empty($this->merged_templates)) { + foreach ($this->merged_templates as $code) { + $merged_code .= $code; + } + } + // run postfilter if required on compiled template code + if ((isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) && !$this->suppressFilter && $_compiled_code != '') { + $_compiled_code = Smarty_Internal_Filter_Handler::runFilter('post', $_compiled_code, $template); + } + if ($this->suppressTemplatePropertyHeader) { + $code = $_compiled_code . $merged_code; + } else { + $code = $template_header . $template->createTemplateCodeFrame($_compiled_code) . $merged_code; + } + // unset content because template inheritance could have replace source with parent code + unset ($template->source->content); + + return $code; + } + + /** + * Compile Tag + * + * This is a call back from the lexer/parser + * It executes the required compile plugin for the Smarty tag + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * @return string compiled code + */ + public function compileTag($tag, $args, $parameter = array()) + { + // $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->get_used_tags) && $this->smarty->get_used_tags) { + $this->template->used_tags[] = array($tag, $args); + } + // check nocache option flag + if (in_array("'nocache'", $args) || in_array(array('nocache' => 'true'), $args) + || in_array(array('nocache' => '"true"'), $args) || in_array(array('nocache' => "'true'"), $args) + ) { + $this->tag_nocache = true; + } + // compile the smarty tag (required compile classes to compile the tag are autoloaded) + if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { + if (isset($this->smarty->template_functions[$tag])) { + // 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_methode'])) { + $methode = $parameter['object_methode']; + if (!in_array($methode, $this->smarty->registered_objects[$tag][3]) && + (empty($this->smarty->registered_objects[$tag][1]) || in_array($methode, $this->smarty->registered_objects[$tag][1])) + ) { + return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $methode); + } elseif (in_array($methode, $this->smarty->registered_objects[$tag][3])) { + return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); + } else { + return $this->trigger_template_error('unallowed methode "' . $methode . '" in registered object "' . $tag . '"', $this->lex->taglineno); + } + } + // 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; + } + $function = $this->smarty->registered_plugins[$plugin_type][$tag][0]; + if (!is_array($function)) { + return $function($new_args, $this); + } elseif (is_object($function[0])) { + return $this->smarty->registered_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this); + } else { + return call_user_func_array($function, 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->smarty->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->smarty->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->smarty->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 $mixed) { + $new_args = array_merge($new_args, $mixed); + } + $function = $this->default_handler_plugins[$plugin_type][$tag][0]; + if (!is_array($function)) { + return $function($new_args, $this); + } elseif (is_object($function[0])) { + return $this->default_handler_plugins[$plugin_type][$tag][0][0]->$function[1]($new_args, $this); + } else { + return call_user_func_array($function, 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_methode'])) { + $methode = $parameter['object_methode']; + if (in_array($methode, $this->smarty->registered_objects[$base_tag][3])) { + return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); + } else { + return $this->trigger_template_error('unallowed closing tag methode "' . $methode . '" in registered object "' . $base_tag . '"', $this->lex->taglineno); + } + } + // 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); + } + // block plugin? + if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { + return $this->callTagCompiler('private_block_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; + } + $function = $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0]; + if (!is_array($function)) { + return $function($args, $this); + } elseif (is_object($function[0])) { + return $this->smarty->registered_plugins[Smarty::PLUGIN_COMPILER][$tag][0][0]->$function[1]($args, $this); + } else { + return call_user_func_array($function, 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 . "\"", $this->lex->taglineno); + } + } + + /** + * lazy loads internal compile plugin for tag and calls the compile methode + * + * 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 compiled code + */ + public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) + { + // re-use object if already exists + if (isset(self::$_tag_objects[$tag])) { + // compile this tag + return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); + } + // lazy load internal compiler plugin + $class_name = 'Smarty_Internal_Compile_' . $tag; + if ($this->smarty->loadPlugin($class_name)) { + // check if tag allowed by security + if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) { + // use plugin if found + self::$_tag_objects[$tag] = new $class_name; + // compile this tag + return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); + } + } + // no internal compile plugin for this tag + return false; + } + + /** + * Check for plugins and return function name + * + * @param string $pugin_name name of plugin or function + * @param string $plugin_type type of plugin + * @return string call name of function + */ + public function getPlugin($plugin_name, $plugin_type) + { + $function = null; + if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { + if (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) { + $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function']; + } elseif (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) { + $this->template->required_plugins['nocache'][$plugin_name][$plugin_type] = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]; + $function = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function']; + } + } else { + if (isset($this->template->required_plugins['compiled'][$plugin_name][$plugin_type])) { + $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function']; + } elseif (isset($this->template->required_plugins['nocache'][$plugin_name][$plugin_type])) { + $this->template->required_plugins['compiled'][$plugin_name][$plugin_type] = $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]; + $function = $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function']; + } + } + if (isset($function)) { + 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->template->required_plugins['nocache'][$plugin_name][$plugin_type]['file'] = $file; + $this->template->required_plugins['nocache'][$plugin_name][$plugin_type]['function'] = $function; + } else { + $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['file'] = $file; + $this->template->required_plugins['compiled'][$plugin_name][$plugin_type]['function'] = $function; + } + 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; + } + + /** + * Check for plugins by default plugin handler + * + * @param string $tag name of tag + * @param string $plugin_type type of plugin + * @return boolean true if found + */ + 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) + ); + if ($result) { + $this->tag_nocache = $this->tag_nocache || !$cacheable; + if ($script !== null) { + if (is_file($script)) { + if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { + $this->template->required_plugins['nocache'][$tag][$plugin_type]['file'] = $script; + $this->template->required_plugins['nocache'][$tag][$plugin_type]['function'] = $callback; + } else { + $this->template->required_plugins['compiled'][$tag][$plugin_type]['file'] = $script; + $this->template->required_plugins['compiled'][$tag][$plugin_type]['function'] = $callback; + } + include_once $script; + } else { + $this->trigger_template_error("Default plugin handler: Returned script file \"{$script}\" for \"{$tag}\" not found"); + } + } + if (!is_string($callback) && !(is_array($callback) && is_string($callback[0]) && is_string($callback[1]))) { + $this->trigger_template_error("Default plugin handler: Returned callback for \"{$tag}\" must be a static function name or array of class and function name"); + } + if (is_callable($callback)) { + $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; + } + + /** + * Inject inline code for nocache template sections + * + * This method gets the content of each template element from the parser. + * If the content is compiled code and it should be not cached the code is injected + * into the rendered output. + * + * @param string $content content of template element + * @param boolean $is_code true if content is compiled code + * @return string content + */ + public function processNocacheCode($content, $is_code) + { + // If the template is not evaluated and we have a nocache section and or a nocache tag + if ($is_code && !empty($content)) { + // generate replacement code + if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && !$this->suppressNocacheProcessing && + ($this->nocache || $this->tag_nocache) + ) { + $this->template->has_nocache_code = true; + $_output = addcslashes($content, '\'\\'); + $_output = str_replace("^#^", "'", $_output); + $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>\n"; + // make sure we include modifier plugins for nocache code + foreach ($this->modifier_plugins as $plugin_name => $dummy) { + if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) { + $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier']; + } + } + } else { + $_output = $content; + } + } else { + $_output = $content; + } + $this->modifier_plugins = array(); + $this->suppressNocacheProcessing = false; + $this->tag_nocache = false; + + return $_output; + } + + /** + * push current file and line offset on stack for tracing {block} source lines + * + * @param string $file new filename + * @param string $uid uid of file + * @param string $debug false debug end_compile shall not be called + * @param int $line line offset to source + */ + public function pushTrace($file, $uid, $line, $debug = true) + { + if ($this->smarty->debugging && $debug) { + Smarty_Internal_Debug::end_compile($this->template); + } + array_push($this->trace_stack, array($this->smarty->_current_file, $this->trace_filepath, $this->trace_uid, $this->trace_line_offset)); + $this->trace_filepath = $this->smarty->_current_file = $file; + $this->trace_uid = $uid; + $this->trace_line_offset = $line ; + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_compile($this->template); + } + } + + /** + * restore file and line offset + * + */ + public function popTrace() + { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_compile($this->template); + } + $r = array_pop($this->trace_stack); + $this->smarty->_current_file = $r[0]; + $this->trace_filepath = $r[1]; + $this->trace_uid = $r[2]; + $this->trace_line_offset = $r[3]; + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_compile($this->template); + } + } + + /** + * display compiler error messages without dying + * + * If parameter $args is empty it is a parser detected syntax error. + * In this case the parser is called to obtain information about expected tokens. + * + * If parameter $args contains a string this is used as error message + * + * @param string $args individual error message or null + * @param string $line line-number + * @throws SmartyCompilerException when an unexpected token is found + */ + public function trigger_template_error($args = null, $line = null) + { + // get template source line which has error + if (!isset($line)) { + $line = $this->lex->line; + } +// $line += $this->trace_line_offset; + $match = preg_split("/\n/", $this->lex->data); + $error_text = 'Syntax error in template "' . (empty($this->trace_filepath) ? $this->template->source->filepath : $this->trace_filepath) . '" on line ' . ($line + $this->trace_line_offset) . ' "' . trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])) . '" '; + if (isset($args)) { + // individual error message + $error_text .= $args; + } else { + // expected token from parser + $error_text .= ' - Unexpected "' . $this->lex->value . '"'; + if (count($this->parser->yy_get_expected_tokens($this->parser->yymajor)) <= 4) { + foreach ($this->parser->yy_get_expected_tokens($this->parser->yymajor) as $token) { + $exp_token = $this->parser->yyTokenName[$token]; + if (isset($this->lex->smarty_token_names[$exp_token])) { + // token type from lexer + $expect[] = '"' . $this->lex->smarty_token_names[$exp_token] . '"'; + } else { + // otherwise internal token name + $expect[] = $this->parser->yyTokenName[$token]; + } + } + $error_text .= ', expected one of: ' . implode(' , ', $expect); + } + } + $e = new SmartyCompilerException($error_text); + $e->line = $line; + $e->source = trim(preg_replace('![\t\r\n]+!', ' ', $match[$line - 1])); + $e->desc = $args; + $e->template = $this->template->source->filepath; + throw $e; + } + +} diff --git a/libs/sysplugins/smarty_internal_utility.php b/libs/sysplugins/smarty_internal_utility.php index 5bd881cb..82f200df 100644 --- a/libs/sysplugins/smarty_internal_utility.php +++ b/libs/sysplugins/smarty_internal_utility.php @@ -1,823 +1,823 @@ - - * @author Uwe Tews - * @package Smarty - * @subpackage PluginsInternal - * @version 3-SVN$Rev: 3286 $ - */ - -/** - * Utility class - * - * @package Smarty - * @subpackage Security - */ -class Smarty_Internal_Utility -{ - /** - * private constructor to prevent calls creation of new instances - */ - final private function __construct() - { - // intentionally left blank - } - - /** - * Compile all template files - * - * @param string $extension template file name extension - * @param bool $force_compile force all to recompile - * @param int $time_limit set maximum execution time - * @param int $max_errors set maximum allowed errors - * @param Smarty $smarty Smarty instance - * @return integer number of template files compiled - */ - public static function compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) - { - // switch off time limit - if (function_exists('set_time_limit')) { - @set_time_limit($time_limit); - } - $smarty->force_compile = $force_compile; - $_count = 0; - $_error_count = 0; - // loop over array of template directories - foreach ($smarty->getTemplateDir() as $_dir) { - $_compileDirs = new RecursiveDirectoryIterator($_dir); - $_compile = new RecursiveIteratorIterator($_compileDirs); - foreach ($_compile as $_fileinfo) { - $_file = $_fileinfo->getFilename(); - if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; - if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; - if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { - $_template_file = $_file; - } else { - $_template_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; - } - echo '
', $_dir, '---', $_template_file; - flush(); - $_start_time = microtime(true); - try { - $_tpl = $smarty->createTemplate($_template_file,null,null,null,false); - if ($_tpl->mustCompile()) { - $_tpl->compileTemplateSource(); - $_count++; - echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; - flush(); - } else { - echo ' is up to date'; - flush(); - } - } catch (Exception $e) { - echo 'Error: ', $e->getMessage(), "

"; - $_error_count++; - } - // free memory - $smarty->template_objects = array(); - $_tpl->smarty->template_objects = array(); - $_tpl = null; - if ($max_errors !== null && $_error_count == $max_errors) { - echo '

too many errors'; - exit(); - } - } - } - - return $_count; - } - - /** - * Compile all config files - * - * @param string $extension config file name extension - * @param bool $force_compile force all to recompile - * @param int $time_limit set maximum execution time - * @param int $max_errors set maximum allowed errors - * @param Smarty $smarty Smarty instance - * @return integer number of config files compiled - */ - public static function compileAllConfig($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) - { - // switch off time limit - if (function_exists('set_time_limit')) { - @set_time_limit($time_limit); - } - $smarty->force_compile = $force_compile; - $_count = 0; - $_error_count = 0; - // loop over array of template directories - foreach ($smarty->getConfigDir() as $_dir) { - $_compileDirs = new RecursiveDirectoryIterator($_dir); - $_compile = new RecursiveIteratorIterator($_compileDirs); - foreach ($_compile as $_fileinfo) { - $_file = $_fileinfo->getFilename(); - if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; - if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; - if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { - $_config_file = $_file; - } else { - $_config_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; - } - echo '
', $_dir, '---', $_config_file; - flush(); - $_start_time = microtime(true); - try { - $_config = new Smarty_Internal_Config($_config_file, $smarty); - if ($_config->mustCompile()) { - $_config->compileConfigSource(); - $_count++; - echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; - flush(); - } else { - echo ' is up to date'; - flush(); - } - } catch (Exception $e) { - echo 'Error: ', $e->getMessage(), "

"; - $_error_count++; - } - if ($max_errors !== null && $_error_count == $max_errors) { - echo '

too many errors'; - exit(); - } - } - } - - return $_count; - } - - /** - * Delete compiled template file - * - * @param string $resource_name template name - * @param string $compile_id compile id - * @param integer $exp_time expiration time - * @param Smarty $smarty Smarty instance - * @return integer number of template files deleted - */ - public static function clearCompiledTemplate($resource_name, $compile_id, $exp_time, Smarty $smarty) - { - $_compile_dir = realpath($smarty->getCompileDir()).'/'; - $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; - $_dir_sep = $smarty->use_sub_dirs ? DS : '^'; - if (isset($resource_name)) { - $_save_stat = $smarty->caching; - $smarty->caching = false; - $tpl = new $smarty->template_class($resource_name, $smarty); - $smarty->caching = $_save_stat; - - // remove from template cache - $tpl->source; // have the template registered before unset() - if ($smarty->allow_ambiguous_resources) { - $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; - } else { - $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; - } - if (isset($_templateId[150])) { - $_templateId = sha1($_templateId); - } - unset($smarty->template_objects[$_templateId]); - - if ($tpl->source->exists) { - $_resource_part_1 = basename(str_replace('^', '/', $tpl->compiled->filepath)); - $_resource_part_1_length = strlen($_resource_part_1); - } else { - return 0; - } - - $_resource_part_2 = str_replace('.php','.cache.php',$_resource_part_1); - $_resource_part_2_length = strlen($_resource_part_2); - } - $_dir = $_compile_dir; - if ($smarty->use_sub_dirs && isset($_compile_id)) { - $_dir .= $_compile_id . $_dir_sep; - } - if (isset($_compile_id)) { - $_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep; - $_compile_id_part_length = strlen($_compile_id_part); - } - $_count = 0; - try { - $_compileDirs = new RecursiveDirectoryIterator($_dir); - // NOTE: UnexpectedValueException thrown for PHP >= 5.3 - } catch (Exception $e) { - return 0; - } - $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); - foreach ($_compile as $_file) { - if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) - continue; - - $_filepath = (string) $_file; - - if ($_file->isDir()) { - if (!$_compile->isDot()) { - // delete folder if empty - @rmdir($_file->getPathname()); - } - } else { - $unlink = false; - if ((!isset($_compile_id) || (isset($_filepath[$_compile_id_part_length]) && !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) - && (!isset($resource_name) - || (isset($_filepath[$_resource_part_1_length]) - && substr_compare($_filepath, $_resource_part_1, -$_resource_part_1_length, $_resource_part_1_length) == 0) - || (isset($_filepath[$_resource_part_2_length]) - && substr_compare($_filepath, $_resource_part_2, -$_resource_part_2_length, $_resource_part_2_length) == 0))) { - if (isset($exp_time)) { - if (time() - @filemtime($_filepath) >= $exp_time) { - $unlink = true; - } - } else { - $unlink = true; - } - } - - if ($unlink && @unlink($_filepath)) { - $_count++; - } - } - } - // clear compiled cache - Smarty_Resource::$sources = array(); - Smarty_Resource::$compileds = array(); - - return $_count; - } - - /** - * Return array of tag/attributes of all tags used by an template - * - * @param Smarty_Internal_Template $templae template object - * @return array of tag/attributes - */ - public static function getTags(Smarty_Internal_Template $template) - { - $template->smarty->get_used_tags = true; - $template->compileTemplateSource(); - - return $template->used_tags; - } - - /** - * diagnose Smarty setup - * - * If $errors is secified, the diagnostic report will be appended to the array, rather than being output. - * - * @param Smarty $smarty Smarty instance to test - * @param array $errors array to push results into rather than outputting them - * @return bool status, true if everything is fine, false else - */ - public static function testInstall(Smarty $smarty, &$errors=null) - { - $status = true; - - if ($errors === null) { - echo "
\n";
-            echo "Smarty Installation test...\n";
-            echo "Testing template directory...\n";
-        }
-
-        $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
-
-        // test if all registered template_dir are accessible
-        foreach ($smarty->getTemplateDir() as $template_dir) {
-            $_template_dir = $template_dir;
-            $template_dir = realpath($template_dir);
-            // resolve include_path or fail existence
-            if (!$template_dir) {
-                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
-                    // try PHP include_path
-                    if ($_stream_resolve_include_path) {
-                        $template_dir = stream_resolve_include_path($_template_dir);
-                    } else {
-                        $template_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_template_dir);
-                    }
-
-                    if ($template_dir !== false) {
-                        if ($errors === null) {
-                            echo "$template_dir is OK.\n";
-                        }
-
-                        continue;
-                    } else {
-                        $status = false;
-                        $message = "FAILED: $_template_dir does not exist (and couldn't be found in include_path either)";
-                        if ($errors === null) {
-                            echo $message . ".\n";
-                        } else {
-                            $errors['template_dir'] = $message;
-                        }
-
-                        continue;
-                    }
-                } else {
-                    $status = false;
-                    $message = "FAILED: $_template_dir does not exist";
-                    if ($errors === null) {
-                        echo $message . ".\n";
-                    } else {
-                        $errors['template_dir'] = $message;
-                    }
-
-                    continue;
-                }
-            }
-
-            if (!is_dir($template_dir)) {
-                $status = false;
-                $message = "FAILED: $template_dir is not a directory";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['template_dir'] = $message;
-                }
-            } elseif (!is_readable($template_dir)) {
-                $status = false;
-                $message = "FAILED: $template_dir is not readable";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['template_dir'] = $message;
-                }
-            } else {
-                if ($errors === null) {
-                    echo "$template_dir is OK.\n";
-                }
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing compile directory...\n";
-        }
-
-        // test if registered compile_dir is accessible
-        $__compile_dir = $smarty->getCompileDir();
-        $_compile_dir = realpath($__compile_dir);
-        if (!$_compile_dir) {
-            $status = false;
-            $message = "FAILED: {$__compile_dir} does not exist";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['compile_dir'] = $message;
-            }
-        } elseif (!is_dir($_compile_dir)) {
-            $status = false;
-            $message = "FAILED: {$_compile_dir} is not a directory";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['compile_dir'] = $message;
-            }
-        } elseif (!is_readable($_compile_dir)) {
-            $status = false;
-            $message = "FAILED: {$_compile_dir} is not readable";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['compile_dir'] = $message;
-            }
-        } elseif (!is_writable($_compile_dir)) {
-            $status = false;
-            $message = "FAILED: {$_compile_dir} is not writable";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['compile_dir'] = $message;
-            }
-        } else {
-            if ($errors === null) {
-                echo "{$_compile_dir} is OK.\n";
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing plugins directory...\n";
-        }
-
-        // test if all registered plugins_dir are accessible
-        // and if core plugins directory is still registered
-        $_core_plugins_dir = realpath(dirname(__FILE__) .'/../plugins');
-        $_core_plugins_available = false;
-        foreach ($smarty->getPluginsDir() as $plugin_dir) {
-            $_plugin_dir = $plugin_dir;
-            $plugin_dir = realpath($plugin_dir);
-            // resolve include_path or fail existence
-            if (!$plugin_dir) {
-                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
-                    // try PHP include_path
-                    if ($_stream_resolve_include_path) {
-                        $plugin_dir = stream_resolve_include_path($_plugin_dir);
-                    } else {
-                        $plugin_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_plugin_dir);
-                    }
-
-                    if ($plugin_dir !== false) {
-                        if ($errors === null) {
-                            echo "$plugin_dir is OK.\n";
-                        }
-
-                        continue;
-                    } else {
-                        $status = false;
-                        $message = "FAILED: $_plugin_dir does not exist (and couldn't be found in include_path either)";
-                        if ($errors === null) {
-                            echo $message . ".\n";
-                        } else {
-                            $errors['plugins_dir'] = $message;
-                        }
-
-                        continue;
-                    }
-                } else {
-                    $status = false;
-                    $message = "FAILED: $_plugin_dir does not exist";
-                    if ($errors === null) {
-                        echo $message . ".\n";
-                    } else {
-                        $errors['plugins_dir'] = $message;
-                    }
-
-                    continue;
-                }
-            }
-
-            if (!is_dir($plugin_dir)) {
-                $status = false;
-                $message = "FAILED: $plugin_dir is not a directory";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['plugins_dir'] = $message;
-                }
-            } elseif (!is_readable($plugin_dir)) {
-                $status = false;
-                $message = "FAILED: $plugin_dir is not readable";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['plugins_dir'] = $message;
-                }
-            } elseif ($_core_plugins_dir && $_core_plugins_dir == realpath($plugin_dir)) {
-                $_core_plugins_available = true;
-                if ($errors === null) {
-                    echo "$plugin_dir is OK.\n";
-                }
-            } else {
-                if ($errors === null) {
-                    echo "$plugin_dir is OK.\n";
-                }
-            }
-        }
-        if (!$_core_plugins_available) {
-            $status = false;
-            $message = "WARNING: Smarty's own libs/plugins is not available";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } elseif (!isset($errors['plugins_dir'])) {
-                $errors['plugins_dir'] = $message;
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing cache directory...\n";
-        }
-
-        // test if all registered cache_dir is accessible
-        $__cache_dir = $smarty->getCacheDir();
-        $_cache_dir = realpath($__cache_dir);
-        if (!$_cache_dir) {
-            $status = false;
-            $message = "FAILED: {$__cache_dir} does not exist";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['cache_dir'] = $message;
-            }
-        } elseif (!is_dir($_cache_dir)) {
-            $status = false;
-            $message = "FAILED: {$_cache_dir} is not a directory";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['cache_dir'] = $message;
-            }
-        } elseif (!is_readable($_cache_dir)) {
-            $status = false;
-            $message = "FAILED: {$_cache_dir} is not readable";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['cache_dir'] = $message;
-            }
-        } elseif (!is_writable($_cache_dir)) {
-            $status = false;
-            $message = "FAILED: {$_cache_dir} is not writable";
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['cache_dir'] = $message;
-            }
-        } else {
-            if ($errors === null) {
-                echo "{$_cache_dir} is OK.\n";
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing configs directory...\n";
-        }
-
-        // test if all registered config_dir are accessible
-        foreach ($smarty->getConfigDir() as $config_dir) {
-            $_config_dir = $config_dir;
-            $config_dir = realpath($config_dir);
-            // resolve include_path or fail existence
-            if (!$config_dir) {
-                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) {
-                    // try PHP include_path
-                    if ($_stream_resolve_include_path) {
-                        $config_dir = stream_resolve_include_path($_config_dir);
-                    } else {
-                        $config_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_config_dir);
-                    }
-
-                    if ($config_dir !== false) {
-                        if ($errors === null) {
-                            echo "$config_dir is OK.\n";
-                        }
-
-                        continue;
-                    } else {
-                        $status = false;
-                        $message = "FAILED: $_config_dir does not exist (and couldn't be found in include_path either)";
-                        if ($errors === null) {
-                            echo $message . ".\n";
-                        } else {
-                            $errors['config_dir'] = $message;
-                        }
-
-                        continue;
-                    }
-                } else {
-                    $status = false;
-                    $message = "FAILED: $_config_dir does not exist";
-                    if ($errors === null) {
-                        echo $message . ".\n";
-                    } else {
-                        $errors['config_dir'] = $message;
-                    }
-
-                    continue;
-                }
-            }
-
-            if (!is_dir($config_dir)) {
-                $status = false;
-                $message = "FAILED: $config_dir is not a directory";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['config_dir'] = $message;
-                }
-            } elseif (!is_readable($config_dir)) {
-                $status = false;
-                $message = "FAILED: $config_dir is not readable";
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['config_dir'] = $message;
-                }
-            } else {
-                if ($errors === null) {
-                    echo "$config_dir is OK.\n";
-                }
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing sysplugin files...\n";
-        }
-        // test if sysplugins are available
-        $source = SMARTY_SYSPLUGINS_DIR;
-        if (is_dir($source)) {
-            $expected = array(
-                "smarty_cacheresource.php" => true,
-                "smarty_cacheresource_custom.php" => true,
-                "smarty_cacheresource_keyvaluestore.php" => true,
-                "smarty_config_source.php" => true,
-                "smarty_internal_cacheresource_file.php" => true,
-                "smarty_internal_compile_append.php" => true,
-                "smarty_internal_compile_assign.php" => true,
-                "smarty_internal_compile_block.php" => true,
-                "smarty_internal_compile_break.php" => true,
-                "smarty_internal_compile_call.php" => true,
-                "smarty_internal_compile_capture.php" => true,
-                "smarty_internal_compile_config_load.php" => true,
-                "smarty_internal_compile_continue.php" => true,
-                "smarty_internal_compile_debug.php" => true,
-                "smarty_internal_compile_eval.php" => true,
-                "smarty_internal_compile_extends.php" => true,
-                "smarty_internal_compile_for.php" => true,
-                "smarty_internal_compile_foreach.php" => true,
-                "smarty_internal_compile_function.php" => true,
-                "smarty_internal_compile_if.php" => true,
-                "smarty_internal_compile_include.php" => true,
-                "smarty_internal_compile_include_php.php" => true,
-                "smarty_internal_compile_insert.php" => true,
-                "smarty_internal_compile_ldelim.php" => true,
-                "smarty_internal_compile_nocache.php" => true,
-                "smarty_internal_compile_private_block_plugin.php" => true,
-                "smarty_internal_compile_private_function_plugin.php" => true,
-                "smarty_internal_compile_private_modifier.php" => true,
-                "smarty_internal_compile_private_object_block_function.php" => true,
-                "smarty_internal_compile_private_object_function.php" => true,
-                "smarty_internal_compile_private_print_expression.php" => true,
-                "smarty_internal_compile_private_registered_block.php" => true,
-                "smarty_internal_compile_private_registered_function.php" => true,
-                "smarty_internal_compile_private_special_variable.php" => true,
-                "smarty_internal_compile_rdelim.php" => true,
-                "smarty_internal_compile_section.php" => true,
-                "smarty_internal_compile_setfilter.php" => true,
-                "smarty_internal_compile_while.php" => true,
-                "smarty_internal_compilebase.php" => true,
-                "smarty_internal_config.php" => true,
-                "smarty_internal_config_file_compiler.php" => true,
-                "smarty_internal_configfilelexer.php" => true,
-                "smarty_internal_configfileparser.php" => true,
-                "smarty_internal_data.php" => true,
-                "smarty_internal_debug.php" => true,
-                "smarty_internal_filter_handler.php" => true,
-                "smarty_internal_function_call_handler.php" => true,
-                "smarty_internal_get_include_path.php" => true,
-                "smarty_internal_nocache_insert.php" => true,
-                "smarty_internal_parsetree.php" => true,
-                "smarty_internal_resource_eval.php" => true,
-                "smarty_internal_resource_extends.php" => true,
-                "smarty_internal_resource_file.php" => true,
-                "smarty_internal_resource_registered.php" => true,
-                "smarty_internal_resource_stream.php" => true,
-                "smarty_internal_resource_string.php" => true,
-                "smarty_internal_smartytemplatecompiler.php" => true,
-                "smarty_internal_template.php" => true,
-                "smarty_internal_templatebase.php" => true,
-                "smarty_internal_templatecompilerbase.php" => true,
-                "smarty_internal_templatelexer.php" => true,
-                "smarty_internal_templateparser.php" => true,
-                "smarty_internal_utility.php" => true,
-                "smarty_internal_write_file.php" => true,
-                "smarty_resource.php" => true,
-                "smarty_resource_custom.php" => true,
-                "smarty_resource_recompiled.php" => true,
-                "smarty_resource_uncompiled.php" => true,
-                "smarty_security.php" => true,
-            );
-            $iterator = new DirectoryIterator($source);
-            foreach ($iterator as $file) {
-                if (!$file->isDot()) {
-                    $filename = $file->getFilename();
-                    if (isset($expected[$filename])) {
-                        unset($expected[$filename]);
-                    }
-                }
-            }
-            if ($expected) {
-                $status = false;
-                $message = "FAILED: files missing from libs/sysplugins: ". join(', ', array_keys($expected));
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['sysplugins'] = $message;
-                }
-            } elseif ($errors === null) {
-                echo "... OK\n";
-            }
-        } else {
-            $status = false;
-            $message = "FAILED: ". SMARTY_SYSPLUGINS_DIR .' is not a directory';
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['sysplugins_dir_constant'] = $message;
-            }
-        }
-
-        if ($errors === null) {
-            echo "Testing plugin files...\n";
-        }
-        // test if core plugins are available
-        $source = SMARTY_PLUGINS_DIR;
-        if (is_dir($source)) {
-            $expected = array(
-                "block.textformat.php" => true,
-                "function.counter.php" => true,
-                "function.cycle.php" => true,
-                "function.fetch.php" => true,
-                "function.html_checkboxes.php" => true,
-                "function.html_image.php" => true,
-                "function.html_options.php" => true,
-                "function.html_radios.php" => true,
-                "function.html_select_date.php" => true,
-                "function.html_select_time.php" => true,
-                "function.html_table.php" => true,
-                "function.mailto.php" => true,
-                "function.math.php" => true,
-                "modifier.capitalize.php" => true,
-                "modifier.date_format.php" => true,
-                "modifier.debug_print_var.php" => true,
-                "modifier.escape.php" => true,
-                "modifier.regex_replace.php" => true,
-                "modifier.replace.php" => true,
-                "modifier.spacify.php" => true,
-                "modifier.truncate.php" => true,
-                "modifiercompiler.cat.php" => true,
-                "modifiercompiler.count_characters.php" => true,
-                "modifiercompiler.count_paragraphs.php" => true,
-                "modifiercompiler.count_sentences.php" => true,
-                "modifiercompiler.count_words.php" => true,
-                "modifiercompiler.default.php" => true,
-                "modifiercompiler.escape.php" => true,
-                "modifiercompiler.from_charset.php" => true,
-                "modifiercompiler.indent.php" => true,
-                "modifiercompiler.lower.php" => true,
-                "modifiercompiler.noprint.php" => true,
-                "modifiercompiler.string_format.php" => true,
-                "modifiercompiler.strip.php" => true,
-                "modifiercompiler.strip_tags.php" => true,
-                "modifiercompiler.to_charset.php" => true,
-                "modifiercompiler.unescape.php" => true,
-                "modifiercompiler.upper.php" => true,
-                "modifiercompiler.wordwrap.php" => true,
-                "outputfilter.trimwhitespace.php" => true,
-                "shared.escape_special_chars.php" => true,
-                "shared.literal_compiler_param.php" => true,
-                "shared.make_timestamp.php" => true,
-                "shared.mb_str_replace.php" => true,
-                "shared.mb_unicode.php" => true,
-                "shared.mb_wordwrap.php" => true,
-                "variablefilter.htmlspecialchars.php" => true,
-            );
-            $iterator = new DirectoryIterator($source);
-            foreach ($iterator as $file) {
-                if (!$file->isDot()) {
-                    $filename = $file->getFilename();
-                    if (isset($expected[$filename])) {
-                        unset($expected[$filename]);
-                    }
-                }
-            }
-            if ($expected) {
-                $status = false;
-                $message = "FAILED: files missing from libs/plugins: ". join(', ', array_keys($expected));
-                if ($errors === null) {
-                    echo $message . ".\n";
-                } else {
-                    $errors['plugins'] = $message;
-                }
-            } elseif ($errors === null) {
-                echo "... OK\n";
-            }
-        } else {
-            $status = false;
-            $message = "FAILED: ". SMARTY_PLUGINS_DIR .' is not a directory';
-            if ($errors === null) {
-                echo $message . ".\n";
-            } else {
-                $errors['plugins_dir_constant'] = $message;
-            }
-        }
-
-        if ($errors === null) {
-            echo "Tests complete.\n";
-            echo "
\n"; - } - - return $status; - } - -} + + * @author Uwe Tews + * @package Smarty + * @subpackage PluginsInternal + * @version 3-SVN$Rev: 3286 $ + */ + +/** + * Utility class + * + * @package Smarty + * @subpackage Security + */ +class Smarty_Internal_Utility +{ + /** + * private constructor to prevent calls creation of new instances + */ + final private function __construct() + { + // intentionally left blank + } + + /** + * Compile all template files + * + * @param string $extension template file name extension + * @param bool $force_compile force all to recompile + * @param int $time_limit set maximum execution time + * @param int $max_errors set maximum allowed errors + * @param Smarty $smarty Smarty instance + * @return integer number of template files compiled + */ + public static function compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) + { + // switch off time limit + if (function_exists('set_time_limit')) { + @set_time_limit($time_limit); + } + $smarty->force_compile = $force_compile; + $_count = 0; + $_error_count = 0; + // loop over array of template directories + foreach ($smarty->getTemplateDir() as $_dir) { + $_compileDirs = new RecursiveDirectoryIterator($_dir); + $_compile = new RecursiveIteratorIterator($_compileDirs); + foreach ($_compile as $_fileinfo) { + $_file = $_fileinfo->getFilename(); + if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; + if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; + if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { + $_template_file = $_file; + } else { + $_template_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; + } + echo '
', $_dir, '---', $_template_file; + flush(); + $_start_time = microtime(true); + try { + $_tpl = $smarty->createTemplate($_template_file,null,null,null,false); + if ($_tpl->mustCompile()) { + $_tpl->compileTemplateSource(); + $_count++; + echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; + flush(); + } else { + echo ' is up to date'; + flush(); + } + } catch (Exception $e) { + echo 'Error: ', $e->getMessage(), "

"; + $_error_count++; + } + // free memory + $smarty->template_objects = array(); + $_tpl->smarty->template_objects = array(); + $_tpl = null; + if ($max_errors !== null && $_error_count == $max_errors) { + echo '

too many errors'; + exit(); + } + } + } + + return $_count; + } + + /** + * Compile all config files + * + * @param string $extension config file name extension + * @param bool $force_compile force all to recompile + * @param int $time_limit set maximum execution time + * @param int $max_errors set maximum allowed errors + * @param Smarty $smarty Smarty instance + * @return integer number of config files compiled + */ + public static function compileAllConfig($extension, $force_compile, $time_limit, $max_errors, Smarty $smarty) + { + // switch off time limit + if (function_exists('set_time_limit')) { + @set_time_limit($time_limit); + } + $smarty->force_compile = $force_compile; + $_count = 0; + $_error_count = 0; + // loop over array of template directories + foreach ($smarty->getConfigDir() as $_dir) { + $_compileDirs = new RecursiveDirectoryIterator($_dir); + $_compile = new RecursiveIteratorIterator($_compileDirs); + foreach ($_compile as $_fileinfo) { + $_file = $_fileinfo->getFilename(); + if (substr(basename($_fileinfo->getPathname()),0,1) == '.' || strpos($_file, '.svn') !== false) continue; + if (!substr_compare($_file, $extension, - strlen($extension)) == 0) continue; + if ($_fileinfo->getPath() == substr($_dir, 0, -1)) { + $_config_file = $_file; + } else { + $_config_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; + } + echo '
', $_dir, '---', $_config_file; + flush(); + $_start_time = microtime(true); + try { + $_config = new Smarty_Internal_Config($_config_file, $smarty); + if ($_config->mustCompile()) { + $_config->compileConfigSource(); + $_count++; + echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; + flush(); + } else { + echo ' is up to date'; + flush(); + } + } catch (Exception $e) { + echo 'Error: ', $e->getMessage(), "

"; + $_error_count++; + } + if ($max_errors !== null && $_error_count == $max_errors) { + echo '

too many errors'; + exit(); + } + } + } + + return $_count; + } + + /** + * Delete compiled template file + * + * @param string $resource_name template name + * @param string $compile_id compile id + * @param integer $exp_time expiration time + * @param Smarty $smarty Smarty instance + * @return integer number of template files deleted + */ + public static function clearCompiledTemplate($resource_name, $compile_id, $exp_time, Smarty $smarty) + { + $_compile_dir = realpath($smarty->getCompileDir()).'/'; + $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; + $_dir_sep = $smarty->use_sub_dirs ? DS : '^'; + if (isset($resource_name)) { + $_save_stat = $smarty->caching; + $smarty->caching = false; + $tpl = new $smarty->template_class($resource_name, $smarty); + $smarty->caching = $_save_stat; + + // remove from template cache + $tpl->source; // have the template registered before unset() + if ($smarty->allow_ambiguous_resources) { + $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; + } else { + $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; + } + if (isset($_templateId[150])) { + $_templateId = sha1($_templateId); + } + unset($smarty->template_objects[$_templateId]); + + if ($tpl->source->exists) { + $_resource_part_1 = basename(str_replace('^', '/', $tpl->compiled->filepath)); + $_resource_part_1_length = strlen($_resource_part_1); + } else { + return 0; + } + + $_resource_part_2 = str_replace('.php','.cache.php',$_resource_part_1); + $_resource_part_2_length = strlen($_resource_part_2); + } + $_dir = $_compile_dir; + if ($smarty->use_sub_dirs && isset($_compile_id)) { + $_dir .= $_compile_id . $_dir_sep; + } + if (isset($_compile_id)) { + $_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep; + $_compile_id_part_length = strlen($_compile_id_part); + } + $_count = 0; + try { + $_compileDirs = new RecursiveDirectoryIterator($_dir); + // NOTE: UnexpectedValueException thrown for PHP >= 5.3 + } catch (Exception $e) { + return 0; + } + $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($_compile as $_file) { + if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) + continue; + + $_filepath = (string) $_file; + + if ($_file->isDir()) { + if (!$_compile->isDot()) { + // delete folder if empty + @rmdir($_file->getPathname()); + } + } else { + $unlink = false; + if ((!isset($_compile_id) || (isset($_filepath[$_compile_id_part_length]) && !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) + && (!isset($resource_name) + || (isset($_filepath[$_resource_part_1_length]) + && substr_compare($_filepath, $_resource_part_1, -$_resource_part_1_length, $_resource_part_1_length) == 0) + || (isset($_filepath[$_resource_part_2_length]) + && substr_compare($_filepath, $_resource_part_2, -$_resource_part_2_length, $_resource_part_2_length) == 0))) { + if (isset($exp_time)) { + if (time() - @filemtime($_filepath) >= $exp_time) { + $unlink = true; + } + } else { + $unlink = true; + } + } + + if ($unlink && @unlink($_filepath)) { + $_count++; + } + } + } + // clear compiled cache + Smarty_Resource::$sources = array(); + Smarty_Resource::$compileds = array(); + + return $_count; + } + + /** + * Return array of tag/attributes of all tags used by an template + * + * @param Smarty_Internal_Template $templae template object + * @return array of tag/attributes + */ + public static function getTags(Smarty_Internal_Template $template) + { + $template->smarty->get_used_tags = true; + $template->compileTemplateSource(); + + return $template->used_tags; + } + + /** + * diagnose Smarty setup + * + * If $errors is secified, the diagnostic report will be appended to the array, rather than being output. + * + * @param Smarty $smarty Smarty instance to test + * @param array $errors array to push results into rather than outputting them + * @return bool status, true if everything is fine, false else + */ + public static function testInstall(Smarty $smarty, &$errors=null) + { + $status = true; + + if ($errors === null) { + echo "
\n";
+            echo "Smarty Installation test...\n";
+            echo "Testing template directory...\n";
+        }
+
+        $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
+
+        // test if all registered template_dir are accessible
+        foreach ($smarty->getTemplateDir() as $template_dir) {
+            $_template_dir = $template_dir;
+            $template_dir = realpath($template_dir);
+            // resolve include_path or fail existence
+            if (!$template_dir) {
+                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) {
+                    // try PHP include_path
+                    if ($_stream_resolve_include_path) {
+                        $template_dir = stream_resolve_include_path($_template_dir);
+                    } else {
+                        $template_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_template_dir);
+                    }
+
+                    if ($template_dir !== false) {
+                        if ($errors === null) {
+                            echo "$template_dir is OK.\n";
+                        }
+
+                        continue;
+                    } else {
+                        $status = false;
+                        $message = "FAILED: $_template_dir does not exist (and couldn't be found in include_path either)";
+                        if ($errors === null) {
+                            echo $message . ".\n";
+                        } else {
+                            $errors['template_dir'] = $message;
+                        }
+
+                        continue;
+                    }
+                } else {
+                    $status = false;
+                    $message = "FAILED: $_template_dir does not exist";
+                    if ($errors === null) {
+                        echo $message . ".\n";
+                    } else {
+                        $errors['template_dir'] = $message;
+                    }
+
+                    continue;
+                }
+            }
+
+            if (!is_dir($template_dir)) {
+                $status = false;
+                $message = "FAILED: $template_dir is not a directory";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['template_dir'] = $message;
+                }
+            } elseif (!is_readable($template_dir)) {
+                $status = false;
+                $message = "FAILED: $template_dir is not readable";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['template_dir'] = $message;
+                }
+            } else {
+                if ($errors === null) {
+                    echo "$template_dir is OK.\n";
+                }
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing compile directory...\n";
+        }
+
+        // test if registered compile_dir is accessible
+        $__compile_dir = $smarty->getCompileDir();
+        $_compile_dir = realpath($__compile_dir);
+        if (!$_compile_dir) {
+            $status = false;
+            $message = "FAILED: {$__compile_dir} does not exist";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['compile_dir'] = $message;
+            }
+        } elseif (!is_dir($_compile_dir)) {
+            $status = false;
+            $message = "FAILED: {$_compile_dir} is not a directory";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['compile_dir'] = $message;
+            }
+        } elseif (!is_readable($_compile_dir)) {
+            $status = false;
+            $message = "FAILED: {$_compile_dir} is not readable";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['compile_dir'] = $message;
+            }
+        } elseif (!is_writable($_compile_dir)) {
+            $status = false;
+            $message = "FAILED: {$_compile_dir} is not writable";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['compile_dir'] = $message;
+            }
+        } else {
+            if ($errors === null) {
+                echo "{$_compile_dir} is OK.\n";
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing plugins directory...\n";
+        }
+
+        // test if all registered plugins_dir are accessible
+        // and if core plugins directory is still registered
+        $_core_plugins_dir = realpath(dirname(__FILE__) .'/../plugins');
+        $_core_plugins_available = false;
+        foreach ($smarty->getPluginsDir() as $plugin_dir) {
+            $_plugin_dir = $plugin_dir;
+            $plugin_dir = realpath($plugin_dir);
+            // resolve include_path or fail existence
+            if (!$plugin_dir) {
+                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
+                    // try PHP include_path
+                    if ($_stream_resolve_include_path) {
+                        $plugin_dir = stream_resolve_include_path($_plugin_dir);
+                    } else {
+                        $plugin_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_plugin_dir);
+                    }
+
+                    if ($plugin_dir !== false) {
+                        if ($errors === null) {
+                            echo "$plugin_dir is OK.\n";
+                        }
+
+                        continue;
+                    } else {
+                        $status = false;
+                        $message = "FAILED: $_plugin_dir does not exist (and couldn't be found in include_path either)";
+                        if ($errors === null) {
+                            echo $message . ".\n";
+                        } else {
+                            $errors['plugins_dir'] = $message;
+                        }
+
+                        continue;
+                    }
+                } else {
+                    $status = false;
+                    $message = "FAILED: $_plugin_dir does not exist";
+                    if ($errors === null) {
+                        echo $message . ".\n";
+                    } else {
+                        $errors['plugins_dir'] = $message;
+                    }
+
+                    continue;
+                }
+            }
+
+            if (!is_dir($plugin_dir)) {
+                $status = false;
+                $message = "FAILED: $plugin_dir is not a directory";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['plugins_dir'] = $message;
+                }
+            } elseif (!is_readable($plugin_dir)) {
+                $status = false;
+                $message = "FAILED: $plugin_dir is not readable";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['plugins_dir'] = $message;
+                }
+            } elseif ($_core_plugins_dir && $_core_plugins_dir == realpath($plugin_dir)) {
+                $_core_plugins_available = true;
+                if ($errors === null) {
+                    echo "$plugin_dir is OK.\n";
+                }
+            } else {
+                if ($errors === null) {
+                    echo "$plugin_dir is OK.\n";
+                }
+            }
+        }
+        if (!$_core_plugins_available) {
+            $status = false;
+            $message = "WARNING: Smarty's own libs/plugins is not available";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } elseif (!isset($errors['plugins_dir'])) {
+                $errors['plugins_dir'] = $message;
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing cache directory...\n";
+        }
+
+        // test if all registered cache_dir is accessible
+        $__cache_dir = $smarty->getCacheDir();
+        $_cache_dir = realpath($__cache_dir);
+        if (!$_cache_dir) {
+            $status = false;
+            $message = "FAILED: {$__cache_dir} does not exist";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['cache_dir'] = $message;
+            }
+        } elseif (!is_dir($_cache_dir)) {
+            $status = false;
+            $message = "FAILED: {$_cache_dir} is not a directory";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['cache_dir'] = $message;
+            }
+        } elseif (!is_readable($_cache_dir)) {
+            $status = false;
+            $message = "FAILED: {$_cache_dir} is not readable";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['cache_dir'] = $message;
+            }
+        } elseif (!is_writable($_cache_dir)) {
+            $status = false;
+            $message = "FAILED: {$_cache_dir} is not writable";
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['cache_dir'] = $message;
+            }
+        } else {
+            if ($errors === null) {
+                echo "{$_cache_dir} is OK.\n";
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing configs directory...\n";
+        }
+
+        // test if all registered config_dir are accessible
+        foreach ($smarty->getConfigDir() as $config_dir) {
+            $_config_dir = $config_dir;
+            $config_dir = realpath($config_dir);
+            // resolve include_path or fail existence
+            if (!$config_dir) {
+                if ($smarty->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_config_dir)) {
+                    // try PHP include_path
+                    if ($_stream_resolve_include_path) {
+                        $config_dir = stream_resolve_include_path($_config_dir);
+                    } else {
+                        $config_dir = Smarty_Internal_Get_Include_Path::getIncludePath($_config_dir);
+                    }
+
+                    if ($config_dir !== false) {
+                        if ($errors === null) {
+                            echo "$config_dir is OK.\n";
+                        }
+
+                        continue;
+                    } else {
+                        $status = false;
+                        $message = "FAILED: $_config_dir does not exist (and couldn't be found in include_path either)";
+                        if ($errors === null) {
+                            echo $message . ".\n";
+                        } else {
+                            $errors['config_dir'] = $message;
+                        }
+
+                        continue;
+                    }
+                } else {
+                    $status = false;
+                    $message = "FAILED: $_config_dir does not exist";
+                    if ($errors === null) {
+                        echo $message . ".\n";
+                    } else {
+                        $errors['config_dir'] = $message;
+                    }
+
+                    continue;
+                }
+            }
+
+            if (!is_dir($config_dir)) {
+                $status = false;
+                $message = "FAILED: $config_dir is not a directory";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['config_dir'] = $message;
+                }
+            } elseif (!is_readable($config_dir)) {
+                $status = false;
+                $message = "FAILED: $config_dir is not readable";
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['config_dir'] = $message;
+                }
+            } else {
+                if ($errors === null) {
+                    echo "$config_dir is OK.\n";
+                }
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing sysplugin files...\n";
+        }
+        // test if sysplugins are available
+        $source = SMARTY_SYSPLUGINS_DIR;
+        if (is_dir($source)) {
+            $expected = array(
+                "smarty_cacheresource.php" => true,
+                "smarty_cacheresource_custom.php" => true,
+                "smarty_cacheresource_keyvaluestore.php" => true,
+                "smarty_config_source.php" => true,
+                "smarty_internal_cacheresource_file.php" => true,
+                "smarty_internal_compile_append.php" => true,
+                "smarty_internal_compile_assign.php" => true,
+                "smarty_internal_compile_block.php" => true,
+                "smarty_internal_compile_break.php" => true,
+                "smarty_internal_compile_call.php" => true,
+                "smarty_internal_compile_capture.php" => true,
+                "smarty_internal_compile_config_load.php" => true,
+                "smarty_internal_compile_continue.php" => true,
+                "smarty_internal_compile_debug.php" => true,
+                "smarty_internal_compile_eval.php" => true,
+                "smarty_internal_compile_extends.php" => true,
+                "smarty_internal_compile_for.php" => true,
+                "smarty_internal_compile_foreach.php" => true,
+                "smarty_internal_compile_function.php" => true,
+                "smarty_internal_compile_if.php" => true,
+                "smarty_internal_compile_include.php" => true,
+                "smarty_internal_compile_include_php.php" => true,
+                "smarty_internal_compile_insert.php" => true,
+                "smarty_internal_compile_ldelim.php" => true,
+                "smarty_internal_compile_nocache.php" => true,
+                "smarty_internal_compile_private_block_plugin.php" => true,
+                "smarty_internal_compile_private_function_plugin.php" => true,
+                "smarty_internal_compile_private_modifier.php" => true,
+                "smarty_internal_compile_private_object_block_function.php" => true,
+                "smarty_internal_compile_private_object_function.php" => true,
+                "smarty_internal_compile_private_print_expression.php" => true,
+                "smarty_internal_compile_private_registered_block.php" => true,
+                "smarty_internal_compile_private_registered_function.php" => true,
+                "smarty_internal_compile_private_special_variable.php" => true,
+                "smarty_internal_compile_rdelim.php" => true,
+                "smarty_internal_compile_section.php" => true,
+                "smarty_internal_compile_setfilter.php" => true,
+                "smarty_internal_compile_while.php" => true,
+                "smarty_internal_compilebase.php" => true,
+                "smarty_internal_config.php" => true,
+                "smarty_internal_config_file_compiler.php" => true,
+                "smarty_internal_configfilelexer.php" => true,
+                "smarty_internal_configfileparser.php" => true,
+                "smarty_internal_data.php" => true,
+                "smarty_internal_debug.php" => true,
+                "smarty_internal_filter_handler.php" => true,
+                "smarty_internal_function_call_handler.php" => true,
+                "smarty_internal_get_include_path.php" => true,
+                "smarty_internal_nocache_insert.php" => true,
+                "smarty_internal_parsetree.php" => true,
+                "smarty_internal_resource_eval.php" => true,
+                "smarty_internal_resource_extends.php" => true,
+                "smarty_internal_resource_file.php" => true,
+                "smarty_internal_resource_registered.php" => true,
+                "smarty_internal_resource_stream.php" => true,
+                "smarty_internal_resource_string.php" => true,
+                "smarty_internal_smartytemplatecompiler.php" => true,
+                "smarty_internal_template.php" => true,
+                "smarty_internal_templatebase.php" => true,
+                "smarty_internal_templatecompilerbase.php" => true,
+                "smarty_internal_templatelexer.php" => true,
+                "smarty_internal_templateparser.php" => true,
+                "smarty_internal_utility.php" => true,
+                "smarty_internal_write_file.php" => true,
+                "smarty_resource.php" => true,
+                "smarty_resource_custom.php" => true,
+                "smarty_resource_recompiled.php" => true,
+                "smarty_resource_uncompiled.php" => true,
+                "smarty_security.php" => true,
+            );
+            $iterator = new DirectoryIterator($source);
+            foreach ($iterator as $file) {
+                if (!$file->isDot()) {
+                    $filename = $file->getFilename();
+                    if (isset($expected[$filename])) {
+                        unset($expected[$filename]);
+                    }
+                }
+            }
+            if ($expected) {
+                $status = false;
+                $message = "FAILED: files missing from libs/sysplugins: ". join(', ', array_keys($expected));
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['sysplugins'] = $message;
+                }
+            } elseif ($errors === null) {
+                echo "... OK\n";
+            }
+        } else {
+            $status = false;
+            $message = "FAILED: ". SMARTY_SYSPLUGINS_DIR .' is not a directory';
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['sysplugins_dir_constant'] = $message;
+            }
+        }
+
+        if ($errors === null) {
+            echo "Testing plugin files...\n";
+        }
+        // test if core plugins are available
+        $source = SMARTY_PLUGINS_DIR;
+        if (is_dir($source)) {
+            $expected = array(
+                "block.textformat.php" => true,
+                "function.counter.php" => true,
+                "function.cycle.php" => true,
+                "function.fetch.php" => true,
+                "function.html_checkboxes.php" => true,
+                "function.html_image.php" => true,
+                "function.html_options.php" => true,
+                "function.html_radios.php" => true,
+                "function.html_select_date.php" => true,
+                "function.html_select_time.php" => true,
+                "function.html_table.php" => true,
+                "function.mailto.php" => true,
+                "function.math.php" => true,
+                "modifier.capitalize.php" => true,
+                "modifier.date_format.php" => true,
+                "modifier.debug_print_var.php" => true,
+                "modifier.escape.php" => true,
+                "modifier.regex_replace.php" => true,
+                "modifier.replace.php" => true,
+                "modifier.spacify.php" => true,
+                "modifier.truncate.php" => true,
+                "modifiercompiler.cat.php" => true,
+                "modifiercompiler.count_characters.php" => true,
+                "modifiercompiler.count_paragraphs.php" => true,
+                "modifiercompiler.count_sentences.php" => true,
+                "modifiercompiler.count_words.php" => true,
+                "modifiercompiler.default.php" => true,
+                "modifiercompiler.escape.php" => true,
+                "modifiercompiler.from_charset.php" => true,
+                "modifiercompiler.indent.php" => true,
+                "modifiercompiler.lower.php" => true,
+                "modifiercompiler.noprint.php" => true,
+                "modifiercompiler.string_format.php" => true,
+                "modifiercompiler.strip.php" => true,
+                "modifiercompiler.strip_tags.php" => true,
+                "modifiercompiler.to_charset.php" => true,
+                "modifiercompiler.unescape.php" => true,
+                "modifiercompiler.upper.php" => true,
+                "modifiercompiler.wordwrap.php" => true,
+                "outputfilter.trimwhitespace.php" => true,
+                "shared.escape_special_chars.php" => true,
+                "shared.literal_compiler_param.php" => true,
+                "shared.make_timestamp.php" => true,
+                "shared.mb_str_replace.php" => true,
+                "shared.mb_unicode.php" => true,
+                "shared.mb_wordwrap.php" => true,
+                "variablefilter.htmlspecialchars.php" => true,
+            );
+            $iterator = new DirectoryIterator($source);
+            foreach ($iterator as $file) {
+                if (!$file->isDot()) {
+                    $filename = $file->getFilename();
+                    if (isset($expected[$filename])) {
+                        unset($expected[$filename]);
+                    }
+                }
+            }
+            if ($expected) {
+                $status = false;
+                $message = "FAILED: files missing from libs/plugins: ". join(', ', array_keys($expected));
+                if ($errors === null) {
+                    echo $message . ".\n";
+                } else {
+                    $errors['plugins'] = $message;
+                }
+            } elseif ($errors === null) {
+                echo "... OK\n";
+            }
+        } else {
+            $status = false;
+            $message = "FAILED: ". SMARTY_PLUGINS_DIR .' is not a directory';
+            if ($errors === null) {
+                echo $message . ".\n";
+            } else {
+                $errors['plugins_dir_constant'] = $message;
+            }
+        }
+
+        if ($errors === null) {
+            echo "Tests complete.\n";
+            echo "
\n"; + } + + return $status; + } + +}