1: <?php
2: /**
3: * Project: Smarty: the PHP compiling template engine
4: * File: Smarty.class.php
5: *
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 3.0 of the License, or (at your option) any later version.
10: *
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.
15: *
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/
24: * @copyright 2018 New Digital Group, Inc.
25: * @copyright 2018 Uwe Tews
26: * @author Monte Ohrt <monte at ohrt dot com>
27: * @author Uwe Tews <uwe dot tews at gmail dot com>
28: * @author Rodney Rehm
29: * @package Smarty
30: */
31: /**
32: * set SMARTY_DIR to absolute path to Smarty library files.
33: * Sets SMARTY_DIR only if user application has not already defined it.
34: */
35: if (!defined('SMARTY_DIR')) {
36: /**
37: *
38: */
39: define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
40: }
41: /**
42: * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins.
43: * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it.
44: */
45: if (!defined('SMARTY_SYSPLUGINS_DIR')) {
46: /**
47: *
48: */
49: define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DIRECTORY_SEPARATOR);
50: }
51: if (!defined('SMARTY_PLUGINS_DIR')) {
52: /**
53: *
54: */
55: define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DIRECTORY_SEPARATOR);
56: }
57: if (!defined('SMARTY_MBSTRING')) {
58: /**
59: *
60: */
61: define('SMARTY_MBSTRING', function_exists('mb_get_info'));
62: }
63: if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
64: // UTF-8 can only be done properly when mbstring is available!
65: /**
66: * @deprecated in favor of Smarty::$_CHARSET
67: */
68: define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
69: }
70: if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
71: /**
72: * @deprecated in favor of Smarty::$_DATE_FORMAT
73: */
74: define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
75: }
76: /**
77: * Load Smarty_Autoloader
78: */
79: if (!class_exists('Smarty_Autoloader')) {
80: include dirname(__FILE__) . '/bootstrap.php';
81: }
82: /**
83: * Load always needed external class files
84: */
85: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
86: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
87: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
88: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
89: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
90: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
91: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
92: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
93: require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
94:
95: /**
96: * This is the main Smarty class
97: *
98: * @package Smarty
99: *
100: * The following methods will be dynamically loaded by the extension handler when they are called.
101: * They are located in a corresponding Smarty_Internal_Method_xxxx class
102: *
103: * @method int clearAllCache(int $exp_time = null, string $type = null)
104: * @method int clearCache(string $template_name, string $cache_id = null, string $compile_id = null, int $exp_time = null, string $type = null)
105: * @method int compileAllTemplates(string $extension = '.tpl', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
106: * @method int compileAllConfig(string $extension = '.conf', bool $force_compile = false, int $time_limit = 0, $max_errors = null)
107: * @method int clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
108: */
109: class Smarty extends Smarty_Internal_TemplateBase
110: {
111: /**
112: * smarty version
113: */
114: const SMARTY_VERSION = '3.1.48';
115: /**
116: * define variable scopes
117: */
118: const SCOPE_LOCAL = 1;
119: const SCOPE_PARENT = 2;
120: const SCOPE_TPL_ROOT = 4;
121: const SCOPE_ROOT = 8;
122: const SCOPE_SMARTY = 16;
123: const SCOPE_GLOBAL = 32;
124: /**
125: * define caching modes
126: */
127: const CACHING_OFF = 0;
128: const CACHING_LIFETIME_CURRENT = 1;
129: const CACHING_LIFETIME_SAVED = 2;
130: /**
131: * define constant for clearing cache files be saved expiration dates
132: */
133: const CLEAR_EXPIRED = -1;
134: /**
135: * define compile check modes
136: */
137: const COMPILECHECK_OFF = 0;
138: const COMPILECHECK_ON = 1;
139: const COMPILECHECK_CACHEMISS = 2;
140: /**
141: * define debug modes
142: */
143: const DEBUG_OFF = 0;
144: const DEBUG_ON = 1;
145: const DEBUG_INDIVIDUAL = 2;
146: /**
147: * modes for handling of "<?php ... ?>" tags in templates.
148: */
149: const PHP_PASSTHRU = 0; //-> print tags as plain text
150: const PHP_QUOTE = 1; //-> escape tags as entities
151: const PHP_REMOVE = 2; //-> escape tags as entities
152: const PHP_ALLOW = 3; //-> escape tags as entities
153: /**
154: * filter types
155: */
156: const FILTER_POST = 'post';
157: const FILTER_PRE = 'pre';
158: const FILTER_OUTPUT = 'output';
159: const FILTER_VARIABLE = 'variable';
160: /**
161: * plugin types
162: */
163: const PLUGIN_FUNCTION = 'function';
164: const PLUGIN_BLOCK = 'block';
165: const PLUGIN_COMPILER = 'compiler';
166: const PLUGIN_MODIFIER = 'modifier';
167: const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
168:
169: /**
170: * assigned global tpl vars
171: */
172: public static $global_tpl_vars = array();
173:
174: /**
175: * Flag denoting if Multibyte String functions are available
176: */
177: public static $_MBSTRING = SMARTY_MBSTRING;
178:
179: /**
180: * The character set to adhere to (e.g. "UTF-8")
181: */
182: public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
183:
184: /**
185: * The date format to be used internally
186: * (accepts date() and strftime())
187: */
188: public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
189:
190: /**
191: * Flag denoting if PCRE should run in UTF-8 mode
192: */
193: public static $_UTF8_MODIFIER = 'u';
194:
195: /**
196: * Flag denoting if operating system is windows
197: */
198: public static $_IS_WINDOWS = false;
199:
200: /**
201: * auto literal on delimiters with whitespace
202: *
203: * @var boolean
204: */
205: public $auto_literal = true;
206:
207: /**
208: * display error on not assigned variables
209: *
210: * @var boolean
211: */
212: public $error_unassigned = false;
213:
214: /**
215: * look up relative file path in include_path
216: *
217: * @var boolean
218: */
219: public $use_include_path = false;
220:
221: /**
222: * flag if template_dir is normalized
223: *
224: * @var bool
225: */
226: public $_templateDirNormalized = false;
227:
228: /**
229: * joined template directory string used in cache keys
230: *
231: * @var string
232: */
233: public $_joined_template_dir = null;
234:
235: /**
236: * flag if config_dir is normalized
237: *
238: * @var bool
239: */
240: public $_configDirNormalized = false;
241:
242: /**
243: * joined config directory string used in cache keys
244: *
245: * @var string
246: */
247: public $_joined_config_dir = null;
248:
249: /**
250: * default template handler
251: *
252: * @var callable
253: */
254: public $default_template_handler_func = null;
255:
256: /**
257: * default config handler
258: *
259: * @var callable
260: */
261: public $default_config_handler_func = null;
262:
263: /**
264: * default plugin handler
265: *
266: * @var callable
267: */
268: public $default_plugin_handler_func = null;
269:
270: /**
271: * flag if template_dir is normalized
272: *
273: * @var bool
274: */
275: public $_compileDirNormalized = false;
276:
277: /**
278: * flag if plugins_dir is normalized
279: *
280: * @var bool
281: */
282: public $_pluginsDirNormalized = false;
283:
284: /**
285: * flag if template_dir is normalized
286: *
287: * @var bool
288: */
289: public $_cacheDirNormalized = false;
290:
291: /**
292: * force template compiling?
293: *
294: * @var boolean
295: */
296: public $force_compile = false;
297:
298: /**
299: * use sub dirs for compiled/cached files?
300: *
301: * @var boolean
302: */
303: public $use_sub_dirs = false;
304:
305: /**
306: * allow ambiguous resources (that are made unique by the resource handler)
307: *
308: * @var boolean
309: */
310: public $allow_ambiguous_resources = false;
311:
312: /**
313: * merge compiled includes
314: *
315: * @var boolean
316: */
317: public $merge_compiled_includes = false;
318:
319: /*
320: * flag for behaviour when extends: resource and {extends} tag are used simultaneous
321: * if false disable execution of {extends} in templates called by extends resource.
322: * (behaviour as versions < 3.1.28)
323: *
324: * @var boolean
325: */
326: public $extends_recursion = true;
327:
328: /**
329: * force cache file creation
330: *
331: * @var boolean
332: */
333: public $force_cache = false;
334:
335: /**
336: * template left-delimiter
337: *
338: * @var string
339: */
340: public $left_delimiter = "{";
341:
342: /**
343: * template right-delimiter
344: *
345: * @var string
346: */
347: public $right_delimiter = "}";
348:
349: /**
350: * array of strings which shall be treated as literal by compiler
351: *
352: * @var array string
353: */
354: public $literals = array();
355:
356: /**
357: * class name
358: * This should be instance of Smarty_Security.
359: *
360: * @var string
361: * @see Smarty_Security
362: */
363: public $security_class = 'Smarty_Security';
364:
365: /**
366: * implementation of security class
367: *
368: * @var Smarty_Security
369: */
370: public $security_policy = null;
371:
372: /**
373: * controls handling of PHP-blocks
374: *
375: * @var integer
376: */
377: public $php_handling = self::PHP_PASSTHRU;
378:
379: /**
380: * controls if the php template file resource is allowed
381: *
382: * @var bool
383: */
384: public $allow_php_templates = false;
385:
386: /**
387: * debug mode
388: * Setting this to true enables the debug-console.
389: *
390: * @var boolean
391: */
392: public $debugging = false;
393:
394: /**
395: * This determines if debugging is enable-able from the browser.
396: * <ul>
397: * <li>NONE => no debugging control allowed</li>
398: * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
399: * </ul>
400: *
401: * @var string
402: */
403: public $debugging_ctrl = 'NONE';
404:
405: /**
406: * Name of debugging URL-param.
407: * Only used when $debugging_ctrl is set to 'URL'.
408: * The name of the URL-parameter that activates debugging.
409: *
410: * @var string
411: */
412: public $smarty_debug_id = 'SMARTY_DEBUG';
413:
414: /**
415: * Path of debug template.
416: *
417: * @var string
418: */
419: public $debug_tpl = null;
420:
421: /**
422: * When set, smarty uses this value as error_reporting-level.
423: *
424: * @var int
425: */
426: public $error_reporting = null;
427:
428: /**
429: * Controls whether variables with the same name overwrite each other.
430: *
431: * @var boolean
432: */
433: public $config_overwrite = true;
434:
435: /**
436: * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
437: *
438: * @var boolean
439: */
440: public $config_booleanize = true;
441:
442: /**
443: * Controls whether hidden config sections/vars are read from the file.
444: *
445: * @var boolean
446: */
447: public $config_read_hidden = false;
448:
449: /**
450: * locking concurrent compiles
451: *
452: * @var boolean
453: */
454: public $compile_locking = true;
455:
456: /**
457: * Controls whether cache resources should use locking mechanism
458: *
459: * @var boolean
460: */
461: public $cache_locking = false;
462:
463: /**
464: * seconds to wait for acquiring a lock before ignoring the write lock
465: *
466: * @var float
467: */
468: public $locking_timeout = 10;
469:
470: /**
471: * resource type used if none given
472: * Must be an valid key of $registered_resources.
473: *
474: * @var string
475: */
476: public $default_resource_type = 'file';
477:
478: /**
479: * caching type
480: * Must be an element of $cache_resource_types.
481: *
482: * @var string
483: */
484: public $caching_type = 'file';
485:
486: /**
487: * config type
488: *
489: * @var string
490: */
491: public $default_config_type = 'file';
492:
493: /**
494: * check If-Modified-Since headers
495: *
496: * @var boolean
497: */
498: public $cache_modified_check = false;
499:
500: /**
501: * registered plugins
502: *
503: * @var array
504: */
505: public $registered_plugins = array();
506:
507: /**
508: * registered objects
509: *
510: * @var array
511: */
512: public $registered_objects = array();
513:
514: /**
515: * registered classes
516: *
517: * @var array
518: */
519: public $registered_classes = array();
520:
521: /**
522: * registered filters
523: *
524: * @var array
525: */
526: public $registered_filters = array();
527:
528: /**
529: * registered resources
530: *
531: * @var array
532: */
533: public $registered_resources = array();
534:
535: /**
536: * registered cache resources
537: *
538: * @var array
539: */
540: public $registered_cache_resources = array();
541:
542: /**
543: * autoload filter
544: *
545: * @var array
546: */
547: public $autoload_filters = array();
548:
549: /**
550: * default modifier
551: *
552: * @var array
553: */
554: public $default_modifiers = array();
555:
556: /**
557: * autoescape variable output
558: *
559: * @var boolean
560: */
561: public $escape_html = false;
562:
563: /**
564: * start time for execution time calculation
565: *
566: * @var int
567: */
568: public $start_time = 0;
569:
570: /**
571: * required by the compiler for BC
572: *
573: * @var string
574: */
575: public $_current_file = null;
576:
577: /**
578: * internal flag to enable parser debugging
579: *
580: * @var bool
581: */
582: public $_parserdebug = false;
583:
584: /**
585: * This object type (Smarty = 1, template = 2, data = 4)
586: *
587: * @var int
588: */
589: public $_objType = 1;
590:
591: /**
592: * Debug object
593: *
594: * @var Smarty_Internal_Debug
595: */
596: public $_debug = null;
597:
598: /**
599: * template directory
600: *
601: * @var array
602: */
603: protected $template_dir = array('./templates/');
604:
605: /**
606: * flags for normalized template directory entries
607: *
608: * @var array
609: */
610: protected $_processedTemplateDir = array();
611:
612: /**
613: * config directory
614: *
615: * @var array
616: */
617: protected $config_dir = array('./configs/');
618:
619: /**
620: * flags for normalized template directory entries
621: *
622: * @var array
623: */
624: protected $_processedConfigDir = array();
625:
626: /**
627: * compile directory
628: *
629: * @var string
630: */
631: protected $compile_dir = './templates_c/';
632:
633: /**
634: * plugins directory
635: *
636: * @var array
637: */
638: protected $plugins_dir = array();
639:
640: /**
641: * cache directory
642: *
643: * @var string
644: */
645: protected $cache_dir = './cache/';
646:
647: /**
648: * removed properties
649: *
650: * @var string[]
651: */
652: protected $obsoleteProperties = array(
653: 'resource_caching', 'template_resource_caching', 'direct_access_security',
654: '_dir_perms', '_file_perms', 'plugin_search_order',
655: 'inheritance_merge_compiled_includes', 'resource_cache_mode',
656: );
657:
658: /**
659: * List of private properties which will call getter/setter on a direct access
660: *
661: * @var string[]
662: */
663: protected $accessMap = array(
664: 'template_dir' => 'TemplateDir', 'config_dir' => 'ConfigDir',
665: 'plugins_dir' => 'PluginsDir', 'compile_dir' => 'CompileDir',
666: 'cache_dir' => 'CacheDir',
667: );
668:
669: /**
670: * Initialize new Smarty object
671: */
672: public function __construct()
673: {
674: $this->_clearTemplateCache();
675: parent::__construct();
676: if (is_callable('mb_internal_encoding')) {
677: mb_internal_encoding(Smarty::$_CHARSET);
678: }
679: $this->start_time = microtime(true);
680: if (isset($_SERVER[ 'SCRIPT_NAME' ])) {
681: Smarty::$global_tpl_vars[ 'SCRIPT_NAME' ] = new Smarty_Variable($_SERVER[ 'SCRIPT_NAME' ]);
682: }
683: // Check if we're running on windows
684: Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
685: // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
686: if (Smarty::$_CHARSET !== 'UTF-8') {
687: Smarty::$_UTF8_MODIFIER = '';
688: }
689: }
690:
691: /**
692: * Enable error handler to mute expected messages
693: *
694: * @return boolean
695: * @deprecated
696: */
697: public static function muteExpectedErrors()
698: {
699: return Smarty_Internal_ErrorHandler::muteExpectedErrors();
700: }
701:
702: /**
703: * Disable error handler muting expected messages
704: *
705: * @deprecated
706: */
707: public static function unmuteExpectedErrors()
708: {
709: restore_error_handler();
710: }
711:
712: /**
713: * Check if a template resource exists
714: *
715: * @param string $resource_name template name
716: *
717: * @return bool status
718: * @throws \SmartyException
719: */
720: public function templateExists($resource_name)
721: {
722: // create source object
723: $source = Smarty_Template_Source::load(null, $this, $resource_name);
724: return $source->exists;
725: }
726:
727: /**
728: * Loads security class and enables security
729: *
730: * @param string|Smarty_Security $security_class if a string is used, it must be class-name
731: *
732: * @return Smarty current Smarty instance for chaining
733: * @throws \SmartyException
734: */
735: public function enableSecurity($security_class = null)
736: {
737: Smarty_Security::enableSecurity($this, $security_class);
738: return $this;
739: }
740:
741: /**
742: * Disable security
743: *
744: * @return Smarty current Smarty instance for chaining
745: */
746: public function disableSecurity()
747: {
748: $this->security_policy = null;
749: return $this;
750: }
751:
752: /**
753: * Add template directory(s)
754: *
755: * @param string|array $template_dir directory(s) of template sources
756: * @param string $key of the array element to assign the template dir to
757: * @param bool $isConfig true for config_dir
758: *
759: * @return Smarty current Smarty instance for chaining
760: */
761: public function addTemplateDir($template_dir, $key = null, $isConfig = false)
762: {
763: if ($isConfig) {
764: $processed = &$this->_processedConfigDir;
765: $dir = &$this->config_dir;
766: $this->_configDirNormalized = false;
767: } else {
768: $processed = &$this->_processedTemplateDir;
769: $dir = &$this->template_dir;
770: $this->_templateDirNormalized = false;
771: }
772: if (is_array($template_dir)) {
773: foreach ($template_dir as $k => $v) {
774: if (is_int($k)) {
775: // indexes are not merged but appended
776: $dir[] = $v;
777: } else {
778: // string indexes are overridden
779: $dir[ $k ] = $v;
780: unset($processed[ $key ]);
781: }
782: }
783: } else {
784: if ($key !== null) {
785: // override directory at specified index
786: $dir[ $key ] = $template_dir;
787: unset($processed[ $key ]);
788: } else {
789: // append new directory
790: $dir[] = $template_dir;
791: }
792: }
793: return $this;
794: }
795:
796: /**
797: * Get template directories
798: *
799: * @param mixed $index index of directory to get, null to get all
800: * @param bool $isConfig true for config_dir
801: *
802: * @return array|string list of template directories, or directory of $index
803: */
804: public function getTemplateDir($index = null, $isConfig = false)
805: {
806: if ($isConfig) {
807: $dir = &$this->config_dir;
808: } else {
809: $dir = &$this->template_dir;
810: }
811: if ($isConfig ? !$this->_configDirNormalized : !$this->_templateDirNormalized) {
812: $this->_normalizeTemplateConfig($isConfig);
813: }
814: if ($index !== null) {
815: return isset($dir[ $index ]) ? $dir[ $index ] : null;
816: }
817: return $dir;
818: }
819:
820: /**
821: * Set template directory
822: *
823: * @param string|array $template_dir directory(s) of template sources
824: * @param bool $isConfig true for config_dir
825: *
826: * @return \Smarty current Smarty instance for chaining
827: */
828: public function setTemplateDir($template_dir, $isConfig = false)
829: {
830: if ($isConfig) {
831: $this->config_dir = array();
832: $this->_processedConfigDir = array();
833: } else {
834: $this->template_dir = array();
835: $this->_processedTemplateDir = array();
836: }
837: $this->addTemplateDir($template_dir, null, $isConfig);
838: return $this;
839: }
840:
841: /**
842: * Add config directory(s)
843: *
844: * @param string|array $config_dir directory(s) of config sources
845: * @param mixed $key key of the array element to assign the config dir to
846: *
847: * @return Smarty current Smarty instance for chaining
848: */
849: public function addConfigDir($config_dir, $key = null)
850: {
851: return $this->addTemplateDir($config_dir, $key, true);
852: }
853:
854: /**
855: * Get config directory
856: *
857: * @param mixed $index index of directory to get, null to get all
858: *
859: * @return array configuration directory
860: */
861: public function getConfigDir($index = null)
862: {
863: return $this->getTemplateDir($index, true);
864: }
865:
866: /**
867: * Set config directory
868: *
869: * @param $config_dir
870: *
871: * @return Smarty current Smarty instance for chaining
872: */
873: public function setConfigDir($config_dir)
874: {
875: return $this->setTemplateDir($config_dir, true);
876: }
877:
878: /**
879: * Adds directory of plugin files
880: *
881: * @param null|array|string $plugins_dir
882: *
883: * @return Smarty current Smarty instance for chaining
884: */
885: public function addPluginsDir($plugins_dir)
886: {
887: if (empty($this->plugins_dir)) {
888: $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
889: }
890: $this->plugins_dir = array_merge($this->plugins_dir, (array)$plugins_dir);
891: $this->_pluginsDirNormalized = false;
892: return $this;
893: }
894:
895: /**
896: * Get plugin directories
897: *
898: * @return array list of plugin directories
899: */
900: public function getPluginsDir()
901: {
902: if (empty($this->plugins_dir)) {
903: $this->plugins_dir[] = SMARTY_PLUGINS_DIR;
904: $this->_pluginsDirNormalized = false;
905: }
906: if (!$this->_pluginsDirNormalized) {
907: if (!is_array($this->plugins_dir)) {
908: $this->plugins_dir = (array)$this->plugins_dir;
909: }
910: foreach ($this->plugins_dir as $k => $v) {
911: $this->plugins_dir[ $k ] = $this->_realpath(rtrim($v, '/\\') . DIRECTORY_SEPARATOR, true);
912: }
913: $this->_cache[ 'plugin_files' ] = array();
914: $this->_pluginsDirNormalized = true;
915: }
916: return $this->plugins_dir;
917: }
918:
919: /**
920: * Set plugins directory
921: *
922: * @param string|array $plugins_dir directory(s) of plugins
923: *
924: * @return Smarty current Smarty instance for chaining
925: */
926: public function setPluginsDir($plugins_dir)
927: {
928: $this->plugins_dir = (array)$plugins_dir;
929: $this->_pluginsDirNormalized = false;
930: return $this;
931: }
932:
933: /**
934: * Get compiled directory
935: *
936: * @return string path to compiled templates
937: */
938: public function getCompileDir()
939: {
940: if (!$this->_compileDirNormalized) {
941: $this->_normalizeDir('compile_dir', $this->compile_dir);
942: $this->_compileDirNormalized = true;
943: }
944: return $this->compile_dir;
945: }
946:
947: /**
948: *
949: * @param string $compile_dir directory to store compiled templates in
950: *
951: * @return Smarty current Smarty instance for chaining
952: */
953: public function setCompileDir($compile_dir)
954: {
955: $this->_normalizeDir('compile_dir', $compile_dir);
956: $this->_compileDirNormalized = true;
957: return $this;
958: }
959:
960: /**
961: * Get cache directory
962: *
963: * @return string path of cache directory
964: */
965: public function getCacheDir()
966: {
967: if (!$this->_cacheDirNormalized) {
968: $this->_normalizeDir('cache_dir', $this->cache_dir);
969: $this->_cacheDirNormalized = true;
970: }
971: return $this->cache_dir;
972: }
973:
974: /**
975: * Set cache directory
976: *
977: * @param string $cache_dir directory to store cached templates in
978: *
979: * @return Smarty current Smarty instance for chaining
980: */
981: public function setCacheDir($cache_dir)
982: {
983: $this->_normalizeDir('cache_dir', $cache_dir);
984: $this->_cacheDirNormalized = true;
985: return $this;
986: }
987:
988: /**
989: * creates a template object
990: *
991: * @param string $template the resource handle of the template file
992: * @param mixed $cache_id cache id to be used with this template
993: * @param mixed $compile_id compile id to be used with this template
994: * @param object $parent next higher level of Smarty variables
995: * @param boolean $do_clone flag is Smarty object shall be cloned
996: *
997: * @return \Smarty_Internal_Template template object
998: * @throws \SmartyException
999: */
1000: public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true)
1001: {
1002: if ($cache_id !== null && (is_object($cache_id) || is_array($cache_id))) {
1003: $parent = $cache_id;
1004: $cache_id = null;
1005: }
1006: if ($parent !== null && is_array($parent)) {
1007: $data = $parent;
1008: $parent = null;
1009: } else {
1010: $data = null;
1011: }
1012: if (!$this->_templateDirNormalized) {
1013: $this->_normalizeTemplateConfig(false);
1014: }
1015: $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
1016: $tpl = null;
1017: if ($this->caching && isset(Smarty_Internal_Template::$isCacheTplObj[ $_templateId ])) {
1018: $tpl = $do_clone ? clone Smarty_Internal_Template::$isCacheTplObj[ $_templateId ] :
1019: Smarty_Internal_Template::$isCacheTplObj[ $_templateId ];
1020: $tpl->inheritance = null;
1021: $tpl->tpl_vars = $tpl->config_vars = array();
1022: } elseif (!$do_clone && isset(Smarty_Internal_Template::$tplObjCache[ $_templateId ])) {
1023: $tpl = clone Smarty_Internal_Template::$tplObjCache[ $_templateId ];
1024: $tpl->inheritance = null;
1025: $tpl->tpl_vars = $tpl->config_vars = array();
1026: } else {
1027: /* @var Smarty_Internal_Template $tpl */
1028: $tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null);
1029: $tpl->templateId = $_templateId;
1030: }
1031: if ($do_clone) {
1032: $tpl->smarty = clone $tpl->smarty;
1033: }
1034: $tpl->parent = $parent ? $parent : $this;
1035: // fill data if present
1036: if (!empty($data) && is_array($data)) {
1037: // set up variable values
1038: foreach ($data as $_key => $_val) {
1039: $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val);
1040: }
1041: }
1042: if ($this->debugging || $this->debugging_ctrl === 'URL') {
1043: $tpl->smarty->_debug = new Smarty_Internal_Debug();
1044: // check URL debugging control
1045: if (!$this->debugging && $this->debugging_ctrl === 'URL') {
1046: $tpl->smarty->_debug->debugUrl($tpl->smarty);
1047: }
1048: }
1049: return $tpl;
1050: }
1051:
1052: /**
1053: * Takes unknown classes and loads plugin files for them
1054: * class name format: Smarty_PluginType_PluginName
1055: * plugin filename format: plugintype.pluginname.php
1056: *
1057: * @param string $plugin_name class plugin name to load
1058: * @param bool $check check if already loaded
1059: *
1060: * @return string |boolean filepath of loaded file or false
1061: * @throws \SmartyException
1062: */
1063: public function loadPlugin($plugin_name, $check = true)
1064: {
1065: return $this->ext->loadPlugin->loadPlugin($this, $plugin_name, $check);
1066: }
1067:
1068: /**
1069: * Get unique template id
1070: *
1071: * @param string $template_name
1072: * @param null|mixed $cache_id
1073: * @param null|mixed $compile_id
1074: * @param null $caching
1075: * @param \Smarty_Internal_Template $template
1076: *
1077: * @return string
1078: * @throws \SmartyException
1079: */
1080: public function _getTemplateId(
1081: $template_name,
1082: $cache_id = null,
1083: $compile_id = null,
1084: $caching = null,
1085: Smarty_Internal_Template $template = null
1086: ) {
1087: $template_name = (strpos($template_name, ':') === false) ? "{$this->default_resource_type}:{$template_name}" :
1088: $template_name;
1089: $cache_id = $cache_id === null ? $this->cache_id : $cache_id;
1090: $compile_id = $compile_id === null ? $this->compile_id : $compile_id;
1091: $caching = (int)($caching === null ? $this->caching : $caching);
1092: if ((isset($template) && strpos($template_name, ':.') !== false) || $this->allow_ambiguous_resources) {
1093: $_templateId =
1094: Smarty_Resource::getUniqueTemplateName((isset($template) ? $template : $this), $template_name) .
1095: "#{$cache_id}#{$compile_id}#{$caching}";
1096: } else {
1097: $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}";
1098: }
1099: if (isset($_templateId[ 150 ])) {
1100: $_templateId = sha1($_templateId);
1101: }
1102: return $_templateId;
1103: }
1104:
1105: /**
1106: * Normalize path
1107: * - remove /./ and /../
1108: * - make it absolute if required
1109: *
1110: * @param string $path file path
1111: * @param bool $realpath if true - convert to absolute
1112: * false - convert to relative
1113: * null - keep as it is but
1114: * remove /./ /../
1115: *
1116: * @return string
1117: */
1118: public function _realpath($path, $realpath = null)
1119: {
1120: $nds = array('/' => '\\', '\\' => '/');
1121: preg_match(
1122: '%^(?<root>(?:[[:alpha:]]:[\\\\/]|/|[\\\\]{2}[[:alpha:]]+|[[:print:]]{2,}:[/]{2}|[\\\\])?)(?<path>(.*))$%u',
1123: $path,
1124: $parts
1125: );
1126: $path = $parts[ 'path' ];
1127: if ($parts[ 'root' ] === '\\') {
1128: $parts[ 'root' ] = substr(getcwd(), 0, 2) . $parts[ 'root' ];
1129: } else {
1130: if ($realpath !== null && !$parts[ 'root' ]) {
1131: $path = getcwd() . DIRECTORY_SEPARATOR . $path;
1132: }
1133: }
1134: // normalize DIRECTORY_SEPARATOR
1135: $path = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $path);
1136: $parts[ 'root' ] = str_replace($nds[ DIRECTORY_SEPARATOR ], DIRECTORY_SEPARATOR, $parts[ 'root' ]);
1137: do {
1138: $path = preg_replace(
1139: array('#[\\\\/]{2}#', '#[\\\\/][.][\\\\/]#', '#[\\\\/]([^\\\\/.]+)[\\\\/][.][.][\\\\/]#'),
1140: DIRECTORY_SEPARATOR,
1141: $path,
1142: -1,
1143: $count
1144: );
1145: } while ($count > 0);
1146: return $realpath !== false ? $parts[ 'root' ] . $path : str_ireplace(getcwd(), '.', $parts[ 'root' ] . $path);
1147: }
1148:
1149: /**
1150: * Empty template objects cache
1151: */
1152: public function _clearTemplateCache()
1153: {
1154: Smarty_Internal_Template::$isCacheTplObj = array();
1155: Smarty_Internal_Template::$tplObjCache = array();
1156: }
1157:
1158: /**
1159: * @param boolean $use_sub_dirs
1160: */
1161: public function setUseSubDirs($use_sub_dirs)
1162: {
1163: $this->use_sub_dirs = $use_sub_dirs;
1164: }
1165:
1166: /**
1167: * @param int $error_reporting
1168: */
1169: public function setErrorReporting($error_reporting)
1170: {
1171: $this->error_reporting = $error_reporting;
1172: }
1173:
1174: /**
1175: * @param boolean $escape_html
1176: */
1177: public function setEscapeHtml($escape_html)
1178: {
1179: $this->escape_html = $escape_html;
1180: }
1181:
1182: /**
1183: * Return auto_literal flag
1184: *
1185: * @return boolean
1186: */
1187: public function getAutoLiteral()
1188: {
1189: return $this->auto_literal;
1190: }
1191:
1192: /**
1193: * Set auto_literal flag
1194: *
1195: * @param boolean $auto_literal
1196: */
1197: public function setAutoLiteral($auto_literal = true)
1198: {
1199: $this->auto_literal = $auto_literal;
1200: }
1201:
1202: /**
1203: * @param boolean $force_compile
1204: */
1205: public function setForceCompile($force_compile)
1206: {
1207: $this->force_compile = $force_compile;
1208: }
1209:
1210: /**
1211: * @param boolean $merge_compiled_includes
1212: */
1213: public function setMergeCompiledIncludes($merge_compiled_includes)
1214: {
1215: $this->merge_compiled_includes = $merge_compiled_includes;
1216: }
1217:
1218: /**
1219: * Get left delimiter
1220: *
1221: * @return string
1222: */
1223: public function getLeftDelimiter()
1224: {
1225: return $this->left_delimiter;
1226: }
1227:
1228: /**
1229: * Set left delimiter
1230: *
1231: * @param string $left_delimiter
1232: */
1233: public function setLeftDelimiter($left_delimiter)
1234: {
1235: $this->left_delimiter = $left_delimiter;
1236: }
1237:
1238: /**
1239: * Get right delimiter
1240: *
1241: * @return string $right_delimiter
1242: */
1243: public function getRightDelimiter()
1244: {
1245: return $this->right_delimiter;
1246: }
1247:
1248: /**
1249: * Set right delimiter
1250: *
1251: * @param string
1252: */
1253: public function setRightDelimiter($right_delimiter)
1254: {
1255: $this->right_delimiter = $right_delimiter;
1256: }
1257:
1258: /**
1259: * @param boolean $debugging
1260: */
1261: public function setDebugging($debugging)
1262: {
1263: $this->debugging = $debugging;
1264: }
1265:
1266: /**
1267: * @param boolean $config_overwrite
1268: */
1269: public function setConfigOverwrite($config_overwrite)
1270: {
1271: $this->config_overwrite = $config_overwrite;
1272: }
1273:
1274: /**
1275: * @param boolean $config_booleanize
1276: */
1277: public function setConfigBooleanize($config_booleanize)
1278: {
1279: $this->config_booleanize = $config_booleanize;
1280: }
1281:
1282: /**
1283: * @param boolean $config_read_hidden
1284: */
1285: public function setConfigReadHidden($config_read_hidden)
1286: {
1287: $this->config_read_hidden = $config_read_hidden;
1288: }
1289:
1290: /**
1291: * @param boolean $compile_locking
1292: */
1293: public function setCompileLocking($compile_locking)
1294: {
1295: $this->compile_locking = $compile_locking;
1296: }
1297:
1298: /**
1299: * @param string $default_resource_type
1300: */
1301: public function setDefaultResourceType($default_resource_type)
1302: {
1303: $this->default_resource_type = $default_resource_type;
1304: }
1305:
1306: /**
1307: * @param string $caching_type
1308: */
1309: public function setCachingType($caching_type)
1310: {
1311: $this->caching_type = $caching_type;
1312: }
1313:
1314: /**
1315: * Test install
1316: *
1317: * @param null $errors
1318: */
1319: public function testInstall(&$errors = null)
1320: {
1321: Smarty_Internal_TestInstall::testInstall($this, $errors);
1322: }
1323:
1324: /**
1325: * Get Smarty object
1326: *
1327: * @return Smarty
1328: */
1329: public function _getSmartyObj()
1330: {
1331: return $this;
1332: }
1333:
1334: /**
1335: * <<magic>> Generic getter.
1336: * Calls the appropriate getter function.
1337: * Issues an E_USER_NOTICE if no valid getter is found.
1338: *
1339: * @param string $name property name
1340: *
1341: * @return mixed
1342: */
1343: public function __get($name)
1344: {
1345: if (isset($this->accessMap[ $name ])) {
1346: $method = 'get' . $this->accessMap[ $name ];
1347: return $this->{$method}();
1348: } elseif (isset($this->_cache[ $name ])) {
1349: return $this->_cache[ $name ];
1350: } elseif (in_array($name, $this->obsoleteProperties)) {
1351: return null;
1352: } else {
1353: trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1354: }
1355: return null;
1356: }
1357:
1358: /**
1359: * <<magic>> Generic setter.
1360: * Calls the appropriate setter function.
1361: * Issues an E_USER_NOTICE if no valid setter is found.
1362: *
1363: * @param string $name property name
1364: * @param mixed $value parameter passed to setter
1365: *
1366: */
1367: public function __set($name, $value)
1368: {
1369: if (isset($this->accessMap[ $name ])) {
1370: $method = 'set' . $this->accessMap[ $name ];
1371: $this->{$method}($value);
1372: } elseif (in_array($name, $this->obsoleteProperties)) {
1373: return;
1374: } elseif (is_object($value) && method_exists($value, $name)) {
1375: $this->$name = $value;
1376: } else {
1377: trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE);
1378: }
1379: }
1380:
1381: /**
1382: * Normalize and set directory string
1383: *
1384: * @param string $dirName cache_dir or compile_dir
1385: * @param string $dir filepath of folder
1386: */
1387: private function _normalizeDir($dirName, $dir)
1388: {
1389: $this->{$dirName} = $this->_realpath(rtrim($dir, "/\\") . DIRECTORY_SEPARATOR, true);
1390: if (class_exists('Smarty_Internal_ErrorHandler', false)) {
1391: if (!isset(Smarty_Internal_ErrorHandler::$mutedDirectories[ $this->{$dirName} ])) {
1392: Smarty_Internal_ErrorHandler::$mutedDirectories[ $this->{$dirName} ] = null;
1393: }
1394: }
1395: }
1396:
1397: /**
1398: * Normalize template_dir or config_dir
1399: *
1400: * @param bool $isConfig true for config_dir
1401: */
1402: private function _normalizeTemplateConfig($isConfig)
1403: {
1404: if ($isConfig) {
1405: $processed = &$this->_processedConfigDir;
1406: $dir = &$this->config_dir;
1407: } else {
1408: $processed = &$this->_processedTemplateDir;
1409: $dir = &$this->template_dir;
1410: }
1411: if (!is_array($dir)) {
1412: $dir = (array)$dir;
1413: }
1414: foreach ($dir as $k => $v) {
1415: if (!isset($processed[ $k ])) {
1416: $dir[ $k ] = $v = $this->_realpath(rtrim($v, "/\\") . DIRECTORY_SEPARATOR, true);
1417: $processed[ $k ] = true;
1418: }
1419: }
1420: $isConfig ? $this->_configDirNormalized = true : $this->_templateDirNormalized = true;
1421: $isConfig ? $this->_joined_config_dir = join('#', $this->config_dir) :
1422: $this->_joined_template_dir = join('#', $this->template_dir);
1423: }
1424: }
1425: