Smarty.class.php 38 KB

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