diff --git a/libs/sysplugins/smarty_internal_method_unregistercacheresource.php b/libs/sysplugins/smarty_internal_method_unregistercacheresource.php new file mode 100644 index 0000000..1a157ff --- /dev/null +++ b/libs/sysplugins/smarty_internal_method_unregistercacheresource.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_cache_resources[ $name ])) { + unset($smarty->registered_cache_resources[ $name ]); + } + return $obj; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_method_unregisterfilter.php b/libs/sysplugins/smarty_internal_method_unregisterfilter.php new file mode 100644 index 0000000..c5b88f5 --- /dev/null +++ b/libs/sysplugins/smarty_internal_method_unregisterfilter.php @@ -0,0 +1,42 @@ +_getSmartyObj(); + $this->_checkFilterType($type); + if (isset($smarty->registered_filters[ $type ])) { + $name = is_string($callback) ? $callback : $this->_getFilterName($callback); + if (isset($smarty->registered_filters[ $type ][ $name ])) { + unset($smarty->registered_filters[ $type ][ $name ]); + if (empty($smarty->registered_filters[ $type ])) { + unset($smarty->registered_filters[ $type ]); + } + } + } + return $obj; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_method_unregisterobject.php b/libs/sysplugins/smarty_internal_method_unregisterobject.php new file mode 100644 index 0000000..76d4866 --- /dev/null +++ b/libs/sysplugins/smarty_internal_method_unregisterobject.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_objects[ $object_name ])) { + unset($smarty->registered_objects[ $object_name ]); + } + return $obj; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_method_unregisterplugin.php b/libs/sysplugins/smarty_internal_method_unregisterplugin.php new file mode 100644 index 0000000..b5f0d50 --- /dev/null +++ b/libs/sysplugins/smarty_internal_method_unregisterplugin.php @@ -0,0 +1,41 @@ +_getSmartyObj(); + if (isset($smarty->registered_plugins[ $type ][ $name ])) { + unset($smarty->registered_plugins[ $type ][ $name ]); + } + return $obj; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_method_unregisterresource.php b/libs/sysplugins/smarty_internal_method_unregisterresource.php new file mode 100644 index 0000000..ed4801d --- /dev/null +++ b/libs/sysplugins/smarty_internal_method_unregisterresource.php @@ -0,0 +1,40 @@ +_getSmartyObj(); + if (isset($smarty->registered_resources[ $type ])) { + unset($smarty->registered_resources[ $type ]); + } + return $obj; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_nocache_insert.php b/libs/sysplugins/smarty_internal_nocache_insert.php new file mode 100644 index 0000000..65fc143 --- /dev/null +++ b/libs/sysplugins/smarty_internal_nocache_insert.php @@ -0,0 +1,53 @@ +assign('{$_assign}' , {$_function} (" . var_export($_attr, true) . + ",\$_smarty_tpl), true);?>"; + } else { + $_output .= "echo {$_function}(" . var_export($_attr, true) . ",\$_smarty_tpl);?>"; + } + $_tpl = $_template; + while ($_tpl->_isSubTpl()) { + $_tpl = $_tpl->parent; + } + + return "/*%%SmartyNocache:{$_tpl->compiled->nocache_hash}%%*/" . $_output . + "/*/%%SmartyNocache:{$_tpl->compiled->nocache_hash}%%*/"; + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree.php b/libs/sysplugins/smarty_internal_parsetree.php new file mode 100644 index 0000000..32c9df0 --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree.php @@ -0,0 +1,54 @@ +data = null; + $this->subtrees = null; + } + +} + + diff --git a/libs/sysplugins/smarty_internal_parsetree_code.php b/libs/sysplugins/smarty_internal_parsetree_code.php new file mode 100644 index 0000000..d0f0b3f --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_code.php @@ -0,0 +1,42 @@ +data = $data; + } + + /** + * Return buffer content in parentheses + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return sprintf("(%s)", $this->data); + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree_dq.php b/libs/sysplugins/smarty_internal_parsetree_dq.php new file mode 100644 index 0000000..8c2e0d9 --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_dq.php @@ -0,0 +1,95 @@ +subtrees[] = $subtree; + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $parser->block_nesting_level = count($parser->compiler->_tag_stack); + } + } + + /** + * Append buffer to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param Smarty_Internal_ParseTree $subtree parse tree buffer + */ + public function append_subtree(Smarty_Internal_Templateparser $parser, Smarty_Internal_ParseTree $subtree) + { + $last_subtree = count($this->subtrees) - 1; + if ($last_subtree >= 0 && $this->subtrees[ $last_subtree ] instanceof Smarty_Internal_ParseTree_Tag && + $this->subtrees[ $last_subtree ]->saved_block_nesting < $parser->block_nesting_level + ) { + if ($subtree instanceof Smarty_Internal_ParseTree_Code) { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, + 'data . ';?>'); + } elseif ($subtree instanceof Smarty_Internal_ParseTree_DqContent) { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, + 'data . '";?>'); + } else { + $this->subtrees[ $last_subtree ]->data = + $parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data); + } + } else { + $this->subtrees[] = $subtree; + } + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $parser->block_nesting_level = count($parser->compiler->_tag_stack); + } + } + + /** + * Merge subtree buffer content together + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string compiled template code + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + $code = ''; + foreach ($this->subtrees as $subtree) { + if ($code !== "") { + $code .= "."; + } + if ($subtree instanceof Smarty_Internal_ParseTree_Tag) { + $more_php = $subtree->assign_to_var($parser); + } else { + $more_php = $subtree->to_smarty_php($parser); + } + + $code .= $more_php; + + if (!$subtree instanceof Smarty_Internal_ParseTree_DqContent) { + $parser->compiler->has_variable_string = true; + } + } + + return $code; + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree_dqcontent.php b/libs/sysplugins/smarty_internal_parsetree_dqcontent.php new file mode 100644 index 0000000..a8ca389 --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_dqcontent.php @@ -0,0 +1,42 @@ +data = $data; + } + + /** + * Return content as double quoted string + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string doubled quoted string + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return '"' . $this->data . '"'; + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree_tag.php b/libs/sysplugins/smarty_internal_parsetree_tag.php new file mode 100644 index 0000000..9058aab --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_tag.php @@ -0,0 +1,69 @@ +data = $data; + $this->saved_block_nesting = $parser->block_nesting_level; + } + + /** + * Return buffer content + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return $this->data; + } + + /** + * Return complied code that loads the evaluated output of buffer content into a temporary variable + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string template code + */ + public function assign_to_var(Smarty_Internal_Templateparser $parser) + { + $var = $parser->compiler->getNewPrefixVariable(); + $tmp = $parser->compiler->appendCode('', $this->data); + $tmp = $parser->compiler->appendCode($tmp, ""); + $parser->compiler->prefix_code[] = sprintf("%s", $tmp); + + return $var; + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree_template.php b/libs/sysplugins/smarty_internal_parsetree_template.php new file mode 100644 index 0000000..f603235 --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_template.php @@ -0,0 +1,128 @@ +subtrees)) { + $this->subtrees = array_merge($this->subtrees, $subtree->subtrees); + } else { + if ($subtree->data !== '') { + $this->subtrees[] = $subtree; + } + } + } + + /** + * Append array to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param \Smarty_Internal_ParseTree[] $array + */ + public function append_array(Smarty_Internal_Templateparser $parser, $array = array()) + { + if (!empty($array)) { + $this->subtrees = array_merge($this->subtrees, (array) $array); + } + } + + /** + * Prepend array to subtree + * + * @param \Smarty_Internal_Templateparser $parser + * @param \Smarty_Internal_ParseTree[] $array + */ + public function prepend_array(Smarty_Internal_Templateparser $parser, $array = array()) + { + if (!empty($array)) { + $this->subtrees = array_merge((array) $array, $this->subtrees); + } + } + + /** + * Sanitize and merge subtree buffers together + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string template code content + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + $code = ''; + for ($key = 0, $cnt = count($this->subtrees); $key < $cnt; $key ++) { + if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Text) { + $subtree = $this->subtrees[ $key ]->to_smarty_php($parser); + while ($key + 1 < $cnt && ($this->subtrees[ $key + 1 ] instanceof Smarty_Internal_ParseTree_Text || + $this->subtrees[ $key + 1 ]->data == '')) { + $key ++; + if ($this->subtrees[ $key ]->data == '') { + continue; + } + $subtree .= $this->subtrees[ $key ]->to_smarty_php($parser); + } + if ($subtree == '') { + continue; + } + $code .= preg_replace('/((<%)|(%>)|(<\?php)|(<\?)|(\?>)|(<\/?script))/', "\n", + $subtree); + continue; + } + if ($this->subtrees[ $key ] instanceof Smarty_Internal_ParseTree_Tag) { + $subtree = $this->subtrees[ $key ]->to_smarty_php($parser); + while ($key + 1 < $cnt && ($this->subtrees[ $key + 1 ] instanceof Smarty_Internal_ParseTree_Tag || + $this->subtrees[ $key + 1 ]->data == '')) { + $key ++; + if ($this->subtrees[ $key ]->data == '') { + continue; + } + $subtree = $parser->compiler->appendCode($subtree, $this->subtrees[ $key ]->to_smarty_php($parser)); + } + if ($subtree == '') { + continue; + } + $code .= $subtree; + continue; + } + $code .= $this->subtrees[ $key ]->to_smarty_php($parser); + } + return $code; + } +} diff --git a/libs/sysplugins/smarty_internal_parsetree_text.php b/libs/sysplugins/smarty_internal_parsetree_text.php new file mode 100644 index 0000000..b3100fa --- /dev/null +++ b/libs/sysplugins/smarty_internal_parsetree_text.php @@ -0,0 +1,40 @@ +data = $data; + } + + /** + * Return buffer content + * + * @param \Smarty_Internal_Templateparser $parser + * + * @return string text + */ + public function to_smarty_php(Smarty_Internal_Templateparser $parser) + { + return $this->data; + } +} diff --git a/libs/sysplugins/smarty_internal_resource_eval.php b/libs/sysplugins/smarty_internal_resource_eval.php new file mode 100644 index 0000000..d3088bd --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_eval.php @@ -0,0 +1,95 @@ +uid = $source->filepath = sha1($source->name); + $source->timestamp = $source->exists = true; + } + + /** + * Load template's source from $resource_name into current template object + * + * @uses decode() to decode base64 and urlencoded template_resources + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + */ + public function getContent(Smarty_Template_Source $source) + { + return $this->decode($source->name); + } + + /** + * decode base64 and urlencode + * + * @param string $string template_resource to decode + * + * @return string decoded template_resource + */ + protected function decode($string) + { + // decode if specified + if (($pos = strpos($string, ':')) !== false) { + if (!strncmp($string, 'base64', 6)) { + return base64_decode(substr($string, 7)); + } elseif (!strncmp($string, 'urlencode', 9)) { + return urldecode(substr($string, 10)); + } + } + + return $string; + } + + /** + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name + */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $this->decode($resource_name); + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return ''; + } +} diff --git a/libs/sysplugins/smarty_internal_resource_extends.php b/libs/sysplugins/smarty_internal_resource_extends.php new file mode 100644 index 0000000..4f1f09e --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_extends.php @@ -0,0 +1,125 @@ +name); + $smarty = &$source->smarty; + $exists = true; + foreach ($components as $component) { + /* @var \Smarty_Template_Source $_s */ + $_s = Smarty_Template_Source::load(null, $smarty, $component); + if ($_s->type == 'php') { + throw new SmartyException("Resource type {$_s->type} cannot be used with the extends resource type"); + } + $sources[ $_s->uid ] = $_s; + $uid .= $_s->filepath; + if ($_template) { + $exists = $exists && $_s->exists; + } + } + $source->components = $sources; + $source->filepath = $_s->filepath; + $source->uid = sha1($uid . $source->smarty->_joined_template_dir); + $source->exists = $exists; + if ($_template) { + $source->timestamp = $_s->timestamp; + } + } + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + $source->exists = true; + /* @var \Smarty_Template_Source $_s */ + foreach ($source->components as $_s) { + $source->exists = $source->exists && $_s->exists; + } + $source->timestamp = $source->exists ? $_s->getTimeStamp() : false; + } + + /** + * Load template's source from files into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + if (!$source->exists) { + throw new SmartyException("Unable to load template '{$source->type}:{$source->name}'"); + } + + $_components = array_reverse($source->components); + + $_content = ''; + /* @var \Smarty_Template_Source $_s */ + foreach ($_components as $_s) { + // read content + $_content .= $_s->getContent(); + } + return $_content; + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return str_replace(':', '.', basename($source->filepath)); + } + + /* + * Disable timestamp checks for extends resource. + * The individual source components will be checked. + * + * @return bool + */ + public function checkTimestamps() + { + return false; + } +} diff --git a/libs/sysplugins/smarty_internal_resource_file.php b/libs/sysplugins/smarty_internal_resource_file.php new file mode 100644 index 0000000..a58771a --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_file.php @@ -0,0 +1,176 @@ +name; + // absolute file ? + if ($file[ 0 ] == '/' || $file[ 1 ] == ':') { + $file = $source->smarty->_realpath($file, true); + return is_file($file) ? $file : false; + } + // go relative to a given template? + if ($file[ 0 ] == '.' && $_template && $_template->_isSubTpl() && + preg_match('#^[.]{1,2}[\\\/]#', $file) + ) { + if ($_template->parent->source->type != 'file' && $_template->parent->source->type != 'extends' && + !isset($_template->parent->_cache[ 'allow_relative_path' ]) + ) { + throw new SmartyException("Template '{$file}' cannot be relative to template of resource type '{$_template->parent->source->type}'"); + } + // normalize path + $path = $source->smarty->_realpath(dirname($_template->parent->source->filepath) . $source->smarty->ds . $file); + // files relative to a template only get one shot + return is_file($path) ? $path : false; + } + // normalize $source->smarty->ds + if (strpos($file, $source->smarty->ds == '/' ? '\\' : '/') !== false) { + $file = str_replace($source->smarty->ds == '/' ? '\\' : '/', $source->smarty->ds, $file); + } + + $_directories = $source->smarty->getTemplateDir(null, $source->isConfig); + // template_dir index? + if ($file[ 0 ] == '[' && preg_match('#^\[([^\]]+)\](.+)$#', $file, $fileMatch)) { + $file = $fileMatch[ 2 ]; + $_indices = explode(',', $fileMatch[ 1 ]); + $_index_dirs = array(); + foreach ($_indices as $index) { + $index = trim($index); + // try string indexes + if (isset($_directories[ $index ])) { + $_index_dirs[] = $_directories[ $index ]; + } elseif (is_numeric($index)) { + // try numeric index + $index = (int) $index; + if (isset($_directories[ $index ])) { + $_index_dirs[] = $_directories[ $index ]; + } else { + // try at location index + $keys = array_keys($_directories); + if (isset($_directories[ $keys[ $index ] ])) { + $_index_dirs[] = $_directories[ $keys[ $index ] ]; + } + } + } + } + if (empty($_index_dirs)) { + // index not found + return false; + } else { + $_directories = $_index_dirs; + } + } + + // relative file name? + foreach ($_directories as $_directory) { + $path = $_directory . $file; + if (is_file($path)) { + return (strpos($path, '.' . $source->smarty->ds) !== false) ? $source->smarty->_realpath($path) : $path; + } + } + if (!isset($_index_dirs)) { + // Could be relative to cwd + $path = $source->smarty->_realpath($file, true); + if (is_file($path)) { + return $path; + } + } + // Use include path ? + if ($source->smarty->use_include_path) { + return $source->smarty->ext->_getIncludePath->getIncludePath($_directories, $file, $source->smarty); + } + return false; + } + + /** + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + */ + public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) + { + $source->filepath = $this->buildFilepath($source, $_template); + + if ($source->filepath !== false) { + if (isset($source->smarty->security_policy) && is_object($source->smarty->security_policy)) { + $source->smarty->security_policy->isTrustedResourceDir($source->filepath, $source->isConfig); + } + $source->exists = true; + $source->uid = sha1($source->filepath . ($source->isConfig ? $source->smarty->_joined_config_dir : + $source->smarty->_joined_template_dir)); + $source->timestamp = filemtime($source->filepath); + } else { + $source->timestamp = $source->exists = false; + } + } + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + if (!$source->exists) { + $source->timestamp = $source->exists = is_file($source->filepath); + } + if ($source->exists) { + $source->timestamp = filemtime($source->filepath); + } + } + + /** + * Load template's source from file into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + if ($source->exists) { + return file_get_contents($source->filepath); + } + throw new SmartyException('Unable to read ' . ($source->isConfig ? 'config' : 'template') . + " {$source->type} '{$source->name}'"); + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename($source->filepath); + } +} diff --git a/libs/sysplugins/smarty_internal_resource_php.php b/libs/sysplugins/smarty_internal_resource_php.php new file mode 100644 index 0000000..6e9351d --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_php.php @@ -0,0 +1,111 @@ +short_open_tag = function_exists('ini_get') ? ini_get('short_open_tag') : 1; + } + + /** + * Load template's source from file into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + if ($source->exists) { + return ''; + } + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } + + /** + * populate compiled object with compiled filepath + * + * @param Smarty_Template_Compiled $compiled compiled object + * @param Smarty_Internal_Template $_template template object (is ignored) + */ + public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) + { + $compiled->filepath = $_template->source->filepath; + $compiled->timestamp = $_template->source->timestamp; + $compiled->exists = $_template->source->exists; + $compiled->file_dependency[ $_template->source->uid ] = + array($compiled->filepath, + $compiled->timestamp, + $_template->source->type,); + } + + /** + * Render and output the template (without using the compiler) + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + * + * @return void + * @throws SmartyException if template cannot be loaded or allow_php_templates is disabled + */ + public function renderUncompiled(Smarty_Template_Source $source, Smarty_Internal_Template $_template) + { + if (!$source->smarty->allow_php_templates) { + throw new SmartyException("PHP templates are disabled"); + } + if (!$source->exists) { + throw new SmartyException("Unable to load template {$source->type} '{$source->name}'" . + ($_template->_isSubTpl() ? " in '{$_template->parent->template_resource}'" : '')); + } + + // prepare variables + extract($_template->getTemplateVars()); + + // include PHP template with short open tags enabled + if (function_exists('ini_set')) { + ini_set('short_open_tag', '1'); + } + /** @var Smarty_Internal_Template $_smarty_template + * used in included file + */ + $_smarty_template = $_template; + include($source->filepath); + if (function_exists('ini_set')) { + ini_set('short_open_tag', $this->short_open_tag); + } + } +} diff --git a/libs/sysplugins/smarty_internal_resource_registered.php b/libs/sysplugins/smarty_internal_resource_registered.php new file mode 100644 index 0000000..8535257 --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_registered.php @@ -0,0 +1,99 @@ +filepath = $source->type . ':' . $source->name; + $source->uid = sha1($source->filepath . $source->smarty->_joined_template_dir); + $source->timestamp = $this->getTemplateTimestamp($source); + $source->exists = !!$source->timestamp; + } + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + * + * @return void + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + $source->timestamp = $this->getTemplateTimestamp($source); + $source->exists = !!$source->timestamp; + } + + /** + * Get timestamp (epoch) the template source was modified + * + * @param Smarty_Template_Source $source source object + * + * @return integer|boolean timestamp (epoch) the template was modified, false if resources has no timestamp + */ + public function getTemplateTimestamp(Smarty_Template_Source $source) + { + // return timestamp + $time_stamp = false; + call_user_func_array($source->smarty->registered_resources[ $source->type ][ 0 ][ 1 ], + array($source->name, &$time_stamp, $source->smarty)); + + return is_numeric($time_stamp) ? (int) $time_stamp : $time_stamp; + } + + /** + * Load template's source by invoking the registered callback into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + // return template string + $content = null; + $t = call_user_func_array($source->smarty->registered_resources[ $source->type ][ 0 ][ 0 ], + array($source->name, &$content, $source->smarty)); + if (is_bool($t) && !$t) { + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } + + return $content; + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename($source->name); + } +} diff --git a/libs/sysplugins/smarty_internal_resource_stream.php b/libs/sysplugins/smarty_internal_resource_stream.php new file mode 100644 index 0000000..b4248fb --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_stream.php @@ -0,0 +1,80 @@ +resource, '://') !== false) { + $source->filepath = $source->resource; + } else { + $source->filepath = str_replace(':', '://', $source->resource); + } + $source->uid = false; + $source->content = $this->getContent($source); + $source->timestamp = $source->exists = !!$source->content; + } + + /** + * Load template's source from stream into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + $t = ''; + // the availability of the stream has already been checked in Smarty_Resource::fetch() + $fp = fopen($source->filepath, 'r+'); + if ($fp) { + while (!feof($fp) && ($current_line = fgets($fp)) !== false) { + $t .= $current_line; + } + fclose($fp); + + return $t; + } else { + return false; + } + } + + /** + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name + */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $resource_name; + } +} diff --git a/libs/sysplugins/smarty_internal_resource_string.php b/libs/sysplugins/smarty_internal_resource_string.php new file mode 100644 index 0000000..f2610d9 --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_string.php @@ -0,0 +1,107 @@ +uid = $source->filepath = sha1($source->name . $source->smarty->_joined_template_dir); + $source->timestamp = $source->exists = true; + } + + /** + * Load template's source from $resource_name into current template object + * + * @uses decode() to decode base64 and urlencoded template_resources + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + */ + public function getContent(Smarty_Template_Source $source) + { + return $this->decode($source->name); + } + + /** + * decode base64 and urlencode + * + * @param string $string template_resource to decode + * + * @return string decoded template_resource + */ + protected function decode($string) + { + // decode if specified + if (($pos = strpos($string, ':')) !== false) { + if (!strncmp($string, 'base64', 6)) { + return base64_decode(substr($string, 7)); + } elseif (!strncmp($string, 'urlencode', 9)) { + return urldecode(substr($string, 10)); + } + } + + return $string; + } + + /** + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name + */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + return get_class($this) . '#' . $this->decode($resource_name); + } + + /** + * Determine basename for compiled filename + * Always returns an empty string. + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return ''; + } + + /* + * Disable timestamp checks for string resource. + * + * @return bool + */ + public function checkTimestamps() + { + return false; + } +} + diff --git a/libs/sysplugins/smarty_internal_runtime_cachemodify.php b/libs/sysplugins/smarty_internal_runtime_cachemodify.php new file mode 100644 index 0000000..a91874a --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_cachemodify.php @@ -0,0 +1,68 @@ +isCached() && !$_template->compiled->has_nocache_code; + $_last_modified_date = + @substr($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ], 0, strpos($_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ], 'GMT') + 3); + if ($_isCached && $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: + if ( /* ^phpunit */ + !empty($_SERVER[ 'SMARTY_PHPUNIT_DISABLE_HEADERS' ]) /* phpunit$ */ + ) { + $_SERVER[ 'SMARTY_PHPUNIT_HEADERS' ][] = '304 Not Modified'; + } else { + 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', $cached->timestamp) . ' GMT'; + } + break; + default: + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $cached->timestamp) . ' GMT'); + break; + } + echo $content; + } + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php b/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php new file mode 100644 index 0000000..38ad41c --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_cacheresourcefile.php @@ -0,0 +1,142 @@ +use_sub_dirs ? '/' : '^'; + $_compile_id_offset = $smarty->use_sub_dirs ? 3 : 0; + $_dir = $smarty->getCacheDir(); + if ($_dir == '/') { //We should never want to delete this! + return 0; + } + $_dir_length = strlen($_dir); + if (isset($_cache_id)) { + $_cache_id_parts = explode('|', $_cache_id); + $_cache_id_parts_count = count($_cache_id_parts); + if ($smarty->use_sub_dirs) { + foreach ($_cache_id_parts as $id_part) { + $_dir .= $id_part . $smarty->ds; + } + } + } + if (isset($resource_name)) { + $_save_stat = $smarty->caching; + $smarty->caching = true; + $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 ($tpl->source->exists) { + $_resourcename_parts = basename(str_replace('^', '/', $tpl->cached->filepath)); + } else { + return 0; + } + } + $_count = 0; + $_time = time(); + if (file_exists($_dir)) { + $_cacheDirs = new RecursiveDirectoryIterator($_dir); + $_cache = new RecursiveIteratorIterator($_cacheDirs, RecursiveIteratorIterator::CHILD_FIRST); + foreach ($_cache as $_file) { + if (substr(basename($_file->getPathname()), 0, 1) == '.') { + continue; + } + $_filepath = (string) $_file; + // directory ? + if ($_file->isDir()) { + if (!$_cache->isDot()) { + // delete folder if empty + @rmdir($_file->getPathname()); + } + } else { + // delete only php files + if (substr($_filepath, - 4) !== '.php') { + continue; + } + $_parts = explode($_dir_sep, str_replace('\\', '/', substr($_filepath, $_dir_length))); + $_parts_count = count($_parts); + // check name + if (isset($resource_name)) { + if ($_parts[ $_parts_count - 1 ] != $_resourcename_parts) { + continue; + } + } + // check compile id + if (isset($_compile_id) && (!isset($_parts[ $_parts_count - 2 - $_compile_id_offset ]) || + $_parts[ $_parts_count - 2 - $_compile_id_offset ] != $_compile_id) + ) { + continue; + } + // check cache id + if (isset($_cache_id)) { + // count of cache id parts + $_parts_count = (isset($_compile_id)) ? $_parts_count - 2 - $_compile_id_offset : + $_parts_count - 1 - $_compile_id_offset; + if ($_parts_count < $_cache_id_parts_count) { + continue; + } + for ($i = 0; $i < $_cache_id_parts_count; $i ++) { + if ($_parts[ $i ] != $_cache_id_parts[ $i ]) { + continue 2; + } + } + } + if (is_file($_filepath)) { + // expired ? + if (isset($exp_time)) { + if ($exp_time < 0) { + preg_match('#\'cache_lifetime\' =>\s*(\d*)#', file_get_contents($_filepath), $match); + if ($_time < (@filemtime($_filepath) + $match[ 1 ])) { + continue; + } + } else { + if ($_time - @filemtime($_filepath) < $exp_time) { + continue; + } + } + } + $_count += @unlink($_filepath) ? 1 : 0; + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) + ) { + opcache_invalidate($_filepath, true); + } elseif (function_exists('apc_delete_file')) { + apc_delete_file($_filepath); + } + } + } + } + } + return $_count; + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_runtime_capture.php b/libs/sysplugins/smarty_internal_runtime_capture.php new file mode 100644 index 0000000..18da7e8 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_capture.php @@ -0,0 +1,169 @@ +isRegistered) { + $this->register($_template); + } + $this->captureStack[] = array($buffer, + $assign, + $append); + $this->captureCount ++; + ob_start(); + } + + /** + * Register callbacks in template class + * + * @param \Smarty_Internal_Template $_template + */ + private function register(Smarty_Internal_Template $_template) + { + $_template->startRenderCallbacks[] = array($this, + 'startRender'); + $_template->endRenderCallbacks[] = array($this, + 'endRender'); + $this->startRender($_template); + $this->isRegistered = true; + } + + /** + * Start render callback + * + * @param \Smarty_Internal_Template $_template + */ + public function startRender(Smarty_Internal_Template $_template) + { + $this->countStack[] = $this->captureCount; + $this->captureCount = 0; + } + + /** + * Close capture section + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function close(Smarty_Internal_Template $_template) + { + if ($this->captureCount) { + list($buffer, $assign, $append) = array_pop($this->captureStack); + $this->captureCount --; + if (isset($assign)) { + $_template->assign($assign, ob_get_contents()); + } + if (isset($append)) { + $_template->append($append, ob_get_contents()); + } + $this->namedBuffer[ $buffer ] = ob_get_clean(); + } else { + $this->error($_template); + } + } + + /** + * Error exception on not matching {capture}{/capture} + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function error(Smarty_Internal_Template $_template) + { + throw new SmartyException("Not matching {capture}{/capture} in \"{$_template->template_resource}\""); + } + + /** + * Return content of named capture buffer by key or as array + * + * @param \Smarty_Internal_Template $_template + * @param string|null $name + * + * @return string|string[]|null + */ + public function getBuffer(Smarty_Internal_Template $_template, $name = null) + { + if (isset($name)) { + return isset($this->namedBuffer[ $name ]) ? $this->namedBuffer[ $name ] : null; + } else { + return $this->namedBuffer; + } + } + + /** + * End render callback + * + * @param \Smarty_Internal_Template $_template + * + * @throws \SmartyException + */ + public function endRender(Smarty_Internal_Template $_template) + { + if ($this->captureCount) { + $this->error($_template); + } else { + $this->captureCount = array_pop($this->countStack); + } + } + +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_runtime_codeframe.php b/libs/sysplugins/smarty_internal_runtime_codeframe.php new file mode 100644 index 0000000..ceb386f --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_codeframe.php @@ -0,0 +1,98 @@ +compiled->has_nocache_code; + $properties[ 'file_dependency' ] = $_template->compiled->file_dependency; + $properties[ 'includes' ] = $_template->compiled->includes; + } else { + $properties[ 'has_nocache_code' ] = $_template->cached->has_nocache_code; + $properties[ 'file_dependency' ] = $_template->cached->file_dependency; + $properties[ 'cache_lifetime' ] = $_template->cache_lifetime; + } + $output = "source->filepath) . "\" */\n\n"; + $output .= "/* @var Smarty_Internal_Template \$_smarty_tpl */\n"; + $dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' . + ($cache ? 'true' : 'false') . ")"; + $output .= "if ({$dec}) {\n"; + $output .= "function {$properties['unifunc']} (Smarty_Internal_Template \$_smarty_tpl) {\n"; + if (!$cache && !empty($compiler->tpl_function)) { + $output .= "\$_smarty_tpl->smarty->ext->_tplFunction->registerTplFunctions(\$_smarty_tpl, " . + var_export($compiler->tpl_function, true) . ");\n"; + } + if ($cache && isset($_template->smarty->ext->_tplFunction)) { + $output .= "\$_smarty_tpl->smarty->ext->_tplFunction->registerTplFunctions(\$_smarty_tpl, " . + var_export($_template->smarty->ext->_tplFunction->getTplFunction($_template), true) . ");\n"; + + } + // include code for plugins + if (!$cache) { + if (!empty($_template->compiled->required_plugins[ 'compiled' ])) { + foreach ($_template->compiled->required_plugins[ 'compiled' ] as $tmp) { + foreach ($tmp as $data) { + $file = addslashes($data[ 'file' ]); + if (is_array($data[ 'function' ])) { + $output .= "if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n"; + } else { + $output .= "if (!is_callable('{$data['function']}')) require_once '{$file}';\n"; + } + } + } + } + if ($_template->caching && !empty($_template->compiled->required_plugins[ 'nocache' ])) { + $_template->compiled->has_nocache_code = true; + $output .= "echo '/*%%SmartyNocache:{$_template->compiled->nocache_hash}%%*/smarty; "; + foreach ($_template->compiled->required_plugins[ 'nocache' ] as $tmp) { + foreach ($tmp as $data) { + $file = addslashes($data[ 'file' ]); + if (is_array($data[ 'function' ])) { + $output .= addslashes("if (!is_callable(array('{$data['function'][0]}','{$data['function'][1]}'))) require_once '{$file}';\n"); + } else { + $output .= addslashes("if (!is_callable('{$data['function']}')) require_once '{$file}';\n"); + } + } + } + $output .= "?>/*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%*/';\n"; + } + } + $output .= "?>\n"; + $output .= $content; + $output .= ""; + $output .= $functions; + $output .= "[\n]?<\?php\s*/', '/\?>\s*$/'), array("\n", ''), $output); + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_runtime_filterhandler.php b/libs/sysplugins/smarty_internal_runtime_filterhandler.php new file mode 100644 index 0000000..f6cfa7c --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_filterhandler.php @@ -0,0 +1,69 @@ +smarty->autoload_filters[ $type ])) { + foreach ((array) $template->smarty->autoload_filters[ $type ] as $name) { + $plugin_name = "Smarty_{$type}filter_{$name}"; + if (function_exists($plugin_name)) { + $callback = $plugin_name; + } elseif (class_exists($plugin_name, false) && is_callable(array($plugin_name, 'execute'))) { + $callback = array($plugin_name, 'execute'); + } elseif ($template->smarty->loadPlugin($plugin_name, false)) { + if (function_exists($plugin_name)) { + // use loaded Smarty2 style plugin + $callback = $plugin_name; + } elseif (class_exists($plugin_name, false) && is_callable(array($plugin_name, 'execute'))) { + // loaded class of filter plugin + $callback = array($plugin_name, 'execute'); + } else { + throw new SmartyException("Auto load {$type}-filter plugin method \"{$plugin_name}::execute\" not callable"); + } + } else { + // nothing found, throw exception + throw new SmartyException("Unable to auto load {$type}-filter plugin \"{$plugin_name}\""); + } + $content = call_user_func($callback, $content, $template); + } + } + // loop over registered filters of specified type + if (!empty($template->smarty->registered_filters[ $type ])) { + foreach ($template->smarty->registered_filters[ $type ] as $key => $name) { + $content = call_user_func($template->smarty->registered_filters[ $type ][ $key ], $content, $template); + } + } + // return filtered output + return $content; + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_foreach.php b/libs/sysplugins/smarty_internal_runtime_foreach.php new file mode 100644 index 0000000..8b60768 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_foreach.php @@ -0,0 +1,151 @@ +count($from); + } else { + settype($from, 'array'); + } + } + if (!isset($total)) { + $total = empty($from) ? 0 : (($needTotal || isset($properties[ 'total' ])) ? count($from) : 1); + } + if (isset($tpl->tpl_vars[ $item ])) { + $saveVars[ 'item' ] = array($item, + $tpl->tpl_vars[ $item ]); + } + $tpl->tpl_vars[ $item ] = new Smarty_Variable(null, $tpl->isRenderingCache); + if ($total === 0) { + $from = null; + } else { + if ($key) { + if (isset($tpl->tpl_vars[ $key ])) { + $saveVars[ 'key' ] = array($key, + $tpl->tpl_vars[ $key ]); + } + $tpl->tpl_vars[ $key ] = new Smarty_Variable(null, $tpl->isRenderingCache); + } + } + if ($needTotal) { + $tpl->tpl_vars[ $item ]->total = $total; + } + if ($name) { + $namedVar = "__smarty_foreach_{$name}"; + if (isset($tpl->tpl_vars[ $namedVar ])) { + $saveVars[ 'named' ] = array($namedVar, + $tpl->tpl_vars[ $namedVar ]); + } + $namedProp = array(); + if (isset($properties[ 'total' ])) { + $namedProp[ 'total' ] = $total; + } + if (isset($properties[ 'iteration' ])) { + $namedProp[ 'iteration' ] = 0; + } + if (isset($properties[ 'index' ])) { + $namedProp[ 'index' ] = - 1; + } + if (isset($properties[ 'show' ])) { + $namedProp[ 'show' ] = ($total > 0); + } + $tpl->tpl_vars[ $namedVar ] = new Smarty_Variable($namedProp); + } + $this->stack[] = $saveVars; + return $from; + } + + /** + * + * [util function] counts an array, arrayAccess/traversable or PDOStatement object + * + * @param mixed $value + * + * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 + * for empty elements + */ + public function count($value) + { + if ($value instanceof IteratorAggregate) { + // Note: getIterator() returns a Traversable, not an Iterator + // thus rewind() and valid() methods may not be present + return iterator_count($value->getIterator()); + } elseif ($value instanceof Iterator) { + return $value instanceof Generator ? 1 : iterator_count($value); + } elseif ($value instanceof Countable) { + return count($value); + } elseif ($value instanceof PDOStatement) { + return $value->rowCount(); + } elseif ($value instanceof Traversable) { + return iterator_count($value); + } + return count((array) $value); + } + + /** + * Restore saved variables + * + * will be called by {break n} or {continue n} for the required number of levels + * + * @param \Smarty_Internal_Template $tpl + * @param int $levels number of levels + */ + public function restore(Smarty_Internal_Template $tpl, $levels = 1) + { + while ($levels) { + $saveVars = array_pop($this->stack); + if (!empty($saveVars)) { + if (isset($saveVars[ 'item' ])) { + $item = &$saveVars[ 'item' ]; + $tpl->tpl_vars[ $item[ 0 ] ]->value = $item[ 1 ]->value; + } + if (isset($saveVars[ 'key' ])) { + $tpl->tpl_vars[ $saveVars[ 'key' ][ 0 ] ] = $saveVars[ 'key' ][ 1 ]; + } + if (isset($saveVars[ 'named' ])) { + $tpl->tpl_vars[ $saveVars[ 'named' ][ 0 ] ] = $saveVars[ 'named' ][ 1 ]; + } + } + $levels --; + } + } + +} diff --git a/libs/sysplugins/smarty_internal_runtime_getincludepath.php b/libs/sysplugins/smarty_internal_runtime_getincludepath.php new file mode 100644 index 0000000..e12b0c5 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_getincludepath.php @@ -0,0 +1,182 @@ +_include_path != $_i_path) { + $this->_include_dirs = array(); + $this->_include_path = $_i_path; + $_dirs = (array) explode(PATH_SEPARATOR, $_i_path); + foreach ($_dirs as $_path) { + if (is_dir($_path)) { + $this->_include_dirs[] = $smarty->_realpath($_path . $smarty->ds, true); + } + } + return true; + } + return false; + } + + /** + * return array with include path directories + * + * @param \Smarty $smarty + * + * @return array + */ + public function getIncludePathDirs(Smarty $smarty) + { + $this->isNewIncludePath($smarty); + return $this->_include_dirs; + } + + /** + * Return full file path from PHP include_path + * + * @param string[] $dirs + * @param string $file + * @param \Smarty $smarty + * + * @return bool|string full filepath or false + * + */ + public function getIncludePath($dirs, $file, Smarty $smarty) + { + //if (!(isset($this->_has_stream_include) ? $this->_has_stream_include : $this->_has_stream_include = false)) { + if (!(isset($this->_has_stream_include) ? $this->_has_stream_include : + $this->_has_stream_include = function_exists('stream_resolve_include_path')) + ) { + $this->isNewIncludePath($smarty); + } + // try PHP include_path + foreach ($dirs as $dir) { + $dir_n = isset($this->number[ $dir ]) ? $this->number[ $dir ] : $this->number[ $dir ] = $this->counter ++; + if (isset($this->isFile[ $dir_n ][ $file ])) { + if ($this->isFile[ $dir_n ][ $file ]) { + return $this->isFile[ $dir_n ][ $file ]; + } else { + continue; + } + } + if (isset($this->_user_dirs[ $dir_n ])) { + if (false === $this->_user_dirs[ $dir_n ]) { + continue; + } else { + $dir = $this->_user_dirs[ $dir_n ]; + } + } else { + if ($dir[ 0 ] == '/' || $dir[ 1 ] == ':') { + $dir = str_ireplace(getcwd(), '.', $dir); + if ($dir[ 0 ] == '/' || $dir[ 1 ] == ':') { + $this->_user_dirs[ $dir_n ] = false; + continue; + } + } + $dir = substr($dir, 2); + $this->_user_dirs[ $dir_n ] = $dir; + } + if ($this->_has_stream_include) { + $path = stream_resolve_include_path($dir . (isset($file) ? $file : '')); + if ($path) { + return $this->isFile[ $dir_n ][ $file ] = $path; + } + } else { + foreach ($this->_include_dirs as $key => $_i_path) { + $path = isset($this->isPath[ $key ][ $dir_n ]) ? $this->isPath[ $key ][ $dir_n ] : + $this->isPath[ $key ][ $dir_n ] = is_dir($_dir_path = $_i_path . $dir) ? $_dir_path : false; + if ($path === false) { + continue; + } + if (isset($file)) { + $_file = $this->isFile[ $dir_n ][ $file ] = (is_file($path . $file)) ? $path . $file : false; + if ($_file) { + return $_file; + } + } else { + // no file was given return directory path + return $path; + } + } + } + } + return false; + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_inheritance.php b/libs/sysplugins/smarty_internal_runtime_inheritance.php new file mode 100644 index 0000000..5e4bd2a --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_inheritance.php @@ -0,0 +1,241 @@ +state == 3 && (strpos($tpl->template_resource, 'extendsall') === false)) { + $tpl->inheritance = new Smarty_Internal_Runtime_Inheritance(); + $tpl->inheritance->init($tpl, $initChild, $blockNames); + return; + } + $this->tplIndex ++; + $this->sources[ $this->tplIndex ] = $tpl->source; + + // start of child sub template(s) + if ($initChild) { + $this->state = 1; + if (!$this->inheritanceLevel) { + //grab any output of child templates + ob_start(); + } + $this->inheritanceLevel ++; + // $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart'); + // $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd'); + } + // if state was waiting for parent change state to parent + if ($this->state == 2) { + $this->state = 3; + } + } + + /** + * End of child template(s) + * - if outer level is reached flush output buffer and switch to wait for parent template state + * + * @param \Smarty_Internal_Template $tpl + * @param null|string $template optional name of inheritance parent template + * @param null|string $uid uid of inline template + * @param null|string $func function call name of inline template + */ + public function endChild(Smarty_Internal_Template $tpl, $template = null, $uid = null, $func = null) + { + $this->inheritanceLevel --; + if (!$this->inheritanceLevel) { + ob_end_clean(); + $this->state = 2; + } + if (isset($template) && (($tpl->parent->_isTplObj() && $tpl->parent->source->type !== 'extends') || $tpl->smarty->extends_recursion)) { + $tpl->_subTemplateRender($template, $tpl->cache_id, $tpl->compile_id, $tpl->caching ? 9999 : 0, + $tpl->cache_lifetime, array(), 2, false, $uid, $func); + } + } + + /** + * Smarty_Internal_Block constructor. + * - if outer level {block} of child template ($state == 1) save it as child root block + * - otherwise process inheritance and render + * + * @param \Smarty_Internal_Template $tpl + * @param $className + * @param string $name + * @param int|null $tplIndex index of outer level {block} if nested + */ + public function instanceBlock(Smarty_Internal_Template $tpl, $className, $name, $tplIndex = null) + { + $block = new $className($name, isset($tplIndex) ? $tplIndex : $this->tplIndex); + if (isset($this->childRoot[ $name ])) { + $block->child = $this->childRoot[ $name ]; + } + if ($this->state == 1) { + $this->childRoot[ $name ] = $block; + return; + } + // make sure we got child block of child template of current block + while ($block->child && $block->tplIndex <= $block->child->tplIndex) { + $block->child = $block->child->child; + } + $this->process($tpl, $block); + } + + /** + * Goto child block or render this + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * @param \Smarty_Internal_Block|null $parent + * + * @throws \SmartyException + */ + public function process(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, + Smarty_Internal_Block $parent = null) + { + if ($block->hide && !isset($block->child)) { + return; + } + if (isset($block->child) && $block->child->hide && !isset($block->child->child)) { + $block->child = null; + } + $block->parent = $parent; + if ($block->append && !$block->prepend && isset($parent)) { + $this->callParent($tpl, $block); + } + if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) { + $this->callBlock($block, $tpl); + } else { + $this->process($tpl, $block->child, $block); + } + if ($block->prepend && isset($parent)) { + $this->callParent($tpl, $block); + if ($block->append) { + if ($block->callsChild || !isset($block->child) || + ($block->child->hide && !isset($block->child->child)) + ) { + $this->callBlock($block, $tpl); + } else { + $this->process($tpl, $block->child, $block); + } + } + } + $block->parent = null; + } + + /** + * Render child on {$smarty.block.child} + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + */ + public function callChild(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block) + { + if (isset($block->child)) { + $this->process($tpl, $block->child, $block); + } + } + + /** + * Render parent on {$smarty.block.parent} or {block append/prepend} * + * + * @param \Smarty_Internal_Template $tpl + * @param \Smarty_Internal_Block $block + * + * @param null $name + * + * @throws \SmartyException + */ + public function callParent(Smarty_Internal_Template $tpl, Smarty_Internal_Block $block, $name = null) + { + if (isset($name)) { + $block = $block->parent; + while (isset($block)) { + if (isset($block->subBlocks[ $name ])) { + } else { + $block = $block->parent; + } + } + return; + } else if (isset($block->parent)) { + $this->callBlock($block->parent, $tpl); + } else { + throw new SmartyException("inheritance: illegal {\$smarty.block.parent} or {block append/prepend} used in parent template '{$tpl->inheritance->sources[$block->tplIndex]->filepath}' block '{$block->name}'"); + } + } + + /** + * @param \Smarty_Internal_Block $block + * @param \Smarty_Internal_Template $tpl + */ + public function callBlock(Smarty_Internal_Block $block, Smarty_Internal_Template $tpl) + { + $this->sourceStack[] = $tpl->source; + $tpl->source = $this->sources[ $block->tplIndex ]; + $block->callBlock($tpl); + $tpl->source = array_pop($this->sourceStack); + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_make_nocache.php b/libs/sysplugins/smarty_internal_runtime_make_nocache.php new file mode 100644 index 0000000..6538277 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_make_nocache.php @@ -0,0 +1,56 @@ +tpl_vars[ $var ])) { + $export = + preg_replace('/^Smarty_Variable::__set_state[(]|[)]$/', '', var_export($tpl->tpl_vars[ $var ], true)); + if (preg_match('/(\w+)::__set_state/', $export, $match)) { + throw new SmartyException("{make_nocache \${$var}} in template '{$tpl->source->name}': variable does contain object '{$match[1]}' not implementing method '__set_state'"); + } + echo "/*%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/smarty->ext->_make_nocache->store(\$_smarty_tpl, '{$var}', ", '\\') . + $export . ");?>\n/*/%%SmartyNocache:{$tpl->compiled->nocache_hash}%%*/"; + } + } + + /** + * Store variable value saved while rendering compiled template in cached template context + * + * @param \Smarty_Internal_Template $tpl + * @param string $var variable name + * @param array $properties + */ + public function store(Smarty_Internal_Template $tpl, $var, $properties) + { + // do not overwrite existing nocache variables + if (!isset($tpl->tpl_vars[ $var ]) || !$tpl->tpl_vars[ $var ]->nocache) { + $newVar = new Smarty_Variable(); + unset($properties[ 'nocache' ]); + foreach ($properties as $k => $v) { + $newVar->$k = $v; + } + $tpl->tpl_vars[ $var ] = $newVar; + } + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_tplfunction.php b/libs/sysplugins/smarty_internal_runtime_tplfunction.php new file mode 100644 index 0000000..f6b36f2 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_tplfunction.php @@ -0,0 +1,171 @@ +tplFunctions[ $name ]) ? $tpl->tplFunctions[ $name ] : + (isset($tpl->smarty->tplFunctions[ $name ]) ? $tpl->smarty->tplFunctions[ $name ] : null); + if (isset($funcParam)) { + if (!$tpl->caching || ($tpl->caching && $nocache)) { + $function = $funcParam[ 'call_name' ]; + } else { + if (isset($funcParam[ 'call_name_caching' ])) { + $function = $funcParam[ 'call_name_caching' ]; + } else { + $function = $funcParam[ 'call_name' ]; + } + } + if (function_exists($function)) { + $this->saveTemplateVariables($tpl, $name); + $function ($tpl, $params); + $this->restoreTemplateVariables($tpl, $name); + return; + } + // try to load template function dynamically + if ($this->addTplFuncToCache($tpl, $name, $function)) { + $this->saveTemplateVariables($tpl, $name); + $function ($tpl, $params); + $this->restoreTemplateVariables($tpl, $name); + return; + } + } + throw new SmartyException("Unable to find template function '{$name}'"); + } + + /** + * Register template functions defined by template + * + * @param \Smarty|\Smarty_Internal_Template|\Smarty_Internal_TemplateBase $obj + * @param array $tplFunctions source information array of template functions defined in template + * @param bool $override if true replace existing functions with same name + */ + public function registerTplFunctions(Smarty_Internal_TemplateBase $obj, $tplFunctions, $override = true) + { + $obj->tplFunctions = + $override ? array_merge($obj->tplFunctions, $tplFunctions) : array_merge($tplFunctions, $obj->tplFunctions); + // make sure that the template functions are known in parent templates + if ($obj->_isSubTpl()) { + $obj->smarty->ext->_tplFunction->registerTplFunctions($obj->parent, $tplFunctions, false); + } else { + $obj->smarty->tplFunctions = $override ? array_merge($obj->smarty->tplFunctions, $tplFunctions) : + array_merge($tplFunctions, $obj->smarty->tplFunctions); + } + } + + /** + * Return source parameter array for single or all template functions + * + * @param \Smarty_Internal_Template $tpl template object + * @param null|string $name template function name + * + * @return array|bool|mixed + */ + public function getTplFunction(Smarty_Internal_Template $tpl, $name = null) + { + if (isset($name)) { + return isset($tpl->tplFunctions[ $name ]) ? $tpl->tplFunctions[ $name ] : + (isset($tpl->smarty->tplFunctions[ $name ]) ? $tpl->smarty->tplFunctions[ $name ] : false); + } else { + return empty($tpl->tplFunctions) ? $tpl->smarty->tplFunctions : $tpl->tplFunctions; + } + } + + /** + * + * Add template function to cache file for nocache calls + * + * @param Smarty_Internal_Template $tpl + * @param string $_name template function name + * @param string $_function PHP function name + * + * @return bool + */ + public function addTplFuncToCache(Smarty_Internal_Template $tpl, $_name, $_function) + { + $funcParam = $tpl->tplFunctions[ $_name ]; + if (is_file($funcParam[ 'compiled_filepath' ])) { + // read compiled file + $code = file_get_contents($funcParam[ 'compiled_filepath' ]); + // grab template function + if (preg_match("/\/\* {$_function} \*\/([\S\s]*?)\/\*\/ {$_function} \*\//", $code, $match)) { + // grab source info from file dependency + preg_match("/\s*'{$funcParam['uid']}'([\S\s]*?)\),/", $code, $match1); + unset($code); + // make PHP function known + eval($match[ 0 ]); + if (function_exists($_function)) { + // search cache file template + $tplPtr = $tpl; + while (!isset($tplPtr->cached) && isset($tplPtr->parent)) { + $tplPtr = $tplPtr->parent; + } + // add template function code to cache file + if (isset($tplPtr->cached)) { + /* @var Smarty_Template_Cached $cache */ + $cache = $tplPtr->cached; + $content = $cache->read($tplPtr); + if ($content) { + // check if we must update file dependency + if (!preg_match("/'{$funcParam['uid']}'(.*?)'nocache_hash'/", $content, $match2)) { + $content = preg_replace("/('file_dependency'(.*?)\()/", "\\1{$match1[0]}", $content); + } + $tplPtr->smarty->ext->_updateCache->write($cache, $tplPtr, + preg_replace('/\s*\?>\s*$/', "\n", $content) . + "\n" . preg_replace(array('/^\s*<\?php\s+/', + '/\s*\?>\s*$/',), "\n", + $match[ 0 ])); + } + } + return true; + } + } + } + return false; + } + + /** + * Save current template variables on stack + * + * @param \Smarty_Internal_Template $tpl + * @param string $name stack name + */ + public function saveTemplateVariables(Smarty_Internal_Template $tpl, $name) + { + $tpl->_cache[ 'varStack' ][] = + array('tpl' => $tpl->tpl_vars, 'config' => $tpl->config_vars, 'name' => "_tplFunction_{$name}"); + } + + /** + * Restore saved variables into template objects + * + * @param \Smarty_Internal_Template $tpl + * @param string $name stack name + */ + public function restoreTemplateVariables(Smarty_Internal_Template $tpl, $name) + { + if (isset($tpl->_cache[ 'varStack' ])) { + $vars = array_pop($tpl->_cache[ 'varStack' ]); + $tpl->tpl_vars = $vars[ 'tpl' ]; + $tpl->config_vars = $vars[ 'config' ]; + } + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_updatecache.php b/libs/sysplugins/smarty_internal_runtime_updatecache.php new file mode 100644 index 0000000..ceee3b7 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_updatecache.php @@ -0,0 +1,165 @@ +hashes[ $_template->compiled->nocache_hash ]); + if (!empty($cached->hashes)) { + $hash_array = array(); + foreach ($cached->hashes as $hash => $foo) { + $hash_array[] = "/{$hash}/"; + } + $content = preg_replace($hash_array, $_template->compiled->nocache_hash, $content); + } + $_template->cached->has_nocache_code = false; + // get text between non-cached items + $cache_split = + preg_split("!/\*%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*/!s", + $content); + // get non-cached items + preg_match_all("!/\*%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*\/(.+?)/\*/%%SmartyNocache:{$_template->compiled->nocache_hash}%%\*/!s", + $content, $cache_parts); + $content = ''; + // loop over items, stitch back together + foreach ($cache_split as $curr_idx => $curr_split) { + // escape PHP tags in template content + $content .= preg_replace('/(<%|%>|<\?php|<\?|\?>|)/', + "\n", $curr_split); + if (isset($cache_parts[ 0 ][ $curr_idx ])) { + $_template->cached->has_nocache_code = true; + $content .= $cache_parts[ 1 ][ $curr_idx ]; + } + } + if (!$no_output_filter && !$_template->cached->has_nocache_code && + (isset($_template->smarty->autoload_filters[ 'output' ]) || + isset($_template->smarty->registered_filters[ 'output' ])) + ) { + $content = $_template->smarty->ext->_filterHandler->runFilter('output', $content, $_template); + } + // write cache file content + $this->writeCachedContent($cached, $_template, $content); + } + + /** + * Cache was invalid , so render from compiled and write to cache + * + * @param \Smarty_Template_Cached $cached + * @param \Smarty_Internal_Template $_template + * @param $no_output_filter + * + * @throws \Exception + */ + public function updateCache(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template, $no_output_filter) + { + ob_start(); + if (!isset($_template->compiled)) { + $_template->loadCompiled(); + } + $_template->compiled->render($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + $this->removeNoCacheHash($cached, $_template, $no_output_filter); + $compile_check = $_template->smarty->compile_check; + $_template->smarty->compile_check = false; + if ($_template->_isSubTpl()) { + $_template->compiled->unifunc = $_template->parent->compiled->unifunc; + } + if (!$_template->cached->processed) { + $_template->cached->process($_template, true); + } + $_template->smarty->compile_check = $compile_check; + $cached->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + } + + /** + * Writes the content to cache resource + * + * @param \Smarty_Template_Cached $cached + * @param Smarty_Internal_Template $_template + * @param string $content + * + * @return bool + */ + public function writeCachedContent(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template, $content) + { + if ($_template->source->handler->recompiled || !($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || + $_template->caching == Smarty::CACHING_LIFETIME_SAVED) + ) { + // don't write cache file + return false; + } + $content = $_template->smarty->ext->_codeFrame->create($_template, $content, '', true); + return $this->write($cached, $_template, $content); + } + + /** + * Write this cache object to handler + * + * @param \Smarty_Template_Cached $cached + * @param Smarty_Internal_Template $_template template object + * @param string $content content to cache + * + * @return bool success + */ + public function write(Smarty_Template_Cached $cached, Smarty_Internal_Template $_template, $content) + { + if (!$_template->source->handler->recompiled) { + if ($cached->handler->writeCachedContent($_template, $content)) { + $cached->content = null; + $cached->timestamp = time(); + $cached->exists = true; + $cached->valid = true; + $cached->cache_lifetime = $_template->cache_lifetime; + $cached->processed = false; + if ($_template->smarty->cache_locking) { + $cached->handler->releaseLock($_template->smarty, $cached); + } + + return true; + } + $cached->content = null; + $cached->timestamp = false; + $cached->exists = false; + $cached->valid = false; + $cached->processed = false; + } + + return false; + } + +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_runtime_updatescope.php b/libs/sysplugins/smarty_internal_runtime_updatescope.php new file mode 100644 index 0000000..2d62c60 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_updatescope.php @@ -0,0 +1,115 @@ +_updateVarStack($tpl, $varName); + $tagScope = $tagScope & ~Smarty::SCOPE_LOCAL; + if (!$tpl->scope && !$tagScope) return; + } + $mergedScope = $tagScope | $tpl->scope; + if ($mergedScope) { + if ($mergedScope & Smarty::SCOPE_GLOBAL && $varName) { + Smarty::$global_tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ]; + } + // update scopes + foreach ($this->_getAffectedScopes($tpl, $mergedScope) as $ptr) { + $this->_updateVariableInOtherScope($ptr->tpl_vars, $tpl, $varName); + if($tagScope && $ptr->_isTplObj() && isset($tpl->_cache[ 'varStack' ])) { + $this->_updateVarStack($ptr, $varName); } + } + } + } + + /** + * Get array of objects which needs to be updated by given scope value + * + * @param Smarty_Internal_Template $tpl + * @param int $mergedScope merged tag and template scope to which bubble up variable value + * + * @return array + */ + public function _getAffectedScopes(Smarty_Internal_Template $tpl, $mergedScope) + { + $_stack = array(); + $ptr = $tpl->parent; + if ($mergedScope && isset($ptr) && $ptr->_isTplObj()) { + $_stack[] = $ptr; + $mergedScope = $mergedScope & ~Smarty::SCOPE_PARENT; + if (!$mergedScope) { + // only parent was set, we are done + return $_stack; + } + $ptr = $ptr->parent; + } + while (isset($ptr) && $ptr->_isTplObj()) { + $_stack[] = $ptr; + $ptr = $ptr->parent; + } + if ($mergedScope & Smarty::SCOPE_SMARTY) { + if (isset($tpl->smarty)) { + $_stack[] = $tpl->smarty; + } + } elseif ($mergedScope & Smarty::SCOPE_ROOT) { + while (isset($ptr)) { + if (!$ptr->_isTplObj()) { + $_stack[] = $ptr; + break; + } + $ptr = $ptr->parent; + } + } + return $_stack; + } + + /** + * Update variable in other scope + * + * @param array $tpl_vars template variable array + * @param \Smarty_Internal_Template $from + * @param string $varName variable name + */ + public function _updateVariableInOtherScope(&$tpl_vars, Smarty_Internal_Template $from, $varName) + { + if (!isset($tpl_vars[ $varName ])) { + $tpl_vars[ $varName ] = clone $from->tpl_vars[ $varName ]; + } else { + $tpl_vars[ $varName ] = clone $tpl_vars[ $varName ]; + $tpl_vars[ $varName ]->value = $from->tpl_vars[ $varName ]->value; + } + } + + /** + * Update variable in template local variable stack + * + * @param \Smarty_Internal_Template $tpl + * @param string|null $varName variable name or null for config variables + */ + public function _updateVarStack(Smarty_Internal_Template $tpl, $varName) + { + $i = 0; + while (isset($tpl->_cache[ 'varStack' ][ $i ])) { + $this->_updateVariableInOtherScope($tpl->_cache[ 'varStack' ][ $i ][ 'tpl' ], $tpl, $varName); + $i ++; + } + } +} diff --git a/libs/sysplugins/smarty_internal_runtime_writefile.php b/libs/sysplugins/smarty_internal_runtime_writefile.php new file mode 100644 index 0000000..ffa0b51 --- /dev/null +++ b/libs/sysplugins/smarty_internal_runtime_writefile.php @@ -0,0 +1,105 @@ +_file_perms : 0644; + $_dir_perms = + property_exists($smarty, '_dir_perms') ? (isset($smarty->_dir_perms) ? $smarty->_dir_perms : 0777) : 0771; + if ($_file_perms !== null) { + $old_umask = umask(0); + } + + $_dirpath = dirname($_filepath); + + // if subdirs, create dir structure + if ($_dirpath !== '.') { + $i=0; + // loop if concurrency problem occurs + // see https://bugs.php.net/bug.php?id=35326 + while (!is_dir($_dirpath)) { + if (@mkdir($_dirpath, $_dir_perms, true)) { + break; + } + clearstatcache(); + if (++$i === 3) { + error_reporting($_error_reporting); + throw new SmartyException("unable to create directory {$_dirpath}"); + } + sleep(1); + } + } + + // write to tmp file, then move to overt file lock race condition + $_tmp_file = $_dirpath . $smarty->ds . str_replace(array('.', ','), '_', uniqid('wrt', true)); + if (!file_put_contents($_tmp_file, $_contents)) { + error_reporting($_error_reporting); + throw new SmartyException("unable to write file {$_tmp_file}"); + } + + /* + * Windows' rename() fails if the destination exists, + * Linux' rename() properly handles the overwrite. + * Simply unlink()ing a file might cause other processes + * currently reading that file to fail, but linux' rename() + * seems to be smart enough to handle that for us. + */ + if (Smarty::$_IS_WINDOWS) { + // remove original file + if (is_file($_filepath)) { + @unlink($_filepath); + } + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } else { + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + if (!$success) { + // remove original file + if (is_file($_filepath)) { + @unlink($_filepath); + } + // rename tmp file + $success = @rename($_tmp_file, $_filepath); + } + } + if (!$success) { + error_reporting($_error_reporting); + throw new SmartyException("unable to write file {$_filepath}"); + } + if ($_file_perms !== null) { + // set file permissions + chmod($_filepath, $_file_perms); + umask($old_umask); + } + error_reporting($_error_reporting); + + return true; + } +} diff --git a/libs/sysplugins/smarty_internal_smartytemplatecompiler.php b/libs/sysplugins/smarty_internal_smartytemplatecompiler.php new file mode 100644 index 0000000..bdf7406 --- /dev/null +++ b/libs/sysplugins/smarty_internal_smartytemplatecompiler.php @@ -0,0 +1,174 @@ +lexer_class = $lexer_class; + $this->parser_class = $parser_class; + } + + /** + * method to compile a Smarty template + * + * @param mixed $_content template source + * @param bool $isTemplateSource + * + * @return bool true if compiling succeeded, false if it failed + * @throws \SmartyCompilerException + */ + protected function doCompile($_content, $isTemplateSource = false) + { + /* here is where the compiling takes place. Smarty + tags in the templates are replaces with PHP code, + then written to compiled files. */ + // init the lexer/parser to compile the template + $this->parser = + new $this->parser_class(new $this->lexer_class(str_replace(array("\r\n", + "\r"), "\n", $_content), $this), + $this); + if ($isTemplateSource && $this->template->caching) { + $this->parser->insertPhpCode("compiled->nocache_hash = '{$this->nocache_hash}';\n?>\n"); + } + if (function_exists('mb_internal_encoding') + && function_exists('ini_get') + && ((int) ini_get('mbstring.func_overload')) & 2 + ) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } else { + $mbEncoding = null; + } + + if ($this->smarty->_parserdebug) { + $this->parser->PrintTrace(); + $this->parser->lex->PrintTrace(); + } + // get tokens from lexer and parse them + while ($this->parser->lex->yylex()) { + if ($this->smarty->_parserdebug) { + echo "
Line {$this->parser->lex->line} Parsing  {$this->parser->yyTokenName[$this->parser->lex->token]} Token " .
+                     htmlentities($this->parser->lex->value) . "
"; + } + $this->parser->doParse($this->parser->lex->token, $this->parser->lex->value); + } + + // finish parsing process + $this->parser->doParse(0, 0); + if ($mbEncoding) { + mb_internal_encoding($mbEncoding); + } + // check for unclosed tags + if (count($this->_tag_stack) > 0) { + // get stacked info + list($openTag, $_data) = array_pop($this->_tag_stack); + $this->trigger_template_error("unclosed {$this->smarty->left_delimiter}" . $openTag . + "{$this->smarty->right_delimiter} tag"); + } + // call post compile callbacks + foreach ($this->postCompileCallbacks as $cb) { + $parameter = $cb; + $parameter[ 0 ] = $this; + call_user_func_array($cb[ 0 ], $parameter); + } + // return compiled code + return $this->prefixCompiledCode . $this->parser->retvalue . $this->postfixCompiledCode; + } + + /** + * Register a post compile callback + * - when the callback is called after template compiling the compiler object will be inserted as first parameter + * + * @param callback $callback + * @param array $parameter optional parameter array + * @param string $key optional key for callback + * @param bool $replace if true replace existing keyed callback + * + */ + public function registerPostCompileCallback($callback, $parameter = array(), $key = null, $replace = false) + { + array_unshift($parameter, $callback); + if (isset($key)) { + if ($replace || !isset($this->postCompileCallbacks[ $key ])) { + $this->postCompileCallbacks[ $key ] = $parameter; + } + } else { + $this->postCompileCallbacks[] = $parameter; + } + } + + /** + * Remove a post compile callback + * + * @param string $key callback key + */ + public function unregisterPostCompileCallback($key) + { + unset($this->postCompileCallbacks[ $key ]); + } +} diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php new file mode 100644 index 0000000..f950606 --- /dev/null +++ b/libs/sysplugins/smarty_internal_template.php @@ -0,0 +1,692 @@ +smarty = $smarty; + // Smarty parameter + $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id; + $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id; + $this->caching = $_caching === null ? $this->smarty->caching : $_caching; + if ($this->caching === true) { + $this->caching = Smarty::CACHING_LIFETIME_CURRENT; + } + $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime; + $this->parent = $_parent; + // Template resource + $this->template_resource = $template_resource; + $this->source = $_isConfig ? Smarty_Template_Config::load($this) : Smarty_Template_Source::load($this); + parent::__construct(); + if ($smarty->security_policy && method_exists($smarty->security_policy, 'registerCallBacks')) { + $smarty->security_policy->registerCallBacks($this); + } + } + + /** + * render template + * + * @param bool $no_output_filter if true do not run output filter + * @param null|bool $display true: display, false: fetch null: sub-template + * + * @return string + * @throws \SmartyException + */ + public function render($no_output_filter = true, $display = null) + { + if ($this->smarty->debugging) { + if (!isset($this->smarty->_debug)) { + $this->smarty->_debug = new Smarty_Internal_Debug(); + } + $this->smarty->_debug->start_template($this, $display); + } + // checks if template exists + if (!$this->source->exists) { + throw new SmartyException("Unable to load template '{$this->source->type}:{$this->source->name}'" . + ($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : '')); + } + // disable caching for evaluated code + if ($this->source->handler->recompiled) { + $this->caching = false; + } + // read from cache or render + $isCacheTpl = + $this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED; + if ($isCacheTpl) { + if (!isset($this->cached) || $this->cached->cache_id !== $this->cache_id || + $this->cached->compile_id !== $this->compile_id + ) { + $this->loadCached(true); + } + $this->cached->render($this, $no_output_filter); + } else { + if (!isset($this->compiled) || $this->compiled->compile_id !== $this->compile_id) { + $this->loadCompiled(true); + } + $this->compiled->render($this); + } + + // display or fetch + if ($display) { + if ($this->caching && $this->smarty->cache_modified_check) { + $this->smarty->ext->_cacheModify->cacheModifiedCheck($this->cached, $this, + isset($content) ? $content : ob_get_clean()); + } else { + if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) && + !$no_output_filter && (isset($this->smarty->autoload_filters[ 'output' ]) || + isset($this->smarty->registered_filters[ 'output' ])) + ) { + echo $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); + } else { + echo ob_get_clean(); + } + } + if ($this->smarty->debugging) { + $this->smarty->_debug->end_template($this); + // debug output + $this->smarty->_debug->display_debug($this, true); + } + return ''; + } else { + if ($this->smarty->debugging) { + $this->smarty->_debug->end_template($this); + if ($this->smarty->debugging === 2 && $display === false) { + $this->smarty->_debug->display_debug($this, true); + } + } + if ($this->_isSubTpl()) { + foreach ($this->compiled->required_plugins as $code => $tmp1) { + foreach ($tmp1 as $name => $tmp) { + foreach ($tmp as $type => $data) { + $this->parent->compiled->required_plugins[ $code ][ $name ][ $type ] = $data; + } + } + } + } + if (!$no_output_filter && + (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) && + (isset($this->smarty->autoload_filters[ 'output' ]) || + isset($this->smarty->registered_filters[ 'output' ])) + ) { + return $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); + } + // return cache content + return null; + } + } + + /** + * Runtime function to render sub-template + * + * @param string $template template name + * @param mixed $cache_id cache id + * @param mixed $compile_id compile id + * @param integer $caching cache mode + * @param integer $cache_lifetime life time of cache data + * @param array $data passed parameter template variables + * @param int $scope scope in which {include} should execute + * @param bool $forceTplCache cache template object + * @param string $uid file dependency uid + * @param string $content_func function name + * + */ + public function _subTemplateRender($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope, + $forceTplCache, $uid = null, $content_func = null) + { + $tpl = clone $this; + $tpl->parent = $this; + $smarty = &$this->smarty; + $_templateId = $smarty->_getTemplateId($template, $cache_id, $compile_id, $caching, $tpl); + // recursive call ? + if (isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId() != $_templateId) { + // already in template cache? + if (isset(self::$tplObjCache[ $_templateId ])) { + // copy data from cached object + $cachedTpl = &self::$tplObjCache[ $_templateId ]; + $tpl->templateId = $cachedTpl->templateId; + $tpl->template_resource = $cachedTpl->template_resource; + $tpl->cache_id = $cachedTpl->cache_id; + $tpl->compile_id = $cachedTpl->compile_id; + $tpl->source = $cachedTpl->source; + if (isset($cachedTpl->compiled)) { + $tpl->compiled = $cachedTpl->compiled; + } else { + unset($tpl->compiled); + } + if ($caching != 9999 && isset($cachedTpl->cached)) { + $tpl->cached = $cachedTpl->cached; + } else { + unset($tpl->cached); + } + } else { + $tpl->templateId = $_templateId; + $tpl->template_resource = $template; + $tpl->cache_id = $cache_id; + $tpl->compile_id = $compile_id; + if (isset($uid)) { + // for inline templates we can get all resource information from file dependency + list($filepath, $timestamp, $type) = $tpl->compiled->file_dependency[ $uid ]; + $tpl->source = new Smarty_Template_Source($smarty, $filepath, $type, $filepath); + $tpl->source->filepath = $filepath; + $tpl->source->timestamp = $timestamp; + $tpl->source->exists = true; + $tpl->source->uid = $uid; + } else { + $tpl->source = Smarty_Template_Source::load($tpl); + unset($tpl->compiled); + } + if ($caching != 9999) { + unset($tpl->cached); + } + } + } else { + // on recursive calls force caching + $forceTplCache = true; + } + $tpl->caching = $caching; + $tpl->cache_lifetime = $cache_lifetime; + // set template scope + $tpl->scope = $scope; + if (!isset(self::$tplObjCache[ $tpl->templateId ]) && !$tpl->source->handler->recompiled) { + // check if template object should be cached + if ($forceTplCache || (isset(self::$subTplInfo[ $tpl->template_resource ]) && + self::$subTplInfo[ $tpl->template_resource ] > 1) || + ($tpl->_isSubTpl() && isset(self::$tplObjCache[ $tpl->parent->templateId ])) + ) { + self::$tplObjCache[ $tpl->templateId ] = $tpl; + } + } + + if (!empty($data)) { + // set up variable values + foreach ($data as $_key => $_val) { + $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val, $this->isRenderingCache); + } + } + if ($tpl->caching == 9999) { + if (!isset($tpl->compiled)) { + $this->loadCompiled(true); + } + if ($tpl->compiled->has_nocache_code) { + $this->cached->hashes[ $tpl->compiled->nocache_hash ] = true; + } + } + $tpl->_cache = array(); + if (isset($uid)) { + if ($smarty->debugging) { + if (!isset($smarty->_debug)) { + $smarty->_debug = new Smarty_Internal_Debug(); + } + $smarty->_debug->start_template($tpl); + $smarty->_debug->start_render($tpl); + } + $tpl->compiled->getRenderedTemplateCode($tpl, $content_func); + if ($smarty->debugging) { + $smarty->_debug->end_template($tpl); + $smarty->_debug->end_render($tpl); + } + } else { + if (isset($tpl->compiled)) { + $tpl->compiled->render($tpl); + } else { + $tpl->render(); + } + } + } + + /** + * Get called sub-templates and save call count + * + */ + public function _subTemplateRegister() + { + foreach ($this->compiled->includes as $name => $count) { + if (isset(self::$subTplInfo[ $name ])) { + self::$subTplInfo[ $name ] += $count; + } else { + self::$subTplInfo[ $name ] = $count; + } + } + } + + /** + * Check if this is a sub template + * + * @return bool true is sub template + */ + public function _isSubTpl() + { + return isset($this->parent) && $this->parent->_isTplObj(); + } + + /** + * Assign variable in scope + * + * @param string $varName variable name + * @param mixed $value value + * @param bool $nocache nocache flag + * @param int $scope scope into which variable shall be assigned + * + */ + public function _assignInScope($varName, $value, $nocache = false, $scope = 0) + { + if (isset($this->tpl_vars[ $varName ])) { + $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ]; + $this->tpl_vars[ $varName ]->value = $value; + if ($nocache || $this->isRenderingCache) { + $this->tpl_vars[ $varName ]->nocache = true; + } + } else { + $this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache || $this->isRenderingCache); + } + if ($scope >= 0) { + if ($scope > 0 || $this->scope > 0) { + $this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope); + } + } + } + + /** + * This function is executed automatically when a compiled or cached template file is included + * - Decode saved properties from compiled template and cache files + * - Check if compiled or cache file is valid + * + * @param \Smarty_Internal_Template $tpl + * @param array $properties special template properties + * @param bool $cache flag if called from cache file + * + * @return bool flag if compiled or cache file is valid + * @throws \SmartyException + */ + public function _decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false) + { + // on cache resources other than file check version stored in cache code + if (!isset($properties[ 'version' ]) || Smarty::SMARTY_VERSION !== $properties[ 'version' ]) { + if ($cache) { + $tpl->smarty->clearAllCache(); + } else { + $tpl->smarty->clearCompiledTemplate(); + } + return false; + } + $is_valid = true; + if (!empty($properties[ 'file_dependency' ]) && + ((!$cache && $tpl->smarty->compile_check) || $tpl->smarty->compile_check == 1) + ) { + // check file dependencies at compiled code + foreach ($properties[ 'file_dependency' ] as $_file_to_check) { + if ($_file_to_check[ 2 ] == 'file' || $_file_to_check[ 2 ] == 'php') { + if ($tpl->source->filepath == $_file_to_check[ 0 ]) { + // do not recheck current template + continue; + //$mtime = $tpl->source->getTimeStamp(); + } else { + // file and php types can be checked without loading the respective resource handlers + $mtime = is_file($_file_to_check[ 0 ]) ? filemtime($_file_to_check[ 0 ]) : false; + } + } else { + $handler = Smarty_Resource::load($tpl->smarty, $_file_to_check[ 2 ]); + if ($handler->checkTimestamps()) { + $source = Smarty_Template_Source::load($tpl, $tpl->smarty, $_file_to_check[ 0 ]); + $mtime = $source->getTimeStamp(); + } else { + continue; + } + } + if ($mtime === false || $mtime > $_file_to_check[ 1 ]) { + $is_valid = false; + break; + } + } + } + if ($cache) { + // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc + if ($tpl->caching === Smarty::CACHING_LIFETIME_SAVED && $properties[ 'cache_lifetime' ] >= 0 && + (time() > ($tpl->cached->timestamp + $properties[ 'cache_lifetime' ])) + ) { + $is_valid = false; + } + $tpl->cached->cache_lifetime = $properties[ 'cache_lifetime' ]; + $tpl->cached->valid = $is_valid; + $resource = $tpl->cached; + } else { + $tpl->mustCompile = !$is_valid; + $resource = $tpl->compiled; + $resource->includes = isset($properties[ 'includes' ]) ? $properties[ 'includes' ] : array(); + } + if ($is_valid) { + $resource->unifunc = $properties[ 'unifunc' ]; + $resource->has_nocache_code = $properties[ 'has_nocache_code' ]; + // $tpl->compiled->nocache_hash = $properties['nocache_hash']; + $resource->file_dependency = $properties[ 'file_dependency' ]; + } + return $is_valid && !function_exists($properties[ 'unifunc' ]); + } + + /** + * Compiles the template + * If the template is not evaluated the compiled template is saved on disk + */ + public function compileTemplateSource() + { + return $this->compiled->compileTemplateSource($this); + } + + /** + * Writes the content to cache resource + * + * @param string $content + * + * @return bool + */ + public function writeCachedContent($content) + { + return $this->smarty->ext->_updateCache->writeCachedContent($this->cached, $this, $content); + } + + /** + * Get unique template id + * + * @return string + */ + public function _getTemplateId() + { + return isset($this->templateId) ? $this->templateId : $this->templateId = + $this->smarty->_getTemplateId($this->template_resource, $this->cache_id, $this->compile_id); + } + + /** + * runtime error not matching capture tags + */ + public function capture_error() + { + throw new SmartyException("Not matching {capture} open/close in \"{$this->template_resource}\""); + } + + /** + * Load compiled object + * + * @param bool $force force new compiled object + */ + public function loadCompiled($force = false) + { + if ($force || !isset($this->compiled)) { + $this->compiled = Smarty_Template_Compiled::load($this); + } + } + + /** + * Load cached object + * + * @param bool $force force new cached object + */ + public function loadCached($force = false) + { + if ($force || !isset($this->cached)) { + $this->cached = Smarty_Template_Cached::load($this); + } + } + + /** + * Load inheritance object + * + */ + public function _loadInheritance() + { + if (!isset($this->inheritance)) { + $this->inheritance = new Smarty_Internal_Runtime_Inheritance(); + } + } + + /** + * Unload inheritance object + * + */ + public function _cleanUp() + { + $this->startRenderCallbacks = array(); + $this->endRenderCallbacks = array(); + $this->inheritance = null; + } + + /** + * Load compiler object + * + * @throws \SmartyException + */ + public function loadCompiler() + { + if (!class_exists($this->source->compiler_class)) { + $this->smarty->loadPlugin($this->source->compiler_class); + } + $this->compiler = + new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, + $this->smarty); + } + + /** + * Handle unknown class methods + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed + * @throws SmartyException + */ + public function __call($name, $args) + { + // method of Smarty object? + if (method_exists($this->smarty, $name)) { + return call_user_func_array(array($this->smarty, $name), $args); + } + // parent + return parent::__call($name, $args); + } + + /** + * set Smarty property in template context + * + * @param string $property_name property name + * @param mixed $value value + * + * @throws SmartyException + */ + public function __set($property_name, $value) + { + switch ($property_name) { + case 'compiled': + case 'cached': + case 'compiler': + $this->$property_name = $value; + return; + default: + // Smarty property ? + if (property_exists($this->smarty, $property_name)) { + $this->smarty->$property_name = $value; + return; + } + } + throw new SmartyException("invalid template property '$property_name'."); + } + + /** + * get Smarty property in template context + * + * @param string $property_name property name + * + * @return mixed|Smarty_Template_Cached + * @throws SmartyException + */ + public function __get($property_name) + { + switch ($property_name) { + case 'compiled': + $this->loadCompiled(); + return $this->compiled; + + case 'cached': + $this->loadCached(); + return $this->cached; + + case 'compiler': + $this->loadCompiler(); + return $this->compiler; + default: + // Smarty property ? + if (property_exists($this->smarty, $property_name)) { + return $this->smarty->$property_name; + } + } + throw new SmartyException("template property '$property_name' does not exist."); + } + + /** + * Template data object destructor + */ + public function __destruct() + { + if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) { + $this->cached->handler->releaseLock($this->smarty, $this->cached); + } + } +} diff --git a/libs/sysplugins/smarty_internal_templatebase.php b/libs/sysplugins/smarty_internal_templatebase.php new file mode 100644 index 0000000..1a5285e --- /dev/null +++ b/libs/sysplugins/smarty_internal_templatebase.php @@ -0,0 +1,354 @@ +_execute($template, $cache_id, $compile_id, $parent, 0); + return $result === null ? ob_get_clean() : $result; + } + + /** + * 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->_execute($template, $cache_id, $compile_id, $parent, 1); + } + + /** + * test if cache is valid + * + * @api Smarty::isCached() + * @link http://www.smarty.net/docs/en/api.is.cached.tpl + * + * @param null|string|\Smarty_Internal_Template $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) + { + return $this->_execute($template, $cache_id, $compile_id, $parent, 2); + } + + /** + * fetches a rendered 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 + * @param string $function function type 0 = fetch, 1 = display, 2 = isCache + * + * @return mixed + * @throws \Exception + * @throws \SmartyException + */ + private function _execute($template, $cache_id, $compile_id, $parent, $function) + { + $smarty = $this->_getSmartyObj(); + $saveVars = true; + if ($template === null) { + if (!$this->_isTplObj()) { + throw new SmartyException($function . '():Missing \'$template\' parameter'); + } else { + $template = $this; + } + } elseif (is_object($template)) { + /* @var Smarty_Internal_Template $template */ + if (!isset($template->_objType) || !$template->_isTplObj()) { + throw new SmartyException($function . '():Template object expected'); + } + } else { + // get template object + $saveVars = false; + + $template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent ? $parent : $this, false); + if ($this->_objType == 1) { + // set caching in template object + $template->caching = $this->caching; + } + } + // fetch template content + $level = ob_get_level(); + try { + $_smarty_old_error_level = + isset($smarty->error_reporting) ? error_reporting($smarty->error_reporting) : null; + if ($this->_objType == 2) { + /* @var Smarty_Internal_Template $this */ + $template->tplFunctions = $this->tplFunctions; + $template->inheritance = $this->inheritance; + } + /* @var Smarty_Internal_Template $parent */ + if (isset($parent->_objType) && ($parent->_objType == 2) && !empty($parent->tplFunctions)) { + $template->tplFunctions = array_merge($parent->tplFunctions, $template->tplFunctions); + } + if ($function == 2) { + if ($template->caching) { + // return cache status of template + if (!isset($template->cached)) { + $template->loadCached(); + } + $result = $template->cached->isCached($template); + Smarty_Internal_Template::$isCacheTplObj[ $template->_getTemplateId() ] = $template; + } else { + return false; + } + } else { + if ($saveVars) { + $savedTplVars = $template->tpl_vars; + $savedConfigVars = $template->config_vars; + } + ob_start(); + $template->_mergeVars(); + if (!empty(Smarty::$global_tpl_vars)) { + $template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars); + } + $result = $template->render(false, $function); + $template->_cleanUp(); + if ($saveVars) { + $template->tpl_vars = $savedTplVars; + $template->config_vars = $savedConfigVars; + } else { + if (!$function && !isset(Smarty_Internal_Template::$tplObjCache[ $template->templateId ])) { + $template->parent = null; + $template->tpl_vars = $template->config_vars = array(); + Smarty_Internal_Template::$tplObjCache[ $template->templateId ] = $template; + } + } + } + if (isset($_smarty_old_error_level)) { + error_reporting($_smarty_old_error_level); + } + return $result; + } + catch (Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + if (isset($_smarty_old_error_level)) { + error_reporting($_smarty_old_error_level); + } + throw $e; + } + } + + /** + * Registers plugin to be used in templates + * + * @api Smarty::registerPlugin() + * @link http://www.smarty.net/docs/en/api.register.plugin.tpl + * + * @param string $type plugin type + * @param string $name name of template tag + * @param callback $callback PHP callback to register + * @param bool $cacheable if true (default) this function is cache able + * @param mixed $cache_attr caching attributes if any + * + * @return \Smarty|\Smarty_Internal_Template + * @throws SmartyException when the plugin tag is invalid + */ + public function registerPlugin($type, $name, $callback, $cacheable = true, $cache_attr = null) + { + return $this->ext->registerPlugin->registerPlugin($this, $type, $name, $callback, $cacheable, $cache_attr); + } + + /** + * load a filter of specified type and name + * + * @api Smarty::loadFilter() + * @link http://www.smarty.net/docs/en/api.load.filter.tpl + * + * @param string $type filter type + * @param string $name filter name + * + * @return bool + * @throws SmartyException if filter could not be loaded + */ + public function loadFilter($type, $name) + { + return $this->ext->loadFilter->loadFilter($this, $type, $name); + } + + /** + * Registers a filter function + * + * @api Smarty::registerFilter() + * @link http://www.smarty.net/docs/en/api.register.filter.tpl + * + * @param string $type filter type + * @param callback $callback + * @param string|null $name optional filter name + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerFilter($type, $callback, $name = null) + { + return $this->ext->registerFilter->registerFilter($this, $type, $callback, $name); + } + + /** + * Registers object to be used in templates + * + * @api Smarty::registerObject() + * @link http://www.smarty.net/docs/en/api.register.object.tpl + * + * @param string $object_name + * @param object $object the referenced PHP object to register + * @param array $allowed_methods_properties list of allowed methods (empty = all) + * @param bool $format smarty argument format, else traditional + * @param array $block_methods list of block-methods + * + * @return \Smarty|\Smarty_Internal_Template + * @throws \SmartyException + */ + public function registerObject($object_name, $object, $allowed_methods_properties = array(), $format = true, + $block_methods = array()) + { + return $this->ext->registerObject->registerObject($this, $object_name, $object, $allowed_methods_properties, + $format, $block_methods); + } + + /** + * @param boolean $caching + */ + public function setCaching($caching) + { + $this->caching = $caching; + } + + /** + * @param int $cache_lifetime + */ + public function setCacheLifetime($cache_lifetime) + { + $this->cache_lifetime = $cache_lifetime; + } + + /** + * @param string $compile_id + */ + public function setCompileId($compile_id) + { + $this->compile_id = $compile_id; + } + + /** + * @param string $cache_id + */ + public function setCacheId($cache_id) + { + $this->cache_id = $cache_id; + } + +} + diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php new file mode 100644 index 0000000..70c832a --- /dev/null +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -0,0 +1,1394 @@ +smarty = $smarty; + $this->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 + * @param null|Smarty_Internal_TemplateCompilerBase $parent_compiler + * + * @return bool true if compiling succeeded, false if it failed + * @throws \Exception + */ + public function compileTemplate(Smarty_Internal_Template $template, $nocache = null, + Smarty_Internal_TemplateCompilerBase $parent_compiler = null) + { + // get code frame of compiled template + $_compiled_code = $template->smarty->ext->_codeFrame->create($template, + $this->compileTemplateSource($template, $nocache, + $parent_compiler), + $this->postFilter($this->blockOrFunctionCode) . + join('', $this->mergedSubTemplatesCode), false, + $this); + return $_compiled_code; + } + + /** + * Compile template source and run optional post filter + * + * @param \Smarty_Internal_Template $template + * @param null|bool $nocache flag if template must be compiled in nocache mode + * @param \Smarty_Internal_TemplateCompilerBase $parent_compiler + * + * @return string + * @throws \Exception + */ + public function compileTemplateSource(Smarty_Internal_Template $template, $nocache = null, + Smarty_Internal_TemplateCompilerBase $parent_compiler = null) + { + try { + // save template object in compiler class + $this->template = $template; + if (property_exists($this->template->smarty, 'plugin_search_order')) { + $this->plugin_search_order = $this->template->smarty->plugin_search_order; + } + if ($this->smarty->debugging) { + if (!isset($this->smarty->_debug)) { + $this->smarty->_debug = new Smarty_Internal_Debug(); + } + $this->smarty->_debug->start_compile($this->template); + } + if (isset($this->template->smarty->security_policy)) { + $this->php_handling = $this->template->smarty->security_policy->php_handling; + } else { + $this->php_handling = $this->template->smarty->php_handling; + } + $this->parent_compiler = $parent_compiler ? $parent_compiler : $this; + $nocache = isset($nocache) ? $nocache : false; + if (empty($template->compiled->nocache_hash)) { + $template->compiled->nocache_hash = $this->nocache_hash; + } else { + $this->nocache_hash = $template->compiled->nocache_hash; + } + // flag for nocache sections + $this->nocache = $nocache; + $this->tag_nocache = false; + // reset has nocache code flag + $this->template->compiled->has_nocache_code = false; + $this->has_variable_string = false; + $this->prefix_code = array(); + // add file dependency + if ($this->smarty->merge_compiled_includes || $this->template->source->handler->checkTimestamps()) { + $this->parent_compiler->template->compiled->file_dependency[ $this->template->source->uid ] = + array($this->template->source->filepath, + $this->template->source->getTimeStamp(), + $this->template->source->type,); + } + $this->smarty->_current_file = $this->template->source->filepath; + // get template source + if (!empty($this->template->source->components)) { + // we have array of inheritance templates by extends: resource + // generate corresponding source code sequence + $_content = + Smarty_Internal_Compile_Extends::extendsSourceArrayCode($this->template->source->components); + } else { + // get template source + $_content = $this->template->source->getContent(); + } + $_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true)); + } + catch (Exception $e) { + if ($this->smarty->debugging) { + $this->smarty->_debug->end_compile($this->template); + } + $this->_tag_stack = array(); + // free memory + $this->parent_compiler = null; + $this->template = null; + $this->parser = null; + throw $e; + } + if ($this->smarty->debugging) { + $this->smarty->_debug->end_compile($this->template); + } + $this->parent_compiler = null; + $this->parser = null; + return $_compiled_code; + } + + /** + * Optionally process compiled code by post filter + * + * @param string $code compiled code + * + * @return string + * @throws \SmartyException + */ + public function postFilter($code) + { + // run post filter if on code + if (!empty($code) && + (isset($this->smarty->autoload_filters[ 'post' ]) || isset($this->smarty->registered_filters[ 'post' ])) + ) { + return $this->smarty->ext->_filterHandler->runFilter('post', $code, $this->template); + } else { + return $code; + } + } + + /** + * Run optional prefilter + * + * @param string $_content template source + * + * @return string + * @throws \SmartyException + */ + public function preFilter($_content) + { + // run pre filter if required + if ($_content !== '' && + ((isset($this->smarty->autoload_filters[ 'pre' ]) || isset($this->smarty->registered_filters[ 'pre' ]))) + ) { + return $this->smarty->ext->_filterHandler->runFilter('pre', $_content, $this->template); + } else { + return $_content; + } + } + + /** + * Compile Tag + * This is a call back from the lexer/parser + * + * Save current prefix code + * Compile tag + * Merge tag prefix code with saved one + * (required nested tags in attributes) + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * + * @throws SmartyCompilerException + * @throws SmartyException + * @return string compiled code + */ + public function compileTag($tag, $args, $parameter = array()) + { + $this->prefixCodeStack[] = $this->prefix_code; + $this->prefix_code = array(); + $result = $this->compileTag2($tag, $args, $parameter); + $this->prefix_code = array_merge($this->prefix_code, array_pop($this->prefixCodeStack)); + return $result; + } + + /** + * Compile Tag + * + * @param string $tag tag name + * @param array $args array with tag attributes + * @param array $parameter array with compilation parameter + * + * @throws SmartyCompilerException + * @throws SmartyException + * @return string compiled code + */ + private function compileTag2($tag, $args, $parameter) + { + $plugin_type = ''; + // $args contains the attributes parsed and compiled by the lexer/parser + // assume that tag does compile into code, but creates no HTML output + $this->has_code = true; + $this->has_output = false; + // log tag/attributes + if (isset($this->smarty->_cache[ 'get_used_tags' ])) { + $this->template->_cache[ 'used_tags' ][] = array($tag, + $args); + } + // check nocache option flag + foreach ($args as $arg) { + if (!is_array($arg)) { + if ($arg === "'nocache'" || $arg === 'nocache') { + $this->tag_nocache = true; + } + } else { + foreach ($arg as $k => $v) { + if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) { + $this->tag_nocache = true; + } + } + } + } + // compile the smarty tag (required compile classes to compile the tag are auto loaded) + if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { + if (isset($this->parent_compiler->tpl_function[ $tag ]) || + (isset ($this->template->smarty->ext->_tplFunction) && + $this->template->smarty->ext->_tplFunction->getTplFunction($this->template, $tag) !== false) + ) { + // template defined by {template} tag + $args[ '_attr' ][ 'name' ] = "'" . $tag . "'"; + $_output = $this->callTagCompiler('call', $args, $parameter); + } + } + if ($_output !== false) { + if ($_output !== true) { + // did we get compiled code + if ($this->has_code) { + // Does it create output? + if ($this->has_output) { + $_output .= "\n"; + } + // return compiled code + return $_output; + } + } + // tag did not produce compiled code + return null; + } else { + // map_named attributes + if (isset($args[ '_attr' ])) { + foreach ($args[ '_attr' ] as $key => $attribute) { + if (is_array($attribute)) { + $args = array_merge($args, $attribute); + } + } + } + // not an internal compiler tag + if (strlen($tag) < 6 || substr($tag, - 5) !== 'close') { + // check if tag is a registered object + if (isset($this->smarty->registered_objects[ $tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (!in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ]) && + (empty($this->smarty->registered_objects[ $tag ][ 1 ]) || + in_array($method, $this->smarty->registered_objects[ $tag ][ 1 ])) + ) { + return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method); + } elseif (in_array($method, $this->smarty->registered_objects[ $tag ][ 3 ])) { + return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, + $method); + } else { + // throw exception + $this->trigger_template_error('not allowed method "' . $method . '" in registered object "' . + $tag . '"', null, true); + } + } + // check if tag is registered + foreach (array(Smarty::PLUGIN_COMPILER, + Smarty::PLUGIN_FUNCTION, + Smarty::PLUGIN_BLOCK,) as $plugin_type) { + if (isset($this->smarty->registered_plugins[ $plugin_type ][ $tag ])) { + // if compiler function plugin call it now + if ($plugin_type === Smarty::PLUGIN_COMPILER) { + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + if (!$this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 1 ]) { + $this->tag_nocache = true; + } + return call_user_func_array($this->smarty->registered_plugins[ $plugin_type ][ $tag ][ 0 ], + array($new_args, + $this)); + } + // compile registered function or block function + if ($plugin_type === Smarty::PLUGIN_FUNCTION || $plugin_type === Smarty::PLUGIN_BLOCK) { + return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, + $tag); + } + } + } + // check plugins from plugins folder + foreach ($this->plugin_search_order as $plugin_type) { + if ($plugin_type === Smarty::PLUGIN_COMPILER && + $this->smarty->loadPlugin('smarty_compiler_' . $tag) && + (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + $plugin = 'smarty_compiler_' . $tag; + if (is_callable($plugin)) { + // convert arguments format for old compiler plugins + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + + return $plugin($new_args, $this->smarty); + } + if (class_exists($plugin, false)) { + $plugin_object = new $plugin; + if (method_exists($plugin_object, 'compile')) { + return $plugin_object->compile($args, $this); + } + } + throw new SmartyException("Plugin \"{$tag}\" not callable"); + } else { + if ($function = $this->getPlugin($tag, $plugin_type)) { + if (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter, + $tag, $function); + } + } + } + } + if (is_callable($this->smarty->default_plugin_handler_func)) { + $found = false; + // look for already resolved tags + foreach ($this->plugin_search_order as $plugin_type) { + if (isset($this->default_handler_plugins[ $plugin_type ][ $tag ])) { + $found = true; + break; + } + } + if (!$found) { + // call default handler + foreach ($this->plugin_search_order as $plugin_type) { + if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) { + $found = true; + break; + } + } + } + if ($found) { + // if compiler function plugin call it now + if ($plugin_type === Smarty::PLUGIN_COMPILER) { + $new_args = array(); + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[ $key ] = $mixed; + } + } + return call_user_func_array($this->default_handler_plugins[ $plugin_type ][ $tag ][ 0 ], + array($new_args, + $this)); + } else { + return $this->callTagCompiler('private_registered_' . $plugin_type, $args, $parameter, + $tag); + } + } + } + } else { + // compile closing tag of block function + $base_tag = substr($tag, 0, - 5); + // check if closing tag is a registered object + if (isset($this->smarty->registered_objects[ $base_tag ]) && isset($parameter[ 'object_method' ])) { + $method = $parameter[ 'object_method' ]; + if (in_array($method, $this->smarty->registered_objects[ $base_tag ][ 3 ])) { + return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, + $method); + } else { + // throw exception + $this->trigger_template_error('not allowed closing tag method "' . $method . + '" in registered object "' . $base_tag . '"', null, true); + } + } + // registered block tag ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) || + isset($this->default_handler_plugins[ Smarty::PLUGIN_BLOCK ][ $base_tag ]) + ) { + return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag); + } + // registered function tag ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_FUNCTION ][ $tag ])) { + return $this->callTagCompiler('private_registered_function', $args, $parameter, $tag); + } + // block plugin? + if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { + return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function); + } + // function plugin? + if ($function = $this->getPlugin($tag, Smarty::PLUGIN_FUNCTION)) { + if (!isset($this->smarty->security_policy) || + $this->smarty->security_policy->isTrustedTag($tag, $this) + ) { + return $this->callTagCompiler('private_function_plugin', $args, $parameter, $tag, $function); + } + } + // registered compiler plugin ? + if (isset($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ])) { + // if compiler function plugin call it now + $args = array(); + if (!$this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 1 ]) { + $this->tag_nocache = true; + } + return call_user_func_array($this->smarty->registered_plugins[ Smarty::PLUGIN_COMPILER ][ $tag ][ 0 ], + array($args, + $this)); + } + if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) { + $plugin = 'smarty_compiler_' . $tag; + if (is_callable($plugin)) { + return $plugin($args, $this->smarty); + } + if (class_exists($plugin, false)) { + $plugin_object = new $plugin; + if (method_exists($plugin_object, 'compile')) { + return $plugin_object->compile($args, $this); + } + } + throw new SmartyException("Plugin \"{$tag}\" not callable"); + } + } + $this->trigger_template_error("unknown tag \"" . $tag . "\"", null, true); + } + } + + /** + * compile variable + * + * @param string $variable + * + * @return string + */ + public function compileVariable($variable) + { + if (strpos($variable, '(') == 0) { + // not a variable variable + $var = trim($variable, '\''); + $this->tag_nocache = $this->tag_nocache | + $this->template->ext->getTemplateVars->_getVariable($this->template, $var, null, true, + false)->nocache; + // todo $this->template->compiled->properties['variables'][$var] = $this->tag_nocache | $this->nocache; + } + return '$_smarty_tpl->tpl_vars[' . $variable . ']->value'; + } + + /** + * compile config variable + * + * @param string $variable + * + * @return string + */ + public function compileConfigVariable($variable) + { + // return '$_smarty_tpl->config_vars[' . $variable . ']'; + return '$_smarty_tpl->smarty->ext->configLoad->_getConfigVariable($_smarty_tpl, ' . $variable . ')'; + } + + /** + * compile PHP function call + * + * @param string $name + * @param array $parameter + * + * @return string + */ + public function compilePHPFunctionCall($name, $parameter) + { + if (!$this->smarty->security_policy || $this->smarty->security_policy->isTrustedPhpFunction($name, $this)) { + if (strcasecmp($name, 'isset') === 0 || strcasecmp($name, 'empty') === 0 || + strcasecmp($name, 'array') === 0 || is_callable($name) + ) { + $func_name = strtolower($name); + $par = implode(',', $parameter); + $parHasFuction = strpos($par, '(') !== false; + if ($func_name === 'isset') { + if (count($parameter) === 0) { + $this->trigger_template_error('Illegal number of parameter in "isset()"'); + } + if ($parHasFuction) { + $pa = array(); + foreach ($parameter as $p) { + $pa[] = (strpos($p, '(') === false) ? ('isset(' . $p . ')') : ('(' . $p . ' !== null )'); + } + return "(" . implode(' && ', $pa) . ")"; + } else { + $isset_par = str_replace("')->value", "',null,true,false)->value", $par); + } + return $name . "(" . $isset_par . ")"; + } elseif (in_array($func_name, array('empty', + 'reset', + 'current', + 'end', + 'prev', + 'next'))) { + if (count($parameter) !== 1) { + $this->trigger_template_error("Illegal number of parameter in '{$func_name()}'"); + } + if ($func_name === 'empty') { + if ($parHasFuction && version_compare(PHP_VERSION, '5.5.0', '<')) { + return '(' . $parameter[ 0 ] . ' == false )'; + } else { + return $func_name . '(' . + str_replace("')->value", "',null,true,false)->value", $parameter[ 0 ]) . ')'; + } + } else { + return $func_name . '(' . $parameter[ 0 ] . ')'; + } + } else { + return $name . "(" . implode(',', $parameter) . ")"; + } + } else { + $this->trigger_template_error("unknown function \"" . $name . "\""); + } + } + } + + /** + * This method is called from parser to process a text content section + * - remove text from inheritance child templates as they may generate output + * - strip text if strip is enabled + * + * @param string $text + * + * @return null|\Smarty_Internal_ParseTree_Text + */ + public function processText($text) + { + if ((string) $text !== '') { + $store = array(); + $_store = 0; + if ($this->parser->strip) { + if (strpos($text, '<') !== false) { + // capture html elements not to be messed with + $_offset = 0; + if (preg_match_all('#(]*>.*?]*>)|(]*>.*?]*>)|(]*>.*?]*>)#is', + $text, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + foreach ($matches as $match) { + $store[] = $match[ 0 ][ 0 ]; + $_length = strlen($match[ 0 ][ 0 ]); + $replace = '@!@SMARTY:' . $_store . ':SMARTY@!@'; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] - $_offset, $_length); + + $_offset += $_length - strlen($replace); + ++ $_store; + } + } + $expressions = array(// replace multiple spaces between tags by a single space + '#(:SMARTY@!@|>)[\040\011]+(?=@!@SMARTY:|<)#s' => '\1 \2', + // remove newline between tags + '#(:SMARTY@!@|>)[\040\011]*[\n]\s*(?=@!@SMARTY:|<)#s' => '\1\2', + // remove multiple spaces between attributes (but not in attribute values!) + '#(([a-z0-9]\s*=\s*("[^"]*?")|(\'[^\']*?\'))|<[a-z0-9_]+)\s+([a-z/>])#is' => '\1 \5', + '#>[\040\011]+$#Ss' => '> ', + '#>[\040\011]*[\n]\s*$#Ss' => '>', + $this->stripRegEx => '',); + + $text = preg_replace(array_keys($expressions), array_values($expressions), $text); + $_offset = 0; + if (preg_match_all('#@!@SMARTY:([0-9]+):SMARTY@!@#is', $text, $matches, + PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) { + foreach ($matches as $match) { + $_length = strlen($match[ 0 ][ 0 ]); + $replace = $store[ $match[ 1 ][ 0 ] ]; + $text = substr_replace($text, $replace, $match[ 0 ][ 1 ] + $_offset, $_length); + + $_offset += strlen($replace) - $_length; + ++ $_store; + } + } + } else { + $text = preg_replace($this->stripRegEx, '', $text); + } + } + return new Smarty_Internal_ParseTree_Text($text); + } + return null; + } + + /** + * lazy loads internal compile plugin for tag and calls the compile method + * compile objects cached for reuse. + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php + * + * @param string $tag tag name + * @param array $args list of tag attributes + * @param mixed $param1 optional parameter + * @param mixed $param2 optional parameter + * @param mixed $param3 optional parameter + * + * @return string|bool compiled code or false + */ + public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) + { + /* @var Smarty_Internal_CompileBase $tagCompiler */ + $tagCompiler = $this->getTagCompiler($tag); + // compile this tag + return $tagCompiler === false ? false : $tagCompiler->compile($args, $this, $param1, $param2, $param3); + } + + /** + * lazy loads internal compile plugin for tag compile objects cached for reuse. + * + * class name format: Smarty_Internal_Compile_TagName + * plugin filename format: Smarty_Internal_TagName.php + * + * @param string $tag tag name + * + * @return Smarty_Internal_CompileBase|bool tag compiler object or false if not found + */ + public function getTagCompiler($tag) + { + // re-use object if already exists + if (!isset(self::$_tag_objects[ $tag ])) { + // lazy load internal compiler plugin + $_tag = explode('_', $tag); + $_tag = array_map('ucfirst', $_tag); + $class_name = 'Smarty_Internal_Compile_' . implode('_', $_tag); + if (class_exists($class_name) && + (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) + ) { + self::$_tag_objects[ $tag ] = new $class_name; + } else { + self::$_tag_objects[ $tag ] = false; + } + } + return self::$_tag_objects[ $tag ]; + } + + /** + * Check for plugins and return function name + * + * @param $plugin_name + * @param string $plugin_type type of plugin + * + * @return string call name of function + */ + public function getPlugin($plugin_name, $plugin_type) + { + $function = null; + if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { + if (isset($this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { + $function = + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } elseif (isset($this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ] = + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ]; + $function = + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } + } else { + if (isset($this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ])) { + $function = + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'function' ]; + } elseif (isset($this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ])) { + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ] = + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ]; + $function = + $this->parent_compiler->template->compiled->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->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'file' ] = + $file; + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ $plugin_type ][ 'function' ] = + $function; + } else { + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ $plugin_type ][ 'file' ] = + $file; + $this->parent_compiler->template->compiled->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->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $tag ][ $plugin_type ][ 'file' ] = + $script; + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $tag ][ $plugin_type ][ 'function' ] = + $callback; + } else { + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $tag ][ $plugin_type ][ 'file' ] = + $script; + $this->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $tag ][ $plugin_type ][ 'function' ] = + $callback; + } + require_once $script; + } else { + $this->trigger_template_error("Default plugin handler: Returned script file \"{$script}\" for \"{$tag}\" not found"); + } + } + 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; + } + + /** + * Append code segments and remove unneeded ?> \s*$/', $left) && preg_match('/^\s*<\?php\s+/', $right)) { + $left = preg_replace('/\s*\?>\s*$/', "\n", $left); + $left .= preg_replace('/^\s*<\?php\s+/', '', $right); + } else { + $left .= $right; + } + return $left; + } + + /** + * 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->handler->recompiled) || $this->forceNocache) && $this->template->caching && + !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache) + ) { + $this->template->compiled->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->parent_compiler->template->compiled->required_plugins[ 'compiled' ][ $plugin_name ][ 'modifier' ])) { + $this->parent_compiler->template->compiled->required_plugins[ 'nocache' ][ $plugin_name ][ 'modifier' ] = + $this->parent_compiler->template->compiled->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; + } + + /** + * Get Id + * + * @param string $input + * + * @return bool|string + */ + public function getId($input) + { + if (preg_match('~^([\'"]*)([0-9]*[a-zA-Z_]\w*)\1$~', $input, $match)) { + return $match[ 2 ]; + } + return false; + } + + /** + * Get variable name from string + * + * @param string $input + * + * @return bool|string + */ + public function getVariableName($input) + { + if (preg_match('~^[$]_smarty_tpl->tpl_vars\[[\'"]*([0-9]*[a-zA-Z_]\w*)[\'"]*\]->value$~', $input, $match)) { + return $match[ 1 ]; + } + return false; + } + + /** + * Set nocache flag in variable or create new variable + * + * @param string $varName + */ + public function setNocacheInVariable($varName) + { + // create nocache var to make it know for further compiling + if ($_var = $this->getId($varName)) { + if (isset($this->template->tpl_vars[ $_var ])) { + $this->template->tpl_vars[ $_var ] = clone $this->template->tpl_vars[ $_var ]; + $this->template->tpl_vars[ $_var ]->nocache = true; + } else { + $this->template->tpl_vars[ $_var ] = new Smarty_Variable(null, true); + } + } + } + + /** + * @param array $_attr tag attributes + * @param array $validScopes + * + * @return int|string + * @throws \SmartyCompilerException + */ + public function convertScope($_attr, $validScopes) + { + $_scope = 0; + if (isset($_attr[ 'scope' ])) { + $_scopeName = trim($_attr[ 'scope' ], "'\""); + if (is_numeric($_scopeName) && in_array($_scopeName, $validScopes)) { + $_scope = $_scopeName; + } elseif (is_string($_scopeName)) { + $_scopeName = trim($_scopeName, "'\""); + $_scope = isset($validScopes[ $_scopeName ]) ? $validScopes[ $_scopeName ] : false; + } else { + $_scope = false; + } + if ($_scope === false) { + $err = var_export($_scopeName, true); + $this->trigger_template_error("illegal value '{$err}' for \"scope\" attribute", null, true); + } + } + return $_scope; + } + + /** + * Generate nocache code string + * + * @param string $code PHP code + * + * @return string + */ + public function makeNocacheCode($code) + { + return "echo '/*%%SmartyNocache:{$this->nocache_hash}%%*//*/%%SmartyNocache:{$this->nocache_hash}%%*/';\n"; + } + + /** + * 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 + * @param null|bool $tagline if true the line number of last tag + * + * @throws \SmartyCompilerException when an unexpected token is found + */ + public function trigger_template_error($args = null, $line = null, $tagline = null) + { + $lex = $this->parser->lex; + if ($tagline === true) { + // get line number of Tag + $line = $lex->taglineno; + } elseif (!isset($line)) { + // get template source line which has error + $line = $lex->line; + } else { + $line = (int) $line; + } + + if (in_array($this->template->source->type, array('eval', + 'string'))) { + $templateName = $this->template->source->type . ':' . trim(preg_replace('![\t\r\n]+!', ' ', + strlen($lex->data) > 40 ? + substr($lex->data, 0, 40) . + '...' : $lex->data)); + } else { + $templateName = $this->template->source->type . ':' . $this->template->source->filepath; + } + + // $line += $this->trace_line_offset; + $match = preg_split("/\n/", $lex->data); + $error_text = + 'Syntax error in template "' . (empty($this->trace_filepath) ? $templateName : $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 { + $expect = array(); + // expected token from parser + $error_text .= ' - Unexpected "' . $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($lex->smarty_token_names[ $exp_token ])) { + // token type from lexer + $expect[] = '"' . $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; + } + + /** + * Return var_export() value with all white spaces removed + * + * @param mixed $value + * + * @return string + */ + public function getVarExport($value) + { + return preg_replace('/\s/', '', var_export($value, true)); + } + + /** + * Check if $value contains variable elements + * + * @param mixed $value + * + * @return bool|int + */ + public function isVariable($value) + { + if (is_string($value)) { + return preg_match('/[$(]/', $value); + } + if (is_bool($value) || is_numeric($value)) { + return false; + } + if (is_array($value)) { + foreach ($value as $k => $v) { + if ($this->isVariable($k) || $this->isVariable($v)) { + return true; + } + } + return false; + } + return false; + } + + /** + * Get new prefix variable name + * + * @return string + */ + public function getNewPrefixVariable() + { + ++ self::$prefixVariableNumber; + return $this->getPrefixVariable(); + } + + /** + * Get current prefix variable name + * + * @return string + */ + public function getPrefixVariable() + { + return '$_prefixVariable' . self::$prefixVariableNumber; + } + + /** + * append code to prefix buffer + * + * @param string $code + */ + public function appendPrefixCode($code) + { + $this->prefix_code[] = $code; + } + + /** + * get prefix code string + * + * @return string + */ + public function getPrefixCode() + { + $code = ''; + $prefixArray = array_merge($this->prefix_code, array_pop($this->prefixCodeStack)); + $this->prefixCodeStack[] = array(); + foreach ($prefixArray as $c) { + $code = $this->appendCode($code, $c); + } + $this->prefix_code = array(); + return $code; + } + +} diff --git a/libs/sysplugins/smarty_internal_templatelexer.php b/libs/sysplugins/smarty_internal_templatelexer.php new file mode 100644 index 0000000..a6d0ec2 --- /dev/null +++ b/libs/sysplugins/smarty_internal_templatelexer.php @@ -0,0 +1,1136 @@ + + */ +class Smarty_Internal_Templatelexer +{ + const TEXT = 1; + const TAG = 2; + const TAGBODY = 3; + const LITERAL = 4; + const DOUBLEQUOTEDSTRING = 5; + /** + * Source + * + * @var string + */ + public $data; + /** + * Source length + * + * @var int + */ + public $dataLength = null; + /** + * byte counter + * + * @var int + */ + public $counter; + /** + * token number + * + * @var int + */ + public $token; + /** + * token value + * + * @var string + */ + public $value; + /** + * current line + * + * @var int + */ + public $line; + /** + * tag start line + * + * @var + */ + public $taglineno; + /** + * php code type + * + * @var string + */ + public $phpType = ''; + /** + * escaped left delimiter + * + * @var string + */ + public $ldel = ''; + /** + * escaped left delimiter length + * + * @var int + */ + public $ldel_length = 0; + /** + * escaped right delimiter + * + * @var string + */ + public $rdel = ''; + + /** + * PHP start tag string + * + * @var string + */ + /** + * escaped right delimiter length + * + * @var int + */ + public $rdel_length = 0; + /** + * state number + * + * @var int + */ + public $state = 1; + /** + * Smarty object + * + * @var Smarty + */ + public $smarty = null; + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + /** + * trace file + * + * @var resource + */ + public $yyTraceFILE; + /** + * trace prompt + * + * @var string + */ + public $yyTracePrompt; + /** + * XML flag true while processing xml + * + * @var bool + */ + public $is_xml = false; + /** + * state names + * + * @var array + */ + public $state_name = array(1 => 'TEXT', 2 => 'TAG', 3 => 'TAGBODY', 4 => 'LITERAL', 5 => 'DOUBLEQUOTEDSTRING',); + /** + * token names + * + * @var array + */ + public $smarty_token_names = array( // Text for parser error messages + 'NOT' => '(!,not)', 'OPENP' => '(', 'CLOSEP' => ')', 'OPENB' => '[', + 'CLOSEB' => ']', 'PTR' => '->', 'APTR' => '=>', 'EQUAL' => '=', + 'NUMBER' => 'number', 'UNIMATH' => '+" , "-', 'MATH' => '*" , "/" , "%', + 'INCDEC' => '++" , "--', 'SPACE' => ' ', 'DOLLAR' => '$', + 'SEMICOLON' => ';', 'COLON' => ':', 'DOUBLECOLON' => '::', 'AT' => '@', + 'HATCH' => '#', 'QUOTE' => '"', 'BACKTICK' => '`', + 'VERT' => '"|" modifier', 'DOT' => '.', 'COMMA' => '","', + 'QMARK' => '"?"', 'ID' => 'id, name', 'TEXT' => 'text', + 'LDELSLASH' => '{/..} closing tag', 'LDEL' => '{...} Smarty tag', + 'COMMENT' => 'comment', 'AS' => 'as', 'TO' => 'to', + 'PHP' => '" '"<", "==" ... logical operator', + 'TLOGOP' => '"lt", "eq" ... logical operator; "is div by" ... if condition', + 'SCOND' => '"is even" ... if condition',); + /** + * literal tag nesting level + * + * @var int + */ + private $literal_cnt = 0; + /** + * storage for assembled token patterns + * + * @var string + */ + private $yy_global_pattern1 = null; + private $yy_global_pattern2 = null; + + /* + * Check if this tag is autoliteral + */ + private $yy_global_pattern3 = null; + private $yy_global_pattern4 = null; + private $yy_global_pattern5 = null; + private $_yy_state = 1; + private $_yy_stack = array(); + + /** + * constructor + * + * @param string $data template source + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + function __construct($data, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->data = $data; + $this->dataLength = strlen($data); + $this->counter = 0; + if (preg_match('/^\xEF\xBB\xBF/i', $this->data, $match)) { + $this->counter += strlen($match[0]); + } + $this->line = 1; + $this->smarty = $compiler->smarty; + $this->compiler = $compiler; + $this->pldel = preg_quote($this->smarty->left_delimiter, '/'); + $this->ldel = $this->pldel . ($this->smarty->auto_literal ? '(?!\\s+)' : '\\s*'); + $this->ldel_length = strlen($this->smarty->left_delimiter); + $this->rdel = preg_quote($this->smarty->right_delimiter, '/'); + $this->rdel_length = strlen($this->smarty->right_delimiter); + $this->smarty_token_names['LDEL'] = $this->smarty->left_delimiter; + $this->smarty_token_names['RDEL'] = $this->smarty->right_delimiter; + } + + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + public function isAutoLiteral() + { + return $this->smarty->auto_literal && isset($this->value[ $this->ldel_length ]) ? + strpos(" \n\t\r", $this->value[ $this->ldel_length ]) !== false : false; + } + +public function yylex1() + { + if (!isset($this->yy_global_pattern1)) { + $this->yy_global_pattern1 = + $this->replace("/\G([{][}])|\G(SMARTYldel[*])|\G((SMARTYldelphp([ ].*?)?SMARTYrdel)|(SMARTYldel[\/]phpSMARTYrdel))|\G(SMARTYrawldel{2,})|\G(SMARTYldelliteral\\s*SMARTYrdel)|\G(SMARTYldel[\/]literal\\s*SMARTYrdel)|\G(SMARTYldel)|\G((<[?]((php\\s+|=)|\\s+))|(<[%])|(<[?]xml\\s+)|()|([?][>])|([%][>]))|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + + do { + if (preg_match($this->yy_global_pattern1, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[0][1])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . + substr($this->data, + $this->counter, + 5) . '... state TEXT'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r1_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } else if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else if ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + + } // end function + + public function replace($input) + { + return str_replace(array('SMARTYldel', 'SMARTYrawldel', 'SMARTYrdel'), + array($this->ldel, $this->pldel, $this->rdel), + $input); + } + + public function yylex() + { + return $this->{'yylex' . $this->_yy_state}(); + } + + function yy_r1_1() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r1_2() + { + + preg_match("/[*]{$this->rdel}/", $this->data, $match, PREG_OFFSET_CAPTURE, $this->counter); + if (isset($match[0][1])) { + $to = $match[0][1] + strlen($match[0][0]); + } else { + $this->compiler->trigger_template_error("missing or misspelled comment closing tag '*{$this->smarty->right_delimiter}'"); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + return false; + } + + function yy_r1_3() + { + + $this->compiler->getTagCompiler('private_php')->parsePhp($this); + } + + function yy_r1_7() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r1_8() + { + + $this->token = Smarty_Internal_Templateparser::TP_LITERALSTART; + $this->yypushstate(self::LITERAL); + } + + public function yypushstate($state) + { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sState push %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : + $this->_yy_state); + } + array_push($this->_yy_stack, $this->_yy_state); + $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%snew State %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : + $this->_yy_state); + } + } + + function yy_r1_9() + { + + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypushstate(self::LITERAL); + } + + function yy_r1_10() + { + + $this->yypushstate(self::TAG); + return true; + } + + function yy_r1_11() + { + + $this->compiler->getTagCompiler('private_php')->parsePhp($this); + } // end function + + function yy_r1_20() + { + + $to = $this->dataLength; + preg_match("/((?pldel){$this->ldel})|(<[?]((php\s+|=)|\s+))|(<[%])|(<[?]xml\s+)|()|([?][>])|([%][>])/i", + $this->data, + $match, + PREG_OFFSET_CAPTURE, + $this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + +public function yylex2() + { + if (!isset($this->yy_global_pattern2)) { + $this->yy_global_pattern2 = + $this->replace("/\G(SMARTYldel(if|elseif|else if|while)\\s+)|\G(SMARTYldelfor\\s+)|\G(SMARTYldelforeach(?![^\s]))|\G(SMARTYldelsetfilter\\s+)|\G(SMARTYldelmake_nocache\\s+)|\G(SMARTYldel[0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G(SMARTYldel[\/](?:(?!block)[0-9]*[a-zA-Z_]\\w*)\\s*SMARTYrdel)|\G(SMARTYldel[$][0-9]*[a-zA-Z_]\\w*(\\s+nocache)?\\s*SMARTYrdel)|\G(SMARTYldel[\/])|\G(SMARTYldel)/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + + do { + if (preg_match($this->yy_global_pattern2, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[0][1])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . + substr($this->data, + $this->counter, + 5) . '... state TAG'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r2_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } else if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else if ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + + } + + function yy_r2_1() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELIF; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + public function yybegin($state) + { + $this->_yy_state = $state; + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sState set %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : + $this->_yy_state); + } + } + + function yy_r2_3() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELFOR; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r2_4() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELFOREACH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r2_5() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELSETFILTER; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r2_6() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELMAKENOCACHE; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r2_7() + { + + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPLETAG; + $this->taglineno = $this->line; + } + + public function yypopstate() + { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sState pop %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : + $this->_yy_state); + } + $this->_yy_state = array_pop($this->_yy_stack); + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%snew State %s\n", + $this->yyTracePrompt, + isset($this->state_name[ $this->_yy_state ]) ? $this->state_name[ $this->_yy_state ] : + $this->_yy_state); + } + + } + + function yy_r2_9() + { + + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_CLOSETAG; + $this->taglineno = $this->line; + } + + function yy_r2_10() + { + + if ($this->_yy_stack[ count($this->_yy_stack) - 1 ] == self::TEXT) { + $this->yypopstate(); + $this->token = Smarty_Internal_Templateparser::TP_SIMPELOUTPUT; + $this->taglineno = $this->line; + } else { + $this->value = $this->smarty->left_delimiter; + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + } // end function + + function yy_r2_12() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDELSLASH; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r2_13() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->yybegin(self::TAGBODY); + $this->taglineno = $this->line; + } + +public function yylex3() + { + if (!isset($this->yy_global_pattern3)) { + $this->yy_global_pattern3 = + $this->replace("/\G(\\s*SMARTYrdel)|\G(SMARTYldel)|\G([\"])|\G('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')|\G([$]smarty\\.block\\.(child|parent))|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(\\s+is\\s+in\\s+)|\G(\\s+as\\s+)|\G(\\s+to\\s+)|\G(\\s+step\\s+)|\G(\\s+instanceof\\s+)|\G(\\s*(([!=][=]{1,2})|([<][=>]?)|([>][=]?)|[&|]{2})\\s*)|\G(\\s+(eq|ne|neq|gt|ge|gte|lt|le|lte|mod|and|or|xor)\\s+)|\G(\\s+(is\\s+(not\\s+)?(odd|even|div)\\s+by)\\s+)|\G(\\s+is\\s+(not\\s+)?(odd|even))|\G(([!]\\s*)|(not\\s+))|\G([(](int(eger)?|bool(ean)?|float|double|real|string|binary|array|object)[)]\\s*)|\G(\\s*[(]\\s*)|\G(\\s*[)])|\G(\\[\\s*)|\G(\\s*\\])|\G(\\s*[-][>]\\s*)|\G(\\s*[=][>]\\s*)|\G(\\s*[=]\\s*)|\G(([+]|[-]){2})|\G(\\s*([+]|[-])\\s*)|\G(\\s*([*]{1,2}|[%\/^&]|[<>]{2})\\s*)|\G([@])|\G([#])|\G(\\s+[0-9]*[a-zA-Z_][a-zA-Z0-9_\-:]*\\s*[=]\\s*)|\G(([0-9]*[a-zA-Z_]\\w*)?(\\\\[0-9]*[a-zA-Z_]\\w*)+)|\G([0-9]*[a-zA-Z_]\\w*)|\G(\\d+)|\G([`])|\G([|])|\G([.])|\G(\\s*[,]\\s*)|\G(\\s*[;]\\s*)|\G([:]{2})|\G(\\s*[:]\\s*)|\G(\\s*[?]\\s*)|\G(0[xX][0-9a-fA-F]+)|\G(\\s+)|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + + do { + if (preg_match($this->yy_global_pattern3, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[0][1])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . + substr($this->data, + $this->counter, + 5) . '... state TAGBODY'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r3_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } else if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else if ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + + } + + function yy_r3_1() + { + + $this->token = Smarty_Internal_Templateparser::TP_RDEL; + $this->yypopstate(); + } + + function yy_r3_2() + { + + $this->yypushstate(self::TAG); + return true; + } + + function yy_r3_3() + { + + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypushstate(self::DOUBLEQUOTEDSTRING); + } + + function yy_r3_4() + { + + $this->token = Smarty_Internal_Templateparser::TP_SINGLEQUOTESTRING; + } + + function yy_r3_5() + { + + $this->token = Smarty_Internal_Templateparser::TP_SMARTYBLOCKCHILDPARENT; + $this->taglineno = $this->line; + } + + function yy_r3_7() + { + + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + + function yy_r3_8() + { + + $this->token = Smarty_Internal_Templateparser::TP_DOLLAR; + } + + function yy_r3_9() + { + + $this->token = Smarty_Internal_Templateparser::TP_ISIN; + } + + function yy_r3_10() + { + + $this->token = Smarty_Internal_Templateparser::TP_AS; + } + + function yy_r3_11() + { + + $this->token = Smarty_Internal_Templateparser::TP_TO; + } + + function yy_r3_12() + { + + $this->token = Smarty_Internal_Templateparser::TP_STEP; + } + + function yy_r3_13() + { + + $this->token = Smarty_Internal_Templateparser::TP_INSTANCEOF; + } + + function yy_r3_14() + { + + $this->token = Smarty_Internal_Templateparser::TP_LOGOP; + } + + function yy_r3_19() + { + + $this->token = Smarty_Internal_Templateparser::TP_SLOGOP; + } + + function yy_r3_21() + { + + $this->token = Smarty_Internal_Templateparser::TP_TLOGOP; + } + + function yy_r3_25() + { + + $this->token = Smarty_Internal_Templateparser::TP_SINGLECOND; + } + + function yy_r3_28() + { + + $this->token = Smarty_Internal_Templateparser::TP_NOT; + } + + function yy_r3_31() + { + + $this->token = Smarty_Internal_Templateparser::TP_TYPECAST; + } + + function yy_r3_35() + { + + $this->token = Smarty_Internal_Templateparser::TP_OPENP; + } + + function yy_r3_36() + { + + $this->token = Smarty_Internal_Templateparser::TP_CLOSEP; + } + + function yy_r3_37() + { + + $this->token = Smarty_Internal_Templateparser::TP_OPENB; + } + + function yy_r3_38() + { + + $this->token = Smarty_Internal_Templateparser::TP_CLOSEB; + } + + function yy_r3_39() + { + + $this->token = Smarty_Internal_Templateparser::TP_PTR; + } + + function yy_r3_40() + { + + $this->token = Smarty_Internal_Templateparser::TP_APTR; + } + + function yy_r3_41() + { + + $this->token = Smarty_Internal_Templateparser::TP_EQUAL; + } + + function yy_r3_42() + { + + $this->token = Smarty_Internal_Templateparser::TP_INCDEC; + } + + function yy_r3_44() + { + + $this->token = Smarty_Internal_Templateparser::TP_UNIMATH; + } + + function yy_r3_46() + { + + $this->token = Smarty_Internal_Templateparser::TP_MATH; + } + + function yy_r3_48() + { + + $this->token = Smarty_Internal_Templateparser::TP_AT; + } + + function yy_r3_49() + { + + $this->token = Smarty_Internal_Templateparser::TP_HATCH; + } + + function yy_r3_50() + { + + // resolve conflicts with shorttag and right_delimiter starting with '=' + if (substr($this->data, $this->counter + strlen($this->value) - 1, $this->rdel_length) == + $this->smarty->right_delimiter) { + preg_match("/\s+/", $this->value, $match); + $this->value = $match[0]; + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } else { + $this->token = Smarty_Internal_Templateparser::TP_ATTR; + } + } + + function yy_r3_51() + { + + $this->token = Smarty_Internal_Templateparser::TP_NAMESPACE; + } + + function yy_r3_54() + { + + $this->token = Smarty_Internal_Templateparser::TP_ID; + } + + function yy_r3_55() + { + + $this->token = Smarty_Internal_Templateparser::TP_INTEGER; + } + + function yy_r3_56() + { + + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->yypopstate(); + } + + function yy_r3_57() + { + + $this->token = Smarty_Internal_Templateparser::TP_VERT; + } + + function yy_r3_58() + { + + $this->token = Smarty_Internal_Templateparser::TP_DOT; + } + + function yy_r3_59() + { + + $this->token = Smarty_Internal_Templateparser::TP_COMMA; + } + + function yy_r3_60() + { + + $this->token = Smarty_Internal_Templateparser::TP_SEMICOLON; + } + + function yy_r3_61() + { + + $this->token = Smarty_Internal_Templateparser::TP_DOUBLECOLON; + } + + function yy_r3_62() + { + + $this->token = Smarty_Internal_Templateparser::TP_COLON; + } + + function yy_r3_63() + { + + $this->token = Smarty_Internal_Templateparser::TP_QMARK; + } + + function yy_r3_64() + { + + $this->token = Smarty_Internal_Templateparser::TP_HEX; + } + + function yy_r3_65() + { + + $this->token = Smarty_Internal_Templateparser::TP_SPACE; + } // end function + + function yy_r3_66() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + +public function yylex4() + { + if (!isset($this->yy_global_pattern4)) { + $this->yy_global_pattern4 = + $this->replace("/\G(SMARTYldelliteral\\s*SMARTYrdel)|\G(SMARTYldel[\/]literal\\s*SMARTYrdel)|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + + do { + if (preg_match($this->yy_global_pattern4, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[0][1])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . + substr($this->data, + $this->counter, + 5) . '... state LITERAL'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r4_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } else if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else if ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + + } + + function yy_r4_1() + { + + $this->literal_cnt++; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } + + function yy_r4_2() + { + + if ($this->literal_cnt) { + $this->literal_cnt--; + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } else { + $this->token = Smarty_Internal_Templateparser::TP_LITERALEND; + $this->yypopstate(); + } + } + + function yy_r4_3() + { + + $to = $this->dataLength; + preg_match("/{$this->ldel}[\/]?literal{$this->rdel}/i", + $this->data, + $match, + PREG_OFFSET_CAPTURE, + $this->counter); + if (isset($match[0][1])) { + $to = $match[0][1]; + } else { + $this->compiler->trigger_template_error("missing or misspelled literal closing tag"); + } + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_LITERAL; + } // end function + +public function yylex5() + { + if (!isset($this->yy_global_pattern5)) { + $this->yy_global_pattern5 = + $this->replace("/\G(SMARTYrawldel{2,})|\G(SMARTYldelliteral\\s*SMARTYrdel)|\G(SMARTYldel[\/]literal\\s*SMARTYrdel)|\G(SMARTYldel[\/])|\G(SMARTYldel[0-9]*[a-zA-Z_]\\w*)|\G(SMARTYldel)|\G([\"])|\G([`][$])|\G([$][0-9]*[a-zA-Z_]\\w*)|\G([$])|\G(([^\"\\\\]*?)((?:\\\\.[^\"\\\\]*?)*?)(?=(SMARTYldel|\\$|`\\$|\")))|\G([\S\s])/isS"); + } + if (!isset($this->dataLength)) { + $this->dataLength = strlen($this->data); + } + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + + do { + if (preg_match($this->yy_global_pattern5, $this->data, $yymatches, 0, $this->counter)) { + if (!isset($yymatches[0][1])) { + $yymatches = preg_grep("/(.|\s)+/", $yymatches); + } else { + $yymatches = array_filter($yymatches); + } + if (empty($yymatches)) { + throw new Exception('Error: lexing failed because a rule matched' . ' an empty string. Input "' . + substr($this->data, + $this->counter, + 5) . '... state DOUBLEQUOTEDSTRING'); + } + next($yymatches); // skip global match + $this->token = key($yymatches); // token number + $this->value = current($yymatches); // token value + $r = $this->{'yy_r5_' . $this->token}(); + if ($r === null) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + // accept this token + return true; + } else if ($r === true) { + // we have changed state + // process this token in the new state + return $this->yylex(); + } else if ($r === false) { + $this->counter += strlen($this->value); + $this->line += substr_count($this->value, "\n"); + if ($this->counter >= $this->dataLength) { + return false; // end of input + } + // skip this token + continue; + } + } else { + throw new Exception('Unexpected input at line' . $this->line . ': ' . $this->data[ $this->counter ]); + } + break; + } while (true); + + } + + function yy_r5_1() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r5_2() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r5_3() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r5_4() + { + + $this->yypushstate(self::TAG); + return true; + } + + function yy_r5_5() + { + + $this->yypushstate(self::TAG); + return true; + } + + function yy_r5_6() + { + + $this->token = Smarty_Internal_Templateparser::TP_LDEL; + $this->taglineno = $this->line; + $this->yypushstate(self::TAGBODY); + } + + function yy_r5_7() + { + + $this->token = Smarty_Internal_Templateparser::TP_QUOTE; + $this->yypopstate(); + } + + function yy_r5_8() + { + + $this->token = Smarty_Internal_Templateparser::TP_BACKTICK; + $this->value = substr($this->value, 0, -1); + $this->yypushstate(self::TAGBODY); + $this->taglineno = $this->line; + } + + function yy_r5_9() + { + + $this->token = Smarty_Internal_Templateparser::TP_DOLLARID; + } + + function yy_r5_10() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r5_11() + { + + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + + function yy_r5_15() + { + + $to = $this->dataLength; + $this->value = substr($this->data, $this->counter, $to - $this->counter); + $this->token = Smarty_Internal_Templateparser::TP_TEXT; + } + +} + + \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_templateparser.php b/libs/sysplugins/smarty_internal_templateparser.php new file mode 100644 index 0000000..cfe6710 --- /dev/null +++ b/libs/sysplugins/smarty_internal_templateparser.php @@ -0,0 +1,2764 @@ +string = $s->string; + $this->metadata = $s->metadata; + } else { + $this->string = (string)$s; + if ($m instanceof TP_yyToken) { + $this->metadata = $m->metadata; + } else if (is_array($m)) { + $this->metadata = $m; + } + } + } + + public function __toString() + { + return $this->string; + } + + public function offsetExists($offset) + { + return isset($this->metadata[ $offset ]); + } + + public function offsetGet($offset) + { + return $this->metadata[ $offset ]; + } + + public function offsetSet($offset, $value) + { + if ($offset === null) { + if (isset($value[0])) { + $x = ($value instanceof TP_yyToken) ? $value->metadata : $value; + $this->metadata = array_merge($this->metadata, $x); + + return; + } + $offset = count($this->metadata); + } + if ($value === null) { + return; + } + if ($value instanceof TP_yyToken) { + if ($value->metadata) { + $this->metadata[ $offset ] = $value->metadata; + } + } else if ($value) { + $this->metadata[ $offset ] = $value; + } + } + + public function offsetUnset($offset) + { + unset($this->metadata[ $offset ]); + } +} + +class TP_yyStackEntry +{ + public $stateno; /* The state-number */ + public $major; /* The major token value. This is the code + ** number for the token at this stack level */ + public $minor; /* The user-supplied minor token value. This + ** is the value of the token */ +} + +; + + +#line 11 "../smarty/lexer/smarty_internal_templateparser.y" + +/** + * Smarty Template Parser Class + * + * This is the template parser. + * It is generated from the smarty_internal_templateparser.y file + * + * @author Uwe Tews + */ +class Smarty_Internal_Templateparser +{ + #line 23 "../smarty/lexer/smarty_internal_templateparser.y" + + const Err1 = "Security error: Call to private object member not allowed"; + const Err2 = "Security error: Call to dynamic object member not allowed"; + const Err3 = "PHP in template not allowed. Use SmartyBC to enable it"; + + /** + * result status + * + * @var bool + */ + public $successful = true; + + /** + * return value + * + * @var mixed + */ + public $retvalue = 0; + + /** + * @var + */ + public $yymajor; + + /** + * last index of array variable + * + * @var mixed + */ + public $last_index; + + /** + * last variable name + * + * @var string + */ + public $last_variable; + + /** + * root parse tree buffer + * + * @var Smarty_Internal_ParseTree + */ + public $root_buffer; + + /** + * current parse tree object + * + * @var Smarty_Internal_ParseTree + */ + public $current_buffer; + + /** + * lexer object + * + * @var Smarty_Internal_Templatelexer + */ + public $lex; + + /** + * internal error flag + * + * @var bool + */ + private $internalError = false; + + /** + * {strip} status + * + * @var bool + */ + public $strip = false; + /** + * compiler object + * + * @var Smarty_Internal_TemplateCompilerBase + */ + public $compiler = null; + + /** + * smarty object + * + * @var Smarty + */ + public $smarty = null; + + /** + * template object + * + * @var Smarty_Internal_Template + */ + public $template = null; + + /** + * block nesting level + * + * @var int + */ + public $block_nesting_level = 0; + + /** + * security object + * + * @var Smarty_Security + */ + public $security = null; + + /** + * template prefix array + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_prefix = array(); + + /** + * security object + * + * @var \Smarty_Internal_ParseTree[] + */ + public $template_postfix = array(); + + /** + * constructor + * + * @param Smarty_Internal_Templatelexer $lex + * @param Smarty_Internal_TemplateCompilerBase $compiler + */ + function __construct(Smarty_Internal_Templatelexer $lex, Smarty_Internal_TemplateCompilerBase $compiler) + { + $this->lex = $lex; + $this->compiler = $compiler; + $this->template = $this->compiler->template; + $this->smarty = $this->template->smarty; + $this->security = isset($this->smarty->security_policy) ? $this->smarty->security_policy : false; + $this->current_buffer = $this->root_buffer = new Smarty_Internal_ParseTree_Template(); + } + + /** + * insert PHP code in current buffer + * + * @param string $code + */ + public function insertPhpCode($code) + { + $this->current_buffer->append_subtree($this, new Smarty_Internal_ParseTree_Tag($this, $code)); + } + + /** + * merge PHP code with prefix code and return parse tree tag object + * + * @param string $code + * + * @return Smarty_Internal_ParseTree_Tag + */ + public function mergePrefixCode($code) + { + $tmp = ''; + foreach ($this->compiler->prefix_code as $preCode) { + $tmp .= $preCode; + } + $this->compiler->prefix_code = array(); + $tmp .= $code; + return new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp, true)); + } + + + const TP_VERT = 1; + const TP_COLON = 2; + const TP_PHP = 3; + const TP_TEXT = 4; + const TP_STRIPON = 5; + const TP_STRIPOFF = 6; + const TP_LITERALSTART = 7; + const TP_LITERALEND = 8; + const TP_LITERAL = 9; + const TP_RDEL = 10; + const TP_SIMPELOUTPUT = 11; + const TP_LDEL = 12; + const TP_DOLLARID = 13; + const TP_EQUAL = 14; + const TP_SIMPLETAG = 15; + const TP_ID = 16; + const TP_PTR = 17; + const TP_LDELMAKENOCACHE = 18; + const TP_LDELIF = 19; + const TP_LDELFOR = 20; + const TP_SEMICOLON = 21; + const TP_INCDEC = 22; + const TP_TO = 23; + const TP_STEP = 24; + const TP_LDELFOREACH = 25; + const TP_SPACE = 26; + const TP_AS = 27; + const TP_APTR = 28; + const TP_LDELSETFILTER = 29; + const TP_SMARTYBLOCKCHILDPARENT = 30; + const TP_CLOSETAG = 31; + const TP_LDELSLASH = 32; + const TP_ATTR = 33; + const TP_INTEGER = 34; + const TP_COMMA = 35; + const TP_OPENP = 36; + const TP_CLOSEP = 37; + const TP_MATH = 38; + const TP_UNIMATH = 39; + const TP_ISIN = 40; + const TP_QMARK = 41; + const TP_NOT = 42; + const TP_TYPECAST = 43; + const TP_HEX = 44; + const TP_DOT = 45; + const TP_INSTANCEOF = 46; + const TP_SINGLEQUOTESTRING = 47; + const TP_DOUBLECOLON = 48; + const TP_NAMESPACE = 49; + const TP_AT = 50; + const TP_HATCH = 51; + const TP_OPENB = 52; + const TP_CLOSEB = 53; + const TP_DOLLAR = 54; + const TP_LOGOP = 55; + const TP_SLOGOP = 56; + const TP_TLOGOP = 57; + const TP_SINGLECOND = 58; + const TP_QUOTE = 59; + const TP_BACKTICK = 60; + const YY_NO_ACTION = 532; + const YY_ACCEPT_ACTION = 531; + const YY_ERROR_ACTION = 530; + + const YY_SZ_ACTTAB = 1993; + static public $yy_action = array(272, 8, 131, 237, 275, 80, 179, 230, 6, 84, 20, 324, 175, 101, 116, 41, 16, 327, + 225, 299, 257, 232, 277, 235, 214, 26, 216, 202, 42, 106, 190, 40, 43, 314, 234, + 278, 310, 244, 212, 355, 82, 1, 204, 291, 114, 272, 8, 132, 79, 275, 196, 246, + 230, 6, 84, 11, 177, 267, 269, 116, 21, 197, 14, 225, 252, 257, 232, 11, 205, + 31, 26, 223, 101, 42, 14, 78, 40, 43, 314, 234, 290, 220, 245, 212, 293, 82, 1, + 316, 291, 446, 272, 8, 134, 79, 275, 208, 246, 230, 6, 84, 11, 446, 291, 114, + 116, 15, 204, 14, 225, 136, 257, 232, 251, 235, 254, 26, 185, 298, 42, 90, 78, + 40, 43, 314, 234, 213, 310, 181, 212, 120, 82, 1, 204, 291, 99, 272, 8, 136, 79, + 275, 208, 402, 230, 6, 84, 253, 289, 82, 246, 116, 291, 190, 280, 225, 204, 257, + 232, 402, 235, 189, 12, 18, 17, 42, 402, 204, 40, 43, 314, 234, 228, 310, 78, + 212, 402, 82, 1, 204, 291, 326, 272, 8, 134, 79, 275, 208, 399, 230, 6, 84, 402, + 154, 459, 237, 116, 182, 23, 402, 225, 459, 257, 232, 399, 194, 239, 26, 184, + 298, 42, 399, 158, 40, 43, 314, 234, 106, 310, 246, 212, 190, 82, 1, 204, 291, + 7, 272, 8, 134, 79, 275, 195, 357, 230, 6, 84, 256, 19, 256, 19, 116, 279, 78, + 279, 225, 137, 257, 232, 11, 211, 183, 26, 9, 227, 42, 14, 306, 40, 43, 314, + 234, 93, 310, 214, 212, 270, 82, 1, 106, 291, 2, 272, 8, 134, 79, 275, 193, 224, + 230, 6, 84, 101, 109, 256, 19, 116, 29, 231, 279, 225, 141, 257, 232, 304, 235, + 214, 26, 217, 233, 42, 106, 11, 40, 43, 314, 234, 172, 310, 14, 212, 243, 82, 1, + 36, 291, 313, 272, 8, 135, 79, 275, 208, 222, 230, 6, 84, 446, 36, 291, 292, + 116, 246, 85, 302, 225, 218, 257, 232, 446, 235, 95, 26, 136, 321, 42, 221, 447, + 40, 43, 314, 234, 291, 310, 459, 212, 78, 82, 1, 447, 291, 459, 272, 8, 134, 79, + 275, 199, 35, 230, 6, 84, 475, 475, 475, 475, 116, 475, 140, 475, 225, 82, 257, + 232, 291, 235, 304, 26, 5, 101, 42, 233, 3, 40, 43, 314, 234, 36, 310, 311, 212, + 92, 82, 1, 105, 291, 297, 272, 8, 133, 79, 275, 208, 475, 230, 6, 84, 137, 149, + 291, 278, 116, 296, 180, 9, 225, 312, 257, 232, 27, 235, 176, 4, 139, 148, 42, + 147, 446, 40, 43, 314, 234, 242, 310, 33, 212, 277, 82, 1, 446, 291, 14, 272, 8, + 136, 79, 275, 208, 163, 230, 6, 84, 204, 171, 189, 178, 116, 204, 277, 161, 225, + 367, 257, 232, 291, 235, 361, 12, 236, 277, 42, 278, 101, 40, 43, 314, 234, 11, + 310, 190, 212, 204, 82, 329, 14, 291, 204, 446, 233, 209, 79, 117, 70, 113, 287, + 259, 260, 238, 99, 446, 233, 240, 286, 114, 325, 274, 320, 210, 323, 144, 289, + 129, 119, 24, 261, 263, 264, 265, 177, 277, 203, 294, 272, 8, 145, 143, 275, 3, + 94, 230, 6, 84, 247, 331, 277, 277, 116, 189, 188, 329, 225, 157, 257, 232, 233, + 209, 317, 117, 70, 113, 146, 277, 190, 258, 99, 319, 268, 240, 286, 25, 277, + 150, 320, 210, 323, 179, 289, 204, 38, 282, 165, 277, 219, 329, 41, 16, 327, + 284, 233, 209, 277, 122, 63, 103, 248, 217, 186, 298, 99, 190, 400, 240, 286, + 278, 215, 142, 320, 210, 323, 91, 289, 20, 329, 167, 30, 277, 400, 233, 209, + 276, 122, 67, 113, 400, 110, 330, 446, 99, 271, 187, 240, 286, 129, 190, 318, + 320, 210, 323, 446, 289, 237, 152, 329, 278, 83, 315, 206, 233, 209, 262, 122, + 67, 113, 190, 288, 280, 273, 99, 256, 19, 240, 286, 162, 279, 155, 320, 210, + 323, 182, 289, 303, 86, 168, 11, 277, 160, 201, 272, 10, 305, 14, 275, 254, 138, + 230, 6, 84, 159, 256, 19, 88, 116, 190, 279, 278, 225, 329, 257, 232, 166, 38, + 233, 209, 11, 122, 67, 113, 475, 475, 277, 14, 99, 475, 459, 240, 286, 111, 169, + 266, 320, 210, 323, 278, 289, 303, 300, 13, 104, 87, 89, 207, 272, 10, 305, 303, + 275, 303, 303, 230, 6, 84, 459, 303, 303, 459, 116, 475, 303, 459, 225, 329, + 257, 232, 303, 303, 233, 209, 303, 122, 47, 103, 303, 112, 303, 303, 99, 303, + 303, 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, 303, 301, 13, 329, 303, + 303, 303, 303, 233, 209, 303, 108, 50, 113, 256, 19, 303, 303, 99, 279, 303, + 240, 286, 303, 303, 303, 320, 210, 323, 11, 289, 173, 303, 329, 303, 303, 14, + 303, 233, 209, 303, 122, 54, 113, 204, 303, 303, 303, 99, 303, 303, 240, 286, + 191, 303, 303, 320, 210, 323, 303, 289, 329, 303, 303, 303, 303, 233, 209, 303, + 122, 77, 113, 303, 303, 303, 303, 99, 303, 303, 240, 286, 44, 39, 37, 320, 210, + 323, 329, 289, 303, 303, 303, 233, 209, 303, 122, 74, 113, 322, 308, 307, 285, + 99, 303, 303, 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, 303, 303, 329, + 303, 303, 303, 303, 233, 209, 303, 122, 49, 113, 204, 22, 303, 303, 99, 156, + 303, 240, 286, 179, 303, 303, 320, 210, 323, 277, 289, 329, 41, 16, 327, 303, + 233, 209, 303, 96, 53, 113, 303, 303, 303, 303, 99, 190, 303, 240, 286, 44, 39, + 37, 320, 210, 323, 329, 289, 303, 303, 303, 233, 209, 303, 122, 60, 113, 322, + 308, 307, 285, 99, 303, 303, 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, + 303, 303, 329, 303, 303, 303, 303, 233, 209, 303, 122, 71, 113, 204, 303, 303, + 303, 99, 170, 303, 240, 286, 179, 303, 303, 320, 210, 323, 277, 289, 329, 41, + 16, 327, 303, 233, 198, 303, 115, 61, 113, 303, 303, 303, 303, 99, 190, 303, + 240, 286, 44, 39, 37, 320, 210, 323, 329, 289, 303, 303, 303, 233, 97, 303, 81, + 45, 107, 322, 308, 307, 285, 99, 255, 303, 240, 286, 303, 303, 303, 320, 210, + 323, 303, 289, 303, 303, 329, 303, 303, 303, 303, 233, 209, 303, 122, 62, 113, + 204, 303, 303, 303, 99, 303, 303, 240, 286, 283, 303, 303, 320, 210, 323, 303, + 289, 329, 303, 303, 303, 303, 233, 209, 303, 100, 69, 113, 303, 303, 303, 303, + 99, 303, 303, 240, 286, 44, 39, 37, 320, 210, 323, 329, 289, 303, 303, 303, 233, + 200, 303, 122, 58, 113, 322, 308, 307, 285, 99, 303, 303, 240, 286, 303, 303, + 303, 320, 210, 323, 303, 289, 303, 303, 329, 303, 303, 303, 303, 233, 209, 303, + 102, 68, 113, 204, 303, 303, 303, 99, 303, 303, 240, 286, 241, 303, 303, 320, + 210, 323, 303, 289, 329, 303, 303, 303, 303, 233, 209, 303, 122, 55, 113, 303, + 303, 303, 303, 99, 303, 303, 240, 286, 44, 39, 37, 320, 210, 323, 329, 289, 303, + 303, 303, 233, 209, 303, 122, 65, 113, 322, 308, 307, 285, 99, 303, 303, 240, + 286, 303, 303, 303, 320, 210, 323, 303, 289, 303, 303, 329, 303, 303, 303, 303, + 233, 209, 303, 122, 66, 113, 204, 303, 303, 303, 99, 303, 303, 240, 286, 192, + 303, 303, 320, 210, 323, 303, 289, 329, 303, 303, 303, 303, 233, 209, 303, 122, + 59, 113, 303, 303, 303, 303, 99, 303, 303, 240, 286, 44, 39, 37, 320, 210, 323, + 329, 289, 303, 303, 303, 233, 209, 303, 122, 56, 113, 322, 308, 307, 285, 99, + 303, 303, 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, 303, 303, 329, 303, + 303, 303, 303, 233, 209, 303, 122, 75, 113, 204, 303, 303, 303, 99, 303, 303, + 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, 329, 303, 303, 118, 303, 233, + 209, 303, 122, 51, 113, 303, 303, 303, 303, 99, 303, 303, 240, 286, 44, 39, 37, + 320, 210, 323, 329, 289, 303, 303, 303, 233, 209, 303, 122, 72, 113, 322, 308, + 307, 285, 99, 303, 303, 240, 286, 303, 303, 303, 320, 210, 323, 303, 289, 303, + 303, 329, 303, 303, 303, 303, 233, 209, 303, 122, 63, 113, 204, 303, 303, 303, + 99, 151, 303, 240, 286, 179, 303, 303, 320, 210, 323, 277, 289, 329, 41, 16, + 327, 303, 233, 209, 303, 122, 64, 113, 303, 303, 303, 303, 99, 190, 303, 240, + 286, 44, 39, 37, 320, 210, 323, 329, 289, 303, 303, 303, 233, 209, 303, 122, 46, + 113, 322, 308, 307, 285, 99, 303, 303, 240, 286, 303, 303, 303, 320, 210, 323, + 303, 289, 303, 303, 329, 303, 303, 303, 303, 233, 98, 303, 81, 48, 107, 303, + 303, 303, 303, 99, 153, 303, 240, 286, 179, 303, 303, 320, 210, 323, 277, 289, + 329, 41, 16, 327, 303, 233, 209, 303, 122, 73, 113, 303, 303, 303, 303, 99, 190, + 303, 240, 286, 44, 39, 37, 320, 210, 323, 329, 289, 303, 303, 303, 233, 209, + 303, 122, 57, 113, 322, 308, 307, 285, 99, 303, 303, 240, 286, 303, 303, 303, + 320, 210, 323, 303, 289, 303, 204, 329, 303, 303, 303, 303, 233, 209, 204, 122, + 76, 113, 303, 412, 412, 303, 99, 303, 303, 240, 286, 303, 303, 250, 320, 210, + 323, 120, 289, 303, 303, 28, 99, 11, 303, 303, 229, 44, 39, 37, 14, 249, 303, + 303, 289, 44, 39, 37, 446, 303, 412, 412, 412, 303, 322, 308, 307, 285, 303, + 303, 446, 303, 322, 308, 307, 285, 303, 412, 412, 412, 412, 303, 303, 329, 303, + 303, 303, 303, 233, 209, 303, 123, 303, 113, 303, 303, 303, 303, 99, 303, 406, + 303, 328, 303, 303, 303, 320, 210, 323, 329, 289, 406, 204, 406, 233, 209, 406, + 130, 303, 113, 303, 295, 303, 406, 99, 406, 303, 406, 281, 303, 303, 226, 320, + 210, 323, 237, 289, 11, 303, 303, 475, 475, 303, 18, 14, 475, 459, 303, 204, 44, + 39, 37, 303, 303, 531, 52, 334, 259, 260, 238, 303, 303, 233, 303, 303, 303, + 322, 308, 307, 285, 303, 303, 303, 11, 459, 303, 303, 459, 303, 475, 14, 459, + 303, 329, 303, 44, 39, 37, 233, 209, 303, 125, 303, 113, 303, 303, 303, 303, 99, + 303, 303, 303, 322, 308, 307, 285, 320, 210, 323, 329, 289, 303, 303, 303, 233, + 209, 303, 124, 303, 113, 303, 303, 303, 303, 99, 303, 303, 303, 303, 303, 303, + 303, 320, 210, 323, 329, 289, 303, 303, 303, 233, 209, 303, 121, 303, 113, 329, + 303, 303, 303, 99, 233, 209, 303, 127, 303, 113, 303, 320, 210, 323, 99, 289, + 303, 303, 226, 303, 303, 303, 320, 210, 323, 303, 289, 475, 475, 329, 303, 226, + 475, 459, 233, 209, 303, 128, 303, 113, 475, 475, 303, 34, 99, 475, 459, 204, + 303, 303, 303, 303, 320, 210, 323, 303, 289, 303, 204, 303, 303, 459, 303, 303, + 459, 329, 475, 303, 459, 332, 233, 209, 303, 126, 459, 113, 303, 459, 303, 475, + 99, 459, 303, 303, 44, 39, 37, 303, 320, 210, 323, 303, 289, 303, 309, 44, 39, + 37, 303, 333, 303, 322, 308, 307, 285, 303, 303, 226, 303, 303, 303, 303, 322, + 308, 307, 285, 475, 475, 32, 303, 303, 475, 459, 303, 303, 303, 164, 475, 475, + 303, 179, 303, 475, 459, 204, 303, 277, 303, 303, 41, 16, 327, 303, 303, 303, + 303, 303, 303, 303, 303, 459, 303, 303, 459, 190, 475, 303, 459, 303, 303, 174, + 459, 303, 303, 459, 303, 475, 303, 459, 303, 303, 44, 39, 37, 303, 303, 303, + 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 303, 322, 308, 307, 285,); + static public $yy_lookahead = array(11, 12, 13, 45, 15, 16, 76, 18, 19, 20, 14, 53, 72, 17, 25, 85, 86, 87, 29, 30, + 31, 32, 82, 34, 75, 36, 77, 78, 39, 80, 100, 42, 43, 44, 45, 95, 47, 16, 49, 10, + 51, 52, 1, 54, 48, 11, 12, 13, 59, 15, 16, 22, 18, 19, 20, 26, 7, 8, 9, 25, 12, + 13, 33, 29, 16, 31, 32, 26, 34, 14, 36, 50, 17, 39, 33, 46, 42, 43, 44, 45, 97, + 47, 34, 49, 10, 51, 52, 53, 54, 36, 11, 12, 13, 59, 15, 16, 22, 18, 19, 20, 26, + 48, 54, 48, 25, 21, 1, 33, 29, 13, 31, 32, 16, 34, 94, 36, 96, 97, 39, 35, 46, + 42, 43, 44, 45, 71, 47, 76, 49, 75, 51, 52, 1, 54, 80, 11, 12, 13, 59, 15, 16, + 10, 18, 19, 20, 49, 92, 51, 22, 25, 54, 100, 101, 29, 1, 31, 32, 26, 34, 100, + 36, 14, 14, 39, 33, 1, 42, 43, 44, 45, 17, 47, 46, 49, 10, 51, 52, 1, 54, 53, + 11, 12, 13, 59, 15, 16, 10, 18, 19, 20, 26, 27, 45, 45, 25, 76, 14, 33, 29, 52, + 31, 32, 26, 34, 22, 36, 96, 97, 39, 33, 75, 42, 43, 44, 45, 80, 47, 22, 49, 100, + 51, 52, 1, 54, 36, 11, 12, 13, 59, 15, 16, 10, 18, 19, 20, 11, 12, 11, 12, 25, + 16, 46, 16, 29, 45, 31, 32, 26, 34, 13, 36, 52, 16, 39, 33, 60, 42, 43, 44, 45, + 93, 47, 75, 49, 77, 51, 52, 80, 54, 36, 11, 12, 13, 59, 15, 16, 50, 18, 19, 20, + 17, 48, 11, 12, 25, 12, 13, 16, 29, 16, 31, 32, 65, 34, 75, 36, 77, 70, 39, 80, + 26, 42, 43, 44, 45, 93, 47, 33, 49, 13, 51, 52, 35, 54, 37, 11, 12, 13, 59, 15, + 16, 50, 18, 19, 20, 36, 35, 54, 37, 25, 22, 104, 105, 29, 45, 31, 32, 48, 34, + 81, 36, 13, 53, 39, 16, 36, 42, 43, 44, 45, 54, 47, 45, 49, 46, 51, 52, 48, 54, + 52, 11, 12, 13, 59, 15, 16, 12, 18, 19, 20, 11, 12, 11, 12, 25, 16, 13, 16, 29, + 51, 31, 32, 54, 34, 65, 36, 35, 17, 39, 70, 36, 42, 43, 44, 45, 35, 47, 37, 49, + 36, 51, 52, 80, 54, 53, 11, 12, 13, 59, 15, 16, 50, 18, 19, 20, 45, 93, 54, 95, + 25, 98, 81, 52, 29, 105, 31, 32, 28, 34, 81, 36, 13, 93, 39, 72, 36, 42, 43, 44, + 45, 16, 47, 26, 49, 82, 51, 52, 48, 54, 33, 11, 12, 13, 59, 15, 16, 72, 18, 19, + 20, 1, 51, 100, 76, 25, 1, 82, 72, 29, 10, 31, 32, 54, 34, 10, 36, 17, 82, 39, + 95, 17, 42, 43, 44, 45, 26, 47, 100, 49, 1, 51, 65, 33, 54, 1, 36, 70, 71, 59, + 73, 74, 75, 64, 65, 66, 67, 80, 48, 70, 83, 84, 48, 91, 37, 88, 89, 90, 72, 92, + 98, 16, 28, 3, 4, 5, 6, 7, 82, 102, 103, 11, 12, 72, 72, 15, 36, 76, 18, 19, 20, + 16, 53, 82, 82, 25, 100, 16, 65, 29, 72, 31, 32, 70, 71, 53, 73, 74, 75, 72, 82, + 100, 66, 80, 53, 69, 83, 84, 23, 82, 72, 88, 89, 90, 76, 92, 1, 2, 16, 72, 82, + 16, 65, 85, 86, 87, 103, 70, 71, 82, 73, 74, 75, 16, 77, 96, 97, 80, 100, 10, + 83, 84, 95, 14, 72, 88, 89, 90, 76, 92, 14, 65, 51, 41, 82, 26, 70, 71, 13, 73, + 74, 75, 33, 16, 91, 36, 80, 10, 76, 83, 84, 98, 100, 34, 88, 89, 90, 48, 92, 45, + 93, 65, 95, 16, 34, 99, 70, 71, 4, 73, 74, 75, 100, 16, 101, 82, 80, 11, 12, 83, + 84, 93, 16, 72, 88, 89, 90, 76, 92, 4, 80, 93, 26, 82, 28, 99, 11, 12, 13, 33, + 15, 94, 80, 18, 19, 20, 93, 11, 12, 80, 25, 100, 16, 95, 29, 65, 31, 32, 72, 2, + 70, 71, 26, 73, 74, 75, 11, 12, 82, 33, 80, 16, 17, 83, 84, 79, 93, 8, 88, 89, + 90, 95, 92, 4, 59, 60, 68, 80, 80, 99, 11, 12, 13, 106, 15, 106, 106, 18, 19, + 20, 45, 106, 106, 48, 25, 50, 106, 52, 29, 65, 31, 32, 106, 106, 70, 71, 106, + 73, 74, 75, 106, 77, 106, 106, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, 90, + 106, 92, 106, 59, 60, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, 11, 12, + 106, 106, 80, 16, 106, 83, 84, 106, 106, 106, 88, 89, 90, 26, 92, 28, 106, 65, + 106, 106, 33, 106, 70, 71, 106, 73, 74, 75, 1, 106, 106, 106, 80, 106, 106, 83, + 84, 10, 106, 106, 88, 89, 90, 106, 92, 65, 106, 106, 106, 106, 70, 71, 106, 73, + 74, 75, 106, 106, 106, 106, 80, 106, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, + 92, 106, 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, + 84, 106, 106, 106, 88, 89, 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, + 71, 106, 73, 74, 75, 1, 2, 106, 106, 80, 72, 106, 83, 84, 76, 106, 106, 88, 89, + 90, 82, 92, 65, 85, 86, 87, 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, + 80, 100, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, + 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, + 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, 1, 106, + 106, 106, 80, 72, 106, 83, 84, 76, 106, 106, 88, 89, 90, 82, 92, 65, 85, 86, 87, + 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, 80, 100, 106, 83, 84, 38, 39, + 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, 57, 58, + 80, 60, 106, 83, 84, 106, 106, 106, 88, 89, 90, 106, 92, 106, 106, 65, 106, 106, + 106, 106, 70, 71, 106, 73, 74, 75, 1, 106, 106, 106, 80, 106, 106, 83, 84, 10, + 106, 106, 88, 89, 90, 106, 92, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, + 106, 106, 106, 106, 80, 106, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, 92, 106, + 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, 84, 106, + 106, 106, 88, 89, 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, 71, 106, + 73, 74, 75, 1, 106, 106, 106, 80, 106, 106, 83, 84, 10, 106, 106, 88, 89, 90, + 106, 92, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, + 80, 106, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, + 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, + 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, 1, 106, + 106, 106, 80, 106, 106, 83, 84, 10, 106, 106, 88, 89, 90, 106, 92, 65, 106, 106, + 106, 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, 80, 106, 106, 83, 84, 38, + 39, 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, 57, + 58, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, 90, 106, 92, 106, 106, 65, 106, + 106, 106, 106, 70, 71, 106, 73, 74, 75, 1, 106, 106, 106, 80, 106, 106, 83, 84, + 106, 106, 106, 88, 89, 90, 106, 92, 65, 106, 106, 21, 106, 70, 71, 106, 73, 74, + 75, 106, 106, 106, 106, 80, 106, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, 92, + 106, 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, 84, + 106, 106, 106, 88, 89, 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, 71, + 106, 73, 74, 75, 1, 106, 106, 106, 80, 72, 106, 83, 84, 76, 106, 106, 88, 89, + 90, 82, 92, 65, 85, 86, 87, 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, + 80, 100, 106, 83, 84, 38, 39, 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, + 106, 73, 74, 75, 55, 56, 57, 58, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, + 90, 106, 92, 106, 106, 65, 106, 106, 106, 106, 70, 71, 106, 73, 74, 75, 106, + 106, 106, 106, 80, 72, 106, 83, 84, 76, 106, 106, 88, 89, 90, 82, 92, 65, 85, + 86, 87, 106, 70, 71, 106, 73, 74, 75, 106, 106, 106, 106, 80, 100, 106, 83, 84, + 38, 39, 40, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, 106, 73, 74, 75, 55, 56, + 57, 58, 80, 106, 106, 83, 84, 106, 106, 106, 88, 89, 90, 106, 92, 106, 1, 65, + 106, 106, 106, 106, 70, 71, 1, 73, 74, 75, 106, 1, 2, 106, 80, 106, 106, 83, 84, + 106, 106, 71, 88, 89, 90, 75, 92, 106, 106, 24, 80, 26, 106, 106, 37, 38, 39, + 40, 33, 89, 106, 106, 92, 38, 39, 40, 36, 106, 38, 39, 40, 106, 55, 56, 57, 58, + 106, 106, 48, 106, 55, 56, 57, 58, 106, 55, 56, 57, 58, 106, 106, 65, 106, 106, + 106, 106, 70, 71, 106, 73, 106, 75, 106, 106, 106, 106, 80, 106, 10, 106, 84, + 106, 106, 106, 88, 89, 90, 65, 92, 21, 1, 23, 70, 71, 26, 73, 106, 75, 106, 10, + 106, 33, 80, 35, 106, 37, 84, 106, 106, 2, 88, 89, 90, 45, 92, 26, 106, 106, 11, + 12, 106, 14, 33, 16, 17, 106, 1, 38, 39, 40, 106, 106, 62, 63, 64, 65, 66, 67, + 106, 106, 70, 106, 106, 106, 55, 56, 57, 58, 106, 106, 106, 26, 45, 106, 106, + 48, 106, 50, 33, 52, 106, 65, 106, 38, 39, 40, 70, 71, 106, 73, 106, 75, 106, + 106, 106, 106, 80, 106, 106, 106, 55, 56, 57, 58, 88, 89, 90, 65, 92, 106, 106, + 106, 70, 71, 106, 73, 106, 75, 106, 106, 106, 106, 80, 106, 106, 106, 106, 106, + 106, 106, 88, 89, 90, 65, 92, 106, 106, 106, 70, 71, 106, 73, 106, 75, 65, 106, + 106, 106, 80, 70, 71, 106, 73, 106, 75, 106, 88, 89, 90, 80, 92, 106, 106, 2, + 106, 106, 106, 88, 89, 90, 106, 92, 11, 12, 65, 106, 2, 16, 17, 70, 71, 106, 73, + 106, 75, 11, 12, 106, 14, 80, 16, 17, 1, 106, 106, 106, 106, 88, 89, 90, 106, + 92, 106, 1, 106, 106, 45, 106, 106, 48, 65, 50, 106, 52, 53, 70, 71, 106, 73, + 45, 75, 106, 48, 106, 50, 80, 52, 106, 106, 38, 39, 40, 106, 88, 89, 90, 106, + 92, 106, 37, 38, 39, 40, 106, 53, 106, 55, 56, 57, 58, 106, 106, 2, 106, 106, + 106, 106, 55, 56, 57, 58, 11, 12, 2, 106, 106, 16, 17, 106, 106, 106, 72, 11, + 12, 106, 76, 106, 16, 17, 1, 106, 82, 106, 106, 85, 86, 87, 106, 106, 106, 106, + 106, 106, 106, 106, 45, 106, 106, 48, 100, 50, 106, 52, 106, 106, 27, 45, 106, + 106, 48, 106, 50, 106, 52, 106, 106, 38, 39, 40, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 55, 56, 57, 58,); + const YY_SHIFT_USE_DFLT = -43; + const YY_SHIFT_MAX = 238; + static public $yy_shift_ofst = array(519, 349, 79, 79, 394, 349, 394, 79, -11, 34, -11, 214, 79, 79, 79, 79, 79, 79, + 169, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 304, 79, 259, 214, 79, 79, 79, + 124, 124, 439, 439, 439, 439, 439, 439, 1665, 1571, 1701, 1701, 1701, 1701, + 1701, 519, 1934, 1239, 1323, 1155, 1071, 987, 1858, 903, 1847, 819, 1563, 1407, + 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1407, 1491, 1491, + 96, 664, 459, 221, 328, 41, 363, 718, 779, 645, 675, 675, 363, 41, 363, 370, + 41, 574, 164, 74, 29, 271, 131, 273, 176, -4, 49, 224, 224, 55, 464, 236, 153, + 274, 274, 463, 236, 488, 416, 493, 418, 105, 263, 105, 105, 105, 105, 105, 105, + 105, 105, 263, -43, 1830, 1817, 1683, 1906, 1917, 694, 48, 226, 359, 147, 354, + 274, 274, 274, 274, 274, 274, 199, 199, 274, 274, 199, 274, 296, 274, 274, 274, + 182, 199, 296, 274, 199, 274, 274, 274, 274, 307, 199, 199, 274, 307, 199, 296, + 296, 274, 696, 708, 105, 105, 696, 105, 105, 188, 263, 263, 263, 105, -43, -43, + -43, -43, -43, 1576, 1644, 588, 289, 361, 126, 399, 195, 360, 84, 351, 21, -42, + 291, 277, 53, 308, 233, 148, 309, 560, 595, 576, 544, 476, 564, 510, 501, 410, + 636, 424, 524, 530, 561, 499, 504, 571, 604, 188, 606, 616, 598, 593, 626, 609, + 643,); + const YY_REDUCE_USE_DFLT = -71; + const YY_REDUCE_MAX = 192; + static public $yy_reduce_ofst = array(1646, 426, 629, 575, 516, 482, 683, 545, 1416, 940, 966, 1024, 1192, 1050, + 1080, 1108, 1134, 1164, 912, 1218, 1360, 1470, 1500, 1444, 1248, 1386, 1332, + 1302, 1276, 996, 882, 828, 772, 856, 714, 744, 798, 1572, 1598, 1765, 1672, + 1724, 1735, 1698, 1801, 1425, 921, 1855, 1425, 1341, 497, 837, 438, -70, + -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, -70, + -70, -70, -70, -70, -70, -70, -70, -70, -70, 1516, 227, 531, 590, 54, 460, + -51, 319, 625, 506, 384, -60, 187, 362, 219, 20, 445, 51, 119, 395, 395, + 323, 119, 322, 119, 110, 495, 546, 323, 110, 119, 532, 551, 486, 477, 110, + 421, 119, 461, 119, 135, 387, 110, 119, 119, 119, 119, 119, 119, 119, 119, + 498, 119, 577, 577, 577, 577, 577, 577, 601, 597, 577, 577, 592, 572, 572, + 572, 572, 572, 572, 586, 586, 572, 572, 586, 572, 589, 572, 572, 572, 635, + 586, 647, 572, 586, 572, 572, 572, 572, 567, 586, 586, 572, 622, 586, 608, + 646, 572, 552, 657, 59, 59, 552, 59, 59, 167, -17, -17, -17, 59, 258, 348, + 340, 212, 339,); + static public $yyExpectedTokens = array(array(3, 4, 5, 6, 7, 11, 12, 15, 18, 19, 20, 25, 29, 31, 32,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 30, 31, 32, 34, 36, 39, 42, + 43, 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 53, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 30, 31, 32, 34, 36, 39, 42, + 43, 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 52, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(11, 12, 13, 15, 16, 18, 19, 20, 25, 29, 31, 32, 34, 36, 39, 42, 43, + 44, 45, 47, 49, 51, 54, 59,), + array(1, 10, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 24, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(1, 26, 33, 38, 39, 40, 55, 56, 57, 58,), + array(3, 4, 5, 6, 7, 11, 12, 15, 18, 19, 20, 25, 29, 31, 32,), + array(1, 27, 38, 39, 40, 55, 56, 57, 58,), + array(1, 10, 38, 39, 40, 55, 56, 57, 58,), + array(1, 21, 38, 39, 40, 55, 56, 57, 58,), + array(1, 10, 38, 39, 40, 55, 56, 57, 58,), + array(1, 10, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58, 60,), + array(1, 37, 38, 39, 40, 55, 56, 57, 58,), + array(1, 2, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 53, 55, 56, 57, 58,), + array(1, 10, 38, 39, 40, 55, 56, 57, 58,), + array(1, 37, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), + array(1, 38, 39, 40, 55, 56, 57, 58,), array(38, 39, 40, 55, 56, 57, 58,), + array(38, 39, 40, 55, 56, 57, 58,), array(13, 16, 49, 51, 54,), + array(4, 11, 12, 13, 15, 18, 19, 20, 25, 29, 31, 32, 59, 60,), + array(1, 10, 17, 26, 33, 36, 48,), array(1, 10, 26, 33,), + array(13, 16, 51, 54,), array(1, 26, 33,), array(13, 36, 54,), + array(4, 11, 12, 13, 15, 18, 19, 20, 25, 29, 31, 32, 59, 60,), + array(11, 12, 16, 26, 28, 33,), array(11, 12, 16, 26, 28, 33,), + array(11, 12, 16, 26, 33,), array(11, 12, 16, 26, 33,), array(13, 36, 54,), + array(1, 26, 33,), array(13, 36, 54,), array(17, 45, 52,), + array(1, 26, 33,), array(1, 2,), array(1, 10, 26, 27, 33,), + array(10, 22, 26, 33, 46,), array(10, 22, 26, 33, 46,), + array(11, 12, 16, 50,), array(1, 10, 26, 33,), array(12, 13, 16, 54,), + array(1, 10, 26, 33,), array(14, 17, 48,), array(7, 8, 9,), + array(11, 12, 16,), array(11, 12, 16,), array(14, 17, 48,), array(1, 10,), + array(13, 16,), array(1, 17,), array(26, 33,), array(26, 33,), + array(17, 48,), array(13, 16,), array(1, 53,), array(26, 33,), + array(1, 28,), array(13, 54,), array(1,), array(17,), array(1,), array(1,), + array(1,), array(1,), array(1,), array(1,), array(1,), array(1,), + array(17,), array(), array(2, 11, 12, 14, 16, 17, 45, 48, 50, 52,), + array(2, 11, 12, 16, 17, 45, 48, 50, 52, 53,), + array(2, 11, 12, 14, 16, 17, 45, 48, 50, 52,), + array(2, 11, 12, 16, 17, 45, 48, 50, 52,), + array(2, 11, 12, 16, 17, 45, 48, 50, 52,), + array(11, 12, 16, 17, 45, 48, 50, 52,), array(12, 13, 16, 34, 54,), + array(11, 12, 16, 50,), array(11, 12, 16,), array(14, 45, 52,), + array(12, 36,), array(26, 33,), array(26, 33,), array(26, 33,), + array(26, 33,), array(26, 33,), array(26, 33,), array(45, 52,), + array(45, 52,), array(26, 33,), array(26, 33,), array(45, 52,), + array(26, 33,), array(13, 54,), array(26, 33,), array(26, 33,), + array(26, 33,), array(14, 22,), array(45, 52,), array(13, 54,), + array(26, 33,), array(45, 52,), array(26, 33,), array(26, 33,), + array(26, 33,), array(26, 33,), array(45, 52,), array(45, 52,), + array(45, 52,), array(26, 33,), array(45, 52,), array(45, 52,), + array(13, 54,), array(13, 54,), array(26, 33,), array(2,), array(8,), + array(1,), array(1,), array(2,), array(1,), array(1,), array(36,), + array(17,), array(17,), array(17,), array(1,), array(), array(), array(), + array(), array(), array(1, 2, 36, 38, 39, 40, 48, 55, 56, 57, 58,), + array(10, 21, 23, 26, 33, 35, 37, 45,), array(10, 14, 26, 33, 36, 48,), + array(36, 45, 48, 53,), array(11, 12, 16, 50,), array(22, 46, 53,), + array(28, 36, 48,), array(22, 46, 60,), array(35, 37,), array(21, 35,), + array(35, 53,), array(16, 50,), array(45, 53,), array(35, 37,), + array(35, 37,), array(36, 48,), array(22, 46,), array(36, 48,), + array(14, 45,), array(36, 48,), array(51,), array(14,), array(16,), + array(23,), array(37,), array(16,), array(53,), array(53,), array(51,), + array(16,), array(16,), array(16,), array(16,), array(16,), array(36,), + array(16,), array(41,), array(13,), array(36,), array(16,), array(10,), + array(34,), array(45,), array(16,), array(34,), array(4,), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(), array(), array(), + array(), array(), array(), array(), array(), array(),); + static public $yy_default = array(338, 515, 494, 494, 530, 530, 530, 494, 530, 530, 530, 530, 530, 530, 530, + 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, + 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, 530, + 530, 396, 372, 359, 396, 362, 396, 335, 401, 530, 530, 530, 530, 530, 530, + 530, 530, 530, 530, 408, 418, 403, 493, 398, 401, 518, 407, 517, 377, 492, + 516, 423, 422, 530, 530, 434, 410, 530, 396, 530, 530, 396, 396, 396, 396, + 530, 396, 530, 506, 396, 386, 410, 424, 424, 459, 410, 530, 410, 449, 530, + 459, 459, 449, 410, 530, 390, 396, 374, 449, 530, 410, 396, 410, 530, 392, + 449, 417, 410, 421, 427, 426, 413, 425, 414, 503, 501, 448, 448, 448, 448, + 448, 448, 530, 461, 459, 475, 459, 366, 381, 370, 369, 376, 368, 487, 457, + 363, 364, 485, 360, 530, 358, 380, 375, 530, 484, 530, 356, 455, 383, 373, + 384, 382, 454, 456, 453, 379, 452, 486, 530, 530, 385, 495, 350, 393, 416, + 496, 387, 443, 459, 481, 507, 504, 391, 500, 500, 500, 459, 459, 434, 430, + 434, 434, 460, 424, 434, 424, 530, 530, 530, 530, 430, 530, 530, 434, 424, + 530, 430, 444, 530, 530, 530, 404, 530, 530, 530, 439, 530, 530, 530, 530, + 530, 530, 505, 530, 436, 530, 475, 530, 530, 530, 430, 530, 432, 342, 378, + 411, 480, 497, 475, 498, 464, 428, 462, 397, 437, 438, 446, 463, 447, 458, + 524, 479, 389, 351, 339, 340, 341, 344, 343, 345, 346, 347, 348, 349, 352, + 405, 353, 354, 394, 409, 365, 371, 395, 477, 478, 499, 502, 412, 465, 514, + 511, 415, 337, 450, 451, 483, 476, 491, 526, 513, 527, 488, 512, 482, 388, + 519, 520, 522, 529, 528, 525, 523, 510, 509, 436, 439, 490, 521, 489, 429, + 431, 474, 468, 433, 467, 435, 466, 508, 440, 469, 441, 471, 419, 420, 442, + 445, 472, 470, 473, 336,); + const YYNOCODE = 107; + const YYSTACKDEPTH = 500; + const YYNSTATE = 335; + const YYNRULE = 195; + const YYERRORSYMBOL = 61; + const YYERRSYMDT = 'yy0'; + const YYFALLBACK = 0; + public static $yyFallback = array(); + + public function Trace($TraceFILE, $zTracePrompt) + { + if (!$TraceFILE) { + $zTracePrompt = 0; + } else if (!$zTracePrompt) { + $TraceFILE = 0; + } + $this->yyTraceFILE = $TraceFILE; + $this->yyTracePrompt = $zTracePrompt; + } + + public function PrintTrace() + { + $this->yyTraceFILE = fopen('php://output', 'w'); + $this->yyTracePrompt = '
'; + } + + public $yyTraceFILE; + public $yyTracePrompt; + public $yyidx; /* Index of top element in stack */ + public $yyerrcnt; /* Shifts left before out of the error */ + public $yystack = array(); /* The parser's stack */ + + public $yyTokenName = array('$', 'VERT', 'COLON', 'PHP', 'TEXT', 'STRIPON', 'STRIPOFF', 'LITERALSTART', + 'LITERALEND', 'LITERAL', 'RDEL', 'SIMPELOUTPUT', 'LDEL', 'DOLLARID', 'EQUAL', + 'SIMPLETAG', 'ID', 'PTR', 'LDELMAKENOCACHE', 'LDELIF', 'LDELFOR', 'SEMICOLON', 'INCDEC', + 'TO', 'STEP', 'LDELFOREACH', 'SPACE', 'AS', 'APTR', 'LDELSETFILTER', + 'SMARTYBLOCKCHILDPARENT', 'CLOSETAG', 'LDELSLASH', 'ATTR', 'INTEGER', 'COMMA', 'OPENP', + 'CLOSEP', 'MATH', 'UNIMATH', 'ISIN', 'QMARK', 'NOT', 'TYPECAST', 'HEX', 'DOT', + 'INSTANCEOF', 'SINGLEQUOTESTRING', 'DOUBLECOLON', 'NAMESPACE', 'AT', 'HATCH', 'OPENB', + 'CLOSEB', 'DOLLAR', 'LOGOP', 'SLOGOP', 'TLOGOP', 'SINGLECOND', 'QUOTE', 'BACKTICK', + 'error', 'start', 'template', 'template_element', 'smartytag', 'literal', + 'text_content', 'literal_elements', 'literal_element', 'tag', 'variable', 'attributes', + 'value', 'expr', 'varindexed', 'modifierlist', 'statement', 'statements', 'foraction', + 'varvar', 'modparameters', 'attribute', 'ternary', 'array', 'tlop', 'lop', 'scond', + 'function', 'ns1', 'doublequoted_with_quotes', 'static_class_access', 'object', + 'arrayindex', 'indexdef', 'varvarele', 'objectchain', 'objectelement', 'method', + 'params', 'modifier', 'modparameter', 'arrayelements', 'arrayelement', 'doublequoted', + 'doublequotedcontent',); + + public static $yyRuleName = array('start ::= template', 'template ::= template_element', + 'template ::= template template_element', 'template ::=', + 'template_element ::= smartytag', 'template_element ::= literal', + 'template_element ::= PHP', 'template_element ::= text_content', + 'text_content ::= TEXT', 'text_content ::= text_content TEXT', + 'template_element ::= STRIPON', 'template_element ::= STRIPOFF', + 'literal ::= LITERALSTART LITERALEND', + 'literal ::= LITERALSTART literal_elements LITERALEND', + 'literal_elements ::= literal_elements literal_element', 'literal_elements ::=', + 'literal_element ::= literal', 'literal_element ::= LITERAL', + 'smartytag ::= tag RDEL', 'smartytag ::= SIMPELOUTPUT', 'tag ::= LDEL variable', + 'tag ::= LDEL variable attributes', 'tag ::= LDEL value', + 'tag ::= LDEL value attributes', 'tag ::= LDEL expr', + 'tag ::= LDEL expr attributes', 'tag ::= LDEL DOLLARID EQUAL value', + 'tag ::= LDEL DOLLARID EQUAL expr', 'tag ::= LDEL DOLLARID EQUAL expr attributes', + 'tag ::= LDEL varindexed EQUAL expr attributes', 'smartytag ::= SIMPLETAG', + 'tag ::= LDEL ID attributes', 'tag ::= LDEL ID', + 'tag ::= LDEL ID modifierlist attributes', 'tag ::= LDEL ID PTR ID attributes', + 'tag ::= LDEL ID PTR ID modifierlist attributes', + 'tag ::= LDELMAKENOCACHE DOLLARID', 'tag ::= LDELIF expr', + 'tag ::= LDELIF expr attributes', 'tag ::= LDELIF statement', + 'tag ::= LDELIF statement attributes', + 'tag ::= LDELFOR statements SEMICOLON expr SEMICOLON varindexed foraction attributes', + 'foraction ::= EQUAL expr', 'foraction ::= INCDEC', + 'tag ::= LDELFOR statement TO expr attributes', + 'tag ::= LDELFOR statement TO expr STEP expr attributes', + 'tag ::= LDELFOREACH attributes', + 'tag ::= LDELFOREACH SPACE value AS varvar attributes', + 'tag ::= LDELFOREACH SPACE value AS varvar APTR varvar attributes', + 'tag ::= LDELFOREACH SPACE expr AS varvar attributes', + 'tag ::= LDELFOREACH SPACE expr AS varvar APTR varvar attributes', + 'tag ::= LDELSETFILTER ID modparameters', + 'tag ::= LDELSETFILTER ID modparameters modifierlist', + 'tag ::= LDEL SMARTYBLOCKCHILDPARENT', 'smartytag ::= CLOSETAG', + 'tag ::= LDELSLASH ID', 'tag ::= LDELSLASH ID modifierlist', + 'tag ::= LDELSLASH ID PTR ID', 'tag ::= LDELSLASH ID PTR ID modifierlist', + 'attributes ::= attributes attribute', 'attributes ::= attribute', + 'attributes ::=', 'attribute ::= SPACE ID EQUAL ID', 'attribute ::= ATTR expr', + 'attribute ::= ATTR value', 'attribute ::= SPACE ID', 'attribute ::= SPACE expr', + 'attribute ::= SPACE value', 'attribute ::= SPACE INTEGER EQUAL expr', + 'statements ::= statement', 'statements ::= statements COMMA statement', + 'statement ::= DOLLARID EQUAL INTEGER', 'statement ::= DOLLARID EQUAL expr', + 'statement ::= varindexed EQUAL expr', 'statement ::= OPENP statement CLOSEP', + 'expr ::= value', 'expr ::= ternary', 'expr ::= DOLLARID COLON ID', + 'expr ::= expr MATH value', 'expr ::= expr UNIMATH value', 'expr ::= array', + 'expr ::= expr modifierlist', 'expr ::= expr tlop value', + 'expr ::= expr lop expr', 'expr ::= expr scond', 'expr ::= expr ISIN array', + 'expr ::= expr ISIN value', + 'ternary ::= OPENP expr CLOSEP QMARK DOLLARID COLON expr', + 'ternary ::= OPENP expr CLOSEP QMARK expr COLON expr', 'value ::= variable', + 'value ::= UNIMATH value', 'value ::= NOT value', 'value ::= TYPECAST value', + 'value ::= variable INCDEC', 'value ::= HEX', 'value ::= INTEGER', + 'value ::= INTEGER DOT INTEGER', 'value ::= INTEGER DOT', 'value ::= DOT INTEGER', + 'value ::= ID', 'value ::= function', 'value ::= OPENP expr CLOSEP', + 'value ::= variable INSTANCEOF ns1', 'value ::= variable INSTANCEOF variable', + 'value ::= SINGLEQUOTESTRING', 'value ::= doublequoted_with_quotes', + 'value ::= varindexed DOUBLECOLON static_class_access', 'value ::= smartytag', + 'value ::= value modifierlist', 'value ::= NAMESPACE', + 'value ::= ns1 DOUBLECOLON static_class_access', 'ns1 ::= ID', + 'ns1 ::= NAMESPACE', 'variable ::= DOLLARID', 'variable ::= varindexed', + 'variable ::= varvar AT ID', 'variable ::= object', 'variable ::= HATCH ID HATCH', + 'variable ::= HATCH ID HATCH arrayindex', 'variable ::= HATCH variable HATCH', + 'variable ::= HATCH variable HATCH arrayindex', + 'varindexed ::= DOLLARID arrayindex', 'varindexed ::= varvar arrayindex', + 'arrayindex ::= arrayindex indexdef', 'arrayindex ::=', + 'indexdef ::= DOT DOLLARID', 'indexdef ::= DOT varvar', + 'indexdef ::= DOT varvar AT ID', 'indexdef ::= DOT ID', + 'indexdef ::= DOT INTEGER', 'indexdef ::= DOT LDEL expr RDEL', + 'indexdef ::= OPENB ID CLOSEB', 'indexdef ::= OPENB ID DOT ID CLOSEB', + 'indexdef ::= OPENB SINGLEQUOTESTRING CLOSEB', + 'indexdef ::= OPENB INTEGER CLOSEB', 'indexdef ::= OPENB DOLLARID CLOSEB', + 'indexdef ::= OPENB variable CLOSEB', 'indexdef ::= OPENB value CLOSEB', + 'indexdef ::= OPENB expr CLOSEB', 'indexdef ::= OPENB CLOSEB', + 'varvar ::= DOLLARID', 'varvar ::= DOLLAR', 'varvar ::= varvar varvarele', + 'varvarele ::= ID', 'varvarele ::= SIMPELOUTPUT', 'varvarele ::= LDEL expr RDEL', + 'object ::= varindexed objectchain', 'objectchain ::= objectelement', + 'objectchain ::= objectchain objectelement', + 'objectelement ::= PTR ID arrayindex', 'objectelement ::= PTR varvar arrayindex', + 'objectelement ::= PTR LDEL expr RDEL arrayindex', + 'objectelement ::= PTR ID LDEL expr RDEL arrayindex', + 'objectelement ::= PTR method', 'function ::= ns1 OPENP params CLOSEP', + 'method ::= ID OPENP params CLOSEP', 'method ::= DOLLARID OPENP params CLOSEP', + 'params ::= params COMMA expr', 'params ::= expr', 'params ::=', + 'modifierlist ::= modifierlist modifier modparameters', + 'modifierlist ::= modifier modparameters', 'modifier ::= VERT AT ID', + 'modifier ::= VERT ID', 'modparameters ::= modparameters modparameter', + 'modparameters ::=', 'modparameter ::= COLON value', + 'modparameter ::= COLON array', 'static_class_access ::= method', + 'static_class_access ::= method objectchain', 'static_class_access ::= ID', + 'static_class_access ::= DOLLARID arrayindex', + 'static_class_access ::= DOLLARID arrayindex objectchain', 'lop ::= LOGOP', + 'lop ::= SLOGOP', 'tlop ::= TLOGOP', 'scond ::= SINGLECOND', + 'array ::= OPENB arrayelements CLOSEB', 'arrayelements ::= arrayelement', + 'arrayelements ::= arrayelements COMMA arrayelement', 'arrayelements ::=', + 'arrayelement ::= value APTR expr', 'arrayelement ::= ID APTR expr', + 'arrayelement ::= expr', 'doublequoted_with_quotes ::= QUOTE QUOTE', + 'doublequoted_with_quotes ::= QUOTE doublequoted QUOTE', + 'doublequoted ::= doublequoted doublequotedcontent', + 'doublequoted ::= doublequotedcontent', + 'doublequotedcontent ::= BACKTICK variable BACKTICK', + 'doublequotedcontent ::= BACKTICK expr BACKTICK', + 'doublequotedcontent ::= DOLLARID', 'doublequotedcontent ::= LDEL variable RDEL', + 'doublequotedcontent ::= LDEL expr RDEL', 'doublequotedcontent ::= smartytag', + 'doublequotedcontent ::= TEXT',); + + public function tokenName($tokenType) + { + if ($tokenType === 0) { + return 'End of Input'; + } + if ($tokenType > 0 && $tokenType < count($this->yyTokenName)) { + return $this->yyTokenName[ $tokenType ]; + } else { + return "Unknown"; + } + } + + public static function yy_destructor($yymajor, $yypminor) + { + switch ($yymajor) { + default: + break; /* If no destructor action specified: do nothing */ + } + } + + public function yy_pop_parser_stack() + { + if (empty($this->yystack)) { + return; + } + $yytos = array_pop($this->yystack); + if ($this->yyTraceFILE && $this->yyidx >= 0) { + fwrite($this->yyTraceFILE, + $this->yyTracePrompt . 'Popping ' . $this->yyTokenName[ $yytos->major ] . "\n"); + } + $yymajor = $yytos->major; + self::yy_destructor($yymajor, $yytos->minor); + $this->yyidx--; + + return $yymajor; + } + + public function __destruct() + { + while ($this->yystack !== Array()) { + $this->yy_pop_parser_stack(); + } + if (is_resource($this->yyTraceFILE)) { + fclose($this->yyTraceFILE); + } + } + + public function yy_get_expected_tokens($token) + { + static $res3 = array(); + static $res4 = array(); + $state = $this->yystack[ $this->yyidx ]->stateno; + $expected = self::$yyExpectedTokens[ $state ]; + if (isset($res3[ $state ][ $token ])) { + if ($res3[ $state ][ $token ]) { + return $expected; + } + } else { + if ($res3[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return $expected; + } + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return array_unique($expected); + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][1]; + $nextstate = $this->yy_find_reduce_action($this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][0]); + if (isset(self::$yyExpectedTokens[ $nextstate ])) { + $expected = array_merge($expected, self::$yyExpectedTokens[ $nextstate ]); + if (isset($res4[ $nextstate ][ $token ])) { + if ($res4[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } else { + if ($res4[ $nextstate ][ $token ] = + in_array($token, self::$yyExpectedTokens[ $nextstate ], true)) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return array_unique($expected); + } + } + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new TP_yyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[ $yyruleno ][0]; + $this->yystack[ $this->yyidx ] = $x; + continue 2; + } else if ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return array_unique($expected); + } else if ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return $expected; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + $this->yyidx = $yyidx; + $this->yystack = $stack; + + return array_unique($expected); + } + + public function yy_is_expected_token($token) + { + static $res = array(); + static $res2 = array(); + if ($token === 0) { + return true; // 0 is not part of this + } + $state = $this->yystack[ $this->yyidx ]->stateno; + if (isset($res[ $state ][ $token ])) { + if ($res[ $state ][ $token ]) { + return true; + } + } else { + if ($res[ $state ][ $token ] = in_array($token, self::$yyExpectedTokens[ $state ], true)) { + return true; + } + } + $stack = $this->yystack; + $yyidx = $this->yyidx; + do { + $yyact = $this->yy_find_shift_action($token); + if ($yyact >= self::YYNSTATE && $yyact < self::YYNSTATE + self::YYNRULE) { + // reduce action + $done = 0; + do { + if ($done++ == 100) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // too much recursion prevents proper detection + // so give up + return true; + } + $yyruleno = $yyact - self::YYNSTATE; + $this->yyidx -= self::$yyRuleInfo[ $yyruleno ][1]; + $nextstate = $this->yy_find_reduce_action($this->yystack[ $this->yyidx ]->stateno, + self::$yyRuleInfo[ $yyruleno ][0]); + if (isset($res2[ $nextstate ][ $token ])) { + if ($res2[ $nextstate ][ $token ]) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + } else { + if ($res2[ $nextstate ][ $token ] = (isset(self::$yyExpectedTokens[ $nextstate ]) && + in_array($token, + self::$yyExpectedTokens[ $nextstate ], + true))) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + return true; + } + } + if ($nextstate < self::YYNSTATE) { + // we need to shift a non-terminal + $this->yyidx++; + $x = new TP_yyStackEntry; + $x->stateno = $nextstate; + $x->major = self::$yyRuleInfo[ $yyruleno ][0]; + $this->yystack[ $this->yyidx ] = $x; + continue 2; + } else if ($nextstate == self::YYNSTATE + self::YYNRULE + 1) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + if (!$token) { + // end of input: this is valid + return true; + } + // the last token was just ignored, we can't accept + // by ignoring input, this is in essence ignoring a + // syntax error! + return false; + } else if ($nextstate === self::YY_NO_ACTION) { + $this->yyidx = $yyidx; + $this->yystack = $stack; + // input accepted, but not shifted (I guess) + return true; + } else { + $yyact = $nextstate; + } + } while (true); + } + break; + } while (true); + $this->yyidx = $yyidx; + $this->yystack = $stack; + + return true; + } + + public function yy_find_shift_action($iLookAhead) + { + $stateno = $this->yystack[ $this->yyidx ]->stateno; + + /* if ($this->yyidx < 0) return self::YY_NO_ACTION; */ + if (!isset(self::$yy_shift_ofst[ $stateno ])) { + // no shift actions + return self::$yy_default[ $stateno ]; + } + $i = self::$yy_shift_ofst[ $stateno ]; + if ($i === self::YY_SHIFT_USE_DFLT) { + return self::$yy_default[ $stateno ]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || self::$yy_lookahead[ $i ] != $iLookAhead) { + if (count(self::$yyFallback) && $iLookAhead < count(self::$yyFallback) && + ($iFallback = self::$yyFallback[ $iLookAhead ]) != 0) { + if ($this->yyTraceFILE) { + fwrite($this->yyTraceFILE, + $this->yyTracePrompt . "FALLBACK " . $this->yyTokenName[ $iLookAhead ] . " => " . + $this->yyTokenName[ $iFallback ] . "\n"); + } + + return $this->yy_find_shift_action($iFallback); + } + + return self::$yy_default[ $stateno ]; + } else { + return self::$yy_action[ $i ]; + } + } + + public function yy_find_reduce_action($stateno, $iLookAhead) + { + /* $stateno = $this->yystack[$this->yyidx]->stateno; */ + + if (!isset(self::$yy_reduce_ofst[ $stateno ])) { + return self::$yy_default[ $stateno ]; + } + $i = self::$yy_reduce_ofst[ $stateno ]; + if ($i == self::YY_REDUCE_USE_DFLT) { + return self::$yy_default[ $stateno ]; + } + if ($iLookAhead == self::YYNOCODE) { + return self::YY_NO_ACTION; + } + $i += $iLookAhead; + if ($i < 0 || $i >= self::YY_SZ_ACTTAB || self::$yy_lookahead[ $i ] != $iLookAhead) { + return self::$yy_default[ $stateno ]; + } else { + return self::$yy_action[ $i ]; + } + } + + public function yy_shift($yyNewState, $yyMajor, $yypMinor) + { + $this->yyidx++; + if ($this->yyidx >= self::YYSTACKDEPTH) { + $this->yyidx--; + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sStack Overflow!\n", $this->yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + #line 207 "../smarty/lexer/smarty_internal_templateparser.y" + + $this->internalError = true; + $this->compiler->trigger_template_error("Stack overflow in template parser"); + + return; + } + $yytos = new TP_yyStackEntry; + $yytos->stateno = $yyNewState; + $yytos->major = $yyMajor; + $yytos->minor = $yypMinor; + $this->yystack[] = $yytos; + if ($this->yyTraceFILE && $this->yyidx > 0) { + fprintf($this->yyTraceFILE, + "%sShift %d\n", + $this->yyTracePrompt, + $yyNewState); + fprintf($this->yyTraceFILE, "%sStack:", $this->yyTracePrompt); + for ($i = 1; $i <= $this->yyidx; $i++) { + fprintf($this->yyTraceFILE, + " %s", + $this->yyTokenName[ $this->yystack[ $i ]->major ]); + } + fwrite($this->yyTraceFILE, "\n"); + } + } + + public static $yyRuleInfo = array(array(0 => 62, 1 => 1), array(0 => 63, 1 => 1), array(0 => 63, 1 => 2), + array(0 => 63, 1 => 0), array(0 => 64, 1 => 1), array(0 => 64, 1 => 1), + array(0 => 64, 1 => 1), array(0 => 64, 1 => 1), array(0 => 67, 1 => 1), + array(0 => 67, 1 => 2), array(0 => 64, 1 => 1), array(0 => 64, 1 => 1), + array(0 => 66, 1 => 2), array(0 => 66, 1 => 3), array(0 => 68, 1 => 2), + array(0 => 68, 1 => 0), array(0 => 69, 1 => 1), array(0 => 69, 1 => 1), + array(0 => 65, 1 => 2), array(0 => 65, 1 => 1), array(0 => 70, 1 => 2), + array(0 => 70, 1 => 3), array(0 => 70, 1 => 2), array(0 => 70, 1 => 3), + array(0 => 70, 1 => 2), array(0 => 70, 1 => 3), array(0 => 70, 1 => 4), + array(0 => 70, 1 => 4), array(0 => 70, 1 => 5), array(0 => 70, 1 => 5), + array(0 => 65, 1 => 1), array(0 => 70, 1 => 3), array(0 => 70, 1 => 2), + array(0 => 70, 1 => 4), array(0 => 70, 1 => 5), array(0 => 70, 1 => 6), + array(0 => 70, 1 => 2), array(0 => 70, 1 => 2), array(0 => 70, 1 => 3), + array(0 => 70, 1 => 2), array(0 => 70, 1 => 3), array(0 => 70, 1 => 8), + array(0 => 79, 1 => 2), array(0 => 79, 1 => 1), array(0 => 70, 1 => 5), + array(0 => 70, 1 => 7), array(0 => 70, 1 => 2), array(0 => 70, 1 => 6), + array(0 => 70, 1 => 8), array(0 => 70, 1 => 6), array(0 => 70, 1 => 8), + array(0 => 70, 1 => 3), array(0 => 70, 1 => 4), array(0 => 70, 1 => 2), + array(0 => 65, 1 => 1), array(0 => 70, 1 => 2), array(0 => 70, 1 => 3), + array(0 => 70, 1 => 4), array(0 => 70, 1 => 5), array(0 => 72, 1 => 2), + array(0 => 72, 1 => 1), array(0 => 72, 1 => 0), array(0 => 82, 1 => 4), + array(0 => 82, 1 => 2), array(0 => 82, 1 => 2), array(0 => 82, 1 => 2), + array(0 => 82, 1 => 2), array(0 => 82, 1 => 2), array(0 => 82, 1 => 4), + array(0 => 78, 1 => 1), array(0 => 78, 1 => 3), array(0 => 77, 1 => 3), + array(0 => 77, 1 => 3), array(0 => 77, 1 => 3), array(0 => 77, 1 => 3), + array(0 => 74, 1 => 1), array(0 => 74, 1 => 1), array(0 => 74, 1 => 3), + array(0 => 74, 1 => 3), array(0 => 74, 1 => 3), array(0 => 74, 1 => 1), + array(0 => 74, 1 => 2), array(0 => 74, 1 => 3), array(0 => 74, 1 => 3), + array(0 => 74, 1 => 2), array(0 => 74, 1 => 3), array(0 => 74, 1 => 3), + array(0 => 83, 1 => 7), array(0 => 83, 1 => 7), array(0 => 73, 1 => 1), + array(0 => 73, 1 => 2), array(0 => 73, 1 => 2), array(0 => 73, 1 => 2), + array(0 => 73, 1 => 2), array(0 => 73, 1 => 1), array(0 => 73, 1 => 1), + array(0 => 73, 1 => 3), array(0 => 73, 1 => 2), array(0 => 73, 1 => 2), + array(0 => 73, 1 => 1), array(0 => 73, 1 => 1), array(0 => 73, 1 => 3), + array(0 => 73, 1 => 3), array(0 => 73, 1 => 3), array(0 => 73, 1 => 1), + array(0 => 73, 1 => 1), array(0 => 73, 1 => 3), array(0 => 73, 1 => 1), + array(0 => 73, 1 => 2), array(0 => 73, 1 => 1), array(0 => 73, 1 => 3), + array(0 => 89, 1 => 1), array(0 => 89, 1 => 1), array(0 => 71, 1 => 1), + array(0 => 71, 1 => 1), array(0 => 71, 1 => 3), array(0 => 71, 1 => 1), + array(0 => 71, 1 => 3), array(0 => 71, 1 => 4), array(0 => 71, 1 => 3), + array(0 => 71, 1 => 4), array(0 => 75, 1 => 2), array(0 => 75, 1 => 2), + array(0 => 93, 1 => 2), array(0 => 93, 1 => 0), array(0 => 94, 1 => 2), + array(0 => 94, 1 => 2), array(0 => 94, 1 => 4), array(0 => 94, 1 => 2), + array(0 => 94, 1 => 2), array(0 => 94, 1 => 4), array(0 => 94, 1 => 3), + array(0 => 94, 1 => 5), array(0 => 94, 1 => 3), array(0 => 94, 1 => 3), + array(0 => 94, 1 => 3), array(0 => 94, 1 => 3), array(0 => 94, 1 => 3), + array(0 => 94, 1 => 3), array(0 => 94, 1 => 2), array(0 => 80, 1 => 1), + array(0 => 80, 1 => 1), array(0 => 80, 1 => 2), array(0 => 95, 1 => 1), + array(0 => 95, 1 => 1), array(0 => 95, 1 => 3), array(0 => 92, 1 => 2), + array(0 => 96, 1 => 1), array(0 => 96, 1 => 2), array(0 => 97, 1 => 3), + array(0 => 97, 1 => 3), array(0 => 97, 1 => 5), array(0 => 97, 1 => 6), + array(0 => 97, 1 => 2), array(0 => 88, 1 => 4), array(0 => 98, 1 => 4), + array(0 => 98, 1 => 4), array(0 => 99, 1 => 3), array(0 => 99, 1 => 1), + array(0 => 99, 1 => 0), array(0 => 76, 1 => 3), array(0 => 76, 1 => 2), + array(0 => 100, 1 => 3), array(0 => 100, 1 => 2), array(0 => 81, 1 => 2), + array(0 => 81, 1 => 0), array(0 => 101, 1 => 2), array(0 => 101, 1 => 2), + array(0 => 91, 1 => 1), array(0 => 91, 1 => 2), array(0 => 91, 1 => 1), + array(0 => 91, 1 => 2), array(0 => 91, 1 => 3), array(0 => 86, 1 => 1), + array(0 => 86, 1 => 1), array(0 => 85, 1 => 1), array(0 => 87, 1 => 1), + array(0 => 84, 1 => 3), array(0 => 102, 1 => 1), array(0 => 102, 1 => 3), + array(0 => 102, 1 => 0), array(0 => 103, 1 => 3), array(0 => 103, 1 => 3), + array(0 => 103, 1 => 1), array(0 => 90, 1 => 2), array(0 => 90, 1 => 3), + array(0 => 104, 1 => 2), array(0 => 104, 1 => 1), array(0 => 105, 1 => 3), + array(0 => 105, 1 => 3), array(0 => 105, 1 => 1), array(0 => 105, 1 => 3), + array(0 => 105, 1 => 3), array(0 => 105, 1 => 1), array(0 => 105, 1 => 1),); + + public static $yyReduceMap = array(0 => 0, 1 => 1, 2 => 2, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 16 => 8, 17 => 8, + 43 => 8, 66 => 8, 67 => 8, 75 => 8, 76 => 8, 80 => 8, 89 => 8, 94 => 8, 95 => 8, + 100 => 8, 104 => 8, 105 => 8, 109 => 8, 111 => 8, 116 => 8, 178 => 8, 183 => 8, + 9 => 9, 10 => 10, 11 => 11, 12 => 12, 15 => 12, 13 => 13, 74 => 13, 14 => 14, + 90 => 14, 92 => 14, 93 => 14, 123 => 14, 18 => 18, 19 => 19, 20 => 20, 22 => 20, + 24 => 20, 21 => 21, 23 => 21, 25 => 21, 26 => 26, 27 => 26, 28 => 28, 29 => 29, + 30 => 30, 31 => 31, 32 => 32, 33 => 33, 34 => 34, 35 => 35, 36 => 36, 37 => 37, + 38 => 38, 40 => 38, 39 => 39, 41 => 41, 42 => 42, 44 => 44, 45 => 45, 46 => 46, + 47 => 47, 49 => 47, 48 => 48, 50 => 48, 51 => 51, 52 => 52, 53 => 53, 54 => 54, + 55 => 55, 56 => 56, 57 => 57, 58 => 58, 59 => 59, 60 => 60, 69 => 60, 158 => 60, + 162 => 60, 166 => 60, 167 => 60, 61 => 61, 159 => 61, 165 => 61, 62 => 62, + 63 => 63, 64 => 63, 65 => 65, 143 => 65, 68 => 68, 70 => 70, 71 => 71, 72 => 71, + 73 => 73, 77 => 77, 78 => 78, 79 => 78, 81 => 81, 108 => 81, 82 => 82, 83 => 83, + 84 => 84, 85 => 85, 86 => 86, 87 => 87, 88 => 88, 91 => 91, 96 => 96, 97 => 97, + 98 => 98, 99 => 99, 101 => 101, 102 => 102, 103 => 102, 106 => 106, 107 => 107, + 110 => 110, 112 => 112, 113 => 113, 114 => 114, 115 => 115, 117 => 117, + 118 => 118, 119 => 119, 120 => 120, 121 => 121, 122 => 122, 124 => 124, + 180 => 124, 125 => 125, 126 => 126, 127 => 127, 128 => 128, 129 => 129, + 130 => 130, 138 => 130, 131 => 131, 132 => 132, 133 => 133, 134 => 133, + 136 => 133, 137 => 133, 135 => 135, 139 => 139, 140 => 140, 141 => 141, + 184 => 141, 142 => 142, 144 => 144, 145 => 145, 146 => 146, 147 => 147, + 148 => 148, 149 => 149, 150 => 150, 151 => 151, 152 => 152, 153 => 153, + 154 => 154, 155 => 155, 156 => 156, 157 => 157, 160 => 160, 161 => 161, + 163 => 163, 164 => 164, 168 => 168, 169 => 169, 170 => 170, 171 => 171, + 172 => 172, 173 => 173, 174 => 174, 175 => 175, 176 => 176, 177 => 177, + 179 => 179, 181 => 181, 182 => 182, 185 => 185, 186 => 186, 187 => 187, + 188 => 188, 189 => 188, 191 => 188, 190 => 190, 192 => 192, 193 => 193, + 194 => 194,); + + #line 218 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r0() + { + $this->root_buffer->prepend_array($this, $this->template_prefix); + $this->root_buffer->append_array($this, $this->template_postfix); + $this->_retvalue = $this->root_buffer->to_smarty_php($this); + } + + #line 228 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r1() + { + if ($this->yystack[ $this->yyidx + 0 ]->minor != null) { + $this->current_buffer->append_subtree($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + } + + #line 235 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r2() + { + if ($this->yystack[ $this->yyidx + 0 ]->minor != null) { + // because of possible code injection + $this->current_buffer->append_subtree($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + } + + #line 249 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r4() + { + if ($this->compiler->has_code) { + $this->_retvalue = $this->mergePrefixCode($this->yystack[ $this->yyidx + 0 ]->minor); + } else { + $this->_retvalue = null; + } + $this->compiler->has_variable_string = false; + $this->block_nesting_level = count($this->compiler->_tag_stack); + } + + #line 260 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r5() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Text($this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 264 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r6() + { + $code = $this->compiler->compileTag('private_php', + array(array('code' => $this->yystack[ $this->yyidx + 0 ]->minor), + array('type' => $this->lex->phpType)), + array()); + if ($this->compiler->has_code && !empty($code)) { + $tmp = ''; + foreach ($this->compiler->prefix_code as $code) { + $tmp .= $code; + } + $this->compiler->prefix_code = array(); + $this->_retvalue = + new Smarty_Internal_ParseTree_Tag($this, $this->compiler->processNocacheCode($tmp . $code, true)); + } else { + $this->_retvalue = null; + } + } + + #line 275 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r7() + { + $this->_retvalue = $this->compiler->processText($this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 279 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r8() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 283 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r9() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 288 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r10() + { + $this->strip = true; + } + + #line 292 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r11() + { + $this->strip = false; + } + + #line 297 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r12() + { + $this->_retvalue = ''; + } + + #line 301 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r13() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + #line 305 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r14() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 321 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r18() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + #line 327 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r19() + { + $var = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->lex->ldel_length, -$this->lex->rdel_length), + ' $'); + if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) { + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + array('nocache'), + array('value' => $this->compiler->compileVariable('\'' . + $match[1] . + '\''))); + } else { + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + array(), + array('value' => $this->compiler->compileVariable('\'' . + $var . + '\''))); + } + } + + #line 337 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r20() + { + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + array(), + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + #line 341 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r21() + { + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + $this->yystack[ $this->yyidx + 0 ]->minor, + array('value' => $this->yystack[ $this->yyidx + -1 ]->minor)); + } + + #line 364 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r26() + { + $this->_retvalue = $this->compiler->compileTag('assign', + array(array('value' => $this->yystack[ $this->yyidx + + 0 ]->minor), + array('var' => '\'' . substr($this->yystack[ $this->yyidx + + -2 ]->minor, + 1) . '\''))); + } + + #line 372 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r28() + { + $this->_retvalue = $this->compiler->compileTag('assign', + array_merge(array(array('value' => $this->yystack[ $this->yyidx + + -1 ]->minor), + array('var' => '\'' . + substr($this->yystack[ $this->yyidx + + -3 ]->minor, + 1) . '\'')), + $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + #line 376 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r29() + { + $this->_retvalue = $this->compiler->compileTag('assign', + array_merge(array(array('value' => $this->yystack[ $this->yyidx + + -1 ]->minor), + array('var' => $this->yystack[ $this->yyidx + + -3 ]->minor['var'])), + $this->yystack[ $this->yyidx + 0 ]->minor), + array('smarty_internal_index' => $this->yystack[ $this->yyidx + + -3 ]->minor['smarty_internal_index'])); + } + + #line 381 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r30() + { + $tag = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->lex->ldel_length, -$this->lex->rdel_length)); + if ($tag == 'strip') { + $this->strip = true; + $this->_retvalue = null;; + } else { + if (defined($tag)) { + if ($this->security) { + $this->security->isTrustedConstant($tag, $this->compiler); + } + $this->_retvalue = + $this->compiler->compileTag('private_print_expression', array(), array('value' => $tag)); + } else { + if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { + $this->_retvalue = $this->compiler->compileTag($match[1], array("'nocache'")); + } else { + $this->_retvalue = $this->compiler->compileTag($tag, array()); + } + } + } + } + + #line 403 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r31() + { + if (defined($this->yystack[ $this->yyidx + -1 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + -1 ]->minor, $this->compiler); + } + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + $this->yystack[ $this->yyidx + 0 ]->minor, + array('value' => $this->yystack[ $this->yyidx + + -1 ]->minor)); + } else { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -1 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor); + } + } + + #line 413 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r32() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + array(), + array('value' => $this->yystack[ $this->yyidx + 0 ]->minor)); + } else { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + 0 ]->minor, array()); + } + } + + #line 426 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r33() + { + if (defined($this->yystack[ $this->yyidx + -2 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + -2 ]->minor, $this->compiler); + } + $this->_retvalue = $this->compiler->compileTag('private_print_expression', + $this->yystack[ $this->yyidx + 0 ]->minor, + array('value' => $this->yystack[ $this->yyidx + -2 ]->minor, + 'modifierlist' => $this->yystack[ $this->yyidx + + -1 ]->minor)); + } else { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('modifierlist' => $this->yystack[ $this->yyidx + + -1 ]->minor)); + } + } + + #line 438 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r34() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('object_method' => $this->yystack[ $this->yyidx + + -1 ]->minor)); + } + + #line 443 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r35() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -4 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('modifierlist' => $this->yystack[ $this->yyidx + + -1 ]->minor, + 'object_method' => $this->yystack[ $this->yyidx + + -2 ]->minor)); + } + + #line 448 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r36() + { + $this->_retvalue = $this->compiler->compileTag('make_nocache', + array(array('var' => '\'' . substr($this->yystack[ $this->yyidx + + 0 ]->minor, + 1) . '\''))); + } + + #line 453 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r37() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->lex->ldel_length)); + $this->_retvalue = $this->compiler->compileTag(($tag == 'else if') ? 'elseif' : $tag, + array(), + array('if condition' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 458 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r38() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -2 ]->minor, $this->lex->ldel_length)); + $this->_retvalue = $this->compiler->compileTag(($tag == 'else if') ? 'elseif' : $tag, + $this->yystack[ $this->yyidx + 0 ]->minor, + array('if condition' => $this->yystack[ $this->yyidx + + -1 ]->minor)); + } + + #line 463 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r39() + { + $tag = trim(substr($this->yystack[ $this->yyidx + -1 ]->minor, $this->lex->ldel_length)); + $this->_retvalue = $this->compiler->compileTag(($tag == 'else if') ? 'elseif' : $tag, + array(), + array('if condition' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 474 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r41() + { + $this->_retvalue = $this->compiler->compileTag('for', + array_merge($this->yystack[ $this->yyidx + 0 ]->minor, + array(array('start' => $this->yystack[ $this->yyidx + + -6 ]->minor), + array('ifexp' => $this->yystack[ $this->yyidx + + -4 ]->minor), + array('var' => $this->yystack[ $this->yyidx + + -2 ]->minor), + array('step' => $this->yystack[ $this->yyidx + + -1 ]->minor))), + 1); + } + + #line 478 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r42() + { + $this->_retvalue = '=' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 486 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r44() + { + $this->_retvalue = $this->compiler->compileTag('for', + array_merge($this->yystack[ $this->yyidx + 0 ]->minor, + array(array('start' => $this->yystack[ $this->yyidx + + -3 ]->minor), + array('to' => $this->yystack[ $this->yyidx + + -1 ]->minor))), + 0); + } + + #line 490 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r45() + { + $this->_retvalue = $this->compiler->compileTag('for', + array_merge($this->yystack[ $this->yyidx + 0 ]->minor, + array(array('start' => $this->yystack[ $this->yyidx + + -5 ]->minor), + array('to' => $this->yystack[ $this->yyidx + + -3 ]->minor), + array('step' => $this->yystack[ $this->yyidx + + -1 ]->minor))), + 0); + } + + #line 495 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r46() + { + $this->_retvalue = $this->compiler->compileTag('foreach', $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 500 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r47() + { + $this->_retvalue = $this->compiler->compileTag('foreach', + array_merge($this->yystack[ $this->yyidx + 0 ]->minor, + array(array('from' => $this->yystack[ $this->yyidx + + -3 ]->minor), + array('item' => $this->yystack[ $this->yyidx + + -1 ]->minor)))); + } + + #line 504 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r48() + { + $this->_retvalue = $this->compiler->compileTag('foreach', + array_merge($this->yystack[ $this->yyidx + 0 ]->minor, + array(array('from' => $this->yystack[ $this->yyidx + + -5 ]->minor), + array('item' => $this->yystack[ $this->yyidx + + -1 ]->minor), + array('key' => $this->yystack[ $this->yyidx + + -3 ]->minor)))); + } + + #line 517 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r51() + { + $this->_retvalue = $this->compiler->compileTag('setfilter', + array(), + array('modifier_list' => array(array_merge(array($this->yystack[ $this->yyidx + + -1 ]->minor), + $this->yystack[ $this->yyidx + + 0 ]->minor)))); + } + + #line 521 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r52() + { + $this->_retvalue = $this->compiler->compileTag('setfilter', + array(), + array('modifier_list' => array_merge(array(array_merge(array($this->yystack[ $this->yyidx + + -2 ]->minor), + $this->yystack[ $this->yyidx + + -1 ]->minor)), + $this->yystack[ $this->yyidx + + 0 ]->minor))); + } + + #line 526 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r53() + { + $j = strrpos($this->yystack[ $this->yyidx + 0 ]->minor, '.'); + if ($this->yystack[ $this->yyidx + 0 ]->minor[ $j + 1 ] == 'c') { + // {$smarty.block.child} + $this->_retvalue = $this->compiler->compileTag('block_child', array());; + } else { + // {$smarty.block.parent} + $this->_retvalue = $this->compiler->compileTag('block_parent', array());; + } + } + + #line 539 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r54() + { + $tag = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->lex->ldel_length, -$this->lex->rdel_length), + ' /'); + if ($tag == 'strip') { + $this->strip = false; + $this->_retvalue = null; + } else { + $this->_retvalue = $this->compiler->compileTag($tag . 'close', array()); + } + } + + #line 548 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r55() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + 0 ]->minor . 'close', array()); + } + + #line 552 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r56() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -1 ]->minor . 'close', + array(), + array('modifier_list' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 557 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r57() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -2 ]->minor . 'close', + array(), + array('object_method' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 561 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r58() + { + $this->_retvalue = $this->compiler->compileTag($this->yystack[ $this->yyidx + -3 ]->minor . 'close', + array(), + array('object_method' => $this->yystack[ $this->yyidx + + -1 ]->minor, + 'modifier_list' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 569 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r59() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + $this->_retvalue[] = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 575 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r60() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 580 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r61() + { + $this->_retvalue = array(); + } + + #line 585 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r62() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = + array($this->yystack[ $this->yyidx + -2 ]->minor => $this->yystack[ $this->yyidx + 0 ]->minor); + } else { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -2 ]->minor => '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . + '\''); + } + } + + #line 596 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r63() + { + $this->_retvalue = + array(trim($this->yystack[ $this->yyidx + -1 ]->minor, " =\n\r\t") => $this->yystack[ $this->yyidx + + 0 ]->minor); + } + + #line 604 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r65() + { + $this->_retvalue = '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\''; + } + + #line 616 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r68() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -2 ]->minor => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 629 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r70() + { + $this->yystack[ $this->yyidx + -2 ]->minor[] = $this->yystack[ $this->yyidx + 0 ]->minor; + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor; + } + + #line 634 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r71() + { + $this->_retvalue = array('var' => '\'' . substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . '\'', + 'value' => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 641 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r73() + { + $this->_retvalue = array('var' => $this->yystack[ $this->yyidx + -2 ]->minor, + 'value' => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 665 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r77() + { + $this->_retvalue = + '$_smarty_tpl->getStreamVariable(\'' . substr($this->yystack[ $this->yyidx + -2 ]->minor, 1) . '://' . + $this->yystack[ $this->yyidx + 0 ]->minor . '\')'; + } + + #line 670 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r78() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . trim($this->yystack[ $this->yyidx + -1 ]->minor) . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 684 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r81() + { + $this->_retvalue = $this->compiler->compileTag('private_modifier', + array(), + array('value' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'modifierlist' => $this->yystack[ $this->yyidx + + 0 ]->minor)); + } + + #line 690 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r82() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -1 ]->minor['pre'] . $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + -1 ]->minor['op'] . $this->yystack[ $this->yyidx + 0 ]->minor . ')'; + } + + #line 694 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r83() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 698 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r84() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + #line 702 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r85() + { + $this->_retvalue = + 'in_array(' . $this->yystack[ $this->yyidx + -2 ]->minor . ',' . $this->yystack[ $this->yyidx + 0 ]->minor . + ')'; + } + + #line 706 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r86() + { + $this->_retvalue = 'in_array(' . $this->yystack[ $this->yyidx + -2 ]->minor . ',(array)' . + $this->yystack[ $this->yyidx + 0 ]->minor . ')'; + } + + #line 714 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r87() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -5 ]->minor . ' ? ' . $this->compiler->compileVariable('\'' . + substr($this->yystack[ $this->yyidx + + -2 ]->minor, + 1) . + '\'') . + ' : ' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 718 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r88() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -5 ]->minor . ' ? ' . $this->yystack[ $this->yyidx + -2 ]->minor . ' : ' . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 733 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r91() + { + $this->_retvalue = '!' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 754 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r96() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 758 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r97() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.'; + } + + #line 762 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r98() + { + $this->_retvalue = '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 767 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r99() + { + if (defined($this->yystack[ $this->yyidx + 0 ]->minor)) { + if ($this->security) { + $this->security->isTrustedConstant($this->yystack[ $this->yyidx + 0 ]->minor, $this->compiler); + } + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } else { + $this->_retvalue = '\'' . $this->yystack[ $this->yyidx + 0 ]->minor . '\''; + } + } + + #line 784 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r101() + { + $this->_retvalue = "(" . $this->yystack[ $this->yyidx + -1 ]->minor . ")"; + } + + #line 788 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r102() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + -1 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 806 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r106() + { + $prefixVar = $this->compiler->getNewPrefixVariable(); + if ($this->yystack[ $this->yyidx + -2 ]->minor['var'] == '\'smarty\'') { + $this->compiler->appendPrefixCode("compiler->compileTag('private_special_variable', + array(), + $this->yystack[ $this->yyidx + + -2 ]->minor['smarty_internal_index']) . + ';?>'); + } else { + $this->compiler->appendPrefixCode("compiler->compileVariable($this->yystack[ $this->yyidx + + -2 ]->minor['var']) . + $this->yystack[ $this->yyidx + -2 ]->minor['smarty_internal_index'] . + ';?>'); + } + $this->_retvalue = $prefixVar . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[0] . + $this->yystack[ $this->yyidx + 0 ]->minor[1]; + } + + #line 817 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r107() + { + $prefixVar = $this->compiler->getNewPrefixVariable(); + $tmp = $this->compiler->appendCode('', $this->yystack[ $this->yyidx + 0 ]->minor); + $this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "')); + $this->_retvalue = $prefixVar; + } + + #line 834 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r110() + { + if (!in_array(strtolower($this->yystack[ $this->yyidx + -2 ]->minor), array('self', 'parent')) && + (!$this->security || $this->security->isTrustedStaticClassAccess($this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor, + $this->compiler))) { + if (isset($this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ])) { + $this->_retvalue = + $this->smarty->registered_classes[ $this->yystack[ $this->yyidx + -2 ]->minor ] . '::' . + $this->yystack[ $this->yyidx + 0 ]->minor[0] . $this->yystack[ $this->yyidx + 0 ]->minor[1]; + } else { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . '::' . $this->yystack[ $this->yyidx + 0 ]->minor[0] . + $this->yystack[ $this->yyidx + 0 ]->minor[1]; + } + } else { + $this->compiler->trigger_template_error("static class '" . $this->yystack[ $this->yyidx + -2 ]->minor . + "' is undefined or not allowed by security setting"); + } + } + + #line 853 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r112() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 864 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r113() + { + $this->_retvalue = + $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''); + } + + #line 867 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r114() + { + if ($this->yystack[ $this->yyidx + 0 ]->minor['var'] == '\'smarty\'') { + $smarty_var = $this->compiler->compileTag('private_special_variable', + array(), + $this->yystack[ $this->yyidx + + 0 ]->minor['smarty_internal_index']); + $this->_retvalue = $smarty_var; + } else { + // used for array reset,next,prev,end,current + $this->last_variable = $this->yystack[ $this->yyidx + 0 ]->minor['var']; + $this->last_index = $this->yystack[ $this->yyidx + 0 ]->minor['smarty_internal_index']; + $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor['var']) . + $this->yystack[ $this->yyidx + 0 ]->minor['smarty_internal_index']; + } + } + + #line 880 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r115() + { + $this->_retvalue = '$_smarty_tpl->tpl_vars[' . $this->yystack[ $this->yyidx + -2 ]->minor . ']->' . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 890 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r117() + { + $this->_retvalue = + $this->compiler->compileConfigVariable("'" . $this->yystack[ $this->yyidx + -1 ]->minor . "'"); + } + + #line 894 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r118() + { + $this->_retvalue = '(is_array($tmp = ' . + $this->compiler->compileConfigVariable("'" . $this->yystack[ $this->yyidx + -2 ]->minor . + "'") . ') ? $tmp' . + $this->yystack[ $this->yyidx + 0 ]->minor . ' :null)'; + } + + #line 898 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r119() + { + $this->_retvalue = $this->compiler->compileConfigVariable($this->yystack[ $this->yyidx + -1 ]->minor); + } + + #line 902 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r120() + { + $this->_retvalue = + '(is_array($tmp = ' . $this->compiler->compileConfigVariable($this->yystack[ $this->yyidx + -2 ]->minor) . + ') ? $tmp' . $this->yystack[ $this->yyidx + 0 ]->minor . ' : null)'; + } + + #line 906 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r121() + { + $this->_retvalue = array('var' => '\'' . substr($this->yystack[ $this->yyidx + -1 ]->minor, 1) . '\'', + 'smarty_internal_index' => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 909 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r122() + { + $this->_retvalue = array('var' => $this->yystack[ $this->yyidx + -1 ]->minor, + 'smarty_internal_index' => $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 922 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r124() + { + return; + } + + #line 928 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r125() + { + $this->_retvalue = + '[' . $this->compiler->compileVariable('\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\'') . + ']'; + } + + #line 931 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r126() + { + $this->_retvalue = '[' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + 0 ]->minor) . ']'; + } + + #line 935 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r127() + { + $this->_retvalue = '[' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + -2 ]->minor) . '->' . + $this->yystack[ $this->yyidx + 0 ]->minor . ']'; + } + + #line 939 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r128() + { + $this->_retvalue = "['" . $this->yystack[ $this->yyidx + 0 ]->minor . "']"; + } + + #line 943 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r129() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + 0 ]->minor . ']'; + } + + #line 948 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r130() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; + } + + #line 953 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r131() + { + $this->_retvalue = '[' . $this->compiler->compileTag('private_special_variable', + array(), + '[\'section\'][\'' . + $this->yystack[ $this->yyidx + -1 ]->minor . + '\'][\'index\']') . ']'; + } + + #line 957 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r132() + { + $this->_retvalue = '[' . $this->compiler->compileTag('private_special_variable', + array(), + '[\'section\'][\'' . + $this->yystack[ $this->yyidx + -3 ]->minor . '\'][\'' . + $this->yystack[ $this->yyidx + -1 ]->minor . '\']') . ']'; + } + + #line 960 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r133() + { + $this->_retvalue = '[' . $this->yystack[ $this->yyidx + -1 ]->minor . ']'; + } + + #line 966 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r135() + { + $this->_retvalue = '[' . $this->compiler->compileVariable('\'' . + substr($this->yystack[ $this->yyidx + -1 ]->minor, + 1) . '\'') . ']';; + } + + #line 982 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r139() + { + $this->_retvalue = '[]'; + } + + #line 992 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r140() + { + $this->_retvalue = '\'' . substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . '\''; + } + + #line 996 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r141() + { + $this->_retvalue = "''"; + } + + #line 1001 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r142() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . '.' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1009 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r144() + { + $var = + trim(substr($this->yystack[ $this->yyidx + 0 ]->minor, $this->lex->ldel_length, -$this->lex->rdel_length), + ' $'); + $this->_retvalue = $this->compiler->compileVariable('\'' . $var . '\''); + } + + #line 1015 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r145() + { + $this->_retvalue = '(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + #line 1022 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r146() + { + if ($this->yystack[ $this->yyidx + -1 ]->minor['var'] == '\'smarty\'') { + $this->_retvalue = $this->compiler->compileTag('private_special_variable', + array(), + $this->yystack[ $this->yyidx + + -1 ]->minor['smarty_internal_index']) . + $this->yystack[ $this->yyidx + 0 ]->minor; + } else { + $this->_retvalue = $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor['var']) . + $this->yystack[ $this->yyidx + -1 ]->minor['smarty_internal_index'] . + $this->yystack[ $this->yyidx + 0 ]->minor; + } + } + + #line 1031 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r147() + { + $this->_retvalue = $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1036 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r148() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1041 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r149() + { + if ($this->security && substr($this->yystack[ $this->yyidx + -1 ]->minor, 0, 1) == '_') { + $this->compiler->trigger_template_error(self::Err1); + } + $this->_retvalue = + '->' . $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1048 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r150() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::Err2); + } + $this->_retvalue = '->{' . $this->compiler->compileVariable($this->yystack[ $this->yyidx + -1 ]->minor) . + $this->yystack[ $this->yyidx + 0 ]->minor . '}'; + } + + #line 1055 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r151() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::Err2); + } + $this->_retvalue = + '->{' . $this->yystack[ $this->yyidx + -2 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor . '}'; + } + + #line 1062 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r152() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::Err2); + } + $this->_retvalue = + '->{\'' . $this->yystack[ $this->yyidx + -4 ]->minor . '\'.' . $this->yystack[ $this->yyidx + -2 ]->minor . + $this->yystack[ $this->yyidx + 0 ]->minor . '}'; + } + + #line 1070 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r153() + { + $this->_retvalue = '->' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1078 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r154() + { + $this->_retvalue = $this->compiler->compilePHPFunctionCall($this->yystack[ $this->yyidx + -3 ]->minor, + $this->yystack[ $this->yyidx + -1 ]->minor); + } + + #line 1086 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r155() + { + if ($this->security && substr($this->yystack[ $this->yyidx + -3 ]->minor, 0, 1) == '_') { + $this->compiler->trigger_template_error(self::Err1); + } + $this->_retvalue = $this->yystack[ $this->yyidx + -3 ]->minor . "(" . + implode(',', $this->yystack[ $this->yyidx + -1 ]->minor) . ")"; + } + + #line 1093 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r156() + { + if ($this->security) { + $this->compiler->trigger_template_error(self::Err2); + } + $prefixVar = $this->compiler->getNewPrefixVariable(); + $this->compiler->appendPrefixCode("compiler->compileVariable('\'' . + substr($this->yystack[ $this->yyidx + + -3 ]->minor, + 1) . + '\'') . ';?>'); + $this->_retvalue = $prefixVar . '(' . implode(',', $this->yystack[ $this->yyidx + -1 ]->minor) . ')'; + } + + #line 1104 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r157() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -2 ]->minor, array($this->yystack[ $this->yyidx + 0 ]->minor)); + } + + #line 1121 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r160() + { + $this->_retvalue = array_merge($this->yystack[ $this->yyidx + -2 ]->minor, + array(array_merge($this->yystack[ $this->yyidx + -1 ]->minor, + $this->yystack[ $this->yyidx + 0 ]->minor))); + } + + #line 1125 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r161() + { + $this->_retvalue = + array(array_merge($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor)); + } + + #line 1133 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r163() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 1141 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r164() + { + $this->_retvalue = + array_merge($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 1160 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r168() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, '', 'method'); + } + + #line 1165 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r169() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor, 'method'); + } + + #line 1170 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r170() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + 0 ]->minor, ''); + } + + #line 1175 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r171() + { + $this->_retvalue = + array($this->yystack[ $this->yyidx + -1 ]->minor, $this->yystack[ $this->yyidx + 0 ]->minor, 'property'); + } + + #line 1180 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r172() + { + $this->_retvalue = array($this->yystack[ $this->yyidx + -2 ]->minor, + $this->yystack[ $this->yyidx + -1 ]->minor . $this->yystack[ $this->yyidx + 0 ]->minor, + 'property'); + } + + #line 1186 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r173() + { + $this->_retvalue = ' ' . trim($this->yystack[ $this->yyidx + 0 ]->minor) . ' '; + } + + #line 1190 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r174() + { + static $lops = + array('eq' => ' == ', 'ne' => ' != ', 'neq' => ' != ', 'gt' => ' > ', 'ge' => ' >= ', 'gte' => ' >= ', + 'lt' => ' < ', 'le' => ' <= ', 'lte' => ' <= ', 'mod' => ' % ', 'and' => ' && ', 'or' => ' || ', + 'xor' => ' xor ',); + $op = strtolower(preg_replace('/\s*/', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $lops[ $op ]; + } + + #line 1209 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r175() + { + static $tlops = + array('isdivby' => array('op' => ' % ', 'pre' => '!('), 'isnotdivby' => array('op' => ' % ', 'pre' => '('), + 'isevenby' => array('op' => ' / ', 'pre' => '!(1 & '), + 'isnotevenby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isoddby' => array('op' => ' / ', 'pre' => '(1 & '), + 'isnotoddby' => array('op' => ' / ', 'pre' => '!(1 & '),); + $op = strtolower(preg_replace('/\s*/', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $tlops[ $op ]; + } + + #line 1222 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r176() + { + static $scond = + array('iseven' => '!(1 & ', 'isnoteven' => '(1 & ', 'isodd' => '(1 & ', 'isnotodd' => '!(1 & ',); + $op = strtolower(str_replace(' ', '', $this->yystack[ $this->yyidx + 0 ]->minor)); + $this->_retvalue = $scond[ $op ]; + } + + #line 1236 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r177() + { + $this->_retvalue = 'array(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'; + } + + #line 1244 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r179() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -2 ]->minor . ',' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1252 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r181() + { + $this->_retvalue = + $this->yystack[ $this->yyidx + -2 ]->minor . '=>' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1256 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r182() + { + $this->_retvalue = + '\'' . $this->yystack[ $this->yyidx + -2 ]->minor . '\'=>' . $this->yystack[ $this->yyidx + 0 ]->minor; + } + + #line 1272 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r185() + { + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor->to_smarty_php($this); + } + + #line 1277 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r186() + { + $this->yystack[ $this->yyidx + -1 ]->minor->append_subtree($this, $this->yystack[ $this->yyidx + 0 ]->minor); + $this->_retvalue = $this->yystack[ $this->yyidx + -1 ]->minor; + } + + #line 1282 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r187() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Dq($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 1286 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r188() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)' . $this->yystack[ $this->yyidx + -1 ]->minor); + } + + #line 1294 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r190() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Code('(string)$_smarty_tpl->tpl_vars[\'' . + substr($this->yystack[ $this->yyidx + 0 ]->minor, 1) . + '\']->value'); + } + + #line 1302 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r192() + { + $this->_retvalue = + new Smarty_Internal_ParseTree_Code('(string)(' . $this->yystack[ $this->yyidx + -1 ]->minor . ')'); + } + + #line 1306 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r193() + { + $this->_retvalue = new Smarty_Internal_ParseTree_Tag($this, $this->yystack[ $this->yyidx + 0 ]->minor); + } + + #line 1310 "../smarty/lexer/smarty_internal_templateparser.y" + function yy_r194() + { + $this->_retvalue = new Smarty_Internal_ParseTree_DqContent($this->yystack[ $this->yyidx + 0 ]->minor); + } + + private $_retvalue; + + public function yy_reduce($yyruleno) + { + if ($this->yyTraceFILE && $yyruleno >= 0 && $yyruleno < count(self::$yyRuleName)) { + fprintf($this->yyTraceFILE, + "%sReduce (%d) [%s].\n", + $this->yyTracePrompt, + $yyruleno, + self::$yyRuleName[ $yyruleno ]); + } + + $this->_retvalue = $yy_lefthand_side = null; + if (isset(self::$yyReduceMap[ $yyruleno ])) { + // call the action + $this->_retvalue = null; + $this->{'yy_r' . self::$yyReduceMap[ $yyruleno ]}(); + $yy_lefthand_side = $this->_retvalue; + } + $yygoto = self::$yyRuleInfo[ $yyruleno ][0]; + $yysize = self::$yyRuleInfo[ $yyruleno ][1]; + $this->yyidx -= $yysize; + for ($i = $yysize; $i; $i--) { + // pop all of the right-hand side parameters + array_pop($this->yystack); + } + $yyact = $this->yy_find_reduce_action($this->yystack[ $this->yyidx ]->stateno, $yygoto); + if ($yyact < self::YYNSTATE) { + if (!$this->yyTraceFILE && $yysize) { + $this->yyidx++; + $x = new TP_yyStackEntry; + $x->stateno = $yyact; + $x->major = $yygoto; + $x->minor = $yy_lefthand_side; + $this->yystack[ $this->yyidx ] = $x; + } else { + $this->yy_shift($yyact, $yygoto, $yy_lefthand_side); + } + } else if ($yyact == self::YYNSTATE + self::YYNRULE + 1) { + $this->yy_accept(); + } + } + + public function yy_parse_failed() + { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sFail!\n", $this->yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + } + + public function yy_syntax_error($yymajor, $TOKEN) + { + #line 200 "../smarty/lexer/smarty_internal_templateparser.y" + + $this->internalError = true; + $this->yymajor = $yymajor; + $this->compiler->trigger_template_error(); + } + + public function yy_accept() + { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, "%sAccept!\n", $this->yyTracePrompt); + } + while ($this->yyidx >= 0) { + $this->yy_pop_parser_stack(); + } + #line 193 "../smarty/lexer/smarty_internal_templateparser.y" + + $this->successful = !$this->internalError; + $this->internalError = false; + $this->retvalue = $this->_retvalue; + } + + public function doParse($yymajor, $yytokenvalue) + { + $yyerrorhit = 0; /* True if yymajor has invoked an error */ + + if ($this->yyidx === null || $this->yyidx < 0) { + $this->yyidx = 0; + $this->yyerrcnt = -1; + $x = new TP_yyStackEntry; + $x->stateno = 0; + $x->major = 0; + $this->yystack = array(); + $this->yystack[] = $x; + } + $yyendofinput = ($yymajor == 0); + + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sInput %s\n", + $this->yyTracePrompt, + $this->yyTokenName[ $yymajor ]); + } + + do { + $yyact = $this->yy_find_shift_action($yymajor); + if ($yymajor < self::YYERRORSYMBOL && !$this->yy_is_expected_token($yymajor)) { + // force a syntax error + $yyact = self::YY_ERROR_ACTION; + } + if ($yyact < self::YYNSTATE) { + $this->yy_shift($yyact, $yymajor, $yytokenvalue); + $this->yyerrcnt--; + if ($yyendofinput && $this->yyidx >= 0) { + $yymajor = 0; + } else { + $yymajor = self::YYNOCODE; + } + } else if ($yyact < self::YYNSTATE + self::YYNRULE) { + $this->yy_reduce($yyact - self::YYNSTATE); + } else if ($yyact == self::YY_ERROR_ACTION) { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sSyntax Error!\n", + $this->yyTracePrompt); + } + if (self::YYERRORSYMBOL) { + if ($this->yyerrcnt < 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $yymx = $this->yystack[ $this->yyidx ]->major; + if ($yymx == self::YYERRORSYMBOL || $yyerrorhit) { + if ($this->yyTraceFILE) { + fprintf($this->yyTraceFILE, + "%sDiscard input token %s\n", + $this->yyTracePrompt, + $this->yyTokenName[ $yymajor ]); + } + $this->yy_destructor($yymajor, $yytokenvalue); + $yymajor = self::YYNOCODE; + } else { + while ($this->yyidx >= 0 && $yymx != self::YYERRORSYMBOL && + ($yyact = $this->yy_find_shift_action(self::YYERRORSYMBOL)) >= self::YYNSTATE) { + $this->yy_pop_parser_stack(); + } + if ($this->yyidx < 0 || $yymajor == 0) { + $this->yy_destructor($yymajor, $yytokenvalue); + $this->yy_parse_failed(); + $yymajor = self::YYNOCODE; + } else if ($yymx != self::YYERRORSYMBOL) { + $u2 = 0; + $this->yy_shift($yyact, self::YYERRORSYMBOL, $u2); + } + } + $this->yyerrcnt = 3; + $yyerrorhit = 1; + } else { + if ($this->yyerrcnt <= 0) { + $this->yy_syntax_error($yymajor, $yytokenvalue); + } + $this->yyerrcnt = 3; + $this->yy_destructor($yymajor, $yytokenvalue); + if ($yyendofinput) { + $this->yy_parse_failed(); + } + $yymajor = self::YYNOCODE; + } + } else { + $this->yy_accept(); + $yymajor = self::YYNOCODE; + } + } while ($yymajor != self::YYNOCODE && $this->yyidx >= 0); + } +} + diff --git a/libs/sysplugins/smarty_internal_testinstall.php b/libs/sysplugins/smarty_internal_testinstall.php new file mode 100644 index 0000000..e3b7dab --- /dev/null +++ b/libs/sysplugins/smarty_internal_testinstall.php @@ -0,0 +1,599 @@ +\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->ext->_getIncludePath->getIncludePath($_template_dir, null, $smarty); + } + + 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; + } + } else if (!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; + } + } else if (!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; + } + } else if (!is_readable($_compile_dir)) { + $status = false; + $message = "FAILED: {$_compile_dir} is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors['compile_dir'] = $message; + } + } else if (!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->ext->_getIncludePath->getIncludePath($_plugin_dir, null, $smarty); + } + + 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; + } + } else if (!is_readable($plugin_dir)) { + $status = false; + $message = "FAILED: $plugin_dir is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors['plugins_dir'] = $message; + } + } else if ($_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"; + } else if (!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; + } + } else if (!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; + } + } else if (!is_readable($_cache_dir)) { + $status = false; + $message = "FAILED: {$_cache_dir} is not readable"; + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors['cache_dir'] = $message; + } + } else if (!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; + // 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->ext->_getIncludePath->getIncludePath($_config_dir, null, $smarty); + } + + 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; + } + } else if (!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)) { + $expectedSysplugins = array('smartycompilerexception.php' => true, 'smartyexception.php' => true, + 'smarty_cacheresource.php' => true, 'smarty_cacheresource_custom.php' => true, + 'smarty_cacheresource_keyvaluestore.php' => true, 'smarty_data.php' => true, + 'smarty_internal_block.php' => true, + 'smarty_internal_cacheresource_file.php' => true, + 'smarty_internal_compilebase.php' => true, + 'smarty_internal_compile_append.php' => true, + 'smarty_internal_compile_assign.php' => true, + 'smarty_internal_compile_block.php' => true, + 'smarty_internal_compile_block_child.php' => true, + 'smarty_internal_compile_block_parent.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_make_nocache.php' => true, + 'smarty_internal_compile_nocache.php' => true, + 'smarty_internal_compile_private_block_plugin.php' => true, + 'smarty_internal_compile_private_foreachsection.php' => true, + 'smarty_internal_compile_private_function_plugin.php' => true, + 'smarty_internal_compile_private_modifier.php' => true, + 'smarty_internal_compile_private_object_block_function.php' => true, + 'smarty_internal_compile_private_object_function.php' => true, + 'smarty_internal_compile_private_php.php' => true, + 'smarty_internal_compile_private_print_expression.php' => true, + 'smarty_internal_compile_private_registered_block.php' => true, + 'smarty_internal_compile_private_registered_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_shared_inheritance.php' => true, + 'smarty_internal_compile_while.php' => true, + 'smarty_internal_configfilelexer.php' => true, + 'smarty_internal_configfileparser.php' => true, + 'smarty_internal_config_file_compiler.php' => true, + 'smarty_internal_data.php' => true, 'smarty_internal_debug.php' => true, + 'smarty_internal_extension_handler.php' => true, + 'smarty_internal_method_addautoloadfilters.php' => true, + 'smarty_internal_method_adddefaultmodifiers.php' => true, + 'smarty_internal_method_append.php' => true, + 'smarty_internal_method_appendbyref.php' => true, + 'smarty_internal_method_assignbyref.php' => true, + 'smarty_internal_method_assignglobal.php' => true, + 'smarty_internal_method_clearallassign.php' => true, + 'smarty_internal_method_clearallcache.php' => true, + 'smarty_internal_method_clearassign.php' => true, + 'smarty_internal_method_clearcache.php' => true, + 'smarty_internal_method_clearcompiledtemplate.php' => true, + 'smarty_internal_method_clearconfig.php' => true, + 'smarty_internal_method_compileallconfig.php' => true, + 'smarty_internal_method_compilealltemplates.php' => true, + 'smarty_internal_method_configload.php' => true, + 'smarty_internal_method_createdata.php' => true, + 'smarty_internal_method_getautoloadfilters.php' => true, + 'smarty_internal_method_getconfigvariable.php' => true, + 'smarty_internal_method_getconfigvars.php' => true, + 'smarty_internal_method_getdebugtemplate.php' => true, + 'smarty_internal_method_getdefaultmodifiers.php' => true, + 'smarty_internal_method_getglobal.php' => true, + 'smarty_internal_method_getregisteredobject.php' => true, + 'smarty_internal_method_getstreamvariable.php' => true, + 'smarty_internal_method_gettags.php' => true, + 'smarty_internal_method_gettemplatevars.php' => true, + 'smarty_internal_method_loadfilter.php' => true, + 'smarty_internal_method_loadplugin.php' => true, + 'smarty_internal_method_mustcompile.php' => true, + 'smarty_internal_method_registercacheresource.php' => true, + 'smarty_internal_method_registerclass.php' => true, + 'smarty_internal_method_registerdefaultconfighandler.php' => true, + 'smarty_internal_method_registerdefaultpluginhandler.php' => true, + 'smarty_internal_method_registerdefaulttemplatehandler.php' => true, + 'smarty_internal_method_registerfilter.php' => true, + 'smarty_internal_method_registerobject.php' => true, + 'smarty_internal_method_registerplugin.php' => true, + 'smarty_internal_method_registerresource.php' => true, + 'smarty_internal_method_setautoloadfilters.php' => true, + 'smarty_internal_method_setdebugtemplate.php' => true, + 'smarty_internal_method_setdefaultmodifiers.php' => true, + 'smarty_internal_method_unloadfilter.php' => true, + 'smarty_internal_method_unregistercacheresource.php' => true, + 'smarty_internal_method_unregisterfilter.php' => true, + 'smarty_internal_method_unregisterobject.php' => true, + 'smarty_internal_method_unregisterplugin.php' => true, + 'smarty_internal_method_unregisterresource.php' => true, + 'smarty_internal_nocache_insert.php' => true, + 'smarty_internal_parsetree.php' => true, + 'smarty_internal_parsetree_code.php' => true, + 'smarty_internal_parsetree_dq.php' => true, + 'smarty_internal_parsetree_dqcontent.php' => true, + 'smarty_internal_parsetree_tag.php' => true, + 'smarty_internal_parsetree_template.php' => true, + 'smarty_internal_parsetree_text.php' => true, + 'smarty_internal_resource_eval.php' => true, + 'smarty_internal_resource_extends.php' => true, + 'smarty_internal_resource_file.php' => true, + 'smarty_internal_resource_php.php' => true, + 'smarty_internal_resource_registered.php' => true, + 'smarty_internal_resource_stream.php' => true, + 'smarty_internal_resource_string.php' => true, + 'smarty_internal_runtime_cachemodify.php' => true, + 'smarty_internal_runtime_cacheresourcefile.php' => true, + 'smarty_internal_runtime_capture.php' => true, + 'smarty_internal_runtime_codeframe.php' => true, + 'smarty_internal_runtime_filterhandler.php' => true, + 'smarty_internal_runtime_foreach.php' => true, + 'smarty_internal_runtime_getincludepath.php' => true, + 'smarty_internal_runtime_inheritance.php' => true, + 'smarty_internal_runtime_make_nocache.php' => true, + 'smarty_internal_runtime_tplfunction.php' => true, + 'smarty_internal_runtime_updatecache.php' => true, + 'smarty_internal_runtime_updatescope.php' => true, + 'smarty_internal_runtime_writefile.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_testinstall.php' => true, + 'smarty_internal_undefined.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, + 'smarty_template_cached.php' => true, 'smarty_template_compiled.php' => true, + 'smarty_template_config.php' => true, + 'smarty_template_resource_base.php' => true, + 'smarty_template_source.php' => true, 'smarty_undefined_variable.php' => true, + 'smarty_variable.php' => true,); + $iterator = new DirectoryIterator($source); + foreach ($iterator as $file) { + if (!$file->isDot()) { + $filename = $file->getFilename(); + if (isset($expectedSysplugins[ $filename ])) { + unset($expectedSysplugins[ $filename ]); + } + } + } + if ($expectedSysplugins) { + $status = false; + $message = "FAILED: files missing from libs/sysplugins: " . join(', ', array_keys($expectedSysplugins)); + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors['sysplugins'] = $message; + } + } else if ($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)) { + $expectedPlugins = + 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.mb_wordwrap.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, + 'variablefilter.htmlspecialchars.php' => true,); + $iterator = new DirectoryIterator($source); + foreach ($iterator as $file) { + if (!$file->isDot()) { + $filename = $file->getFilename(); + if (isset($expectedPlugins[ $filename ])) { + unset($expectedPlugins[ $filename ]); + } + } + } + if ($expectedPlugins) { + $status = false; + $message = "FAILED: files missing from libs/plugins: " . join(', ', array_keys($expectedPlugins)); + if ($errors === null) { + echo $message . ".\n"; + } else { + $errors['plugins'] = $message; + } + } else if ($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; + } +} diff --git a/libs/sysplugins/smarty_internal_undefined.php b/libs/sysplugins/smarty_internal_undefined.php new file mode 100644 index 0000000..d6f4bf6 --- /dev/null +++ b/libs/sysplugins/smarty_internal_undefined.php @@ -0,0 +1,68 @@ +class = $class; + } + + /** + * Wrapper for obsolete class Smarty_Internal_Runtime_ValidateCompiled + * + * @param \Smarty_Internal_Template $tpl + * @param array $properties special template properties + * @param bool $cache flag if called from cache file + * + * @return bool false + */ + public function decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false) + { + if ($cache) { + $tpl->cached->valid = false; + } else { + $tpl->mustCompile = true; + } + return false; + } + + /** + * Call error handler for undefined method + * + * @param string $name unknown method-name + * @param array $args argument array + * + * @return mixed + * @throws SmartyException + */ + public function __call($name, $args) + { + if (isset($this->class)) { + throw new SmartyException("undefined extension class '{$this->class}'"); + } else { + throw new SmartyException(get_class($args[ 0 ]) . "->{$name}() undefined method"); + } + } +} \ No newline at end of file diff --git a/libs/sysplugins/smarty_resource.php b/libs/sysplugins/smarty_resource.php new file mode 100644 index 0000000..ea673ea --- /dev/null +++ b/libs/sysplugins/smarty_resource.php @@ -0,0 +1,254 @@ + 'smarty_internal_resource_file.php', + 'string' => 'smarty_internal_resource_string.php', + 'extends' => 'smarty_internal_resource_extends.php', + 'stream' => 'smarty_internal_resource_stream.php', + 'eval' => 'smarty_internal_resource_eval.php', + 'php' => 'smarty_internal_resource_php.php'); + + /** + * Flag if resource does implement populateCompiledFilepath() method + * + * @var bool + */ + public $hasCompiledHandler = false; + + /** + * Load template's source into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + abstract public function getContent(Smarty_Template_Source $source); + + /** + * populate Source Object with meta data from Resource + * + * @param Smarty_Template_Source $source source object + * @param Smarty_Internal_Template $_template template object + */ + abstract public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null); + + /** + * populate Source Object with timestamp and exists from Resource + * + * @param Smarty_Template_Source $source source object + */ + public function populateTimestamp(Smarty_Template_Source $source) + { + // intentionally left blank + } + + /** + * modify resource_name according to resource handlers specifications + * + * @param Smarty $smarty Smarty instance + * @param string $resource_name resource_name to make unique + * @param boolean $isConfig flag for config resource + * + * @return string unique resource name + */ + public function buildUniqueResourceName(Smarty $smarty, $resource_name, $isConfig = false) + { + if ($isConfig) { + if (!isset($smarty->_joined_config_dir)) { + $smarty->getTemplateDir(null, true); + } + return get_class($this) . '#' . $smarty->_joined_config_dir . '#' . $resource_name; + } else { + if (!isset($smarty->_joined_template_dir)) { + $smarty->getTemplateDir(); + } + return get_class($this) . '#' . $smarty->_joined_template_dir . '#' . $resource_name; + } + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename(preg_replace('![^\w]+!', '_', $source->name)); + } + + /** + * Load Resource Handler + * + * @param Smarty $smarty smarty object + * @param string $type name of the resource + * + * @throws SmartyException + * @return Smarty_Resource Resource Handler + */ + public static function load(Smarty $smarty, $type) + { + // try smarty's cache + if (isset($smarty->_cache[ 'resource_handlers' ][ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ]; + } + + // try registered resource + if (isset($smarty->registered_resources[ $type ])) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = + $smarty->registered_resources[ $type ] instanceof Smarty_Resource ? + $smarty->registered_resources[ $type ] : new Smarty_Internal_Resource_Registered(); + } + + // try sysplugins dir + if (isset(self::$sysplugins[ $type ])) { + $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($type); + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } + + // try plugins dir + $_resource_class = 'Smarty_Resource_' . ucfirst($type); + if ($smarty->loadPlugin($_resource_class)) { + if (class_exists($_resource_class, false)) { + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new $_resource_class(); + } else { + $smarty->registerResource($type, + array("smarty_resource_{$type}_source", "smarty_resource_{$type}_timestamp", + "smarty_resource_{$type}_secure", "smarty_resource_{$type}_trusted")); + // give it another try, now that the resource is registered properly + return self::load($smarty, $type); + } + } + + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($type, $_known_stream)) { + // is known stream + if (is_object($smarty->security_policy)) { + $smarty->security_policy->isTrustedStream($type); + } + return $smarty->_cache[ 'resource_handlers' ][ $type ] = new Smarty_Internal_Resource_Stream(); + } + + // TODO: try default_(template|config)_handler + + // give up + throw new SmartyException("Unknown resource type '{$type}'"); + } + + /** + * extract resource_type and resource_name from template_resource and config_resource + * @note "C:/foo.tpl" was forced to file resource up till Smarty 3.1.3 (including). + * + * @param string $resource_name template_resource or config_resource to parse + * @param string $default_resource the default resource_type defined in $smarty + * + * @return array with parsed resource name and type + */ + public static function parseResourceName($resource_name, $default_resource) + { + if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]/', $resource_name, $match)) { + $type = $match[ 1 ]; + $name = substr($resource_name, strlen($match[ 0 ])); + } else { + // no resource given, use default + // or single character before the colon is not a resource type, but part of the filepath + $type = $default_resource; + $name = $resource_name; + } + return array($name, $type); + } + + /** + * modify template_resource according to resource handlers specifications + * + * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance + * @param string $template_resource template_resource to extract resource handler and name of + * + * @return string unique resource name + */ + public static function getUniqueTemplateName($obj, $template_resource) + { + $smarty = $obj->_getSmartyObj(); + list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); + // TODO: optimize for Smarty's internal resource types + $resource = Smarty_Resource::load($smarty, $type); + // go relative to a given template? + $_file_is_dotted = $name[ 0 ] == '.' && ($name[ 1 ] == '.' || $name[ 1 ] == '/'); + if ($obj->_isTplObj() && $_file_is_dotted && + ($obj->source->type == 'file' || $obj->parent->source->type == 'extends') + ) { + $name = $smarty->_realpath(dirname($obj->parent->source->filepath) . $smarty->ds . $name); + } + return $resource->buildUniqueResourceName($smarty, $name); + } + + /* + * Check if resource must check time stamps when when loading complied or cached templates. + * Resources like 'extends' which use source components my disable timestamp checks on own resource. + * + * @return bool + */ + public function checkTimestamps() + { + return true; + } + + /** + * initialize Source Object for given resource + * wrapper for backward compatibility to versions < 3.1.22 + * Either [$_template] or [$smarty, $template_resource] must be specified + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty $smarty smarty object + * @param string $template_resource resource identifier + * + * @return Smarty_Template_Source Source Object + */ + public static function source(Smarty_Internal_Template $_template = null, Smarty $smarty = null, + $template_resource = null) + { + return Smarty_Template_Source::load($_template, $smarty, $template_resource); + } +} + diff --git a/libs/sysplugins/smarty_resource_custom.php b/libs/sysplugins/smarty_resource_custom.php new file mode 100644 index 0000000..77f619e --- /dev/null +++ b/libs/sysplugins/smarty_resource_custom.php @@ -0,0 +1,95 @@ +filepath = $source->type . ':' . substr(preg_replace('/[^A-Za-z0-9.]/','',$source->name),0,25); + $source->uid = sha1($source->type . ':' . $source->name); + + $mtime = $this->fetchTimestamp($source->name); + if ($mtime !== null) { + $source->timestamp = $mtime; + } else { + $this->fetch($source->name, $content, $timestamp); + $source->timestamp = isset($timestamp) ? $timestamp : false; + if (isset($content)) { + $source->content = $content; + } + } + $source->exists = !!$source->timestamp; + } + + /** + * Load template's source into current template object + * + * @param Smarty_Template_Source $source source object + * + * @return string template source + * @throws SmartyException if source cannot be loaded + */ + public function getContent(Smarty_Template_Source $source) + { + $this->fetch($source->name, $content, $timestamp); + if (isset($content)) { + return $content; + } + + throw new SmartyException("Unable to read template {$source->type} '{$source->name}'"); + } + + /** + * Determine basename for compiled filename + * + * @param Smarty_Template_Source $source source object + * + * @return string resource's basename + */ + public function getBasename(Smarty_Template_Source $source) + { + return basename(substr(preg_replace('/[^A-Za-z0-9.]/','',$source->name),0,25)); + } +} diff --git a/libs/sysplugins/smarty_resource_recompiled.php b/libs/sysplugins/smarty_resource_recompiled.php new file mode 100644 index 0000000..7e51d1b --- /dev/null +++ b/libs/sysplugins/smarty_resource_recompiled.php @@ -0,0 +1,92 @@ +compiled; + $compiled->file_dependency = array(); + $compiled->includes = array(); + $compiled->nocache_hash = null; + $compiled->unifunc = null; + $level = ob_get_level(); + ob_start(); + $_smarty_tpl->loadCompiler(); + // call compiler + try { + eval("?>" . $_smarty_tpl->compiler->compileTemplate($_smarty_tpl)); + } + catch (Exception $e) { + unset($_smarty_tpl->compiler); + while (ob_get_level() > $level) { + ob_end_clean(); + } + throw $e; + } + // release compiler object to free memory + unset($_smarty_tpl->compiler); + ob_get_clean(); + $compiled->timestamp = time(); + $compiled->exists = true; + } + + /** + * populate Compiled Object with compiled filepath + * + * @param Smarty_Template_Compiled $compiled compiled object + * @param Smarty_Internal_Template $_template template object + * + * @return void + */ + public function populateCompiledFilepath(Smarty_Template_Compiled $compiled, Smarty_Internal_Template $_template) + { + $compiled->filepath = false; + $compiled->timestamp = false; + $compiled->exists = false; + } + + /* + * Disable timestamp checks for recompiled resource. + * + * @return bool + */ + public function checkTimestamps() + { + return false; + } +} diff --git a/libs/sysplugins/smarty_resource_uncompiled.php b/libs/sysplugins/smarty_resource_uncompiled.php new file mode 100644 index 0000000..554f3ae --- /dev/null +++ b/libs/sysplugins/smarty_resource_uncompiled.php @@ -0,0 +1,49 @@ +filepath = $_template->source->filepath; + $compiled->timestamp = $_template->source->timestamp; + $compiled->exists = $_template->source->exists; + if ($_template->smarty->merge_compiled_includes || $_template->source->handler->checkTimestamps()) { + $compiled->file_dependency[ $_template->source->uid ] = + array($compiled->filepath, $compiled->timestamp, $_template->source->type,); + } + } +} diff --git a/libs/sysplugins/smarty_security.php b/libs/sysplugins/smarty_security.php new file mode 100644 index 0000000..4f75f75 --- /dev/null +++ b/libs/sysplugins/smarty_security.php @@ -0,0 +1,730 @@ +" tags in templates. + * possible values: + *
    + *
  • Smarty::PHP_PASSTHRU -> echo PHP tags as they are
  • + *
  • Smarty::PHP_QUOTE -> escape tags as entities
  • + *
  • Smarty::PHP_REMOVE -> remove php tags
  • + *
  • Smarty::PHP_ALLOW -> execute php tags
  • + *
+ * + * @var integer + */ + public $php_handling = Smarty::PHP_PASSTHRU; + + /** + * This is the list of template directories that are considered secure. + * $template_dir is in this list implicitly. + * + * @var array + */ + public $secure_dir = array(); + + /** + * This is an array of directories where trusted php scripts reside. + * {@link $security} is disabled during their inclusion/execution. + * + * @var array + */ + public $trusted_dir = array(); + + /** + * List of regular expressions (PCRE) that include trusted URIs + * + * @var array + */ + public $trusted_uri = array(); + + /** + * List of trusted constants names + * + * @var array + */ + public $trusted_constants = array(); + + /** + * This is an array of trusted static classes. + * If empty access to all static classes is allowed. + * If set to 'none' none is allowed. + * + * @var array + */ + public $static_classes = array(); + + /** + * This is an nested array of trusted classes and static methods. + * If empty access to all static classes and methods is allowed. + * Format: + * array ( + * 'class_1' => array('method_1', 'method_2'), // allowed methods listed + * 'class_2' => array(), // all methods of class allowed + * ) + * If set to null none is allowed. + * + * @var array + */ + public $trusted_static_methods = array(); + + /** + * This is an array of trusted static properties. + * If empty access to all static classes and properties is allowed. + * Format: + * array ( + * 'class_1' => array('prop_1', 'prop_2'), // allowed properties listed + * 'class_2' => array(), // all properties of class allowed + * ) + * If set to null none is allowed. + * + * @var array + */ + public $trusted_static_properties = array(); + + /** + * This is an array of trusted PHP functions. + * If empty all functions are allowed. + * To disable all PHP functions set $php_functions = null. + * + * @var array + */ + public $php_functions = array('isset', 'empty', 'count', 'sizeof', 'in_array', 'is_array', 'time',); + + /** + * This is an array of trusted PHP modifiers. + * If empty all modifiers are allowed. + * To disable all modifier set $php_modifiers = null. + * + * @var array + */ + public $php_modifiers = array('escape', 'count', 'nl2br',); + + /** + * This is an array of allowed tags. + * If empty no restriction by allowed_tags. + * + * @var array + */ + public $allowed_tags = array(); + + /** + * This is an array of disabled tags. + * If empty no restriction by disabled_tags. + * + * @var array + */ + public $disabled_tags = array(); + + /** + * This is an array of allowed modifier plugins. + * If empty no restriction by allowed_modifiers. + * + * @var array + */ + public $allowed_modifiers = array(); + + /** + * This is an array of disabled modifier plugins. + * If empty no restriction by disabled_modifiers. + * + * @var array + */ + public $disabled_modifiers = array(); + + /** + * This is an array of disabled special $smarty variables. + * + * @var array + */ + public $disabled_special_smarty_vars = array(); + + /** + * This is an array of trusted streams. + * If empty all streams are allowed. + * To disable all streams set $streams = null. + * + * @var array + */ + public $streams = array('file'); + + /** + * + flag if constants can be accessed from template + * + * @var boolean + */ + public $allow_constants = true; + + /** + * + flag if super globals can be accessed from template + * + * @var boolean + */ + public $allow_super_globals = true; + + /** + * max template nesting level + * + * @var int + */ + public $max_template_nesting = 0; + + /** + * current template nesting level + * + * @var int + */ + private $_current_template_nesting = 0; + + /** + * Cache for $resource_dir lookup + * + * @var array + */ + protected $_resource_dir = array(); + + /** + * Cache for $template_dir lookup + * + * @var array + */ + protected $_template_dir = array(); + + /** + * Cache for $config_dir lookup + * + * @var array + */ + protected $_config_dir = array(); + + /** + * Cache for $secure_dir lookup + * + * @var array + */ + protected $_secure_dir = array(); + + /** + * Cache for $php_resource_dir lookup + * + * @var array + */ + protected $_php_resource_dir = null; + + /** + * Cache for $trusted_dir lookup + * + * @var array + */ + protected $_trusted_dir = null; + + /** + * Cache for include path status + * + * @var bool + */ + protected $_include_path_status = false; + + /** + * Cache for $_include_array lookup + * + * @var array + */ + protected $_include_dir = array(); + + /** + * @param Smarty $smarty + */ + public function __construct($smarty) + { + $this->smarty = $smarty; + $this->smarty->_cache[ 'template_dir_new' ] = true; + $this->smarty->_cache[ 'config_dir_new' ] = true; + } + + /** + * Check if PHP function is trusted. + * + * @param string $function_name + * @param object $compiler compiler object + * + * @return boolean true if function is trusted + * @throws SmartyCompilerException if php function is not trusted + */ + public function isTrustedPhpFunction($function_name, $compiler) + { + if (isset($this->php_functions) && + (empty($this->php_functions) || in_array($function_name, $this->php_functions)) + ) { + return true; + } + + $compiler->trigger_template_error("PHP function '{$function_name}' not allowed by security setting"); + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if static class is trusted. + * + * @param string $class_name + * @param object $compiler compiler object + * + * @return boolean true if class is trusted + * @throws SmartyCompilerException if static class is not trusted + */ + public function isTrustedStaticClass($class_name, $compiler) + { + if (isset($this->static_classes) && + (empty($this->static_classes) || in_array($class_name, $this->static_classes)) + ) { + return true; + } + + $compiler->trigger_template_error("access to static class '{$class_name}' not allowed by security setting"); + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if static class method/property is trusted. + * + * @param string $class_name + * @param string $params + * @param object $compiler compiler object + * + * @return boolean true if class method is trusted + * @throws SmartyCompilerException if static class method is not trusted + */ + public function isTrustedStaticClassAccess($class_name, $params, $compiler) + { + if (!isset($params[ 2 ])) { + // fall back + return $this->isTrustedStaticClass($class_name, $compiler); + } + if ($params[ 2 ] == 'method') { + $allowed = $this->trusted_static_methods; + $name = substr($params[ 0 ], 0, strpos($params[ 0 ], '(')); + } else { + $allowed = $this->trusted_static_properties; + // strip '$' + $name = substr($params[ 0 ], 1); + } + if (isset($allowed)) { + if (empty($allowed)) { + // fall back + return $this->isTrustedStaticClass($class_name, $compiler); + } + if (isset($allowed[ $class_name ]) && + (empty($allowed[ $class_name ]) || in_array($name, $allowed[ $class_name ])) + ) { + return true; + } + } + $compiler->trigger_template_error("access to static class '{$class_name}' {$params[2]} '{$name}' not allowed by security setting"); + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if PHP modifier is trusted. + * + * @param string $modifier_name + * @param object $compiler compiler object + * + * @return boolean true if modifier is trusted + * @throws SmartyCompilerException if modifier is not trusted + */ + public function isTrustedPhpModifier($modifier_name, $compiler) + { + if (isset($this->php_modifiers) && + (empty($this->php_modifiers) || in_array($modifier_name, $this->php_modifiers)) + ) { + return true; + } + + $compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting"); + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if tag is trusted. + * + * @param string $tag_name + * @param object $compiler compiler object + * + * @return boolean true if tag is trusted + * @throws SmartyCompilerException if modifier is not trusted + */ + public function isTrustedTag($tag_name, $compiler) + { + // check for internal always required tags + if (in_array($tag_name, + array('assign', 'call', 'private_filter', 'private_block_plugin', 'private_function_plugin', + 'private_object_block_function', 'private_object_function', 'private_registered_function', + 'private_registered_block', 'private_special_variable', 'private_print_expression', + 'private_modifier'))) { + return true; + } + // check security settings + if (empty($this->allowed_tags)) { + if (empty($this->disabled_tags) || !in_array($tag_name, $this->disabled_tags)) { + return true; + } else { + $compiler->trigger_template_error("tag '{$tag_name}' disabled by security setting", null, true); + } + } elseif (in_array($tag_name, $this->allowed_tags) && !in_array($tag_name, $this->disabled_tags)) { + return true; + } else { + $compiler->trigger_template_error("tag '{$tag_name}' not allowed by security setting", null, true); + } + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if special $smarty variable is trusted. + * + * @param string $var_name + * @param object $compiler compiler object + * + * @return boolean true if tag is trusted + * @throws SmartyCompilerException if modifier is not trusted + */ + public function isTrustedSpecialSmartyVar($var_name, $compiler) + { + if (!in_array($var_name, $this->disabled_special_smarty_vars)) { + return true; + } else { + $compiler->trigger_template_error("special variable '\$smarty.{$var_name}' not allowed by security setting", + null, true); + } + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if modifier plugin is trusted. + * + * @param string $modifier_name + * @param object $compiler compiler object + * + * @return boolean true if tag is trusted + * @throws SmartyCompilerException if modifier is not trusted + */ + public function isTrustedModifier($modifier_name, $compiler) + { + // check for internal always allowed modifier + if (in_array($modifier_name, array('default'))) { + return true; + } + // check security settings + if (empty($this->allowed_modifiers)) { + if (empty($this->disabled_modifiers) || !in_array($modifier_name, $this->disabled_modifiers)) { + return true; + } else { + $compiler->trigger_template_error("modifier '{$modifier_name}' disabled by security setting", null, + true); + } + } elseif (in_array($modifier_name, $this->allowed_modifiers) && + !in_array($modifier_name, $this->disabled_modifiers) + ) { + return true; + } else { + $compiler->trigger_template_error("modifier '{$modifier_name}' not allowed by security setting", null, + true); + } + + return false; // should not, but who knows what happens to the compiler in the future? + } + + /** + * Check if constants are enabled or trusted + * + * @param string $const constant name + * @param object $compiler compiler object + * + * @return bool + */ + public function isTrustedConstant($const, $compiler) + { + if (in_array($const, array('true', 'false', 'null'))) { + return true; + } + if (!empty($this->trusted_constants)) { + if (!in_array(strtolower($const), $this->trusted_constants)) { + $compiler->trigger_template_error("Security: access to constant '{$const}' not permitted"); + return false; + } + return true; + } + if ($this->allow_constants) { + return true; + } + $compiler->trigger_template_error("Security: access to constants not permitted"); + return false; + } + + /** + * Check if stream is trusted. + * + * @param string $stream_name + * + * @return boolean true if stream is trusted + * @throws SmartyException if stream is not trusted + */ + public function isTrustedStream($stream_name) + { + if (isset($this->streams) && (empty($this->streams) || in_array($stream_name, $this->streams))) { + return true; + } + + throw new SmartyException("stream '{$stream_name}' not allowed by security setting"); + } + + /** + * Check if directory of file resource is trusted. + * + * @param string $filepath + * @param null|bool $isConfig + * + * @return bool true if directory is trusted + * @throws \SmartyException if directory is not trusted + */ + public function isTrustedResourceDir($filepath, $isConfig = null) + { + if ($this->_include_path_status !== $this->smarty->use_include_path) { + foreach ($this->_include_dir as $directory) { + unset($this->_resource_dir[ $directory ]); + } + if ($this->smarty->use_include_path) { + $this->_include_dir = array(); + $_dirs = $this->smarty->ext->_getIncludePath->getIncludePathDirs($this->smarty); + foreach ($_dirs as $directory) { + $this->_include_dir[] = $directory; + $this->_resource_dir[ $directory ] = true; + } + } + $this->_include_path_status = $this->smarty->use_include_path; + } + if ($isConfig !== true && + (!isset($this->smarty->_cache[ 'template_dir_new' ]) || $this->smarty->_cache[ 'template_dir_new' ]) + ) { + $_dir = $this->smarty->getTemplateDir(); + if ($this->_template_dir !== $_dir) { + foreach ($this->_template_dir as $directory) { + unset($this->_resource_dir[ $directory ]); + } + foreach ($_dir as $directory) { + $this->_resource_dir[ $directory ] = true; + } + $this->_template_dir = $_dir; + } + $this->smarty->_cache[ 'template_dir_new' ] = false; + } + if ($isConfig !== false && + (!isset($this->smarty->_cache[ 'config_dir_new' ]) || $this->smarty->_cache[ 'config_dir_new' ]) + ) { + $_dir = $this->smarty->getConfigDir(); + if ($this->_config_dir !== $_dir) { + foreach ($this->_config_dir as $directory) { + unset($this->_resource_dir[ $directory ]); + } + foreach ($_dir as $directory) { + $this->_resource_dir[ $directory ] = true; + } + $this->_config_dir = $_dir; + } + $this->smarty->_cache[ 'config_dir_new' ] = false; + } + if ($this->_secure_dir !== (array) $this->secure_dir) { + foreach ($this->_secure_dir as $directory) { + unset($this->_resource_dir[ $directory ]); + } + foreach ((array) $this->secure_dir as $directory) { + $directory = $this->smarty->_realpath($directory . DIRECTORY_SEPARATOR, true); + $this->_resource_dir[ $directory ] = true; + } + $this->_secure_dir = (array) $this->secure_dir; + } + $this->_resource_dir = $this->_checkDir($filepath, $this->_resource_dir); + return true; + } + + /** + * Check if URI (e.g. {fetch} or {html_image}) is trusted + * To simplify things, isTrustedUri() resolves all input to "{$PROTOCOL}://{$HOSTNAME}". + * So "http://username:password@hello.world.example.org:8080/some-path?some=query-string" + * is reduced to "http://hello.world.example.org" prior to applying the patters from {@link $trusted_uri}. + * + * @param string $uri + * + * @return boolean true if URI is trusted + * @throws SmartyException if URI is not trusted + * @uses $trusted_uri for list of patterns to match against $uri + */ + public function isTrustedUri($uri) + { + $_uri = parse_url($uri); + if (!empty($_uri[ 'scheme' ]) && !empty($_uri[ 'host' ])) { + $_uri = $_uri[ 'scheme' ] . '://' . $_uri[ 'host' ]; + foreach ($this->trusted_uri as $pattern) { + if (preg_match($pattern, $_uri)) { + return true; + } + } + } + + throw new SmartyException("URI '{$uri}' not allowed by security setting"); + } + + /** + * Check if directory of file resource is trusted. + * + * @param string $filepath + * + * @return boolean true if directory is trusted + * @throws SmartyException if PHP directory is not trusted + */ + public function isTrustedPHPDir($filepath) + { + if (empty($this->trusted_dir)) { + throw new SmartyException("directory '{$filepath}' not allowed by security setting (no trusted_dir specified)"); + } + + // check if index is outdated + if (!$this->_trusted_dir || $this->_trusted_dir !== $this->trusted_dir) { + $this->_php_resource_dir = array(); + + $this->_trusted_dir = $this->trusted_dir; + foreach ((array) $this->trusted_dir as $directory) { + $directory = $this->smarty->_realpath($directory . DIRECTORY_SEPARATOR, true); + $this->_php_resource_dir[ $directory ] = true; + } + } + + $this->_php_resource_dir = + $this->_checkDir($this->smarty->_realpath($filepath, true), $this->_php_resource_dir); + return true; + } + + /** + * Check if file is inside a valid directory + * + * @param string $filepath + * @param array $dirs valid directories + * + * @return array + * @throws \SmartyException + */ + private function _checkDir($filepath, $dirs) + { + $directory = dirname($filepath) . DIRECTORY_SEPARATOR; + $_directory = array(); + while (true) { + // remember the directory to add it to _resource_dir in case we're successful + $_directory[ $directory ] = true; + // test if the directory is trusted + if (isset($dirs[ $directory ])) { + // merge sub directories of current $directory into _resource_dir to speed up subsequent lookup + $dirs = array_merge($dirs, $_directory); + + return $dirs; + } + // abort if we've reached root + if (!preg_match('#[\\\/][^\\\/]+[\\\/]$#', $directory)) { + break; + } + // bubble up one level + $directory = preg_replace('#[\\\/][^\\\/]+[\\\/]$#', DIRECTORY_SEPARATOR, $directory); + } + + // give up + throw new SmartyException("directory '{$filepath}' not allowed by security setting"); + } + + /** + * Loads security class and enables security + * + * @param \Smarty $smarty + * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * + * @return \Smarty current Smarty instance for chaining + * @throws \SmartyException when an invalid class name is provided + */ + public static function enableSecurity(Smarty $smarty, $security_class) + { + if ($security_class instanceof Smarty_Security) { + $smarty->security_policy = $security_class; + return; + } elseif (is_object($security_class)) { + throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security."); + } + if ($security_class == null) { + $security_class = $smarty->security_class; + } + if (!class_exists($security_class)) { + throw new SmartyException("Security class '$security_class' is not defined"); + } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) { + throw new SmartyException("Class '$security_class' must extend Smarty_Security."); + } else { + $smarty->security_policy = new $security_class($smarty); + } + return; + } + /** + * Start template processing + * + * @param $template + * + * @throws SmartyException + */ + public function startTemplate($template) + { + if ($this->max_template_nesting > 0 && $this->_current_template_nesting ++ >= $this->max_template_nesting) { + throw new SmartyException("maximum template nesting level of '{$this->max_template_nesting}' exceeded when calling '{$template->template_resource}'"); + } + } + + /** + * Exit template processing + * + */ + public function endTemplate() + { + if ($this->max_template_nesting > 0) { + $this->_current_template_nesting --; + } + } + + /** + * Register callback functions call at start/end of template rendering + * + * @param \Smarty_Internal_Template $template + */ + public function registerCallBacks(Smarty_Internal_Template $template) + { + $template->startRenderCallbacks[] = array($this, 'startTemplate'); + $template->endRenderCallbacks[] = array($this, 'endTemplate'); + } +} diff --git a/libs/sysplugins/smarty_template_cached.php b/libs/sysplugins/smarty_template_cached.php new file mode 100644 index 0000000..58f0daf --- /dev/null +++ b/libs/sysplugins/smarty_template_cached.php @@ -0,0 +1,256 @@ +compile_id = $_template->compile_id; + $this->cache_id = $_template->cache_id; + $this->source = $_template->source; + if (!class_exists('Smarty_CacheResource', false)) { + require SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; + } + $this->handler = Smarty_CacheResource::load($_template->smarty); + } + + /** + * @param Smarty_Internal_Template $_template + * + * @return Smarty_Template_Cached + */ + static function load(Smarty_Internal_Template $_template) + { + $_template->cached = new Smarty_Template_Cached($_template); + $_template->cached->handler->populate($_template->cached, $_template); + // caching enabled ? + if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || + $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->handler->recompiled + ) { + $_template->cached->valid = false; + } + return $_template->cached; + } + + /** + * Render cache template + * + * @param \Smarty_Internal_Template $_template + * @param bool $no_output_filter + * + * @throws \Exception + */ + public function render(Smarty_Internal_Template $_template, $no_output_filter = true) + { + if ($this->isCached($_template)) { + if ($_template->smarty->debugging) { + if (!isset($_template->smarty->_debug)) { + $_template->smarty->_debug = new Smarty_Internal_Debug(); + } + $_template->smarty->_debug->start_cache($_template); + } + if (!$this->processed) { + $this->process($_template); + } + $this->getRenderedTemplateCode($_template); + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + return; + } else { + $_template->smarty->ext->_updateCache->updateCache($this, $_template, $no_output_filter); + } + } + + /** + * Check if cache is valid, lock cache if required + * + * @param \Smarty_Internal_Template $_template + * + * @return bool flag true if cache is valid + */ + public function isCached(Smarty_Internal_Template $_template) + { + if ($this->valid !== null) { + return $this->valid; + } + while (true) { + while (true) { + if ($this->exists === false || $_template->smarty->force_compile || $_template->smarty->force_cache) { + $this->valid = false; + } else { + $this->valid = true; + } + if ($this->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && + $_template->cache_lifetime >= 0 && time() > ($this->timestamp + $_template->cache_lifetime) + ) { + // lifetime expired + $this->valid = false; + } + if ($this->valid && $_template->smarty->compile_check == 1 && + $_template->source->getTimeStamp() > $this->timestamp + ) { + $this->valid = false; + } + if ($this->valid || !$_template->smarty->cache_locking) { + break; + } + if (!$this->handler->locked($_template->smarty, $this)) { + $this->handler->acquireLock($_template->smarty, $this); + break 2; + } + $this->handler->populate($this, $_template); + } + if ($this->valid) { + if (!$_template->smarty->cache_locking || $this->handler->locked($_template->smarty, $this) === null) { + // load cache file for the following checks + if ($_template->smarty->debugging) { + $_template->smarty->_debug->start_cache($_template); + } + if ($this->handler->process($_template, $this) === false) { + $this->valid = false; + } else { + $this->processed = true; + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_cache($_template); + } + } else { + $this->is_locked = true; + continue; + } + } else { + return $this->valid; + } + if ($this->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && + $_template->cached->cache_lifetime >= 0 && + (time() > ($_template->cached->timestamp + $_template->cached->cache_lifetime)) + ) { + $this->valid = false; + } + if ($_template->smarty->cache_locking) { + if (!$this->valid) { + $this->handler->acquireLock($_template->smarty, $this); + } elseif ($this->is_locked) { + $this->handler->releaseLock($_template->smarty, $this); + } + } + return $this->valid; + } + return $this->valid; + } + + /** + * Process cached template + * + * @param Smarty_Internal_Template $_template template object + * @param bool $update flag if called because cache update + */ + public function process(Smarty_Internal_Template $_template, $update = false) + { + if ($this->handler->process($_template, $this, $update) === false) { + $this->valid = false; + } + if ($this->valid) { + $this->processed = true; + } else { + $this->processed = false; + } + } + + /** + * Read cache content from handler + * + * @param Smarty_Internal_Template $_template template object + * + * @return string|false content + */ + public function read(Smarty_Internal_Template $_template) + { + if (!$_template->source->handler->recompiled) { + return $this->handler->readCachedContent($_template); + } + return false; + } +} diff --git a/libs/sysplugins/smarty_template_compiled.php b/libs/sysplugins/smarty_template_compiled.php new file mode 100644 index 0000000..1cd4d29 --- /dev/null +++ b/libs/sysplugins/smarty_template_compiled.php @@ -0,0 +1,257 @@ +source->handler->hasCompiledHandler) { + $_template->source->handler->populateCompiledFilepath($compiled, $_template); + } else { + $compiled->populateCompiledFilepath($_template); + } + return $compiled; + } + + /** + * populate Compiled Object with compiled filepath + * + * @param Smarty_Internal_Template $_template template object + **/ + public function populateCompiledFilepath(Smarty_Internal_Template $_template) + { + $source = &$_template->source; + $smarty = &$_template->smarty; + $this->filepath = $smarty->getCompileDir(); + if (isset($_template->compile_id)) { + $this->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) . + ($smarty->use_sub_dirs ? $smarty->ds : '^'); + } + // if use_sub_dirs, break file into directories + if ($smarty->use_sub_dirs) { + $this->filepath .= $source->uid[ 0 ] . $source->uid[ 1 ] . $smarty->ds . $source->uid[ 2 ] . + $source->uid[ 3 ] . $smarty->ds . $source->uid[ 4 ] . $source->uid[ 5 ] . $smarty->ds; + } + $this->filepath .= $source->uid . '_'; + if ($source->isConfig) { + $this->filepath .= (int) $smarty->config_read_hidden + (int) $smarty->config_booleanize * 2 + + (int) $smarty->config_overwrite * 4; + } else { + $this->filepath .= (int) $smarty->merge_compiled_includes + (int) $smarty->escape_html * 2 + + (($smarty->merge_compiled_includes && $source->type === 'extends') ? + (int) $smarty->extends_recursion * 4 : 0); + } + $this->filepath .= '.' . $source->type; + $basename = $source->handler->getBasename($source); + if (!empty($basename)) { + $this->filepath .= '.' . $basename; + } + if ($_template->caching) { + $this->filepath .= '.cache'; + } + $this->filepath .= '.php'; + $this->timestamp = $this->exists = is_file($this->filepath); + if ($this->exists) { + $this->timestamp = filemtime($this->filepath); + } + } + + /** + * render compiled template code + * + * @param Smarty_Internal_Template $_template + * + * @return string + * @throws Exception + */ + public function render(Smarty_Internal_Template $_template) + { + // checks if template exists + if (!$_template->source->exists) { + $type = $_template->source->isConfig ? 'config' : 'template'; + throw new SmartyException("Unable to load {$type} '{$_template->source->type}:{$_template->source->name}'"); + } + if ($_template->smarty->debugging) { + if (!isset($_template->smarty->_debug)) { + $_template->smarty->_debug = new Smarty_Internal_Debug(); + } + $_template->smarty->_debug->start_render($_template); + } + if (!$this->processed) { + $this->process($_template); + } + if (isset($_template->cached)) { + $_template->cached->file_dependency = + array_merge($_template->cached->file_dependency, $this->file_dependency); + } + if ($_template->source->handler->uncompiled) { + $_template->source->handler->renderUncompiled($_template->source, $_template); + } else { + $this->getRenderedTemplateCode($_template); + } + if ($_template->caching && $this->has_nocache_code) { + $_template->cached->hashes[ $this->nocache_hash ] = true; + } + if ($_template->smarty->debugging) { + $_template->smarty->_debug->end_render($_template); + } + } + + /** + * load compiled template or compile from source + * + * @param Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + * + * @throws Exception + */ + public function process(Smarty_Internal_Template $_smarty_tpl) + { + $source = &$_smarty_tpl->source; + $smarty = &$_smarty_tpl->smarty; + if ($source->handler->recompiled) { + $source->handler->process($_smarty_tpl); + } elseif (!$source->handler->uncompiled) { + if (!$this->exists || $smarty->force_compile || + ($smarty->compile_check && $source->getTimeStamp() > $this->getTimeStamp()) + ) { + $this->compileTemplateSource($_smarty_tpl); + $compileCheck = $smarty->compile_check; + $smarty->compile_check = false; + $this->loadCompiledTemplate($_smarty_tpl); + $smarty->compile_check = $compileCheck; + } else { + $_smarty_tpl->mustCompile = true; + @include($this->filepath); + if ($_smarty_tpl->mustCompile) { + $this->compileTemplateSource($_smarty_tpl); + $compileCheck = $smarty->compile_check; + $smarty->compile_check = false; + $this->loadCompiledTemplate($_smarty_tpl); + $smarty->compile_check = $compileCheck; + } + } + $_smarty_tpl->_subTemplateRegister(); + $this->processed = true; + } + } + + /** + * compile template from source + * + * @param Smarty_Internal_Template $_template + * + * @throws Exception + */ + public function compileTemplateSource(Smarty_Internal_Template $_template) + { + $this->file_dependency = array(); + $this->includes = array(); + $this->nocache_hash = null; + $this->unifunc = null; + // compile locking + if ($saved_timestamp = (!$_template->source->handler->recompiled && is_file($this->filepath))) { + $saved_timestamp = $this->getTimeStamp(); + touch($this->filepath); + } + // compile locking + try { + // call compiler + $_template->loadCompiler(); + $this->write($_template, $_template->compiler->compileTemplate($_template)); + } + catch (Exception $e) { + // restore old timestamp in case of error + if ($saved_timestamp && is_file($this->filepath)) { + touch($this->filepath, $saved_timestamp); + } + unset($_template->compiler); + throw $e; + } + // release compiler object to free memory + unset($_template->compiler); + } + + /** + * Write compiled code by handler + * + * @param Smarty_Internal_Template $_template template object + * @param string $code compiled code + * + * @return boolean success + */ + public function write(Smarty_Internal_Template $_template, $code) + { + if (!$_template->source->handler->recompiled) { + if ($_template->smarty->ext->_writeFile->writeFile($this->filepath, $code, $_template->smarty) === true) { + $this->timestamp = $this->exists = is_file($this->filepath); + if ($this->exists) { + $this->timestamp = filemtime($this->filepath); + return true; + } + } + return false; + } + return true; + } + + /** + * Load fresh compiled template by including the PHP file + * HHVM requires a work around because of a PHP incompatibility + * + * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template + */ + private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl) + { + if (function_exists('opcache_invalidate') + && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1) + ) { + opcache_invalidate($this->filepath, true); + } elseif (function_exists('apc_compile_file')) { + apc_compile_file($this->filepath); + } + if (defined('HHVM_VERSION')) { + eval("?>" . file_get_contents($this->filepath)); + } else { + include($this->filepath); + } + } + + /** + * Read compiled content from handler + * + * @param Smarty_Internal_Template $_template template object + * + * @return string content + */ + public function read(Smarty_Internal_Template $_template) + { + if (!$_template->source->handler->recompiled) { + return file_get_contents($this->filepath); + } + return isset($this->content) ? $this->content : false; + } +} diff --git a/libs/sysplugins/smarty_template_config.php b/libs/sysplugins/smarty_template_config.php new file mode 100644 index 0000000..44cdba6 --- /dev/null +++ b/libs/sysplugins/smarty_template_config.php @@ -0,0 +1,99 @@ + true, 'php' => true); + if ($_template) { + $smarty = $_template->smarty; + $template_resource = $_template->template_resource; + } + if (empty($template_resource)) { + throw new SmartyException('Source: Missing name'); + } + // parse resource_name, load resource handler + list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $smarty->default_config_type); + // make sure configs are not loaded via anything smarty can't handle + if (isset($_incompatible_resources[ $type ])) { + throw new SmartyException ("Unable to use resource '{$type}' for config"); + } + $source = new Smarty_Template_Config($smarty, $template_resource, $type, $name); + $source->handler->populate($source, $_template); + if (!$source->exists && isset($smarty->default_config_handler_func)) { + Smarty_Internal_Method_RegisterDefaultTemplateHandler::_getDefaultTemplate($source); + $source->handler->populate($source, $_template); + } + return $source; + } +} diff --git a/libs/sysplugins/smarty_template_resource_base.php b/libs/sysplugins/smarty_template_resource_base.php new file mode 100644 index 0000000..6cc008a --- /dev/null +++ b/libs/sysplugins/smarty_template_resource_base.php @@ -0,0 +1,158 @@ +smarty; + $_template->isRenderingCache = $this->isCache; + $level = ob_get_level(); + try { + if (!isset($unifunc)) { + $unifunc = $this->unifunc; + } + if (empty($unifunc) || !function_exists($unifunc)) { + throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'"); + } + if ($_template->startRenderCallbacks) { + foreach ($_template->startRenderCallbacks as $callback) { + call_user_func($callback, $_template); + } + } + $unifunc($_template); + foreach ($_template->endRenderCallbacks as $callback) { + call_user_func($callback, $_template); + } + $_template->isRenderingCache = false; + } + catch (Exception $e) { + $_template->isRenderingCache = false; + while (ob_get_level() > $level) { + ob_end_clean(); + } + if (isset($smarty->security_policy)) { + $smarty->security_policy->endTemplate(); + } + throw $e; + } + } + + /** + * Get compiled time stamp + * + * @return int + */ + public function getTimeStamp() + { + if ($this->exists && !$this->timestamp) { + $this->timestamp = filemtime($this->filepath); + } + return $this->timestamp; + } +} diff --git a/libs/sysplugins/smarty_template_source.php b/libs/sysplugins/smarty_template_source.php new file mode 100644 index 0000000..fdb3dea --- /dev/null +++ b/libs/sysplugins/smarty_template_source.php @@ -0,0 +1,210 @@ +handler = + isset($smarty->_cache[ 'resource_handlers' ][ $type ]) ? $smarty->_cache[ 'resource_handlers' ][ $type ] : + Smarty_Resource::load($smarty, $type); + $this->smarty = $smarty; + $this->resource = $resource; + $this->type = $type; + $this->name = $name; + } + + /** + * initialize Source Object for given resource + * Either [$_template] or [$smarty, $template_resource] must be specified + * + * @param Smarty_Internal_Template $_template template object + * @param Smarty $smarty smarty object + * @param string $template_resource resource identifier + * + * @return Smarty_Template_Source Source Object + * @throws SmartyException + */ + public static function load(Smarty_Internal_Template $_template = null, Smarty $smarty = null, + $template_resource = null) + { + if ($_template) { + $smarty = $_template->smarty; + $template_resource = $_template->template_resource; + } + if (empty($template_resource)) { + throw new SmartyException('Source: Missing name'); + } + // parse resource_name, load resource handler, identify unique resource name + if (preg_match('/^([A-Za-z0-9_\-]{2,})[:]([\s\S]*)$/', $template_resource, $match)) { + $type = $match[ 1 ]; + $name = $match[ 2 ]; + } else { + // no resource given, use default + // or single character before the colon is not a resource type, but part of the filepath + $type = $smarty->default_resource_type; + $name = $template_resource; + } + // create new source object + $source = new Smarty_Template_Source($smarty, $template_resource, $type, $name); + $source->handler->populate($source, $_template); + if (!$source->exists && isset($_template->smarty->default_template_handler_func)) { + Smarty_Internal_Method_RegisterDefaultTemplateHandler::_getDefaultTemplate($source); + $source->handler->populate($source, $_template); + } + return $source; + } + + /** + * Get source time stamp + * + * @return int + */ + public function getTimeStamp() + { + if (!isset($this->timestamp)) { + $this->handler->populateTimestamp($this); + } + return $this->timestamp; + } + + /** + * Get source content + * + * @return string + */ + public function getContent() + { + return isset($this->content) ? $this->content : $this->handler->getContent($this); + } +} diff --git a/libs/sysplugins/smarty_undefined_variable.php b/libs/sysplugins/smarty_undefined_variable.php new file mode 100644 index 0000000..88bc6f6 --- /dev/null +++ b/libs/sysplugins/smarty_undefined_variable.php @@ -0,0 +1,37 @@ +value = $value; + $this->nocache = $nocache; + } + + /** + * <> String conversion + * + * @return string + */ + public function __toString() + { + return (string) $this->value; + } +} + diff --git a/libs/sysplugins/smartycompilerexception.php b/libs/sysplugins/smartycompilerexception.php new file mode 100644 index 0000000..763bab1 --- /dev/null +++ b/libs/sysplugins/smartycompilerexception.php @@ -0,0 +1,42 @@ + Smarty Compiler: ' . $this->message . ' <-- '; + } + + /** + * The line number of the template error + * + * @type int|null + */ + public $line = null; + + /** + * The template source snippet relating to the error + * + * @type string|null + */ + public $source = null; + + /** + * The raw text of the error message + * + * @type string|null + */ + public $desc = null; + + /** + * The resource identifier or template name + * + * @type string|null + */ + public $template = null; +} diff --git a/libs/sysplugins/smartyexception.php b/libs/sysplugins/smartyexception.php new file mode 100644 index 0000000..431d8f8 --- /dev/null +++ b/libs/sysplugins/smartyexception.php @@ -0,0 +1,16 @@ + Smarty: ' . (self::$escape ? htmlentities($this->message) : $this->message) . ' <-- '; + } +}