/[health_html]/inc/Smarty.class.php
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /inc/Smarty.class.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Fri Aug 3 09:12:42 2001 UTC (22 years, 8 months ago) by ravilov
Branch: MAIN
Branch point for: pliva
Initial revision

1 <?php
2 /*
3 * Project: Smarty: the PHP compiling template engine
4 * File: Smarty.class.php
5 * Author: Monte Ohrt <monte@ispi.net>
6 * Andrei Zmievski <andrei@ispi.net>
7 *
8 * Version: 1.3.0
9 * Copyright: 2001 ispi of Lincoln, Inc.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 * You may contact the authors of Smarty by e-mail at:
26 * monte@ispi.net
27 * andrei@ispi.net
28 *
29 * Or, write to:
30 * Monte Ohrt
31 * CTO, ispi
32 * 237 S. 70th suite 220
33 * Lincoln, NE 68510
34 *
35 * The latest version of Smarty can be obtained from:
36 * http://www.phpinsider.com/
37 *
38 */
39
40 require('Smarty.addons.php');
41 require("Smarty.local.php");
42
43 define("SMARTY_PHP_PASSTHRU",0);
44 define("SMARTY_PHP_QUOTE",1);
45 define("SMARTY_PHP_REMOVE",2);
46 define("SMARTY_PHP_ALLOW",3);
47
48 class Smarty
49 {
50
51 // public vars
52 var $template_dir = './templates'; // name of directory for templates
53 var $compile_dir = './templates_c'; // name of directory for compiled templates
54 var $config_dir = './configs'; // directory where config files are located
55
56 var $global_assign = array('SCRIPT_NAME'); // variables from the GLOBALS array
57 // that are implicitly assigned
58 // to all templates
59 var $compile_check = true; // whether to check for compiling step or not:
60 // This is generally set to false once the
61 // application is entered into production and
62 // initially compiled. Leave set to true
63 // during development. true/false default true.
64
65 var $force_compile = false; // force templates to compile every time.
66 // if cache file exists, it will
67 // override compile_check and force_compile.
68 // true/false. default false.
69 var $caching = false; // whether to use caching or not. true/false
70 var $cache_dir = './cache'; // name of directory for template cache
71 var $cache_lifetime = 3600; // number of seconds cached content will persist.
72 // 0 = never expires. default is one hour (3600)
73
74 var $tpl_file_ext = '.tpl'; // template file extention
75
76 var $php_handling = SMARTY_PHP_PASSTHRU; // how smarty handles php tags
77 // possible values:
78 // SMARTY_PHP_PASSTHRU -> echo tags as is
79 // SMARTY_PHP_QUOTE -> escape tags as entities
80 // SMARTY_PHP_REMOVE -> remove php tags
81 // SMARTY_PHP_ALLOW -> execute php tags
82 // default: SMARTY_PHP_PASSTHRU
83
84 var $left_delimiter = '{'; // template tag delimiters.
85 var $right_delimiter = '}';
86
87
88 var $custom_funcs = array( 'html_options' => 'smarty_func_html_options',
89 'html_select_date' => 'smarty_func_html_select_date',
90 'header' => 'smarty_func_header',
91
92 //----- local custom_funcs
93 'img' => 'smarty_func_img',
94 'html_checkboxes' => 'smarty_func_html_checkboxes',
95 'input' => 'smarty_func_input',
96 'rinput' => 'smarty_func_rinput',
97
98 );
99
100 var $custom_mods = array( 'lower' => 'strtolower',
101 'upper' => 'strtoupper',
102 'capitalize' => 'ucwords',
103 'escape' => 'smarty_mod_escape',
104 'truncate' => 'smarty_mod_truncate',
105 'spacify' => 'smarty_mod_spacify',
106 'date_format' => 'smarty_mod_date_format',
107 'string_format' => 'smarty_mod_string_format',
108 'replace' => 'smarty_mod_replace',
109 'strip_tags' => 'smarty_mod_strip_tags',
110 'default' => 'smarty_mod_default',
111
112 //----- local custom_mods
113 'filesize' => 'smarty_mod_filesize',
114
115 );
116
117 // internal vars
118 var $_error_msg = false; // error messages. true/false
119 var $_tpl_vars = array();
120 var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part
121 var $_literal_blocks = array(); // keeps literal template blocks
122 var $_current_file = null; // the current template being compiled
123 var $_current_line_no = 1; // line number for error messages
124 var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; // md5 checksum of the string 'Smarty'
125
126
127 /*======================================================================*\
128 Function: Smarty
129 Purpose: Constructor
130 \*======================================================================*/
131 function Smarty()
132 {
133 foreach ($this->global_assign as $var_name)
134 $this->assign($var_name, $GLOBALS[$var_name]);
135 }
136
137
138 /*======================================================================*\
139 Function: assign()
140 Purpose: assigns values to template variables
141 \*======================================================================*/
142
143 function assign($tpl_var, $value = NULL)
144 {
145 if (is_array($tpl_var)){
146 foreach ($tpl_var as $key => $val) {
147 if (!empty($key))
148 $this->_tpl_vars[$key] = $val;
149 }
150 } else {
151 if (!empty($tpl_var) && isset($value))
152 $this->_tpl_vars[$tpl_var] = $value;
153 }
154 }
155
156
157 /*======================================================================*\
158 Function: append
159 Purpose: appens values to template variables
160 \*======================================================================*/
161 function append($tpl_var, $value = NULL)
162 {
163 if (is_array($tpl_var)) {
164 foreach ($tpl_var as $key => $val) {
165 if (!empty($key)) {
166 if (!is_array($this->_tpl_vars[$key]))
167 settype($this->_tpl_vars[$key], 'array');
168 $this->_tpl_vars[$key][] = $val;
169 }
170 }
171 } else {
172 if (!empty($tpl_var) && isset($value)) {
173 if (!is_array($this->_tpl_vars[$tpl_var]))
174 settype($this->_tpl_vars[$tpl_var], 'array');
175 $this->_tpl_vars[$tpl_var][] = $value;
176 }
177 }
178 }
179
180
181 /*======================================================================*\
182 Function: clear_assign()
183 Purpose: clear the given assigned template variable.
184 \*======================================================================*/
185
186 function clear_assign($tpl_var)
187 {
188 if(is_array($tpl_var))
189 foreach($tpl_var as $curr_var)
190 unset($this->_tpl_vars[$curr_var]);
191 else
192 unset($this->_tpl_vars[$tpl_var]);
193 }
194
195
196 /*======================================================================*\
197 Function: register_function
198 Purpose: Registers custom function to be used in templates
199 \*======================================================================*/
200 function register_function($function, $function_impl)
201 {
202 $this->custom_funcs[$function] = $function_impl;
203 }
204
205
206 /*======================================================================*\
207 Function: register_modifier
208 Purpose: Registers modifier to be used in templates
209 \*======================================================================*/
210 function register_modifier($modifier, $modifier_impl)
211 {
212 $this->custom_mods[$modifier] = $modifier_impl;
213 }
214
215
216 /*======================================================================*\
217 Function: clear_cache()
218 Purpose: clear cached content for the given template and cache id
219 \*======================================================================*/
220
221 function clear_cache($tpl_file, $cache_id = null)
222 {
223 $cache_tpl_md5 = md5(realpath($this->template_dir.'/'.$tpl_file));
224 $cache_dir = $this->cache_dir.'/'.$cache_tpl_md5;
225
226 if (!is_dir($cache_dir))
227 return false;
228
229 if (isset($cache_id)) {
230 $cache_id_md5 = md5($cache_id);
231 $cache_id_dir = substr($cache_id_md5, 0, 2);
232 $cache_file = "$cache_dir/$cache_id_dir/{$cache_tpl_md5}_$cache_id_md5.cache";
233 return (bool)(is_file($cache_file) && unlink($cache_file));
234 } else
235 return $this->_clear_tpl_cache_dir($cache_tpl_md5);
236 }
237
238
239 /*======================================================================*\
240 Function: clear_all_cache()
241 Purpose: clear the entire contents of cache (all templates)
242 \*======================================================================*/
243
244 function clear_all_cache()
245 {
246 if (!is_dir($this->cache_dir))
247 return false;
248
249 $dir_handle = opendir($this->cache_dir);
250 while ($curr_dir = readdir($dir_handle)) {
251 if ($curr_dir == '.' || $curr_dir == '..' ||
252 !is_dir($this->cache_dir.'/'.$curr_dir))
253 continue;
254
255 $this->_clear_tpl_cache_dir($curr_dir);
256 }
257 closedir($dir_handle);
258
259 return true;
260 }
261
262
263 /*======================================================================*\
264 Function: is_cached()
265 Purpose: test to see if valid cache exists for this template
266 \*======================================================================*/
267
268 function is_cached($tpl_file, $cache_id = null)
269 {
270 if (!$this->caching)
271 return false;
272
273 // cache name = template path + cache_id
274 $cache_tpl_md5 = md5(realpath($this->template_dir.'/'.$tpl_file));
275 $cache_id_md5 = md5($cache_id);
276 $cache_id_dir = substr($cache_id_md5, 0, 2);
277 $cache_file = $this->cache_dir."/$cache_tpl_md5/$cache_id_dir/{$cache_tpl_md5}_$cache_id_md5.cache";
278
279 if (file_exists($cache_file) &&
280 ($this->cache_lifetime == 0 ||
281 (time() - filemtime($cache_file) <= $this->cache_lifetime)))
282 return true;
283 else
284 return false;
285
286 }
287
288
289 /*======================================================================*\
290 Function: clear_all_assign()
291 Purpose: clear all the assigned template variables.
292 \*======================================================================*/
293
294 function clear_all_assign()
295 {
296 $this->_tpl_vars = array();
297 }
298
299
300 /*======================================================================*\
301 Function: get_template_vars
302 Purpose: Returns an array containing template variables
303 \*======================================================================*/
304 function &get_template_vars()
305 {
306 return $this->_tpl_vars;
307 }
308
309
310 /*======================================================================*\
311 Function: display()
312 Purpose: executes & displays the template results
313 \*======================================================================*/
314
315 function display($tpl_file, $cache_id = null)
316 {
317 $this->fetch($tpl_file, $cache_id, true);
318 }
319
320 /*======================================================================*\
321 Function: fetch()
322 Purpose: executes & returns or displays the template results
323 \*======================================================================*/
324
325 function fetch($tpl_file, $cache_id = null, $display = false)
326 {
327 global $HTTP_SERVER_VARS;
328
329 if ($this->caching) {
330 // cache name = template path + cache_id
331 $cache_tpl_md5 = md5(realpath($this->template_dir.'/'.$tpl_file));
332 $cache_id_md5 = md5($cache_id);
333 $cache_id_dir = substr($cache_id_md5, 0, 2);
334 $cache_file = $this->cache_dir."/$cache_tpl_md5/$cache_id_dir/{$cache_tpl_md5}_$cache_id_md5.cache";
335
336 if (file_exists($cache_file) &&
337 ($this->cache_lifetime == 0 ||
338 (time() - filemtime($cache_file) <= $this->cache_lifetime))) {
339 $results = $this->_read_file($cache_file);
340 $results = $this->_process_cached_inserts($results);
341 if ($display) {
342 echo $results;
343 return;
344 } else
345 return $results;
346 }
347 }
348
349 // compile files
350 $this->_compile($this->template_dir);
351 //assemble compile directory path to file
352 $_compile_file = $this->compile_dir."/".$tpl_file.".php";
353
354 extract($this->_tpl_vars);
355
356 // if we just need to display the results, don't perform output
357 // buffering - for speed
358 if ($display && !$this->caching)
359 include($_compile_file);
360 else {
361 ob_start();
362 include($_compile_file);
363 $results = ob_get_contents();
364 ob_end_clean();
365 }
366
367 if($this->caching) {
368 $this->_write_file($cache_file, $results, true);
369 $results = $this->_process_cached_inserts($results);
370 }
371
372 if ($display) {
373 echo $results;
374 return;
375 } else
376 return $results;
377 }
378
379 /*======================================================================*\
380 Function: compile()
381 Purpose: called to compile the templates
382 \*======================================================================*/
383
384 function _compile($tpl_dir)
385 {
386 if($this->compile_check || $this->force_compile)
387 {
388 if($this->_traverse_files($tpl_dir, 0))
389 return true;
390 else
391 return false;
392 } else
393 return false;
394 }
395
396 /*======================================================================*\
397 Function: _traverse_files()
398 Purpose: traverse the template files & process each one
399 \*======================================================================*/
400
401 function _traverse_files($tpl_dir, $depth)
402 {
403 $retval = true;
404
405 if (is_dir($tpl_dir)) {
406 $dir_handle = opendir($tpl_dir);
407 while ($curr_file = readdir($dir_handle)) {
408 if ($curr_file == '.' || $curr_file == '..')
409 continue;
410
411 $filepath = $tpl_dir.'/'.$curr_file;
412 if (is_readable($filepath)) {
413 if (is_file($filepath) && substr($curr_file, -strlen($this->tpl_file_ext)) == $this->tpl_file_ext) {
414 if (!$this->_process_file($filepath)) {
415 $retval = false;
416 break;
417 }
418 } else if (is_dir($filepath)) {
419 if (!$this->_traverse_files($filepath, $depth + 1)) {
420 $retval = false;
421 break;
422 }
423 } else {
424 // invalid file type, skipping
425 $this->_set_error_msg("Invalid filetype for $filepath, skipping");
426 continue;
427 }
428 }
429 }
430
431 closedir($dir_handle);
432 return $retval;
433 } else {
434 $this->_set_error_msg("Directory \"$tpl_dir\" does not exist or is not a directory.");
435 return false;
436 }
437 }
438
439 /*======================================================================*\
440 Function: _process_file()
441 Input: test template files for modifications
442 and execute the compilation for each
443 one requiring it.
444 \*======================================================================*/
445
446 function _process_file($filepath)
447 {
448 if(preg_match("/^(.+)\/([^\/]+)$/", $filepath, $match)) {
449 $tpl_file_dir = $match[1];
450 $tpl_file_name = $match[2] . '.php';
451
452 $compile_dir = preg_replace('!^' . preg_quote($this->template_dir, '!') . '!',
453 $this->compile_dir, $match[1]);
454
455 //create directory if none exists
456 $this->_create_dir_structure($compile_dir);
457
458 // compile the template file if none exists or has been modified or recompile is forced
459 if ($this->force_compile || !file_exists($compile_dir."/".$tpl_file_name) ||
460 ($this->_modified_file($filepath, $compile_dir."/".$tpl_file_name))) {
461 if (!$this->_compile_file($filepath, $compile_dir."/".$tpl_file_name))
462 return false;
463 } else {
464 // no compilation needed
465 return true;
466 }
467 } else {
468 $this->_set_error_msg("problem matching \"$filepath.\"");
469 return false;
470 }
471
472 return true;
473 }
474
475 /*======================================================================*\
476 Function: _create_dir_structure
477 Purpose: create full directory structure
478 \*======================================================================*/
479 function _create_dir_structure($dir)
480 {
481 if (!file_exists($dir)) {
482 $dir_parts = preg_split('!/+!', $dir, -1, PREG_SPLIT_NO_EMPTY);
483 $new_dir = ($dir{0} == '/') ? '/' : '';
484 foreach ($dir_parts as $dir_part) {
485 $new_dir .= $dir_part;
486 if (!file_exists($new_dir) && !mkdir($new_dir, 0755)) {
487 $this->_set_error_msg("problem creating directory \"$dir\"");
488 return false;
489 }
490 $new_dir .= '/';
491 }
492 }
493 }
494
495 /*======================================================================*\
496 Function: _modified_file()
497 Input: return comparison of modification times of files
498 \*======================================================================*/
499
500 function _modified_file($filepath, $compilepath)
501 {
502 if (filemtime($filepath) >= filemtime($compilepath))
503 return true;
504 return false;
505 }
506
507 /*======================================================================*\
508 Function: _compile_file()
509 Input: compile a template file
510 \*======================================================================*/
511
512 function _compile_file($filepath, $compilepath)
513 {
514 if (!($template_contents = $this->_read_file($filepath)))
515 return false;
516
517 $this->_current_file = str_replace($this->template_dir . '/', '', $filepath);
518 $this->_current_line_no = 1;
519 $ldq = preg_quote($this->left_delimiter, '!');
520 $rdq = preg_quote($this->right_delimiter, '!');
521
522 /* Pull out the literal blocks. */
523 preg_match_all("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s", $template_contents, $match);
524 $this->_literal_blocks = $match[1];
525 $template_contents = preg_replace("!{$ldq}literal{$rdq}(.*?){$ldq}/literal{$rdq}!s",
526 '{literal}', $template_contents);
527
528 /* Gather all template tags. */
529 preg_match_all("!{$ldq}\s*(.*?)\s*{$rdq}!s", $template_contents, $match);
530 $template_tags = $match[1];
531 /* Split content by template tags to obtain non-template content. */
532 $text_blocks = preg_split("!{$ldq}.*?{$rdq}!s", $template_contents);
533
534 /* TODO: speed up the following with preg_replace and /F once we require that version of PHP */
535
536 /* loop through text blocks */
537 for ($curr_tb = 0; $curr_tb <= count($text_blocks); $curr_tb++) {
538 /* match anything within <? ?> */
539 if (preg_match_all('!(<\?[^?]*?\?>|<script\s+language\s*=\s*[\"\']?php[\"\']?\s*>)!is', $text_blocks[$curr_tb], $sp_match)) {
540 /* found at least one match, loop through each one */
541 for ($curr_sp = 0; $curr_sp < count($sp_match[0]); $curr_sp++) {
542 if (preg_match('!^(<\?(php\s|\s|=\s)|<script\s*language\s*=\s*[\"\']?php[\"\']?\s*>)!is', $sp_match[0][$curr_sp])) {
543 /* php tag */
544 if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
545 /* echo php contents */
546 $text_blocks[$curr_tb] = str_replace($sp_match[0][$curr_sp], '<?php echo \''.str_replace("'", "\'", $sp_match[0][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
547 } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
548 /* quote php tags */
549 $text_blocks[$curr_tb] = str_replace($sp_match[0][$curr_sp], htmlspecialchars($sp_match[0][$curr_sp]), $text_blocks[$curr_tb]);
550 } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
551 /* remove php tags */
552 if (substr($sp_match[0][$curr_sp], 0, 2) == '<?')
553 $text_blocks[$curr_tb] = str_replace($sp_match[0][$curr_sp], '', $text_blocks[$curr_tb]);
554 else
555 /* attempt to remove everything between <script ...> and </script> */
556 $text_blocks[$curr_tb] = preg_replace('!'.preg_quote($sp_match[0][$curr_sp], '!').'.*?</script\s*>!is', '', $text_blocks[$curr_tb]);
557 }
558 } else
559 /* echo the non-php tags */
560 $text_blocks[$curr_tb] = str_replace($sp_match[0][$curr_sp], '<?php echo \''.str_replace("'", "\'", $sp_match[0][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
561 }
562 }
563 }
564
565 /* Compile the template tags into PHP code. */
566 $compiled_tags = array();
567 for ($i = 0; $i < count($template_tags); $i++) {
568 $this->_current_line_no += substr_count($text_blocks[$i], "\n");
569 $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
570 $this->_current_line_no += substr_count($template_tags[$i], "\n");
571 }
572
573 $compiled_contents = '';
574
575 /* Interleave the compiled contents and text blocks to get the final result. */
576 for ($i = 0; $i < count($compiled_tags); $i++) {
577 $compiled_contents .= $text_blocks[$i].$compiled_tags[$i];
578 }
579 $compiled_contents .= $text_blocks[$i];
580
581 /* Reformat data between 'strip' and '/strip' tags, removing spaces, tabs and newlines. */
582 if (preg_match_all("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s", $compiled_contents, $match)) {
583 $strip_tags = $match[0];
584 $strip_tags_modified = preg_replace("!{$ldq}/?strip{$rdq}|[\t ]+$|^[\t ]+!m", '', $strip_tags);
585 $strip_tags_modified = preg_replace('![\r\n]+!m', '', $strip_tags_modified);
586 for ($i = 0; $i < count($strip_tags); $i++)
587 $compiled_contents = preg_replace("!{$ldq}strip{$rdq}.*?{$ldq}/strip{$rdq}!s",
588 $strip_tags_modified[$i], $compiled_contents, 1);
589 }
590
591 if(!$this->_write_file($compilepath, $compiled_contents))
592 return false;
593
594 return true;
595 }
596
597 /*======================================================================*\
598 Function: _process_cached_inserts
599 Purpose: Replace cached inserts with the actual results
600 \*======================================================================*/
601 function _process_cached_inserts($results)
602 {
603 preg_match_all('!'.$this->_smarty_md5.'{insert_cache (.*)}'.$this->_smarty_md5.'!Uis',
604 $results, $match);
605 list($cached_inserts, $insert_args) = $match;
606
607 for ($i = 0; $i < count($cached_inserts); $i++) {
608 $args = unserialize($insert_args[$i]);
609 $name = $args['name'];
610 unset($args['name']);
611
612 $function_name = 'insert_' . $name;
613 $replace = $function_name($args);
614
615 $results = str_replace($cached_inserts[$i], $replace, $results);
616 }
617
618 return $results;
619 }
620
621
622 /*======================================================================*\
623 Function: _compile_tag
624 Purpose: Compile a template tag
625 \*======================================================================*/
626 function _compile_tag($template_tag)
627 {
628 /* Matched comment. */
629 if ($template_tag{0} == '*' && $template_tag{strlen($template_tag)-1} == '*')
630 return '';
631
632 $qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
633
634 /* Split tag into two parts: command and the arguments. */
635 preg_match('/^(
636 (?: ' . $qstr_regexp . ' | (?>[^"\'\s]+))+
637 )
638 (?:\s+(.*))?
639 /xs', $template_tag, $match);
640 list(, $tag_command, $tag_args) = $match;
641
642 /* If the tag name matches a variable or section property definition,
643 we simply process it. */
644 /* RA: if (preg_match('!^\$(\w+/)*\w+(?>\.\w+)(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tag_command) || // if a variable */
645 if (preg_match('!^\$(\w+[/\.])*\w+(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tag_command) || // if a variable
646 preg_match('!^#(\w+)#(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tag_command) || // or a configuration variable
647 preg_match('!^%\w+\.\w+%(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tag_command)) { // or a section property
648 settype($tag_command, 'array');
649 $this->_parse_vars_props($tag_command);
650 return "<?php echo $tag_command[0]; ?>\n";
651 }
652
653 switch ($tag_command) {
654 case 'include':
655 return $this->_compile_include_tag($tag_args);
656
657 case 'if':
658 return $this->_compile_if_tag($tag_args);
659
660 case 'else':
661 return '<?php else: ?>';
662
663 case 'elseif':
664 return $this->_compile_if_tag($tag_args, true);
665
666 case '/if':
667 return '<?php endif; ?>';
668
669 case 'ldelim':
670 return $this->left_delimiter;
671
672 case 'rdelim':
673 return $this->right_delimiter;
674
675 case 'section':
676 array_push($this->_sectionelse_stack, false);
677 return $this->_compile_section_start($tag_args);
678
679 case 'sectionelse':
680 $this->_sectionelse_stack[count($this->_sectionelse_stack)-1] = true;
681 return "<?php endfor; else: ?>";
682
683 case '/section':
684 if (array_pop($this->_sectionelse_stack))
685 return "<?php endif; ?>";
686 else
687 return "<?php endfor; endif; ?>";
688
689 case 'config_load':
690 return $this->_compile_config_load_tag($tag_args);
691
692 case 'strip':
693 case '/strip':
694 return $this->left_delimiter.$tag_command.$this->right_delimiter;
695
696 case 'literal':
697 list (,$literal_block) = each($this->_literal_blocks);
698 $this->_current_line_no += substr_count($literal_block, "\n");
699 return $literal_block;
700
701 case 'insert':
702 return $this->_compile_insert_tag($tag_args);
703
704 default:
705 if (isset($this->custom_funcs[$tag_command])) {
706 return $this->_compile_custom_tag($tag_command, $tag_args);
707 } else {
708 $this->_syntax_error("unknown tag - '$tag_command'", E_USER_WARNING);
709 return;
710 }
711 }
712 }
713
714 function _compile_custom_tag($tag_command, $tag_args)
715 {
716 $function = $this->custom_funcs[$tag_command];
717
718 if (!function_exists($function)) {
719 $this->_syntax_error("custom function '$tag_command' is not implemented", E_USER_WARNING);
720 return;
721 }
722
723 $attrs = $this->_parse_attrs($tag_args);
724 foreach ($attrs as $arg_name => $arg_value) {
725 if (is_bool($arg_value))
726 $arg_value = $arg_value ? 'true' : 'false';
727 $arg_list[] = "'$arg_name' => $arg_value";
728 }
729
730 return "<?php $function(array(".implode(',', (array)$arg_list).")); ?>";
731 }
732
733
734 /*======================================================================*\
735 Function: _compile_insert_tag
736 Purpose: Compile {insert ...} tag
737 \*======================================================================*/
738 function _compile_insert_tag($tag_args)
739 {
740 $attrs = $this->_parse_attrs($tag_args);
741 $name = substr($attrs['name'], 1, -1);
742
743 if (empty($name)) {
744 $this->_syntax_error("missing insert name");
745 }
746
747 foreach ($attrs as $arg_name => $arg_value) {
748 if (is_bool($arg_value))
749 $arg_value = $arg_value ? 'true' : 'false';
750 $arg_list[] = "'$arg_name' => $arg_value";
751 }
752
753 return "<?php echo _smarty_insert_handler(array(".implode(', ', (array)$arg_list)."), \$this->caching, \$this->_smarty_md5); ?>\n";
754 }
755
756
757 /*======================================================================*\
758 Function: _compile_config_load_tag
759 Purpose: Compile {config_load ...} tag
760 \*======================================================================*/
761 function _compile_config_load_tag($tag_args)
762 {
763 $attrs = $this->_parse_attrs($tag_args);
764
765 if (empty($attrs['file'])) {
766 $this->_syntax_error("missing 'file' attribute in config_load tag");
767 }
768
769 $output = "<?php if (!class_exists('Config_File'))\n" .
770 " include_once 'Config_File.class.php';\n" .
771 "if (!is_object(\$_conf_obj) || get_class(\$_conf_obj) != 'config_file') {\n" .
772 " \$_conf_obj = new Config_File('".$this->config_dir."');\n" .
773 "}\n" .
774 "\$_config = array_merge((array)\$_config, \$_conf_obj->get(".$attrs['file']."));\n";
775
776 if (!empty($attrs['section']))
777 $output .= '$_config = array_merge((array)$_config, $_conf_obj->get('.$attrs['file'].', '.$attrs['section'].')); ';
778
779 $output .= '?>';
780
781 return $output;
782 }
783
784
785 /*======================================================================*\
786 Function: _compile_include_tag
787 Purpose: Compile {include ...} tag
788 \*======================================================================*/
789 function _compile_include_tag($tag_args)
790 {
791 $attrs = $this->_parse_attrs($tag_args);
792
793 if (empty($attrs['file'])) {
794 $this->_syntax_error("missing 'file' attribute in include tag");
795 } else
796 $attrs['file'] = $this->_dequote($attrs['file']);
797
798 if (count($attrs) > 1) {
799 $include_func_name = uniqid("_include_");
800 $include_file_name = $this->compile_dir.'/'.$attrs['file'];
801
802 foreach ($attrs as $arg_name => $arg_value) {
803 if ($arg_name == 'file') continue;
804 if (is_bool($arg_value))
805 $arg_value = $arg_value ? 'true' : 'false';
806 $arg_list[] = "'$arg_name' => $arg_value";
807 }
808
809 return "<?php " .
810 "if (!function_exists('$include_func_name')) {\n".
811 " function $include_func_name(\$file_name, \$def_vars, \$include_vars)\n" .
812 " {\n" .
813 " extract(\$def_vars);\n" .
814 " extract(\$include_vars);\n" .
815 " include \"\$file_name.php\";\n" .
816 " }\n" .
817 "}\n" .
818 "$include_func_name(\"$include_file_name\", get_defined_vars(), array(".implode(',', (array)$arg_list)."));\n?>";
819 } else
820 return '<?php include "'.$this->compile_dir.'/'.$attrs['file'].'.php"; ?>';
821 }
822
823
824 /*======================================================================*\
825 Function: _compile_section_start
826 Purpose: Compile {section ...} tag
827 \*======================================================================*/
828 function _compile_section_start($tag_args)
829 {
830 $attrs = $this->_parse_attrs($tag_args);
831
832 $output = "<?php ";
833 $section_name = $attrs['name'];
834 if (empty($section_name)) {
835 $this->_syntax_error("missing section name");
836 }
837
838 $output .= "unset(\$_sections[$section_name]);\n";
839 $section_props = "\$_sections[$section_name]['properties']";
840
841 foreach ($attrs as $attr_name => $attr_value) {
842 switch ($attr_name) {
843 case 'loop':
844 $output .= "{$section_props}['loop'] = is_array($attr_value) ? count($attr_value) : $attr_value;\n";
845 break;
846
847 case 'show':
848 if (is_bool($attr_value))
849 $attr_value = $attr_value ? 'true' : 'false';
850 $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
851 break;
852
853 default:
854 $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
855 break;
856 }
857 }
858
859 if (isset($attrs['loop'])) {
860 $loop_check_code = "{$section_props}['loop'] > 0 && ";
861 } else {
862 $output .= "{$section_props}['loop'] = 1;\n";
863 }
864
865 if (isset($attrs['show'])) {
866 $show_check_code = "{$section_props}['show'] && ";
867 } else {
868 $output .= "{$section_props}['show'] = {$section_props}['loop'] > 0;\n";
869 }
870
871 $output .= "if ($loop_check_code $show_check_code true): ";
872
873 $output .= "
874 for ({$section_props}['index'] = 0;
875 {$section_props}['index'] < {$section_props}['loop'];
876 {$section_props}['index']++):\n";
877 $output .= "{$section_props}['rownum'] = {$section_props}['index'] + 1;\n";
878
879 $output .= "?>";
880
881 return $output;
882 }
883
884
885 /*======================================================================*\
886 Function: _compile_if_tag
887 Purpose: Compile {if ...} tag
888 \*======================================================================*/
889 function _compile_if_tag($tag_args, $elseif = false)
890 {
891 /* Tokenize args for 'if' tag. */
892 preg_match_all('/(?:
893 "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | # match all double quoted strings allowed escaped double quotes
894 \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | # match all single quoted strings allowed escaped single quotes
895 [()] | # match parentheses
896 [^"\'\s()]+ # match any other token that is not any of the above
897 )/x', $tag_args, $match);
898 $tokens = $match[0];
899
900 $this->_parse_vars_props($tokens);
901
902 $is_arg_stack = array();
903
904 for ($i = 0; $i < count($tokens); $i++) {
905 $token = &$tokens[$i];
906 switch ($token) {
907 case 'eq':
908 $token = '==';
909 break;
910
911 case 'ne':
912 case 'neq':
913 $token = '!=';
914 break;
915
916 case 'lt':
917 $token = '<';
918 break;
919
920 case 'le':
921 case 'lte':
922 $token = '<=';
923 break;
924
925 case 'gt':
926 $token = '>';
927 break;
928
929 case 'ge':
930 case 'gte':
931 $token = '>=';
932 break;
933
934 case 'and':
935 $token = '&&';
936 break;
937
938 case 'or':
939 $token = '||';
940 break;
941
942 case 'not':
943 $token = '!';
944 break;
945
946 case 'mod':
947 $token = '%';
948 break;
949
950 case '(':
951 array_push($is_arg_stack, $i);
952 break;
953
954 case 'is':
955 /* If last token was a ')', we operate on the parenthesized
956 expression. The start of the expression is on the stack.
957 Otherwise, we operate on the last encountered token. */
958 if ($tokens[$i-1] == ')')
959 $is_arg_start = array_pop($is_arg_stack);
960 else
961 $is_arg_start = $i-1;
962 /* Construct the argument for 'is' expression, so it knows
963 what to operate on. */
964 $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
965
966 /* Pass all tokens from next one until the end to the
967 'is' expression parsing function. The function will
968 return modified tokens, where the first one is the result
969 of the 'is' expression and the rest are the tokens it
970 didn't touch. */
971 $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
972
973 /* Replace the old tokens with the new ones. */
974 array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
975
976 /* Adjust argument start so that it won't change from the
977 current position for the next iteration. */
978 $i = $is_arg_start;
979 break;
980 }
981 }
982
983 if ($elseif)
984 return '<?php elseif ('.implode(' ', $tokens).'): ?>';
985 else
986 return '<?php if ('.implode(' ', $tokens).'): ?>';
987 }
988
989 function _parse_is_expr($is_arg, $tokens)
990 {
991 $expr_end = 0;
992
993 if (($first_token = array_shift($tokens)) == 'not') {
994 $negate_expr = true;
995 $expr_type = array_shift($tokens);
996 } else
997 $expr_type = $first_token;
998
999 switch ($expr_type) {
1000 case 'even':
1001 if ($tokens[$expr_end] == 'by') {
1002 $expr_end++;
1003 $expr_arg = $tokens[$expr_end++];
1004 $expr = "!(($is_arg / $expr_arg) % $expr_arg)";
1005 }
1006 else
1007 $expr = "!($is_arg % 2)";
1008 break;
1009
1010 case 'odd':
1011 if ($tokens[$expr_end] == 'by') {
1012 $expr_end++;
1013 $expr_arg = $tokens[$expr_end++];
1014 $expr = "(($is_arg / $expr_arg) % $expr_arg)";
1015 }
1016 else
1017 $expr = "($is_arg % 2)";
1018 break;
1019
1020 case 'div':
1021 if ($tokens[$expr_end] == 'by') {
1022 $expr_end++;
1023 $expr_arg = $tokens[$expr_end++];
1024 $expr = "!($is_arg % $expr_arg)";
1025 } else {
1026 $this->_syntax_error("expecting 'by' after 'div'");
1027 }
1028 break;
1029
1030 default:
1031 $this->_syntax_error("unknown 'is' expression - '$expr_type'");
1032 break;
1033 }
1034
1035 if ($negate_expr) {
1036 $expr = "!($expr)";
1037 }
1038
1039 array_splice($tokens, 0, $expr_end, $expr);
1040
1041 return $tokens;
1042 }
1043
1044
1045 /*======================================================================*\
1046 Function: _parse_attrs
1047 Purpose: Parse attribute string
1048 \*======================================================================*/
1049 function _parse_attrs($tag_args, $quote = true)
1050 {
1051 /* Tokenize tag attributes. */
1052 preg_match_all('/(?:"[^"\\\\]*(?:\\\\.[^"\\\\]*)*" |
1053 \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | (?>[^"\'=\s]+)
1054 )+ |
1055 [=]
1056 /x', $tag_args, $match);
1057 $tokens = $match[0];
1058 $var_delims = array('$', '#', '%');
1059
1060 $attrs = array();
1061 /* Parse state:
1062 0 - expecting attribute name
1063 1 - expecting '='
1064 2 - expecting attribute value (not '=') */
1065 $state = 0;
1066
1067 foreach ($tokens as $token) {
1068 switch ($state) {
1069 case 0:
1070 /* If the token is a valid identifier, we set attribute name
1071 and go to state 1. */
1072 if (preg_match('!^\w+$!', $token)) {
1073 $attr_name = $token;
1074 $state = 1;
1075 } else
1076 $this->_syntax_error("invalid attribute name - '$token'");
1077 break;
1078
1079 case 1:
1080 /* If the token is '=', then we go to state 2. */
1081 if ($token == '=') {
1082 $state = 2;
1083 } else
1084 $this->_syntax_error("expecting '=' after attribute name");
1085 break;
1086
1087 case 2:
1088 /* If token is not '=', we set the attribute value and go to
1089 state 0. */
1090 if ($token != '=') {
1091 /* We booleanize the token if it's a non-quoted possible
1092 boolean value. */
1093 if (preg_match('!^(on|yes|true)$!', $token))
1094 $token = true;
1095 else if (preg_match('!^(off|no|false)$!', $token))
1096 $token = false;
1097 /* If the token is not variable (doesn't start with
1098 '$', '#', or '%') and not enclosed in single or
1099 double quotes we single-quote it. */
1100 else if ($quote && !in_array($token{0}, $var_delims) &&
1101 !(($token{0} == '"' || $token[0] == "'") &&
1102 $token{strlen($token)-1} == $token{0}))
1103 $token = "'".$token."'";
1104
1105 $attrs[$attr_name] = $token;
1106 $state = 0;
1107 } else
1108 $this->_syntax_error("'=' cannot be an attribute value");
1109 break;
1110 }
1111 }
1112
1113 $this->_parse_vars_props($attrs);
1114
1115 return $attrs;
1116 }
1117
1118
1119 /*======================================================================*\
1120 Function: _preg_grep
1121 Purpose: Emulate PHP's preg_grep()
1122 \*======================================================================*/
1123 function _preg_grep($pattern, $array)
1124 {
1125 $result = array();
1126
1127 foreach ($array as $key => $entry) {
1128 if (preg_match($pattern, $entry))
1129 $result[$key] = $entry;
1130 }
1131
1132 return $result;
1133 }
1134
1135 function _parse_vars_props(&$tokens)
1136 {
1137 $qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
1138
1139 /* preg_grep() was fixed to return keys properly in 4.0.4 and later. To
1140 allow people to use older versions of PHP we emulate preg_grep() and
1141 use the version check to see what function to call. */
1142 if (strnatcmp(PHP_VERSION, '4.0.4') >= 0) {
1143 /* RA: $var_exprs = preg_grep('!^\$(\w+/)*\w+(?>\.\w+)*(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens); */
1144 $var_exprs = preg_grep('!^\$(\w+[/\.])*\w+(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1145 $conf_var_exprs = preg_grep('!^#(\w+)#(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1146 $sect_prop_exprs = preg_grep('!^%\w+\.\w+%(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1147 } else {
1148 /* RA: $var_exprs = $this->_preg_grep('!^\$(\w+/)*\w+(?>\.\w+)*(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens); */
1149 $var_exprs = $this->_preg_grep('!^\$(\w+[/\.])*\w+(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1150 $conf_var_exprs = $this->_preg_grep('!^#(\w+)#(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1151 $sect_prop_exprs = $this->_preg_grep('!^%\w+\.\w+%(?>\|@?\w+(:(?>' . $qstr_regexp . '|[^|]+))*)*$!', $tokens);
1152 }
1153
1154 if (count($var_exprs)) {
1155 foreach ($var_exprs as $expr_index => $var_expr) {
1156 $tokens[$expr_index] = $this->_parse_var($var_expr);
1157 }
1158 }
1159
1160 if (count($conf_var_exprs)) {
1161 foreach ($conf_var_exprs as $expr_index => $var_expr) {
1162 $tokens[$expr_index] = $this->_parse_conf_var($var_expr);
1163 }
1164 }
1165
1166 if (count($sect_prop_exprs)) {
1167 foreach ($sect_prop_exprs as $expr_index => $section_prop_expr) {
1168 $tokens[$expr_index] = $this->_parse_section_prop($section_prop_expr);
1169 }
1170 }
1171 }
1172
1173 function _parse_var($var_expr)
1174 {
1175 list($var_ref, $modifiers) = explode('|', substr($var_expr, 1), 2);
1176
1177 $sections = explode('/', $var_ref);
1178 $props = explode('.', array_pop($sections));
1179 $var_name = array_shift($props);
1180
1181 $output = "\$$var_name";
1182
1183 foreach ($sections as $section) {
1184 // RA:
1185 $tmp = explode('.', $section);
1186 $sec = array_shift($tmp);
1187 foreach ($tmp as $t) {
1188 $output .= "['$t']";
1189 }
1190 $output .= "[\$_sections['$sec']['properties']['index']]";
1191 }
1192 foreach ($props as $prop) {
1193 $output .= "['$prop']";
1194 }
1195
1196 $this->_parse_modifiers($output, $modifiers);
1197
1198 return $output;
1199 }
1200
1201 function _parse_conf_var($conf_var_expr)
1202 {
1203 list($var_ref, $modifiers) = explode('|', $conf_var_expr, 2);
1204
1205 $var_name = substr($var_ref, 1, -1);
1206
1207 $output = "\$_config['$var_name']";
1208
1209 $this->_parse_modifiers($output, $modifiers);
1210
1211 return $output;
1212 }
1213
1214 function _parse_section_prop($section_prop_expr)
1215 {
1216 list($var_ref, $modifiers) = explode('|', $section_prop_expr, 2);
1217
1218 preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
1219 $section_name = $match[1];
1220 $prop_name = $match[2];
1221
1222 $output = "\$_sections['$section_name']['properties']['$prop_name']";
1223
1224 $this->_parse_modifiers($output, $modifiers);
1225
1226 return $output;
1227 }
1228
1229 function _parse_modifiers(&$output, $modifier_string)
1230 {
1231 $qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
1232 preg_match_all('!\|(@?\w+)((?>:(?:'. $qstr_regexp . '|[^|]+))*)!', '|' . $modifier_string, $match);
1233 list(, $modifiers, $modifier_arg_strings) = $match;
1234
1235 for ($i = 0; $i < count($modifiers); $i++) {
1236 $modifier_name = $modifiers[$i];
1237 preg_match_all('!:(' . $qstr_regexp . '|[^:]+)!', $modifier_arg_strings[$i], $match);
1238 $modifier_args = $match[1];
1239
1240 if ($modifier_name{0} == '@') {
1241 $map_array = 'false';
1242 $modifier_name = substr($modifier_name, 1);
1243 } else
1244 $map_array = 'true';
1245
1246 /*
1247 * First we lookup the modifier function name in the registered
1248 * modifiers table.
1249 */
1250 $mod_func_name = $this->custom_mods[$modifier_name];
1251
1252 /*
1253 * If we don't find that modifier there, we assume it's just a PHP
1254 * function name.
1255 */
1256 if (!isset($mod_func_name))
1257 $mod_func_name = $modifier_name;
1258
1259 if (!function_exists($mod_func_name)) {
1260 $this->_syntax_error("modifier '$modifier_name' is not implemented", E_USER_WARNING);
1261 continue;
1262 }
1263
1264 $this->_parse_vars_props($modifier_args);
1265
1266 if (count($modifier_args) > 0)
1267 $modifier_args = ', '.implode(', ', $modifier_args);
1268 else
1269 $modifier_args = '';
1270
1271 $output = "_smarty_mod_handler('$mod_func_name', $map_array, $output$modifier_args)";
1272 }
1273 }
1274
1275
1276 /*======================================================================*\
1277 Function: _dequote
1278 Purpose: Remove starting and ending quotes from the string
1279 \*======================================================================*/
1280 function _dequote($string)
1281 {
1282 if (($string{0} == "'" || $string{0} == '"') &&
1283 $string{strlen($string)-1} == $string{0})
1284 return substr($string, 1, -1);
1285 else
1286 return $string;
1287 }
1288
1289
1290 /*======================================================================*\
1291 Function: _read_file()
1292 Purpose: read in a file
1293 \*======================================================================*/
1294
1295 function _read_file($filename)
1296
1297 {
1298 if (!($fd = fopen($filename, 'r'))) {
1299 $this->_set_error_msg("problem reading '$filename.'");
1300 return false;
1301 }
1302 flock($fd, LOCK_SH);
1303 $contents = fread($fd, filesize($filename));
1304 fclose($fd);
1305 return $contents;
1306 }
1307
1308 /*======================================================================*\
1309 Function: _write_file()
1310 Purpose: write out a file
1311 \*======================================================================*/
1312
1313 function _write_file($filename, $contents, $create_dirs = false)
1314 {
1315 if($create_dirs)
1316 $this->_create_dir_structure(dirname($filename));
1317
1318 if (!($fd = fopen($filename, 'a'))) {
1319 $this->_set_error_msg("problem writing '$filename.'");
1320 return false;
1321 }
1322 flock($fd, LOCK_EX);
1323
1324 $fd_safe = fopen($filename, 'w');
1325
1326 fwrite($fd_safe, $contents);
1327 fclose($fd_safe);
1328 fclose($fd);
1329
1330 return true;
1331 }
1332
1333
1334 /*======================================================================*\
1335 Function: _clear_tpl_cache_dir
1336 Purpose: Clear the specified template cache
1337 \*======================================================================*/
1338 function _clear_tpl_cache_dir($cache_tpl_md5)
1339 {
1340 $cache_dir = $this->cache_dir.'/'.$cache_tpl_md5;
1341
1342 if (!is_dir($cache_dir))
1343 return false;
1344
1345 $dir_handle = opendir($cache_dir);
1346 while ($curr_dir = readdir($dir_handle)) {
1347 $cache_path_dir = $cache_dir.'/'.$curr_dir;
1348 if ($curr_dir == '.' || $curr_dir == '..' ||
1349 !is_dir($cache_path_dir))
1350 continue;
1351
1352 $dir_handle2 = opendir($cache_path_dir);
1353 while ($curr_file = readdir($dir_handle2)) {
1354 if ($curr_file == '.' || $curr_file == '..')
1355 continue;
1356
1357 $cache_file = $cache_path_dir.'/'.$curr_file;
1358 if (is_file($cache_file))
1359 unlink($cache_file);
1360 }
1361 closedir($dir_handle2);
1362 @rmdir($cache_path_dir);
1363 }
1364 closedir($dir_handle);
1365 @rmdir($cache_dir);
1366
1367 return true;
1368 }
1369
1370
1371 /*======================================================================*\
1372 Function: _set_error_msg()
1373 Purpose: set the error message
1374 \*======================================================================*/
1375
1376 function _set_error_msg($error_msg)
1377 {
1378 $this->_error_msg="smarty error: $error_msg";
1379 return true;
1380 }
1381
1382 /*======================================================================*\
1383 Function: _syntax_error
1384 Purpose: display Smarty syntax error
1385 \*======================================================================*/
1386 function _syntax_error($error_msg, $error_type = E_USER_ERROR)
1387 {
1388 trigger_error("Smarty: [in " . $this->_current_file . " line " .
1389 $this->_current_line_no . "]: syntax error: $error_msg", $error_type);
1390 }
1391 }
1392
1393 /* vim: set expandtab: */
1394
1395 ?>

  ViewVC Help
Powered by ViewVC 1.1.26