diff options
Diffstat (limited to '')
-rw-r--r-- | include/smarty/libs/Smarty.class.php | 2458 |
1 files changed, 1010 insertions, 1448 deletions
diff --git a/include/smarty/libs/Smarty.class.php b/include/smarty/libs/Smarty.class.php index 2aaecbd93..40532fc2a 100644 --- a/include/smarty/libs/Smarty.class.php +++ b/include/smarty/libs/Smarty.class.php @@ -1,8 +1,8 @@ <?php - /** * Project: Smarty: the PHP compiling template engine * File: Smarty.class.php + * SVN: $Id: Smarty.class.php 4694 2013-01-13 21:13:14Z uwe.tews@googlemail.com $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,1944 +23,1506 @@ * smarty-discussion-subscribe@googlegroups.com * * @link http://www.smarty.net/ - * @copyright 2001-2005 New Digital Group, Inc. + * @copyright 2008 New Digital Group, Inc. * @author Monte Ohrt <monte at ohrt dot com> - * @author Andrei Zmievski <andrei@php.net> + * @author Uwe Tews + * @author Rodney Rehm * @package Smarty - * @version 2.6.26 + * @version 3.1.13 */ -/* $Id: Smarty.class.php 3163 2009-06-17 14:39:24Z monte.ohrt $ */ - /** - * DIR_SEP isn't used anymore, but third party apps might + * define shorthand directory separator constant */ -if(!defined('DIR_SEP')) { - define('DIR_SEP', DIRECTORY_SEPARATOR); +if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); } /** * set SMARTY_DIR to absolute path to Smarty library files. - * if not defined, include_path will be used. Sets SMARTY_DIR only if user - * application has not already defined it. + * Sets SMARTY_DIR only if user application has not already defined it. */ - if (!defined('SMARTY_DIR')) { - define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR); + define('SMARTY_DIR', dirname(__FILE__) . DS); +} + +/** + * set SMARTY_SYSPLUGINS_DIR to absolute path to Smarty internal plugins. + * Sets SMARTY_SYSPLUGINS_DIR only if user application has not already defined it. + */ +if (!defined('SMARTY_SYSPLUGINS_DIR')) { + define('SMARTY_SYSPLUGINS_DIR', SMARTY_DIR . 'sysplugins' . DS); +} +if (!defined('SMARTY_PLUGINS_DIR')) { + define('SMARTY_PLUGINS_DIR', SMARTY_DIR . 'plugins' . DS); +} +if (!defined('SMARTY_MBSTRING')) { + define('SMARTY_MBSTRING', function_exists('mb_split')); +} +if (!defined('SMARTY_RESOURCE_CHAR_SET')) { + // UTF-8 can only be done properly when mbstring is available! + /** + * @deprecated in favor of Smarty::$_CHARSET + */ + define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1'); +} +if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) { + /** + * @deprecated in favor of Smarty::$_DATE_FORMAT + */ + define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y'); } -if (!defined('SMARTY_CORE_DIR')) { - define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR); +/** + * register the class autoloader + */ +if (!defined('SMARTY_SPL_AUTOLOAD')) { + define('SMARTY_SPL_AUTOLOAD', 0); +} + +if (SMARTY_SPL_AUTOLOAD && set_include_path(get_include_path() . PATH_SEPARATOR . SMARTY_SYSPLUGINS_DIR) !== false) { + $registeredAutoLoadFunctions = spl_autoload_functions(); + if (!isset($registeredAutoLoadFunctions['spl_autoload'])) { + spl_autoload_register(); + } +} else { + spl_autoload_register('smartyAutoload'); } -define('SMARTY_PHP_PASSTHRU', 0); -define('SMARTY_PHP_QUOTE', 1); -define('SMARTY_PHP_REMOVE', 2); -define('SMARTY_PHP_ALLOW', 3); +/** + * Load always needed external class files + */ +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_data.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_templatebase.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_template.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_resource.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_resource_file.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_cacheresource.php'; +include_once SMARTY_SYSPLUGINS_DIR.'smarty_internal_cacheresource_file.php'; /** + * This is the main Smarty class * @package Smarty */ -class Smarty -{ +class Smarty extends Smarty_Internal_TemplateBase { + /**#@+ - * Smarty Configuration Section + * constant definitions */ /** - * The name of the directory where templates are located. - * - * @var string + * smarty version */ - var $template_dir = 'templates'; + const SMARTY_VERSION = 'Smarty-3.1.13'; /** - * The directory where compiled templates are located. - * - * @var string + * define variable scopes */ - var $compile_dir = 'templates_c'; - + const SCOPE_LOCAL = 0; + const SCOPE_PARENT = 1; + const SCOPE_ROOT = 2; + const SCOPE_GLOBAL = 3; /** - * The directory where config files are located. - * - * @var string + * define caching modes + */ + const CACHING_OFF = 0; + const CACHING_LIFETIME_CURRENT = 1; + const CACHING_LIFETIME_SAVED = 2; + /** + * define compile check modes + */ + const COMPILECHECK_OFF = 0; + const COMPILECHECK_ON = 1; + const COMPILECHECK_CACHEMISS = 2; + /** + * modes for handling of "<?php ... ?>" tags in templates. */ - var $config_dir = 'configs'; + const PHP_PASSTHRU = 0; //-> print tags as plain text + const PHP_QUOTE = 1; //-> escape tags as entities + const PHP_REMOVE = 2; //-> escape tags as entities + const PHP_ALLOW = 3; //-> escape tags as entities + /** + * filter types + */ + const FILTER_POST = 'post'; + const FILTER_PRE = 'pre'; + const FILTER_OUTPUT = 'output'; + const FILTER_VARIABLE = 'variable'; + /** + * plugin types + */ + const PLUGIN_FUNCTION = 'function'; + const PLUGIN_BLOCK = 'block'; + const PLUGIN_COMPILER = 'compiler'; + const PLUGIN_MODIFIER = 'modifier'; + const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler'; + + /**#@-*/ /** - * An array of directories searched for plugins. - * - * @var array + * assigned global tpl vars */ - var $plugins_dir = array('plugins'); + public static $global_tpl_vars = array(); /** - * If debugging is enabled, a debug console window will display - * when the page loads (make sure your browser allows unrequested - * popup windows) - * - * @var boolean + * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors() + */ + public static $_previous_error_handler = null; + /** + * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors() + */ + public static $_muted_directories = array(); + /** + * Flag denoting if Multibyte String functions are available + */ + public static $_MBSTRING = SMARTY_MBSTRING; + /** + * The character set to adhere to (e.g. "UTF-8") + */ + public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET; + /** + * The date format to be used internally + * (accepts date() and strftime()) + */ + public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT; + /** + * Flag denoting if PCRE should run in UTF-8 mode */ - var $debugging = false; + public static $_UTF8_MODIFIER = 'u'; /** - * When set, smarty does uses this value as error_reporting-level. - * - * @var integer + * Flag denoting if operating system is windows + */ + public static $_IS_WINDOWS = false; + + /**#@+ + * variables */ - var $error_reporting = null; /** - * This is the path to the debug console template. If not set, - * the default one will be used. - * + * auto literal on delimiters with whitspace + * @var boolean + */ + public $auto_literal = true; + /** + * display error on not assigned variables + * @var boolean + */ + public $error_unassigned = false; + /** + * look up relative filepaths in include_path + * @var boolean + */ + public $use_include_path = false; + /** + * template directory + * @var array + */ + private $template_dir = array(); + /** + * joined template directory string used in cache keys * @var string */ - var $debug_tpl = ''; - + public $joined_template_dir = null; /** - * This determines if debugging is enable-able from the browser. - * <ul> - * <li>NONE => no debugging control allowed</li> - * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li> - * </ul> - * @link http://www.foo.dom/index.php?SMARTY_DEBUG + * joined config directory string used in cache keys * @var string */ - var $debugging_ctrl = 'NONE'; - + public $joined_config_dir = null; /** - * This tells Smarty whether to check for recompiling or not. Recompiling - * does not need to happen unless a template or config file is changed. - * Typically you enable this during development, and disable for - * production. - * + * default template handler + * @var callable + */ + public $default_template_handler_func = null; + /** + * default config handler + * @var callable + */ + public $default_config_handler_func = null; + /** + * default plugin handler + * @var callable + */ + public $default_plugin_handler_func = null; + /** + * compile directory + * @var string + */ + private $compile_dir = null; + /** + * plugins directory + * @var array + */ + private $plugins_dir = array(); + /** + * cache directory + * @var string + */ + private $cache_dir = null; + /** + * config directory + * @var array + */ + private $config_dir = array(); + /** + * force template compiling? * @var boolean */ - var $compile_check = true; - + public $force_compile = false; /** - * This forces templates to compile every time. Useful for development - * or debugging. - * + * check template for modifications? * @var boolean */ - var $force_compile = false; - + public $compile_check = true; /** - * This enables template caching. - * <ul> - * <li>0 = no caching</li> - * <li>1 = use class cache_lifetime value</li> - * <li>2 = use cache_lifetime in cache file</li> - * </ul> - * @var integer + * use sub dirs for compiled/cached files? + * @var boolean */ - var $caching = 0; - + public $use_sub_dirs = false; /** - * The name of the directory for cache files. - * - * @var string + * allow ambiguous resources (that are made unique by the resource handler) + * @var boolean */ - var $cache_dir = 'cache'; - + public $allow_ambiguous_resources = false; /** - * This is the number of seconds cached content will persist. - * <ul> - * <li>0 = always regenerate cache</li> - * <li>-1 = never expires</li> - * </ul> - * - * @var integer + * caching enabled + * @var boolean */ - var $cache_lifetime = 3600; - + public $caching = false; /** - * Only used when $caching is enabled. If true, then If-Modified-Since headers - * are respected with cached content, and appropriate HTTP headers are sent. - * This way repeated hits to a cached page do not send the entire page to the - * client every time. - * + * merge compiled includes * @var boolean */ - var $cache_modified_check = false; - + public $merge_compiled_includes = false; /** - * This determines how Smarty handles "<?php ... ?>" tags in templates. - * possible values: - * <ul> - * <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li> - * <li>SMARTY_PHP_QUOTE -> escape tags as entities</li> - * <li>SMARTY_PHP_REMOVE -> remove php tags</li> - * <li>SMARTY_PHP_ALLOW -> execute php tags</li> - * </ul> - * + * cache lifetime in seconds * @var integer */ - var $php_handling = SMARTY_PHP_PASSTHRU; - + public $cache_lifetime = 3600; /** - * This enables template security. When enabled, many things are restricted - * in the templates that normally would go unchecked. This is useful when - * untrusted parties are editing templates and you want a reasonable level - * of security. (no direct execution of PHP in templates for example) - * + * force cache file creation * @var boolean */ - var $security = false; - + public $force_cache = false; /** - * This is the list of template directories that are considered secure. This - * is used only if {@link $security} is enabled. One directory per array - * element. {@link $template_dir} is in this list implicitly. + * Set this if you want different sets of cache files for the same + * templates. * - * @var array + * @var string */ - var $secure_dir = array(); - + public $cache_id = null; /** - * These are the security settings for Smarty. They are used only when - * {@link $security} is enabled. + * Set this if you want different sets of compiled files for the same + * templates. * - * @var array + * @var string */ - var $security_settings = array( - 'PHP_HANDLING' => false, - 'IF_FUNCS' => array('array', 'list', - 'isset', 'empty', - 'count', 'sizeof', - 'in_array', 'is_array', - 'true', 'false', 'null'), - 'INCLUDE_ANY' => false, - 'PHP_TAGS' => false, - 'MODIFIER_FUNCS' => array('count'), - 'ALLOW_CONSTANTS' => false, - 'ALLOW_SUPER_GLOBALS' => true - ); - - /** - * This is an array of directories where trusted php scripts reside. - * {@link $security} is disabled during their inclusion/execution. - * - * @var array + public $compile_id = null; + /** + * template left-delimiter + * @var string */ - var $trusted_dir = array(); - + public $left_delimiter = "{"; /** - * The left delimiter used for the template tags. - * + * template right-delimiter * @var string */ - var $left_delimiter = '{'; - + public $right_delimiter = "}"; + /**#@+ + * security + */ /** - * The right delimiter used for the template tags. + * class name + * + * This should be instance of Smarty_Security. * * @var string + * @see Smarty_Security */ - var $right_delimiter = '}'; - + public $security_class = 'Smarty_Security'; /** - * The order in which request variables are registered, similar to - * variables_order in php.ini E = Environment, G = GET, P = POST, - * C = Cookies, S = Server + * implementation of security class * - * @var string + * @var Smarty_Security */ - var $request_vars_order = 'EGPCS'; - + public $security_policy = null; /** - * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false) - * are uses as request-vars or $_*[]-vars. note: if - * request_use_auto_globals is true, then $request_vars_order has - * no effect, but the php-ini-value "gpc_order" + * controls handling of PHP-blocks * - * @var boolean + * @var integer */ - var $request_use_auto_globals = true; - + public $php_handling = self::PHP_PASSTHRU; /** - * Set this if you want different sets of compiled files for the same - * templates. This is useful for things like different languages. - * Instead of creating separate sets of templates per language, you - * set different compile_ids like 'en' and 'de'. + * controls if the php template file resource is allowed * - * @var string + * @var bool */ - var $compile_id = null; - + public $allow_php_templates = false; /** - * This tells Smarty whether or not to use sub dirs in the cache/ and - * templates_c/ directories. sub directories better organized, but - * may not work well with PHP safe mode enabled. + * Should compiled-templates be prevented from being called directly? * - * @var boolean + * {@internal + * Currently used by Smarty_Internal_Template only. + * }} * + * @var boolean */ - var $use_sub_dirs = false; - + public $direct_access_security = true; + /**#@-*/ /** - * This is a list of the modifiers to apply to all template variables. - * Put each modifier in a separate array element in the order you want - * them applied. example: <code>array('escape:"htmlall"');</code> + * debug mode * - * @var array + * Setting this to true enables the debug-console. + * + * @var boolean */ - var $default_modifiers = array(); - + public $debugging = false; /** - * This is the resource type to be used when not specified - * at the beginning of the resource path. examples: - * $smarty->display('file:index.tpl'); - * $smarty->display('db:index.tpl'); - * $smarty->display('index.tpl'); // will use default resource type - * {include file="file:index.tpl"} - * {include file="db:index.tpl"} - * {include file="index.tpl"} {* will use default resource type *} - * - * @var array + * This determines if debugging is enable-able from the browser. + * <ul> + * <li>NONE => no debugging control allowed</li> + * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li> + * </ul> + * @var string */ - var $default_resource_type = 'file'; - + public $debugging_ctrl = 'NONE'; /** - * The function used for cache file handling. If not set, built-in caching is used. + * Name of debugging URL-param. * - * @var null|string function name + * Only used when $debugging_ctrl is set to 'URL'. + * The name of the URL-parameter that activates debugging. + * + * @var type */ - var $cache_handler_func = null; - + public $smarty_debug_id = 'SMARTY_DEBUG'; /** - * This indicates which filters are automatically loaded into Smarty. - * - * @var array array of filter names + * Path of debug template. + * @var string + */ + public $debug_tpl = null; + /** + * When set, smarty uses this value as error_reporting-level. + * @var int */ - var $autoload_filters = array(); + public $error_reporting = null; + /** + * Internal flag for getTags() + * @var boolean + */ + public $get_used_tags = false; /**#@+ + * config var settings + */ + + /** + * Controls whether variables with the same name overwrite each other. * @var boolean */ + public $config_overwrite = true; /** - * This tells if config file vars of the same name overwrite each other or not. - * if disabled, same name variables are accumulated in an array. + * Controls whether config values of on/true/yes and off/false/no get converted to boolean. + * @var boolean */ - var $config_overwrite = true; - + public $config_booleanize = true; /** - * This tells whether or not to automatically booleanize config file variables. - * If enabled, then the strings "on", "true", and "yes" are treated as boolean - * true, and "off", "false" and "no" are treated as boolean false. + * Controls whether hidden config sections/vars are read from the file. + * @var boolean */ - var $config_booleanize = true; + public $config_read_hidden = false; - /** - * This tells whether hidden sections [.foobar] are readable from the - * tempalates or not. Normally you would never allow this since that is - * the point behind hidden sections: the application can access them, but - * the templates cannot. + /**#@-*/ + + /**#@+ + * resource locking */ - var $config_read_hidden = false; /** - * This tells whether or not automatically fix newlines in config files. - * It basically converts \r (mac) or \r\n (dos) to \n + * locking concurrent compiles + * @var boolean + */ + public $compile_locking = true; + /** + * Controls whether cache resources should emply locking mechanism + * @var boolean + */ + public $cache_locking = false; + /** + * seconds to wait for acquiring a lock before ignoring the write lock + * @var float */ - var $config_fix_newlines = true; + public $locking_timeout = 10; + /**#@-*/ /** - * If a template cannot be found, this PHP function will be executed. - * Useful for creating templates on-the-fly or other special action. - * - * @var string function name + * global template functions + * @var array */ - var $default_template_handler_func = ''; - + public $template_functions = array(); /** - * The file that contains the compiler class. This can a full - * pathname, or relative to the php_include path. + * resource type used if none given * + * Must be an valid key of $registered_resources. * @var string */ - var $compiler_file = 'Smarty_Compiler.class.php'; - + public $default_resource_type = 'file'; /** - * The class used for compiling templates. + * caching type + * + * Must be an element of $cache_resource_types. * * @var string */ - var $compiler_class = 'Smarty_Compiler'; - + public $caching_type = 'file'; /** - * The class used to load config vars. - * + * internal config properties + * @var array + */ + public $properties = array(); + /** + * config type * @var string */ - var $config_class = 'Config_File'; - -/**#@+ - * END Smarty Configuration Section - * There should be no need to touch anything below this line. - * @access private - */ + public $default_config_type = 'file'; /** - * where assigned template vars are kept - * + * cached template objects * @var array */ - var $_tpl_vars = array(); - + public $template_objects = array(); /** - * stores run-time $smarty.* vars - * - * @var null|array + * check If-Modified-Since headers + * @var boolean */ - var $_smarty_vars = null; - + public $cache_modified_check = false; /** - * keeps track of sections - * + * registered plugins * @var array */ - var $_sections = array(); - + public $registered_plugins = array(); /** - * keeps track of foreach blocks - * + * plugin search order * @var array */ - var $_foreach = array(); - + public $plugin_search_order = array('function', 'block', 'compiler', 'class'); /** - * keeps track of tag hierarchy - * + * registered objects * @var array */ - var $_tag_stack = array(); - + public $registered_objects = array(); /** - * configuration object - * - * @var Config_file + * registered classes + * @var array */ - var $_conf_obj = null; - + public $registered_classes = array(); /** - * loaded configuration settings - * + * registered filters * @var array */ - var $_config = array(array('vars' => array(), 'files' => array())); - + public $registered_filters = array(); /** - * md5 checksum of the string 'Smarty' - * - * @var string + * registered resources + * @var array */ - var $_smarty_md5 = 'f8d698aea36fcbead2b9d5359ffca76f'; - + public $registered_resources = array(); /** - * Smarty version number - * - * @var string + * resource handler cache + * @var array */ - var $_version = '2.6.26'; - + public $_resource_handlers = array(); /** - * current template inclusion depth - * - * @var integer + * registered cache resources + * @var array */ - var $_inclusion_depth = 0; - + public $registered_cache_resources = array(); /** - * for different compiled templates - * - * @var string + * cache resource handler cache + * @var array */ - var $_compile_id = null; - + public $_cacheresource_handlers = array(); /** - * text in URL to enable debug mode - * - * @var string + * autoload filter + * @var array */ - var $_smarty_debug_id = 'SMARTY_DEBUG'; - + public $autoload_filters = array(); /** - * debugging information for debug console - * + * default modifier * @var array */ - var $_smarty_debug_info = array(); - + public $default_modifiers = array(); /** - * info that makes up a cache file - * + * autoescape variable output + * @var boolean + */ + public $escape_html = false; + /** + * global internal smarty vars * @var array */ - var $_cache_info = array(); - + public static $_smarty_vars = array(); + /** + * start time for execution time calculation + * @var int + */ + public $start_time = 0; /** * default file permissions - * - * @var integer + * @var int */ - var $_file_perms = 0644; - + public $_file_perms = 0644; /** * default dir permissions - * - * @var integer + * @var int */ - var $_dir_perms = 0771; - + public $_dir_perms = 0771; /** - * registered objects - * + * block tag hierarchy * @var array */ - var $_reg_objects = array(); - + public $_tag_stack = array(); /** - * table keeping track of plugins - * - * @var array + * self pointer to Smarty object + * @var Smarty */ - var $_plugins = array( - 'modifier' => array(), - 'function' => array(), - 'block' => array(), - 'compiler' => array(), - 'prefilter' => array(), - 'postfilter' => array(), - 'outputfilter' => array(), - 'resource' => array(), - 'insert' => array()); - - + public $smarty; /** - * cache serials - * - * @var array + * required by the compiler for BC + * @var string */ - var $_cache_serials = array(); - + public $_current_file = null; /** - * name of optional cache include file - * - * @var string + * internal flag to enable parser debugging + * @var bool */ - var $_cache_include = null; - + public $_parserdebug = false; /** - * indicate if the current code is used in a compiled - * include + * Saved parameter of merged templates during compilation * - * @var string + * @var array */ - var $_cache_including = false; - + public $merged_templates_func = array(); /**#@-*/ - /** - * The class constructor. - */ - function Smarty() - { - $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] - : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']); - } /** - * assigns values to template variables + * Initialize new Smarty object * - * @param array|string $tpl_var the template variable name(s) - * @param mixed $value the value to assign */ - function assign($tpl_var, $value = null) + public function __construct() { - if (is_array($tpl_var)){ - foreach ($tpl_var as $key => $val) { - if ($key != '') { - $this->_tpl_vars[$key] = $val; - } - } - } else { - if ($tpl_var != '') - $this->_tpl_vars[$tpl_var] = $value; + // selfpointer needed by some other class methods + $this->smarty = $this; + if (is_callable('mb_internal_encoding')) { + mb_internal_encoding(Smarty::$_CHARSET); + } + $this->start_time = microtime(true); + // set default dirs + $this->setTemplateDir('.' . DS . 'templates' . DS) + ->setCompileDir('.' . DS . 'templates_c' . DS) + ->setPluginsDir(SMARTY_PLUGINS_DIR) + ->setCacheDir('.' . DS . 'cache' . DS) + ->setConfigDir('.' . DS . 'configs' . DS); + + $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl'; + if (isset($_SERVER['SCRIPT_NAME'])) { + $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']); } } - /** - * assigns values to template variables by reference - * - * @param string $tpl_var the template variable name - * @param mixed $value the referenced value to assign - */ - function assign_by_ref($tpl_var, &$value) - { - if ($tpl_var != '') - $this->_tpl_vars[$tpl_var] = &$value; - } /** - * appends values to template variables - * - * @param array|string $tpl_var the template variable name(s) - * @param mixed $value the value to append + * Class destructor */ - function append($tpl_var, $value=null, $merge=false) + public function __destruct() { - if (is_array($tpl_var)) { - // $tpl_var is an array, ignore $value - foreach ($tpl_var as $_key => $_val) { - if ($_key != '') { - if(!@is_array($this->_tpl_vars[$_key])) { - settype($this->_tpl_vars[$_key],'array'); - } - if($merge && is_array($_val)) { - foreach($_val as $_mkey => $_mval) { - $this->_tpl_vars[$_key][$_mkey] = $_mval; - } - } else { - $this->_tpl_vars[$_key][] = $_val; - } - } - } - } else { - if ($tpl_var != '' && isset($value)) { - if(!@is_array($this->_tpl_vars[$tpl_var])) { - settype($this->_tpl_vars[$tpl_var],'array'); - } - if($merge && is_array($value)) { - foreach($value as $_mkey => $_mval) { - $this->_tpl_vars[$tpl_var][$_mkey] = $_mval; - } - } else { - $this->_tpl_vars[$tpl_var][] = $value; - } - } - } + // intentionally left blank } /** - * appends values to template variables by reference - * - * @param string $tpl_var the template variable name - * @param mixed $value the referenced value to append + * <<magic>> set selfpointer on cloned object */ - function append_by_ref($tpl_var, &$value, $merge=false) + public function __clone() { - if ($tpl_var != '' && isset($value)) { - if(!@is_array($this->_tpl_vars[$tpl_var])) { - settype($this->_tpl_vars[$tpl_var],'array'); - } - if ($merge && is_array($value)) { - foreach($value as $_key => $_val) { - $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key]; - } - } else { - $this->_tpl_vars[$tpl_var][] = &$value; - } - } + $this->smarty = $this; } /** - * clear the given assigned template variable. + * <<magic>> Generic getter. * - * @param string $tpl_var the template variable to clear - */ - function clear_assign($tpl_var) - { - if (is_array($tpl_var)) - foreach ($tpl_var as $curr_var) - unset($this->_tpl_vars[$curr_var]); - else - unset($this->_tpl_vars[$tpl_var]); - } - - - /** - * Registers custom function to be used in templates + * Calls the appropriate getter function. + * Issues an E_USER_NOTICE if no valid getter is found. * - * @param string $function the name of the template function - * @param string $function_impl the name of the PHP function to register + * @param string $name property name + * @return mixed */ - function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null) + public function __get($name) { - $this->_plugins['function'][$function] = - array($function_impl, null, null, false, $cacheable, $cache_attrs); + $allowed = array( + 'template_dir' => 'getTemplateDir', + 'config_dir' => 'getConfigDir', + 'plugins_dir' => 'getPluginsDir', + 'compile_dir' => 'getCompileDir', + 'cache_dir' => 'getCacheDir', + ); + if (isset($allowed[$name])) { + return $this->{$allowed[$name]}(); + } else { + trigger_error('Undefined property: '. get_class($this) .'::$'. $name, E_USER_NOTICE); + } } /** - * Unregisters custom function + * <<magic>> Generic setter. * - * @param string $function name of template function - */ - function unregister_function($function) - { - unset($this->_plugins['function'][$function]); - } - - /** - * Registers object to be used in templates + * Calls the appropriate setter function. + * Issues an E_USER_NOTICE if no valid setter is found. * - * @param string $object name of template object - * @param object &$object_impl the referenced PHP object to register - * @param null|array $allowed list of allowed methods (empty = all) - * @param boolean $smarty_args smarty argument format, else traditional - * @param null|array $block_functs list of methods that are block format + * @param string $name property name + * @param mixed $value parameter passed to setter */ - function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array()) + public function __set($name, $value) { - settype($allowed, 'array'); - settype($smarty_args, 'boolean'); - $this->_reg_objects[$object] = - array(&$object_impl, $allowed, $smarty_args, $block_methods); + $allowed = array( + 'template_dir' => 'setTemplateDir', + 'config_dir' => 'setConfigDir', + 'plugins_dir' => 'setPluginsDir', + 'compile_dir' => 'setCompileDir', + 'cache_dir' => 'setCacheDir', + ); + + if (isset($allowed[$name])) { + $this->{$allowed[$name]}($value); + } else { + trigger_error('Undefined property: ' . get_class($this) . '::$' . $name, E_USER_NOTICE); + } } /** - * Unregisters object + * Check if a template resource exists * - * @param string $object name of template object + * @param string $resource_name template name + * @return boolean status */ - function unregister_object($object) + public function templateExists($resource_name) { - unset($this->_reg_objects[$object]); + // create template object + $save = $this->template_objects; + $tpl = new $this->template_class($resource_name, $this); + // check if it does exists + $result = $tpl->source->exists; + $this->template_objects = $save; + return $result; } - /** - * Registers block function to be used in templates + * Returns a single or all global variables * - * @param string $block name of template block - * @param string $block_impl PHP function to register + * @param object $smarty + * @param string $varname variable name or null + * @return string variable value or or array of variables */ - function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null) + public function getGlobal($varname = null) { - $this->_plugins['block'][$block] = - array($block_impl, null, null, false, $cacheable, $cache_attrs); + if (isset($varname)) { + if (isset(self::$global_tpl_vars[$varname])) { + return self::$global_tpl_vars[$varname]->value; + } else { + return ''; + } + } else { + $_result = array(); + foreach (self::$global_tpl_vars AS $key => $var) { + $_result[$key] = $var->value; + } + return $_result; + } } /** - * Unregisters block function + * Empty cache folder * - * @param string $block name of template function + * @param integer $exp_time expiration time + * @param string $type resource type + * @return integer number of cache files deleted */ - function unregister_block($block) + function clearAllCache($exp_time = null, $type = null) { - unset($this->_plugins['block'][$block]); + // load cache resource and call clearAll + $_cache_resource = Smarty_CacheResource::load($this, $type); + Smarty_CacheResource::invalidLoadedCache($this); + return $_cache_resource->clearAll($this, $exp_time); } /** - * Registers compiler function + * Empty cache for a specific template * - * @param string $function name of template function - * @param string $function_impl name of PHP function to register + * @param string $template_name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer $exp_time expiration time + * @param string $type resource type + * @return integer number of cache files deleted */ - function register_compiler_function($function, $function_impl, $cacheable=true) + public function clearCache($template_name, $cache_id = null, $compile_id = null, $exp_time = null, $type = null) { - $this->_plugins['compiler'][$function] = - array($function_impl, null, null, false, $cacheable); + // load cache resource and call clear + $_cache_resource = Smarty_CacheResource::load($this, $type); + Smarty_CacheResource::invalidLoadedCache($this); + return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time); } /** - * Unregisters compiler function + * Loads security class and enables security * - * @param string $function name of template function + * @param string|Smarty_Security $security_class if a string is used, it must be class-name + * @return Smarty current Smarty instance for chaining + * @throws SmartyException when an invalid class name is provided */ - function unregister_compiler_function($function) + public function enableSecurity($security_class = null) { - unset($this->_plugins['compiler'][$function]); + if ($security_class instanceof Smarty_Security) { + $this->security_policy = $security_class; + return $this; + } elseif (is_object($security_class)) { + throw new SmartyException("Class '" . get_class($security_class) . "' must extend Smarty_Security."); + } + if ($security_class == null) { + $security_class = $this->security_class; + } + if (!class_exists($security_class)) { + throw new SmartyException("Security class '$security_class' is not defined"); + } elseif ($security_class !== 'Smarty_Security' && !is_subclass_of($security_class, 'Smarty_Security')) { + throw new SmartyException("Class '$security_class' must extend Smarty_Security."); + } else { + $this->security_policy = new $security_class($this); + } + + return $this; } /** - * Registers modifier to be used in templates - * - * @param string $modifier name of template modifier - * @param string $modifier_impl name of PHP function to register + * Disable security + * @return Smarty current Smarty instance for chaining */ - function register_modifier($modifier, $modifier_impl) + public function disableSecurity() { - $this->_plugins['modifier'][$modifier] = - array($modifier_impl, null, null, false); + $this->security_policy = null; + + return $this; } /** - * Unregisters modifier + * Set template directory * - * @param string $modifier name of template modifier + * @param string|array $template_dir directory(s) of template sources + * @return Smarty current Smarty instance for chaining */ - function unregister_modifier($modifier) + public function setTemplateDir($template_dir) { - unset($this->_plugins['modifier'][$modifier]); + $this->template_dir = array(); + foreach ((array) $template_dir as $k => $v) { + $this->template_dir[$k] = rtrim($v, '/\\') . DS; + } + + $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); + return $this; } /** - * Registers a resource to fetch a template + * Add template directory(s) * - * @param string $type name of resource - * @param array $functions array of functions to handle resource + * @param string|array $template_dir directory(s) of template sources + * @param string $key of the array element to assign the template dir to + * @return Smarty current Smarty instance for chaining + * @throws SmartyException when the given template directory is not valid */ - function register_resource($type, $functions) + public function addTemplateDir($template_dir, $key=null) { - if (count($functions)==4) { - $this->_plugins['resource'][$type] = - array($functions, false); - - } elseif (count($functions)==5) { - $this->_plugins['resource'][$type] = - array(array(array(&$functions[0], $functions[1]) - ,array(&$functions[0], $functions[2]) - ,array(&$functions[0], $functions[3]) - ,array(&$functions[0], $functions[4])) - ,false); - + // make sure we're dealing with an array + $this->template_dir = (array) $this->template_dir; + + if (is_array($template_dir)) { + foreach ($template_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->template_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->template_dir[$k] = rtrim($v, '/\\') . DS; + } + } + } elseif ($key !== null) { + // override directory at specified index + $this->template_dir[$key] = rtrim($template_dir, '/\\') . DS; } else { - $this->trigger_error("malformed function-list for '$type' in register_resource"); - + // append new directory + $this->template_dir[] = rtrim($template_dir, '/\\') . DS; } + $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir); + return $this; } /** - * Unregisters a resource + * Get template directories * - * @param string $type name of resource + * @param mixed index of directory to get, null to get all + * @return array|string list of template directories, or directory of $index */ - function unregister_resource($type) + public function getTemplateDir($index=null) { - unset($this->_plugins['resource'][$type]); - } + if ($index !== null) { + return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null; + } - /** - * Registers a prefilter function to apply - * to a template before compiling - * - * @param callback $function - */ - function register_prefilter($function) - { - $this->_plugins['prefilter'][$this->_get_filter_name($function)] - = array($function, null, null, false); + return (array)$this->template_dir; } /** - * Unregisters a prefilter function + * Set config directory * - * @param callback $function + * @param string|array $template_dir directory(s) of configuration sources + * @return Smarty current Smarty instance for chaining */ - function unregister_prefilter($function) + public function setConfigDir($config_dir) { - unset($this->_plugins['prefilter'][$this->_get_filter_name($function)]); - } + $this->config_dir = array(); + foreach ((array) $config_dir as $k => $v) { + $this->config_dir[$k] = rtrim($v, '/\\') . DS; + } - /** - * Registers a postfilter function to apply - * to a compiled template after compilation - * - * @param callback $function - */ - function register_postfilter($function) - { - $this->_plugins['postfilter'][$this->_get_filter_name($function)] - = array($function, null, null, false); + $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); + return $this; } /** - * Unregisters a postfilter function + * Add config directory(s) * - * @param callback $function + * @param string|array $config_dir directory(s) of config sources + * @param string key of the array element to assign the config dir to + * @return Smarty current Smarty instance for chaining */ - function unregister_postfilter($function) + public function addConfigDir($config_dir, $key=null) { - unset($this->_plugins['postfilter'][$this->_get_filter_name($function)]); - } + // make sure we're dealing with an array + $this->config_dir = (array) $this->config_dir; + + if (is_array($config_dir)) { + foreach ($config_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->config_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->config_dir[$k] = rtrim($v, '/\\') . DS; + } + } + } elseif( $key !== null ) { + // override directory at specified index + $this->config_dir[$key] = rtrim($config_dir, '/\\') . DS; + } else { + // append new directory + $this->config_dir[] = rtrim($config_dir, '/\\') . DS; + } - /** - * Registers an output filter function to apply - * to a template output - * - * @param callback $function - */ - function register_outputfilter($function) - { - $this->_plugins['outputfilter'][$this->_get_filter_name($function)] - = array($function, null, null, false); + $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir); + return $this; } /** - * Unregisters an outputfilter function + * Get config directory * - * @param callback $function + * @param mixed index of directory to get, null to get all + * @return array|string configuration directory */ - function unregister_outputfilter($function) + public function getConfigDir($index=null) { - unset($this->_plugins['outputfilter'][$this->_get_filter_name($function)]); + if ($index !== null) { + return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null; + } + + return (array)$this->config_dir; } /** - * load a filter of specified type and name + * Set plugins directory * - * @param string $type filter type - * @param string $name filter name + * @param string|array $plugins_dir directory(s) of plugins + * @return Smarty current Smarty instance for chaining */ - function load_filter($type, $name) + public function setPluginsDir($plugins_dir) { - switch ($type) { - case 'output': - $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false))); - require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); - smarty_core_load_plugins($_params, $this); - break; - - case 'pre': - case 'post': - if (!isset($this->_plugins[$type . 'filter'][$name])) - $this->_plugins[$type . 'filter'][$name] = false; - break; + $this->plugins_dir = array(); + foreach ((array)$plugins_dir as $k => $v) { + $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; } + + return $this; } /** - * clear cached content for the given template and cache id + * Adds directory of plugin files * - * @param string $tpl_file name of template file - * @param string $cache_id name of cache_id - * @param string $compile_id name of compile_id - * @param string $exp_time expiration time - * @return boolean + * @param object $smarty + * @param string $ |array $ plugins folder + * @return Smarty current Smarty instance for chaining */ - function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null) + public function addPluginsDir($plugins_dir) { - - if (!isset($compile_id)) - $compile_id = $this->compile_id; - - if (!isset($tpl_file)) - $compile_id = null; - - $_auto_id = $this->_get_auto_id($cache_id, $compile_id); - - if (!empty($this->cache_handler_func)) { - return call_user_func_array($this->cache_handler_func, - array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time)); + // make sure we're dealing with an array + $this->plugins_dir = (array) $this->plugins_dir; + + if (is_array($plugins_dir)) { + foreach ($plugins_dir as $k => $v) { + if (is_int($k)) { + // indexes are not merged but appended + $this->plugins_dir[] = rtrim($v, '/\\') . DS; + } else { + // string indexes are overridden + $this->plugins_dir[$k] = rtrim($v, '/\\') . DS; + } + } } else { - $_params = array('auto_base' => $this->cache_dir, - 'auto_source' => $tpl_file, - 'auto_id' => $_auto_id, - 'exp_time' => $exp_time); - require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); - return smarty_core_rm_auto($_params, $this); + // append new directory + $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS; } + $this->plugins_dir = array_unique($this->plugins_dir); + return $this; } - /** - * clear the entire contents of cache (all templates) + * Get plugin directories * - * @param string $exp_time expire time - * @return boolean results of {@link smarty_core_rm_auto()} + * @return array list of plugin directories */ - function clear_all_cache($exp_time = null) + public function getPluginsDir() { - return $this->clear_cache(null, null, null, $exp_time); + return (array)$this->plugins_dir; } - /** - * test to see if valid cache exists for this template + * Set compile directory * - * @param string $tpl_file name of template file - * @param string $cache_id - * @param string $compile_id - * @return string|false results of {@link _read_cache_file()} + * @param string $compile_dir directory to store compiled templates in + * @return Smarty current Smarty instance for chaining */ - function is_cached($tpl_file, $cache_id = null, $compile_id = null) + public function setCompileDir($compile_dir) { - if (!$this->caching) - return false; - - if (!isset($compile_id)) - $compile_id = $this->compile_id; - - $_params = array( - 'tpl_file' => $tpl_file, - 'cache_id' => $cache_id, - 'compile_id' => $compile_id - ); - require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); - return smarty_core_read_cache_file($_params, $this); + $this->compile_dir = rtrim($compile_dir, '/\\') . DS; + if (!isset(Smarty::$_muted_directories[$this->compile_dir])) { + Smarty::$_muted_directories[$this->compile_dir] = null; + } + return $this; } - /** - * clear all the assigned template variables. + * Get compiled directory * + * @return string path to compiled templates */ - function clear_all_assign() + public function getCompileDir() { - $this->_tpl_vars = array(); + return $this->compile_dir; } /** - * clears compiled version of specified template resource, - * or all compiled template files if one is not specified. - * This function is for advanced use only, not normally needed. + * Set cache directory * - * @param string $tpl_file - * @param string $compile_id - * @param string $exp_time - * @return boolean results of {@link smarty_core_rm_auto()} + * @param string $cache_dir directory to store cached templates in + * @return Smarty current Smarty instance for chaining */ - function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null) + public function setCacheDir($cache_dir) { - if (!isset($compile_id)) { - $compile_id = $this->compile_id; + $this->cache_dir = rtrim($cache_dir, '/\\') . DS; + if (!isset(Smarty::$_muted_directories[$this->cache_dir])) { + Smarty::$_muted_directories[$this->cache_dir] = null; } - $_params = array('auto_base' => $this->compile_dir, - 'auto_source' => $tpl_file, - 'auto_id' => $compile_id, - 'exp_time' => $exp_time, - 'extensions' => array('.inc', '.php')); - require_once(SMARTY_CORE_DIR . 'core.rm_auto.php'); - return smarty_core_rm_auto($_params, $this); + return $this; } /** - * Checks whether requested template exists. + * Get cache directory * - * @param string $tpl_file - * @return boolean + * @return string path of cache directory */ - function template_exists($tpl_file) + public function getCacheDir() { - $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false); - return $this->_fetch_resource_info($_params); + return $this->cache_dir; } /** - * Returns an array containing template variables + * Set default modifiers * - * @param string $name - * @param string $type - * @return array + * @param array|string $modifiers modifier or list of modifiers to set + * @return Smarty current Smarty instance for chaining */ - function &get_template_vars($name=null) + public function setDefaultModifiers($modifiers) { - if(!isset($name)) { - return $this->_tpl_vars; - } elseif(isset($this->_tpl_vars[$name])) { - return $this->_tpl_vars[$name]; - } else { - // var non-existant, return valid reference - $_tmp = null; - return $_tmp; - } + $this->default_modifiers = (array) $modifiers; + return $this; } /** - * Returns an array containing config variables + * Add default modifiers * - * @param string $name - * @param string $type - * @return array + * @param array|string $modifiers modifier or list of modifiers to add + * @return Smarty current Smarty instance for chaining */ - function &get_config_vars($name=null) + public function addDefaultModifiers($modifiers) { - if(!isset($name) && is_array($this->_config[0])) { - return $this->_config[0]['vars']; - } else if(isset($this->_config[0]['vars'][$name])) { - return $this->_config[0]['vars'][$name]; + if (is_array($modifiers)) { + $this->default_modifiers = array_merge($this->default_modifiers, $modifiers); } else { - // var non-existant, return valid reference - $_tmp = null; - return $_tmp; + $this->default_modifiers[] = $modifiers; } + + return $this; } /** - * trigger Smarty error + * Get default modifiers * - * @param string $error_msg - * @param integer $error_type + * @return array list of default modifiers */ - function trigger_error($error_msg, $error_type = E_USER_WARNING) + public function getDefaultModifiers() { - trigger_error("Smarty error: $error_msg", $error_type); + return $this->default_modifiers; } /** - * executes & displays the template results + * Set autoload filters * - * @param string $resource_name - * @param string $cache_id - * @param string $compile_id + * @param array $filters filters to load automatically + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @return Smarty current Smarty instance for chaining */ - function display($resource_name, $cache_id = null, $compile_id = null) + public function setAutoloadFilters($filters, $type=null) { - $this->fetch($resource_name, $cache_id, $compile_id, true); + if ($type !== null) { + $this->autoload_filters[$type] = (array) $filters; + } else { + $this->autoload_filters = (array) $filters; + } + + return $this; } /** - * executes & returns or displays the template results + * Add autoload filters * - * @param string $resource_name - * @param string $cache_id - * @param string $compile_id - * @param boolean $display + * @param array $filters filters to load automatically + * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types + * @return Smarty current Smarty instance for chaining */ - function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false) + public function addAutoloadFilters($filters, $type=null) { - static $_cache_info = array(); - - $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting) - ? $this->error_reporting : error_reporting() & ~E_NOTICE); - - if (!$this->debugging && $this->debugging_ctrl == 'URL') { - $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING']; - if (@strstr($_query_string, $this->_smarty_debug_id)) { - if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) { - // enable debugging for this browser session - @setcookie('SMARTY_DEBUG', true); - $this->debugging = true; - } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) { - // disable debugging for this browser session - @setcookie('SMARTY_DEBUG', false); - $this->debugging = false; - } else { - // enable debugging for this page - $this->debugging = true; - } + if ($type !== null) { + if (!empty($this->autoload_filters[$type])) { + $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters); } else { - $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']); + $this->autoload_filters[$type] = (array) $filters; } - } - - if ($this->debugging) { - // capture time for debugging info - $_params = array(); - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $_debug_start_time = smarty_core_get_microtime($_params, $this); - $this->_smarty_debug_info[] = array('type' => 'template', - 'filename' => $resource_name, - 'depth' => 0); - $_included_tpls_idx = count($this->_smarty_debug_info) - 1; - } - - if (!isset($compile_id)) { - $compile_id = $this->compile_id; - } - - $this->_compile_id = $compile_id; - $this->_inclusion_depth = 0; - - if ($this->caching) { - // save old cache_info, initialize cache_info - array_push($_cache_info, $this->_cache_info); - $this->_cache_info = array(); - $_params = array( - 'tpl_file' => $resource_name, - 'cache_id' => $cache_id, - 'compile_id' => $compile_id, - 'results' => null - ); - require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php'); - if (smarty_core_read_cache_file($_params, $this)) { - $_smarty_results = $_params['results']; - if (!empty($this->_cache_info['insert_tags'])) { - $_params = array('plugins' => $this->_cache_info['insert_tags']); - require_once(SMARTY_CORE_DIR . 'core.load_plugins.php'); - smarty_core_load_plugins($_params, $this); - $_params = array('results' => $_smarty_results); - require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); - $_smarty_results = smarty_core_process_cached_inserts($_params, $this); - } - if (!empty($this->_cache_info['cache_serials'])) { - $_params = array('results' => $_smarty_results); - require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php'); - $_smarty_results = smarty_core_process_compiled_include($_params, $this); - } - - - if ($display) { - if ($this->debugging) - { - // capture time for debugging info - $_params = array(); - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time; - require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); - $_smarty_results .= smarty_core_display_debug_console($_params, $this); - } - if ($this->cache_modified_check) { - $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS']; - $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3); - $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT'; - if (@count($this->_cache_info['insert_tags']) == 0 - && !$this->_cache_serials - && $_gmt_mtime == $_last_modified_date) { - if (php_sapi_name()=='cgi') - header('Status: 304 Not Modified'); - else - header('HTTP/1.1 304 Not Modified'); - - } else { - header('Last-Modified: '.$_gmt_mtime); - echo $_smarty_results; - } - } else { - echo $_smarty_results; - } - error_reporting($_smarty_old_error_level); - // restore initial cache_info - $this->_cache_info = array_pop($_cache_info); - return true; + } else { + foreach ((array) $filters as $key => $value) { + if (!empty($this->autoload_filters[$key])) { + $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value); } else { - error_reporting($_smarty_old_error_level); - // restore initial cache_info - $this->_cache_info = array_pop($_cache_info); - return $_smarty_results; - } - } else { - $this->_cache_info['template'][$resource_name] = true; - if ($this->cache_modified_check && $display) { - header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT'); - } - } - } - - // load filters that are marked as autoload - if (count($this->autoload_filters)) { - foreach ($this->autoload_filters as $_filter_type => $_filters) { - foreach ($_filters as $_filter) { - $this->load_filter($_filter_type, $_filter); + $this->autoload_filters[$key] = (array) $value; } } } - $_smarty_compile_path = $this->_get_compile_path($resource_name); - - // if we just need to display the results, don't perform output - // buffering - for speed - $_cache_including = $this->_cache_including; - $this->_cache_including = false; - if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) { - if ($this->_is_compiled($resource_name, $_smarty_compile_path) - || $this->_compile_resource($resource_name, $_smarty_compile_path)) - { - include($_smarty_compile_path); - } - } else { - ob_start(); - if ($this->_is_compiled($resource_name, $_smarty_compile_path) - || $this->_compile_resource($resource_name, $_smarty_compile_path)) - { - include($_smarty_compile_path); - } - $_smarty_results = ob_get_contents(); - ob_end_clean(); - - foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) { - $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this)); - } - } - - if ($this->caching) { - $_params = array('tpl_file' => $resource_name, - 'cache_id' => $cache_id, - 'compile_id' => $compile_id, - 'results' => $_smarty_results); - require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php'); - smarty_core_write_cache_file($_params, $this); - require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php'); - $_smarty_results = smarty_core_process_cached_inserts($_params, $this); - - if ($this->_cache_serials) { - // strip nocache-tags from output - $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s' - ,'' - ,$_smarty_results); - } - // restore initial cache_info - $this->_cache_info = array_pop($_cache_info); - } - $this->_cache_including = $_cache_including; - - if ($display) { - if (isset($_smarty_results)) { echo $_smarty_results; } - if ($this->debugging) { - // capture time for debugging info - $_params = array(); - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time); - require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php'); - echo smarty_core_display_debug_console($_params, $this); - } - error_reporting($_smarty_old_error_level); - return; - } else { - if ($this->debugging) { - // capture time for debugging info - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime(array(), $this) - $_debug_start_time); - } - error_reporting($_smarty_old_error_level); - if (isset($_smarty_results)) { return $_smarty_results; } - } + return $this; } /** - * load configuration values + * Get autoload filters * - * @param string $file - * @param string $section - * @param string $scope + * @param string $type type of filter to get autoloads for. Defaults to all autoload filters + * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified */ - function config_load($file, $section = null, $scope = 'global') + public function getAutoloadFilters($type=null) { - require_once($this->_get_plugin_filepath('function', 'config_load')); - smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this); - } - - /** - * return a reference to a registered object - * - * @param string $name - * @return object - */ - function &get_registered_object($name) { - if (!isset($this->_reg_objects[$name])) - $this->_trigger_fatal_error("'$name' is not a registered object"); - - if (!is_object($this->_reg_objects[$name][0])) - $this->_trigger_fatal_error("registered '$name' is not an object"); + if ($type !== null) { + return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array(); + } - return $this->_reg_objects[$name][0]; + return $this->autoload_filters; } /** - * clear configuration values + * return name of debugging template * - * @param string $var + * @return string */ - function clear_config($var = null) + public function getDebugTemplate() { - if(!isset($var)) { - // clear all values - $this->_config = array(array('vars' => array(), - 'files' => array())); - } else { - unset($this->_config[0]['vars'][$var]); - } + return $this->debug_tpl; } /** - * get filepath of requested plugin + * set the debug template * - * @param string $type - * @param string $name - * @return string|false + * @param string $tpl_name + * @return Smarty current Smarty instance for chaining + * @throws SmartyException if file is not readable */ - function _get_plugin_filepath($type, $name) + public function setDebugTemplate($tpl_name) { - $_params = array('type' => $type, 'name' => $name); - require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php'); - return smarty_core_assemble_plugin_filepath($_params, $this); - } - - /** - * test if resource needs compiling - * - * @param string $resource_name - * @param string $compile_path - * @return boolean - */ - function _is_compiled($resource_name, $compile_path) - { - if (!$this->force_compile && file_exists($compile_path)) { - if (!$this->compile_check) { - // no need to check compiled file - return true; - } else { - // get file source and timestamp - $_params = array('resource_name' => $resource_name, 'get_source'=>false); - if (!$this->_fetch_resource_info($_params)) { - return false; - } - if ($_params['resource_timestamp'] <= filemtime($compile_path)) { - // template not expired, no recompile - return true; - } else { - // compile template - return false; - } - } - } else { - // compiled template does not exist, or forced compile - return false; + if (!is_readable($tpl_name)) { + throw new SmartyException("Unknown file '{$tpl_name}'"); } + $this->debug_tpl = $tpl_name; + + return $this; } - /** - * compile the template + /** + * creates a template object * - * @param string $resource_name - * @param string $compile_path - * @return boolean + * @param string $template the resource handle of the template file + * @param mixed $cache_id cache id to be used with this template + * @param mixed $compile_id compile id to be used with this template + * @param object $parent next higher level of Smarty variables + * @param boolean $do_clone flag is Smarty object shall be cloned + * @return object template object */ - function _compile_resource($resource_name, $compile_path) + public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) { - - $_params = array('resource_name' => $resource_name); - if (!$this->_fetch_resource_info($_params)) { - return false; + if (!empty($cache_id) && (is_object($cache_id) || is_array($cache_id))) { + $parent = $cache_id; + $cache_id = null; } - - $_source_content = $_params['source_content']; - $_cache_include = substr($compile_path, 0, -4).'.inc'; - - if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) { - // if a _cache_serial was set, we also have to write an include-file: - if ($this->_cache_include_info) { - require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php'); - smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)), $this); - } - - $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content); - require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php'); - smarty_core_write_compiled_resource($_params, $this); - - return true; + if (!empty($parent) && is_array($parent)) { + $data = $parent; + $parent = null; } else { - return false; + $data = null; } - - } - - /** - * compile the given source - * - * @param string $resource_name - * @param string $source_content - * @param string $compiled_content - * @return boolean - */ - function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null) - { - if (file_exists(SMARTY_DIR . $this->compiler_file)) { - require_once(SMARTY_DIR . $this->compiler_file); + // default to cache_id and compile_id of Smarty object + $cache_id = $cache_id === null ? $this->cache_id : $cache_id; + $compile_id = $compile_id === null ? $this->compile_id : $compile_id; + // already in template cache? + if ($this->allow_ambiguous_resources) { + $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id; } else { - // use include_path - require_once($this->compiler_file); - } - - - $smarty_compiler = new $this->compiler_class; - - $smarty_compiler->template_dir = $this->template_dir; - $smarty_compiler->compile_dir = $this->compile_dir; - $smarty_compiler->plugins_dir = $this->plugins_dir; - $smarty_compiler->config_dir = $this->config_dir; - $smarty_compiler->force_compile = $this->force_compile; - $smarty_compiler->caching = $this->caching; - $smarty_compiler->php_handling = $this->php_handling; - $smarty_compiler->left_delimiter = $this->left_delimiter; - $smarty_compiler->right_delimiter = $this->right_delimiter; - $smarty_compiler->_version = $this->_version; - $smarty_compiler->security = $this->security; - $smarty_compiler->secure_dir = $this->secure_dir; - $smarty_compiler->security_settings = $this->security_settings; - $smarty_compiler->trusted_dir = $this->trusted_dir; - $smarty_compiler->use_sub_dirs = $this->use_sub_dirs; - $smarty_compiler->_reg_objects = &$this->_reg_objects; - $smarty_compiler->_plugins = &$this->_plugins; - $smarty_compiler->_tpl_vars = &$this->_tpl_vars; - $smarty_compiler->default_modifiers = $this->default_modifiers; - $smarty_compiler->compile_id = $this->_compile_id; - $smarty_compiler->_config = $this->_config; - $smarty_compiler->request_use_auto_globals = $this->request_use_auto_globals; - - if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) { - $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path]; + $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id; } - $smarty_compiler->_cache_include = $cache_include_path; - - - $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content); - - if ($smarty_compiler->_cache_serial) { - $this->_cache_include_info = array( - 'cache_serial'=>$smarty_compiler->_cache_serial - ,'plugins_code'=>$smarty_compiler->_plugins_code - ,'include_file_path' => $cache_include_path); - - } else { - $this->_cache_include_info = null; - + if (isset($_templateId[150])) { + $_templateId = sha1($_templateId); } - - return $_results; - } - - /** - * Get the compile path for this resource - * - * @param string $resource_name - * @return string results of {@link _get_auto_filename()} - */ - function _get_compile_path($resource_name) - { - return $this->_get_auto_filename($this->compile_dir, $resource_name, - $this->_compile_id) . '.php'; - } - - /** - * fetch the template info. Gets timestamp, and source - * if get_source is true - * - * sets $source_content to the source of the template, and - * $resource_timestamp to its time stamp - * @param string $resource_name - * @param string $source_content - * @param integer $resource_timestamp - * @param boolean $get_source - * @param boolean $quiet - * @return boolean - */ - - function _fetch_resource_info(&$params) - { - if(!isset($params['get_source'])) { $params['get_source'] = true; } - if(!isset($params['quiet'])) { $params['quiet'] = false; } - - $_return = false; - $_params = array('resource_name' => $params['resource_name']) ; - if (isset($params['resource_base_path'])) - $_params['resource_base_path'] = $params['resource_base_path']; - else - $_params['resource_base_path'] = $this->template_dir; - - if ($this->_parse_resource_name($_params)) { - $_resource_type = $_params['resource_type']; - $_resource_name = $_params['resource_name']; - switch ($_resource_type) { - case 'file': - if ($params['get_source']) { - $params['source_content'] = $this->_read_file($_resource_name); - } - $params['resource_timestamp'] = filemtime($_resource_name); - $_return = is_file($_resource_name) && is_readable($_resource_name); - break; - - default: - // call resource functions to fetch the template source and timestamp - if ($params['get_source']) { - $_source_return = isset($this->_plugins['resource'][$_resource_type]) && - call_user_func_array($this->_plugins['resource'][$_resource_type][0][0], - array($_resource_name, &$params['source_content'], &$this)); - } else { - $_source_return = true; - } - - $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) && - call_user_func_array($this->_plugins['resource'][$_resource_type][0][1], - array($_resource_name, &$params['resource_timestamp'], &$this)); - - $_return = $_source_return && $_timestamp_return; - break; + if ($do_clone) { + if (isset($this->template_objects[$_templateId])) { + // return cached template object + $tpl = clone $this->template_objects[$_templateId]; + $tpl->smarty = clone $tpl->smarty; + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); + } else { + $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id); } - } - - if (!$_return) { - // see if we can get a template with the default template handler - if (!empty($this->default_template_handler_func)) { - if (!is_callable($this->default_template_handler_func)) { - $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist."); - } else { - $_return = call_user_func_array( - $this->default_template_handler_func, - array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this)); - } + } else { + if (isset($this->template_objects[$_templateId])) { + // return cached template object + $tpl = $this->template_objects[$_templateId]; + $tpl->parent = $parent; + $tpl->tpl_vars = array(); + $tpl->config_vars = array(); + } else { + $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); } } - - if (!$_return) { - if (!$params['quiet']) { - $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"'); - } - } else if ($_return && $this->security) { - require_once(SMARTY_CORE_DIR . 'core.is_secure.php'); - if (!smarty_core_is_secure($_params, $this)) { - if (!$params['quiet']) - $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed'); - $params['source_content'] = null; - $params['resource_timestamp'] = null; - return false; + // fill data if present + if (!empty($data) && is_array($data)) { + // set up variable values + foreach ($data as $_key => $_val) { + $tpl->tpl_vars[$_key] = new Smarty_variable($_val); } } - return $_return; + return $tpl; } /** - * parse out the type and name from the resource + * Takes unknown classes and loads plugin files for them + * class name format: Smarty_PluginType_PluginName + * plugin filename format: plugintype.pluginname.php * - * @param string $resource_base_path - * @param string $resource_name - * @param string $resource_type - * @param string $resource_name - * @return boolean + * @param string $plugin_name class plugin name to load + * @param bool $check check if already loaded + * @return string |boolean filepath of loaded file or false */ - - function _parse_resource_name(&$params) + public function loadPlugin($plugin_name, $check = true) { - - // split tpl_path by the first colon - $_resource_name_parts = explode(':', $params['resource_name'], 2); - - if (count($_resource_name_parts) == 1) { - // no resource type given - $params['resource_type'] = $this->default_resource_type; - $params['resource_name'] = $_resource_name_parts[0]; - } else { - if(strlen($_resource_name_parts[0]) == 1) { - // 1 char is not resource type, but part of filepath - $params['resource_type'] = $this->default_resource_type; - $params['resource_name'] = $params['resource_name']; + // if function or class exists, exit silently (already loaded) + if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) { + return true; + } + // Plugin name is expected to be: Smarty_[Type]_[Name] + $_name_parts = explode('_', $plugin_name, 3); + // class name must have three parts to be valid plugin + // count($_name_parts) < 3 === !isset($_name_parts[2]) + if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') { + throw new SmartyException("plugin {$plugin_name} is not a valid name format"); + return false; + } + // if type is "internal", get plugin from sysplugins + if (strtolower($_name_parts[1]) == 'internal') { + $file = SMARTY_SYSPLUGINS_DIR . strtolower($plugin_name) . '.php'; + if (file_exists($file)) { + require_once($file); + return $file; } else { - $params['resource_type'] = $_resource_name_parts[0]; - $params['resource_name'] = $_resource_name_parts[1]; + return false; } } + // plugin filename is expected to be: [type].[name].php + $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php"; - if ($params['resource_type'] == 'file') { - if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) { - // relative pathname to $params['resource_base_path'] - // use the first directory where the file is found - foreach ((array)$params['resource_base_path'] as $_curr_path) { - $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name']; - if (file_exists($_fullpath) && is_file($_fullpath)) { - $params['resource_name'] = $_fullpath; - return true; + $_stream_resolve_include_path = function_exists('stream_resolve_include_path'); + + // loop through plugin dirs and find the plugin + foreach($this->getPluginsDir() as $_plugin_dir) { + $names = array( + $_plugin_dir . $_plugin_filename, + $_plugin_dir . strtolower($_plugin_filename), + ); + foreach ($names as $file) { + if (file_exists($file)) { + require_once($file); + return $file; + } + if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) { + // try PHP include_path + if ($_stream_resolve_include_path) { + $file = stream_resolve_include_path($file); + } else { + $file = Smarty_Internal_Get_Include_Path::getIncludePath($file); } - // didn't find the file, try include_path - $_params = array('file_path' => $_fullpath); - require_once(SMARTY_CORE_DIR . 'core.get_include_path.php'); - if(smarty_core_get_include_path($_params, $this)) { - $params['resource_name'] = $_params['new_file_path']; - return true; + + if ($file !== false) { + require_once($file); + return $file; } } - return false; - } else { - /* absolute path */ - return file_exists($params['resource_name']); } - } elseif (empty($this->_plugins['resource'][$params['resource_type']])) { - $_params = array('type' => $params['resource_type']); - require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php'); - smarty_core_load_resource_plugin($_params, $this); } - - return true; + // no plugin loaded + return false; } - /** - * Handle modifiers + * Compile all template files * - * @param string|null $modifier_name - * @param array|null $map_array - * @return string result of modifiers + * @param string $extension file extension + * @param bool $force_compile force all to recompile + * @param int $time_limit + * @param int $max_errors + * @return integer number of template files recompiled */ - function _run_mod_handler() + public function compileAllTemplates($extention = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null) { - $_args = func_get_args(); - list($_modifier_name, $_map_array) = array_splice($_args, 0, 2); - list($_func_name, $_tpl_file, $_tpl_line) = - $this->_plugins['modifier'][$_modifier_name]; - - $_var = $_args[0]; - foreach ($_var as $_key => $_val) { - $_args[0] = $_val; - $_var[$_key] = call_user_func_array($_func_name, $_args); - } - return $_var; + return Smarty_Internal_Utility::compileAllTemplates($extention, $force_compile, $time_limit, $max_errors, $this); } /** - * Remove starting and ending quotes from the string + * Compile all config files * - * @param string $string - * @return string + * @param string $extension file extension + * @param bool $force_compile force all to recompile + * @param int $time_limit + * @param int $max_errors + * @return integer number of template files recompiled */ - function _dequote($string) + public function compileAllConfig($extention = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null) { - if ((substr($string, 0, 1) == "'" || substr($string, 0, 1) == '"') && - substr($string, -1) == substr($string, 0, 1)) - return substr($string, 1, -1); - else - return $string; + return Smarty_Internal_Utility::compileAllConfig($extention, $force_compile, $time_limit, $max_errors, $this); } - /** - * read in a file + * Delete compiled template file * - * @param string $filename - * @return string + * @param string $resource_name template name + * @param string $compile_id compile id + * @param integer $exp_time expiration time + * @return integer number of template files deleted */ - function _read_file($filename) + public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null) { - if ( file_exists($filename) && is_readable($filename) && ($fd = @fopen($filename, 'rb')) ) { - $contents = ''; - while (!feof($fd)) { - $contents .= fread($fd, 8192); - } - fclose($fd); - return $contents; - } else { - return false; - } + return Smarty_Internal_Utility::clearCompiledTemplate($resource_name, $compile_id, $exp_time, $this); } - /** - * get a concrete filename for automagically created content - * - * @param string $auto_base - * @param string $auto_source - * @param string $auto_id - * @return string - * @staticvar string|null - * @staticvar string|null - */ - function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null) - { - $_compile_dir_sep = $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; - $_return = $auto_base . DIRECTORY_SEPARATOR; - - if(isset($auto_id)) { - // make auto_id safe for directory names - $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id))); - // split into separate directories - $_return .= $auto_id . $_compile_dir_sep; - } - - if(isset($auto_source)) { - // make source name safe for filename - $_filename = urlencode(basename($auto_source)); - $_crc32 = sprintf('%08X', crc32($auto_source)); - // prepend %% to avoid name conflicts with - // with $params['auto_id'] names - $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep . - substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32; - $_return .= '%%' . $_crc32 . '%%' . $_filename; - } - - return $_return; - } /** - * unlink a file, possibly using expiration time + * Return array of tag/attributes of all tags used by an template * - * @param string $resource - * @param integer $exp_time + * @param object $templae template object + * @return array of tag/attributes */ - function _unlink($resource, $exp_time = null) + public function getTags(Smarty_Internal_Template $template) { - if(isset($exp_time)) { - if(time() - @filemtime($resource) >= $exp_time) { - return @unlink($resource); - } - } else { - return @unlink($resource); - } - } - - /** - * returns an auto_id for auto-file-functions - * - * @param string $cache_id - * @param string $compile_id - * @return string|null - */ - function _get_auto_id($cache_id=null, $compile_id=null) { - if (isset($cache_id)) - return (isset($compile_id)) ? $cache_id . '|' . $compile_id : $cache_id; - elseif(isset($compile_id)) - return $compile_id; - else - return null; + return Smarty_Internal_Utility::getTags($template); } /** - * trigger Smarty plugin error + * Run installation test * - * @param string $error_msg - * @param string $tpl_file - * @param integer $tpl_line - * @param string $file - * @param integer $line - * @param integer $error_type - */ - function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null, - $file = null, $line = null, $error_type = E_USER_ERROR) - { - if(isset($file) && isset($line)) { - $info = ' ('.basename($file).", line $line)"; - } else { - $info = ''; - } - if (isset($tpl_line) && isset($tpl_file)) { - $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type); - } else { - $this->trigger_error($error_msg . $info, $error_type); - } - } - - - /** - * callback function for preg_replace, to call a non-cacheable block - * @return string + * @param array $errors Array to write errors into, rather than outputting them + * @return boolean true if setup is fine, false if something is wrong */ - function _process_compiled_include_callback($match) { - $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3]; - ob_start(); - $_func($this); - $_ret = ob_get_contents(); - ob_end_clean(); - return $_ret; + public function testInstall(&$errors=null) + { + return Smarty_Internal_Utility::testInstall($this, $errors); } - /** - * called for included templates + * Error Handler to mute expected messages * - * @param string $_smarty_include_tpl_file - * @param string $_smarty_include_vars + * @link http://php.net/set_error_handler + * @param integer $errno Error level + * @return boolean */ - - // $_smarty_include_tpl_file, $_smarty_include_vars - - function _smarty_include($params) + public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) { - if ($this->debugging) { - $_params = array(); - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $debug_start_time = smarty_core_get_microtime($_params, $this); - $this->_smarty_debug_info[] = array('type' => 'template', - 'filename' => $params['smarty_include_tpl_file'], - 'depth' => ++$this->_inclusion_depth); - $included_tpls_idx = count($this->_smarty_debug_info) - 1; - } - - $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']); - - // config vars are treated as local, so push a copy of the - // current ones onto the front of the stack - array_unshift($this->_config, $this->_config[0]); - - $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']); - - - if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path) - || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path)) - { - include($_smarty_compile_path); - } - - // pop the local vars off the front of the stack - array_shift($this->_config); - - $this->_inclusion_depth--; - - if ($this->debugging) { - // capture time for debugging info - $_params = array(); - require_once(SMARTY_CORE_DIR . 'core.get_microtime.php'); - $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time; + $_is_muted_directory = false; + + // add the SMARTY_DIR to the list of muted directories + if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) { + $smarty_dir = realpath(SMARTY_DIR); + if ($smarty_dir !== false) { + Smarty::$_muted_directories[SMARTY_DIR] = array( + 'file' => $smarty_dir, + 'length' => strlen($smarty_dir), + ); + } } - if ($this->caching) { - $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true; + // walk the muted directories and test against $errfile + foreach (Smarty::$_muted_directories as $key => &$dir) { + if (!$dir) { + // resolve directory and length for speedy comparisons + $file = realpath($key); + if ($file === false) { + // this directory does not exist, remove and skip it + unset(Smarty::$_muted_directories[$key]); + continue; + } + $dir = array( + 'file' => $file, + 'length' => strlen($file), + ); + } + if (!strncmp($errfile, $dir['file'], $dir['length'])) { + $_is_muted_directory = true; + break; + } } - } - - - /** - * get or set an array of cached attributes for function that is - * not cacheable - * @return array - */ - function &_smarty_cache_attrs($cache_serial, $count) { - $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count]; - - if ($this->_cache_including) { - /* return next set of cache_attrs */ - $_return = current($_cache_attrs); - next($_cache_attrs); - return $_return; - - } else { - /* add a reference to a new set of cache_attrs */ - $_cache_attrs[] = array(); - return $_cache_attrs[count($_cache_attrs)-1]; + // pass to next error handler if this error did not occur inside SMARTY_DIR + // or the error was within smarty but masked to be ignored + if (!$_is_muted_directory || ($errno && $errno & error_reporting())) { + if (Smarty::$_previous_error_handler) { + return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext); + } else { + return false; + } } - } - /** - * wrapper for include() retaining $this - * @return mixed + * Enable error handler to mute expected messages + * + * @return void */ - function _include($filename, $once=false, $params=null) + public static function muteExpectedErrors() { - if ($once) { - return include_once($filename); - } else { - return include($filename); + /* + error muting is done because some people implemented custom error_handlers using + http://php.net/set_error_handler and for some reason did not understand the following paragraph: + + It is important to remember that the standard PHP error handler is completely bypassed for the + error types specified by error_types unless the callback function returns FALSE. + error_reporting() settings will have no effect and your error handler will be called regardless - + however you are still able to read the current value of error_reporting and act appropriately. + Of particular note is that this value will be 0 if the statement that caused the error was + prepended by the @ error-control operator. + + Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include + - @filemtime() is almost twice as fast as using an additional file_exists() + - between file_exists() and filemtime() a possible race condition is opened, + which does not exist using the simple @filemtime() approach. + */ + $error_handler = array('Smarty', 'mutingErrorHandler'); + $previous = set_error_handler($error_handler); + + // avoid dead loops + if ($previous !== $error_handler) { + Smarty::$_previous_error_handler = $previous; } } - /** - * wrapper for eval() retaining $this - * @return mixed + * Disable error handler muting expected messages + * + * @return void */ - function _eval($code, $params=null) + public static function unmuteExpectedErrors() { - return eval($code); + restore_error_handler(); } +} - /** - * Extracts the filter name from the given callback - * - * @param callback $function - * @return string - */ - function _get_filter_name($function) - { - if (is_array($function)) { - $_class_name = (is_object($function[0]) ? - get_class($function[0]) : $function[0]); - return $_class_name . '_' . $function[1]; - } - else { - return $function; - } - } +// Check if we're running on windows +Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'; - /**#@-*/ +// let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8 +if (Smarty::$_CHARSET !== 'UTF-8') { + Smarty::$_UTF8_MODIFIER = ''; +} +/** + * Smarty exception class + * @package Smarty + */ +class SmartyException extends Exception { + public static $escape = true; + public function __construct($message) { + $this->message = self::$escape ? htmlentities($message) : $message; + } } -/* vim: set expandtab: */ +/** + * Smarty compiler exception class + * @package Smarty + */ +class SmartyCompilerException extends SmartyException { +} + +/** + * Autoloader + */ +function smartyAutoload($class) +{ + $_class = strtolower($class); + $_classes = array( + 'smarty_config_source' => true, + 'smarty_config_compiled' => true, + 'smarty_security' => true, + 'smarty_cacheresource' => true, + 'smarty_cacheresource_custom' => true, + 'smarty_cacheresource_keyvaluestore' => true, + 'smarty_resource' => true, + 'smarty_resource_custom' => true, + 'smarty_resource_uncompiled' => true, + 'smarty_resource_recompiled' => true, + ); + + if (!strncmp($_class, 'smarty_internal_', 16) || isset($_classes[$_class])) { + include SMARTY_SYSPLUGINS_DIR . $_class . '.php'; + } +} ?> |