fix last commit
[GitHub/Stricted/Domain-Control-Panel.git] / lib / api / smarty / Smarty.class.php
CommitLineData
2aa91ff2
S
1<?php
2/**
3 * Project: Smarty: the PHP compiling template engine
4 * File: Smarty.class.php
ccd27f54 5 *
2aa91ff2
S
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
ccd27f54 10 *
2aa91ff2
S
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
ccd27f54 15 *
2aa91ff2
S
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * For questions, help, comments, discussion, etc., please join the
20 * Smarty mailing list. Send a blank e-mail to
21 * smarty-discussion-subscribe@googlegroups.com
22 *
23 * @link http://www.smarty.net/
ccd27f54
S
24 * @copyright 2015 New Digital Group, Inc.
25 * @copyright 2015 Uwe Tews
2aa91ff2
S
26 * @author Monte Ohrt <monte at ohrt dot com>
27 * @author Uwe Tews
28 * @author Rodney Rehm
29 * @package Smarty
ccd27f54 30 * @version 3.1-DEV
2aa91ff2
S
31 */
32
33/**
34 * define shorthand directory separator constant
35 */
36if (!defined('DS')) {
37 define('DS', DIRECTORY_SEPARATOR);
38}
39
40/**
41 * set SMARTY_DIR to absolute path to Smarty library files.
42 * Sets SMARTY_DIR only if user application has not already defined it.
43 */
44if (!defined('SMARTY_DIR')) {
45 define('SMARTY_DIR', dirname(__FILE__) . DS);
46}
47
48/**
49 * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
50 * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
51 */
52if (!defined('SMARTY_SYSPLUGINS_DIR')) {
53 define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS);
54}
55if (!defined('SMARTY_PLUGINS_DIR')) {
56 define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS);
57}
58if (!defined('SMARTY_MBSTRING')) {
ccd27f54 59 define('SMARTY_MBSTRING', function_exists('mb_get_info'));
2aa91ff2
S
60}
61if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
62 // UTF-8 can only be done properly when mbstring is available!
63 /**
64 * @deprecated in favor of Smarty::$_CHARSET
65 */
66 define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
67}
68if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
69 /**
70 * @deprecated in favor of Smarty::$_DATE_FORMAT
71 */
72 define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
73}
74
75/**
ccd27f54
S
76 * Try loading the Smmarty_Internal_Data class
77 * If we fail we must load Smarty's autoloader.
78 * Otherwise we may have a global autoloader like Composer
2aa91ff2 79 */
ccd27f54
S
80if (!class_exists('Smarty_Autoloader', false)) {
81 if (!class_exists('Smarty_Internal_Data', true)) {
82 require_once 'Autoloader.php';
83 Smarty_Autoloader::registerBC();
2aa91ff2 84 }
2aa91ff2
S
85}
86
87/**
88 * Load always needed external class files
89 */
ccd27f54
S
90
91if (!class_exists('Smarty_Internal_Data', false)) {
92 require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
93}
94require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
95require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
96require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
97require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
98require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
2aa91ff2
S
99
100/**
101 * This is the main Smarty class
102 *
103 * @package Smarty
104 */
105class Smarty extends Smarty_Internal_TemplateBase
106{
107 /**#@+
108 * constant definitions
109 */
110
111 /**
112 * smarty version
113 */
f2fc2a18 114 const SMARTY_VERSION = '3.1.22';
2aa91ff2
S
115
116 /**
117 * define variable scopes
118 */
119 const SCOPE_LOCAL = 0;
120 const SCOPE_PARENT = 1;
121 const SCOPE_ROOT = 2;
122 const SCOPE_GLOBAL = 3;
123 /**
124 * define caching modes
125 */
126 const CACHING_OFF = 0;
127 const CACHING_LIFETIME_CURRENT = 1;
128 const CACHING_LIFETIME_SAVED = 2;
129 /**
130 * define constant for clearing cache files be saved expiration datees
131 */
132 const CLEAR_EXPIRED = - 1;
133
134 /**
135 * define compile check modes
136 */
137 const COMPILECHECK_OFF = 0;
138 const COMPILECHECK_ON = 1;
139 const COMPILECHECK_CACHEMISS = 2;
ccd27f54
S
140
141 /**
142 * define debug modes
143 */
144 const DEBUG_OFF = 0;
145 const DEBUG_ON = 1;
146 const DEBUG_INDIVIDUAL = 2;
2aa91ff2
S
147 /**
148 * modes for handling of "<?php ... ?>" tags in templates.
149 */
150 const PHP_PASSTHRU = 0; //-> print tags as plain text
151 const PHP_QUOTE = 1; //-> escape tags as entities
152 const PHP_REMOVE = 2; //-> escape tags as entities
153 const PHP_ALLOW = 3; //-> escape tags as entities
154 /**
155 * filter types
156 */
157 const FILTER_POST = 'post';
158 const FILTER_PRE = 'pre';
159 const FILTER_OUTPUT = 'output';
160 const FILTER_VARIABLE = 'variable';
161 /**
162 * plugin types
163 */
164 const PLUGIN_FUNCTION = 'function';
165 const PLUGIN_BLOCK = 'block';
166 const PLUGIN_COMPILER = 'compiler';
167 const PLUGIN_MODIFIER = 'modifier';
168 const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
169
170 /**#@-*/
171
172 /**
173 * assigned global tpl vars
174 */
175 public static $global_tpl_vars = array();
176
177 /**
178 * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors()
179 */
180 public static $_previous_error_handler = null;
181 /**
182 * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
183 */
ccd27f54 184 public static $_muted_directories = array('./templates_c/' => null, './cache/' => null);
2aa91ff2
S
185 /**
186 * Flag denoting if Multibyte String functions are available
187 */
188 public static $_MBSTRING = SMARTY_MBSTRING;
189 /**
190 * The character set to adhere to (e.g. "UTF-8")
191 */
192 public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
193 /**
194 * The date format to be used internally
195 * (accepts date() and strftime())
196 */
197 public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
198 /**
199 * Flag denoting if PCRE should run in UTF-8 mode
200 */
201 public static $_UTF8_MODIFIER = 'u';
202
203 /**
204 * Flag denoting if operating system is windows
205 */
206 public static $_IS_WINDOWS = false;
207
208 /**#@+
209 * variables
210 */
211
212 /**
213 * auto literal on delimiters with whitspace
214 *
215 * @var boolean
216 */
217 public $auto_literal = true;
218 /**
219 * display error on not assigned variables
220 *
221 * @var boolean
222 */
223 public $error_unassigned = false;
224 /**
225 * look up relative filepaths in include_path
226 *
227 * @var boolean
228 */
229 public $use_include_path = false;
230 /**
231 * template directory
232 *
233 * @var array
234 */
ccd27f54 235 private $template_dir = array('./templates/');
2aa91ff2
S
236 /**
237 * joined template directory string used in cache keys
238 *
239 * @var string
240 */
ccd27f54 241 public $joined_template_dir = './templates/';
2aa91ff2
S
242 /**
243 * joined config directory string used in cache keys
244 *
245 * @var string
246 */
ccd27f54 247 public $joined_config_dir = './configs/';
2aa91ff2
S
248 /**
249 * default template handler
250 *
251 * @var callable
252 */
253 public $default_template_handler_func = null;
254 /**
255 * default config handler
256 *
257 * @var callable
258 */
259 public $default_config_handler_func = null;
260 /**
261 * default plugin handler
262 *
263 * @var callable
264 */
265 public $default_plugin_handler_func = null;
266 /**
267 * compile directory
268 *
269 * @var string
270 */
ccd27f54 271 private $compile_dir = './templates_c/';
2aa91ff2
S
272 /**
273 * plugins directory
274 *
275 * @var array
276 */
ccd27f54 277 private $plugins_dir = null;
2aa91ff2
S
278 /**
279 * cache directory
280 *
281 * @var string
282 */
ccd27f54 283 private $cache_dir = './cache/';
2aa91ff2
S
284 /**
285 * config directory
286 *
287 * @var array
288 */
ccd27f54 289 private $config_dir = array('./configs/');
2aa91ff2
S
290 /**
291 * force template compiling?
292 *
293 * @var boolean
294 */
295 public $force_compile = false;
296 /**
297 * check template for modifications?
298 *
299 * @var boolean
300 */
301 public $compile_check = true;
302 /**
303 * use sub dirs for compiled/cached files?
304 *
305 * @var boolean
306 */
307 public $use_sub_dirs = false;
308 /**
309 * allow ambiguous resources (that are made unique by the resource handler)
310 *
311 * @var boolean
312 */
313 public $allow_ambiguous_resources = false;
2aa91ff2
S
314 /**
315 * merge compiled includes
316 *
317 * @var boolean
318 */
319 public $merge_compiled_includes = false;
320 /**
321 * template inheritance merge compiled includes
322 *
323 * @var boolean
324 */
325 public $inheritance_merge_compiled_includes = true;
2aa91ff2
S
326 /**
327 * force cache file creation
328 *
329 * @var boolean
330 */
331 public $force_cache = false;
2aa91ff2
S
332 /**
333 * template left-delimiter
334 *
335 * @var string
336 */
337 public $left_delimiter = "{";
338 /**
339 * template right-delimiter
340 *
341 * @var string
342 */
343 public $right_delimiter = "}";
344 /**#@+
345 * security
346 */
347 /**
348 * class name
349 * This should be instance of Smarty_Security.
350 *
351 * @var string
352 * @see Smarty_Security
353 */
354 public $security_class = 'Smarty_Security';
355 /**
356 * implementation of security class
357 *
358 * @var Smarty_Security
359 */
360 public $security_policy = null;
361 /**
362 * controls handling of PHP-blocks
363 *
364 * @var integer
365 */
366 public $php_handling = self::PHP_PASSTHRU;
367 /**
368 * controls if the php template file resource is allowed
369 *
370 * @var bool
371 */
372 public $allow_php_templates = false;
373 /**
374 * Should compiled-templates be prevented from being called directly?
375 * {@internal
376 * Currently used by Smarty_Internal_Template only.
377 * }}
378 *
379 * @var boolean
380 */
381 public $direct_access_security = true;
382 /**#@-*/
383 /**
384 * debug mode
385 * Setting this to true enables the debug-console.
386 *
387 * @var boolean
388 */
389 public $debugging = false;
390 /**
391 * This determines if debugging is enable-able from the browser.
392 * <ul>
393 * <li>NONE => no debugging control allowed</li>
394 * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
395 * </ul>
396 *
397 * @var string
398 */
399 public $debugging_ctrl = 'NONE';
400 /**
401 * Name of debugging URL-param.
402 * Only used when $debugging_ctrl is set to 'URL'.
403 * The name of the URL-parameter that activates debugging.
404 *
ccd27f54 405 * @var string
2aa91ff2
S
406 */
407 public $smarty_debug_id = 'SMARTY_DEBUG';
408 /**
409 * Path of debug template.
410 *
411 * @var string
412 */
413 public $debug_tpl = null;
414 /**
415 * When set, smarty uses this value as error_reporting-level.
416 *
417 * @var int
418 */
419 public $error_reporting = null;
ccd27f54 420
2aa91ff2
S
421 /**
422 * Internal flag for getTags()
423 *
424 * @var boolean
425 */
426 public $get_used_tags = false;
427
428 /**#@+
429 * config var settings
430 */
431
432 /**
433 * Controls whether variables with the same name overwrite each other.
434 *
435 * @var boolean
436 */
437 public $config_overwrite = true;
438 /**
439 * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
440 *
441 * @var boolean
442 */
443 public $config_booleanize = true;
444 /**
445 * Controls whether hidden config sections/vars are read from the file.
446 *
447 * @var boolean
448 */
449 public $config_read_hidden = false;
450
451 /**#@-*/
452
453 /**#@+
454 * resource locking
455 */
456
457 /**
458 * locking concurrent compiles
459 *
460 * @var boolean
461 */
462 public $compile_locking = true;
463 /**
464 * Controls whether cache resources should emply locking mechanism
465 *
466 * @var boolean
467 */
468 public $cache_locking = false;
469 /**
470 * seconds to wait for acquiring a lock before ignoring the write lock
471 *
472 * @var float
473 */
474 public $locking_timeout = 10;
475
476 /**#@-*/
477
2aa91ff2
S
478 /**
479 * resource type used if none given
480 * Must be an valid key of $registered_resources.
481 *
482 * @var string
483 */
484 public $default_resource_type = 'file';
485 /**
486 * caching type
487 * Must be an element of $cache_resource_types.
488 *
489 * @var string
490 */
491 public $caching_type = 'file';
492 /**
493 * internal config properties
494 *
495 * @var array
496 */
497 public $properties = array();
498 /**
499 * config type
500 *
501 * @var string
502 */
503 public $default_config_type = 'file';
ccd27f54
S
504 /**
505 * cached template objects
506 *
507 * @var array
508 */
509 public $source_objects = array();
2aa91ff2
S
510 /**
511 * cached template objects
512 *
513 * @var array
514 */
515 public $template_objects = array();
ccd27f54
S
516
517 /**
518 * enable resource caching
519 *
520 * @var bool
521 */
522 public $resource_caching = false;
523 /**
524 * enable template resource caching
525 *
526 * @var bool
527 */
528 public $template_resource_caching = true;
2aa91ff2
S
529 /**
530 * check If-Modified-Since headers
531 *
532 * @var boolean
533 */
534 public $cache_modified_check = false;
535 /**
536 * registered plugins
537 *
538 * @var array
539 */
540 public $registered_plugins = array();
541 /**
542 * plugin search order
543 *
544 * @var array
545 */
546 public $plugin_search_order = array('function', 'block', 'compiler', 'class');
547 /**
548 * registered objects
549 *
550 * @var array
551 */
552 public $registered_objects = array();
553 /**
554 * registered classes
555 *
556 * @var array
557 */
558 public $registered_classes = array();
559 /**
560 * registered filters
561 *
562 * @var array
563 */
564 public $registered_filters = array();
565 /**
566 * registered resources
567 *
568 * @var array
569 */
570 public $registered_resources = array();
571 /**
572 * resource handler cache
573 *
574 * @var array
575 */
576 public $_resource_handlers = array();
577 /**
578 * registered cache resources
579 *
580 * @var array
581 */
582 public $registered_cache_resources = array();
583 /**
584 * cache resource handler cache
585 *
586 * @var array
587 */
588 public $_cacheresource_handlers = array();
589 /**
590 * autoload filter
591 *
592 * @var array
593 */
594 public $autoload_filters = array();
595 /**
596 * default modifier
597 *
598 * @var array
599 */
600 public $default_modifiers = array();
601 /**
602 * autoescape variable output
603 *
604 * @var boolean
605 */
606 public $escape_html = false;
607 /**
608 * global internal smarty vars
609 *
610 * @var array
611 */
612 public static $_smarty_vars = array();
613 /**
614 * start time for execution time calculation
615 *
616 * @var int
617 */
618 public $start_time = 0;
619 /**
620 * default file permissions
621 *
622 * @var int
623 */
624 public $_file_perms = 0644;
625 /**
626 * default dir permissions
627 *
628 * @var int
629 */
630 public $_dir_perms = 0771;
631 /**
632 * block tag hierarchy
633 *
634 * @var array
635 */
636 public $_tag_stack = array();
2aa91ff2
S
637 /**
638 * required by the compiler for BC
639 *
640 * @var string
641 */
642 public $_current_file = null;
643 /**
644 * internal flag to enable parser debugging
645 *
646 * @var bool
647 */
648 public $_parserdebug = false;
2aa91ff2
S
649
650 /**
651 * Cache of is_file results of loadPlugin()
ccd27f54 652 *
2aa91ff2
S
653 * @var array
654 */
ccd27f54 655 public $_is_file_cache = array();
2aa91ff2
S
656
657 /**#@-*/
658
659 /**
660 * Initialize new Smarty object
661
662 */
663 public function __construct()
664 {
2aa91ff2
S
665 if (is_callable('mb_internal_encoding')) {
666 mb_internal_encoding(Smarty::$_CHARSET);
667 }
668 $this->start_time = microtime(true);
ccd27f54
S
669 // check default dirs for overloading
670 if ($this->template_dir[0] !== './templates/' || isset($this->template_dir[1])) {
671 $this->setTemplateDir($this->template_dir);
672 }
673 if ($this->config_dir[0] !== './configs/' || isset($this->config_dir[1])) {
674 $this->setConfigDir($this->config_dir);
675 }
676 if ($this->compile_dir !== './templates_c/') {
677 unset(self::$_muted_directories['./templates_c/']);
678 $this->setCompileDir($this->compile_dir);
679 }
680 if ($this->cache_dir !== './cache/') {
681 unset(self::$_muted_directories['./cache/']);
682 $this->setCacheDir($this->cache_dir);
683 }
684 if (isset($this->plugins_dir)) {
685 $this->setPluginsDir($this->plugins_dir);
686 } else {
687 $this->setPluginsDir(SMARTY_PLUGINS_DIR);
688 }
2aa91ff2
S
689
690 $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl';
691 if (isset($_SERVER['SCRIPT_NAME'])) {
ccd27f54 692 Smarty::$global_tpl_vars['SCRIPT_NAME'] = new Smarty_Variable($_SERVER['SCRIPT_NAME']);
2aa91ff2 693 }
2aa91ff2 694
ccd27f54
S
695 // Check if we're running on windows
696 Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
2aa91ff2 697
ccd27f54
S
698 // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
699 if (Smarty::$_CHARSET !== 'UTF-8') {
700 Smarty::$_UTF8_MODIFIER = '';
701 }
2aa91ff2
S
702 }
703
704 /**
ccd27f54 705 * fetches a rendered Smarty template
2aa91ff2 706 *
ccd27f54
S
707 * @param string $template the resource handle of the template file or template object
708 * @param mixed $cache_id cache id to be used with this template
709 * @param mixed $compile_id compile id to be used with this template
710 * @param object $parent next higher level of Smarty variables
711 * @param bool $display true: display, false: fetch
712 * @param bool $merge_tpl_vars not used - left for BC
713 * @param bool $no_output_filter not used - left for BC
2aa91ff2 714 *
ccd27f54
S
715 * @throws Exception
716 * @throws SmartyException
717 * @return string rendered template output
2aa91ff2 718 */
ccd27f54 719 public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
2aa91ff2 720 {
ccd27f54
S
721 if ($cache_id !== null && is_object($cache_id)) {
722 $parent = $cache_id;
723 $cache_id = null;
724 }
725 if ($parent === null) {
726 $parent = $this;
2aa91ff2 727 }
ccd27f54
S
728 // get template object
729 $_template = is_object($template) ? $template : $this->createTemplate($template, $cache_id, $compile_id, $parent, false);
730 // set caching in template object
731 $_template->caching = $this->caching;
732 // fetch template content
733 return $_template->render(true, false, $display);
2aa91ff2
S
734 }
735
736 /**
ccd27f54 737 * displays a Smarty template
2aa91ff2 738 *
ccd27f54
S
739 * @param string $template the resource handle of the template file or template object
740 * @param mixed $cache_id cache id to be used with this template
741 * @param mixed $compile_id compile id to be used with this template
742 * @param object $parent next higher level of Smarty variables
2aa91ff2 743 */
ccd27f54 744 public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
2aa91ff2 745 {
ccd27f54
S
746 // display template
747 $this->fetch($template, $cache_id, $compile_id, $parent, true);
2aa91ff2
S
748 }
749
750 /**
751 * Check if a template resource exists
752 *
753 * @param string $resource_name template name
754 *
755 * @return boolean status
756 */
757 public function templateExists($resource_name)
758 {
759 // create template object
760 $save = $this->template_objects;
761 $tpl = new $this->template_class($resource_name, $this);
762 // check if it does exists
763 $result = $tpl->source->exists;
764 $this->template_objects = $save;
765
766 return $result;
767 }
768
769 /**
770 * Returns a single or all global variables
771 *
772 * @param string $varname variable name or null
773 *
774 * @return string variable value or or array of variables
775 */
776 public function getGlobal($varname = null)
777 {
778 if (isset($varname)) {
779 if (isset(self::$global_tpl_vars[$varname])) {
780 return self::$global_tpl_vars[$varname]->value;
781 } else {
782 return '';
783 }
784 } else {
785 $_result = array();
786 foreach (self::$global_tpl_vars AS $key => $var) {
787 $_result[$key] = $var->value;
788 }
789
790 return $_result;
791 }
792 }
793
794 /**
795 * Empty cache folder
796 *
797 * @param integer $exp_time expiration time
798 * @param string $type resource type
799 *
800 * @return integer number of cache files deleted
801 */
802 public function clearAllCache($exp_time = null, $type = null)
803 {
804 // load cache resource and call clearAll
805 $_cache_resource = Smarty_CacheResource::load($this, $type);
806 Smarty_CacheResource::invalidLoadedCache($this);
807
808 return $_cache_resource->clearAll($this, $exp_time);
809 }
810
811 /**
812 * Empty cache for a specific template
813 *
814 * @param string $template_name template name
815 * @param string $cache_id cache id
816 * @param string $compile_id compile id
817 * @param integer $exp_time expiration time
818 * @param string $type resource type
819 *
820 * @return integer number of cache files deleted
821 */
822 public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
823 {
824 // load cache resource and call clear
825 $_cache_resource = Smarty_CacheResource::load($this, $type);
826 Smarty_CacheResource::invalidLoadedCache($this);
827
828 return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
829 }
830
831 /**
832 * Loads security class and enables security
833 *
834 * @param string|Smarty_Security $security_class if a string is used, it must be class-name
835 *
836 * @return Smarty current Smarty instance for chaining
837 * @throws SmartyException when an invalid class name is provided
838 */
839 public function enableSecurity($security_class = null)
840 {
841 if ($security_class instanceof Smarty_Security) {
842 $this->security_policy = $security_class;
843
844 return $this;
845 } elseif (is_object($security_class)) {
846 throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security.");
847 }
848 if ($security_class == null) {
849 $security_class = $this->security_class;
850 }
851 if (!class_exists($security_class)) {
852 throw new SmartyException("Security class '$security_class' is not defined");
853 } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) {
854 throw new SmartyException("Class '$security_class' must extend Smarty_Security.");
855 } else {
856 $this->security_policy = new $security_class($this);
857 }
858
859 return $this;
860 }
861
862 /**
863 * Disable security
864 *
865 * @return Smarty current Smarty instance for chaining
866 */
867 public function disableSecurity()
868 {
869 $this->security_policy = null;
870
871 return $this;
872 }
873
874 /**
875 * Set template directory
876 *
877 * @param string|array $template_dir directory(s) of template sources
878 *
879 * @return Smarty current Smarty instance for chaining
880 */
881 public function setTemplateDir($template_dir)
882 {
883 $this->template_dir = array();
884 foreach ((array) $template_dir as $k => $v) {
ccd27f54 885 $this->template_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/';
2aa91ff2 886 }
ccd27f54 887 $this->joined_template_dir = join(' # ', $this->template_dir);
2aa91ff2
S
888 return $this;
889 }
890
891 /**
892 * Add template directory(s)
893 *
894 * @param string|array $template_dir directory(s) of template sources
895 * @param string $key of the array element to assign the template dir to
896 *
897 * @return Smarty current Smarty instance for chaining
898 * @throws SmartyException when the given template directory is not valid
899 */
900 public function addTemplateDir($template_dir, $key = null)
901 {
ccd27f54
S
902 $this->_addDir('template_dir', $template_dir, $key);
903 $this->joined_template_dir = join(' # ', $this->template_dir);
2aa91ff2
S
904 return $this;
905 }
906
907 /**
908 * Get template directories
909 *
910 * @param mixed $index index of directory to get, null to get all
911 *
912 * @return array|string list of template directories, or directory of $index
913 */
914 public function getTemplateDir($index = null)
915 {
916 if ($index !== null) {
917 return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null;
918 }
2aa91ff2
S
919 return (array) $this->template_dir;
920 }
921
922 /**
923 * Set config directory
924 *
925 * @param $config_dir
926 *
927 * @return Smarty current Smarty instance for chaining
928 */
929 public function setConfigDir($config_dir)
930 {
931 $this->config_dir = array();
932 foreach ((array) $config_dir as $k => $v) {
ccd27f54 933 $this->config_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/';
2aa91ff2 934 }
ccd27f54 935 $this->joined_config_dir = join(' # ', $this->config_dir);
2aa91ff2
S
936 return $this;
937 }
938
939 /**
940 * Add config directory(s)
941 *
ccd27f54
S
942 * @param string|array $config_dir directory(s) of config sources
943 * @param mixed $key key of the array element to assign the config dir to
2aa91ff2
S
944 *
945 * @return Smarty current Smarty instance for chaining
946 */
947 public function addConfigDir($config_dir, $key = null)
948 {
ccd27f54
S
949 $this->_addDir('config_dir', $config_dir, $key);
950 $this->joined_config_dir = join(' # ', $this->config_dir);
2aa91ff2
S
951 return $this;
952 }
953
954 /**
955 * Get config directory
956 *
957 * @param mixed $index index of directory to get, null to get all
958 *
959 * @return array|string configuration directory
960 */
961 public function getConfigDir($index = null)
962 {
963 if ($index !== null) {
964 return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null;
965 }
2aa91ff2
S
966 return (array) $this->config_dir;
967 }
968
969 /**
970 * Set plugins directory
971 *
972 * @param string|array $plugins_dir directory(s) of plugins
973 *
974 * @return Smarty current Smarty instance for chaining
975 */
976 public function setPluginsDir($plugins_dir)
977 {
978 $this->plugins_dir = array();
979 foreach ((array) $plugins_dir as $k => $v) {
ccd27f54 980 $this->plugins_dir[$k] = rtrim(strtr($v, '\\', '/'), '/') . '/';
2aa91ff2 981 }
ccd27f54 982 $this->_is_file_cache = array();
2aa91ff2
S
983 return $this;
984 }
985
986 /**
987 * Adds directory of plugin files
988 *
989 * @param $plugins_dir
990 *
991 * @return Smarty current Smarty instance for chaining
992 */
993 public function addPluginsDir($plugins_dir)
994 {
ccd27f54 995 $this->_addDir('plugins_dir', $plugins_dir);
2aa91ff2 996 $this->plugins_dir = array_unique($this->plugins_dir);
ccd27f54 997 $this->_is_file_cache = array();
2aa91ff2
S
998 return $this;
999 }
1000
1001 /**
1002 * Get plugin directories
1003 *
1004 * @return array list of plugin directories
1005 */
1006 public function getPluginsDir()
1007 {
1008 return (array) $this->plugins_dir;
1009 }
1010
1011 /**
1012 * Set compile directory
1013 *
1014 * @param string $compile_dir directory to store compiled templates in
1015 *
1016 * @return Smarty current Smarty instance for chaining
1017 */
1018 public function setCompileDir($compile_dir)
1019 {
ccd27f54 1020 $this->compile_dir = rtrim(strtr($compile_dir, '\\', '/'), '/') . '/';
2aa91ff2
S
1021 if (!isset(Smarty::$_muted_directories[$this->compile_dir])) {
1022 Smarty::$_muted_directories[$this->compile_dir] = null;
1023 }
1024
1025 return $this;
1026 }
1027
1028 /**
1029 * Get compiled directory
1030 *
1031 * @return string path to compiled templates
1032 */
1033 public function getCompileDir()
1034 {
1035 return $this->compile_dir;
1036 }
1037
1038 /**
1039 * Set cache directory
1040 *
1041 * @param string $cache_dir directory to store cached templates in
1042 *
1043 * @return Smarty current Smarty instance for chaining
1044 */
1045 public function setCacheDir($cache_dir)
1046 {
ccd27f54 1047 $this->cache_dir = rtrim(strtr($cache_dir, '\\', '/'), '/') . '/';
2aa91ff2
S
1048 if (!isset(Smarty::$_muted_directories[$this->cache_dir])) {
1049 Smarty::$_muted_directories[$this->cache_dir] = null;
1050 }
1051
1052 return $this;
1053 }
1054
1055 /**
1056 * Get cache directory
1057 *
1058 * @return string path of cache directory
1059 */
1060 public function getCacheDir()
1061 {
1062 return $this->cache_dir;
1063 }
1064
ccd27f54
S
1065 /**
1066 * add directories to given property name
1067 *
1068 * @param string $dirName directory property name
1069 * @param string|array $dir directory string or array of strings
1070 * @param mixed $key optional key
1071 */
1072 private function _addDir($dirName, $dir, $key = null)
1073 {
1074 // make sure we're dealing with an array
1075 $this->$dirName = (array) $this->$dirName;
1076
1077 if (is_array($dir)) {
1078 foreach ($dir as $k => $v) {
1079 $v = rtrim(strtr($v, '\\', '/'), '/') . '/';
1080 if (is_int($k)) {
1081 // indexes are not merged but appended
1082 $this->{$dirName}[] = $v;
1083 } else {
1084 // string indexes are overridden
1085 $this->{$dirName}[$k] = $v;
1086 }
1087 }
1088 } else {
1089 $v = rtrim(strtr($dir, '\\', '/'), '/') . '/';
1090 if ($key !== null) {
1091 // override directory at specified index
1092 $this->{$dirName}[$key] = $v;
1093 } else {
1094 // append new directory
1095 $this->{$dirName}[] = $v;
1096 }
1097 }
1098 }
1099
2aa91ff2
S
1100 /**
1101 * Set default modifiers
1102 *
1103 * @param array|string $modifiers modifier or list of modifiers to set
1104 *
1105 * @return Smarty current Smarty instance for chaining
1106 */
1107 public function setDefaultModifiers($modifiers)
1108 {
1109 $this->default_modifiers = (array) $modifiers;
1110
1111 return $this;
1112 }
1113
1114 /**
1115 * Add default modifiers
1116 *
1117 * @param array|string $modifiers modifier or list of modifiers to add
1118 *
1119 * @return Smarty current Smarty instance for chaining
1120 */
1121 public function addDefaultModifiers($modifiers)
1122 {
1123 if (is_array($modifiers)) {
1124 $this->default_modifiers = array_merge($this->default_modifiers, $modifiers);
1125 } else {
1126 $this->default_modifiers[] = $modifiers;
1127 }
1128
1129 return $this;
1130 }
1131
1132 /**
1133 * Get default modifiers
1134 *
1135 * @return array list of default modifiers
1136 */
1137 public function getDefaultModifiers()
1138 {
1139 return $this->default_modifiers;
1140 }
1141
1142 /**
1143 * Set autoload filters
1144 *
1145 * @param array $filters filters to load automatically
ccd27f54
S
1146 * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters'
1147 * keys as the appropriate types
2aa91ff2
S
1148 *
1149 * @return Smarty current Smarty instance for chaining
1150 */
1151 public function setAutoloadFilters($filters, $type = null)
1152 {
1153 if ($type !== null) {
1154 $this->autoload_filters[$type] = (array) $filters;
1155 } else {
1156 $this->autoload_filters = (array) $filters;
1157 }
1158
1159 return $this;
1160 }
1161
1162 /**
1163 * Add autoload filters
1164 *
1165 * @param array $filters filters to load automatically
ccd27f54
S
1166 * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters'
1167 * keys as the appropriate types
2aa91ff2
S
1168 *
1169 * @return Smarty current Smarty instance for chaining
1170 */
1171 public function addAutoloadFilters($filters, $type = null)
1172 {
1173 if ($type !== null) {
1174 if (!empty($this->autoload_filters[$type])) {
1175 $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters);
1176 } else {
1177 $this->autoload_filters[$type] = (array) $filters;
1178 }
1179 } else {
1180 foreach ((array) $filters as $key => $value) {
1181 if (!empty($this->autoload_filters[$key])) {
1182 $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value);
1183 } else {
1184 $this->autoload_filters[$key] = (array) $value;
1185 }
1186 }
1187 }
1188
1189 return $this;
1190 }
1191
1192 /**
1193 * Get autoload filters
1194 *
1195 * @param string $type type of filter to get autoloads for. Defaults to all autoload filters
1196 *
ccd27f54
S
1197 * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type
1198 * was specified
2aa91ff2
S
1199 */
1200 public function getAutoloadFilters($type = null)
1201 {
1202 if ($type !== null) {
1203 return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array();
1204 }
1205
1206 return $this->autoload_filters;
1207 }
1208
1209 /**
1210 * return name of debugging template
1211 *
1212 * @return string
1213 */
1214 public function getDebugTemplate()
1215 {
1216 return $this->debug_tpl;
1217 }
1218
1219 /**
1220 * set the debug template
1221 *
1222 * @param string $tpl_name
1223 *
1224 * @return Smarty current Smarty instance for chaining
1225 * @throws SmartyException if file is not readable
1226 */
1227 public function setDebugTemplate($tpl_name)
1228 {
1229 if (!is_readable($tpl_name)) {
1230 throw new SmartyException("Unknown file '{$tpl_name}'");
1231 }
1232 $this->debug_tpl = $tpl_name;
1233
1234 return $this;
1235 }
1236
1237 /**
1238 * creates a template object
1239 *
1240 * @param string $template the resource handle of the template file
1241 * @param mixed $cache_id cache id to be used with this template
1242 * @param mixed $compile_id compile id to be used with this template
1243 * @param object $parent next higher level of Smarty variables
1244 * @param boolean $do_clone flag is Smarty object shall be cloned
1245 *
1246 * @return object template object
1247 */
1248 public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
1249 {
1250 if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
1251 $parent = $cache_id;
1252 $cache_id = null;
1253 }
1254 if ($parent !== null && is_array($parent)) {
1255 $data = $parent;
1256 $parent = null;
1257 } else {
1258 $data = null;
1259 }
ccd27f54
S
1260 $_templateId = $this->getTemplateId($template, $cache_id, $compile_id);
1261 if (isset($this->template_objects[$_templateId])) {
1262 if ($do_clone) {
2aa91ff2
S
1263 $tpl = clone $this->template_objects[$_templateId];
1264 $tpl->smarty = clone $tpl->smarty;
2aa91ff2 1265 } else {
ccd27f54 1266 $tpl = $this->template_objects[$_templateId];
2aa91ff2 1267 }
ccd27f54
S
1268 $tpl->parent = $parent;
1269 $tpl->tpl_vars = array();
1270 $tpl->config_vars = array();
2aa91ff2 1271 } else {
ccd27f54
S
1272 $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id);
1273 if ($do_clone) {
1274 $tpl->smarty = clone $tpl->smarty;
2aa91ff2 1275 }
ccd27f54 1276 $tpl->templateId = $_templateId;
2aa91ff2
S
1277 }
1278 // fill data if present
1279 if (!empty($data) && is_array($data)) {
1280 // set up variable values
1281 foreach ($data as $_key => $_val) {
ccd27f54
S
1282 $tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
1283 }
1284 }
1285 if ($this->debugging) {
1286 if ($this->debugging) {
1287 Smarty_Internal_Debug::register_template($tpl);
2aa91ff2
S
1288 }
1289 }
2aa91ff2
S
1290 return $tpl;
1291 }
1292
1293 /**
1294 * Takes unknown classes and loads plugin files for them
1295 * class name format: Smarty_PluginType_PluginName
1296 * plugin filename format: plugintype.pluginname.php
1297 *
1298 * @param string $plugin_name class plugin name to load
1299 * @param bool $check check if already loaded
1300 *
1301 * @throws SmartyException
1302 * @return string |boolean filepath of loaded file or false
1303 */
1304 public function loadPlugin($plugin_name, $check = true)
1305 {
1306 // if function or class exists, exit silently (already loaded)
1307 if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) {
1308 return true;
1309 }
1310 // Plugin name is expected to be: Smarty_[Type]_[Name]
1311 $_name_parts = explode('_', $plugin_name, 3);
1312 // class name must have three parts to be valid plugin
1313 // count($_name_parts) < 3 === !isset($_name_parts[2])
1314 if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') {
1315 throw new SmartyException("plugin {$plugin_name} is not a valid name format");
1316 }
1317 // if type is "internal", get plugin from sysplugins
1318 if (strtolower($_name_parts[1]) == 'internal') {
1319 $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php';
ccd27f54 1320 if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) {
2aa91ff2
S
1321 require_once($file);
1322 return $file;
1323 } else {
1324 return false;
1325 }
1326 }
1327 // plugin filename is expected to be: [type].[name].php
1328 $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php";
1329
1330 $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
1331
1332 // loop through plugin dirs and find the plugin
1333 foreach ($this->getPluginsDir() as $_plugin_dir) {
1334 $names = array(
1335 $_plugin_dir . $_plugin_filename,
1336 $_plugin_dir . strtolower($_plugin_filename),
1337 );
1338 foreach ($names as $file) {
ccd27f54 1339 if (isset($this->_is_file_cache[$file]) ? $this->_is_file_cache[$file] : $this->_is_file_cache[$file] = is_file($file)) {
2aa91ff2
S
1340 require_once($file);
1341 return $file;
1342 }
1343 if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
1344 // try PHP include_path
1345 if ($_stream_resolve_include_path) {
1346 $file = stream_resolve_include_path($file);
1347 } else {
1348 $file = Smarty_Internal_Get_Include_Path::getIncludePath($file);
1349 }
1350
1351 if ($file !== false) {
1352 require_once($file);
1353
1354 return $file;
1355 }
1356 }
1357 }
1358 }
1359 // no plugin loaded
1360 return false;
1361 }
1362
1363 /**
1364 * Compile all template files
1365 *
1366 * @param string $extension file extension
1367 * @param bool $force_compile force all to recompile
1368 * @param int $time_limit
1369 * @param int $max_errors
1370 *
1371 * @return integer number of template files recompiled
1372 */
1373 public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
1374 {
1375 return Smarty_Internal_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this);
1376 }
1377
1378 /**
1379 * Compile all config files
1380 *
1381 * @param string $extension file extension
1382 * @param bool $force_compile force all to recompile
1383 * @param int $time_limit
1384 * @param int $max_errors
1385 *
1386 * @return integer number of template files recompiled
1387 */
1388 public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
1389 {
1390 return Smarty_Internal_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this);
1391 }
1392
1393 /**
1394 * Delete compiled template file
1395 *
1396 * @param string $resource_name template name
1397 * @param string $compile_id compile id
1398 * @param integer $exp_time expiration time
1399 *
1400 * @return integer number of template files deleted
1401 */
1402 public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
1403 {
1404 return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this);
1405 }
1406
1407 /**
1408 * Return array of tag/attributes of all tags used by an template
1409 *
1410 * @param Smarty_Internal_Template $template
1411 *
1412 * @return array of tag/attributes
1413 */
1414 public function getTags(Smarty_Internal_Template $template)
1415 {
1416 return Smarty_Internal_Utility::getTags($template);
1417 }
1418
1419 /**
1420 * Run installation test
1421 *
1422 * @param array $errors Array to write errors into, rather than outputting them
1423 *
1424 * @return boolean true if setup is fine, false if something is wrong
1425 */
1426 public function testInstall(&$errors = null)
1427 {
ccd27f54
S
1428 return Smarty_Internal_TestInstall::testInstall($this, $errors);
1429 }
1430
1431 /**
1432 * @param boolean $compile_check
1433 */
1434 public function setCompileCheck($compile_check)
1435 {
1436 $this->compile_check = $compile_check;
1437 }
1438
1439 /**
1440 * @param boolean $use_sub_dirs
1441 */
1442 public function setUseSubDirs($use_sub_dirs)
1443 {
1444 $this->use_sub_dirs = $use_sub_dirs;
1445 }
1446
1447 /**
1448 * @param boolean $caching
1449 */
1450 public function setCaching($caching)
1451 {
1452 $this->caching = $caching;
1453 }
1454
1455 /**
1456 * @param int $cache_lifetime
1457 */
1458 public function setCacheLifetime($cache_lifetime)
1459 {
1460 $this->cache_lifetime = $cache_lifetime;
1461 }
1462
1463 /**
1464 * @param string $compile_id
1465 */
1466 public function setCompileId($compile_id)
1467 {
1468 $this->compile_id = $compile_id;
1469 }
1470
1471 /**
1472 * @param string $cache_id
1473 */
1474 public function setCacheId($cache_id)
1475 {
1476 $this->cache_id = $cache_id;
1477 }
1478
1479 /**
1480 * @param int $error_reporting
1481 */
1482 public function setErrorReporting($error_reporting)
1483 {
1484 $this->error_reporting = $error_reporting;
1485 }
1486
1487 /**
1488 * @param boolean $escape_html
1489 */
1490 public function setEscapeHtml($escape_html)
1491 {
1492 $this->escape_html = $escape_html;
1493 }
1494
1495 /**
1496 * @param boolean $auto_literal
1497 */
1498 public function setAutoLiteral($auto_literal)
1499 {
1500 $this->auto_literal = $auto_literal;
1501 }
1502
1503 /**
1504 * @param boolean $force_compile
1505 */
1506 public function setForceCompile($force_compile)
1507 {
1508 $this->force_compile = $force_compile;
1509 }
1510
1511 /**
1512 * @param boolean $merge_compiled_includes
1513 */
1514 public function setMergeCompiledIncludes($merge_compiled_includes)
1515 {
1516 $this->merge_compiled_includes = $merge_compiled_includes;
1517 }
1518
1519 /**
1520 * @param string $left_delimiter
1521 */
1522 public function setLeftDelimiter($left_delimiter)
1523 {
1524 $this->left_delimiter = $left_delimiter;
1525 }
1526
1527 /**
1528 * @param string $right_delimiter
1529 */
1530 public function setRightDelimiter($right_delimiter)
1531 {
1532 $this->right_delimiter = $right_delimiter;
1533 }
1534
1535 /**
1536 * @param boolean $debugging
1537 */
1538 public function setDebugging($debugging)
1539 {
1540 $this->debugging = $debugging;
1541 }
1542
1543 /**
1544 * @param boolean $config_overwrite
1545 */
1546 public function setConfigOverwrite($config_overwrite)
1547 {
1548 $this->config_overwrite = $config_overwrite;
1549 }
1550
1551 /**
1552 * @param boolean $config_booleanize
1553 */
1554 public function setConfigBooleanize($config_booleanize)
1555 {
1556 $this->config_booleanize = $config_booleanize;
1557 }
1558
1559 /**
1560 * @param boolean $config_read_hidden
1561 */
1562 public function setConfigReadHidden($config_read_hidden)
1563 {
1564 $this->config_read_hidden = $config_read_hidden;
1565 }
1566
1567 /**
1568 * @param boolean $compile_locking
1569 */
1570 public function setCompileLocking($compile_locking)
1571 {
1572 $this->compile_locking = $compile_locking;
1573 }
1574
1575 /**
1576 * Class destructor
1577 */
1578 public function __destruct()
1579 {
1580 // intentionally left blank
1581 }
1582
1583 /**
1584 * <<magic>> Generic getter.
1585 * Calls the appropriate getter function.
1586 * Issues an E_USER_NOTICE if no valid getter is found.
1587 *
1588 * @param string $name property name
1589 *
1590 * @return mixed
1591 */
1592 public function __get($name)
1593 {
1594 $allowed = array(
1595 'template_dir' => 'getTemplateDir',
1596 'config_dir' => 'getConfigDir',
1597 'plugins_dir' => 'getPluginsDir',
1598 'compile_dir' => 'getCompileDir',
1599 'cache_dir' => 'getCacheDir',
1600 );
1601
1602 if (isset($allowed[$name])) {
1603 return $this->{$allowed[$name]}();
1604 } else {
1605 trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1606 }
1607 }
1608
1609 /**
1610 * <<magic>> Generic setter.
1611 * Calls the appropriate setter function.
1612 * Issues an E_USER_NOTICE if no valid setter is found.
1613 *
1614 * @param string $name property name
1615 * @param mixed $value parameter passed to setter
1616 */
1617 public function __set($name, $value)
1618 {
1619 $allowed = array(
1620 'template_dir' => 'setTemplateDir',
1621 'config_dir' => 'setConfigDir',
1622 'plugins_dir' => 'setPluginsDir',
1623 'compile_dir' => 'setCompileDir',
1624 'cache_dir' => 'setCacheDir',
1625 );
1626
1627 if (isset($allowed[$name])) {
1628 $this->{$allowed[$name]}($value);
1629 } else {
1630 trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1631 }
2aa91ff2
S
1632 }
1633
1634 /**
1635 * Error Handler to mute expected messages
1636 *
1637 * @link http://php.net/set_error_handler
1638 *
1639 * @param integer $errno Error level
1640 * @param $errstr
1641 * @param $errfile
1642 * @param $errline
1643 * @param $errcontext
1644 *
1645 * @return boolean
1646 */
1647 public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext)
1648 {
1649 $_is_muted_directory = false;
1650
1651 // add the SMARTY_DIR to the list of muted directories
1652 if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) {
1653 $smarty_dir = realpath(SMARTY_DIR);
1654 if ($smarty_dir !== false) {
1655 Smarty::$_muted_directories[SMARTY_DIR] = array(
1656 'file' => $smarty_dir,
1657 'length' => strlen($smarty_dir),
1658 );
1659 }
1660 }
1661
1662 // walk the muted directories and test against $errfile
1663 foreach (Smarty::$_muted_directories as $key => &$dir) {
1664 if (!$dir) {
1665 // resolve directory and length for speedy comparisons
1666 $file = realpath($key);
1667 if ($file === false) {
1668 // this directory does not exist, remove and skip it
1669 unset(Smarty::$_muted_directories[$key]);
1670 continue;
1671 }
1672 $dir = array(
1673 'file' => $file,
1674 'length' => strlen($file),
1675 );
1676 }
1677 if (!strncmp($errfile, $dir['file'], $dir['length'])) {
1678 $_is_muted_directory = true;
1679 break;
1680 }
1681 }
1682
1683 // pass to next error handler if this error did not occur inside SMARTY_DIR
1684 // or the error was within smarty but masked to be ignored
1685 if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
1686 if (Smarty::$_previous_error_handler) {
1687 return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext);
1688 } else {
1689 return false;
1690 }
1691 }
1692 }
1693
1694 /**
1695 * Enable error handler to mute expected messages
1696 *
1697 * @return void
1698 */
1699 public static function muteExpectedErrors()
1700 {
1701 /*
1702 error muting is done because some people implemented custom error_handlers using
1703 http://php.net/set_error_handler and for some reason did not understand the following paragraph:
1704
1705 It is important to remember that the standard PHP error handler is completely bypassed for the
1706 error types specified by error_types unless the callback function returns FALSE.
1707 error_reporting() settings will have no effect and your error handler will be called regardless -
1708 however you are still able to read the current value of error_reporting and act appropriately.
1709 Of particular note is that this value will be 0 if the statement that caused the error was
1710 prepended by the @ error-control operator.
1711
1712 Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
1713 - @filemtime() is almost twice as fast as using an additional file_exists()
1714 - between file_exists() and filemtime() a possible race condition is opened,
1715 which does not exist using the simple @filemtime() approach.
1716 */
1717 $error_handler = array('Smarty', 'mutingErrorHandler');
1718 $previous = set_error_handler($error_handler);
1719
1720 // avoid dead loops
1721 if ($previous !== $error_handler) {
1722 Smarty::$_previous_error_handler = $previous;
1723 }
1724 }
1725
1726 /**
1727 * Disable error handler muting expected messages
1728 *
1729 * @return void
1730 */
1731 public static function unmuteExpectedErrors()
1732 {
1733 restore_error_handler();
1734 }
1735}