home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / Smarty.class.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  86.8 KB  |  2,678 lines

  1. <?php
  2. /**
  3.  * Project:     Smarty: the PHP compiling template engine
  4.  * File:        Smarty.class.php
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2.1 of the License, or (at your option) any later version.
  10.  *
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  *
  20.  * For questions, help, comments, discussion, etc., please join the
  21.  * Smarty mailing list. Send a blank e-mail to
  22.  * smarty-general-subscribe@lists.php.net
  23.  *
  24.  * You may contact the authors of Smarty by e-mail at:
  25.  * monte@ispi.net
  26.  * andrei@php.net
  27.  *
  28.  * Or, write to:
  29.  * Monte Ohrt
  30.  * Director of Technology, ispi
  31.  * 237 S. 70th suite 220
  32.  * Lincoln, NE 68510
  33.  *
  34.  * The latest version of Smarty can be obtained from:
  35.  * http://smarty.php.net/
  36.  *
  37.  * @link http://smarty.php.net/
  38.  * @copyright 2001,2002 ispi of Lincoln, Inc.
  39.  * @author Monte Ohrt <monte@ispi.net>
  40.  * @author Andrei Zmievski <andrei@php.net>
  41.  * @package Smarty
  42.  * @version 2.5.0
  43.  */
  44.  
  45. /* $Id: Smarty.class.php,v 1.4 2003/04/23 20:21:45 CelloG Exp $ */
  46.  
  47. /**
  48.  * set SMARTY_DIR to absolute path to Smarty library files.
  49.  * if not defined, include_path will be used.
  50.  */
  51.  
  52. define('DIR_SEP', DIRECTORY_SEPARATOR);
  53.  
  54. /**
  55.  * Sets SMARTY_DIR only if user application has not already defined it
  56.  */
  57. if (!defined('SMARTY_DIR')) {
  58.     define('SMARTY_DIR', dirname(__FILE__) . DIR_SEP);
  59. }
  60.  
  61. define('SMARTY_PHP_PASSTHRU',   0);
  62. define('SMARTY_PHP_QUOTE',      1);
  63. define('SMARTY_PHP_REMOVE',     2);
  64. define('SMARTY_PHP_ALLOW',      3);
  65.  
  66. /**
  67.  * @package Smarty
  68.  */
  69. class Smarty
  70. {
  71.     /**#@+
  72.      * Smarty Configuration Section
  73.      */
  74.  
  75.     /**
  76.      * The name of the directory where templates are located.
  77.      * 
  78.      * @var string
  79.      */
  80.     var $template_dir    =  'templates';
  81.  
  82.     /**
  83.      * The directory where compiled templates are located.
  84.      * 
  85.      * @var string
  86.      */
  87.     var $compile_dir     =  'templates_c';
  88.  
  89.     /**
  90.      * The directory where config files are located.
  91.      * 
  92.      * @var string
  93.      */
  94.     var $config_dir      =  'configs';
  95.  
  96.     /**
  97.      * An array of directories searched for plugins.
  98.      * 
  99.      * @var array
  100.      */
  101.     var $plugins_dir     =  array('plugins');
  102.  
  103.     /**
  104.      * If debugging is enabled, a debug console window will display
  105.      * when the page loads (make sure your browser allows unrequested
  106.      * popup windows)
  107.      * 
  108.      * @var boolean
  109.      */
  110.     var $debugging       =  false;
  111.  
  112.     /**
  113.      * This is the path to the debug console template. If not set,
  114.      * the default one will be used.
  115.      * 
  116.      * @var string
  117.      */
  118.     var $debug_tpl       =  '';
  119.  
  120.     /**
  121.      * This determines if debugging is enable-able from the browser.
  122.      * <ul>
  123.      *  <li>NONE => no debugging control allowed</li>
  124.      *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
  125.      * </ul>
  126.      * @link http://www.foo.dom/index.php?SMARTY_DEBUG
  127.      * @var string
  128.      */
  129.     var $debugging_ctrl  =  'NONE';
  130.  
  131.     /**
  132.      * This tells Smarty whether to check for recompiling or not. Recompiling
  133.      * does not need to happen unless a template or config file is changed. 
  134.      * Typically you enable this during development, and disable for
  135.      * production.
  136.      * 
  137.      * @var boolean
  138.      */
  139.     var $compile_check   =  true;
  140.  
  141.     /**
  142.      * This forces templates to compile every time. Useful for development
  143.      * or debugging.
  144.      * 
  145.      * @var boolean
  146.      */
  147.     var $force_compile   =  false;
  148.  
  149.     /**
  150.      * This enables template caching.
  151.      * <ul>
  152.      *  <li>0 = no caching</li>
  153.      *  <li>1 = use class cache_lifetime value</li>
  154.      *  <li>2 = use cache_lifetime in cache file</li>
  155.      * </ul>
  156.      * @var integer
  157.      */
  158.     var $caching         =  0;
  159.  
  160.     /**
  161.      * The name of the directory for cache files.
  162.      * 
  163.      * @var string
  164.      */
  165.     var $cache_dir       =  'cache';
  166.  
  167.     /**
  168.      * This is the number of seconds cached content will persist.
  169.      * <ul>
  170.      *  <li>0 = always regenerate cache</li>
  171.      *  <li>-1 = never expires</li>
  172.      * </ul>
  173.      * 
  174.      * @var integer
  175.      */
  176.     var $cache_lifetime  =  3600;
  177.  
  178.     /**
  179.      * Only used when $caching is enabled. If true, then If-Modified-Since headers
  180.      * are respected with cached content, and appropriate HTTP headers are sent.
  181.      * This way repeated hits to a cached page do not send the entire page to the
  182.      * client every time.
  183.      * 
  184.      * @var boolean
  185.      */
  186.     var $cache_modified_check = false;
  187.  
  188.     /**
  189.      * This determines how Smarty handles "<?php ... ?>" tags in templates.
  190.      * possible values:
  191.      * <ul>
  192.      *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
  193.      *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>
  194.      *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>
  195.      *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>
  196.      * </ul>
  197.      *
  198.      * @var integer
  199.      */
  200.     var $php_handling    =  SMARTY_PHP_PASSTHRU;
  201.  
  202.     /**
  203.      * This enables template security. When enabled, many things are restricted
  204.      * in the templates that normally would go unchecked. This is useful when
  205.      * untrusted parties are editing templates and you want a reasonable level
  206.      * of security. (no direct execution of PHP in templates for example)
  207.      * 
  208.      * @var boolean
  209.      */
  210.     var $security       =   false;
  211.  
  212.     /**
  213.      * This is the list of template directories that are considered secure. This
  214.      * is used only if {@link $security} is enabled. One directory per array
  215.      * element.  {@link $template_dir} is in this list implicitly.
  216.      * 
  217.      * @var array
  218.      */
  219.     var $secure_dir     =   array();
  220.  
  221.     /**
  222.      * These are the security settings for Smarty. They are used only when
  223.      * {@link $security} is enabled.
  224.      * 
  225.      * @var array
  226.      */
  227.     var $security_settings  = array(
  228.                                     'PHP_HANDLING'    => false,
  229.                                     'IF_FUNCS'        => array('array', 'list',
  230.                                                                'isset', 'empty',
  231.                                                                'count', 'sizeof',
  232.                                                                'in_array', 'is_array',
  233.                                                                'true','false'),
  234.                                     'INCLUDE_ANY'     => false,
  235.                                     'PHP_TAGS'        => false,
  236.                                     'MODIFIER_FUNCS'  => array('count'),
  237.                                     'ALLOW_CONSTANTS' => false
  238.                                    );
  239.  
  240.     /**
  241.      * This is an array of directories where trusted php scripts reside.
  242.      * {@link $security} is disabled during their inclusion/execution.
  243.      *
  244.      * @var array
  245.      */
  246.     var $trusted_dir        = array();
  247.  
  248.     /**
  249.      * The left delimiter used for the template tags.
  250.      * 
  251.      * @var string
  252.      */
  253.     var $left_delimiter  =  '{';
  254.  
  255.     /**
  256.      * The right delimiter used for the template tags.
  257.      * 
  258.      * @var string
  259.      */
  260.     var $right_delimiter =  '}';
  261.  
  262.     /**
  263.      * The order in which request variables are registered, similar to
  264.      * variables_order in php.ini E = Environment, G = GET, P = POST,
  265.      * C = Cookies, S = Server
  266.      * 
  267.      * @var string
  268.      */
  269.     var $request_vars_order    = "EGPCS"; 
  270.  
  271.     /**
  272.      * Set this if you want different sets of compiled files for the same
  273.      * templates. This is useful for things like different languages.
  274.      * Instead of creating separate sets of templates per language, you
  275.      * set different compile_ids like 'en' and 'de'.
  276.      *
  277.      * @var string
  278.      */
  279.     var $compile_id            = null;
  280.  
  281.     /**
  282.      * This tells Smarty whether or not to use sub dirs in the cache/ and
  283.      * templates_c/ directories. sub directories better organized, but
  284.      * may not work well with PHP safe mode enabled.
  285.      * 
  286.      * @var boolean
  287.      * 
  288.      */
  289.     var $use_sub_dirs          = false;
  290.  
  291.     /**
  292.      * This is a list of the modifiers to apply to all template variables.
  293.      * Put each modifier in a separate array element in the order you want
  294.      * them applied. example: <code>array('escape:"htmlall"');</code>
  295.      *
  296.      * @var array
  297.      */
  298.     var $default_modifiers        = array();
  299.  
  300.     /**
  301.      * The function used for cache file handling. If not set, built-in caching is used.
  302.      * 
  303.      * @var null|string function name
  304.      */
  305.     var $cache_handler_func   = null;
  306.      
  307.     /**
  308.      * These are the variables from the globals array that are
  309.      * assigned to all templates automatically. This isn't really
  310.      * necessary any more, you can use the $smarty var to access them
  311.      * directly.
  312.      * 
  313.      * @var array
  314.      */
  315.     var $global_assign   =  array('HTTP_SERVER_VARS' => array('SCRIPT_NAME'));
  316.  
  317.     /**
  318.      * The value of "undefined". Leave it alone :-)
  319.      * 
  320.      * @var null
  321.      */
  322.     var $undefined       =  null;
  323.  
  324.     /**
  325.      * This indicates which filters are automatically loaded into Smarty.
  326.      * 
  327.      * @var array array of filter names
  328.      */
  329.     var $autoload_filters = array();
  330.  
  331.     /**#@+
  332.      * @var boolean
  333.      */     
  334.     /**
  335.      * This tells if config file vars of the same name overwrite each other or not.
  336.      * if disabled, same name variables are accumulated in an array.
  337.      */
  338.     var $config_overwrite = true;
  339.  
  340.     /**
  341.      * This tells whether or not to automatically booleanize config file variables.
  342.      * If enabled, then the strings "on", "true", and "yes" are treated as boolean
  343.      * true, and "off", "false" and "no" are treated as boolean false.
  344.      */
  345.     var $config_booleanize = true;
  346.  
  347.     /**
  348.      * This tells whether hidden sections [.foobar] are readable from the
  349.      * tempalates or not. Normally you would never allow this since that is
  350.      * the point behind hidden sections: the application can access them, but
  351.      * the templates cannot.
  352.      */
  353.     var $config_read_hidden = false;
  354.  
  355.     /**
  356.      * This tells whether or not automatically fix newlines in config files.
  357.      * It basically converts \r (mac) or \r\n (dos) to \n
  358.      */
  359.     var $config_fix_newlines = true;
  360.     /**#@-*/
  361.      
  362.     /**
  363.      * If a template cannot be found, this PHP function will be executed.
  364.      * Useful for creating templates on-the-fly or other special action.
  365.      * 
  366.      * @var string function name
  367.      */
  368.     var $default_template_handler_func = '';
  369.  
  370.     /**
  371.      * The file that contains the compiler class. This can a full
  372.      * pathname, or relative to the php_include path.
  373.      * 
  374.      * @var string
  375.      */
  376.     var $compiler_file        =    'Smarty_Compiler.class.php';
  377.  
  378.     /**
  379.      * The class used for compiling templates.
  380.      * 
  381.      * @var string
  382.      */
  383.     var $compiler_class        =   'Smarty_Compiler';
  384.  
  385.     /**
  386.      * The class used to load config vars.
  387.      *
  388.      * @var string
  389.      */
  390.     var $config_class          =   'Config_File';
  391.  
  392. /**#@+
  393.  * END Smarty Configuration Section
  394.  * There should be no need to touch anything below this line.
  395.  * @access private
  396.  */
  397.     /**
  398.      * error messages. true/false
  399.      *
  400.      * @var boolean
  401.      */
  402.     var $_error_msg            = false;
  403.  
  404.     /**
  405.      * where assigned template vars are kept
  406.      *
  407.      * @var array
  408.      */
  409.     var $_tpl_vars             = array();
  410.  
  411.     /**
  412.      * stores run-time $smarty.* vars
  413.      *
  414.      * @var null|array
  415.      */
  416.     var $_smarty_vars          = null;
  417.  
  418.     /**
  419.      * keeps track of sections
  420.      *
  421.      * @var array
  422.      */
  423.     var $_sections             = array();
  424.  
  425.     /**
  426.      * keeps track of foreach blocks
  427.      *
  428.      * @var array
  429.      */
  430.     var $_foreach              = array();
  431.  
  432.     /**
  433.      * keeps track of tag hierarchy
  434.      *
  435.      * @var array
  436.      */
  437.     var $_tag_stack            = array();
  438.  
  439.     /**
  440.      * configuration object
  441.      *
  442.      * @var Config_file
  443.      */
  444.     var $_conf_obj             = null;
  445.  
  446.     /**
  447.      * loaded configuration settings
  448.      *
  449.      * @var array
  450.      */
  451.     var $_config               = array(array('vars'  => array(), 'files' => array()));
  452.  
  453.     /**
  454.      * md5 checksum of the string 'Smarty'
  455.      *
  456.      * @var string
  457.      */
  458.     var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';
  459.  
  460.     /**
  461.      * Smarty version number
  462.      *
  463.      * @var string
  464.      */
  465.     var $_version              = '2.5.0';
  466.  
  467.     /**
  468.      * current template inclusion depth
  469.      *
  470.      * @var integer
  471.      */
  472.     var $_inclusion_depth      = 0;
  473.  
  474.     /**
  475.      * for different compiled templates
  476.      *
  477.      * @var string
  478.      */
  479.     var $_compile_id           = null;
  480.  
  481.     /**
  482.      * text in URL to enable debug mode
  483.      *
  484.      * @var string
  485.      */
  486.     var $_smarty_debug_id      = 'SMARTY_DEBUG';
  487.  
  488.     /**
  489.      * debugging information for debug console
  490.      *
  491.      * @var array
  492.      */
  493.     var $_smarty_debug_info    = array();
  494.  
  495.     /**
  496.      * info that makes up a cache file
  497.      *
  498.      * @var array
  499.      */
  500.     var $_cache_info           = array();
  501.  
  502.     /**
  503.      * default file permissions
  504.      *
  505.      * @var integer
  506.      */
  507.     var $_file_perms           = 0644;
  508.  
  509.     /**
  510.      * default dir permissions
  511.      *
  512.      * @var integer
  513.      */
  514.     var $_dir_perms               = 0771;
  515.  
  516.     /**
  517.      * registered objects
  518.      *
  519.      * @var array
  520.      */
  521.     var $_reg_objects           = array();
  522.  
  523.     /**
  524.      * table keeping track of plugins
  525.      *
  526.      * @var array
  527.      */
  528.     var $_plugins              = array(
  529.                                        'modifier'      => array(),
  530.                                        'function'      => array(),
  531.                                        'block'         => array(),
  532.                                        'compiler'      => array(),
  533.                                        'prefilter'     => array(),
  534.                                        'postfilter'    => array(),
  535.                                        'outputfilter'  => array(),
  536.                                        'resource'      => array(),
  537.                                        'insert'        => array());
  538.  
  539.     /**#@-*/
  540.     /**
  541.      * The class constructor.
  542.      *
  543.      * @uses $global_assign uses {@link assign()} to assign each corresponding
  544.      *                      value from $GLOBALS to the template vars
  545.      */
  546.     function Smarty()
  547.     {
  548.         foreach ($this->global_assign as $key => $var_name) {
  549.             if (is_array($var_name)) {
  550.                 foreach ($var_name as $var) {
  551.                     if (isset($GLOBALS[$key][$var])) {
  552.                         $this->assign($var, $GLOBALS[$key][$var]);
  553.                     } else {
  554.                         $this->assign($var, $this->undefined);
  555.                     }
  556.                 }
  557.             } else {
  558.                 if (isset($GLOBALS[$var_name])) {
  559.                     $this->assign($var_name, $GLOBALS[$var_name]);
  560.                 } else {
  561.                     $this->assign($var_name, $this->undefined);
  562.                 }
  563.             }
  564.         }
  565.     }
  566.  
  567.  
  568.     /**
  569.      * assigns values to template variables
  570.      *
  571.      * @param array|string $tpl_var the template variable name(s)
  572.      * @param mixed $value the value to assign
  573.      */
  574.     function assign($tpl_var, $value = null)
  575.     {
  576.         if (is_array($tpl_var)){
  577.             foreach ($tpl_var as $key => $val) {
  578.                 if ($key != '') {
  579.                     $this->_tpl_vars[$key] = $val;
  580.                 }
  581.             }
  582.         } else {
  583.             if ($tpl_var != '')
  584.                 $this->_tpl_vars[$tpl_var] = $value;
  585.         }
  586.     }
  587.  
  588.     /**
  589.      * assigns values to template variables by reference
  590.      *
  591.      * @param string $tpl_var the template variable name
  592.      * @param mixed $value the referenced value to assign
  593.      */    
  594.     function assign_by_ref($tpl_var, &$value)
  595.     {
  596.         if ($tpl_var != '')
  597.             $this->_tpl_vars[$tpl_var] = &$value;
  598.     }
  599.     
  600.     /**
  601.      * appends values to template variables
  602.      *
  603.      * @param array|string $tpl_var the template variable name(s)
  604.      * @param mixed $value the value to append
  605.      */    
  606.     function append($tpl_var, $value=null, $merge=false)
  607.     {
  608.         if (is_array($tpl_var)) {
  609.             // $tpl_var is an array, ignore $value
  610.             foreach ($tpl_var as $_key => $_val) {
  611.                 if ($_key != '') {
  612.                     if(!@is_array($this->_tpl_vars[$_key])) {
  613.                         settype($this->_tpl_vars[$_key],'array');
  614.                     }
  615.                     if($merge && is_array($_val)) {
  616.                         foreach($_val as $_mkey => $_mval) {
  617.                             $this->_tpl_vars[$_key][$_mkey] = $_mval;
  618.                         }
  619.                     } else {
  620.                         $this->_tpl_vars[$_key][] = $_val;
  621.                     }
  622.                 }
  623.             }
  624.         } else {
  625.             if ($tpl_var != '' && isset($value)) {
  626.                 if(!@is_array($this->_tpl_vars[$tpl_var])) {
  627.                     settype($this->_tpl_vars[$tpl_var],'array');
  628.                 }
  629.                 if($merge && is_array($value)) {
  630.                     foreach($value as $_mkey => $_mval) {
  631.                         $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
  632.                     }
  633.                 } else {
  634.                     $this->_tpl_vars[$tpl_var][] = $value;
  635.                 }
  636.             }
  637.         }
  638.     }
  639.  
  640.     /**
  641.      * appends values to template variables by reference
  642.      *
  643.      * @param string $tpl_var the template variable name
  644.      * @param mixed $value the referenced value to append
  645.      */    
  646.     function append_by_ref($tpl_var, &$value, $merge=false)
  647.     {
  648.         if ($tpl_var != '' && isset($value)) {
  649.             if(!@is_array($this->_tpl_vars[$tpl_var])) {
  650.              settype($this->_tpl_vars[$tpl_var],'array');
  651.             }
  652.             if ($merge && is_array($value)) {
  653.                 foreach($value as $_key => $_val) {
  654.                     $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
  655.                 }
  656.             } else {
  657.                 $this->_tpl_vars[$tpl_var][] = &$value;
  658.             }
  659.         }
  660.     }
  661.  
  662.  
  663.     /**
  664.      * clear the given assigned template variable.
  665.      *
  666.      * @param string $tpl_var the template variable to clear
  667.      */    
  668.     function clear_assign($tpl_var)
  669.     {
  670.         if (is_array($tpl_var))
  671.             foreach ($tpl_var as $curr_var)
  672.                 unset($this->_tpl_vars[$curr_var]);
  673.         else
  674.             unset($this->_tpl_vars[$tpl_var]);
  675.     }
  676.  
  677.  
  678.     /**
  679.      * Registers custom function to be used in templates
  680.      *
  681.      * @param string $function the name of the template function
  682.      * @param string $function_impl the name of the PHP function to register
  683.      */    
  684.     function register_function($function, $function_impl)
  685.     {
  686.         $this->_plugins['function'][$function] =
  687.             array($function_impl, null, null, false);
  688.     }
  689.  
  690.     /**
  691.      * Unregisters custom function
  692.      *
  693.      * @param string $function name of template function
  694.      */    
  695.     function unregister_function($function)
  696.     {
  697.         unset($this->_plugins['function'][$function]);
  698.     }
  699.  
  700.     /**
  701.      * Registers object to be used in templates
  702.      *
  703.      * @param string $object name of template object
  704.      * @param object &$object_impl the referenced PHP object to register
  705.      * @param null|array $allowed list of allowed methods (empty = all)
  706.      * @param boolean $smarty_args smarty argument format, else traditional
  707.      */    
  708.     function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true)
  709.     {
  710.         settype($allowed, 'array');        
  711.         settype($smarty_args, 'boolean');        
  712.         $this->_reg_objects[$object] =
  713.             array(&$object_impl, $allowed, $smarty_args);
  714.     }
  715.  
  716.     /**
  717.      * Unregisters object
  718.      *
  719.      * @param string $object name of template object
  720.      */    
  721.     function unregister_object($object)
  722.     {
  723.         unset($this->_reg_objects[$object]);
  724.     }
  725.     
  726.     
  727.     /**
  728.      * Registers block function to be used in templates
  729.      *
  730.      * @param string $block name of template block
  731.      * @param string $block_impl PHP function to register
  732.      */    
  733.     function register_block($block, $block_impl)
  734.     {
  735.         $this->_plugins['block'][$block] =
  736.             array($block_impl, null, null, false);
  737.     }
  738.  
  739.     /**
  740.      * Unregisters block function
  741.      *
  742.      * @param string $block name of template function
  743.      */    
  744.     function unregister_block($block)
  745.     {
  746.         unset($this->_plugins['block'][$block]);
  747.     }
  748.  
  749.     /**
  750.      * Registers compiler function
  751.      *
  752.      * @param string $function name of template function
  753.      * @param string $function_impl name of PHP function to register
  754.      */    
  755.     function register_compiler_function($function, $function_impl)
  756.     {
  757.         $this->_plugins['compiler'][$function] =
  758.             array($function_impl, null, null, false);
  759.     }
  760.  
  761.     /**
  762.      * Unregisters compiler function
  763.      *
  764.      * @param string $function name of template function
  765.      */    
  766.     function unregister_compiler_function($function)
  767.     {
  768.         unset($this->_plugins['compiler'][$function]);
  769.     }
  770.  
  771.     /**
  772.      * Registers modifier to be used in templates
  773.      *
  774.      * @param string $modifier name of template modifier
  775.      * @param string $modifier_impl name of PHP function to register
  776.      */    
  777.     function register_modifier($modifier, $modifier_impl)
  778.     {
  779.         $this->_plugins['modifier'][$modifier] =
  780.             array($modifier_impl, null, null, false);
  781.     }
  782.  
  783.     /**
  784.      * Unregisters modifier
  785.      *
  786.      * @param string $modifier name of template modifier
  787.      */    
  788.     function unregister_modifier($modifier)
  789.     {
  790.         unset($this->_plugins['modifier'][$modifier]);
  791.     }
  792.  
  793.     /**
  794.      * Registers a resource to fetch a template
  795.      *
  796.      * @param string $type name of resource
  797.      * @param array $functions array of functions to handle resource
  798.      */    
  799.     function register_resource($type, $functions)
  800.     {
  801.         $this->_plugins['resource'][$type] =
  802.             array((array)$functions, false);
  803.     }
  804.  
  805.     /**
  806.      * Unregisters a resource
  807.      *
  808.      * @param string $type name of resource
  809.      */    
  810.     function unregister_resource($type)
  811.     {
  812.         unset($this->_plugins['resource'][$type]);
  813.     }
  814.  
  815.     /**
  816.      * Registers a prefilter function to apply
  817.      * to a template before compiling
  818.      *
  819.      * @param string $function name of PHP function to register
  820.      */    
  821.     function register_prefilter($function)
  822.     {
  823.     $_name = (is_array($function)) ? $function[1] : $function;
  824.         $this->_plugins['prefilter'][$_name]
  825.             = array($function, null, null, false);
  826.     }
  827.  
  828.     /**
  829.      * Unregisters a prefilter function
  830.      *
  831.      * @param string $function name of PHP function
  832.      */    
  833.     function unregister_prefilter($function)
  834.     {
  835.         unset($this->_plugins['prefilter'][$function]);
  836.     }
  837.  
  838.     /**
  839.      * Registers a postfilter function to apply
  840.      * to a compiled template after compilation
  841.      *
  842.      * @param string $function name of PHP function to register
  843.      */    
  844.     function register_postfilter($function)
  845.     {
  846.     $_name = (is_array($function)) ? $function[1] : $function;
  847.         $this->_plugins['postfilter'][$_name]
  848.             = array($function, null, null, false);
  849.     }
  850.  
  851.     /**
  852.      * Unregisters a postfilter function
  853.      *
  854.      * @param string $function name of PHP function
  855.      */    
  856.     function unregister_postfilter($function)
  857.     {
  858.         unset($this->_plugins['postfilter'][$function]);
  859.     }
  860.  
  861.     /**
  862.      * Registers an output filter function to apply
  863.      * to a template output
  864.      *
  865.      * @param string $function name of PHP function
  866.      */    
  867.     function register_outputfilter($function)
  868.     {
  869.     $_name = (is_array($function)) ? $function[1] : $function;
  870.         $this->_plugins['outputfilter'][$_name]
  871.             = array($function, null, null, false);
  872.     }
  873.  
  874.     /**
  875.      * Unregisters an outputfilter function
  876.      *
  877.      * @param string $function name of PHP function
  878.      */    
  879.     function unregister_outputfilter($function)
  880.     {
  881.         unset($this->_plugins['outputfilter'][$function]);
  882.     }    
  883.     
  884.     /**
  885.      * load a filter of specified type and name
  886.      *
  887.      * @param string $type filter type
  888.      * @param string $name filter name
  889.      */    
  890.     function load_filter($type, $name)
  891.     {
  892.         switch ($type) {
  893.             case 'output':
  894.                 $this->_load_plugins(array(array($type . 'filter', $name, null, null, false)));
  895.                 break;
  896.  
  897.             case 'pre':
  898.             case 'post':
  899.                 if (!isset($this->_plugins[$type . 'filter'][$name]))
  900.                     $this->_plugins[$type . 'filter'][$name] = false;
  901.                 break;
  902.         }
  903.     }
  904.  
  905.     /**
  906.      * clear cached content for the given template and cache id
  907.      *
  908.      * @param string $tpl_file name of template file
  909.      * @param string $cache_id name of cache_id
  910.      * @param string $compile_id name of compile_id
  911.      * @param string $exp_time expiration time
  912.      * @return boolean
  913.      */    
  914.     function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
  915.     {
  916.         
  917.         if (!isset($compile_id))
  918.             $compile_id = $this->compile_id;
  919.  
  920.     if (!isset($tpl_file))
  921.         $compile_id = null;
  922.  
  923.     $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
  924.  
  925.         if (!empty($this->cache_handler_func)) {
  926.             return call_user_func_array($this->cache_handler_func,
  927.                                   array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id));
  928.         } else {
  929.             return $this->_rm_auto($this->cache_dir, $tpl_file, $_auto_id, $exp_time);
  930.         }
  931.         
  932.     }
  933.  
  934.  
  935.     /**
  936.      * clear the entire contents of cache (all templates)
  937.      *
  938.      * @param string $exp_time expire time
  939.      * @return boolean results of {@link _rm_auto()}
  940.      */    
  941.     function clear_all_cache($exp_time = null)
  942.     {
  943.         if (!empty($this->cache_handler_func)) {
  944.             call_user_func_array($this->cache_handler_func,
  945.                            array('clear', &$this, &$dummy));
  946.         } else {
  947.             return $this->_rm_auto($this->cache_dir,null,null,$exp_time);
  948.         }
  949.     }
  950.  
  951.  
  952.     /**
  953.      * test to see if valid cache exists for this template
  954.      *
  955.      * @param string $tpl_file name of template file
  956.      * @param string $cache_id
  957.      * @param string $compile_id
  958.      * @return string|false results of {@link _read_cache_file()}
  959.      */    
  960.     function is_cached($tpl_file, $cache_id = null, $compile_id = null)
  961.     {
  962.         if (!$this->caching)
  963.             return false;
  964.  
  965.         if (!isset($compile_id))
  966.             $compile_id = $this->compile_id;
  967.  
  968.         return $this->_read_cache_file($tpl_file, $cache_id, $compile_id, $results);
  969.     }
  970.  
  971.  
  972.     /**
  973.      * clear all the assigned template variables.
  974.      *
  975.      */    
  976.     function clear_all_assign()
  977.     {
  978.         $this->_tpl_vars = array();
  979.     }
  980.  
  981.     /**
  982.      * clears compiled version of specified template resource,
  983.      * or all compiled template files if one is not specified.
  984.      * This function is for advanced use only, not normally needed.
  985.      *
  986.      * @param string $tpl_file
  987.      * @param string $compile_id
  988.      * @param string $exp_time
  989.      * @return boolean results of {@link _rm_auto()}
  990.      */    
  991.     function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
  992.     {
  993.         if (!isset($compile_id))
  994.             $compile_id = $this->compile_id;
  995.         return $this->_rm_auto($this->compile_dir, $tpl_file, $compile_id, $exp_time);
  996.     }
  997.  
  998.     /**
  999.      * Checks whether requested template exists.
  1000.      *
  1001.      * @param string $tpl_file
  1002.      * @return boolean
  1003.      */    
  1004.     function template_exists($tpl_file)
  1005.     {
  1006.         return $this->_fetch_template_info($tpl_file, $source, $timestamp, true, true);
  1007.     }
  1008.  
  1009.     /**
  1010.      * Returns an array containing template variables
  1011.      *
  1012.      * @param string $name
  1013.      * @param string $type
  1014.      * @return array
  1015.      */    
  1016.     function &get_template_vars($name=null)
  1017.     {
  1018.         if(!isset($name)) {
  1019.             return $this->_tpl_vars;
  1020.         }
  1021.         if(isset($this->_tpl_vars[$name])) {
  1022.             return $this->_tpl_vars[$name];
  1023.         }
  1024.     }
  1025.  
  1026.     /**
  1027.      * Returns an array containing config variables
  1028.      *
  1029.      * @param string $name
  1030.      * @param string $type
  1031.      * @return array
  1032.      */    
  1033.     function &get_config_vars($name=null)
  1034.     {
  1035.         if(!isset($name) && is_array($this->_config[0])) {
  1036.             return $this->_config[0]['vars'];
  1037.         } else if(isset($this->_config[0]['vars'][$name])) {
  1038.             return $this->_config[0]['vars'][$name];
  1039.         }
  1040.     }
  1041.  
  1042.     /**
  1043.      * trigger Smarty error
  1044.      *
  1045.      * @param string $error_msg
  1046.      * @param integer $error_type
  1047.      */    
  1048.     function trigger_error($error_msg, $error_type = E_USER_WARNING)
  1049.     {
  1050.         trigger_error("Smarty error: $error_msg", $error_type);
  1051.     }
  1052.  
  1053.  
  1054.     /**
  1055.      * executes & displays the template results
  1056.      *
  1057.      * @param string $tpl_file
  1058.      * @param string $cache_id
  1059.      * @param string $compile_id
  1060.      */    
  1061.     function display($tpl_file, $cache_id = null, $compile_id = null)
  1062.     {
  1063.         $this->fetch($tpl_file, $cache_id, $compile_id, true);
  1064.     }
  1065.  
  1066.     /**
  1067.      * executes & returns or displays the template results
  1068.      *
  1069.      * @param string $tpl_file
  1070.      * @param string $cache_id
  1071.      * @param string $compile_id
  1072.      * @param boolean $display
  1073.      */
  1074.     function fetch($tpl_file, $cache_id = null, $compile_id = null, $display = false)
  1075.     {
  1076.         static $_cache_info = array();
  1077.  
  1078.         $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(error_reporting() & ~E_NOTICE);
  1079.  
  1080.         if($this->security && !in_array($this->template_dir, $this->secure_dir)) {
  1081.             // add template_dir to secure_dir array
  1082.             array_unshift($this->secure_dir, $this->template_dir);
  1083.         }
  1084.  
  1085.         if (!$this->debugging && $this->debugging_ctrl == 'URL'
  1086.                && strstr($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'], $this->_smarty_debug_id)) {
  1087.             // enable debugging from URL
  1088.             $this->debugging = true;
  1089.         }        
  1090.         
  1091.         if ($this->debugging) {
  1092.             // capture time for debugging info
  1093.             $debug_start_time = $this->_get_microtime();
  1094.             $this->_smarty_debug_info[] = array('type'      => 'template',
  1095.                                                 'filename'  => $tpl_file,
  1096.                                                 'depth'     => 0);
  1097.             $included_tpls_idx = count($this->_smarty_debug_info) - 1;
  1098.         }
  1099.  
  1100.         if (!isset($compile_id)) {
  1101.             $compile_id = $this->compile_id;
  1102.         }
  1103.  
  1104.         $this->_compile_id = $compile_id;
  1105.         $this->_inclusion_depth = 0;
  1106.  
  1107.         if ($this->caching) {
  1108.             // save old cache_info, initialize cache_info
  1109.             array_push($_cache_info, $this->_cache_info);
  1110.             $this->_cache_info = array();
  1111.             if ($this->_read_cache_file($tpl_file, $cache_id, $compile_id, $_smarty_results)) {
  1112.                 if (@count($this->_cache_info['insert_tags'])) {
  1113.                     $this->_load_plugins($this->_cache_info['insert_tags']);
  1114.                     $_smarty_results = $this->_process_cached_inserts($_smarty_results);
  1115.                 }
  1116.                 if ($display) {
  1117.                     if ($this->debugging)
  1118.                     {
  1119.                         // capture time for debugging info
  1120.                         $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = $this->_get_microtime() - $debug_start_time;
  1121.  
  1122.                         $_smarty_results .= $this->_generate_debug_output();
  1123.                     }
  1124.                     if ($this->cache_modified_check) {
  1125.                         $last_modified_date = substr($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 0, strpos($GLOBALS['HTTP_SERVER_VARS']['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
  1126.                         $gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
  1127.                         if (@count($this->_cache_info['insert_tags']) == 0
  1128.                             && $gmt_mtime == $last_modified_date) {
  1129.                             header("HTTP/1.1 304 Not Modified");
  1130.                         } else {
  1131.                             header("Last-Modified: ".$gmt_mtime);
  1132.                             echo $_smarty_results;
  1133.                         }
  1134.                     } else {
  1135.                             echo $_smarty_results;                        
  1136.                     }
  1137.                     error_reporting($_smarty_old_error_level);
  1138.                     // restore initial cache_info
  1139.                     $this->_cache_info = array_pop($_cache_info);
  1140.                     return true;    
  1141.                 } else {
  1142.                     error_reporting($_smarty_old_error_level);
  1143.                     // restore initial cache_info
  1144.                     $this->_cache_info = array_pop($_cache_info);
  1145.                     return $_smarty_results;
  1146.                 }
  1147.             } else {
  1148.                 $this->_cache_info['template'][] = $tpl_file;
  1149.                 if ($this->cache_modified_check) {
  1150.                     header("Last-Modified: ".gmdate('D, d M Y H:i:s', time()).' GMT');
  1151.                 }
  1152.             }
  1153.         }
  1154.  
  1155.         if (count($this->autoload_filters)) {
  1156.             $this->_autoload_filters();
  1157.         }
  1158.  
  1159.         $_smarty_compile_path = $this->_get_compile_path($tpl_file);
  1160.  
  1161.         // if we just need to display the results, don't perform output
  1162.         // buffering - for speed
  1163.         if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
  1164.             if ($this->_process_template($tpl_file, $_smarty_compile_path))
  1165.             {
  1166.                 include($_smarty_compile_path);
  1167.             }
  1168.         } else {
  1169.             ob_start();
  1170.             if ($this->_process_template($tpl_file, $_smarty_compile_path))
  1171.             {
  1172.                 include($_smarty_compile_path);
  1173.             }
  1174.             $_smarty_results = ob_get_contents();
  1175.             ob_end_clean();
  1176.  
  1177.             foreach ((array)$this->_plugins['outputfilter'] as $output_filter) {
  1178.                 $_smarty_results = call_user_func_array($output_filter[0], array($_smarty_results, &$this));
  1179.             }
  1180.         }
  1181.  
  1182.         if ($this->caching) {
  1183.             $this->_write_cache_file($tpl_file, $cache_id, $compile_id, $_smarty_results);
  1184.             $_smarty_results = $this->_process_cached_inserts($_smarty_results);
  1185.             // restore initial cache_info
  1186.             $this->_cache_info = array_pop($_cache_info);
  1187.         }
  1188.  
  1189.         if ($display) {
  1190.             if (isset($_smarty_results)) { echo $_smarty_results; }
  1191.             if ($this->debugging) {
  1192.                 // capture time for debugging info
  1193.                 $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = ($this->_get_microtime() - $debug_start_time);
  1194.  
  1195.                 echo $this->_generate_debug_output();
  1196.             }
  1197.             error_reporting($_smarty_old_error_level);
  1198.             return;
  1199.         } else {
  1200.             error_reporting($_smarty_old_error_level);
  1201.             if (isset($_smarty_results)) { return $_smarty_results; }
  1202.         }
  1203.     }
  1204.  
  1205.  
  1206.     /**
  1207.      * assign $smarty interface variable
  1208.      */    
  1209.     function _assign_smarty_interface()
  1210.     {
  1211.         if (isset($this->_smarty_vars) && isset($this->_smarty_vars['request'])) {
  1212.             return;
  1213.         }
  1214.  
  1215.         $globals_map = array('g'  => 'HTTP_GET_VARS',
  1216.                              'p'  => 'HTTP_POST_VARS',
  1217.                              'c'  => 'HTTP_COOKIE_VARS',
  1218.                              's'  => 'HTTP_SERVER_VARS',
  1219.                              'e'  => 'HTTP_ENV_VARS');
  1220.  
  1221.         $_smarty_vars_request  = array();
  1222.  
  1223.         foreach (preg_split('!!', strtolower($this->request_vars_order)) as $c) {
  1224.             if (isset($globals_map[$c])) {
  1225.                 $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$globals_map[$c]]);
  1226.             }
  1227.         }
  1228.         $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
  1229.  
  1230.         $this->_smarty_vars['request'] = $_smarty_vars_request;
  1231.         
  1232.     }
  1233.  
  1234.  
  1235.     /**
  1236.      * generate debug output
  1237.      * @return string debug.tpl template output
  1238.      * @uses $debug_tpl debug template, used to display debugging output
  1239.      */
  1240.     function _generate_debug_output()
  1241.     {
  1242.         // we must force compile the debug template in case the environment
  1243.         // changed between separate applications.
  1244.  
  1245.         if(empty($this->debug_tpl)) {
  1246.             // set path to debug template from SMARTY_DIR
  1247.             $this->debug_tpl = 'file:'.SMARTY_DIR.'debug.tpl';
  1248.             if($this->security && is_file($this->debug_tpl)) {
  1249.                 $secure_dir[] = $this->debug_tpl;
  1250.             }
  1251.         }
  1252.  
  1253.         $_ldelim_orig = $this->left_delimiter;
  1254.         $_rdelim_orig = $this->right_delimiter;    
  1255.  
  1256.         $this->left_delimiter = '{';
  1257.         $this->right_delimiter = '}';
  1258.  
  1259.         $_force_compile_orig = $this->force_compile;
  1260.         $this->force_compile = true;
  1261.         $_compile_id_orig = $this->_compile_id;
  1262.         $this->_compile_id = null;
  1263.  
  1264.         $compile_path = $this->_get_compile_path($this->debug_tpl);
  1265.         if ($this->_process_template($this->debug_tpl, $compile_path))
  1266.         {
  1267.             ob_start();
  1268.             include($compile_path);
  1269.             $results = ob_get_contents();
  1270.             ob_end_clean();
  1271.         }
  1272.         $this->force_compile = $_force_compile_orig;
  1273.         $this->_compile_id = $_compile_id_orig;
  1274.  
  1275.         $this->left_delimiter = $_ldelim_orig;
  1276.         $this->right_delimiter = $_rdelim_orig;
  1277.  
  1278.         return $results;
  1279.     }
  1280.  
  1281.     /**
  1282.      * load configuration values
  1283.      *
  1284.      * @param string $file
  1285.      * @param string $section
  1286.      * @param string $scope
  1287.      */    
  1288.     function config_load($file, $section = null, $scope = 'global')
  1289.     {
  1290.         require_once($this->_get_plugin_filepath('function', 'config_load'));    
  1291.         smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
  1292.     }
  1293.  
  1294.     /**
  1295.      * return a reference to a registered object
  1296.      *
  1297.      * @param string $name
  1298.      * @return object
  1299.      */    
  1300.     function &get_registered_object($name) {
  1301.         if (!isset($this->_reg_objects[$name]))
  1302.         $this->_trigger_fatal_error("'$name' is not a registered object");
  1303.  
  1304.         if (!is_object($this->_reg_objects[$name][0]))
  1305.         $this->_trigger_fatal_error("registered '$name' is not an object");
  1306.  
  1307.         return $this->_reg_objects[$name][0];        
  1308.     }    
  1309.  
  1310.     /**#@+
  1311.      * @access private
  1312.      */
  1313.     /**
  1314.      * determines if a resource is trusted or not
  1315.      *
  1316.      * @param string $resource_type
  1317.      * @param string $resource_name
  1318.      * @return boolean
  1319.      */    
  1320.     function _is_trusted($resource_type, $resource_name)
  1321.     {
  1322.         $_smarty_trusted = false;
  1323.         if ($resource_type == 'file') {
  1324.             if (!empty($this->trusted_dir)) {
  1325.                 // see if template file is within a trusted directory. If so,
  1326.                 // disable security during the execution of the template.
  1327.  
  1328.                 if (!empty($this->trusted_dir)) {
  1329.                     foreach ((array)$this->trusted_dir as $curr_dir) {
  1330.                         if (!empty($curr_dir) && is_readable ($curr_dir)) {
  1331.                             if (substr(realpath($resource_name),0, strlen(realpath($curr_dir))) == realpath($curr_dir)) {
  1332.                                 $_smarty_trusted = true;
  1333.                                 break;
  1334.                             }
  1335.                         }
  1336.                     }
  1337.                 }
  1338.             }
  1339.         } else {
  1340.             // resource is not on local file system
  1341.             $resource_func = $this->_plugins['resource'][$resource_type][0][3];
  1342.             $_smarty_trusted = $resource_func($resource_name, $this);
  1343.         }
  1344.  
  1345.         return $_smarty_trusted;
  1346.     }
  1347.  
  1348.     
  1349.     /**
  1350.      * determines if a resource is secure or not.
  1351.      *
  1352.      * @param string $resource_type
  1353.      * @param string $resource_name
  1354.      * @return boolean
  1355.      */    
  1356.     function _is_secure($resource_type, $resource_name)
  1357.     {
  1358.         if (!$this->security || $this->security_settings['INCLUDE_ANY']) {
  1359.             return true;
  1360.         }
  1361.  
  1362.         $_smarty_secure = false;
  1363.         if ($resource_type == 'file') {
  1364.             if (!empty($this->secure_dir)) {
  1365.                 foreach ((array)$this->secure_dir as $curr_dir) {
  1366.                     if ( !empty($curr_dir) && is_readable ($curr_dir)) {
  1367.                         if (substr(realpath($resource_name),0, strlen(realpath($curr_dir))) == realpath($curr_dir)) {
  1368.                             $_smarty_secure = true;
  1369.                             break;
  1370.                         }
  1371.                     }
  1372.                 }
  1373.             }
  1374.         } else {
  1375.             // resource is not on local file system
  1376.             $resource_func = $this->_plugins['resource'][$resource_type][0][2];
  1377.             $_smarty_secure = $resource_func($resource_name, $_smarty_secure, $this);
  1378.         }
  1379.  
  1380.         return $_smarty_secure;
  1381.     }
  1382.  
  1383.  
  1384.     /**
  1385.      * Retrieves PHP script resource
  1386.      *
  1387.      * sets $php_resource to the returned resource
  1388.      * @param string $resource
  1389.      * @param string $resource_type
  1390.      * @param  $php_resource
  1391.      * @return boolean
  1392.      */    
  1393.     function _get_php_resource($resource, &$resource_type, &$php_resource)
  1394.     {
  1395.         $this->_parse_file_path($this->trusted_dir, $resource, $resource_type, $resource_name);
  1396.  
  1397.         /*
  1398.          * Find out if the resource exists.
  1399.          */
  1400.         
  1401.         if ($resource_type == 'file') {
  1402.             $readable = false;
  1403.             if(file_exists($resource_name) && is_readable($resource_name)) {
  1404.                 $readable = true;
  1405.             } else {
  1406.                 // test for file in include_path
  1407.                 if($this->_get_include_path($resource_name,$_include_path)) {
  1408.                     $readable = true;
  1409.                 }
  1410.             }
  1411.         } else if ($resource_type != 'file') {
  1412.             $readable = true;
  1413.             $template_source = null;
  1414.             $resource_func = $this->_plugins['resource'][$resource_type][0][0];
  1415.             $readable = $resource_func($resource_name, $template_source, $this);
  1416.         }
  1417.  
  1418.         /*
  1419.          * Set the error function, depending on which class calls us.
  1420.          */
  1421.         if (method_exists($this, '_syntax_error')) {
  1422.             $error_func = '_syntax_error';
  1423.         } else {
  1424.             $error_func = 'trigger_error';
  1425.         }
  1426.  
  1427.         if ($readable) {
  1428.             if ($this->security) {
  1429.                 if (!$this->_is_trusted($resource_type, $resource_name)) {
  1430.                     $this->$error_func("(secure mode) '$resource_type:$resource_name' is not trusted");
  1431.                     return false;
  1432.                 }
  1433.             }
  1434.         } else {
  1435.             $this->$error_func("'$resource_type: $resource_name' is not readable");
  1436.             return false;
  1437.         }
  1438.  
  1439.         if ($resource_type == 'file') {
  1440.             $php_resource = $resource_name;
  1441.         } else {
  1442.             $php_resource = $template_source;
  1443.         }
  1444.  
  1445.         return true;
  1446.     }
  1447.  
  1448.  
  1449.     /**
  1450.      * umm... process the template
  1451.      *
  1452.      * @param string $tpl_file
  1453.      * @param string $compile_path
  1454.      * @return boolean
  1455.      */    
  1456.     function _process_template($tpl_file, $compile_path)
  1457.     {
  1458.         // test if template needs to be compiled
  1459.         if (!$this->force_compile && file_exists($compile_path)) {
  1460.             if (!$this->compile_check) {
  1461.                 // no need to check if the template needs recompiled
  1462.                 return true;
  1463.             } else {
  1464.                 // get template source and timestamp
  1465.                 if (!$this->_fetch_template_info($tpl_file, $template_source,
  1466.                                                  $template_timestamp)) {
  1467.                     return false;
  1468.                 }
  1469.                 if ($template_timestamp <= filemtime($compile_path)) {
  1470.                     // template not expired, no recompile
  1471.                     return true;
  1472.                 } else {
  1473.                     // compile template
  1474.                     $this->_compile_template($tpl_file, $template_source, $template_compiled);
  1475.                     $this->_write_compiled_template($compile_path, $template_compiled, $template_timestamp);
  1476.                     return true;
  1477.                 }
  1478.             }
  1479.         } else {
  1480.             // compiled template does not exist, or forced compile
  1481.             if (!$this->_fetch_template_info($tpl_file, $template_source,
  1482.                                              $template_timestamp)) {
  1483.                 return false;
  1484.             }
  1485.             $this->_compile_template($tpl_file, $template_source, $template_compiled);
  1486.             $this->_write_compiled_template($compile_path, $template_compiled, $template_timestamp);
  1487.             return true;
  1488.         }
  1489.     }
  1490.  
  1491.     /**
  1492.      * Get the compile path for this template file
  1493.      *
  1494.      * @param string $tpl_file
  1495.      * @return string results of {@link _get_auto_filename()}
  1496.      */    
  1497.     function _get_compile_path($tpl_file)
  1498.     {
  1499.         return $this->_get_auto_filename($this->compile_dir, $tpl_file,
  1500.                                          $this->_compile_id);
  1501.     }
  1502.  
  1503.    /**
  1504.      * write the compiled template
  1505.      *
  1506.      * @param string $compile_path
  1507.      * @param string $template_compiled
  1508.      * @param integer $template_timestamp
  1509.      * @return true
  1510.      */    
  1511.     function _write_compiled_template($compile_path, $template_compiled, $template_timestamp)
  1512.     {
  1513.         // we save everything into $compile_dir
  1514.         $this->_write_file($compile_path, $template_compiled, true);
  1515.         touch($compile_path, $template_timestamp);
  1516.         return true;
  1517.     }
  1518.  
  1519.     /**
  1520.      * parse out the type and name from the template resource
  1521.      *
  1522.      * @param string $file_base_path
  1523.      * @param string $file_path
  1524.      * @param string $resource_type
  1525.      * @param string $resource_name
  1526.      * @return boolean
  1527.      */    
  1528.     function _parse_file_path($file_base_path, $file_path, &$resource_type, &$resource_name)
  1529.     {
  1530.         // split tpl_path by the first colon
  1531.         $_file_path_parts = explode(':', $file_path, 2);
  1532.  
  1533.         if (count($_file_path_parts) == 1) {
  1534.             // no resource type, treat as type "file"
  1535.             $resource_type = 'file';
  1536.             $resource_name = $_file_path_parts[0];
  1537.         } else {
  1538.             $resource_type = $_file_path_parts[0];
  1539.             $resource_name = $_file_path_parts[1];
  1540.             if ($resource_type != 'file') {
  1541.                 $this->_load_resource_plugin($resource_type);
  1542.             }
  1543.         }
  1544.  
  1545.         if ($resource_type == 'file') {
  1546.             if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $resource_name)) {
  1547.                 // relative pathname to $file_base_path
  1548.                 // use the first directory where the file is found
  1549.                 foreach ((array)$file_base_path as $_curr_path) {
  1550.                     $_fullpath = $_curr_path . DIR_SEP . $resource_name;
  1551.                     if (file_exists($_fullpath) && is_file($_fullpath)) {
  1552.                         $resource_name = $_fullpath;
  1553.                         return true;
  1554.                     }
  1555.                     // didn't find the file, try include_path
  1556.                     if($this->_get_include_path($_fullpath, $_include_path)) {
  1557.                         $resource_name = $_include_path;
  1558.                         return true;
  1559.                     }
  1560.                 }
  1561.                 return false;
  1562.             }
  1563.         }
  1564.  
  1565.         // resource type != file
  1566.         return true;
  1567.     }
  1568.  
  1569.  
  1570.     /**
  1571.      * fetch the template info. Gets timestamp, and source
  1572.      * if get_source is true
  1573.      *
  1574.      * sets $template_source to the source of the template, and
  1575.      * $template_timestamp to its time stamp
  1576.      * @param string $tpl_path
  1577.      * @param string $template_source
  1578.      * @param integer $template_timestamp
  1579.      * @param boolean $get_source
  1580.      * @param boolean $quiet
  1581.      * @return boolean
  1582.      */    
  1583.     function _fetch_template_info($tpl_path, &$template_source, &$template_timestamp, $get_source = true, $quiet = false)
  1584.     {
  1585.         $_return = false;
  1586.         if ($this->_parse_file_path($this->template_dir, $tpl_path, $resource_type, $resource_name)) {
  1587.             switch ($resource_type) {
  1588.                 case 'file':
  1589.                     if ($get_source) {
  1590.                         $template_source = $this->_read_file($resource_name);
  1591.                     }
  1592.                     $template_timestamp = filemtime($resource_name);
  1593.                     $_return = true;
  1594.                     break;
  1595.  
  1596.                 default:
  1597.                     // call resource functions to fetch the template source and timestamp
  1598.                     if ($get_source) {
  1599.                         $resource_func = $this->_plugins['resource'][$resource_type][0][0];
  1600.                         $_source_return = $resource_func($resource_name, $template_source, $this);
  1601.                     } else {
  1602.                         $_source_return = true;
  1603.                     }
  1604.                     $resource_func = $this->_plugins['resource'][$resource_type][0][1];
  1605.                     $_timestamp_return = $resource_func($resource_name, $template_timestamp, $this);
  1606.                     $_return = $_source_return && $_timestamp_return;
  1607.                     break;
  1608.             }
  1609.         }
  1610.         
  1611.         if (!$_return) {
  1612.             // see if we can get a template with the default template handler
  1613.             if (!empty($this->default_template_handler_func)) {
  1614.                 if (!function_exists($this->default_template_handler_func)) {
  1615.                     $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
  1616.                 } else {
  1617.                     $funcname = $this->default_template_handler_func;
  1618.                     $_return = $funcname($resource_type, $resource_name, $template_source, $template_timestamp, $this);
  1619.                 }
  1620.             }
  1621.         }
  1622.  
  1623.         if (!$_return) {
  1624.             if (!$quiet) {
  1625.                 $this->trigger_error("unable to read template resource: \"$tpl_path\"");
  1626.             }
  1627.         } else if ($_return && $this->security && !$this->_is_secure($resource_type, $resource_name)) {
  1628.             if (!$quiet)
  1629.                 $this->trigger_error("(secure mode) accessing \"$tpl_path\" is not allowed");
  1630.             $template_source = null;
  1631.             $template_timestamp = null;
  1632.             return false;
  1633.         }
  1634.  
  1635.         return $_return;
  1636.     }
  1637.  
  1638.  
  1639.     /**
  1640.      * called to compile the templates
  1641.      *
  1642.      * sets $template_compiled to the compiled template
  1643.      * @param string $tpl_file
  1644.      * @param string $template_source
  1645.      * @param string $template_compiled
  1646.      * @return boolean
  1647.      */    
  1648.     function _compile_template($tpl_file, $template_source, &$template_compiled)
  1649.     {
  1650.         if(file_exists(SMARTY_DIR.$this->compiler_file)) {
  1651.             require_once SMARTY_DIR.$this->compiler_file;            
  1652.         } else {
  1653.             // use include_path
  1654.             require_once $this->compiler_file;
  1655.         }
  1656.  
  1657.         $smarty_compiler = new $this->compiler_class;
  1658.  
  1659.         $smarty_compiler->template_dir      = $this->template_dir;
  1660.         $smarty_compiler->compile_dir       = $this->compile_dir;
  1661.         $smarty_compiler->plugins_dir       = $this->plugins_dir;
  1662.         $smarty_compiler->config_dir        = $this->config_dir;
  1663.         $smarty_compiler->force_compile     = $this->force_compile;
  1664.         $smarty_compiler->caching           = $this->caching;
  1665.         $smarty_compiler->php_handling      = $this->php_handling;
  1666.         $smarty_compiler->left_delimiter    = $this->left_delimiter;
  1667.         $smarty_compiler->right_delimiter   = $this->right_delimiter;
  1668.         $smarty_compiler->_version          = $this->_version;
  1669.         $smarty_compiler->security          = $this->security;
  1670.         $smarty_compiler->secure_dir        = $this->secure_dir;
  1671.         $smarty_compiler->security_settings = $this->security_settings;
  1672.         $smarty_compiler->trusted_dir       = $this->trusted_dir;
  1673.         $smarty_compiler->_reg_objects      = &$this->_reg_objects;
  1674.         $smarty_compiler->_plugins          = &$this->_plugins;
  1675.         $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;
  1676.         $smarty_compiler->default_modifiers = $this->default_modifiers;
  1677.         $smarty_compiler->compile_id        = $this->_compile_id;
  1678.  
  1679.         if ($smarty_compiler->_compile_file($tpl_file, $template_source, $template_compiled)) {
  1680.             return true;
  1681.         } else {
  1682.             $this->trigger_error($smarty_compiler->_error_msg);
  1683.             return false;
  1684.         }
  1685.     }
  1686.  
  1687.     /**
  1688.      * called for included templates
  1689.      *
  1690.      * @param string $_smarty_include_tpl_file
  1691.      * @param string $_smarty_include_vars
  1692.      */    
  1693.     function _smarty_include($_smarty_include_tpl_file, $_smarty_include_vars)
  1694.     {
  1695.         if ($this->debugging) {
  1696.             $debug_start_time = $this->_get_microtime();
  1697.             $this->_smarty_debug_info[] = array('type'      => 'template',
  1698.                                                 'filename'  => $_smarty_include_tpl_file,
  1699.                                                 'depth'     => ++$this->_inclusion_depth);
  1700.             $included_tpls_idx = count($this->_smarty_debug_info) - 1;
  1701.         }
  1702.  
  1703.         $this->_tpl_vars = array_merge($this->_tpl_vars, $_smarty_include_vars);
  1704.  
  1705.         // config vars are treated as local, so push a copy of the
  1706.         // current ones onto the front of the stack
  1707.         array_unshift($this->_config, $this->_config[0]);
  1708.  
  1709.         $_smarty_compile_path = $this->_get_compile_path($_smarty_include_tpl_file);
  1710.  
  1711.         if ($this->_process_template($_smarty_include_tpl_file, $_smarty_compile_path)) {
  1712.             include($_smarty_compile_path);
  1713.         }
  1714.  
  1715.         // pop the local vars off the front of the stack
  1716.         array_shift($this->_config);
  1717.  
  1718.         $this->_inclusion_depth--;
  1719.  
  1720.         if ($this->debugging) {
  1721.             // capture time for debugging info
  1722.             $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = $this->_get_microtime() - $debug_start_time;
  1723.         }
  1724.  
  1725.         if ($this->caching) {
  1726.             $this->_cache_info['template'][] = $_smarty_include_tpl_file;
  1727.         }
  1728.     }
  1729.  
  1730.     /**
  1731.      * called for included templates
  1732.      *
  1733.      * @param string $_smarty_include_php_file
  1734.      * @param string $_smarty_assign variable to assign the included template's
  1735.      *               output into
  1736.      * @param boolean $_smarty_once uses include_once if this is true
  1737.      * @param array $_smarty_include_vars associative array of vars from
  1738.      *              {include file="blah" var=$var}
  1739.      */    
  1740.     function _smarty_include_php($_smarty_include_php_file, $_smarty_assign, $_smarty_once, $_smarty_include_vars)
  1741.     {
  1742.         $this->_get_php_resource($_smarty_include_php_file, $_smarty_resource_type,
  1743.                                  $_smarty_php_resource);
  1744.  
  1745.         extract($_smarty_include_vars, EXTR_PREFIX_SAME, 'include_php_');
  1746.  
  1747.         if (!empty($_smarty_assign)) {
  1748.             ob_start();
  1749.             if ($_smarty_resource_type == 'file') {
  1750.                 if($_smarty_once) {
  1751.                     include_once($_smarty_php_resource);
  1752.                 } else {
  1753.                     include($_smarty_php_resource);                    
  1754.                 }
  1755.             } else {
  1756.                 eval($_smarty_php_resource);
  1757.             }
  1758.             $this->assign($_smarty_assign, ob_get_contents());
  1759.             ob_end_clean();
  1760.         } else {
  1761.             if ($_smarty_resource_type == 'file') {
  1762.                 if($_smarty_once) {
  1763.                     include_once($_smarty_php_resource);
  1764.                 } else {
  1765.                     include($_smarty_php_resource);                    
  1766.                 }
  1767.             } else {
  1768.                 eval($_smarty_php_resource);
  1769.             }
  1770.         }
  1771.     }
  1772.  
  1773.     
  1774.     /**
  1775.      * clear configuration values
  1776.      *
  1777.      * @param string $var
  1778.      */    
  1779.     function clear_config($var = null)
  1780.     {
  1781.         if(!isset($var)) {
  1782.             // clear all values
  1783.             $this->_config = array(array('vars'  => array(),
  1784.                                          'files' => array()));
  1785.         } else {
  1786.             unset($this->_config[0]['vars'][$var]);            
  1787.         }
  1788.     }    
  1789.     
  1790.     
  1791.     /**
  1792.      * Replace cached inserts with the actual results
  1793.      *
  1794.      * @param string $results
  1795.      * @return string
  1796.      */    
  1797.     function _process_cached_inserts($results)
  1798.     {
  1799.         preg_match_all('!'.$this->_smarty_md5.'{insert_cache (.*)}'.$this->_smarty_md5.'!Uis',
  1800.                        $results, $match);
  1801.         list($cached_inserts, $insert_args) = $match;
  1802.  
  1803.         for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
  1804.             if ($this->debugging) {
  1805.                 $debug_start_time = $this->_get_microtime();
  1806.             }
  1807.  
  1808.             $args = unserialize($insert_args[$i]);
  1809.             $name = $args['name'];
  1810.  
  1811.             if (isset($args['script'])) {
  1812.                 if (!$this->_get_php_resource($this->_dequote($args['script']), $resource_type, $php_resource)) {
  1813.                     return false;
  1814.                 }
  1815.  
  1816.                 if ($resource_type == 'file') {
  1817.                     include_once($php_resource);
  1818.                 } else {
  1819.                     eval($php_resource);
  1820.                 }
  1821.             }
  1822.  
  1823.             $function_name = $this->_plugins['insert'][$name][0];
  1824.             $replace = $function_name($args, $this);
  1825.  
  1826.             $results = str_replace($cached_inserts[$i], $replace, $results);
  1827.             if ($this->debugging) {
  1828.                 $this->_smarty_debug_info[] = array('type'      => 'insert',
  1829.                                                     'filename'  => 'insert_'.$name,
  1830.                                                     'depth'     => $this->_inclusion_depth,
  1831.                                                     'exec_time' => $this->_get_microtime() - $debug_start_time);
  1832.             }
  1833.         }
  1834.  
  1835.         return $results;
  1836.     }
  1837.  
  1838.  
  1839.     /**
  1840.      * Handle insert tags
  1841.      *
  1842.      * @param array $args
  1843.      * @return string
  1844.      */    
  1845.     function _run_insert_handler($args)
  1846.     {
  1847.         if ($this->debugging) {
  1848.             $debug_start_time = $this->_get_microtime();
  1849.         }
  1850.     
  1851.         if ($this->caching) {
  1852.             $arg_string = serialize($args);
  1853.             $name = $args['name'];
  1854.             if (!isset($this->_cache_info['insert_tags'][$name])) {
  1855.                 $this->_cache_info['insert_tags'][$name] = array('insert',
  1856.                                                                  $name,
  1857.                                                                  $this->_plugins['insert'][$name][1],
  1858.                                                                  $this->_plugins['insert'][$name][2],
  1859.                                                                  !empty($args['script']) ? true : false);
  1860.             }
  1861.             return $this->_smarty_md5."{insert_cache $arg_string}".$this->_smarty_md5;
  1862.         } else {
  1863.             if (isset($args['script'])) {
  1864.                 if (!$this->_get_php_resource($this->_dequote($args['script']), $resource_type, $php_resource)) {
  1865.                     return false;
  1866.                 }
  1867.     
  1868.                 if ($resource_type == 'file') {
  1869.                     include_once($php_resource);
  1870.                 } else {
  1871.                     eval($php_resource);
  1872.                 }
  1873.                 unset($args['script']);
  1874.             }
  1875.     
  1876.             $function_name = $this->_plugins['insert'][$args['name']][0];
  1877.             $content = $function_name($args, $this);
  1878.             if ($this->debugging) {
  1879.                 $this->_smarty_debug_info[] = array('type'      => 'insert',
  1880.                                                     'filename'  => 'insert_'.$args['name'],
  1881.                                                     'depth'     => $this->_inclusion_depth,
  1882.                                                     'exec_time' => $this->_get_microtime() - $debug_start_time);
  1883.             }
  1884.     
  1885.             if (!empty($args["assign"])) {
  1886.                 $this->assign($args["assign"], $content);
  1887.             } else {
  1888.                 return $content;
  1889.             }
  1890.         }
  1891.     }
  1892.  
  1893.  
  1894.     /**
  1895.      * Handle modifiers
  1896.      *
  1897.      * @param string|null $modifier_name
  1898.      * @param array|null $map_array
  1899.      * @return string result of modifiers
  1900.      */
  1901.     function _run_mod_handler()
  1902.     {
  1903.         $args = func_get_args();
  1904.         list($modifier_name, $map_array) = array_splice($args, 0, 2);
  1905.         list($func_name, $tpl_file, $tpl_line) =
  1906.             $this->_plugins['modifier'][$modifier_name];
  1907.         $var = $args[0];
  1908.  
  1909.         if ($map_array && is_array($var)) {
  1910.             foreach ($var as $key => $val) {
  1911.                 $args[0] = $val;
  1912.                 $var[$key] = call_user_func_array($func_name, $args);
  1913.             }
  1914.             return $var;
  1915.         } else {
  1916.             return call_user_func_array($func_name, $args);
  1917.         }
  1918.     }
  1919.  
  1920.  
  1921.     /**
  1922.      * Remove starting and ending quotes from the string
  1923.      *
  1924.      * @param string $string
  1925.      * @return string
  1926.      */    
  1927.     function _dequote($string)
  1928.     {
  1929.         if (($string{0} == "'" || $string{0} == '"') &&
  1930.             $string{strlen($string)-1} == $string{0})
  1931.             return substr($string, 1, -1);
  1932.         else
  1933.             return $string;
  1934.     }
  1935.  
  1936.  
  1937.     /**
  1938.      * read in a file from line $start for $lines.
  1939.      * read the entire file if $start and $lines are null.
  1940.      *
  1941.      * @param string $filename
  1942.      * @param integer $start
  1943.      * @param integer $lines
  1944.      * @return string
  1945.      */    
  1946.     function _read_file($filename, $start=null, $lines=null)
  1947.     {
  1948.         if (!($fd = @fopen($filename, 'r'))) {
  1949.             return false;
  1950.         }
  1951.         flock($fd, LOCK_SH);
  1952.         if ($start == null && $lines == null) {
  1953.             // read the entire file
  1954.             $contents = fread($fd, filesize($filename));
  1955.         } else {
  1956.             if ( $start > 1 ) {
  1957.                 // skip the first lines before $start
  1958.                 for ($loop=1; $loop < $start; $loop++) {
  1959.                     fgets($fd, 65536);
  1960.                 }
  1961.             }
  1962.             if ( $lines == null ) {
  1963.                 // read the rest of the file
  1964.                 while (!feof($fd)) {
  1965.                     $contents .= fgets($fd, 65536);
  1966.                 }
  1967.             } else {
  1968.                 // read up to $lines lines
  1969.                 for ($loop=0; $loop < $lines; $loop++) {
  1970.                     $contents .= fgets($fd, 65536);
  1971.                     if (feof($fd)) {
  1972.                         break;
  1973.                     }
  1974.                 }
  1975.             }
  1976.         }
  1977.         fclose($fd);
  1978.         return $contents;
  1979.     }
  1980.  
  1981.     /**
  1982.      * write out a file to disk
  1983.      *
  1984.      * @param string $filename
  1985.      * @param string $contents
  1986.      * @param boolean $create_dirs
  1987.      * @return boolean
  1988.      */    
  1989.     function _write_file($filename, $contents, $create_dirs = false)
  1990.     {
  1991.         $_dirname = dirname($filename);
  1992.         
  1993.         if ($create_dirs) {
  1994.             $this->_create_dir_structure($_dirname);
  1995.         }
  1996.  
  1997.         // write to tmp file, then rename it to avoid
  1998.         // file locking race condition
  1999.         $_tmp_file = $_dirname . '/' . uniqid('');
  2000.         
  2001.         if (!($fd = @fopen($_tmp_file, 'w'))) {
  2002.             $this->trigger_error("problem writing temporary file '$_tmp_file'");
  2003.             return false;
  2004.         }
  2005.  
  2006.         fwrite($fd, $contents);
  2007.         fclose($fd);
  2008.         // Win32 can't rename over top another file
  2009.         if(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && file_exists($filename)) {
  2010.             @unlink($filename);
  2011.         } 
  2012.         @rename($_tmp_file, $filename);
  2013.         chmod($filename, $this->_file_perms);
  2014.  
  2015.         return true;
  2016.     }
  2017.  
  2018.     /**
  2019.      * get a concrete filename for automagically created content
  2020.      *
  2021.      * @param string $auto_base
  2022.      * @param string $auto_source
  2023.      * @param string $auto_id
  2024.      * @return string
  2025.      * @staticvar string|null
  2026.      * @staticvar string|null
  2027.      */    
  2028.     function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
  2029.     {
  2030.         static $_dir_sep = null;
  2031.         static $_dir_sep_enc = null;
  2032.         
  2033.         if(!isset($_dir_sep)) {
  2034.             $_dir_sep_enc = urlencode(DIR_SEP);
  2035.             if($this->use_sub_dirs) {
  2036.                 $_dir_sep = DIR_SEP;
  2037.             } else {
  2038.                 $_dir_sep = '^';        
  2039.             }
  2040.         }
  2041.         
  2042.         if(@is_dir($auto_base)) {
  2043.             $res = $auto_base . DIR_SEP;
  2044.         } else {
  2045.             // auto_base not found, try include_path
  2046.             $this->_get_include_path($auto_base,$_include_path);
  2047.             $res = $_include_path . DIR_SEP;
  2048.         }
  2049.         
  2050.         if(isset($auto_id)) {
  2051.             // make auto_id safe for directory names
  2052.             $auto_id = str_replace('%7C','|',(urlencode($auto_id)));
  2053.             // split into separate directories
  2054.             $auto_id = str_replace('|', $_dir_sep, $auto_id);
  2055.             $res .= $auto_id . $_dir_sep;
  2056.         }
  2057.         
  2058.         if(isset($auto_source)) {
  2059.             // make source name safe for filename
  2060.             if($this->use_sub_dirs) {
  2061.                 $_filename = urlencode(basename($auto_source));
  2062.                 $_crc32 = crc32($auto_source) . $_dir_sep;
  2063.                 // prepend %% to avoid name conflicts with
  2064.                 // with $auto_id names
  2065.                 $_crc32 = '%%' . substr($_crc32,0,3) . $_dir_sep . '%%' . $_crc32;
  2066.                 $res .= $_crc32 . $_filename . '.php';
  2067.             } else {
  2068.                 $res .= str_replace($_dir_sep_enc,'^',urlencode($auto_source));
  2069.             }
  2070.         }
  2071.         
  2072.         return $res;
  2073.     }
  2074.  
  2075.     /**
  2076.      * delete an automagically created file by name and id
  2077.      *
  2078.      * @param string $auto_base
  2079.      * @param string $auto_source
  2080.      * @param string $auto_id
  2081.      * @param integer $exp_time
  2082.      * @return boolean
  2083.      */    
  2084.     function _rm_auto($auto_base, $auto_source = null, $auto_id = null, $exp_time = null)
  2085.     {
  2086.         if (!@is_dir($auto_base))
  2087.           return false;
  2088.  
  2089.         if(!isset($auto_id) && !isset($auto_source)) {
  2090.             $res = $this->_rmdir($auto_base, 0, $exp_time);            
  2091.         } else {        
  2092.             $tname = $this->_get_auto_filename($auto_base, $auto_source, $auto_id);
  2093.             
  2094.             if(isset($auto_source)) {
  2095.                 $res = $this->_unlink($tname);
  2096.             } elseif ($this->use_sub_dirs) {
  2097.                 $res = $this->_rmdir($tname, 1, $exp_time);
  2098.             } else {
  2099.                 // remove matching file names
  2100.                 $handle = opendir($auto_base);
  2101.         $res = true;
  2102.                 while (false !== ($filename = readdir($handle))) {
  2103.                     if($filename == '.' || $filename == '..') {
  2104.                         continue;    
  2105.                     } elseif (substr($auto_base . DIR_SEP . $filename,0,strlen($tname)) == $tname) {
  2106.                         $res &= (bool)$this->_unlink($auto_base . DIR_SEP . $filename, $exp_time);
  2107.                     }
  2108.                 }
  2109.             }
  2110.         }
  2111.  
  2112.         return $res;
  2113.     }
  2114.  
  2115.     /**
  2116.      * delete a dir recursively (level=0 -> keep root)
  2117.      * WARNING: no tests, it will try to remove what you tell it!
  2118.      *
  2119.      * @param string $dirname
  2120.      * @param integer $level
  2121.      * @param integer $exp_time
  2122.      * @return boolean
  2123.      */    
  2124.     function _rmdir($dirname, $level = 1, $exp_time = null)
  2125.     {
  2126.  
  2127.        if($handle = @opendir($dirname)) {
  2128.  
  2129.             while (false !== ($entry = readdir($handle))) {
  2130.                 if ($entry != '.' && $entry != '..') {
  2131.                     if (@is_dir($dirname . DIR_SEP . $entry)) {
  2132.                         $this->_rmdir($dirname . DIR_SEP . $entry, $level + 1, $exp_time);
  2133.                     }
  2134.                     else {
  2135.                         $this->_unlink($dirname . DIR_SEP . $entry, $exp_time);
  2136.                     }
  2137.                 }
  2138.             }
  2139.  
  2140.             closedir($handle);
  2141.  
  2142.             if ($level)
  2143.                 @rmdir($dirname);
  2144.             
  2145.             return true;
  2146.         
  2147.         } else {
  2148.                 return false;
  2149.         }
  2150.     }
  2151.  
  2152.     /**
  2153.      * unlink a file, possibly using expiration time
  2154.      *
  2155.      * @param string $resource
  2156.      * @param integer $exp_time
  2157.      */    
  2158.     function _unlink($resource, $exp_time = null)
  2159.     {
  2160.         if(isset($exp_time)) {
  2161.             if(time() - filemtime($resource) >= $exp_time) {
  2162.                 @unlink($resource);
  2163.             }
  2164.         } else {            
  2165.             @unlink($resource);
  2166.         }
  2167.     }
  2168.     
  2169.     /**
  2170.      * create full directory structure
  2171.      *
  2172.      * @param string $dir
  2173.      */    
  2174.     function _create_dir_structure($dir)
  2175.     {
  2176.         if (!file_exists($dir)) {
  2177.             $_dir_parts = preg_split('!\\'.DIR_SEP.'+!', $dir, -1, PREG_SPLIT_NO_EMPTY);
  2178.             $_new_dir = ($dir{0} == DIR_SEP) ? DIR_SEP : '';
  2179.             
  2180.             // do not attempt to test or make directories outside of open_basedir
  2181.             $_open_basedir_ini = ini_get('open_basedir');
  2182.             if(!empty($_open_basedir_ini)) {
  2183.                 $_use_open_basedir = true;
  2184.                 $_open_basedir_sep = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') ? ';' : ':';
  2185.                 $_open_basedirs = explode($_open_basedir_sep, $_open_basedir_ini);
  2186.             } else {                    
  2187.                 $_use_open_basedir = false;
  2188.             }
  2189.  
  2190.             foreach ($_dir_parts as $_dir_part) {
  2191.                 $_new_dir .= $_dir_part;
  2192.  
  2193.                 if ($_use_open_basedir) {
  2194.                     $_make_new_dir = false;
  2195.                     foreach ($_open_basedirs as $_open_basedir) {
  2196.                         if (substr($_new_dir.'/', 0, strlen($_open_basedir)) == $_open_basedir) {
  2197.                             $_make_new_dir = true;
  2198.                             break;
  2199.                         }
  2200.                     }
  2201.                 } else {
  2202.                     $_make_new_dir = true;                    
  2203.                 }
  2204.  
  2205.                 if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $this->_dir_perms)) {
  2206.                     $this->trigger_error("problem creating directory \"$dir\"");
  2207.                     return false;
  2208.                 }
  2209.                 $_new_dir .= DIR_SEP;
  2210.             }
  2211.         }
  2212.     }
  2213.  
  2214.     /**
  2215.      * Prepend the cache information to the cache file
  2216.      * and write it
  2217.      *
  2218.      * @param string $tpl_file
  2219.      * @param string $cache_id
  2220.      * @param string $compile_id
  2221.      * @param string $results
  2222.      * @return true|null
  2223.      */    
  2224.     function _write_cache_file($tpl_file, $cache_id, $compile_id, $results)
  2225.     {
  2226.         // put timestamp in cache header
  2227.         $this->_cache_info['timestamp'] = time();
  2228.         if ($this->cache_lifetime > -1){
  2229.             // expiration set
  2230.             $this->_cache_info['expires'] = $this->_cache_info['timestamp'] + $this->cache_lifetime;
  2231.         } else {
  2232.             // cache will never expire
  2233.             $this->_cache_info['expires'] = -1;
  2234.         }
  2235.  
  2236.         // prepend the cache header info into cache file
  2237.         $results = serialize($this->_cache_info)."\n".$results;
  2238.  
  2239.         if (!empty($this->cache_handler_func)) {
  2240.             // use cache_handler function
  2241.             call_user_func_array($this->cache_handler_func,
  2242.                            array('write', &$this, &$results, $tpl_file, $cache_id, $compile_id));
  2243.         } else {
  2244.             // use local cache file
  2245.             $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
  2246.             $_cache_file = $this->_get_auto_filename($this->cache_dir, $tpl_file, $_auto_id);
  2247.             $this->_write_file($_cache_file, $results, true);
  2248.             return true;
  2249.         }
  2250.     }
  2251.  
  2252.     /**
  2253.      * read a cache file, determine if it needs to be
  2254.      * regenerated or not
  2255.      *
  2256.      * @param string $tpl_file
  2257.      * @param string $cache_id
  2258.      * @param string $compile_id
  2259.      * @param string $results
  2260.      * @return boolean
  2261.      */    
  2262.     function _read_cache_file($tpl_file, $cache_id, $compile_id, &$results)
  2263.     {
  2264.         static  $content_cache = array();
  2265.  
  2266.         if ($this->force_compile) {
  2267.             // force compile enabled, always regenerate
  2268.             return false;
  2269.         }
  2270.  
  2271.         if (isset($content_cache["$tpl_file,$cache_id,$compile_id"])) {
  2272.             list($results, $this->_cache_info) = $content_cache["$tpl_file,$cache_id,$compile_id"];
  2273.             return true;
  2274.         }
  2275.  
  2276.         if (!empty($this->cache_handler_func)) {
  2277.             // use cache_handler function
  2278.             call_user_func_array($this->cache_handler_func,
  2279.                                  array('read', &$this, &$results, $tpl_file, $cache_id, $compile_id));
  2280.         } else {
  2281.             // use local cache file
  2282.             $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
  2283.             $_cache_file = $this->_get_auto_filename($this->cache_dir, $tpl_file, $_auto_id);
  2284.             $results = $this->_read_file($_cache_file);
  2285.         }
  2286.  
  2287.         if (empty($results)) {
  2288.             // nothing to parse (error?), regenerate cache
  2289.             return false;
  2290.         }
  2291.  
  2292.         $cache_split = explode("\n", $results, 2);
  2293.         $cache_header = $cache_split[0];
  2294.  
  2295.         $this->_cache_info = unserialize($cache_header);
  2296.  
  2297.         if ($this->caching == 2 && isset ($this->_cache_info['expires'])){
  2298.             // caching by expiration time
  2299.             if ($this->_cache_info['expires'] > -1 && (time() > $this->_cache_info['expires'])) {
  2300.             // cache expired, regenerate
  2301.             return false;
  2302.             }
  2303.         } else {
  2304.             // caching by lifetime
  2305.             if ($this->cache_lifetime > -1 && (time() - $this->_cache_info['timestamp'] > $this->cache_lifetime)) {
  2306.             // cache expired, regenerate
  2307.             return false;
  2308.             }
  2309.         }
  2310.  
  2311.         if ($this->compile_check) {
  2312.             foreach ($this->_cache_info['template'] as $template_dep) {
  2313.                 $this->_fetch_template_info($template_dep, $template_source, $template_timestamp, false);
  2314.                 if ($this->_cache_info['timestamp'] < $template_timestamp) {
  2315.                     // template file has changed, regenerate cache
  2316.                     return false;
  2317.                 }
  2318.             }
  2319.  
  2320.             if (isset($this->_cache_info['config'])) {
  2321.                 foreach ($this->_cache_info['config'] as $config_dep) {
  2322.                     if ($this->_cache_info['timestamp'] < filemtime($this->config_dir.DIR_SEP.$config_dep)) {
  2323.                         // config file has changed, regenerate cache
  2324.                         return false;
  2325.                     }
  2326.                 }
  2327.             }
  2328.         }
  2329.  
  2330.         $results = $cache_split[1];
  2331.         $content_cache["$tpl_file,$cache_id,$compile_id"] = array($results, $this->_cache_info);
  2332.  
  2333.         return true;
  2334.     }
  2335.  
  2336.     /**
  2337.      * returns an auto_id for auto-file-functions
  2338.      *
  2339.      * @param string $cache_id
  2340.      * @param string $compile_id
  2341.      * @return string|null
  2342.      */
  2343.     function _get_auto_id($cache_id=null, $compile_id=null) {
  2344.     if (isset($cache_id))
  2345.         return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;
  2346.     elseif(isset($compile_id))
  2347.         return $compile_id;
  2348.     else
  2349.         return null;
  2350.     }
  2351.  
  2352.     /**
  2353.      * get filepath of requested plugin
  2354.      *
  2355.      * @param string $type
  2356.      * @param string $name
  2357.      * @return string|false
  2358.      */    
  2359.     function _get_plugin_filepath($type, $name)
  2360.     {
  2361.         $_plugin_filename = "$type.$name.php";
  2362.         
  2363.         foreach ((array)$this->plugins_dir as $_plugin_dir) {
  2364.  
  2365.             $_plugin_filepath = $_plugin_dir . DIR_SEP . $_plugin_filename;
  2366.  
  2367.             // see if path is relative
  2368.             if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
  2369.                 $_relative_paths[] = $_plugin_dir;
  2370.                 // relative path, see if it is in the SMARTY_DIR
  2371.                 if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
  2372.                     return SMARTY_DIR . $_plugin_filepath;
  2373.                 }
  2374.             }
  2375.             // try relative to cwd (or absolute)
  2376.             if (@is_readable($_plugin_filepath)) {
  2377.                 return $_plugin_filepath;
  2378.             }
  2379.         }
  2380.  
  2381.         // still not found, try PHP include_path
  2382.         if(isset($_relative_paths)) {
  2383.             foreach ((array)$_relative_paths as $_plugin_dir) {
  2384.  
  2385.                 $_plugin_filepath = $_plugin_dir . DIR_SEP . $_plugin_filename;
  2386.  
  2387.                 if ($this->_get_include_path($_plugin_filepath, $_include_filepath)) {
  2388.                     return $_include_filepath;
  2389.                 }
  2390.             }
  2391.         }
  2392.         
  2393.         
  2394.         return false;
  2395.     }
  2396.  
  2397.     /**
  2398.      * Load requested plugins
  2399.      *
  2400.      * @param array $plugins
  2401.      */    
  2402.     function _load_plugins($plugins)
  2403.     {
  2404.         
  2405.         foreach ($plugins as $plugin_info) {            
  2406.             list($type, $name, $tpl_file, $tpl_line, $delayed_loading) = $plugin_info;
  2407.             $plugin = &$this->_plugins[$type][$name];
  2408.  
  2409.             /*
  2410.              * We do not load plugin more than once for each instance of Smarty.
  2411.              * The following code checks for that. The plugin can also be
  2412.              * registered dynamically at runtime, in which case template file
  2413.              * and line number will be unknown, so we fill them in.
  2414.              *
  2415.              * The final element of the info array is a flag that indicates
  2416.              * whether the dynamically registered plugin function has been
  2417.              * checked for existence yet or not.
  2418.              */
  2419.             if (isset($plugin)) {
  2420.                 if (!$plugin[3]) {
  2421.                     if (!$this->_plugin_implementation_exists($plugin[0])) {
  2422.                         $this->_trigger_fatal_error("[plugin] $type '$name' is not implemented", $tpl_file, $tpl_line, __FILE__, __LINE__);
  2423.                     } else {
  2424.                         $plugin[1] = $tpl_file;
  2425.                         $plugin[2] = $tpl_line;
  2426.                         $plugin[3] = true;
  2427.                     }
  2428.                 }
  2429.                 continue;
  2430.             } else if ($type == 'insert') {
  2431.                 /*
  2432.                  * For backwards compatibility, we check for insert functions in
  2433.                  * the symbol table before trying to load them as a plugin.
  2434.                  */
  2435.                 $plugin_func = 'insert_' . $name;
  2436.                 if (function_exists($plugin_func)) {
  2437.                     $plugin = array($plugin_func, $tpl_file, $tpl_line, true);
  2438.                     continue;
  2439.                 }
  2440.             }
  2441.  
  2442.             $plugin_file = $this->_get_plugin_filepath($type, $name);
  2443.  
  2444.             if (! $found = ($plugin_file != false)) {
  2445.                 $message = "could not load plugin file '$type.$name.php'\n";
  2446.             }
  2447.  
  2448.             /*
  2449.              * If plugin file is found, it -must- provide the properly named
  2450.              * plugin function. In case it doesn't, simply output the error and
  2451.              * do not fall back on any other method.
  2452.              */
  2453.             if ($found) {
  2454.                 include_once $plugin_file;
  2455.  
  2456.                 $plugin_func = 'smarty_' . $type . '_' . $name;
  2457.                 if (!$this->_plugin_implementation_exists($plugin_func)) {
  2458.                     $this->_trigger_fatal_error("[plugin] function $plugin_func() not found in $plugin_file", $tpl_file, $tpl_line, __FILE__, __LINE__);
  2459.                     continue;
  2460.                 }
  2461.             }
  2462.             /*
  2463.              * In case of insert plugins, their code may be loaded later via
  2464.              * 'script' attribute.
  2465.              */
  2466.             else if ($type == 'insert' && $delayed_loading) {
  2467.                 $plugin_func = 'smarty_' . $type . '_' . $name;
  2468.                 $found = true;
  2469.             }
  2470.  
  2471.             /*
  2472.              * Plugin specific processing and error checking.
  2473.              */
  2474.             if (!$found) {
  2475.                 if ($type == 'modifier') {
  2476.                     /*
  2477.                      * In case modifier falls back on using PHP functions
  2478.                      * directly, we only allow those specified in the security
  2479.                      * context.
  2480.                      */
  2481.                     if ($this->security && !in_array($name, $this->security_settings['MODIFIER_FUNCS'])) {
  2482.                         $message = "(secure mode) modifier '$name' is not allowed";
  2483.                     } else {
  2484.                         if (!function_exists($name)) {
  2485.                             $message = "modifier '$name' is not implemented";
  2486.                         } else {
  2487.                             $plugin_func = $name;
  2488.                             $found = true;
  2489.                         }
  2490.                     }
  2491.                 } else if ($type == 'function') {
  2492.                     /*
  2493.                      * This is a catch-all situation.
  2494.                      */
  2495.                     $message = "unknown tag - '$name'";
  2496.                 }
  2497.             }
  2498.  
  2499.             if ($found) {
  2500.                 $this->_plugins[$type][$name] = array($plugin_func, $tpl_file, $tpl_line, true);
  2501.             } else {
  2502.                 // output error
  2503.                 $this->_trigger_fatal_error('[plugin] ' . $message, $tpl_file, $tpl_line, __FILE__, __LINE__);
  2504.             }
  2505.         }
  2506.     }
  2507.  
  2508.     /**
  2509.      * load a resource plugin
  2510.      *
  2511.      * @param string $type
  2512.      */    
  2513.     function _load_resource_plugin($type)
  2514.     {
  2515.         /*
  2516.          * Resource plugins are not quite like the other ones, so they are
  2517.          * handled differently. The first element of plugin info is the array of
  2518.          * functions provided by the plugin, the second one indicates whether
  2519.          * all of them exist or not.
  2520.          */
  2521.  
  2522.         $plugin = &$this->_plugins['resource'][$type];
  2523.         if (isset($plugin)) {
  2524.             if (!$plugin[1] && count($plugin[0])) {
  2525.                 $plugin[1] = true;
  2526.                 foreach ($plugin[0] as $plugin_func) {
  2527.                     if (!function_exists($plugin_func)) {
  2528.                         $plugin[1] = false;
  2529.                         break;
  2530.                     }
  2531.                 }
  2532.             }
  2533.  
  2534.             if (!$plugin[1]) {
  2535.                 $this->_trigger_fatal_error("[plugin] resource '$type' is not implemented", null, null, __FILE__, __LINE__);
  2536.             }
  2537.  
  2538.             return;
  2539.         }
  2540.  
  2541.         $plugin_file = $this->_get_plugin_filepath('resource', $type);
  2542.         $found = ($plugin_file != false);
  2543.  
  2544.         if ($found) {            /*
  2545.              * If the plugin file is found, it -must- provide the properly named
  2546.              * plugin functions.
  2547.              */
  2548.             include_once $plugin_file;
  2549.  
  2550.             /*
  2551.              * Locate functions that we require the plugin to provide.
  2552.              */
  2553.             $resource_ops = array('source', 'timestamp', 'secure', 'trusted');
  2554.             $resource_funcs = array();
  2555.             foreach ($resource_ops as $op) {
  2556.                 $plugin_func = 'smarty_resource_' . $type . '_' . $op;
  2557.                 if (!function_exists($plugin_func)) {
  2558.                     $this->_trigger_fatal_error("[plugin] function $plugin_func() not found in $plugin_file", null, null, __FILE__, __LINE__);
  2559.                     return;
  2560.                 } else {
  2561.                     $resource_funcs[] = $plugin_func;
  2562.                 }
  2563.             }
  2564.  
  2565.             $this->_plugins['resource'][$type] = array($resource_funcs, true);
  2566.         }
  2567.     }
  2568.  
  2569.     /**
  2570.      * automatically load a set of filters
  2571.      * @uses load_filter()
  2572.      */
  2573.     function _autoload_filters()
  2574.     {
  2575.         foreach ($this->autoload_filters as $filter_type => $filters) {
  2576.             foreach ($filters as $filter) {
  2577.                 $this->load_filter($filter_type, $filter);
  2578.             }
  2579.         }
  2580.     }
  2581.  
  2582.     /**
  2583.      * Quote subpattern references
  2584.      *
  2585.      * @param string $string
  2586.      * @return string
  2587.      */
  2588.     function quote_replace($string)
  2589.     {
  2590.         return preg_replace('![\\$]\d!', '\\\\\\0', $string);
  2591.     }
  2592.  
  2593.  
  2594.     /**
  2595.      * trigger Smarty plugin error
  2596.      *
  2597.      * @param string $error_msg
  2598.      * @param string $tpl_file
  2599.      * @param integer $tpl_line
  2600.      * @param string $file
  2601.      * @param integer $line
  2602.      * @param integer $error_type
  2603.      */    
  2604.     function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
  2605.             $file = null, $line = null, $error_type = E_USER_ERROR)
  2606.     {
  2607.         if(isset($file) && isset($line)) {
  2608.             $info = ' ('.basename($file).", line $line)";
  2609.         } else {
  2610.             $info = null;
  2611.         }
  2612.         if (isset($tpl_line) && isset($tpl_file)) {
  2613.             trigger_error("Smarty error: [in " . $tpl_file . " line " .
  2614.                           $tpl_line . "]: $error_msg$info", $error_type);
  2615.         } else {
  2616.             trigger_error("Smarty error: $error_msg$info", $error_type);
  2617.         }
  2618.     }
  2619.  
  2620.     /**
  2621.      * Get seconds and microseconds
  2622.      * @return double
  2623.      */    
  2624.     function _get_microtime()
  2625.     {
  2626.         $mtime = microtime();
  2627.         $mtime = explode(" ", $mtime);
  2628.         $mtime = (double)($mtime[1]) + (double)($mtime[0]);
  2629.         return ($mtime);
  2630.     }
  2631.  
  2632.     /**
  2633.      * Get path to file from include_path
  2634.      *
  2635.      * @param string $file_path
  2636.      * @param string $new_file_path
  2637.      * @return boolean
  2638.      * @staticvar array|null
  2639.      */    
  2640.     function _get_include_path($file_path, &$new_file_path)
  2641.     {
  2642.         static $_path_array = null;
  2643.         
  2644.         if(!isset($_path_array)) {
  2645.             $_ini_include_path = ini_get('include_path');
  2646.  
  2647.             if(strstr($_ini_include_path,';')) {
  2648.                 // windows pathnames
  2649.                 $_path_array = explode(';',$_ini_include_path);
  2650.             } else {
  2651.                 $_path_array = explode(':',$_ini_include_path);
  2652.             }
  2653.         }
  2654.         foreach ($_path_array as $_include_path) {
  2655.             if (file_exists($_include_path . DIR_SEP . $file_path)) {
  2656.                    $new_file_path = $_include_path . DIR_SEP . $file_path;
  2657.                 return true;
  2658.             }
  2659.         }
  2660.         return false;
  2661.     }    
  2662.  
  2663.     /**
  2664.      * check if the function or method exists
  2665.      * @return bool
  2666.      */       
  2667.     function _plugin_implementation_exists($function)
  2668.     {
  2669.         return (is_array($function)) ?
  2670.             method_exists($function[0], $function[1]) : function_exists($function);
  2671.     }
  2672.     /**#@-*/
  2673. }
  2674.  
  2675. /* vim: set expandtab: */
  2676.  
  2677. ?>
  2678.