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