PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/include/serendipity_smarty_class.inc.php

http://github.com/s9y/Serendipity
PHP | 292 lines | 119 code | 50 blank | 123 comment | 21 complexity | 64e8446be5afd375d313c9bb1e103801 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. <?php
  2. // serendipity_smarty_class.inc.php lm 2014-12-10 Ian
  3. // define secure_dir and trusted_dirs for Serendipity_Smarty_Security_Policy class.
  4. @define('S9Y_TEMPLATE_FALLBACK', $serendipity['serendipityPath'] . $serendipity['templatePath'] . 'default');
  5. @define('S9Y_TEMPLATE_USERDEFAULT', $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template']);
  6. @define('S9Y_TEMPLATE_USERDEFAULT_BACKEND', $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template_backend']);
  7. @define('S9Y_TEMPLATE_SECUREDIR', $serendipity['serendipityPath'] . $serendipity['templatePath']);
  8. // Create a wrapper class extended from Smarty_Security - which allows access to S9Y-plugin and S9Y-template dirs
  9. class Serendipity_Smarty_Security_Policy extends Smarty_Security
  10. {
  11. // these are the allowed functions only. - default as is
  12. public $php_functions = array('isset', 'empty', 'count', 'sizeof', 'in_array', 'is_array', 'time', 'nl2br', 'class_exists', );
  13. // to disable all PHP functions
  14. #public $php_functions = null;
  15. // remove PHP tags
  16. public $php_handling = Smarty::PHP_REMOVE; // = 2
  17. // set allowed modifiers only. (default = array( 'escape', 'count' );)
  18. public $php_modifiers = array('escape', 'sprintf', 'sizeof', 'count', 'rand', 'print_r', 'str_repeat', 'nl2br', 'array_key_exists');
  19. public $allow_constants = true;
  20. public $allow_super_globals = true;
  21. // array of template directories that are considered secure. No need, as ...TemplateDir concidered secure implicitly. (unproofed)
  22. public $secure_dir = array(S9Y_TEMPLATE_SECUREDIR); // do we need this then?
  23. // actually no need, as template dirs are explicit defined as trusted_dirs. (unproofed)
  24. public $trusted_dir = array(S9Y_TEMPLATE_USERDEFAULT, S9Y_TEMPLATE_USERDEFAULT_BACKEND, S9Y_TEMPLATE_FALLBACK); // do we need this then?
  25. #public $modifiers = array(); // can be omitted, when all allowed
  26. // to test this - overwrites Serendipity_Smarty::default_modifiers and Serendipity_Smarty_Security_Policy::php_modifiers - modifier 'escape' not allowed by security setting
  27. #public $allowed_modifiers = array('escape:"htmlall"');
  28. // This allows the fetch() and include calls to pull .tpl files from any directory,
  29. // so that symlinked plugin directories outside the s9y path can be included properly.
  30. // TODO / FUTURE: If Smarty will implement a separation option to dissect fetch() from
  31. // {include} calls, we should only apply this workaround to fetch() calls.
  32. // Redirecting fetch() as our custom function is too risky and has too high a performance
  33. // impact.
  34. public function isTrustedResourceDir($path, $isConfig = NULL) {
  35. return true;
  36. }
  37. public static function test()
  38. {
  39. var_dump(get_called_class());
  40. }
  41. }
  42. // Create a wrapper class extended from Smarty
  43. class Serendipity_Smarty extends Smarty
  44. {
  45. // bc mode for plugins Smarty2 compat INCLUDE_ANY fetch() calls - to avoid an undefinied property error.
  46. public $security_settings = false;
  47. public function __set($name, $value) {
  48. if ($name == 'security') {
  49. if ($value) {
  50. $this->enableSecurity('Serendipity_Smarty_Security_Policy');
  51. } else {
  52. $this->disableSecurity();
  53. }
  54. } else {
  55. parent::__set($name, $value);
  56. }
  57. }
  58. /**
  59. * It is often helpful to access the Smarty object from anywhere in your code, e.g in Plugins.
  60. * Enables the Smarty object by instance always. The singleton pattern ensures that there is only one instance of the object available.
  61. * To obtain an instance of this class use:
  62. * $serendipity['smarty'] = Serendipity_Smarty::getInstance();
  63. * The first time this is called a new instance will be created. Thereafter, the same instance is handed back.
  64. **/
  65. public static function getInstance($newInstance = null)
  66. {
  67. static $instance = null;
  68. if(isset($newInstance)) {
  69. $instance = $newInstance;
  70. }
  71. if ( $instance == null ) {
  72. $instance = new Serendipity_Smarty();
  73. }
  74. return $instance;
  75. }
  76. public function __construct()
  77. {
  78. // Class Constructor. These automatically get set with each new instance.
  79. parent::__construct();
  80. // call the objects initialization parameters
  81. self::setParams();
  82. }
  83. // smarty (3.1.x) object main parameter setup
  84. private function setParams()
  85. {
  86. global $serendipity;
  87. // some documentary from the smarty forum
  88. /*
  89. Addressing a specific $template_dir (see 3.1 release notes)
  90. Smarty 3.1 introduces the $template_dir index notation.
  91. $smarty->fetch('[foo]bar.tpl') and {include file="[foo]bar.tpl"} require the template bar.tpl to be loaded from $template_dir['foo'];
  92. Smarty::setTemplateDir() and Smarty::addTemplateDir() offer ways to define indexes along with the actual directories.
  93. */
  94. /* +++++++++++++++++++++++++++++++++++++++++++
  95. Set all directory setters
  96. Smarty will always use the first template found in order of the given array. Move the least significant directory to the end.
  97. */
  98. $template_engine = serendipity_get_config_var('template_engine');
  99. $template_dirs = array();
  100. // first add template path
  101. $template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . ($serendipity['template'] ?? null);
  102. // then fallback engines (which should never be a comma separated list)
  103. if ($template_engine) {
  104. $p = explode(',', $template_engine);
  105. foreach($p AS $te) {
  106. $template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . trim($te) . '/';
  107. }
  108. }
  109. $template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['defaultTemplate'];
  110. $template_dirs[] = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template_backend'];
  111. // add secure dir to template path, in case engine did have entries
  112. if (S9Y_TEMPLATE_SECUREDIR != $serendipity['serendipityPath'] . $serendipity['templatePath']) {
  113. $template_dirs[] = S9Y_TEMPLATE_SECUREDIR;
  114. }
  115. // disable plugin dir as added template dir is not advised, if set security is enabled (backend & frontend need access to fetch plugin templates)
  116. $template_dirs[] = $serendipity['serendipityPath'] . 'plugins';
  117. // add default template to addTemplate array, if not already set in engine
  118. $template_dirs[] = S9Y_TEMPLATE_FALLBACK;
  119. $this->setTemplateDir($template_dirs);
  120. if (defined('S9Y_DATA_PATH')) {
  121. $this->setCompileDir(S9Y_DATA_PATH . PATH_SMARTY_COMPILE);
  122. } else {
  123. $this->setCompileDir($serendipity['serendipityPath'] . PATH_SMARTY_COMPILE);
  124. }
  125. $this->setConfigDir(array(S9Y_TEMPLATE_USERDEFAULT));
  126. if ( ( !is_dir($this->getCompileDir()) || !is_writable($this->getCompileDir()) ) && IS_installed === true) {
  127. if(ini_get('display_errors') == 0 || ini_get('display_errors') == 'off') printf(DIRECTORY_WRITE_ERROR, $this->getCompileDir());
  128. trigger_error(sprintf(DIRECTORY_WRITE_ERROR, $this->getCompileDir()), E_USER_ERROR);
  129. }
  130. /*
  131. here we go with our other Smarty class properties, which can all be called by their property name (recommended)
  132. $smarty->use_sub_dirs = true; or by $smarty->setUseSubDirs(true); and echo $smarty->getUseSubDirs();
  133. as the latter's would run through an internal __call() wrapper function.
  134. Note: rodneyrehm - From within the Smarty class context you can safely access properties like Smarty::$use_sub_dirs directly.
  135. */
  136. /* +++++++++++++++++++++++++++++++++++
  137. Set Smarty caching - outsourced to README_SMARTY_CACHING_PURPOSES.txt
  138. Not usable in Serendipity with current template structure!
  139. */
  140. /* ++++++++++++++++++++++++++++++++++++++++++++++
  141. Set all other needed Smarty class properties
  142. */
  143. #$this->merge_compiled_includes = true; // $this->setMergeCompiledIncludes(true); // With this option the subtemplate code is stored together with the calling template.
  144. // default here to be overwritten by $serendipity['production'] == 'debug' - see below!
  145. $this->debugging = false; // $this->setDebugging(false);
  146. // Smarty will create subdirectories under the compiled templates and cache directories if $use_sub_dirs is set to TRUE, default is FALSE.
  147. $this->use_sub_dirs = ( ini_get('safe_mode') ? false : true ); // $this->setUseSubDirs(false); // cache and compile dir only
  148. // Smarty should update the cache files automatically if $smarty->compile_check is true.
  149. $this->compile_check = true; // $this->setCompileCheck(true);
  150. #$this->compile_check = COMPILECHECK_OFF (false) - template files will not be checked
  151. #$this->compile_check = COMPILECHECK_ON (true) - template files will always be checked
  152. #$this->compile_check = COMPILECHECK_CACHEMISS - template files will be checked, if caching is enabled and there is no existing cache file, or it has expired
  153. /*
  154. Note: rodneyrehm
  155. If you actually manage to build a page from a single template (with inclusions and plugins and stuff)
  156. in a way that allows smarty to do 304 handling - or implement the serve-stale-while-update approach,
  157. you should go with CACHEMISS.
  158. */
  159. $this->compile_id = &$serendipity['template']; // $this->setCompileId(&$serendipity['template'])
  160. /*
  161. Note: rodneyrehm
  162. Please only specify the compile_id if you really need to.
  163. That means if you pre-process templates for say internationalization.
  164. Otherwise you don't need this and are better off ignoring it (performance-wise).
  165. */
  166. $this->config_overwrite = true; // $this->setConfigOverwrite(true);
  167. // production == debug extends from s9y version information (alpha|beta|cvs) is always debug | USE ===
  168. if ($serendipity['production'] === 'debug') {
  169. $this->force_compile = true; // $this->setForceCompile(true);
  170. $this->caching = false; // $this->setCaching(false);
  171. $this->debugging = true; // $this->setDebugging(true);
  172. }
  173. // set smarty error reporting. General error_reporting is set in serendipity/serendipity_config.inc.php
  174. $this->error_reporting = E_ALL & ~(E_NOTICE|E_STRICT);
  175. // we use our own error_handler and get in conflicts with smarty?
  176. // $this->muteExpectedErrors();
  177. }
  178. /*
  179. Note: Ian
  180. These BC methods are to be kept as long as not converted to new syntax in additional plugins
  181. Search "$serendipity['smarty']->register_" (11 hits in 6 files) in additional_plugins
  182. serendipity_event_communityrating.php, serendipity_event_customarchive.php, serendipity_event_microformats.php,
  183. serendipity_event_multilingual.php, serendipity_event_smartymarkup.php, serendipity_event_staticpage.php
  184. */
  185. /**
  186. * Registers custom function to be used in templates - BC mode Smarty 2 -> 3
  187. *
  188. * @param string $function the name of the template function
  189. * @param string $function_impl the name of the PHP function to register
  190. * @param bool $cacheable
  191. * @param mixed $cache_attrs
  192. */
  193. public function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
  194. {
  195. $this->registerPlugin('function', $function, $function_impl, $cacheable, $cache_attrs);
  196. }
  197. /**
  198. * Registers modifier to be used in templates - BC mode Smarty 2 -> 3
  199. *
  200. * @param string $modifier name of template modifier
  201. * @param string $modifier_impl name of PHP function to register
  202. */
  203. public function register_modifier($modifier, $modifier_impl)
  204. {
  205. $this->registerPlugin('modifier', $modifier, $modifier_impl);
  206. }
  207. /**
  208. * Registers a resource to fetch a template - BC mode Smarty 2 -> 3
  209. *
  210. * @param string $type name of resource
  211. * @param array $functions array of functions to handle resource
  212. */
  213. public function register_resource($type, $functions)
  214. {
  215. $this->registerResource($type, $functions);
  216. }
  217. /**
  218. * wrapper for assign_by_ref - BC mode Smarty 2 -> 3 (Serendipity core uses assignByRef already - and nearly no occurrences in additional plugins)
  219. *
  220. * @param string $tpl_var the template variable name
  221. * @param mixed &$value the referenced value to assign
  222. */
  223. public function assign_by_ref($tpl_var, &$value)
  224. {
  225. $this->assignByRef($tpl_var, $value);
  226. }
  227. /**
  228. * Returns an array containing template variables- BC mode Smarty 2 -> 3
  229. *
  230. * @param string $name
  231. * @return array
  232. */
  233. public function get_template_vars($name=null)
  234. {
  235. return $this->getTemplateVars($name);
  236. }
  237. public static function test()
  238. {
  239. var_dump(get_called_class());
  240. }
  241. }