Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
/**
Chris PeBenito 696b41
 * Project:     Smarty: the PHP compiling template engine
Chris PeBenito 696b41
 * File:        Smarty_Compiler.class.php
Chris PeBenito 696b41
 *
Chris PeBenito 696b41
 * This library is free software; you can redistribute it and/or
Chris PeBenito 696b41
 * modify it under the terms of the GNU Lesser General Public
Chris PeBenito 696b41
 * License as published by the Free Software Foundation; either
Chris PeBenito 696b41
 * version 2.1 of the License, or (at your option) any later version.
Chris PeBenito 696b41
 *
Chris PeBenito 696b41
 * This library is distributed in the hope that it will be useful,
Chris PeBenito 696b41
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris PeBenito 696b41
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Chris PeBenito 696b41
 * Lesser General Public License for more details.
Chris PeBenito 696b41
 *
Chris PeBenito 696b41
 * You should have received a copy of the GNU Lesser General Public
Chris PeBenito 696b41
 * License along with this library; if not, write to the Free Software
Chris PeBenito 696b41
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Chris PeBenito 696b41
 *
Chris PeBenito 696b41
 * @link http://smarty.php.net/
Chris PeBenito 696b41
 * @author Monte Ohrt <monte at ohrt dot com>
Chris PeBenito 696b41
 * @author Andrei Zmievski <andrei@php.net>
Chris PeBenito 696b41
 * @version 2.6.9
Chris PeBenito 696b41
 * @copyright 2001-2005 New Digital Group, Inc.
Chris PeBenito 696b41
 * @package Smarty
Chris PeBenito 696b41
 */
Chris PeBenito 696b41
Chris PeBenito 696b41
/* $Id$ */
Chris PeBenito 696b41
Chris PeBenito 696b41
/**
Chris PeBenito 696b41
 * Template compiling class
Chris PeBenito 696b41
 * @package Smarty
Chris PeBenito 696b41
 */
Chris PeBenito 696b41
class Smarty_Compiler extends Smarty {
Chris PeBenito 696b41
Chris PeBenito 696b41
    // internal vars
Chris PeBenito 696b41
    /**#@+
Chris PeBenito 696b41
     * @access private
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    var $_folded_blocks         =   array();    // keeps folded template blocks
Chris PeBenito 696b41
    var $_current_file          =   null;       // the current template being compiled
Chris PeBenito 696b41
    var $_current_line_no       =   1;          // line number for error messages
Chris PeBenito 696b41
    var $_capture_stack         =   array();    // keeps track of nested capture buffers
Chris PeBenito 696b41
    var $_plugin_info           =   array();    // keeps track of plugins to load
Chris PeBenito 696b41
    var $_init_smarty_vars      =   false;
Chris PeBenito 696b41
    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');
Chris PeBenito 696b41
    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor
Chris PeBenito 696b41
    var $_si_qstr_regexp        =   null;
Chris PeBenito 696b41
    var $_qstr_regexp           =   null;
Chris PeBenito 696b41
    var $_func_regexp           =   null;
Chris PeBenito 696b41
    var $_reg_obj_regexp        =   null;
Chris PeBenito 696b41
    var $_var_bracket_regexp    =   null;
Chris PeBenito 696b41
    var $_num_const_regexp      =   null;
Chris PeBenito 696b41
    var $_dvar_guts_regexp      =   null;
Chris PeBenito 696b41
    var $_dvar_regexp           =   null;
Chris PeBenito 696b41
    var $_cvar_regexp           =   null;
Chris PeBenito 696b41
    var $_svar_regexp           =   null;
Chris PeBenito 696b41
    var $_avar_regexp           =   null;
Chris PeBenito 696b41
    var $_mod_regexp            =   null;
Chris PeBenito 696b41
    var $_var_regexp            =   null;
Chris PeBenito 696b41
    var $_parenth_param_regexp  =   null;
Chris PeBenito 696b41
    var $_func_call_regexp      =   null;
Chris PeBenito 696b41
    var $_obj_ext_regexp        =   null;
Chris PeBenito 696b41
    var $_obj_start_regexp      =   null;
Chris PeBenito 696b41
    var $_obj_params_regexp     =   null;
Chris PeBenito 696b41
    var $_obj_call_regexp       =   null;
Chris PeBenito 696b41
    var $_cacheable_state       =   0;
Chris PeBenito 696b41
    var $_cache_attrs_count     =   0;
Chris PeBenito 696b41
    var $_nocache_count         =   0;
Chris PeBenito 696b41
    var $_cache_serial          =   null;
Chris PeBenito 696b41
    var $_cache_include         =   null;
Chris PeBenito 696b41
Chris PeBenito 696b41
    var $_strip_depth           =   0;
Chris PeBenito 696b41
    var $_additional_newline    =   "\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**#@-*/
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * The class constructor.
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function Smarty_Compiler()
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        // matches double quoted strings:
Chris PeBenito 696b41
        // "foobar"
Chris PeBenito 696b41
        // "foo\"bar"
Chris PeBenito 696b41
        $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches single quoted strings:
Chris PeBenito 696b41
        // 'foobar'
Chris PeBenito 696b41
        // 'foo\'bar'
Chris PeBenito 696b41
        $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches single or double quoted strings
Chris PeBenito 696b41
        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches bracket portion of vars
Chris PeBenito 696b41
        // [0]
Chris PeBenito 696b41
        // [foo]
Chris PeBenito 696b41
        // [$bar]
Chris PeBenito 696b41
        $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches numerical constants
Chris PeBenito 696b41
        // 30
Chris PeBenito 696b41
        // -12
Chris PeBenito 696b41
        // 13.22
Chris PeBenito 696b41
        $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches $ vars (not objects):
Chris PeBenito 696b41
        // $foo
Chris PeBenito 696b41
        // $foo.bar
Chris PeBenito 696b41
        // $foo.bar.foobar
Chris PeBenito 696b41
        // $foo[0]
Chris PeBenito 696b41
        // $foo[$bar]
Chris PeBenito 696b41
        // $foo[5][blah]
Chris PeBenito 696b41
        // $foo[5].bar[$foobar][4]
Chris PeBenito 696b41
        $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
Chris PeBenito 696b41
        $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
Chris PeBenito 696b41
        $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
Chris PeBenito 696b41
                . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
Chris PeBenito 696b41
        $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches config vars:
Chris PeBenito 696b41
        // #foo#
Chris PeBenito 696b41
        // #foobar123_foo#
Chris PeBenito 696b41
        $this->_cvar_regexp = '\#\w+\#';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches section vars:
Chris PeBenito 696b41
        // %foo.bar%
Chris PeBenito 696b41
        $this->_svar_regexp = '\%\w+\.\w+\%';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches all valid variables (no quotes, no modifiers)
Chris PeBenito 696b41
        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
Chris PeBenito 696b41
           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid variable syntax:
Chris PeBenito 696b41
        // $foo
Chris PeBenito 696b41
        // $foo
Chris PeBenito 696b41
        // #foo#
Chris PeBenito 696b41
        // #foo#
Chris PeBenito 696b41
        // "text"
Chris PeBenito 696b41
        // "text"
Chris PeBenito 696b41
        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid object call (one level of object nesting allowed in parameters):
Chris PeBenito 696b41
        // $foo->bar
Chris PeBenito 696b41
        // $foo->bar()
Chris PeBenito 696b41
        // $foo->bar("text")
Chris PeBenito 696b41
        // $foo->bar($foo, $bar, "text")
Chris PeBenito 696b41
        // $foo->bar($foo, "foo")
Chris PeBenito 696b41
        // $foo->bar->foo()
Chris PeBenito 696b41
        // $foo->bar->foo->bar()
Chris PeBenito 696b41
        // $foo->bar($foo->bar)
Chris PeBenito 696b41
        // $foo->bar($foo->bar())
Chris PeBenito 696b41
        // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
Chris PeBenito 696b41
        $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
Chris PeBenito 696b41
        $this->_obj_restricted_param_regexp = '(?:'
Chris PeBenito 696b41
                . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
Chris PeBenito 696b41
                . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
Chris PeBenito 696b41
        $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
Chris PeBenito 696b41
                . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
Chris PeBenito 696b41
        $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
Chris PeBenito 696b41
                . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
Chris PeBenito 696b41
        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
Chris PeBenito 696b41
        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
Chris PeBenito 696b41
        
Chris PeBenito 696b41
        // matches valid modifier syntax:
Chris PeBenito 696b41
        // |foo
Chris PeBenito 696b41
        // |@foo
Chris PeBenito 696b41
        // |foo:"bar"
Chris PeBenito 696b41
        // |foo:$bar
Chris PeBenito 696b41
        // |foo:"bar":$foobar
Chris PeBenito 696b41
        // |foo|bar
Chris PeBenito 696b41
        // |foo:$foo->bar
Chris PeBenito 696b41
        $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
Chris PeBenito 696b41
           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid function name:
Chris PeBenito 696b41
        // foo123
Chris PeBenito 696b41
        // _foo_bar
Chris PeBenito 696b41
        $this->_func_regexp = '[a-zA-Z_]\w*';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid registered object:
Chris PeBenito 696b41
        // foo->bar
Chris PeBenito 696b41
        $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid parameter values:
Chris PeBenito 696b41
        // true
Chris PeBenito 696b41
        // $foo
Chris PeBenito 696b41
        // $foo|bar
Chris PeBenito 696b41
        // #foo#
Chris PeBenito 696b41
        // #foo#|bar
Chris PeBenito 696b41
        // "text"
Chris PeBenito 696b41
        // "text"|bar
Chris PeBenito 696b41
        // $foo->bar
Chris PeBenito 696b41
        $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
Chris PeBenito 696b41
           . $this->_var_regexp . '|' . $this->_num_const_regexp  . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid parenthesised function parameters:
Chris PeBenito 696b41
        //
Chris PeBenito 696b41
        // "text"
Chris PeBenito 696b41
        //    $foo, $bar, "text"
Chris PeBenito 696b41
        // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
Chris PeBenito 696b41
        $this->_parenth_param_regexp = '(?:\((?:\w+|'
Chris PeBenito 696b41
                . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
Chris PeBenito 696b41
                . $this->_param_regexp . ')))*)?\))';
Chris PeBenito 696b41
Chris PeBenito 696b41
        // matches valid function call:
Chris PeBenito 696b41
        // foo()
Chris PeBenito 696b41
        // foo_bar($foo)
Chris PeBenito 696b41
        // _foo_bar($foo,"bar")
Chris PeBenito 696b41
        // foo123($foo,$foo->bar(),"foo")
Chris PeBenito 696b41
        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
Chris PeBenito 696b41
           . $this->_parenth_param_regexp . '))';
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile a resource
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * sets $compiled_content to the compiled source
Chris PeBenito 696b41
     * @param string $resource_name
Chris PeBenito 696b41
     * @param string $source_content
Chris PeBenito 696b41
     * @param string $compiled_content
Chris PeBenito 696b41
     * @return true
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_file($resource_name, $source_content, &$compiled_content)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($this->security) {
Chris PeBenito 696b41
            // do not allow php syntax to be executed unless specified
Chris PeBenito 696b41
            if ($this->php_handling == SMARTY_PHP_ALLOW &&
Chris PeBenito 696b41
                !$this->security_settings['PHP_HANDLING']) {
Chris PeBenito 696b41
                $this->php_handling = SMARTY_PHP_PASSTHRU;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_load_filters();
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_current_file = $resource_name;
Chris PeBenito 696b41
        $this->_current_line_no = 1;
Chris PeBenito 696b41
        $ldq = preg_quote($this->left_delimiter, '~');
Chris PeBenito 696b41
        $rdq = preg_quote($this->right_delimiter, '~');
Chris PeBenito 696b41
Chris PeBenito 696b41
        // run template source through prefilter functions
Chris PeBenito 696b41
        if (count($this->_plugins['prefilter']) > 0) {
Chris PeBenito 696b41
            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
Chris PeBenito 696b41
                if ($prefilter === false) continue;
Chris PeBenito 696b41
                if ($prefilter[3] || is_callable($prefilter[0])) {
Chris PeBenito 696b41
                    $source_content = call_user_func_array($prefilter[0],
Chris PeBenito 696b41
                                                            array($source_content, &$this));
Chris PeBenito 696b41
                    $this->_plugins['prefilter'][$filter_name][3] = true;
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* fetch all special blocks */
Chris PeBenito 696b41
        $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
Chris PeBenito 696b41
Chris PeBenito 696b41
        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);
Chris PeBenito 696b41
        $this->_folded_blocks = $match;
Chris PeBenito 696b41
        reset($this->_folded_blocks);
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* replace special blocks by "{php}" */
Chris PeBenito 696b41
        $source_content = preg_replace($search.'e', "'"
Chris PeBenito 696b41
                                       . $this->_quote_replace($this->left_delimiter) . 'php'
Chris PeBenito 696b41
                                       . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
Chris PeBenito 696b41
                                       . $this->_quote_replace($this->right_delimiter)
Chris PeBenito 696b41
                                       . "'"
Chris PeBenito 696b41
                                       , $source_content);
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Gather all template tags. */
Chris PeBenito 696b41
        preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
Chris PeBenito 696b41
        $template_tags = $_match[1];
Chris PeBenito 696b41
        /* Split content by template tags to obtain non-template content. */
Chris PeBenito 696b41
        $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* loop through text blocks */
Chris PeBenito 696b41
        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
Chris PeBenito 696b41
            /* match anything resembling php tags */
Chris PeBenito 696b41
            if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
Chris PeBenito 696b41
                /* replace tags with placeholders to prevent recursive replacements */
Chris PeBenito 696b41
                $sp_match[1] = array_unique($sp_match[1]);
Chris PeBenito 696b41
                usort($sp_match[1], '_smarty_sort_length');
Chris PeBenito 696b41
                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
Chris PeBenito 696b41
                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                /* process each one */
Chris PeBenito 696b41
                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
Chris PeBenito 696b41
                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
Chris PeBenito 696b41
                        /* echo php contents */
Chris PeBenito 696b41
                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', ''."\n", $text_blocks[$curr_tb]);
Chris PeBenito 696b41
                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
Chris PeBenito 696b41
                        /* quote php tags */
Chris PeBenito 696b41
                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
Chris PeBenito 696b41
                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
Chris PeBenito 696b41
                        /* remove php tags */
Chris PeBenito 696b41
                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
Chris PeBenito 696b41
                    } else {
Chris PeBenito 696b41
                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */
Chris PeBenito 696b41
                        $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', ''."\n", $sp_match[1][$curr_sp]);
Chris PeBenito 696b41
                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Compile the template tags into PHP code. */
Chris PeBenito 696b41
        $compiled_tags = array();
Chris PeBenito 696b41
        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
Chris PeBenito 696b41
            $this->_current_line_no += substr_count($text_blocks[$i], "\n");
Chris PeBenito 696b41
            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
Chris PeBenito 696b41
            $this->_current_line_no += substr_count($template_tags[$i], "\n");
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        if (count($this->_tag_stack)>0) {
Chris PeBenito 696b41
            list($_open_tag, $_line_no) = end($this->_tag_stack);
Chris PeBenito 696b41
            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
            return;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Reformat $text_blocks between 'strip' and '/strip' tags,
Chris PeBenito 696b41
           removing spaces, tabs and newlines. */
Chris PeBenito 696b41
        $strip = false;
Chris PeBenito 696b41
        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
Chris PeBenito 696b41
            if ($compiled_tags[$i] == '{strip}') {
Chris PeBenito 696b41
                $compiled_tags[$i] = '';
Chris PeBenito 696b41
                $strip = true;
Chris PeBenito 696b41
                /* remove leading whitespaces */
Chris PeBenito 696b41
                $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if ($strip) {
Chris PeBenito 696b41
                /* strip all $text_blocks before the next '/strip' */
Chris PeBenito 696b41
                for ($j = $i + 1; $j < $for_max; $j++) {
Chris PeBenito 696b41
                    /* remove leading and trailing whitespaces of each line */
Chris PeBenito 696b41
                    $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
Chris PeBenito 696b41
                    if ($compiled_tags[$j] == '{/strip}') {                       
Chris PeBenito 696b41
                        /* remove trailing whitespaces from the last text_block */
Chris PeBenito 696b41
                        $text_blocks[$j] = rtrim($text_blocks[$j]);
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                    $text_blocks[$j] = ""\'", "\\"=>"\\\\")) . "'; ?>";
Chris PeBenito 696b41
                    if ($compiled_tags[$j] == '{/strip}') {
Chris PeBenito 696b41
                        $compiled_tags[$j] = "\n"; /* slurped by php, but necessary
Chris PeBenito 696b41
                                    if a newline is following the closing strip-tag */
Chris PeBenito 696b41
                        $strip = false;
Chris PeBenito 696b41
                        $i = $j;
Chris PeBenito 696b41
                        break;
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $compiled_content = '';
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Interleave the compiled contents and text blocks to get the final result. */
Chris PeBenito 696b41
        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
Chris PeBenito 696b41
            if ($compiled_tags[$i] == '') {
Chris PeBenito 696b41
                // tag result empty, remove first newline from following text block
Chris PeBenito 696b41
                $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $compiled_content .= $text_blocks[$i];
Chris PeBenito 696b41
Chris PeBenito 696b41
        // remove \n from the end of the file, if any
Chris PeBenito 696b41
        if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) {
Chris PeBenito 696b41
            $compiled_content = substr($compiled_content, 0, -1);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!empty($this->_cache_serial)) {
Chris PeBenito 696b41
            $compiled_content = "_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        // remove unnecessary close/open tags
Chris PeBenito 696b41
        $compiled_content = preg_replace('~\?>\n?<\?php~', '', $compiled_content);
Chris PeBenito 696b41
Chris PeBenito 696b41
        // run compiled template through postfilter functions
Chris PeBenito 696b41
        if (count($this->_plugins['postfilter']) > 0) {
Chris PeBenito 696b41
            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
Chris PeBenito 696b41
                if ($postfilter === false) continue;
Chris PeBenito 696b41
                if ($postfilter[3] || is_callable($postfilter[0])) {
Chris PeBenito 696b41
                    $compiled_content = call_user_func_array($postfilter[0],
Chris PeBenito 696b41
                                                              array($compiled_content, &$this));
Chris PeBenito 696b41
                    $this->_plugins['postfilter'][$filter_name][3] = true;
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        // put header at the top of the compiled template
Chris PeBenito 696b41
        $template_header = "_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
Chris PeBenito 696b41
        $template_header .= "         compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Emit code to load needed plugins. */
Chris PeBenito 696b41
        $this->_plugins_code = '';
Chris PeBenito 696b41
        if (count($this->_plugin_info)) {
Chris PeBenito 696b41
            $_plugins_params = "array('plugins' => array(";
Chris PeBenito 696b41
            foreach ($this->_plugin_info as $plugin_type => $plugins) {
Chris PeBenito 696b41
                foreach ($plugins as $plugin_name => $plugin_info) {
Chris PeBenito 696b41
                    $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
Chris PeBenito 696b41
                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $_plugins_params .= '))';
Chris PeBenito 696b41
            $plugins_code = "\n";
Chris PeBenito 696b41
            $template_header .= $plugins_code;
Chris PeBenito 696b41
            $this->_plugin_info = array();
Chris PeBenito 696b41
            $this->_plugins_code = $plugins_code;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($this->_init_smarty_vars) {
Chris PeBenito 696b41
            $template_header .= "\n";
Chris PeBenito 696b41
            $this->_init_smarty_vars = false;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $compiled_content = $template_header . $compiled_content;
Chris PeBenito 696b41
        return true;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile a template tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $template_tag
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_tag($template_tag)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        /* Matched comment. */
Chris PeBenito 696b41
        if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*')
Chris PeBenito 696b41
            return '';
Chris PeBenito 696b41
        
Chris PeBenito 696b41
        /* Split tag into two three parts: command, command modifiers and the arguments. */
Chris PeBenito 696b41
        if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
Chris PeBenito 696b41
                . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
Chris PeBenito 696b41
                      (?:\s+(.*))?$
Chris PeBenito 696b41
                    ~xs', $template_tag, $match)) {
Chris PeBenito 696b41
            $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        
Chris PeBenito 696b41
        $tag_command = $match[1];
Chris PeBenito 696b41
        $tag_modifier = isset($match[2]) ? $match[2] : null;
Chris PeBenito 696b41
        $tag_args = isset($match[3]) ? $match[3] : null;
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
Chris PeBenito 696b41
            /* tag name is a variable or object */
Chris PeBenito 696b41
            $_return = $this->_parse_var_props($tag_command . $tag_modifier);
Chris PeBenito 696b41
            return "" . $this->_additional_newline;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* If the tag name is a registered object, we process it. */
Chris PeBenito 696b41
        if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
Chris PeBenito 696b41
            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        switch ($tag_command) {
Chris PeBenito 696b41
            case 'include':
Chris PeBenito 696b41
                return $this->_compile_include_tag($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'include_php':
Chris PeBenito 696b41
                return $this->_compile_include_php_tag($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'if':
Chris PeBenito 696b41
                $this->_push_tag('if');
Chris PeBenito 696b41
                return $this->_compile_if_tag($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'else':
Chris PeBenito 696b41
                list($_open_tag) = end($this->_tag_stack);
Chris PeBenito 696b41
                if ($_open_tag != 'if' && $_open_tag != 'elseif')
Chris PeBenito 696b41
                    $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                else
Chris PeBenito 696b41
                    $this->_push_tag('else');
Chris PeBenito 696b41
                return '';
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'elseif':
Chris PeBenito 696b41
                list($_open_tag) = end($this->_tag_stack);
Chris PeBenito 696b41
                if ($_open_tag != 'if' && $_open_tag != 'elseif')
Chris PeBenito 696b41
                    $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                if ($_open_tag == 'if')
Chris PeBenito 696b41
                    $this->_push_tag('elseif');
Chris PeBenito 696b41
                return $this->_compile_if_tag($tag_args, true);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case '/if':
Chris PeBenito 696b41
                $this->_pop_tag('if');
Chris PeBenito 696b41
                return '';
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'capture':
Chris PeBenito 696b41
                return $this->_compile_capture_tag(true, $tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case '/capture':
Chris PeBenito 696b41
                return $this->_compile_capture_tag(false);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'ldelim':
Chris PeBenito 696b41
                return $this->left_delimiter;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'rdelim':
Chris PeBenito 696b41
                return $this->right_delimiter;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'section':
Chris PeBenito 696b41
                $this->_push_tag('section');
Chris PeBenito 696b41
                return $this->_compile_section_start($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'sectionelse':
Chris PeBenito 696b41
                $this->_push_tag('sectionelse');
Chris PeBenito 696b41
                return "";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case '/section':
Chris PeBenito 696b41
                $_open_tag = $this->_pop_tag('section');
Chris PeBenito 696b41
                if ($_open_tag == 'sectionelse')
Chris PeBenito 696b41
                    return "";
Chris PeBenito 696b41
                else
Chris PeBenito 696b41
                    return "";
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'foreach':
Chris PeBenito 696b41
                $this->_push_tag('foreach');
Chris PeBenito 696b41
                return $this->_compile_foreach_start($tag_args);
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'foreachelse':
Chris PeBenito 696b41
                $this->_push_tag('foreachelse');
Chris PeBenito 696b41
                return "";
Chris PeBenito 696b41
Chris PeBenito 696b41
            case '/foreach':
Chris PeBenito 696b41
                $_open_tag = $this->_pop_tag('foreach');
Chris PeBenito 696b41
                if ($_open_tag == 'foreachelse')
Chris PeBenito 696b41
                    return "";
Chris PeBenito 696b41
                else
Chris PeBenito 696b41
                    return "";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'strip':
Chris PeBenito 696b41
            case '/strip':
Chris PeBenito 696b41
                if ($tag_command{0}=='/') {
Chris PeBenito 696b41
                    $this->_pop_tag('strip');
Chris PeBenito 696b41
                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
Chris PeBenito 696b41
                        $this->_additional_newline = "\n";
Chris PeBenito 696b41
                        return '{' . $tag_command . '}';
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_push_tag('strip');
Chris PeBenito 696b41
                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */
Chris PeBenito 696b41
                        $this->_additional_newline = "";
Chris PeBenito 696b41
                        return '{' . $tag_command . '}';
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                return '';
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'php':
Chris PeBenito 696b41
                /* handle folded tags replaced by {php} */
Chris PeBenito 696b41
                list(, $block) = each($this->_folded_blocks);
Chris PeBenito 696b41
                $this->_current_line_no += substr_count($block[0], "\n");
Chris PeBenito 696b41
                /* the number of matched elements in the regexp in _compile_file()
Chris PeBenito 696b41
                   determins the type of folded tag that was found */
Chris PeBenito 696b41
                switch (count($block)) {
Chris PeBenito 696b41
                    case 2: /* comment */
Chris PeBenito 696b41
                        return '';
Chris PeBenito 696b41
Chris PeBenito 696b41
                    case 3: /* literal */
Chris PeBenito 696b41
                        return ""\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
Chris PeBenito 696b41
Chris PeBenito 696b41
                    case 4: /* php */
Chris PeBenito 696b41
                        if ($this->security && !$this->security_settings['PHP_TAGS']) {
Chris PeBenito 696b41
                            $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
Chris PeBenito 696b41
                            return;
Chris PeBenito 696b41
                        }
Chris PeBenito 696b41
                        return '';
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'insert':
Chris PeBenito 696b41
                return $this->_compile_insert_tag($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            default:
Chris PeBenito 696b41
                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
Chris PeBenito 696b41
                    return $output;
Chris PeBenito 696b41
                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
Chris PeBenito 696b41
                    return $output;
Chris PeBenito 696b41
                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
Chris PeBenito 696b41
                    return $output;                    
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile the custom compiler tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * sets $output to the compiled custom compiler tag
Chris PeBenito 696b41
     * @param string $tag_command
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @param string $output
Chris PeBenito 696b41
     * @return boolean
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_compiler_tag($tag_command, $tag_args, &$output)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $found = false;
Chris PeBenito 696b41
        $have_function = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * First we check if the compiler function has already been registered
Chris PeBenito 696b41
         * or loaded from a plugin file.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        if (isset($this->_plugins['compiler'][$tag_command])) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
            $plugin_func = $this->_plugins['compiler'][$tag_command][0];
Chris PeBenito 696b41
            if (!is_callable($plugin_func)) {
Chris PeBenito 696b41
                $message = "compiler function '$tag_command' is not implemented";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * Otherwise we need to load plugin file and look for the function
Chris PeBenito 696b41
         * inside it.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
            include_once $plugin_file;
Chris PeBenito 696b41
Chris PeBenito 696b41
            $plugin_func = 'smarty_compiler_' . $tag_command;
Chris PeBenito 696b41
            if (!is_callable($plugin_func)) {
Chris PeBenito 696b41
                $message = "plugin function $plugin_func() not found in $plugin_file\n";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * True return value means that we either found a plugin or a
Chris PeBenito 696b41
         * dynamically registered function. False means that we didn't and the
Chris PeBenito 696b41
         * compiler should now emit code to load custom function plugin for this
Chris PeBenito 696b41
         * tag.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        if ($found) {
Chris PeBenito 696b41
            if ($have_function) {
Chris PeBenito 696b41
                $output = call_user_func_array($plugin_func, array($tag_args, &$this));
Chris PeBenito 696b41
                if($output != '') {
Chris PeBenito 696b41
                $output = '_push_cacheable_state('compiler', $tag_command)
Chris PeBenito 696b41
                                   . $output
Chris PeBenito 696b41
                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            return true;
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            return false;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile block function tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * sets $output to compiled block function tag
Chris PeBenito 696b41
     * @param string $tag_command
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @param string $tag_modifier
Chris PeBenito 696b41
     * @param string $output
Chris PeBenito 696b41
     * @return boolean
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        if ($tag_command{0} == '/') {
Chris PeBenito 696b41
            $start_tag = false;
Chris PeBenito 696b41
            $tag_command = substr($tag_command, 1);
Chris PeBenito 696b41
        } else
Chris PeBenito 696b41
            $start_tag = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
        $found = false;
Chris PeBenito 696b41
        $have_function = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * First we check if the block function has already been registered
Chris PeBenito 696b41
         * or loaded from a plugin file.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        if (isset($this->_plugins['block'][$tag_command])) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
            $plugin_func = $this->_plugins['block'][$tag_command][0];
Chris PeBenito 696b41
            if (!is_callable($plugin_func)) {
Chris PeBenito 696b41
                $message = "block function '$tag_command' is not implemented";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * Otherwise we need to load plugin file and look for the function
Chris PeBenito 696b41
         * inside it.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
            include_once $plugin_file;
Chris PeBenito 696b41
Chris PeBenito 696b41
            $plugin_func = 'smarty_block_' . $tag_command;
Chris PeBenito 696b41
            if (!function_exists($plugin_func)) {
Chris PeBenito 696b41
                $message = "plugin function $plugin_func() not found in $plugin_file\n";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
Chris PeBenito 696b41
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!$found) {
Chris PeBenito 696b41
            return false;
Chris PeBenito 696b41
        } else if (!$have_function) {
Chris PeBenito 696b41
            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
Chris PeBenito 696b41
            return true;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * Even though we've located the plugin function, compilation
Chris PeBenito 696b41
         * happens only once, so the plugin will still need to be loaded
Chris PeBenito 696b41
         * at runtime for future requests.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        $this->_add_plugin('block', $tag_command);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($start_tag)
Chris PeBenito 696b41
            $this->_push_tag($tag_command);
Chris PeBenito 696b41
        else
Chris PeBenito 696b41
            $this->_pop_tag($tag_command);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($start_tag) {
Chris PeBenito 696b41
            $output = '_push_cacheable_state('block', $tag_command);
Chris PeBenito 696b41
            $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs='');
Chris PeBenito 696b41
            $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
Chris PeBenito 696b41
            $output .= $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat=true);';
Chris PeBenito 696b41
            $output .= 'while ($_block_repeat) { ob_start(); ?>';
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $output = '
Chris PeBenito 696b41
            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat=false)';
Chris PeBenito 696b41
            if ($tag_modifier != '') {
Chris PeBenito 696b41
                $this->_parse_modifiers($_out_tag_text, $tag_modifier);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $output .= 'echo '.$_out_tag_text.'; } ';
Chris PeBenito 696b41
            $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        return true;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile custom function tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_command
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @param string $tag_modifier
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $found = false;
Chris PeBenito 696b41
        $have_function = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * First we check if the custom function has already been registered
Chris PeBenito 696b41
         * or loaded from a plugin file.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        if (isset($this->_plugins['function'][$tag_command])) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
            $plugin_func = $this->_plugins['function'][$tag_command][0];
Chris PeBenito 696b41
            if (!is_callable($plugin_func)) {
Chris PeBenito 696b41
                $message = "custom function '$tag_command' is not implemented";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        /*
Chris PeBenito 696b41
         * Otherwise we need to load plugin file and look for the function
Chris PeBenito 696b41
         * inside it.
Chris PeBenito 696b41
         */
Chris PeBenito 696b41
        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
Chris PeBenito 696b41
            $found = true;
Chris PeBenito 696b41
Chris PeBenito 696b41
            include_once $plugin_file;
Chris PeBenito 696b41
Chris PeBenito 696b41
            $plugin_func = 'smarty_function_' . $tag_command;
Chris PeBenito 696b41
            if (!function_exists($plugin_func)) {
Chris PeBenito 696b41
                $message = "plugin function $plugin_func() not found in $plugin_file\n";
Chris PeBenito 696b41
                $have_function = false;
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
Chris PeBenito 696b41
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!$found) {
Chris PeBenito 696b41
            return false;
Chris PeBenito 696b41
        } else if (!$have_function) {
Chris PeBenito 696b41
            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
Chris PeBenito 696b41
            return true;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* declare plugin to be loaded on display of the template that
Chris PeBenito 696b41
           we compile right now */
Chris PeBenito 696b41
        $this->_add_plugin('function', $tag_command);
Chris PeBenito 696b41
Chris PeBenito 696b41
        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs='');
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
Chris PeBenito 696b41
        if($tag_modifier != '') {
Chris PeBenito 696b41
            $this->_parse_modifiers($output, $tag_modifier);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if($output != '') {
Chris PeBenito 696b41
            $output =  '
Chris PeBenito 696b41
                . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        return true;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile a registered object tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_command
Chris PeBenito 696b41
     * @param array $attrs
Chris PeBenito 696b41
     * @param string $tag_modifier
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        if ($tag_command{0} == '/') {
Chris PeBenito 696b41
            $start_tag = false;
Chris PeBenito 696b41
            $tag_command = substr($tag_command, 1);
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $start_tag = true;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        list($object, $obj_comp) = explode('->', $tag_command);
Chris PeBenito 696b41
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
        if(count($attrs)) {
Chris PeBenito 696b41
            $_assign_var = false;
Chris PeBenito 696b41
            foreach ($attrs as $arg_name => $arg_value) {
Chris PeBenito 696b41
                if($arg_name == 'assign') {
Chris PeBenito 696b41
                    $_assign_var = $arg_value;
Chris PeBenito 696b41
                    unset($attrs['assign']);
Chris PeBenito 696b41
                    continue;
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                if (is_bool($arg_value))
Chris PeBenito 696b41
                    $arg_value = $arg_value ? 'true' : 'false';
Chris PeBenito 696b41
                $arg_list[] = "'$arg_name' => $arg_value";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if($this->_reg_objects[$object][2]) {
Chris PeBenito 696b41
            // smarty object argument format
Chris PeBenito 696b41
            $args = "array(".implode(',', (array)$arg_list)."), \$this";
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            // traditional argument format
Chris PeBenito 696b41
            $args = implode(',', array_values($attrs));
Chris PeBenito 696b41
            if (empty($args)) {
Chris PeBenito 696b41
                $args = 'null';
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $prefix = '';
Chris PeBenito 696b41
        $postfix = '';
Chris PeBenito 696b41
        $newline = '';
Chris PeBenito 696b41
        if(!is_object($this->_reg_objects[$object][0])) {
Chris PeBenito 696b41
            $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
Chris PeBenito 696b41
        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
Chris PeBenito 696b41
            $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
Chris PeBenito 696b41
        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
Chris PeBenito 696b41
            // method
Chris PeBenito 696b41
            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
Chris PeBenito 696b41
                // block method
Chris PeBenito 696b41
                if ($start_tag) {
Chris PeBenito 696b41
                    $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
Chris PeBenito 696b41
                    $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); ";
Chris PeBenito 696b41
                    $prefix .= "while (\$_block_repeat) { ob_start();";
Chris PeBenito 696b41
                    $return = null;
Chris PeBenito 696b41
                    $postfix = '';
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                    $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); ";
Chris PeBenito 696b41
                    $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat=false)";
Chris PeBenito 696b41
                    $postfix = "} array_pop(\$this->_tag_stack);";
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                // non-block method
Chris PeBenito 696b41
                $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            // property
Chris PeBenito 696b41
            $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if($return != null) {
Chris PeBenito 696b41
            if($tag_modifier != '') {
Chris PeBenito 696b41
                $this->_parse_modifiers($return, $tag_modifier);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
Chris PeBenito 696b41
            if(!empty($_assign_var)) {
Chris PeBenito 696b41
                $output = "\$this->assign('" . $this->_dequote($_assign_var) ."',  $return);";
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $output = 'echo ' . $return . ';';
Chris PeBenito 696b41
                $newline = $this->_additional_newline;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $output = '';
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        return '" . $newline;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {insert ...} tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_insert_tag($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
        $name = $this->_dequote($attrs['name']);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (empty($name)) {
Chris PeBenito 696b41
            $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!empty($attrs['script'])) {
Chris PeBenito 696b41
            $delayed_loading = true;
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $delayed_loading = false;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        foreach ($attrs as $arg_name => $arg_value) {
Chris PeBenito 696b41
            if (is_bool($arg_value))
Chris PeBenito 696b41
                $arg_value = $arg_value ? 'true' : 'false';
Chris PeBenito 696b41
            $arg_list[] = "'$arg_name' => $arg_value";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_add_plugin('insert', $name, $delayed_loading);
Chris PeBenito 696b41
Chris PeBenito 696b41
        $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
Chris PeBenito 696b41
Chris PeBenito 696b41
        return "" . $this->_additional_newline;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {include ...} tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_include_tag($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (empty($attrs['file'])) {
Chris PeBenito 696b41
            $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        foreach ($attrs as $arg_name => $arg_value) {
Chris PeBenito 696b41
            if ($arg_name == 'file') {
Chris PeBenito 696b41
                $include_file = $arg_value;
Chris PeBenito 696b41
                continue;
Chris PeBenito 696b41
            } else if ($arg_name == 'assign') {
Chris PeBenito 696b41
                $assign_var = $arg_value;
Chris PeBenito 696b41
                continue;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if (is_bool($arg_value))
Chris PeBenito 696b41
                $arg_value = $arg_value ? 'true' : 'false';
Chris PeBenito 696b41
            $arg_list[] = "'$arg_name' => $arg_value";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = '
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($assign_var)) {
Chris PeBenito 696b41
            $output .= "ob_start();\n";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .=
Chris PeBenito 696b41
            "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
        $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
Chris PeBenito 696b41
        $output .= "\$this->_smarty_include($_params);\n" .
Chris PeBenito 696b41
        "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
Chris PeBenito 696b41
        "unset(\$_smarty_tpl_vars);\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($assign_var)) {
Chris PeBenito 696b41
            $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .= ' ?>';
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {include ...} tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_include_php_tag($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (empty($attrs['file'])) {
Chris PeBenito 696b41
            $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
Chris PeBenito 696b41
        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
Chris PeBenito 696b41
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
        foreach($attrs as $arg_name => $arg_value) {
Chris PeBenito 696b41
            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
Chris PeBenito 696b41
                if(is_bool($arg_value))
Chris PeBenito 696b41
                    $arg_value = $arg_value ? 'true' : 'false';
Chris PeBenito 696b41
                $arg_list[] = "'$arg_name' => $arg_value";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
Chris PeBenito 696b41
Chris PeBenito 696b41
        return "" . $this->_additional_newline;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {section ...} tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_section_start($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = '
Chris PeBenito 696b41
        $section_name = $attrs['name'];
Chris PeBenito 696b41
        if (empty($section_name)) {
Chris PeBenito 696b41
            $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .= "unset(\$this->_sections[$section_name]);\n";
Chris PeBenito 696b41
        $section_props = "\$this->_sections[$section_name]";
Chris PeBenito 696b41
Chris PeBenito 696b41
        foreach ($attrs as $attr_name => $attr_value) {
Chris PeBenito 696b41
            switch ($attr_name) {
Chris PeBenito 696b41
                case 'loop':
Chris PeBenito 696b41
                    $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'show':
Chris PeBenito 696b41
                    if (is_bool($attr_value))
Chris PeBenito 696b41
                        $show_attr_value = $attr_value ? 'true' : 'false';
Chris PeBenito 696b41
                    else
Chris PeBenito 696b41
                        $show_attr_value = "(bool)$attr_value";
Chris PeBenito 696b41
                    $output .= "{$section_props}['show'] = $show_attr_value;\n";
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'name':
Chris PeBenito 696b41
                    $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'max':
Chris PeBenito 696b41
                case 'start':
Chris PeBenito 696b41
                    $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'step':
Chris PeBenito 696b41
                    $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                default:
Chris PeBenito 696b41
                    $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!isset($attrs['show']))
Chris PeBenito 696b41
            $output .= "{$section_props}['show'] = true;\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!isset($attrs['loop']))
Chris PeBenito 696b41
            $output .= "{$section_props}['loop'] = 1;\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!isset($attrs['max']))
Chris PeBenito 696b41
            $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
Chris PeBenito 696b41
        else
Chris PeBenito 696b41
            $output .= "if ({$section_props}['max'] < 0)\n" .
Chris PeBenito 696b41
                       "    {$section_props}['max'] = {$section_props}['loop'];\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!isset($attrs['step']))
Chris PeBenito 696b41
            $output .= "{$section_props}['step'] = 1;\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (!isset($attrs['start']))
Chris PeBenito 696b41
            $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
Chris PeBenito 696b41
        else {
Chris PeBenito 696b41
            $output .= "if ({$section_props}['start'] < 0)\n" .
Chris PeBenito 696b41
                       "    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
Chris PeBenito 696b41
                       "else\n" .
Chris PeBenito 696b41
                       "    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .= "if ({$section_props}['show']) {\n";
Chris PeBenito 696b41
        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
Chris PeBenito 696b41
            $output .= "    {$section_props}['total'] = {$section_props}['loop'];\n";
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $output .= "    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $output .= "    if ({$section_props}['total'] == 0)\n" .
Chris PeBenito 696b41
                   "        {$section_props}['show'] = false;\n" .
Chris PeBenito 696b41
                   "} else\n" .
Chris PeBenito 696b41
                   "    {$section_props}['total'] = 0;\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .= "if ({$section_props}['show']):\n";
Chris PeBenito 696b41
        $output .= "
Chris PeBenito 696b41
            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
Chris PeBenito 696b41
                 {$section_props}['iteration'] <= {$section_props}['total'];
Chris PeBenito 696b41
                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
Chris PeBenito 696b41
        $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
Chris PeBenito 696b41
        $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
Chris PeBenito 696b41
        $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
Chris PeBenito 696b41
        $output .= "{$section_props}['first']      = ({$section_props}['iteration'] == 1);\n";
Chris PeBenito 696b41
        $output .= "{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\n";
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output .= "?>";
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {foreach ...} tag.
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_foreach_start($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (empty($attrs['from'])) {
Chris PeBenito 696b41
            return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $from = $attrs['from'];
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (empty($attrs['item'])) {
Chris PeBenito 696b41
            return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $item = $this->_dequote($attrs['item']);
Chris PeBenito 696b41
        if (!preg_match('~^\w+$~', $item)) {
Chris PeBenito 696b41
            return $this->_syntax_error("'foreach: item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($attrs['key'])) {
Chris PeBenito 696b41
            $key  = $this->_dequote($attrs['key']);
Chris PeBenito 696b41
            if (!preg_match('~^\w+$~', $key)) {
Chris PeBenito 696b41
                return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $key_part = "\$this->_tpl_vars['$key'] => ";
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $key = null;
Chris PeBenito 696b41
            $key_part = '';
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($attrs['name'])) {
Chris PeBenito 696b41
            $name = $attrs['name'];
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $name = null;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = '
Chris PeBenito 696b41
        $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
Chris PeBenito 696b41
        if (isset($name)) {
Chris PeBenito 696b41
            $foreach_props = "\$this->_foreach[$name]";
Chris PeBenito 696b41
            $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
Chris PeBenito 696b41
            $output .= "if ({$foreach_props}['total'] > 0):\n";
Chris PeBenito 696b41
            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
Chris PeBenito 696b41
            $output .= "        {$foreach_props}['iteration']++;\n";
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $output .= "if (count(\$_from)):\n";
Chris PeBenito 696b41
            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $output .= '?>';
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {capture} .. {/capture} tags
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param boolean $start true if this is the {capture} tag
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
Chris PeBenito 696b41
    function _compile_capture_tag($start, $tag_args = '')
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $attrs = $this->_parse_attrs($tag_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($start) {
Chris PeBenito 696b41
            if (isset($attrs['name']))
Chris PeBenito 696b41
                $buffer = $attrs['name'];
Chris PeBenito 696b41
            else
Chris PeBenito 696b41
                $buffer = "'default'";
Chris PeBenito 696b41
Chris PeBenito 696b41
            if (isset($attrs['assign']))
Chris PeBenito 696b41
                $assign = $attrs['assign'];
Chris PeBenito 696b41
            else
Chris PeBenito 696b41
                $assign = null;
Chris PeBenito 696b41
            $output = "";
Chris PeBenito 696b41
            $this->_capture_stack[] = array($buffer, $assign);
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            list($buffer, $assign) = array_pop($this->_capture_stack);
Chris PeBenito 696b41
            $output = "_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
Chris PeBenito 696b41
            if (isset($assign)) {
Chris PeBenito 696b41
                $output .= " \$this->assign($assign, ob_get_contents());";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $output .= "ob_end_clean(); ?>";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compile {if ...} tag
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @param boolean $elseif if true, uses elseif instead of if
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_if_tag($tag_args, $elseif = false)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Tokenize args for 'if' tag. */
Chris PeBenito 696b41
        preg_match_all('~(?>
Chris PeBenito 696b41
                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
Chris PeBenito 696b41
                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string
Chris PeBenito 696b41
                \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@    | # valid non-word token
Chris PeBenito 696b41
                \b\w+\b                                                        | # valid word token
Chris PeBenito 696b41
                \S+                                                           # anything else
Chris PeBenito 696b41
                )~x', $tag_args, $match);
Chris PeBenito 696b41
Chris PeBenito 696b41
        $tokens = $match[0];
Chris PeBenito 696b41
Chris PeBenito 696b41
        // make sure we have balanced parenthesis
Chris PeBenito 696b41
        $token_count = array_count_values($tokens);
Chris PeBenito 696b41
        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
Chris PeBenito 696b41
            $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $is_arg_stack = array();
Chris PeBenito 696b41
Chris PeBenito 696b41
        for ($i = 0; $i < count($tokens); $i++) {
Chris PeBenito 696b41
Chris PeBenito 696b41
            $token = &$tokens[$i];
Chris PeBenito 696b41
Chris PeBenito 696b41
            switch (strtolower($token)) {
Chris PeBenito 696b41
                case '!':
Chris PeBenito 696b41
                case '%':
Chris PeBenito 696b41
                case '!==':
Chris PeBenito 696b41
                case '==':
Chris PeBenito 696b41
                case '===':
Chris PeBenito 696b41
                case '>':
Chris PeBenito 696b41
                case '<':
Chris PeBenito 696b41
                case '!=':
Chris PeBenito 696b41
                case '<>':
Chris PeBenito 696b41
                case '<<':
Chris PeBenito 696b41
                case '>>':
Chris PeBenito 696b41
                case '<=':
Chris PeBenito 696b41
                case '>=':
Chris PeBenito 696b41
                case '&&':
Chris PeBenito 696b41
                case '||':
Chris PeBenito 696b41
                case '|':
Chris PeBenito 696b41
                case '^':
Chris PeBenito 696b41
                case '&':
Chris PeBenito 696b41
                case '~':
Chris PeBenito 696b41
                case ')':
Chris PeBenito 696b41
                case ',':
Chris PeBenito 696b41
                case '+':
Chris PeBenito 696b41
                case '-':
Chris PeBenito 696b41
                case '*':
Chris PeBenito 696b41
                case '/':
Chris PeBenito 696b41
                case '@':
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'eq':
Chris PeBenito 696b41
                    $token = '==';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'ne':
Chris PeBenito 696b41
                case 'neq':
Chris PeBenito 696b41
                    $token = '!=';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'lt':
Chris PeBenito 696b41
                    $token = '<';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'le':
Chris PeBenito 696b41
                case 'lte':
Chris PeBenito 696b41
                    $token = '<=';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'gt':
Chris PeBenito 696b41
                    $token = '>';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'ge':
Chris PeBenito 696b41
                case 'gte':
Chris PeBenito 696b41
                    $token = '>=';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'and':
Chris PeBenito 696b41
                    $token = '&&';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'or':
Chris PeBenito 696b41
                    $token = '||';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'not':
Chris PeBenito 696b41
                    $token = '!';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'mod':
Chris PeBenito 696b41
                    $token = '%';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case '(':
Chris PeBenito 696b41
                    array_push($is_arg_stack, $i);
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 'is':
Chris PeBenito 696b41
                    /* If last token was a ')', we operate on the parenthesized
Chris PeBenito 696b41
                       expression. The start of the expression is on the stack.
Chris PeBenito 696b41
                       Otherwise, we operate on the last encountered token. */
Chris PeBenito 696b41
                    if ($tokens[$i-1] == ')')
Chris PeBenito 696b41
                        $is_arg_start = array_pop($is_arg_stack);
Chris PeBenito 696b41
                    else
Chris PeBenito 696b41
                        $is_arg_start = $i-1;
Chris PeBenito 696b41
                    /* Construct the argument for 'is' expression, so it knows
Chris PeBenito 696b41
                       what to operate on. */
Chris PeBenito 696b41
                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
Chris PeBenito 696b41
Chris PeBenito 696b41
                    /* Pass all tokens from next one until the end to the
Chris PeBenito 696b41
                       'is' expression parsing function. The function will
Chris PeBenito 696b41
                       return modified tokens, where the first one is the result
Chris PeBenito 696b41
                       of the 'is' expression and the rest are the tokens it
Chris PeBenito 696b41
                       didn't touch. */
Chris PeBenito 696b41
                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
Chris PeBenito 696b41
Chris PeBenito 696b41
                    /* Replace the old tokens with the new ones. */
Chris PeBenito 696b41
                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
Chris PeBenito 696b41
Chris PeBenito 696b41
                    /* Adjust argument start so that it won't change from the
Chris PeBenito 696b41
                       current position for the next iteration. */
Chris PeBenito 696b41
                    $i = $is_arg_start;
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                default:
Chris PeBenito 696b41
                    if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {
Chris PeBenito 696b41
                            // function call
Chris PeBenito 696b41
                            if($this->security &&
Chris PeBenito 696b41
                               !in_array($token, $this->security_settings['IF_FUNCS'])) {
Chris PeBenito 696b41
                                $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                            }
Chris PeBenito 696b41
                    } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {
Chris PeBenito 696b41
                        // variable function call
Chris PeBenito 696b41
                        $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);                      
Chris PeBenito 696b41
                    } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {
Chris PeBenito 696b41
                        // object or variable
Chris PeBenito 696b41
                        $token = $this->_parse_var_props($token);
Chris PeBenito 696b41
                    } elseif(is_numeric($token)) {
Chris PeBenito 696b41
                        // number, skip it
Chris PeBenito 696b41
                    } else {
Chris PeBenito 696b41
                        $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($elseif)
Chris PeBenito 696b41
            return '';
Chris PeBenito 696b41
        else
Chris PeBenito 696b41
            return '';
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    function _compile_arg_list($type, $name, $attrs, &$cache_code) {
Chris PeBenito 696b41
        $arg_list = array();
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($type) && isset($name)
Chris PeBenito 696b41
            && isset($this->_plugins[$type])
Chris PeBenito 696b41
            && isset($this->_plugins[$type][$name])
Chris PeBenito 696b41
            && empty($this->_plugins[$type][$name][4])
Chris PeBenito 696b41
            && is_array($this->_plugins[$type][$name][5])
Chris PeBenito 696b41
            ) {
Chris PeBenito 696b41
            /* we have a list of parameters that should be cached */
Chris PeBenito 696b41
            $_cache_attrs = $this->_plugins[$type][$name][5];
Chris PeBenito 696b41
            $_count = $this->_cache_attrs_count++;
Chris PeBenito 696b41
            $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
Chris PeBenito 696b41
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            /* no parameters are cached */
Chris PeBenito 696b41
            $_cache_attrs = null;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        foreach ($attrs as $arg_name => $arg_value) {
Chris PeBenito 696b41
            if (is_bool($arg_value))
Chris PeBenito 696b41
                $arg_value = $arg_value ? 'true' : 'false';
Chris PeBenito 696b41
            if (is_null($arg_value))
Chris PeBenito 696b41
                $arg_value = 'null';
Chris PeBenito 696b41
            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
Chris PeBenito 696b41
                $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $arg_list[] = "'$arg_name' => $arg_value";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        return $arg_list;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Parse is expression
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $is_arg
Chris PeBenito 696b41
     * @param array $tokens
Chris PeBenito 696b41
     * @return array
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_is_expr($is_arg, $tokens)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $expr_end = 0;
Chris PeBenito 696b41
        $negate_expr = false;
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (($first_token = array_shift($tokens)) == 'not') {
Chris PeBenito 696b41
            $negate_expr = true;
Chris PeBenito 696b41
            $expr_type = array_shift($tokens);
Chris PeBenito 696b41
        } else
Chris PeBenito 696b41
            $expr_type = $first_token;
Chris PeBenito 696b41
Chris PeBenito 696b41
        switch ($expr_type) {
Chris PeBenito 696b41
            case 'even':
Chris PeBenito 696b41
                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
Chris PeBenito 696b41
                    $expr_end++;
Chris PeBenito 696b41
                    $expr_arg = $tokens[$expr_end++];
Chris PeBenito 696b41
                    $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
Chris PeBenito 696b41
                } else
Chris PeBenito 696b41
                    $expr = "!(1 & $is_arg)";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'odd':
Chris PeBenito 696b41
                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
Chris PeBenito 696b41
                    $expr_end++;
Chris PeBenito 696b41
                    $expr_arg = $tokens[$expr_end++];
Chris PeBenito 696b41
                    $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
Chris PeBenito 696b41
                } else
Chris PeBenito 696b41
                    $expr = "(1 & $is_arg)";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'div':
Chris PeBenito 696b41
                if (@$tokens[$expr_end] == 'by') {
Chris PeBenito 696b41
                    $expr_end++;
Chris PeBenito 696b41
                    $expr_arg = $tokens[$expr_end++];
Chris PeBenito 696b41
                    $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            default:
Chris PeBenito 696b41
                $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if ($negate_expr) {
Chris PeBenito 696b41
            $expr = "!($expr)";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        array_splice($tokens, 0, $expr_end, $expr);
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $tokens;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Parse attribute string
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $tag_args
Chris PeBenito 696b41
     * @return array
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_attrs($tag_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
Chris PeBenito 696b41
        /* Tokenize tag attributes. */
Chris PeBenito 696b41
        preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
Chris PeBenito 696b41
                         )+ |
Chris PeBenito 696b41
                         [=]
Chris PeBenito 696b41
                        ~x', $tag_args, $match);
Chris PeBenito 696b41
        $tokens       = $match[0];
Chris PeBenito 696b41
Chris PeBenito 696b41
        $attrs = array();
Chris PeBenito 696b41
        /* Parse state:
Chris PeBenito 696b41
            0 - expecting attribute name
Chris PeBenito 696b41
            1 - expecting '='
Chris PeBenito 696b41
            2 - expecting attribute value (not '=') */
Chris PeBenito 696b41
        $state = 0;
Chris PeBenito 696b41
Chris PeBenito 696b41
        foreach ($tokens as $token) {
Chris PeBenito 696b41
            switch ($state) {
Chris PeBenito 696b41
                case 0:
Chris PeBenito 696b41
                    /* If the token is a valid identifier, we set attribute name
Chris PeBenito 696b41
                       and go to state 1. */
Chris PeBenito 696b41
                    if (preg_match('~^\w+$~', $token)) {
Chris PeBenito 696b41
                        $attr_name = $token;
Chris PeBenito 696b41
                        $state = 1;
Chris PeBenito 696b41
                    } else
Chris PeBenito 696b41
                        $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 1:
Chris PeBenito 696b41
                    /* If the token is '=', then we go to state 2. */
Chris PeBenito 696b41
                    if ($token == '=') {
Chris PeBenito 696b41
                        $state = 2;
Chris PeBenito 696b41
                    } else
Chris PeBenito 696b41
                        $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                case 2:
Chris PeBenito 696b41
                    /* If token is not '=', we set the attribute value and go to
Chris PeBenito 696b41
                       state 0. */
Chris PeBenito 696b41
                    if ($token != '=') {
Chris PeBenito 696b41
                        /* We booleanize the token if it's a non-quoted possible
Chris PeBenito 696b41
                           boolean value. */
Chris PeBenito 696b41
                        if (preg_match('~^(on|yes|true)$~', $token)) {
Chris PeBenito 696b41
                            $token = 'true';
Chris PeBenito 696b41
                        } else if (preg_match('~^(off|no|false)$~', $token)) {
Chris PeBenito 696b41
                            $token = 'false';
Chris PeBenito 696b41
                        } else if ($token == 'null') {
Chris PeBenito 696b41
                            $token = 'null';
Chris PeBenito 696b41
                        } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {
Chris PeBenito 696b41
                            /* treat integer literally */
Chris PeBenito 696b41
                        } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {
Chris PeBenito 696b41
                            /* treat as a string, double-quote it escaping quotes */
Chris PeBenito 696b41
                            $token = '"'.addslashes($token).'"';
Chris PeBenito 696b41
                        }
Chris PeBenito 696b41
Chris PeBenito 696b41
                        $attrs[$attr_name] = $token;
Chris PeBenito 696b41
                        $state = 0;
Chris PeBenito 696b41
                    } else
Chris PeBenito 696b41
                        $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $last_token = $token;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if($state != 0) {
Chris PeBenito 696b41
            if($state == 1) {
Chris PeBenito 696b41
                $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_parse_vars_props($attrs);
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $attrs;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile multiple variables and section properties tokens into
Chris PeBenito 696b41
     * PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param array $tokens
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_vars_props(&$tokens)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        foreach($tokens as $key => $val) {
Chris PeBenito 696b41
            $tokens[$key] = $this->_parse_var_props($val);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compile single variable and section properties token into
Chris PeBenito 696b41
     * PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $val
Chris PeBenito 696b41
     * @param string $tag_attrs
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_var_props($val)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $val = trim($val);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {
Chris PeBenito 696b41
            // $ variable or object
Chris PeBenito 696b41
            $return = $this->_parse_var($match[1]);
Chris PeBenito 696b41
            $modifiers = $match[2];
Chris PeBenito 696b41
            if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) {
Chris PeBenito 696b41
                $_default_mod_string = implode('|',(array)$this->default_modifiers);
Chris PeBenito 696b41
                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $this->_parse_modifiers($return, $modifiers);
Chris PeBenito 696b41
            return $return;
Chris PeBenito 696b41
        } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
Chris PeBenito 696b41
                // double quoted text
Chris PeBenito 696b41
                preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
Chris PeBenito 696b41
                $return = $this->_expand_quoted_text($match[1]);
Chris PeBenito 696b41
                if($match[2] != '') {
Chris PeBenito 696b41
                    $this->_parse_modifiers($return, $match[2]);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                return $return;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
Chris PeBenito 696b41
                // numerical constant
Chris PeBenito 696b41
                preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
Chris PeBenito 696b41
                if($match[2] != '') {
Chris PeBenito 696b41
                    $this->_parse_modifiers($match[1], $match[2]);
Chris PeBenito 696b41
                    return $match[1];
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
Chris PeBenito 696b41
                // single quoted text
Chris PeBenito 696b41
                preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
Chris PeBenito 696b41
                if($match[2] != '') {
Chris PeBenito 696b41
                    $this->_parse_modifiers($match[1], $match[2]);
Chris PeBenito 696b41
                    return $match[1];
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
Chris PeBenito 696b41
                // config var
Chris PeBenito 696b41
                return $this->_parse_conf_var($val);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
Chris PeBenito 696b41
                // section var
Chris PeBenito 696b41
                return $this->_parse_section_prop($val);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
Chris PeBenito 696b41
            // literal string
Chris PeBenito 696b41
            return $this->_expand_quoted_text('"' . $val .'"');
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        return $val;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * expand quoted text with embedded variables
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $var_expr
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _expand_quoted_text($var_expr)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        // if contains unescaped $, expand it
Chris PeBenito 696b41
        if(preg_match_all('~(?:\`(?_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?
Chris PeBenito 696b41
            $_match = $_match[0];
Chris PeBenito 696b41
            rsort($_match);
Chris PeBenito 696b41
            reset($_match);
Chris PeBenito 696b41
            foreach($_match as $_var) {
Chris PeBenito 696b41
                $var_expr = str_replace ($_var, '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."', $var_expr);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $_return = preg_replace('~\.""|(?
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            $_return = $var_expr;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        // replace double quoted literal string with single quotes
Chris PeBenito 696b41
        $_return = preg_replace('~^"([\s\w]+)"$~',"'\\1'",$_return);
Chris PeBenito 696b41
        return $_return;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * parse variable expression into PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $var_expr
Chris PeBenito 696b41
     * @param string $output
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_var($var_expr)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $_has_math = false;
Chris PeBenito 696b41
        $_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
Chris PeBenito 696b41
Chris PeBenito 696b41
        if(count($_math_vars) > 1) {
Chris PeBenito 696b41
            $_first_var = "";
Chris PeBenito 696b41
            $_complete_var = "";
Chris PeBenito 696b41
            $_output = "";
Chris PeBenito 696b41
            // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
Chris PeBenito 696b41
            foreach($_math_vars as $_k => $_math_var) {
Chris PeBenito 696b41
                $_math_var = $_math_vars[$_k];
Chris PeBenito 696b41
Chris PeBenito 696b41
                if(!empty($_math_var) || is_numeric($_math_var)) {
Chris PeBenito 696b41
                    // hit a math operator, so process the stuff which came before it
Chris PeBenito 696b41
                    if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {
Chris PeBenito 696b41
                        $_has_math = true;
Chris PeBenito 696b41
                        if(!empty($_complete_var) || is_numeric($_complete_var)) {
Chris PeBenito 696b41
                            $_output .= $this->_parse_var($_complete_var);
Chris PeBenito 696b41
                        }
Chris PeBenito 696b41
Chris PeBenito 696b41
                        // just output the math operator to php
Chris PeBenito 696b41
                        $_output .= $_math_var;
Chris PeBenito 696b41
Chris PeBenito 696b41
                        if(empty($_first_var))
Chris PeBenito 696b41
                            $_first_var = $_complete_var;
Chris PeBenito 696b41
Chris PeBenito 696b41
                        $_complete_var = "";
Chris PeBenito 696b41
                    } else {
Chris PeBenito 696b41
                        $_complete_var .= $_math_var;
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if($_has_math) {
Chris PeBenito 696b41
                if(!empty($_complete_var) || is_numeric($_complete_var))
Chris PeBenito 696b41
                    $_output .= $this->_parse_var($_complete_var);
Chris PeBenito 696b41
Chris PeBenito 696b41
                // get the modifiers working (only the last var from math + modifier is left)
Chris PeBenito 696b41
                $var_expr = $_complete_var;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
Chris PeBenito 696b41
        if(is_numeric($var_expr{0}))
Chris PeBenito 696b41
            $_var_ref = $var_expr;
Chris PeBenito 696b41
        else
Chris PeBenito 696b41
            $_var_ref = substr($var_expr, 1);
Chris PeBenito 696b41
        
Chris PeBenito 696b41
        if(!$_has_math) {
Chris PeBenito 696b41
            
Chris PeBenito 696b41
            // get [foo] and .foo and ->foo and (...) pieces
Chris PeBenito 696b41
            preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match);
Chris PeBenito 696b41
                        
Chris PeBenito 696b41
            $_indexes = $match[0];
Chris PeBenito 696b41
            $_var_name = array_shift($_indexes);
Chris PeBenito 696b41
Chris PeBenito 696b41
            /* Handle $smarty.* variable references as a special case. */
Chris PeBenito 696b41
            if ($_var_name == 'smarty') {
Chris PeBenito 696b41
                /*
Chris PeBenito 696b41
                 * If the reference could be compiled, use the compiled output;
Chris PeBenito 696b41
                 * otherwise, fall back on the $smarty variable generated at
Chris PeBenito 696b41
                 * run-time.
Chris PeBenito 696b41
                 */
Chris PeBenito 696b41
                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
Chris PeBenito 696b41
                    $_output = $smarty_ref;
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $_var_name = substr(array_shift($_indexes), 1);
Chris PeBenito 696b41
                    $_output = "\$this->_smarty_vars['$_var_name']";
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) {
Chris PeBenito 696b41
                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
Chris PeBenito 696b41
                if(count($_indexes) > 0)
Chris PeBenito 696b41
                {
Chris PeBenito 696b41
                    $_var_name .= implode("", $_indexes);
Chris PeBenito 696b41
                    $_indexes = array();
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                $_output = $_var_name;
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $_output = "\$this->_tpl_vars['$_var_name']";
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
Chris PeBenito 696b41
            foreach ($_indexes as $_index) {
Chris PeBenito 696b41
                if ($_index{0} == '[') {
Chris PeBenito 696b41
                    $_index = substr($_index, 1, -1);
Chris PeBenito 696b41
                    if (is_numeric($_index)) {
Chris PeBenito 696b41
                        $_output .= "[$_index]";
Chris PeBenito 696b41
                    } elseif ($_index{0} == '$') {
Chris PeBenito 696b41
                        if (strpos($_index, '.') !== false) {
Chris PeBenito 696b41
                            $_output .= '[' . $this->_parse_var($_index) . ']';
Chris PeBenito 696b41
                        } else {
Chris PeBenito 696b41
                            $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
Chris PeBenito 696b41
                        }
Chris PeBenito 696b41
                    } else {
Chris PeBenito 696b41
                        $_var_parts = explode('.', $_index);
Chris PeBenito 696b41
                        $_var_section = $_var_parts[0];
Chris PeBenito 696b41
                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
Chris PeBenito 696b41
                        $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                } else if ($_index{0} == '.') {
Chris PeBenito 696b41
                    if ($_index{1} == '$')
Chris PeBenito 696b41
                        $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
Chris PeBenito 696b41
                    else
Chris PeBenito 696b41
                        $_output .= "['" . substr($_index, 1) . "']";
Chris PeBenito 696b41
                } else if (substr($_index,0,2) == '->') {
Chris PeBenito 696b41
                    if(substr($_index,2,2) == '__') {
Chris PeBenito 696b41
                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    } elseif($this->security && substr($_index, 2, 1) == '_') {
Chris PeBenito 696b41
                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                    } elseif ($_index{2} == '$') {
Chris PeBenito 696b41
                        if ($this->security) {
Chris PeBenito 696b41
                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                        } else {
Chris PeBenito 696b41
                            $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
Chris PeBenito 696b41
                        }
Chris PeBenito 696b41
                    } else {
Chris PeBenito 696b41
                        $_output .= $_index;
Chris PeBenito 696b41
                    }
Chris PeBenito 696b41
                } elseif ($_index{0} == '(') {
Chris PeBenito 696b41
                    $_index = $this->_parse_parenth_args($_index);
Chris PeBenito 696b41
                    $_output .= $_index;
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $_output .= $_index;
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $_output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * parse arguments in function call parenthesis
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $parenth_args
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_parenth_args($parenth_args)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);
Chris PeBenito 696b41
        $orig_vals = $match = $match[0];
Chris PeBenito 696b41
        $this->_parse_vars_props($match);
Chris PeBenito 696b41
        $replace = array();
Chris PeBenito 696b41
        for ($i = 0, $count = count($match); $i < $count; $i++) {
Chris PeBenito 696b41
            $replace[$orig_vals[$i]] = $match[$i];
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        return strtr($parenth_args, $replace);
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * parse configuration variable expression into PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $conf_var_expr
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_conf_var($conf_var_expr)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $parts = explode('|', $conf_var_expr, 2);
Chris PeBenito 696b41
        $var_ref = $parts[0];
Chris PeBenito 696b41
        $modifiers = isset($parts[1]) ? $parts[1] : '';
Chris PeBenito 696b41
Chris PeBenito 696b41
        $var_name = substr($var_ref, 1, -1);
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = "\$this->_config[0]['vars']['$var_name']";
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_parse_modifiers($output, $modifiers);
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * parse section property expression into PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $section_prop_expr
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_section_prop($section_prop_expr)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $parts = explode('|', $section_prop_expr, 2);
Chris PeBenito 696b41
        $var_ref = $parts[0];
Chris PeBenito 696b41
        $modifiers = isset($parts[1]) ? $parts[1] : '';
Chris PeBenito 696b41
Chris PeBenito 696b41
        preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
Chris PeBenito 696b41
        $section_name = $match[1];
Chris PeBenito 696b41
        $prop_name = $match[2];
Chris PeBenito 696b41
Chris PeBenito 696b41
        $output = "\$this->_sections['$section_name']['$prop_name']";
Chris PeBenito 696b41
Chris PeBenito 696b41
        $this->_parse_modifiers($output, $modifiers);
Chris PeBenito 696b41
Chris PeBenito 696b41
        return $output;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * parse modifier chain into PHP code
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * sets $output to parsed modified chain
Chris PeBenito 696b41
     * @param string $output
Chris PeBenito 696b41
     * @param string $modifier_string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _parse_modifiers(&$output, $modifier_string)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);
Chris PeBenito 696b41
        list(, $_modifiers, $modifier_arg_strings) = $_match;
Chris PeBenito 696b41
Chris PeBenito 696b41
        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
Chris PeBenito 696b41
            $_modifier_name = $_modifiers[$_i];
Chris PeBenito 696b41
Chris PeBenito 696b41
            if($_modifier_name == 'smarty') {
Chris PeBenito 696b41
                // skip smarty modifier
Chris PeBenito 696b41
                continue;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
Chris PeBenito 696b41
            preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);
Chris PeBenito 696b41
            $_modifier_args = $_match[1];
Chris PeBenito 696b41
Chris PeBenito 696b41
            if ($_modifier_name{0} == '@') {
Chris PeBenito 696b41
                $_map_array = false;
Chris PeBenito 696b41
                $_modifier_name = substr($_modifier_name, 1);
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                $_map_array = true;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
Chris PeBenito 696b41
            if (empty($this->_plugins['modifier'][$_modifier_name])
Chris PeBenito 696b41
                && !$this->_get_plugin_filepath('modifier', $_modifier_name)
Chris PeBenito 696b41
                && function_exists($_modifier_name)) {
Chris PeBenito 696b41
                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
Chris PeBenito 696b41
                    $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $this->_add_plugin('modifier', $_modifier_name);
Chris PeBenito 696b41
Chris PeBenito 696b41
            $this->_parse_vars_props($_modifier_args);
Chris PeBenito 696b41
Chris PeBenito 696b41
            if($_modifier_name == 'default') {
Chris PeBenito 696b41
                // supress notifications of default modifier vars and args
Chris PeBenito 696b41
                if($output{0} == '$') {
Chris PeBenito 696b41
                    $output = '@' . $output;
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') {
Chris PeBenito 696b41
                    $_modifier_args[0] = '@' . $_modifier_args[0];
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if (count($_modifier_args) > 0)
Chris PeBenito 696b41
                $_modifier_args = ', '.implode(', ', $_modifier_args);
Chris PeBenito 696b41
            else
Chris PeBenito 696b41
                $_modifier_args = '';
Chris PeBenito 696b41
Chris PeBenito 696b41
            if ($_map_array) {
Chris PeBenito 696b41
                $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
Chris PeBenito 696b41
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
Chris PeBenito 696b41
                $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
Chris PeBenito 696b41
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * add plugin
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $type
Chris PeBenito 696b41
     * @param string $name
Chris PeBenito 696b41
     * @param boolean? $delayed_loading
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _add_plugin($type, $name, $delayed_loading = null)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        if (!isset($this->_plugin_info[$type])) {
Chris PeBenito 696b41
            $this->_plugin_info[$type] = array();
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        if (!isset($this->_plugin_info[$type][$name])) {
Chris PeBenito 696b41
            $this->_plugin_info[$type][$name] = array($this->_current_file,
Chris PeBenito 696b41
                                                      $this->_current_line_no,
Chris PeBenito 696b41
                                                      $delayed_loading);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Compiles references of type $smarty.foo
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $indexes
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_smarty_ref(&$indexes)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        /* Extract the reference name. */
Chris PeBenito 696b41
        $_ref = substr($indexes[0], 1);
Chris PeBenito 696b41
        foreach($indexes as $_index_no=>$_index) {
Chris PeBenito 696b41
            if ($_index{0} != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) {
Chris PeBenito 696b41
                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        switch ($_ref) {
Chris PeBenito 696b41
            case 'now':
Chris PeBenito 696b41
                $compiled_ref = 'time()';
Chris PeBenito 696b41
                $_max_index = 1;
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'foreach':
Chris PeBenito 696b41
                array_shift($indexes);
Chris PeBenito 696b41
                $_var = $this->_parse_var_props(substr($indexes[0], 1));
Chris PeBenito 696b41
                $_propname = substr($indexes[1], 1);
Chris PeBenito 696b41
                $_max_index = 1;
Chris PeBenito 696b41
                switch ($_propname) {
Chris PeBenito 696b41
                    case 'index':
Chris PeBenito 696b41
                        array_shift($indexes);
Chris PeBenito 696b41
                        $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)";
Chris PeBenito 696b41
                        break;
Chris PeBenito 696b41
                        
Chris PeBenito 696b41
                    case 'first':
Chris PeBenito 696b41
                        array_shift($indexes);
Chris PeBenito 696b41
                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)";
Chris PeBenito 696b41
                        break;
Chris PeBenito 696b41
Chris PeBenito 696b41
                    case 'last':
Chris PeBenito 696b41
                        array_shift($indexes);
Chris PeBenito 696b41
                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])";
Chris PeBenito 696b41
                        break;
Chris PeBenito 696b41
                        
Chris PeBenito 696b41
                    case 'show':
Chris PeBenito 696b41
                        array_shift($indexes);
Chris PeBenito 696b41
                        $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)";
Chris PeBenito 696b41
                        break;
Chris PeBenito 696b41
                        
Chris PeBenito 696b41
                    default:
Chris PeBenito 696b41
                        unset($_max_index);
Chris PeBenito 696b41
                        $compiled_ref = "\$this->_foreach[$_var]";
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'section':
Chris PeBenito 696b41
                array_shift($indexes);
Chris PeBenito 696b41
                $_var = $this->_parse_var_props(substr($indexes[0], 1));
Chris PeBenito 696b41
                $compiled_ref = "\$this->_sections[$_var]";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'get':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'post':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'cookies':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'env':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'server':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'session':
Chris PeBenito 696b41
                $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            /*
Chris PeBenito 696b41
             * These cases are handled either at run-time or elsewhere in the
Chris PeBenito 696b41
             * compiler.
Chris PeBenito 696b41
             */
Chris PeBenito 696b41
            case 'request':
Chris PeBenito 696b41
                if ($this->request_use_auto_globals) {
Chris PeBenito 696b41
                    $compiled_ref = '$_REQUEST';
Chris PeBenito 696b41
                    break;
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $this->_init_smarty_vars = true;
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                return null;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'capture':
Chris PeBenito 696b41
                return null;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'template':
Chris PeBenito 696b41
                $compiled_ref = "'$this->_current_file'";
Chris PeBenito 696b41
                $_max_index = 1;
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'version':
Chris PeBenito 696b41
                $compiled_ref = "'$this->_version'";
Chris PeBenito 696b41
                $_max_index = 1;
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'const':
Chris PeBenito 696b41
                if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {
Chris PeBenito 696b41
                    $this->_syntax_error("(secure mode) constants not permitted",
Chris PeBenito 696b41
                                         E_USER_WARNING, __FILE__, __LINE__);
Chris PeBenito 696b41
                    return;
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                array_shift($indexes);
Chris PeBenito 696b41
                if (preg_match('!^\.\w+$!', $indexes[0])) {
Chris PeBenito 696b41
                    $compiled_ref = '@' . substr($indexes[0], 1);
Chris PeBenito 696b41
                } else {
Chris PeBenito 696b41
                    $_val = $this->_parse_var_props(substr($indexes[0], 1));
Chris PeBenito 696b41
                    $compiled_ref = '@constant(' . $_val . ')';
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
                $_max_index = 1;
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'config':
Chris PeBenito 696b41
                $compiled_ref = "\$this->_config[0]['vars']";
Chris PeBenito 696b41
                $_max_index = 3;
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'ldelim':
Chris PeBenito 696b41
                $compiled_ref = "'$this->left_delimiter'";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
Chris PeBenito 696b41
            case 'rdelim':
Chris PeBenito 696b41
                $compiled_ref = "'$this->right_delimiter'";
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
                
Chris PeBenito 696b41
            default:
Chris PeBenito 696b41
                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
                break;
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        if (isset($_max_index) && count($indexes) > $_max_index) {
Chris PeBenito 696b41
            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
Chris PeBenito 696b41
        array_shift($indexes);
Chris PeBenito 696b41
        return $compiled_ref;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * compiles call to plugin of type $type with name $name
Chris PeBenito 696b41
     * returns a string containing the function-name or method call
Chris PeBenito 696b41
     * without the paramter-list that would have follow to make the
Chris PeBenito 696b41
     * call valid php-syntax
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $type
Chris PeBenito 696b41
     * @param string $name
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _compile_plugin_call($type, $name) {
Chris PeBenito 696b41
        if (isset($this->_plugins[$type][$name])) {
Chris PeBenito 696b41
            /* plugin loaded */
Chris PeBenito 696b41
            if (is_array($this->_plugins[$type][$name][0])) {
Chris PeBenito 696b41
                return ((is_object($this->_plugins[$type][$name][0][0])) ?
Chris PeBenito 696b41
                        "\$this->_plugins['$type']['$name'][0][0]->"    /* method callback */
Chris PeBenito 696b41
                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */
Chris PeBenito 696b41
                       ). $this->_plugins[$type][$name][0][1];
Chris PeBenito 696b41
Chris PeBenito 696b41
            } else {
Chris PeBenito 696b41
                /* function callback */
Chris PeBenito 696b41
                return $this->_plugins[$type][$name][0];
Chris PeBenito 696b41
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        } else {
Chris PeBenito 696b41
            /* plugin not loaded -> auto-loadable-plugin */
Chris PeBenito 696b41
            return 'smarty_'.$type.'_'.$name;
Chris PeBenito 696b41
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * load pre- and post-filters
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _load_filters()
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        if (count($this->_plugins['prefilter']) > 0) {
Chris PeBenito 696b41
            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
Chris PeBenito 696b41
                if ($prefilter === false) {
Chris PeBenito 696b41
                    unset($this->_plugins['prefilter'][$filter_name]);
Chris PeBenito 696b41
                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
Chris PeBenito 696b41
                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
Chris PeBenito 696b41
                    smarty_core_load_plugins($_params, $this);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        if (count($this->_plugins['postfilter']) > 0) {
Chris PeBenito 696b41
            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
Chris PeBenito 696b41
                if ($postfilter === false) {
Chris PeBenito 696b41
                    unset($this->_plugins['postfilter'][$filter_name]);
Chris PeBenito 696b41
                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
Chris PeBenito 696b41
                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
Chris PeBenito 696b41
                    smarty_core_load_plugins($_params, $this);
Chris PeBenito 696b41
                }
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * Quote subpattern references
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $string
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _quote_replace($string)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        return strtr($string, array('\\' => '\\\\', '$' => '\\$'));
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * display Smarty syntax error
Chris PeBenito 696b41
     *
Chris PeBenito 696b41
     * @param string $error_msg
Chris PeBenito 696b41
     * @param integer $error_type
Chris PeBenito 696b41
     * @param string $file
Chris PeBenito 696b41
     * @param integer $line
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * check if the compilation changes from cacheable to
Chris PeBenito 696b41
     * non-cacheable state with the beginning of the current
Chris PeBenito 696b41
     * plugin. return php-code to reflect the transition.
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _push_cacheable_state($type, $name) {
Chris PeBenito 696b41
        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
Chris PeBenito 696b41
        if ($_cacheable
Chris PeBenito 696b41
            || 0<$this->_cacheable_state++) return '';
Chris PeBenito 696b41
        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
Chris PeBenito 696b41
        $_ret = 'if ($this->caching && !$this->_cache_including) { echo \'{nocache:'
Chris PeBenito 696b41
            . $this->_cache_serial . '#' . $this->_nocache_count
Chris PeBenito 696b41
            . '}\';}';
Chris PeBenito 696b41
        return $_ret;
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * check if the compilation changes from non-cacheable to
Chris PeBenito 696b41
     * cacheable state with the end of the current plugin return
Chris PeBenito 696b41
     * php-code to reflect the transition.
Chris PeBenito 696b41
     * @return string
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _pop_cacheable_state($type, $name) {
Chris PeBenito 696b41
        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
Chris PeBenito 696b41
        if ($_cacheable
Chris PeBenito 696b41
            || --$this->_cacheable_state>0) return '';
Chris PeBenito 696b41
        return 'if ($this->caching && !$this->_cache_including) { echo \'{/nocache:'
Chris PeBenito 696b41
            . $this->_cache_serial . '#' . ($this->_nocache_count++)
Chris PeBenito 696b41
            . '}\';}';
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * push opening tag-name, file-name and line-number on the tag-stack
Chris PeBenito 696b41
     * @param string the opening tag's name
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _push_tag($open_tag)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
    /**
Chris PeBenito 696b41
     * pop closing tag-name
Chris PeBenito 696b41
     * raise an error if this stack-top doesn't match with the closing tag
Chris PeBenito 696b41
     * @param string the closing tag's name
Chris PeBenito 696b41
     * @return string the opening tag's name
Chris PeBenito 696b41
     */
Chris PeBenito 696b41
    function _pop_tag($close_tag)
Chris PeBenito 696b41
    {
Chris PeBenito 696b41
        $message = '';
Chris PeBenito 696b41
        if (count($this->_tag_stack)>0) {
Chris PeBenito 696b41
            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
Chris PeBenito 696b41
            if ($close_tag == $_open_tag) {
Chris PeBenito 696b41
                return $_open_tag;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
Chris PeBenito 696b41
                return $this->_pop_tag($close_tag);
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
Chris PeBenito 696b41
                $this->_pop_tag($close_tag);
Chris PeBenito 696b41
                return $_open_tag;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
Chris PeBenito 696b41
                $this->_pop_tag($close_tag);
Chris PeBenito 696b41
                return $_open_tag;
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            if ($_open_tag == 'else' || $_open_tag == 'elseif') {
Chris PeBenito 696b41
                $_open_tag = 'if';
Chris PeBenito 696b41
            } elseif ($_open_tag == 'sectionelse') {
Chris PeBenito 696b41
                $_open_tag = 'section';
Chris PeBenito 696b41
            } elseif ($_open_tag == 'foreachelse') {
Chris PeBenito 696b41
                $_open_tag = 'foreach';
Chris PeBenito 696b41
            }
Chris PeBenito 696b41
            $message = " expected {/$_open_tag} (opened line $_line_no).";
Chris PeBenito 696b41
        }
Chris PeBenito 696b41
        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
Chris PeBenito 696b41
                             E_USER_ERROR, __FILE__, __LINE__);
Chris PeBenito 696b41
    }
Chris PeBenito 696b41
Chris PeBenito 696b41
}
Chris PeBenito 696b41
Chris PeBenito 696b41
/**
Chris PeBenito 696b41
 * compare to values by their string length
Chris PeBenito 696b41
 *
Chris PeBenito 696b41
 * @access private
Chris PeBenito 696b41
 * @param string $a
Chris PeBenito 696b41
 * @param string $b
Chris PeBenito 696b41
 * @return 0|-1|1
Chris PeBenito 696b41
 */
Chris PeBenito 696b41
function _smarty_sort_length($a, $b)
Chris PeBenito 696b41
{
Chris PeBenito 696b41
    if($a == $b)
Chris PeBenito 696b41
        return 0;
Chris PeBenito 696b41
Chris PeBenito 696b41
    if(strlen($a) == strlen($b))
Chris PeBenito 696b41
        return ($a > $b) ? -1 : 1;
Chris PeBenito 696b41
Chris PeBenito 696b41
    return (strlen($a) > strlen($b)) ? -1 : 1;
Chris PeBenito 696b41
}
Chris PeBenito 696b41
Chris PeBenito 696b41
Chris PeBenito 696b41
/* vim: set et: */
Chris PeBenito 696b41
Chris PeBenito 696b41
?>