reverted test
[phpeclipse.git] / net.sourceforge.phpeclipse.test / src / net / sourceforge / phpeclipse / tests / parser / SmartyCompilerTestCase.java
1 package net.sourceforge.phpeclipse.tests.parser;
2
3 /*******************************************************************************
4  * Copyright (c) 2002 www.phpeclipse.de All rights
5  * reserved. This program and the accompanying materials are made available
6  * under the terms of the Common Public License v1.0 which accompanies this
7  * distribution, and is available at http://www.eclipse.org/legal/cpl-v10.html
8  ******************************************************************************/
9 import net.sourceforge.phpdt.core.tests.util.AbstractCompilerTest;
10
11 /**
12  * Tests the php parser
13  */
14 public class SmartyCompilerTestCase extends AbstractCompilerTest {
15         // Parser parser;
16         public SmartyCompilerTestCase(String name) {
17                 super(name);
18         }
19
20         /**
21          * Test the PHP Parser with different PHP snippets
22          */
23         public void testPHPParser() {
24                 checkHTML("<?php\n"
25                                 + "\n"
26                                 + "/**\n"
27                                 + " * Project:     Smarty: the PHP compiling template engine\n"
28                                 + " * File:        Smarty_Compiler.class.php\n"
29                                 + " * Author:      Monte Ohrt <monte@ispi.net>\n"
30                                 + " *              Andrei Zmievski <andrei@php.net>\n"
31                                 + " *\n"
32                                 + " * Version:     2.4.2\n"
33                                 + " * Copyright:   2001,2002 ispi of Lincoln, Inc.\n"
34                                 + " *\n"
35                                 + " * This library is free software; you can redistribute it and/or\n"
36                                 + " * modify it under the terms of the GNU Lesser General Public\n"
37                                 + " * License as published by the Free Software Foundation; either\n"
38                                 + " * version 2.1 of the License, or (at your option) any later version.\n"
39                                 + " *\n"
40                                 + " * This library is distributed in the hope that it will be useful,\n"
41                                 + " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
42                                 + " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
43                                 + " * Lesser General Public License for more details.\n"
44                                 + " *\n"
45                                 + " * You should have received a copy of the GNU Lesser General Public\n"
46                                 + " * License along with this library; if not, write to the Free Software\n"
47                                 + " * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
48                                 + " *\n"
49                                 + " * You may contact the authors of Smarty by e-mail at:\n"
50                                 + " * monte@ispi.net\n"
51                                 + " * andrei@php.net\n"
52                                 + " *\n"
53                                 + " * Or, write to:\n"
54                                 + " * Monte Ohrt\n"
55                                 + " * Director of Technology, ispi\n"
56                                 + " * 237 S. 70th suite 220\n"
57                                 + " * Lincoln, NE 68510\n"
58                                 + " *\n"
59                                 + " * The latest version of Smarty can be obtained from:\n"
60                                 + " * http://www.phpinsider.com/\n"
61                                 + " *\n"
62                                 + " */\n"
63                                 + "\n"
64                                 + "class Smarty_Compiler extends Smarty {\n"
65                                 + "     \n"
66                                 + "    // internal vars\n"
67                                 + "    public $_sectionelse_stack     =   array();    // keeps track of whether section had \'else\' part\n"
68                                 + "    public $_foreachelse_stack     =   array();    // keeps track of whether foreach had \'else\' part\n"
69                                 + "    public $_literal_blocks        =   array();    // keeps literal template blocks\n"
70                                 + "    public $_php_blocks            =   array();    // keeps php code blocks\n"
71                                 + "    public $_current_file          =   null;       // the current template being compiled\n"
72                                 + "    public $_current_line_no       =   1;          // line number for error messages\n"
73                                 + "    public $_capture_stack         =   array();    // keeps track of nested capture buffers\n"
74                                 + "    public $_plugin_info           =   array();    // keeps track of plugins to load\n"
75                                 + "    public $_init_smarty_vars      =   false;\n"
76                                 + "     public $_permitted_tokens               =       array(\'true\',\'false\',\'yes\',\'no\',\'on\',\'off\');\n"
77                                 + "    public $_db_qstr_regexp          =       null;           // regexps are setup in the constructor\n"
78                                 + "    public $_si_qstr_regexp          =       null;\n"
79                                 + "    public $_qstr_regexp                     =       null;\n"
80                                 + "    public $_func_regexp                     =       null;\n"
81                                 + "    public $_var_bracket_regexp      =       null;\n"
82                                 + "    public $_dvar_guts_regexp                =       null;\n"
83                                 + "    public $_dvar_regexp                     =       null;\n"
84                                 + "    public $_cvar_regexp                     =       null;\n"
85                                 + "    public $_svar_regexp                     =       null;\n"
86                                 + "    public $_avar_regexp                     =       null;\n"
87                                 + "    public $_mod_regexp                      =       null;\n"
88                                 + "    public $_var_regexp                  =   null;\n"
89                                 + "    public $_parenth_param_regexp    =       null;\n"
90                                 + "     public $_func_call_regexp               =       null;\n"
91                                 + "     public $_obj_ext_regexp         =       null;\n"
92                                 + "     public $_obj_start_regexp               =       null;\n"
93                                 + "     public $_obj_params_regexp              =       null;\n"
94                                 + "     public $_obj_call_regexp                =       null;\n"
95                                 + "\n"
96                                 + "     /**\n"
97                                 + "      * The class constructor.\n"
98                                 + "      *\n"
99                                 + "      * @access public\n"
100                                 + "      */\n"
101                                 + "    function Smarty_Compiler()\n"
102                                 + "    {\n"
103                                 + "             // matches double quoted strings:\n"
104                                 + "             // \"foobar\"\n"
105                                 + "             // \"foo\\\"bar\"\n"
106                                 + "     $this->_db_qstr_regexp = \'\"[^\"\\\\\\\\]*(?:\\\\\\\\.[^\"\\\\\\\\]*)*\"\';\n"
107                                 + "\n"
108                                 + "             // matches single quoted strings:\n"
109                                 + "             // \'foobar\'\n"
110                                 + "             // \'foo\\\'bar\'\n"
111                                 + "     $this->_si_qstr_regexp = \'\\\'[^\\\'\\\\\\\\]*(?:\\\\\\\\.[^\\\'\\\\\\\\]*)*\\\'\';\n"
112                                 + "\n"
113                                 + "             // matches single or double quoted strings\n"
114                                 + "     $this->_qstr_regexp = \'(?:\' . $this->_db_qstr_regexp . \'|\' . $this->_si_qstr_regexp . \')\';\n"
115                                 + "\n"
116                                 + "             // matches bracket portion of vars\n"
117                                 + "             // [0]\n"
118                                 + "             // [foo]\n"
119                                 + "             // [$bar]\n"
120                                 + "             $this->_var_bracket_regexp = \'\\[\\$?[\\w\\.]+\\]\';\n"
121                                 + "                             \n"
122                                 + "             // matches $ vars (not objects):\n"
123                                 + "             // $foo\n"
124                                 + "             // $foo.bar\n"
125                                 + "             // $foo.bar.foobar\n"
126                                 + "             // $foo[0]\n"
127                                 + "             // $foo[$bar]\n"
128                                 + "             // $foo[5][blah]\n"
129                                 + "             // $foo[5].bar[$foobar][4]\n"
130                                 + "             $this->_dvar_guts_regexp = \'\\w+(?:\' . $this->_var_bracket_regexp\n"
131                                 + "                             . \')*(?:\\.\\$?\\w+(?:\' . $this->_var_bracket_regexp . \')*)*\';\n"
132                                 + "             $this->_dvar_regexp = \'\\$\' . $this->_dvar_guts_regexp;\n"
133                                 + "\n"
134                                 + "             // matches config vars:\n"
135                                 + "             // #foo#\n"
136                                 + "             // #foobar123_foo#\n"
137                                 + "             $this->_cvar_regexp = \'\\#\\w+\\#\';\n"
138                                 + "\n"
139                                 + "             // matches section vars:\n"
140                                 + "             // %foo.bar%\n"
141                                 + "             $this->_svar_regexp = \'\\%\\w+\\.\\w+\\%\';\n"
142                                 + "\n"
143                                 + "             // matches all valid variables (no quotes, no modifiers)\n"
144                                 + "             $this->_avar_regexp = \'(?:\' . $this->_dvar_regexp . \'|\'\n"
145                                 + "                . $this->_cvar_regexp . \'|\' . $this->_svar_regexp . \')\';\n"
146                                 + "\n"
147                                 + "             // matches valid modifier syntax:\n"
148                                 + "             // |foo\n"
149                                 + "             // |@foo\n"
150                                 + "             // |foo:\"bar\"\n"
151                                 + "             // |foo:$bar\n"
152                                 + "             // |foo:\"bar\":$foobar\n"
153                                 + "             // |foo|bar\n"
154                                 + "             // |foo\n"
155                                 + "             $this->_mod_regexp = \'(?:\\|@?\\w+(?::(?>\\w+|\'\n"
156                                 + "                . $this->_avar_regexp . \'|\' . $this->_qstr_regexp .\'))*)\';\n"
157                                 + "\n"
158                                 + "             // matches valid variable syntax:\n"
159                                 + "             // $foo\n"
160                                 + "             // $foo\n"
161                                 + "             // #foo#\n"
162                                 + "             // #foo#\n"
163                                 + "             // \"text\"\n"
164                                 + "             // \"text\"\n"
165                                 + "             $this->_var_regexp = \'(?:\' . $this->_avar_regexp . \'|\' . $this->_qstr_regexp . \')\';\n"
166                                 + "                             \n"
167                                 + "             // matches valid object call (no objects allowed in parameters):\n"
168                                 + "             // $foo->bar\n"
169                                 + "             // $foo->bar()\n"
170                                 + "             // $foo->bar(\"text\")\n"
171                                 + "             // $foo->bar($foo, $bar, \"text\")\n"
172                                 + "             // $foo->bar($foo|bar, \"foo\"|bar)\n"
173                                 + "             // $foo->bar->foo()\n"
174                                 + "             // $foo->bar->foo->bar()\n"
175                                 + "             $this->_obj_ext_regexp = \'\\->(?:\\w+|\' . $this->_dvar_regexp . \')\';\n"
176                                 + "     $this->_obj_params_regexp = \'\\((?:\\w+|\'\n"
177                                 + "                             . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*)(?:\\s*,\\s*(?:(?:\\w+|\'\n"
178                                 + "                             . $this->_var_regexp . \'(?>\' . $this->_mod_regexp . \'*))))*)?\\)\';          \n"
179                                 + "     $this->_obj_start_regexp = \'(?:\' . $this->_dvar_regexp . \'(?:\' . $this->_obj_ext_regexp . \')+)\';\n"
180                                 + "             $this->_obj_call_regexp = \'(?:\' . $this->_obj_start_regexp . \'(?:\' . $this->_obj_params_regexp . \')?)\';\n"
181                                 + "             \n"
182                                 + "             // matches valid function name:\n"
183                                 + "             // foo123\n"
184                                 + "             // _foo_bar\n"
185                                 + "             $this->_func_regexp = \'[a-zA-Z_]\\w*\';\n"
186                                 + "\n"
187                                 + "             // matches valid registered object:\n"
188                                 + "             // foo.bar\n"
189                                 + "             $this->_reg_obj_regexp = \'[a-zA-Z_]\\w*->[a-zA-Z_]\\w*\';\n"
190                                 + "                             \n"
191                                 + "             // matches valid parameter values:\n"
192                                 + "             // true\n"
193                                 + "             // $foo\n"
194                                 + "             // $foo|bar\n"
195                                 + "             // #foo#\n"
196                                 + "             // #foo#|bar\n"
197                                 + "             // \"text\"\n"
198                                 + "             // \"text\"|bar\n"
199                                 + "             // $foo->bar\n"
200                                 + "             $this->_param_regexp = \'(?:\\s*(?:\' . $this->_obj_call_regexp . \'|\'\n"
201                                 + "                . $this->_var_regexp  . \'|\\w+)(?>\' . $this->_mod_regexp . \'*)\\s*)\';            \n"
202                                 + "             \n"
203                                 + "             // matches valid parenthesised function parameters:\n"
204                                 + "             // \n"
205                                 + "             // \"text\"\n"
206                                 + "             //      $foo, $bar, \"text\"\n"
207                                 + "             // $foo|bar, \"foo\"|bar, $foo->bar($foo)|bar\n"
208                                 + "     $this->_parenth_param_regexp = \'(?:\\((?:\\w+|\'\n"
209                                 + "                             . $this->_param_regexp . \'(?:\\s*,\\s*(?:(?:\\w+|\'\n"
210                                 + "                             . $this->_param_regexp . \')))*)?\\))\';\n"
211                                 + "     \n"
212                                 + "             // matches valid function call:\n"
213                                 + "             // foo()\n"
214                                 + "             // foo_bar($foo)\n"
215                                 + "             // _foo_bar($foo,\"bar\")\n"
216                                 + "             // foo123($foo,$foo->bar(),\"foo\")\n"
217                                 + "     $this->_func_call_regexp = \'(?:\' . $this->_func_regexp . \'\\s*(?:\'\n"
218                                 + "                . $this->_parenth_param_regexp . \'))\';             \n"
219                                 + "\n"
220                                 + "     }                       \n"
221                                 + "                     \n"
222                                 + "     /**\n"
223                                 + "      * compile a template file\n"
224                                 + "      *\n"
225                                 + "      * @access public\n"
226                                 + "      * @param  $tpl_file\n"
227                                 + "      * @param  $template_source\n"
228                                 + "      * @param  $template_compiled\n"
229                                 + "      */\n"
230                                 + "    function _compile_file($tpl_file, $template_source, &$template_compiled)\n"
231                                 + "    {\n"
232                                 + "        if ($this->security) {\n"
233                                 + "            // do not allow php syntax to be executed unless specified\n"
234                                 + "            if ($this->php_handling == SMARTY_PHP_ALLOW &&\n"
235                                 + "                !$this->security_settings[\'PHP_HANDLING\']) {\n"
236                                 + "                $this->php_handling = SMARTY_PHP_PASSTHRU;\n"
237                                 + "            }\n"
238                                 + "        }\n"
239                                 + "\n"
240                                 + "        $this->_load_filters();\n"
241                                 + "\n"
242                                 + "        $this->_current_file = $tpl_file;\n"
243                                 + "        $this->_current_line_no = 1;\n"
244                                 + "        $ldq = preg_quote($this->left_delimiter, \'!\');\n"
245                                 + "        $rdq = preg_quote($this->right_delimiter, \'!\');\n"
246                                 + "\n"
247                                 + "        // run template source through prefilter functions\n"
248                                 + "        if (count($this->_plugins[\'prefilter\']) > 0) {\n"
249                                 + "            foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\n"
250                                 + "                if ($prefilter === false) continue; \n"
251                                 + "                if ($prefilter[3] || function_exists($prefilter[0])) {\n"
252                                 + "                    $template_source = $prefilter[0]($template_source, $this);\n"
253                                 + "                    $this->_plugins[\'prefilter\'][$filter_name][3] = true;\n"
254                                 + "                } else {\n"
255                                 + "                    $this->_trigger_fatal_error(\"[plugin] prefilter \'$filter_name\' is not implemented\");\n"
256                                 + "                }\n"
257                                 + "            }\n"
258                                 + "        }\n"
259                                 + "\n"
260                                 + "        /* Annihilate the comments. */\n"
261                                 + "        $template_source = preg_replace(\"!({$ldq})\\*(.*?)\\*({$rdq})!se\",\n"
262                                 + "                                        \"\'\\\\1*\'.str_repeat(\\\"\\n\\\", substr_count(\'\\\\2\', \\\"\\n\\\")) .\'*\\\\3\'\",\n"
263                                 + "                                        $template_source);\n"
264                                 + "\n"
265                                 + "        /* Pull out the literal blocks. */\n"
266                                 + "        preg_match_all(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\", $template_source, $match);\n"
267                                 + "        $this->_literal_blocks = $match[1];\n"
268                                 + "        $template_source = preg_replace(\"!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s\",\n"
269                                 + "                                        $this->quote_replace($this->left_delimiter.\'literal\'.$this->right_delimiter), $template_source);\n"
270                                 + "\n"
271                                 + "        /* Pull out the php code blocks. */\n"
272                                 + "        preg_match_all(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\", $template_source, $match);\n"
273                                 + "        $this->_php_blocks = $match[1];\n"
274                                 + "        $template_source = preg_replace(\"!{$ldq}php{$rdq}(.*?){$ldq}/php{$rdq}!s\",\n"
275                                 + "                                        $this->quote_replace($this->left_delimiter.\'php\'.$this->right_delimiter), $template_source);\n"
276                                 + "\n"
277                                 + "        /* Gather all template tags. */\n"
278                                 + "        preg_match_all(\"!{$ldq}\\s*(.*?)\\s*{$rdq}!s\", $template_source, $match);\n"
279                                 + "        $template_tags = $match[1];\n"
280                                 + "        /* Split content by template tags to obtain non-template content. */\n"
281                                 + "        $text_blocks = preg_split(\"!{$ldq}.*?{$rdq}!s\", $template_source);\n"
282                                 + "             \n"
283                                 + "        /* loop through text blocks */\n"
284                                 + "        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {\n"
285                                 + "            /* match anything resembling php tags */\n"
286                                 + "            if (preg_match_all(\'!(<\\?(?:\\w+|=)?|\\?>|language\\s*=\\s*[\\\"\\\']?php[\\\"\\\']?)!is\', $text_blocks[$curr_tb], $sp_match)) {\n"
287                                 + "                             /* replace tags with placeholders to prevent recursive replacements */\n"
288                                 + "                             $sp_match[1] = array_unique($sp_match[1]);\n"
289                                 + "                             usort($sp_match[1], \'_smarty_sort_length\');\n"
290                                 + "                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {\n"
291                                 + "                                     $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],\'%%%SMARTYSP\'.$curr_sp.\'%%%\',$text_blocks[$curr_tb]);\n"
292                                 + "                             }\n"
293                                 + "                /* process each one */\n"
294                                 + "                for ($curr_sp = 0, $for_max2 = count($sp_match[0]); $curr_sp < $for_max2; $curr_sp++) {\n"
295                                 + "                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {\n"
296                                 + "                        /* echo php contents */\n"
297                                 + "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'<?php echo \\\'\'.str_replace(\"\'\", \"\\\'\", $sp_match[1][$curr_sp]).\'\\\'; ?>\'.\"\\n\", $text_blocks[$curr_tb]);\n"
298                                 + "                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {\n"
299                                 + "                        /* quote php tags */\n"
300                                 + "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);\n"
301                                 + "                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {\n"
302                                 + "                        /* remove php tags */\n"
303                                 + "                        $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', \'\', $text_blocks[$curr_tb]);\n"
304                                 + "                    } else {\n"
305                                 + "                                             /* SMARTY_PHP_ALLOW, but echo non php starting tags */\n"
306                                 + "                                             $sp_match[1][$curr_sp] = preg_replace(\'%(<\\?(?!php|=|$))%i\', \'<?php echo \\\'\\\\1\\\'?>\'.\"\\n\", $sp_match[1][$curr_sp]);\n"
307                                 + "                                             $text_blocks[$curr_tb] = str_replace(\'%%%SMARTYSP\'.$curr_sp.\'%%%\', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);\n"
308                                 + "                                     }\n"
309                                 + "                }\n"
310                                 + "            }\n"
311                                 + "        }\n"
312                                 + "\n"
313                                 + "        /* Compile the template tags into PHP code. */\n"
314                                 + "        $compiled_tags = array();\n"
315                                 + "        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {\n"
316                                 + "            $this->_current_line_no += substr_count($text_blocks[$i], \"\\n\");\n"
317                                 + "            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);\n"
318                                 + "            $this->_current_line_no += substr_count($template_tags[$i], \"\\n\");\n"
319                                 + "        }\n"
320                                 + "\n"
321                                 + "        $template_compiled = \'\';\n"
322                                 + "\n"
323                                 + "        /* Interleave the compiled contents and text blocks to get the final result. */\n"
324                                 + "        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {\n"
325                                 + "            $template_compiled .= $text_blocks[$i].$compiled_tags[$i];\n"
326                                 + "        }\n"
327                                 + "        $template_compiled .= $text_blocks[$i];\n"
328                                 + "\n"
329                                 + "        /* Reformat data between \'strip\' and \'/strip\' tags, removing spaces, tabs and newlines. */\n"
330                                 + "        if (preg_match_all(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\", $template_compiled, $match)) {\n"
331                                 + "            $strip_tags = $match[0];\n"
332                                 + "            $strip_tags_modified = preg_replace(\"!{$ldq}/?strip{$rdq}|[\\t ]+$|^[\\t ]+!m\", \'\', $strip_tags);\n"
333                                 + "            $strip_tags_modified = preg_replace(\'![\\r\\n]+!m\', \'\', $strip_tags_modified);\n"
334                                 + "            for ($i = 0, $for_max = count($strip_tags); $i < $for_max; $i++)\n"
335                                 + "                $template_compiled = preg_replace(\"!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s\",\n"
336                                 + "                                                  $this->quote_replace($strip_tags_modified[$i]),\n"
337                                 + "                                                  $template_compiled, 1);\n"
338                                 + "        }\n"
339                                 + "\n"
340                                 + "        // remove \\n from the end of the file, if any\n"
341                                 + "        if ($template_compiled{strlen($template_compiled) - 1} == \"\\n\" ) {\n"
342                                 + "            $template_compiled = substr($template_compiled, 0, -1);\n"
343                                 + "        }\n"
344                                 + "\n"
345                                 + "        // run compiled template through postfilter functions\n"
346                                 + "        if (count($this->_plugins[\'postfilter\']) > 0) {\n"
347                                 + "            foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\n"
348                                 + "                if ($postfilter === false) continue;\n"
349                                 + "                if ($postfilter[3] || function_exists($postfilter[0])) {\n"
350                                 + "                    $template_compiled = $postfilter[0]($template_compiled, $this);\n"
351                                 + "                    $this->_plugins[\'postfilter\'][$filter_name][3] = true;\n"
352                                 + "                } else {\n"
353                                 + "                    $this->_trigger_plugin_error(\"Smarty plugin error: postfilter \'$filter_name\' is not implemented\");\n"
354                                 + "                }\n"
355                                 + "            }\n"
356                                 + "        }\n"
357                                 + "\n"
358                                 + "        // put header at the top of the compiled template\n"
359                                 + "        $template_header = \"<?php /* Smarty version \".$this->_version.\", created on \".strftime(\"%Y-%m-%d %H:%M:%S\").\"\\n\";\n"
360                                 + "        $template_header .= \"         compiled from \".$tpl_file.\" */ ?>\\n\";\n"
361                                 + "\n"
362                                 + "        /* Emit code to load needed plugins. */\n"
363                                 + "        if (count($this->_plugin_info)) {\n"
364                                 + "            $plugins_code = \'<?php $this->_load_plugins(array(\';\n"
365                                 + "            foreach ($this->_plugin_info as $plugin_type => $plugins) {\n"
366                                 + "                foreach ($plugins as $plugin_name => $plugin_info) {\n"
367                                 + "                    $plugins_code .= \"\\narray(\'$plugin_type\', \'$plugin_name\', \'$plugin_info[0]\', $plugin_info[1], \";\n"
368                                 + "                    $plugins_code .= $plugin_info[2] ? \'true),\' : \'false),\';\n"
369                                 + "                }\n"
370                                 + "            }\n"
371                                 + "            $plugins_code .= \")); ?>\";\n"
372                                 + "            $template_header .= $plugins_code;\n"
373                                 + "            $this->_plugin_info = array();\n"
374                                 + "        }\n"
375                                 + "\n"
376                                 + "        if ($this->_init_smarty_vars) {\n"
377                                 + "            $template_header .= \"<?php \\$this->_assign_smarty_interface(); ?>\\n\";\n"
378                                 + "            $this->_init_smarty_vars = false;\n"
379                                 + "        }\n"
380                                 + "\n"
381                                 + "        $template_compiled = $template_header . $template_compiled;\n"
382                                 + "\n"
383                                 + "        return true;\n"
384                                 + "    }\n"
385                                 + "\n"
386                                 + "     /**\n"
387                                 + "      * Compile a template tag\n"
388                                 + "      *\n"
389                                 + "      * @access public\n"
390                                 + "      * @param  $template_tag\n"
391                                 + "      */\n"
392                                 + "    function _compile_tag($template_tag)\n"
393                                 + "    {                \n"
394                                 + "                             \n"
395                                 + "        /* Matched comment. */\n"
396                                 + "        if ($template_tag{0} == \'*\' && $template_tag{strlen($template_tag) - 1} == \'*\')\n"
397                                 + "            return \'\';\n"
398                                 + "             \n"
399                                 + "        /* Split tag into two three parts: command, command modifiers and the arguments. */\n"
400                                 + "        if(! preg_match(\'/^(?:(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp\n"
401                                 + "                             . \'|\' . $this->_reg_obj_regexp . \'|\\/?\' . $this->_func_regexp . \')(\' . $this->_mod_regexp . \'*))\n"
402                                 + "                      (?:\\s+(.*))?$\n"
403                                 + "                    /xs\', $template_tag, $match)) {\n"
404                                 + "                     $this->_syntax_error(\"unrecognized tag: $template_tag\", E_USER_ERROR, __FILE__, __LINE__);\n"
405                                 + "             }\n"
406                                 + "\n"
407                                 + "        $tag_command = $match[1];\n"
408                                 + "        $tag_modifier = isset($match[2]) ? $match[2] : null;\n"
409                                 + "        $tag_args = isset($match[3]) ? $match[3] : null;\n"
410                                 + "             \n"
411                                 + "             \n"
412                                 + "        /* If the tag name is a variable or object, we process it. */\n"
413                                 + "        if (preg_match(\'!^\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \'$!\', $tag_command)) {\n"
414                                 + "            $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args));\n"
415                                 + "                     if(isset($_tag_attrs[\'assign\'])) {\n"
416                                 + "                             return \"<?php \\$this->assign(\'\" . $this->_dequote($_tag_attrs[\'assign\']) . \"\', $return ); ?>\\n\";  \n"
417                                 + "                     } else {\n"
418                                 + "             return \"<?php echo $return; ?>\\n\";\n"
419                                 + "                     }\n"
420                                 + "             }\n"
421                                 + "             \n"
422                                 + "         /* If the tag name is a registered object, we process it. */\n"
423                                 + "        if (preg_match(\'!^\' . $this->_reg_obj_regexp . \'$!\', $tag_command)) {\n"
424                                 + "                     return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);\n"
425                                 + "             }\n"
426                                 + "\n"
427                                 + "        switch ($tag_command) {\n"
428                                 + "            case \'include\':\n"
429                                 + "                return $this->_compile_include_tag($tag_args);\n"
430                                 + "\n"
431                                 + "            case \'include_php\':\n"
432                                 + "                return $this->_compile_include_php_tag($tag_args);\n"
433                                 + "\n"
434                                 + "            case \'if\':\n"
435                                 + "                return $this->_compile_if_tag($tag_args);\n"
436                                 + "\n"
437                                 + "            case \'else\':\n"
438                                 + "                return \'<?php else: ?>\';\n"
439                                 + "\n"
440                                 + "            case \'elseif\':\n"
441                                 + "                return $this->_compile_if_tag($tag_args, true);\n"
442                                 + "\n"
443                                 + "            case \'/if\':\n"
444                                 + "                return \'<?php endif; ?>\';\n"
445                                 + "\n"
446                                 + "            case \'capture\':\n"
447                                 + "                return $this->_compile_capture_tag(true, $tag_args);\n"
448                                 + "\n"
449                                 + "            case \'/capture\':\n"
450                                 + "                return $this->_compile_capture_tag(false);\n"
451                                 + "\n"
452                                 + "            case \'ldelim\':\n"
453                                 + "                return $this->left_delimiter;\n"
454                                 + "\n"
455                                 + "            case \'rdelim\':\n"
456                                 + "                return $this->right_delimiter;\n"
457                                 + "\n"
458                                 + "            case \'section\':\n"
459                                 + "                array_push($this->_sectionelse_stack, false);\n"
460                                 + "                return $this->_compile_section_start($tag_args);\n"
461                                 + "\n"
462                                 + "            case \'sectionelse\':\n"
463                                 + "                $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;\n"
464                                 + "                return \"<?php endfor; else: ?>\";\n"
465                                 + "\n"
466                                 + "            case \'/section\':\n"
467                                 + "                if (array_pop($this->_sectionelse_stack))\n"
468                                 + "                    return \"<?php endif; ?>\";\n"
469                                 + "                else\n"
470                                 + "                    return \"<?php endfor; endif; ?>\";\n"
471                                 + "\n"
472                                 + "            case \'foreach\':\n"
473                                 + "                array_push($this->_foreachelse_stack, false);\n"
474                                 + "                return $this->_compile_foreach_start($tag_args);\n"
475                                 + "                break;\n"
476                                 + "\n"
477                                 + "            case \'foreachelse\':\n"
478                                 + "                $this->_foreachelse_stack[count($this->_foreachelse_stack)-1] = true;\n"
479                                 + "                return \"<?php endforeach; else: ?>\";\n"
480                                 + "\n"
481                                 + "            case \'/foreach\':\n"
482                                 + "                if (array_pop($this->_foreachelse_stack))\n"
483                                 + "                    return \"<?php endif; ?>\";\n"
484                                 + "                else\n"
485                                 + "                    return \"<?php endforeach; endif; ?>\";\n"
486                                 + "\n"
487                                 + "            case \'config_load\':\n"
488                                 + "                return $this->_compile_config_load_tag($tag_args);\n"
489                                 + "\n"
490                                 + "            case \'strip\':\n"
491                                 + "            case \'/strip\':\n"
492                                 + "                return $this->left_delimiter.$tag_command.$this->right_delimiter;\n"
493                                 + "\n"
494                                 + "            case \'literal\':\n"
495                                 + "                list (,$literal_block) = each($this->_literal_blocks);\n"
496                                 + "                $this->_current_line_no += substr_count($literal_block, \"\\n\");\n"
497                                 + "                return \"<?php echo \'\".str_replace(\"\'\", \"\\\'\", str_replace(\"\\\\\", \"\\\\\\\\\", $literal_block)).\"\'; ?>\\n\";\n"
498                                 + "\n"
499                                 + "            case \'php\':\n"
500                                 + "                if ($this->security && !$this->security_settings[\'PHP_TAGS\']) {\n"
501                                 + "                    $this->_syntax_error(\"(secure mode) php tags not permitted\", E_USER_WARNING, __FILE__, __LINE__);\n"
502                                 + "                    return;\n"
503                                 + "                }\n"
504                                 + "                list (,$php_block) = each($this->_php_blocks);\n"
505                                 + "                $this->_current_line_no += substr_count($php_block, \"\\n\");\n"
506                                 + "                return \'<?php \'.$php_block.\' ?>\';\n"
507                                 + "\n"
508                                 + "            case \'insert\':\n"
509                                 + "                return $this->_compile_insert_tag($tag_args);\n"
510                                 + "\n"
511                                 + "            default:\n"
512                                 + "                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {\n"
513                                 + "                    return $output;\n"
514                                 + "                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {\n"
515                                 + "                    return $output;\n"
516                                 + "                } else {\n"
517                                 + "                    return $this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier);\n"
518                                 + "                }\n"
519                                 + "        }\n"
520                                 + "    }\n"
521                                 + "\n"
522                                 + "\n"
523                                 + "     /**\n"
524                                 + "      * compile the custom compiler tag\n"
525                                 + "      *\n"
526                                 + "      * @access public\n"
527                                 + "      * @param  $tag_command\n"
528                                 + "      * @param  $tag_args\n"
529                                 + "      * @param  $output\n"
530                                 + "      */\n"
531                                 + "    function _compile_compiler_tag($tag_command, $tag_args, &$output)\n"
532                                 + "    {\n"
533                                 + "        $found = false;\n"
534                                 + "        $have_function = true;\n"
535                                 + "\n"
536                                 + "        /*\n"
537                                 + "         * First we check if the compiler function has already been registered\n"
538                                 + "         * or loaded from a plugin file.\n"
539                                 + "         */\n"
540                                 + "        if (isset($this->_plugins[\'compiler\'][$tag_command])) {\n"
541                                 + "            $found = true;\n"
542                                 + "            $plugin_func = $this->_plugins[\'compiler\'][$tag_command][0];\n"
543                                 + "            if (!function_exists($plugin_func)) {\n"
544                                 + "                $message = \"compiler function \'$tag_command\' is not implemented\";\n"
545                                 + "                $have_function = false;\n"
546                                 + "            }\n"
547                                 + "        }\n"
548                                 + "        /*\n"
549                                 + "         * Otherwise we need to load plugin file and look for the function\n"
550                                 + "         * inside it.\n"
551                                 + "         */\n"
552                                 + "        else if ($plugin_file = $this->_get_plugin_filepath(\'compiler\', $tag_command)) {\n"
553                                 + "            $found = true;\n"
554                                 + "\n"
555                                 + "            include_once $plugin_file;\n"
556                                 + "\n"
557                                 + "            $plugin_func = \'smarty_compiler_\' . $tag_command;\n"
558                                 + "            if (!function_exists($plugin_func)) {\n"
559                                 + "                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n"
560                                 + "                $have_function = false;\n"
561                                 + "            } else {\n"
562                                 + "                $this->_plugins[\'compiler\'][$tag_command] = array($plugin_func, null, null);\n"
563                                 + "            }\n"
564                                 + "        }\n"
565                                 + "\n"
566                                 + "        /*\n"
567                                 + "         * True return value means that we either found a plugin or a\n"
568                                 + "         * dynamically registered function. False means that we didn\'t and the\n"
569                                 + "         * compiler should now emit code to load custom function plugin for this\n"
570                                 + "         * tag.\n"
571                                 + "         */\n"
572                                 + "        if ($found) {\n"
573                                 + "            if ($have_function) {\n"
574                                 + "                $output = \'<?php \' . $plugin_func($tag_args, $this) . \' ?>\';\n"
575                                 + "            } else {\n"
576                                 + "                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n"
577                                 + "            }\n"
578                                 + "            return true;\n"
579                                 + "        } else {\n"
580                                 + "            return false;\n"
581                                 + "        }\n"
582                                 + "    }\n"
583                                 + "\n"
584                                 + "\n"
585                                 + "     /**\n"
586                                 + "      * compile block function tag\n"
587                                 + "      *\n"
588                                 + "      * @access public\n"
589                                 + "      * @param  $tag_command\n"
590                                 + "      * @param  $tag_args\n"
591                                 + "      * @param  $tag_modifier\n"
592                                 + "      * @param  $output\n"
593                                 + "      */\n"
594                                 + "    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)\n"
595                                 + "    {\n"
596                                 + "        if ($tag_command{0} == \'/\') {\n"
597                                 + "            $start_tag = false;\n"
598                                 + "            $tag_command = substr($tag_command, 1);\n"
599                                 + "        } else\n"
600                                 + "            $start_tag = true;\n"
601                                 + "\n"
602                                 + "        $found = false;\n"
603                                 + "        $have_function = true;\n"
604                                 + "\n"
605                                 + "        /*\n"
606                                 + "         * First we check if the block function has already been registered\n"
607                                 + "         * or loaded from a plugin file.\n"
608                                 + "         */\n"
609                                 + "        if (isset($this->_plugins[\'block\'][$tag_command])) {\n"
610                                 + "            $found = true;\n"
611                                 + "            $plugin_func = $this->_plugins[\'block\'][$tag_command][0];\n"
612                                 + "            if (!function_exists($plugin_func)) {\n"
613                                 + "                $message = \"block function \'$tag_command\' is not implemented\";\n"
614                                 + "                $have_function = false;\n"
615                                 + "            }\n"
616                                 + "        }\n"
617                                 + "        /*\n"
618                                 + "         * Otherwise we need to load plugin file and look for the function\n"
619                                 + "         * inside it.\n"
620                                 + "         */\n"
621                                 + "        else if ($plugin_file = $this->_get_plugin_filepath(\'block\', $tag_command)) {\n"
622                                 + "            $found = true;\n"
623                                 + "\n"
624                                 + "            include_once $plugin_file;\n"
625                                 + "\n"
626                                 + "            $plugin_func = \'smarty_block_\' . $tag_command;\n"
627                                 + "            if (!function_exists($plugin_func)) {\n"
628                                 + "                $message = \"plugin function $plugin_func() not found in $plugin_file\\n\";\n"
629                                 + "                $have_function = false;\n"
630                                 + "            } else {\n"
631                                 + "                $this->_plugins[\'block\'][$tag_command] = array($plugin_func, null, null);\n"
632                                 + "            }\n"
633                                 + "        }\n"
634                                 + "\n"
635                                 + "        if (!$found) {\n"
636                                 + "            return false;\n"
637                                 + "        } else if (!$have_function) {\n"
638                                 + "            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);\n"
639                                 + "            return true;\n"
640                                 + "        }\n"
641                                 + "\n"
642                                 + "        /*\n"
643                                 + "         * Even though we\'ve located the plugin function, compilation\n"
644                                 + "         * happens only once, so the plugin will still need to be loaded\n"
645                                 + "         * at runtime for future requests.\n"
646                                 + "         */\n"
647                                 + "        $this->_add_plugin(\'block\', $tag_command);\n"
648                                 + "\n"
649                                 + "        if ($start_tag) {\n"
650                                 + "            $arg_list = array();\n"
651                                 + "            $attrs = $this->_parse_attrs($tag_args);\n"
652                                 + "            foreach ($attrs as $arg_name => $arg_value) {\n"
653                                 + "                if (is_bool($arg_value))\n"
654                                 + "                    $arg_value = $arg_value ? \'true\' : \'false\';\n"
655                                 + "                $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
656                                 + "            }\n"
657                                 + "\n"
658                                 + "            $output = \"<?php \\$this->_tag_stack[] = array(\'$tag_command\', array(\".implode(\',\', (array)$arg_list).\")); \\$this->_plugins[\'block\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), null, \\$this); ob_start(); ?>\";\n"
659                                 + "        } else {\n"
660                                 + "            $output = \"<?php \\$this->_block_content = ob_get_contents(); ob_end_clean(); \";\n"
661                                 + "                     $out_tag_text = \"\\$this->_plugins[\'block\'][\'$tag_command\'][0](\\$this->_tag_stack[count(\\$this->_tag_stack)-1][1], \\$this->_block_content, \\$this)\";\n"
662                                 + "                     if($tag_modifier != \'\') {\n"
663                                 + "                             $this->_parse_modifiers($out_tag_text, $tag_modifier);\n"
664                                 + "                     }\n"
665                                 + "                     $output .= \'echo \' . $out_tag_text . \';\';\n"
666                                 + "                     $output .= \" array_pop(\\$this->_tag_stack); ?>\";\n"
667                                 + "        }\n"
668                                 + "\n"
669                                 + "        return true;\n"
670                                 + "    }\n"
671                                 + "\n"
672                                 + "\n"
673                                 + "     /**\n"
674                                 + "      * compile custom function tag\n"
675                                 + "      *\n"
676                                 + "      * @access public\n"
677                                 + "      * @param  $tag_command\n"
678                                 + "      * @param  $tag_args\n"
679                                 + "      * @param  $tag_modifier\n"
680                                 + "      */\n"
681                                 + "    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier)\n"
682                                 + "    {\n"
683                                 + "        $this->_add_plugin(\'function\', $tag_command);\n"
684                                 + "\n"
685                                 + "        $arg_list = array();\n"
686                                 + "        $attrs = $this->_parse_attrs($tag_args);\n"
687                                 + "        foreach ($attrs as $arg_name => $arg_value) {\n"
688                                 + "            if (is_bool($arg_value))\n"
689                                 + "                $arg_value = $arg_value ? \'true\' : \'false\';\n"
690                                 + "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
691                                 + "        }\n"
692                                 + "             \n"
693                                 + "             $return = \"\\$this->_plugins[\'function\'][\'$tag_command\'][0](array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n"
694                                 + "             \n"
695                                 + "             if($tag_modifier != \'\') {\n"
696                                 + "                     $this->_parse_modifiers($return, $tag_modifier);\n"
697                                 + "             }\n"
698                                 + "             \n"
699                                 + "        return \'<?php echo \' . $return . \" ; ?>\\n\";\n"
700                                 + "    }\n"
701                                 + "\n"
702                                 + "     /**\n"
703                                 + "      * compile a registered object tag\n"
704                                 + "      *\n"
705                                 + "      * @access public\n"
706                                 + "      * @param  $tag_command\n"
707                                 + "      * @param  $attrs\n"
708                                 + "      * @param  $tag_modifier\n"
709                                 + "      */\n"
710                                 + "    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)\n"
711                                 + "    {\n"
712                                 + "             list($object, $obj_comp) = explode(\'->\', $tag_command);\n"
713                                 + "\n"
714                                 + "        $arg_list = array();\n"
715                                 + "             if(count($attrs)) {\n"
716                                 + "                     $_assign_var = false;\n"
717                                 + "             foreach ($attrs as $arg_name => $arg_value) {\n"
718                                 + "                             if($arg_name == \'assign\') {\n"
719                                 + "                                     $_assign_var = $arg_value;\n"
720                                 + "                                     unset($attrs[\'assign\']);\n"
721                                 + "                                     continue;\n"
722                                 + "                             }\n"
723                                 + "             if (is_bool($arg_value))\n"
724                                 + "                     $arg_value = $arg_value ? \'true\' : \'false\';\n"
725                                 + "             $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
726                                 + "             }\n"
727                                 + "             }\n"
728                                 + "                             \n"
729                                 + "             if(!is_object($this->_reg_objects[$object][0])) {\n"
730                                 + "                     $this->_trigger_fatal_error(\"registered \'$object\' is not an object\");\n"
731                                 + "             } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {\n"
732                                 + "                     $this->_trigger_fatal_error(\"\'$obj_comp\' is not a registered component of object \'$object\'\");\n"
733                                 + "             } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {\n"
734                                 + "                     // method\n"
735                                 + "                     if($this->_reg_objects[$object][2]) {\n"
736                                 + "                             // smarty object argument format\n"
737                                 + "                             $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(array(\".implode(\',\', (array)$arg_list).\"), \\$this)\";\n"
738                                 + "                     } else {\n"
739                                 + "                             // traditional argument format\n"
740                                 + "                             $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp(\".implode(\',\', array_values($attrs)).\")\";\n"
741                                 + "                     }\n"
742                                 + "             } else {\n"
743                                 + "                     // property\n"
744                                 + "                     $return = \"\\$this->_reg_objects[\'$object\'][0]->$obj_comp\";\n"
745                                 + "             }\n"
746                                 + "             \n"
747                                 + "             if($tag_modifier != \'\') {\n"
748                                 + "                     $this->_parse_modifiers($return, $tag_modifier);\n"
749                                 + "             }\n"
750                                 + "             \n"
751                                 + "             if($_assign_var) {\n"
752                                 + "                     return \"<?php \\$this->assign(\'\" . $this->_dequote($_assign_var) .\"\',  $return); ?>\\n\";\n"
753                                 + "             } else {\n"
754                                 + "             return \'<?php echo \' . $return . \"; ?>\\n\";\n"
755                                 + "             }\n"
756                                 + "    }\n"
757                                 + "     \n"
758                                 + "     \n"
759                                 + "\n"
760                                 + "     /**\n"
761                                 + "      * Compile {insert ...} tag\n"
762                                 + "      *\n"
763                                 + "      * @access public\n"
764                                 + "      * @param  $tag_args\n"
765                                 + "      */\n"
766                                 + "    function _compile_insert_tag($tag_args)\n"
767                                 + "    {\n"
768                                 + "        $attrs = $this->_parse_attrs($tag_args);\n"
769                                 + "        $name = $this->_dequote($attrs[\'name\']);\n"
770                                 + "\n"
771                                 + "        if (empty($name)) {\n"
772                                 + "            $this->_syntax_error(\"missing insert name\", E_USER_ERROR, __FILE__, __LINE__);\n"
773                                 + "        }\n"
774                                 + "\n"
775                                 + "        if (!empty($attrs[\'script\'])) {\n"
776                                 + "            $delayed_loading = true;\n"
777                                 + "        } else {\n"
778                                 + "            $delayed_loading = false;                        \n"
779                                 + "             }\n"
780                                 + "\n"
781                                 + "        foreach ($attrs as $arg_name => $arg_value) {\n"
782                                 + "            if (is_bool($arg_value))\n"
783                                 + "                $arg_value = $arg_value ? \'true\' : \'false\';\n"
784                                 + "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\n"
785                                 + "        }\n"
786                                 + "\n"
787                                 + "        $this->_add_plugin(\'insert\', $name, $delayed_loading);\n"
788                                 + "\n"
789                                 + "        return \"<?php echo \\$this->_run_insert_handler(array(\".implode(\', \', (array)$arg_list).\")); ?>\\n\";\n"
790                                 + "    }\n"
791                                 + "\n"
792                                 + "\n"
793                                 + "     /**\n"
794                                 + "      * Compile {config_load ...} tag\n"
795                                 + "      *\n"
796                                 + "      * @access public\n"
797                                 + "      * @param  $tag_args\n"
798                                 + "      */\n"
799                                 + "    function _compile_config_load_tag($tag_args)\n"
800                                 + "    {\n"
801                                 + "        $attrs = $this->_parse_attrs($tag_args);\n"
802                                 + "\n"
803                                 + "        if (empty($attrs[\'file\'])) {\n"
804                                 + "            $this->_syntax_error(\"missing \'file\' attribute in config_load tag\", E_USER_ERROR, __FILE__, __LINE__);\n"
805                                 + "        }\n"
806                                 + "\n"
807                                 + "        if (empty($attrs[\'section\'])) {\n"
808                                 + "            $attrs[\'section\'] = \'null\';\n"
809                                 + "        }\n"
810                                 + "\n"
811                                 + "        if (isset($attrs[\'scope\'])) {\n"
812                                 + "                     $scope = @$this->_dequote($attrs[\'scope\']);\r\n"
813                                 + "            if ($scope != \'local\' &&\r\n"
814                                 + "                $scope != \'parent\' &&\r\n"
815                                 + "                $scope != \'global\') {\r\n"
816                                 + "                $this->_syntax_error(\"invalid \'scope\' attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
817                                 + "            }\r\n"
818                                 + "        } else {\r\n"
819                                 + "            if (isset($attrs[\'global\']) && $attrs[\'global\'])\r\n"
820                                 + "                $scope = \'parent\';\r\n"
821                                 + "            else\r\n"
822                                 + "                $scope = \'local\';\r\n"
823                                 + "        }\r\n"
824                                 + "\r\n"
825                                 + "        return \'<?php $this->config_load(\' . $attrs[\'file\'] . \', \' . $attrs[\'section\'] . \", \'$scope\'); ?>\";\r\n"
826                                 + "    }\r\n"
827                                 + "\r\n"
828                                 + "\r\n"
829                                 + "     /**\r\n"
830                                 + "      * Compile {include ...} tag\r\n"
831                                 + "      *\r\n"
832                                 + "      * @access public\r\n"
833                                 + "      * $param  $tag_args\r\n"
834                                 + "      */\r\n"
835                                 + "    function _compile_include_tag($tag_args)\r\n"
836                                 + "    {\r\n"
837                                 + "        $attrs = $this->_parse_attrs($tag_args);\r\n"
838                                 + "        $arg_list = array();\r\n"
839                                 + "\r\n"
840                                 + "        if (empty($attrs[\'file\'])) {\r\n"
841                                 + "            $this->_syntax_error(\"missing \'file\' attribute in include tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
842                                 + "        }\r\n"
843                                 + "\r\n"
844                                 + "        foreach ($attrs as $arg_name => $arg_value) {\r\n"
845                                 + "            if ($arg_name == \'file\') {\r\n"
846                                 + "                $include_file = $arg_value;\r\n"
847                                 + "                continue;\r\n"
848                                 + "            } else if ($arg_name == \'assign\') {\r\n"
849                                 + "                $assign_var = $arg_value;\r\n"
850                                 + "                continue;\r\n"
851                                 + "            }\r\n"
852                                 + "            if (is_bool($arg_value))\r\n"
853                                 + "                $arg_value = $arg_value ? \'true\' : \'false\';\r\n"
854                                 + "            $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n"
855                                 + "        }\r\n"
856                                 + "\r\n"
857                                 + "        $output = \'<?php \';\r\n"
858                                 + "\r\n"
859                                 + "        if (isset($assign_var)) {\r\n"
860                                 + "                     $output .= \"ob_start();\\n\";\r\n"
861                                 + "        }\r\n"
862                                 + "\r\n"
863                                 + "        $output .=  \r\n"
864                                 + "            \"\\$_smarty_tpl_vars = \\$this->_tpl_vars;\\n\" .\r\n"
865                                 + "            \"\\$this->_smarty_include(\".$include_file.\", array(\".implode(\',\', (array)$arg_list).\"));\\n\" .\r\n"
866                                 + "            \"\\$this->_tpl_vars = \\$_smarty_tpl_vars;\\n\" .\r\n"
867                                 + "            \"unset(\\$_smarty_tpl_vars);\\n\";\r\n"
868                                 + "\r\n"
869                                 + "        if (isset($assign_var)) {\r\n"
870                                 + "                     $output .= \"\\$this->assign(\" . $assign_var . \", ob_get_contents()); ob_end_clean();\\n\";\r\n"
871                                 + "        }\r\n"
872                                 + "\r\n"
873                                 + "        $output .= \' ?>\';\r\n"
874                                 + "\r\n"
875                                 + "             return $output;\r\n"
876                                 + "\r\n"
877                                 + "    }\r\n"
878                                 + "\r\n"
879                                 + "     /**\r\n"
880                                 + "      * Compile {include ...} tag\r\n"
881                                 + "      *\r\n"
882                                 + "      * @access public\r\n"
883                                 + "      * @param $tag_args\r\n"
884                                 + "      */\r\n"
885                                 + "    function _compile_include_php_tag($tag_args)\r\n"
886                                 + "    {\r\n"
887                                 + "        $attrs = $this->_parse_attrs($tag_args);\r\n"
888                                 + "\r\n"
889                                 + "        if (empty($attrs[\'file\'])) {\r\n"
890                                 + "            $this->_syntax_error(\"missing \'file\' attribute in include_php tag\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
891                                 + "        }\r\n"
892                                 + "\r\n"
893                                 + "        $assign_var = $this->_dequote($attrs[\'assign\']);\r\n"
894                                 + "\r\n"
895                                 + "             $once_var = ( $attrs[\'once\'] === false ) ? \'false\' : \'true\';\r\n"
896                                 + "\r\n"
897                                 + "     foreach($attrs as $arg_name => $arg_value) {\r\n"
898                                 + "             if($arg_name != \'file\' AND $arg_name != \'once\' AND $arg_name != \'assign\') {\r\n"
899                                 + "             if(is_bool($arg_value))\r\n"
900                                 + "                     $arg_value = $arg_value ? \'true\' : \'false\';\r\n"
901                                 + "             $arg_list[] = \"\'$arg_name\' => $arg_value\";\r\n"
902                                 + "             }\r\n"
903                                 + "     }\r\n"
904                                 + "\r\n"
905                                 + "     $output =\r\n"
906                                 + "             \"<?php \\$this->_smarty_include_php($attrs[file], \'$assign_var\', $once_var, \" .\r\n"
907                                 + "             \"array(\".implode(\',\', (array)$arg_list).\")); ?>\";\r\n"
908                                 + "                             \r\n"
909                                 + "             return $output;\r\n"
910                                 + "    }\r\n"
911                                 + "     \r\n"
912                                 + "\r\n"
913                                 + "     /**\r\n"
914                                 + "      * Compile {section ...} tag\r\n"
915                                 + "      *\r\n"
916                                 + "      * @access public\r\n"
917                                 + "      * @param  $tag_args\r\n"
918                                 + "      */\r\n"
919                                 + "    function _compile_section_start($tag_args)\r\n"
920                                 + "    {\r\n"
921                                 + "        $attrs = $this->_parse_attrs($tag_args);\r\n"
922                                 + "        $arg_list = array();\r\n"
923                                 + "\r\n"
924                                 + "        $output = \'<?php \';\r\n"
925                                 + "        $section_name = $attrs[\'name\']; \r\n"
926                                 + "        if (empty($section_name)) {\r\n"
927                                 + "            $this->_syntax_error(\"missing section name\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
928                                 + "        }\r\n"
929                                 + "\r\n"
930                                 + "        $output .= \"if (isset(\\$this->_sections[$section_name])) unset(\\$this->_sections[$section_name]);\\n\";\r\n"
931                                 + "        $section_props = \"\\$this->_sections[$section_name]\";\r\n"
932                                 + "\r\n"
933                                 + "        foreach ($attrs as $attr_name => $attr_value) {\r\n"
934                                 + "            switch ($attr_name) {\r\n"
935                                 + "                case \'loop\':\r\n"
936                                 + "                    $output .= \"{$section_props}[\'loop\'] = is_array($attr_value) ? count($attr_value) : max(0, (int)$attr_value);\\n\";\r\n"
937                                 + "                    break;\r\n"
938                                 + "\r\n"
939                                 + "                case \'show\':\r\n"
940                                 + "                    if (is_bool($attr_value))\r\n"
941                                 + "                        $show_attr_value = $attr_value ? \'true\' : \'false\';\r\n"
942                                 + "                    else\r\n"
943                                 + "                        $show_attr_value = \"(bool)$attr_value\";\r\n"
944                                 + "                    $output .= \"{$section_props}[\'show\'] = $show_attr_value;\\n\";\r\n"
945                                 + "                    break;\r\n"
946                                 + "\r\n"
947                                 + "                case \'name\':\r\n"
948                                 + "                    $output .= \"{$section_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n"
949                                 + "                    break;\r\n"
950                                 + "\r\n"
951                                 + "                case \'max\':\r\n"
952                                 + "                case \'start\':\r\n"
953                                 + "                    $output .= \"{$section_props}[\'$attr_name\'] = (int)$attr_value;\\n\";\r\n"
954                                 + "                    break;\r\n"
955                                 + "\r\n"
956                                 + "                case \'step\':\r\n"
957                                 + "                    $output .= \"{$section_props}[\'$attr_name\'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\\n\";\r\n"
958                                 + "                    break;\r\n"
959                                 + "\r\n"
960                                 + "                default:\r\n"
961                                 + "                    $this->_syntax_error(\"unknown section attribute - \'$attr_name\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
962                                 + "                    break;\r\n"
963                                 + "            }\r\n"
964                                 + "        }\r\n"
965                                 + "\r\n"
966                                 + "        if (!isset($attrs[\'show\']))\r\n"
967                                 + "            $output .= \"{$section_props}[\'show\'] = true;\\n\";\r\n"
968                                 + "\r\n"
969                                 + "        if (!isset($attrs[\'loop\']))\r\n"
970                                 + "            $output .= \"{$section_props}[\'loop\'] = 1;\\n\";\r\n"
971                                 + "\r\n"
972                                 + "        if (!isset($attrs[\'max\']))\r\n"
973                                 + "            $output .= \"{$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n"
974                                 + "        else\r\n"
975                                 + "            $output .= \"if ({$section_props}[\'max\'] < 0)\\n\" .\r\n"
976                                 + "                       \"    {$section_props}[\'max\'] = {$section_props}[\'loop\'];\\n\";\r\n"
977                                 + "\r\n"
978                                 + "        if (!isset($attrs[\'step\']))\r\n"
979                                 + "            $output .= \"{$section_props}[\'step\'] = 1;\\n\";\r\n"
980                                 + "\r\n"
981                                 + "        if (!isset($attrs[\'start\']))\r\n"
982                                 + "            $output .= \"{$section_props}[\'start\'] = {$section_props}[\'step\'] > 0 ? 0 : {$section_props}[\'loop\']-1;\\n\";\r\n"
983                                 + "        else {\r\n"
984                                 + "            $output .= \"if ({$section_props}[\'start\'] < 0)\\n\" .\r\n"
985                                 + "                       \"    {$section_props}[\'start\'] = max({$section_props}[\'step\'] > 0 ? 0 : -1, {$section_props}[\'loop\'] + {$section_props}[\'start\']);\\n\" .\r\n"
986                                 + "                       \"else\\n\" .\r\n"
987                                 + "                       \"    {$section_props}[\'start\'] = min({$section_props}[\'start\'], {$section_props}[\'step\'] > 0 ? {$section_props}[\'loop\'] : {$section_props}[\'loop\']-1);\\n\";\r\n"
988                                 + "        }\r\n"
989                                 + "\r\n"
990                                 + "        $output .= \"if ({$section_props}[\'show\']) {\\n\";\r\n"
991                                 + "        if (!isset($attrs[\'start\']) && !isset($attrs[\'step\']) && !isset($attrs[\'max\'])) {\r\n"
992                                 + "            $output .= \"    {$section_props}[\'total\'] = {$section_props}[\'loop\'];\\n\";\r\n"
993                                 + "        } else {\r\n"
994                                 + "            $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\";\r\n"
995                                 + "        }\r\n"
996                                 + "        $output .= \"    if ({$section_props}[\'total\'] == 0)\\n\" .\r\n"
997                                 + "                   \"        {$section_props}[\'show\'] = false;\\n\" .\r\n"
998                                 + "                   \"} else\\n\" .\r\n"
999                                 + "                   \"    {$section_props}[\'total\'] = 0;\\n\";\r\n"
1000                                 + "\r\n"
1001                                 + "        $output .= \"if ({$section_props}[\'show\']):\\n\";\r\n"
1002                                 + "        $output .= \"\r\n"
1003                                 + "            for ({$section_props}[\'index\'] = {$section_props}[\'start\'], {$section_props}[\'iteration\'] = 1;\r\n"
1004                                 + "                 {$section_props}[\'iteration\'] <= {$section_props}[\'total\'];\r\n"
1005                                 + "                 {$section_props}[\'index\'] += {$section_props}[\'step\'], {$section_props}[\'iteration\']++):\\n\";\r\n"
1006                                 + "        $output .= \"{$section_props}[\'rownum\'] = {$section_props}[\'iteration\'];\\n\";\r\n"
1007                                 + "        $output .= \"{$section_props}[\'index_prev\'] = {$section_props}[\'index\'] - {$section_props}[\'step\'];\\n\";\r\n"
1008                                 + "        $output .= \"{$section_props}[\'index_next\'] = {$section_props}[\'index\'] + {$section_props}[\'step\'];\\n\";\r\n"
1009                                 + "        $output .= \"{$section_props}[\'first\']      = ({$section_props}[\'iteration\'] == 1);\\n\";\r\n"
1010                                 + "        $output .= \"{$section_props}[\'last\']       = ({$section_props}[\'iteration\'] == {$section_props}[\'total\']);\\n\";\r\n"
1011                                 + "\r\n"
1012                                 + "        $output .= \"?>\";\r\n"
1013                                 + "\r\n"
1014                                 + "        return $output;\r\n"
1015                                 + "    }\r\n"
1016                                 + "\r\n"
1017                                 + "    \r\n"
1018                                 + "     /**\r\n"
1019                                 + "      * Compile {foreach ...} tag.\r\n"
1020                                 + "      *\r\n"
1021                                 + "      * @access public\r\n"
1022                                 + "      * @param  $tag_args\r\n"
1023                                 + "      */\r\n"
1024                                 + "    function _compile_foreach_start($tag_args)\r\n"
1025                                 + "    {\r\n"
1026                                 + "        $attrs = $this->_parse_attrs($tag_args);\r\n"
1027                                 + "        $arg_list = array();\r\n"
1028                                 + "\r\n"
1029                                 + "        if (empty($attrs[\'from\'])) {\r\n"
1030                                 + "            $this->_syntax_error(\"missing \'from\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1031                                 + "        }\r\n"
1032                                 + "\r\n"
1033                                 + "        if (empty($attrs[\'item\'])) {\r\n"
1034                                 + "            $this->_syntax_error(\"missing \'item\' attribute\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1035                                 + "        }\r\n"
1036                                 + "\r\n"
1037                                 + "        $from = $attrs[\'from\'];\r\n"
1038                                 + "        $item = $this->_dequote($attrs[\'item\']);\r\n"
1039                                 + "        if (isset($attrs[\'name\']))\r\n"
1040                                 + "            $name = $attrs[\'name\'];\r\n"
1041                                 + "\r\n"
1042                                 + "        $output = \'<?php \';\r\n"
1043                                 + "        if (isset($name)) {\r\n"
1044                                 + "            $output .= \"if (isset(\\$this->_foreach[$name])) unset(\\$this->_foreach[$name]);\\n\";\r\n"
1045                                 + "            $foreach_props = \"\\$this->_foreach[$name]\";\r\n"
1046                                 + "        }\r\n"
1047                                 + "\r\n"
1048                                 + "        $key_part = \'\';\r\n"
1049                                 + "\r\n"
1050                                 + "        foreach ($attrs as $attr_name => $attr_value) {\r\n"
1051                                 + "            switch ($attr_name) {\r\n"
1052                                 + "                case \'key\':\r\n"
1053                                 + "                    $key  = $this->_dequote($attrs[\'key\']);\r\n"
1054                                 + "                    $key_part = \"\\$this->_tpl_vars[\'$key\'] => \";\r\n"
1055                                 + "                    break;\r\n"
1056                                 + "\r\n"
1057                                 + "                case \'name\':\r\n"
1058                                 + "                    $output .= \"{$foreach_props}[\'$attr_name\'] = $attr_value;\\n\";\r\n"
1059                                 + "                    break;\r\n"
1060                                 + "            }\r\n"
1061                                 + "        }\r\n"
1062                                 + "\r\n"
1063                                 + "        if (isset($name)) {\r\n"
1064                                 + "            $output .= \"{$foreach_props}[\'total\'] = count((array)$from);\\n\";\r\n"
1065                                 + "            $output .= \"{$foreach_props}[\'show\'] = {$foreach_props}[\'total\'] > 0;\\n\";\r\n"
1066                                 + "            $output .= \"if ({$foreach_props}[\'show\']):\\n\";\r\n"
1067                                 + "            $output .= \"{$foreach_props}[\'iteration\'] = 0;\\n\";\r\n"
1068                                 + "            $output .= \"    foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n"
1069                                 + "            $output .= \"        {$foreach_props}[\'iteration\']++;\\n\";\r\n"
1070                                 + "            $output .= \"        {$foreach_props}[\'first\'] = ({$foreach_props}[\'iteration\'] == 1);\\n\";\r\n"
1071                                 + "            $output .= \"        {$foreach_props}[\'last\']  = ({$foreach_props}[\'iteration\'] == {$foreach_props}[\'total\']);\\n\";\r\n"
1072                                 + "        } else {\r\n"
1073                                 + "            $output .= \"if (count((array)$from)):\\n\";\r\n"
1074                                 + "            $output .= \"    foreach ((array)$from as $key_part\\$this->_tpl_vars[\'$item\']):\\n\";\r\n"
1075                                 + "        }\r\n"
1076                                 + "        $output .= \'?>\';\r\n"
1077                                 + "\r\n"
1078                                 + "        return $output;\r\n"
1079                                 + "    }\r\n"
1080                                 + "\r\n"
1081                                 + "\r\n"
1082                                 + "     /**\r\n"
1083                                 + "      * Compile {capture} .. {/capture} tags\r\n"
1084                                 + "      *\r\n"
1085                                 + "      * @access public\r\n"
1086                                 + "      * @param  $start\r\n"
1087                                 + "      * @param  $tag_args\r\n"
1088                                 + "      */\r\n"
1089                                 + "    function _compile_capture_tag($start, $tag_args = \'\')\r\n"
1090                                 + "    {\r\n"
1091                                 + "        $attrs = $this->_parse_attrs($tag_args);\r\n"
1092                                 + "\r\n"
1093                                 + "        if ($start) {\r\n"
1094                                 + "            if (isset($attrs[\'name\']))\r\n"
1095                                 + "                $buffer = $attrs[\'name\'];\r\n"
1096                                 + "            else\r\n"
1097                                 + "                $buffer = \"\'default\'\";\r\n"
1098                                 + "\r\n"
1099                                 + "            $output = \"<?php ob_start(); ?>\";\r\n"
1100                                 + "            $this->_capture_stack[] = $buffer;\r\n"
1101                                 + "        } else {\r\n"
1102                                 + "            $buffer = array_pop($this->_capture_stack);\r\n"
1103                                 + "            $output = \"<?php \\$this->_smarty_vars[\'capture\'][$buffer] = ob_get_contents(); ob_end_clean(); ?>\";\r\n"
1104                                 + "        }\r\n"
1105                                 + "\r\n"
1106                                 + "        return $output;\r\n"
1107                                 + "    }\r\n"
1108                                 + "\r\n"
1109                                 + "     /**\r\n"
1110                                 + "      * Compile {if ...} tag\r\n"
1111                                 + "      *\r\n"
1112                                 + "      * @access public\r\n"
1113                                 + "      * @param  $tag_args\r\n"
1114                                 + "      * @param  $elseif\r\n"
1115                                 + "      */\r\n"
1116                                 + "    function _compile_if_tag($tag_args, $elseif = false)\r\n"
1117                                 + "    {\r\n"
1118                                 + "\r\n"
1119                                 + "        /* Tokenize args for \'if\' tag. */\r\n"
1120                                 + "        preg_match_all(\'/(?>\r\n"
1121                                 + "                             \' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*) | # valid object call\r\n"
1122                                 + "                             \' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)   | # public or quoted string\r\n"
1123                                 + "                             \\-?\\d+|!==|<=>|==|!=|<=|>=|\\&\\&|\\|\\||\\(|\\)|,|\\!|\\^|=|<|>|\\||\\%|\\+|\\-|\\/|\\*      | # valid non-word token\r\n"
1124                                 + "                             \\b\\w+\\b                                                                                                              | # valid word token\r\n"
1125                                 + "                             \\S+                                                           # anything else\r\n"
1126                                 + "                             )/x\', $tag_args, $match);\r\n"
1127                                 + "                             \r\n"
1128                                 + "        $tokens = $match[0];\r\n"
1129                                 + "             \r\n"
1130                                 + "             // make sure we have balanced parenthesis\r\n"
1131                                 + "             $token_count = array_count_values($tokens);\r\n"
1132                                 + "             if(isset($token_count[\'(\']) && $token_count[\'(\'] != $token_count[\')\']) {\r\n"
1133                                 + "                     $this->_syntax_error(\"unbalanced parenthesis in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1134                                 + "             }\r\n"
1135                                 + "                                                                                             \r\n"
1136                                 + "        $is_arg_stack = array();\r\n"
1137                                 + "\r\n"
1138                                 + "        for ($i = 0; $i < count($tokens); $i++) {\r\n"
1139                                 + "\r\n"
1140                                 + "            $token = &$tokens[$i];\r\n"
1141                                 + "                     \r\n"
1142                                 + "            switch (strtolower($token)) {\r\n"
1143                                 + "                case \'!\':\r\n"
1144                                 + "                case \'%\':\r\n"
1145                                 + "                case \'!==\':\r\n"
1146                                 + "                case \'==\':\r\n"
1147                                 + "                case \'>\':\r\n"
1148                                 + "                case \'<\':\r\n"
1149                                 + "                case \'!=\':\r\n"
1150                                 + "                case \'<=\':\r\n"
1151                                 + "                case \'>=\':\r\n"
1152                                 + "                case \'&&\':\r\n"
1153                                 + "                case \'||\':\r\n"
1154                                 + "                             case \'|\':\r\n"
1155                                 + "                             case \'^\':\r\n"
1156                                 + "                             case \'&\':\r\n"
1157                                 + "                             case \'~\':\r\n"
1158                                 + "                             case \')\':\r\n"
1159                                 + "                             case \',\':\r\n"
1160                                 + "                             case \'+\':\r\n"
1161                                 + "                             case \'-\':\r\n"
1162                                 + "                             case \'*\':\r\n"
1163                                 + "                             case \'/\':\r\n"
1164                                 + "                                     break;                                  \r\n"
1165                                 + "\r\n"
1166                                 + "                case \'eq\':\r\n"
1167                                 + "                    $token = \'==\';\r\n"
1168                                 + "                    break;\r\n"
1169                                 + "\r\n"
1170                                 + "                case \'ne\':\r\n"
1171                                 + "                case \'neq\':\r\n"
1172                                 + "                    $token = \'!=\';\r\n"
1173                                 + "                    break;\r\n"
1174                                 + "\r\n"
1175                                 + "                case \'lt\':\r\n"
1176                                 + "                    $token = \'<\';\r\n"
1177                                 + "                    break;\r\n"
1178                                 + "\r\n"
1179                                 + "                case \'le\':\r\n"
1180                                 + "                case \'lte\':\r\n"
1181                                 + "                    $token = \'<=\';\r\n"
1182                                 + "                    break;\r\n"
1183                                 + "\r\n"
1184                                 + "                case \'gt\':\r\n"
1185                                 + "                    $token = \'>\';\r\n"
1186                                 + "                    break;\r\n"
1187                                 + "\r\n"
1188                                 + "                case \'ge\':\r\n"
1189                                 + "                case \'gte\':\r\n"
1190                                 + "                    $token = \'>=\';\r\n"
1191                                 + "                    break;\r\n"
1192                                 + "\r\n"
1193                                 + "                case \'and\':\r\n"
1194                                 + "                    $token = \'&&\';\r\n"
1195                                 + "                    break;\r\n"
1196                                 + "\r\n"
1197                                 + "                case \'or\':\r\n"
1198                                 + "                    $token = \'||\';\r\n"
1199                                 + "                    break;\r\n"
1200                                 + "\r\n"
1201                                 + "                case \'not\':\r\n"
1202                                 + "                    $token = \'!\';\r\n"
1203                                 + "                    break;\r\n"
1204                                 + "\r\n"
1205                                 + "                case \'mod\':\r\n"
1206                                 + "                    $token = \'%\';\r\n"
1207                                 + "                    break;\r\n"
1208                                 + "\r\n"
1209                                 + "                case \'(\':\r\n"
1210                                 + "                    array_push($is_arg_stack, $i);\r\n"
1211                                 + "                    break;\r\n"
1212                                 + "                                     \r\n"
1213                                 + "                case \'is\':\r\n"
1214                                 + "                    /* If last token was a \')\', we operate on the parenthesized\r\n"
1215                                 + "                       expression. The start of the expression is on the stack.\r\n"
1216                                 + "                       Otherwise, we operate on the last encountered token. */\r\n"
1217                                 + "                    if ($tokens[$i-1] == \')\')\r\n"
1218                                 + "                        $is_arg_start = array_pop($is_arg_stack);\r\n"
1219                                 + "                    else\r\n"
1220                                 + "                        $is_arg_start = $i-1;\r\n"
1221                                 + "                    /* Construct the argument for \'is\' expression, so it knows\r\n"
1222                                 + "                       what to operate on. */\r\n"
1223                                 + "                    $is_arg = implode(\' \', array_slice($tokens, $is_arg_start, $i - $is_arg_start));\r\n"
1224                                 + "                                     \r\n"
1225                                 + "                    /* Pass all tokens from next one until the end to the\r\n"
1226                                 + "                       \'is\' expression parsing function. The function will\r\n"
1227                                 + "                       return modified tokens, where the first one is the result\r\n"
1228                                 + "                       of the \'is\' expression and the rest are the tokens it\r\n"
1229                                 + "                       didn\'t touch. */                                     \r\n"
1230                                 + "                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));\r\n"
1231                                 + "                                                                             \r\n"
1232                                 + "                    /* Replace the old tokens with the new ones. */\r\n"
1233                                 + "                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);\r\n"
1234                                 + "\r\n"
1235                                 + "                    /* Adjust argument start so that it won\'t change from the\r\n"
1236                                 + "                       current position for the next iteration. */\r\n"
1237                                 + "                    $i = $is_arg_start;\r\n"
1238                                 + "                    break;\r\n"
1239                                 + "                                     \r\n"
1240                                 + "                default:\r\n"
1241                                 + "                                     if(preg_match(\'!^\' . $this->_func_regexp . \'$!\', $token) ) {\r\n"
1242                                 + "                                                     // function call        \r\n"
1243                                 + "                             if($this->security &&\r\n"
1244                                 + "                                !in_array($token, $this->security_settings[\'IF_FUNCS\'])) {\r\n"
1245                                 + "                                     $this->_syntax_error(\"(secure mode) \'$token\' not allowed in if statement\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1246                                 + "                                                     }                                                       \r\n"
1247                                 + "                                     } elseif(preg_match(\'!^\' . $this->_var_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n"
1248                                 + "                                             // variable\r\n"
1249                                 + "                                     $token = $this->_parse_var_props($token);\r\n"
1250                                 + "                                     } elseif(preg_match(\'!^\' . $this->_obj_call_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $token)) {\r\n"
1251                                 + "                                             // object\r\n"
1252                                 + "                                     $token = $this->_parse_var_props($token);\r\n"
1253                                 + "                                     } elseif(is_numeric($token)) {\r\n"
1254                                 + "                                             // number, skip it\r\n"
1255                                 + "                                     } else {\r\n"
1256                                 + "                             $this->_syntax_error(\"unidentified token \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1257                                 + "                                     }\r\n"
1258                                 + "                    break;\r\n"
1259                                 + "            }\r\n"
1260                                 + "        }\r\n"
1261                                 + "                             \r\n"
1262                                 + "        if ($elseif)\r\n"
1263                                 + "            return \'<?php elseif (\'.implode(\' \', $tokens).\'): ?>\';\r\n"
1264                                 + "        else\r\n"
1265                                 + "            return \'<?php if (\'.implode(\' \', $tokens).\'): ?>\';\r\n"
1266                                 + "    }\r\n"
1267                                 + "\r\n"
1268                                 + "\r\n"
1269                                 + "     /**\r\n"
1270                                 + "      * Parse is expression\r\n"
1271                                 + "      *\r\n"
1272                                 + "      * @access public\r\n"
1273                                 + "      * @param  $is_arg\r\n"
1274                                 + "      * @param  $tokens\r\n"
1275                                 + "      */\r\n"
1276                                 + "    function _parse_is_expr($is_arg, $tokens)\r\n"
1277                                 + "    {\r\n"
1278                                 + "        $expr_end = 0;\r\n"
1279                                 + "        $negate_expr = false;\r\n"
1280                                 + "\r\n"
1281                                 + "        if (($first_token = array_shift($tokens)) == \'not\') {\r\n"
1282                                 + "            $negate_expr = true;\r\n"
1283                                 + "            $expr_type = array_shift($tokens);\r\n"
1284                                 + "        } else\r\n"
1285                                 + "            $expr_type = $first_token;\r\n"
1286                                 + "\r\n"
1287                                 + "        switch ($expr_type) {\r\n"
1288                                 + "            case \'even\':\r\n"
1289                                 + "                if (@$tokens[$expr_end] == \'by\') {\r\n"
1290                                 + "                    $expr_end++;\r\n"
1291                                 + "                    $expr_arg = $tokens[$expr_end++];\r\n"
1292                                 + "                    $expr = \"!(($is_arg / $expr_arg) % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n"
1293                                 + "                } else\r\n"
1294                                 + "                    $expr = \"!($is_arg % 2)\";\r\n"
1295                                 + "                break;\r\n"
1296                                 + "\r\n"
1297                                 + "            case \'odd\':\r\n"
1298                                 + "                if (@$tokens[$expr_end] == \'by\') {\r\n"
1299                                 + "                    $expr_end++;\r\n"
1300                                 + "                    $expr_arg = $tokens[$expr_end++];\r\n"
1301                                 + "                    $expr = \"(($is_arg / $expr_arg) % \". $this->_parse_var_props($expr_arg) . \")\";\r\n"
1302                                 + "                } else\r\n"
1303                                 + "                    $expr = \"($is_arg % 2)\";\r\n"
1304                                 + "                break;\r\n"
1305                                 + "\r\n"
1306                                 + "            case \'div\':\r\n"
1307                                 + "                if (@$tokens[$expr_end] == \'by\') {\r\n"
1308                                 + "                    $expr_end++;\r\n"
1309                                 + "                    $expr_arg = $tokens[$expr_end++];\r\n"
1310                                 + "                    $expr = \"!($is_arg % \" . $this->_parse_var_props($expr_arg) . \")\";\r\n"
1311                                 + "                } else {\r\n"
1312                                 + "                    $this->_syntax_error(\"expecting \'by\' after \'div\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1313                                 + "                }\r\n"
1314                                 + "                break;\r\n"
1315                                 + "\r\n"
1316                                 + "            default:\r\n"
1317                                 + "                $this->_syntax_error(\"unknown \'is\' expression - \'$expr_type\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1318                                 + "                break;\r\n"
1319                                 + "        }\r\n"
1320                                 + "\r\n"
1321                                 + "        if ($negate_expr) {\r\n"
1322                                 + "            $expr = \"!($expr)\";\r\n"
1323                                 + "        }\r\n"
1324                                 + "             \r\n"
1325                                 + "        array_splice($tokens, 0, $expr_end, $expr);          \r\n"
1326                                 + "             \r\n"
1327                                 + "        return $tokens;\r\n"
1328                                 + "    }\r\n"
1329                                 + "\r\n"
1330                                 + "\r\n"
1331                                 + "     /**\r\n"
1332                                 + "      * Parse attribute string\r\n"
1333                                 + "      *\r\n"
1334                                 + "      * @access public\r\n"
1335                                 + "      * @param  $tag_args\r\n"
1336                                 + "      * @param  $quote\r\n"
1337                                 + "      */\r\n"
1338                                 + "    function _parse_attrs($tag_args, $quote = true)\r\n"
1339                                 + "    {\r\n"
1340                                 + "                             \r\n"
1341                                 + "        /* Tokenize tag attributes. */\r\n"
1342                                 + "        preg_match_all(\'/(?:\' . $this->_obj_call_regexp . \'|\' . $this->_qstr_regexp . \' | (?>[^\"\\\'=\\s]+)\r\n"
1343                                 + "                         )+ |\r\n"
1344                                 + "                         [=]\r\n"
1345                                 + "                        /x\', $tag_args, $match);\r\n"
1346                                 + "        $tokens       = $match[0];           \r\n"
1347                                 + "                             \r\n"
1348                                 + "        $attrs = array();\r\n"
1349                                 + "        /* Parse state:\r\n"
1350                                 + "            0 - expecting attribute name\r\n"
1351                                 + "            1 - expecting \'=\'\r\n"
1352                                 + "            2 - expecting attribute value (not \'=\') */\r\n"
1353                                 + "        $state = 0;\r\n"
1354                                 + "                             \r\n"
1355                                 + "        foreach ($tokens as $token) {\r\n"
1356                                 + "            switch ($state) {\r\n"
1357                                 + "                case 0:\r\n"
1358                                 + "                    /* If the token is a valid identifier, we set attribute name\r\n"
1359                                 + "                       and go to state 1. */\r\n"
1360                                 + "                    if (preg_match(\'!^\\w+$!\', $token)) {\r\n"
1361                                 + "                        $attr_name = $token;\r\n"
1362                                 + "                        $state = 1;\r\n"
1363                                 + "                    } else\r\n"
1364                                 + "                        $this->_syntax_error(\"invalid attribute name - \'$token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1365                                 + "                    break;\r\n"
1366                                 + "\r\n"
1367                                 + "                case 1:\r\n"
1368                                 + "                    /* If the token is \'=\', then we go to state 2. */\r\n"
1369                                 + "                    if ($token == \'=\') {\r\n"
1370                                 + "                        $state = 2;\r\n"
1371                                 + "                    } else\r\n"
1372                                 + "                        $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1373                                 + "                    break;\r\n"
1374                                 + "\r\n"
1375                                 + "                case 2:\r\n"
1376                                 + "                    /* If token is not \'=\', we set the attribute value and go to\r\n"
1377                                 + "                       state 0. */\r\n"
1378                                 + "                    if ($token != \'=\') {\r\n"
1379                                 + "                        /* We booleanize the token if it\'s a non-quoted possible\r\n"
1380                                 + "                           boolean value. */\r\n"
1381                                 + "                        if (preg_match(\'!^(on|yes|true)$!\', $token))\r\n"
1382                                 + "                            $token = true;\r\n"
1383                                 + "                        else if (preg_match(\'!^(off|no|false)$!\', $token))\r\n"
1384                                 + "                            $token = false;\r\n"
1385                                 + "                        /* If the token is just a string,\r\n"
1386                                 + "                           we double-quote it. */\r\n"
1387                                 + "                        else if (preg_match(\'!^\\w+$!\', $token)) {\r\n"
1388                                 + "                            $token = \'\"\'.$token.\'\"\';\r\n"
1389                                 + "                                             }\r\n"
1390                                 + "\r\n"
1391                                 + "                        $attrs[$attr_name] = $token;\r\n"
1392                                 + "                        $state = 0;\r\n"
1393                                 + "                    } else\r\n"
1394                                 + "                        $this->_syntax_error(\"\'=\' cannot be an attribute value\", E_USER_ERROR, __FILE__, __LINE__);\r\n"
1395                                 + "                    break;\r\n"
1396                                 + "            }\r\n"
1397                                 + "                     $last_token = $token;\r\n"
1398                                 + "        }\r\n"
1399                                 + "\r\n"
1400                                 + "             if($state != 0) {\r\n"
1401                                 + "                     if($state == 1) {\r\n"
1402                                 + "                             $this->_syntax_error(\"expecting \'=\' after attribute name \'$last_token\'\", E_USER_ERROR, __FILE__, __LINE__);                               \r\n"
1403                                 + "                     } else {\r\n"
1404                                 + "                             $this->_syntax_error(\"missing attribute value\", E_USER_ERROR, __FILE__, __LINE__);                                                            \r\n"
1405                                 + "                     }\r\n"
1406                                 + "             }\r\n"
1407                                 + "             \r\n"
1408                                 + "        $this->_parse_vars_props($attrs);\r\n"
1409                                 + "\r\n"
1410                                 + "        return $attrs;\r\n"
1411                                 + "    }\r\n"
1412                                 + "\r\n"
1413                                 + "     /**\r\n"
1414                                 + "      * compile multiple variables and section properties tokens into\r\n"
1415                                 + "      * PHP code\r\n"
1416                                 + "      *\r\n"
1417                                 + "      * @access public\r\n"
1418                                 + "      * @param  $tokens\r\n"
1419                                 + "      */\r\n"
1420                                 + "    function _parse_vars_props(&$tokens)\r\n"
1421                                 + "    {\r\n"
1422                                 + "             foreach($tokens as $key => $val) {                      \r\n"
1423                                 + "             $tokens[$key] = $this->_parse_var_props($val);\r\n"
1424                                 + "             }\r\n"
1425                                 + "     }\r\n"
1426                                 + "             \r\n"
1427                                 + "     /**\r\n"
1428                                 + "      * compile single variable and section properties token into\r\n"
1429                                 + "      * PHP code\r\n"
1430                                 + "      *\r\n"
1431                                 + "      * @access public\r\n"
1432                                 + "      * @param  $val\r\n"
1433                                 + "      * @param  $tag_attrs\r\n"
1434                                 + "      */\r\n"
1435                                 + "    function _parse_var_props($val, $tag_attrs = null)\r\n"
1436                                 + "    {                                        \r\n"
1437                                 + "\r\n"
1438                                 + "             $val = trim($val);\r\n"
1439                                 + "\r\n"
1440                                 + "        if(preg_match(\'!^(\' . $this->_obj_call_regexp . \'|\' . $this->_dvar_regexp . \')(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1441                                 + "                             // $ variable or object\r\n"
1442                                 + "                return $this->_parse_var($val, $tag_attrs);\r\n"
1443                                 + "                     }                       \r\n"
1444                                 + "        elseif(preg_match(\'!^\' . $this->_db_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1445                                 + "                             // double quoted text\r\n"
1446                                 + "                             preg_match(\'!^(\' . $this->_db_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n"
1447                                 + "                $return = $this->_expand_quoted_text($match[1]);\r\n"
1448                                 + "                             if($match[2] != \'\') {\r\n"
1449                                 + "                                     $this->_parse_modifiers($return, $match[2]);\r\n"
1450                                 + "                             }\r\n"
1451                                 + "                             return $return;\r\n"
1452                                 + "                     }                       \r\n"
1453                                 + "        elseif(preg_match(\'!^\' . $this->_si_qstr_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1454                                 + "                             // single quoted text\r\n"
1455                                 + "                             preg_match(\'!^(\' . $this->_si_qstr_regexp . \')(\'. $this->_mod_regexp . \'*)$!\', $val, $match);\r\n"
1456                                 + "                             if($match[2] != \'\') {\r\n"
1457                                 + "                                     $this->_parse_modifiers($match[1], $match[2]);\r\n"
1458                                 + "                     return $match[1];\r\n"
1459                                 + "                             }       \r\n"
1460                                 + "                     }                       \r\n"
1461                                 + "        elseif(preg_match(\'!^\' . $this->_cvar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1462                                 + "                             // config var\r\n"
1463                                 + "                return $this->_parse_conf_var($val);\r\n"
1464                                 + "                     }                       \r\n"
1465                                 + "        elseif(preg_match(\'!^\' . $this->_svar_regexp . \'(?:\' . $this->_mod_regexp . \'*)$!\', $val)) {\r\n"
1466                                 + "                             // section var\r\n"
1467                                 + "                return $this->_parse_section_prop($val);\r\n"
1468                                 + "                     }\r\n"
1469                                 + "             elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {\r\n"
1470                                 + "                     // literal string\r\n"
1471                                 + "                     return $this->_expand_quoted_text(\'\"\' . $val .\'\"\');\r\n"
1472                                 + "             }\r\n"
1473                                 + "             return $val;\r\n"
1474                                 + "    }\r\n"
1475                                 + "\r\n"
1476                                 + "     /**\r\n"
1477                                 + "      * expand quoted text with embedded variables\r\n"
1478                                 + "      *\r\n"
1479                                 + "      * @access public\r\n"
1480                                 + "      * @param  $var_expr\r\n"
1481                                 + "      */\r\n"
1482                                 + "    function _expand_quoted_text($var_expr)\r\n"
1483                                 + "    {\r\n"
1484                                 + "             // if contains unescaped $, expand it\r\n"
1485                                 + "             if(preg_match_all(\'|(?<!\\\\\\\\)\\$\' . $this->_dvar_guts_regexp . \'|\', $var_expr, $match)) {\r\n"
1486                                 + "                     rsort($match[0]);\r\n"
1487                                 + "                     reset($match[0]);\r\n"
1488                                 + "                     foreach($match[0] as $var) {\r\n"
1489                                 + "                $var_expr = str_replace ($var, \'\".\' . $this->_parse_var($var) . \'.\"\', $var_expr);\r\n"
1490                                 + "                     }\r\n"
1491                                 + "            return preg_replace(\'!\\.\"\"|\"\"\\.!\', \'\', $var_expr);\r\n"
1492                                 + "             } else {\r\n"
1493                                 + "                     return $var_expr;\r\n"
1494                                 + "             }\r\n"
1495                                 + "     }\r\n"
1496                                 + "     \r\n"
1497                                 + "     /**\r\n"
1498                                 + "      * parse variable expression into PHP code\r\n"
1499                                 + "      *\r\n"
1500                                 + "      * @access public\r\n"
1501                                 + "      * @param  $var_expr\r\n"
1502                                 + "      */\r\n"
1503                                 + "    function _parse_var($var_expr)\r\n"
1504                                 + "    {\r\n"
1505                                 + "                             \r\n"
1506                                 + "             preg_match(\'!(\' . $this->_obj_call_regexp . \'|\' . $this->_var_regexp . \')(\' . $this->_mod_regexp . \'*)$!\', $var_expr, $match);\r\n"
1507                                 + "                             \r\n"
1508                                 + "        $var_ref = substr($match[1],1);\r\n"
1509                                 + "        $modifiers = $match[2];\r\n"
1510                                 + "                                             \r\n"
1511                                 + "             if(!empty($this->default_modifiers) && !preg_match(\'!(^|\\|)smarty:nodefaults($|\\|)!\',$modifiers)) {\r\n"
1512                                 + "                     $_default_mod_string = implode(\'|\',(array)$this->default_modifiers);\r\n"
1513                                 + "                     $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . \'|\' . $modifiers;\r\n"
1514                                 + "             }\r\n"
1515                                 + "\r\n"
1516                                 + "             // get [foo] and .foo and ->foo() pieces                        \r\n"
1517                                 + "        preg_match_all(\'!(?:^\\w+)|(?:\' . $this->_obj_ext_regexp . \')+(?:\' . $this->_obj_params_regexp . \')?|(?:\' . $this->_var_bracket_regexp . \')|\\.\\$?\\w+!\', $var_ref, $match);                \r\n"
1518                                 + "             \r\n"
1519                                 + "        $indexes = $match[0];\r\n"
1520                                 + "        $var_name = array_shift($indexes);\r\n"
1521                                 + "                             \r\n"
1522                                 + "        /* Handle $smarty.* variable references as a special case. */\r\n"
1523                                 + "        if ($var_name == \'smarty\') {\r\n"
1524                                 + "            /*\r\n"
1525                                 + "             * If the reference could be compiled, use the compiled output;\r\n"
1526                                 + "             * otherwise, fall back on the $smarty variable generated at\r\n"
1527                                 + "             * run-time.\r\n"
1528                                 + "             */\r\n"
1529                                 + "            if (($smarty_ref = $this->_compile_smarty_ref($indexes)) !== null) {\r\n"
1530                                 + "                $output = $smarty_ref;\r\n"
1531                                 + "            } else {\r\n"
1532                                 + "                $var_name = substr(array_shift($indexes), 1);\r\n"
1533                                 + "                $output = \"\\$this->_smarty_vars[\'$var_name\']\";\r\n"
1534                                 + "            }\r\n"
1535                                 + "        } else {\r\n"
1536                                 + "            $output = \"\\$this->_tpl_vars[\'$var_name\']\";\r\n"
1537                                 + "        }\r\n"
1538                                 + "\r\n"
1539                                 + "        foreach ($indexes as $index) {                       \r\n"
1540                                 + "            if ($index{0} == \'[\') {\r\n"
1541                                 + "                $index = substr($index, 1, -1);\r\n"
1542                                 + "                if (is_numeric($index)) {\r\n"
1543                                 + "                    $output .= \"[$index]\";\r\n"
1544                                 + "                } elseif ($index{0} == \'$\') {\r\n"
1545                                 + "                    $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 1) . \"\']]\";\r\n"
1546                                 + "                } else {\r\n"
1547                                 + "                    $parts = explode(\'.\', $index);\r\n"
1548                                 + "                    $section = $parts[0];\r\n"
1549                                 + "                    $section_prop = isset($parts[1]) ? $parts[1] : \'index\';\r\n"
1550                                 + "                    $output .= \"[\\$this->_sections[\'$section\'][\'$section_prop\']]\";\r\n"
1551                                 + "                }\r\n"
1552                                 + "            } else if ($index{0} == \'.\') {\r\n"
1553                                 + "                if ($index{1} == \'$\')\r\n"
1554                                 + "                    $output .= \"[\\$this->_tpl_vars[\'\" . substr($index, 2) . \"\']]\";\r\n"
1555                                 + "                else\r\n"
1556                                 + "                    $output .= \"[\'\" . substr($index, 1) . \"\']\";\r\n"
1557                                 + "            } else if (substr($index,0,2) == \'->\') {\r\n"
1558                                 + "                             if(substr($index,2,2) == \'__\') {\r\n"
1559                                 + "                                     $this->_syntax_error(\'call to internal object members is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1560                                 + "                             } elseif($this->security && substr($index,2,1) == \'_\') {\r\n"
1561                                 + "                                     $this->_syntax_error(\'(secure) call to private object member is not allowed\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1562                                 + "                             } else {\r\n"
1563                                 + "                                     if(preg_match(\'!((?:\' . $this->_obj_ext_regexp . \')+)(\' . $this->_obj_params_regexp . \')?!\', $index, $match)) {\r\n"
1564                                 + "                                             if(!empty($match[2])) {\r\n"
1565                                 + "                                                     // parse object parameters\r\n"
1566                                 + "                                                     $index = str_replace($match[2], $this->_parse_parenth_args($match[2]), $index);\r\n"
1567                                 + "                                             }\r\n"
1568                                 + "                                             if(preg_match_all(\'!\' . $this->_dvar_regexp . \'!\', $match[1], $_dvar_match)) {\r\n"
1569                                 + "                                                     // parse embedded variables\r\n"
1570                                 + "                                                     $_match_replace = $match[1];\r\n"
1571                                 + "                                                     foreach($_dvar_match[0] as $_curr_var) {\r\n"
1572                                 + "                                                             $_match_replace = str_replace($_curr_var, \'{\' . $this->_parse_var($_curr_var) . \'}\', $_match_replace);\r\n"
1573                                 + "                                                     }\r\n"
1574                                 + "                                                     $index = str_replace($match[1], $_match_replace, $index);\r\n"
1575                                 + "                                             }\r\n"
1576                                 + "                                     }\r\n"
1577                                 + "                                     $output .= $index;\r\n"
1578                                 + "                             }\r\n"
1579                                 + "            } else {\r\n"
1580                                 + "                $output .= $index;\r\n"
1581                                 + "            }\r\n"
1582                                 + "        }\r\n"
1583                                 + "\r\n"
1584                                 + "             // look for variables imbedded in quoted strings, replace them\r\n"
1585                                 + "        if(preg_match(\'!\' . $this->_qstr_regexp . \'!\', $output, $match)) {\r\n"
1586                                 + "                     $output = str_replace($match[0], $this->_expand_quoted_text($match[0]), $output);\r\n"
1587                                 + "             }\r\n"
1588                                 + "             \r\n"
1589                                 + "        $this->_parse_modifiers($output, $modifiers);\r\n"
1590                                 + "\r\n"
1591                                 + "        return $output;\r\n"
1592                                 + "    }\r\n"
1593                                 + "\r\n"
1594                                 + "     /**\r\n"
1595                                 + "      * parse arguments in function call parenthesis\r\n"
1596                                 + "      *\r\n"
1597                                 + "      * @access public\r\n"
1598                                 + "      * @param  $parenth_args\r\n"
1599                                 + "      */\r\n"
1600                                 + "    function _parse_parenth_args($parenth_args)\r\n"
1601                                 + "    {\r\n"
1602                                 + "             preg_match_all(\'!\' . $this->_param_regexp . \'!\',$parenth_args, $match);\r\n"
1603                                 + "             $match = $match[0];\r\n"
1604                                 + "             rsort($match);\r\n"
1605                                 + "             reset($match);                                          \r\n"
1606                                 + "             $orig_vals = $match;\r\n"
1607                                 + "             $this->_parse_vars_props($match);\r\n"
1608                                 + "             return str_replace($orig_vals, $match, $parenth_args);\r\n"
1609                                 + "     }       \r\n"
1610                                 + "             \r\n"
1611                                 + "     /**\r\n"
1612                                 + "      * parse configuration variable expression into PHP code\r\n"
1613                                 + "      *\r\n"
1614                                 + "      * @access public\r\n"
1615                                 + "      * @param  $conf_var_expr\r\n"
1616                                 + "      */\r\n"
1617                                 + "    function _parse_conf_var($conf_var_expr)\r\n"
1618                                 + "    {\r\n"
1619                                 + "        $parts = explode(\'|\', $conf_var_expr, 2);\r\n"
1620                                 + "        $var_ref = $parts[0];\r\n"
1621                                 + "        $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n"
1622                                 + "\r\n"
1623                                 + "        $var_name = substr($var_ref, 1, -1);\r\n"
1624                                 + "\r\n"
1625                                 + "        $output = \"\\$this->_config[0][\'vars\'][\'$var_name\']\";\r\n"
1626                                 + "\r\n"
1627                                 + "        $this->_parse_modifiers($output, $modifiers);\r\n"
1628                                 + "\r\n"
1629                                 + "        return $output;\r\n"
1630                                 + "    }\r\n"
1631                                 + "\r\n"
1632                                 + "\r\n"
1633                                 + "     /**\r\n"
1634                                 + "      * parse section property expression into PHP code\r\n"
1635                                 + "      *\r\n"
1636                                 + "      * @access public\r\n"
1637                                 + "      * @param  $section_prop_expr\r\n"
1638                                 + "      */\r\n"
1639                                 + "    function _parse_section_prop($section_prop_expr)\r\n"
1640                                 + "    {\r\n"
1641                                 + "        $parts = explode(\'|\', $section_prop_expr, 2);\r\n"
1642                                 + "        $var_ref = $parts[0];\r\n"
1643                                 + "        $modifiers = isset($parts[1]) ? $parts[1] : \'\';\r\n"
1644                                 + "\r\n"
1645                                 + "        preg_match(\'!%(\\w+)\\.(\\w+)%!\', $var_ref, $match);\r\n"
1646                                 + "        $section_name = $match[1];\r\n"
1647                                 + "        $prop_name = $match[2];\r\n"
1648                                 + "\r\n"
1649                                 + "        $output = \"\\$this->_sections[\'$section_name\'][\'$prop_name\']\";\r\n"
1650                                 + "\r\n"
1651                                 + "        $this->_parse_modifiers($output, $modifiers);\r\n"
1652                                 + "\r\n"
1653                                 + "        return $output;\r\n"
1654                                 + "    }\r\n"
1655                                 + "\r\n"
1656                                 + "\r\n"
1657                                 + "     /**\r\n"
1658                                 + "      * parse modifier chain into PHP code\r\n"
1659                                 + "      *\r\n"
1660                                 + "      * @access public\r\n"
1661                                 + "      * @param  $output\r\n"
1662                                 + "      * @param  $modifier_string\r\n"
1663                                 + "      */\r\n"
1664                                 + "    function _parse_modifiers(&$output, $modifier_string)\r\n"
1665                                 + "    {\r\n"
1666                                 + "        preg_match_all(\'!\\|(@?\\w+)((?>:(?:\'. $this->_qstr_regexp . \'|[^|]+))*)!\', \'|\' . $modifier_string, $match);\r\n"
1667                                 + "        list(, $modifiers, $modifier_arg_strings) = $match;\r\n"
1668                                 + "\r\n"
1669                                 + "        for ($i = 0, $for_max = count($modifiers); $i < $for_max; $i++) {\r\n"
1670                                 + "            $modifier_name = $modifiers[$i];\r\n"
1671                                 + "                     \r\n"
1672                                 + "                     if($modifier_name == \'smarty\') {\r\n"
1673                                 + "                             // skip smarty modifier\r\n"
1674                                 + "                             continue;\r\n"
1675                                 + "                     }\r\n"
1676                                 + "                     \r\n"
1677                                 + "            preg_match_all(\'!:(\' . $this->_qstr_regexp . \'|[^:]+)!\', $modifier_arg_strings[$i], $match);\r\n"
1678                                 + "            $modifier_args = $match[1];\r\n"
1679                                 + "\r\n"
1680                                 + "            if ($modifier_name{0} == \'@\') {\r\n"
1681                                 + "                $map_array = \'false\';\r\n"
1682                                 + "                $modifier_name = substr($modifier_name, 1);\r\n"
1683                                 + "            } else {\r\n"
1684                                 + "                $map_array = \'true\';\r\n"
1685                                 + "            }\r\n"
1686                                 + "                     \r\n"
1687                                 + "            $this->_add_plugin(\'modifier\', $modifier_name);\r\n"
1688                                 + "\r\n"
1689                                 + "            $this->_parse_vars_props($modifier_args);\r\n"
1690                                 + "\r\n"
1691                                 + "            if (count($modifier_args) > 0)\r\n"
1692                                 + "                $modifier_args = \', \'.implode(\', \', $modifier_args);\r\n"
1693                                 + "            else\r\n"
1694                                 + "                $modifier_args = \'\';\r\n"
1695                                 + "\r\n"
1696                                 + "            $output = \"\\$this->_run_mod_handler(\'$modifier_name\', $map_array, $output$modifier_args)\";\r\n"
1697                                 + "        }\r\n"
1698                                 + "    }\r\n"
1699                                 + "\r\n"
1700                                 + "\r\n"
1701                                 + "     /**\r\n"
1702                                 + "      * add plugin\r\n"
1703                                 + "      *\r\n"
1704                                 + "      * @access public\r\n"
1705                                 + "      * @param  $type\r\n"
1706                                 + "      * @param  $name\r\n"
1707                                 + "      * @param  $delayed_loading\r\n"
1708                                 + "      */\r\n"
1709                                 + "    function _add_plugin($type, $name, $delayed_loading = null)\r\n"
1710                                 + "    {\r\n"
1711                                 + "        if (!isset($this->_plugin_info[$type])) {\r\n"
1712                                 + "            $this->_plugin_info[$type] = array();\r\n"
1713                                 + "        }\r\n"
1714                                 + "        if (!isset($this->_plugin_info[$type][$name])) {\r\n"
1715                                 + "            $this->_plugin_info[$type][$name] = array($this->_current_file,\r\n"
1716                                 + "                                                      $this->_current_line_no,\r\n"
1717                                 + "                                                      $delayed_loading);\r\n"
1718                                 + "        }\r\n"
1719                                 + "    }\r\n"
1720                                 + "    \r\n"
1721                                 + "\r\n"
1722                                 + "     /**\r\n"
1723                                 + "      * Compiles references of type $smarty.foo\r\n"
1724                                 + "      *\r\n"
1725                                 + "      * @access public\r\n"
1726                                 + "      * @param  $indexes\r\n"
1727                                 + "      */\r\n"
1728                                 + "    function _compile_smarty_ref(&$indexes)\r\n"
1729                                 + "    {\r\n"
1730                                 + "        /* Extract the reference name. */\r\n"
1731                                 + "        $ref = substr($indexes[0], 1);\r\n"
1732                                 + "\r\n"
1733                                 + "        switch ($ref) {\r\n"
1734                                 + "            case \'now\':\r\n"
1735                                 + "                $compiled_ref = \'time()\';\r\n"
1736                                 + "                if (count($indexes) > 1) {\r\n"
1737                                 + "                    $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1738                                 + "                }\r\n"
1739                                 + "                break;\r\n"
1740                                 + "\r\n"
1741                                 + "            case \'foreach\':\r\n"
1742                                 + "            case \'section\':\r\n"
1743                                 + "                if ($indexes[1]{0} != \'.\') {\r\n"
1744                                 + "                    $this->_syntax_error(\'$smarty\' . implode(\'\', array_slice($indexes, 0, 2)) . \' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1745                                 + "                }\r\n"
1746                                 + "                $name = substr($indexes[1], 1);\r\n"
1747                                 + "                array_shift($indexes);\r\n"
1748                                 + "                if ($ref == \'foreach\')\r\n"
1749                                 + "                    $compiled_ref = \"\\$this->_foreach[\'$name\']\";\r\n"
1750                                 + "                else\r\n"
1751                                 + "                    $compiled_ref = \"\\$this->_sections[\'$name\']\";\r\n"
1752                                 + "                break;\r\n"
1753                                 + "\r\n"
1754                                 + "            case \'get\':\r\n"
1755                                 + "                array_shift($indexes);\r\n"
1756                                 + "                $compiled_ref = \"\\$_GET\";\r\n"
1757                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1758                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1759                                 + "                break;\r\n"
1760                                 + "\r\n"
1761                                 + "            case \'post\':\r\n"
1762                                 + "                array_shift($indexes);\r\n"
1763                                 + "                $name = substr($indexes[0], 1);\r\n"
1764                                 + "                $compiled_ref = \"\\$_POST\";\r\n"
1765                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1766                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1767                                 + "                break;\r\n"
1768                                 + "\r\n"
1769                                 + "            case \'cookies\':\r\n"
1770                                 + "                array_shift($indexes);\r\n"
1771                                 + "                $name = substr($indexes[0], 1);\r\n"
1772                                 + "                $compiled_ref = \"\\$_COOKIE\";\r\n"
1773                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1774                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1775                                 + "                break;\r\n"
1776                                 + "\r\n"
1777                                 + "            case \'env\':\r\n"
1778                                 + "                array_shift($indexes);\r\n"
1779                                 + "                $compiled_ref = \"\\$_ENV\";\r\n"
1780                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1781                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1782                                 + "                break;\r\n"
1783                                 + "\r\n"
1784                                 + "            case \'server\':\r\n"
1785                                 + "                array_shift($indexes);\r\n"
1786                                 + "                $name = substr($indexes[0], 1);\r\n"
1787                                 + "                $compiled_ref = \"\\$_SERVER\";\r\n"
1788                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1789                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1790                                 + "                break;\r\n"
1791                                 + "\r\n"
1792                                 + "            case \'session\':\r\n"
1793                                 + "                array_shift($indexes);\r\n"
1794                                 + "                $name = substr($indexes[0], 1);\r\n"
1795                                 + "                $compiled_ref = \"\\$_SESSION\";\r\n"
1796                                 + "                if ($name = substr($indexes[0], 1))\r\n"
1797                                 + "                    $compiled_ref .= \"[\'$name\']\";\r\n"
1798                                 + "                break;\r\n"
1799                                 + "\r\n"
1800                                 + "            /*\r\n"
1801                                 + "             * These cases are handled either at run-time or elsewhere in the\r\n"
1802                                 + "             * compiler.\r\n"
1803                                 + "             */\r\n"
1804                                 + "            case \'request\':\r\n"
1805                                 + "                $this->_init_smarty_vars = true;\r\n"
1806                                 + "                return null;\r\n"
1807                                 + "\r\n"
1808                                 + "            case \'capture\':\r\n"
1809                                 + "                return null;\r\n"
1810                                 + "\r\n"
1811                                 + "            case \'template\':\r\n"
1812                                 + "                $compiled_ref = \"\'$this->_current_file\'\";\r\n"
1813                                 + "                if (count($indexes) > 1) {\r\n"
1814                                 + "                    $this->_syntax_error(\'$smarty\' . implode(\'\', $indexes) .\' is an invalid reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1815                                 + "                }\r\n"
1816                                 + "                break;\r\n"
1817                                 + "                             \r\n"
1818                                 + "                     case \'version\':\r\n"
1819                                 + "                             $compiled_ref = \"\'$this->_version\'\";\r\n"
1820                                 + "                             break;\r\n"
1821                                 + "\r\n"
1822                                 + "                     case \'const\':\r\n"
1823                                 + "                array_shift($indexes);\r\n"
1824                                 + "                             $compiled_ref = \'defined(\\\'\' . substr($indexes[0],1) . \'\\\') ? \' . substr($indexes[0],1) . \' : null\';\r\n"
1825                                 + "                break;\r\n"
1826                                 + "\r\n"
1827                                 + "            default:\r\n"
1828                                 + "                $this->_syntax_error(\'$smarty.\' . $ref . \' is an unknown reference\', E_USER_ERROR, __FILE__, __LINE__);\r\n"
1829                                 + "                break;\r\n"
1830                                 + "        }\r\n"
1831                                 + "\r\n"
1832                                 + "        array_shift($indexes);\r\n"
1833                                 + "        return $compiled_ref;\r\n"
1834                                 + "    }\r\n"
1835                                 + "\r\n"
1836                                 + "\r\n"
1837                                 + "     /**\r\n"
1838                                 + "      * load pre- and post-filters\r\n"
1839                                 + "      *\r\n"
1840                                 + "      * @access public\r\n"
1841                                 + "      */\r\n"
1842                                 + "    function _load_filters()\r\n"
1843                                 + "    {\r\n"
1844                                 + "        if (count($this->_plugins[\'prefilter\']) > 0) {\r\n"
1845                                 + "            foreach ($this->_plugins[\'prefilter\'] as $filter_name => $prefilter) {\r\n"
1846                                 + "                if ($prefilter === false) {\r\n"
1847                                 + "                    unset($this->_plugins[\'prefilter\'][$filter_name]);\r\n"
1848                                 + "                    $this->_load_plugins(array(array(\'prefilter\', $filter_name, null, null, false)));\r\n"
1849                                 + "                }\r\n"
1850                                 + "            }\r\n"
1851                                 + "        }\r\n"
1852                                 + "        if (count($this->_plugins[\'postfilter\']) > 0) {\r\n"
1853                                 + "            foreach ($this->_plugins[\'postfilter\'] as $filter_name => $postfilter) {\r\n"
1854                                 + "                if ($postfilter === false) {\r\n"
1855                                 + "                    unset($this->_plugins[\'postfilter\'][$filter_name]);\r\n"
1856                                 + "                    $this->_load_plugins(array(array(\'postfilter\', $filter_name, null, null, false)));\r\n"
1857                                 + "                }\r\n"
1858                                 + "            }\r\n"
1859                                 + "        }\r\n"
1860                                 + "    }\r\n"
1861                                 + "\r\n"
1862                                 + "\r\n"
1863                                 + "     /**\r\n"
1864                                 + "      * display Smarty syntax error\r\n"
1865                                 + "      *\r\n"
1866                                 + "      * @access public\r\n"
1867                                 + "      * @param  $error_msg\r\n"
1868                                 + "      * @param  $error_type\r\n"
1869                                 + "      * @param  $file\r\n"
1870                                 + "      * @param  $line\r\n"
1871                                 + "      */\r\n"
1872                                 + "    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)\r\n"
1873                                 + "    {\r\n"
1874                                 + "             if(isset($file) && isset($line)) {\r\n"
1875                                 + "                     $info = \' (\'.basename($file).\", line $line)\";\r\n"
1876                                 + "             } else {\r\n"
1877                                 + "                     $info = null;\r\n"
1878                                 + "             }\r\n"
1879                                 + "        trigger_error(\'Smarty: [in \' . $this->_current_file . \' line \' .\r\n"
1880                                 + "                      $this->_current_line_no . \"]: syntax error: $error_msg$info\", $error_type);\r\n"
1881                                 + "    }\r\n" + "}\r\n" + "\r\n" + "/**\r\n"
1882                                 + " * compare to values by their string length\r\n" + " *\r\n"
1883                                 + " * @access private\r\n" + " * @param  $a\r\n"
1884                                 + " * @param  $b\r\n" + " */\r\n"
1885                                 + "function _smarty_sort_length($a, $b)\r\n" + "{\r\n"
1886                                 + "     if($a == $b)\r\n" + "           return 0;\r\n" + "\r\n"
1887                                 + "     if(strlen($a) == strlen($b))\r\n"
1888                                 + "             return ($a > $b) ? -1 : 1;\r\n" + "\r\n"
1889                                 + "     return (strlen($a) > strlen($b)) ? -1 : 1;\r\n" + "}\r\n"
1890                                 + "\r\n" + "\r\n" + "/* vim: set et: */\r\n" + "\r\n"
1891                                 + "?>\r\n" + "");
1892         }
1893 }