includes/template.php
changeset 1227 bdac73ed481e
parent 1220 fbfd6c852c89
child 1274 673a1b6712fa
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
    11  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    11  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    12  */
    12  */
    13  
    13  
    14 class template
    14 class template
    15 {
    15 {
    16   var $tpl_strings, $tpl_bool, $vars_assign_history, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $plugin_blocks_content, $namespace_string, $style_list, $theme_loaded;
    16 	var $tpl_strings, $tpl_bool, $vars_assign_history, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $plugin_blocks_content, $namespace_string, $style_list, $theme_loaded;
    17   
    17 	
    18   var $theme_initted = false;
    18 	var $theme_initted = false;
    19   var $page_initted = false;
    19 	var $page_initted = false;
    20   var $elements = false;
    20 	var $elements = false;
    21   var $page_id = false;
    21 	var $page_id = false;
    22   var $namespace = false;
    22 	var $namespace = false;
    23   var $js_preload = array();
    23 	var $js_preload = array();
    24   var $js_append = '';
    24 	var $js_append = '';
    25   
    25 	
    26   /**
    26 	/**
    27    * Page action conditions
    27  	* Page action conditions
    28    * @var array
    28  	* @var array
    29    */
    29  	*/
    30   
    30 	
    31   var $conds = array();
    31 	var $conds = array();
    32   
    32 	
    33   /**
    33 	/**
    34    * The PageProcessor for the current page
    34  	* The PageProcessor for the current page
    35    * @var object
    35  	* @var object
    36    */
    36  	*/
    37   
    37 	
    38   var $page = false;
    38 	var $page = false;
    39   
    39 	
    40   /**
    40 	/**
    41    * The list of themes that are critical for Enano operation. This doesn't include oxygen which
    41  	* The list of themes that are critical for Enano operation. This doesn't include oxygen which
    42    * remains a user theme. By default this is admin and printable which have to be loaded on demand.
    42  	* remains a user theme. By default this is admin and printable which have to be loaded on demand.
    43    * @var array
    43  	* @var array
    44    */
    44  	*/
    45   
    45 	
    46   var $system_themes = array('admin', 'printable');
    46 	var $system_themes = array('admin', 'printable');
    47   
    47 	
    48   /**
    48 	/**
    49    * Set to true if the site is disabled and thus a message needs to be shown. This should ONLY be changed by common.php.
    49  	* Set to true if the site is disabled and thus a message needs to be shown. This should ONLY be changed by common.php.
    50    * @var bool
    50  	* @var bool
    51    * @access private
    51  	* @access private
    52    */
    52  	*/
    53   
    53 	
    54   var $site_disabled = false;
    54 	var $site_disabled = false;
    55   
    55 	
    56   /**
    56 	/**
    57    * One of the absolute best parts of Enano :-P
    57  	* One of the absolute best parts of Enano :-P
    58    * @var string
    58  	* @var string
    59    */
    59  	*/
    60   
    60 	
    61   var $fading_button = '';
    61 	var $fading_button = '';
    62   
    62 	
    63   function __construct()
    63 	function __construct()
    64   {
    64 	{
    65     global $db, $session, $paths, $template, $plugins; // Common objects
    65 		global $db, $session, $paths, $template, $plugins; // Common objects
    66     global $cache;
    66 		global $cache;
    67     
    67 		
    68     $this->tpl_bool    = Array();
    68 		$this->tpl_bool    = Array();
    69     $this->tpl_strings = Array();
    69 		$this->tpl_strings = Array();
    70     $this->sidebar_extra = '';
    70 		$this->sidebar_extra = '';
    71     $this->toolbar_menu = '';
    71 		$this->toolbar_menu = '';
    72     $this->additional_headers = '';
    72 		$this->additional_headers = '';
    73     $this->plugin_blocks = Array();
    73 		$this->plugin_blocks = Array();
    74     $this->plugin_blocks_content = array();
    74 		$this->plugin_blocks_content = array();
    75     $this->theme_loaded = false;
    75 		$this->theme_loaded = false;
    76     
    76 		
    77     $this->theme_list = Array();
    77 		$this->theme_list = Array();
    78     $this->named_theme_list = Array();
    78 		$this->named_theme_list = Array();
    79     
    79 		
    80     $this->vars_assign_history = array(
    80 		$this->vars_assign_history = array(
    81         'strings' => array(),
    81 				'strings' => array(),
    82         'bool' => array()
    82 				'bool' => array()
    83       );
    83 			);
    84     
    84 		
    85     if ( defined('IN_ENANO_UPGRADE') )
    85 		if ( defined('IN_ENANO_UPGRADE') )
    86     {
    86 		{
    87       return $this->construct_compat();
    87 			return $this->construct_compat();
    88     }
    88 		}
    89     
    89 		
    90     if ( !$this->theme_list = $cache->fetch('themes') )
    90 		if ( !$this->theme_list = $cache->fetch('themes') )
    91     {
    91 		{
    92       $q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style, group_policy, group_list FROM ' . table_prefix . 'themes;');
    92 			$q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style, group_policy, group_list FROM ' . table_prefix . 'themes;');
    93       if ( !$q )
    93 			if ( !$q )
    94         $db->_die('template.php selecting theme list');
    94 				$db->_die('template.php selecting theme list');
    95       
    95 			
    96       $i = 0;
    96 			$i = 0;
    97       while ( $row = $db->fetchrow() )
    97 			while ( $row = $db->fetchrow() )
    98       {
    98 			{
    99         $this->theme_list[$i] = $row;
    99 				$this->theme_list[$i] = $row;
   100         $i++;
   100 				$i++;
   101       }
   101 			}
   102       unset($theme);
   102 			unset($theme);
   103       $this->theme_list = array_values($this->theme_list);
   103 			$this->theme_list = array_values($this->theme_list);
   104       $cache->store('themes', $this->theme_list, -1);
   104 			$cache->store('themes', $this->theme_list, -1);
   105     }
   105 		}
   106     
   106 		
   107     // Create associative array of themes
   107 		// Create associative array of themes
   108     foreach ( $this->theme_list as $i => &$theme )
   108 		foreach ( $this->theme_list as $i => &$theme )
   109       $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   109 			$this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   110     
   110 		
   111     unset($theme);
   111 		unset($theme);
   112     
   112 		
   113     $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
   113 		$this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
   114     $this->named_theme_list[ $this->default_theme ]['css'] = $this->get_theme_css_files($this->default_theme);
   114 		$this->named_theme_list[ $this->default_theme ]['css'] = $this->get_theme_css_files($this->default_theme);
   115     // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   115 		// Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   116     // use that. Otherwise, use the first stylesheet that comes to mind.
   116 		// use that. Otherwise, use the first stylesheet that comes to mind.
   117     $df_data =& $this->named_theme_list[ $this->default_theme ];
   117 		$df_data =& $this->named_theme_list[ $this->default_theme ];
   118     $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   118 		$this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   119   }
   119 	}
   120   
   120 	
   121   /**
   121 	/**
   122    * Gets the list of available CSS files (styles) for the specified theme.
   122  	* Gets the list of available CSS files (styles) for the specified theme.
   123    * @param string Theme ID
   123  	* @param string Theme ID
   124    * @return array
   124  	* @return array
   125    */
   125  	*/
   126   
   126 	
   127   function get_theme_css_files($theme_id)
   127 	function get_theme_css_files($theme_id)
   128   {
   128 	{
   129     $css = array();
   129 		$css = array();
   130     $dir = ENANO_ROOT . "/themes/{$theme_id}/css";
   130 		$dir = ENANO_ROOT . "/themes/{$theme_id}/css";
   131     if ( $dh = @opendir($dir) )
   131 		if ( $dh = @opendir($dir) )
   132     {
   132 		{
   133       while ( ( $file = @readdir($dh) ) !== false )
   133 			while ( ( $file = @readdir($dh) ) !== false )
   134       {
   134 			{
   135         if ( preg_match('/\.css$/', $file) )
   135 				if ( preg_match('/\.css$/', $file) )
   136           $css[] = preg_replace('/\.css$/', '', $file);
   136 					$css[] = preg_replace('/\.css$/', '', $file);
   137       }
   137 			}
   138       closedir($dh);
   138 			closedir($dh);
   139     }
   139 		}
   140     // No CSS files? If so, nuke it.
   140 		// No CSS files? If so, nuke it.
   141     if ( count($css) < 1 )
   141 		if ( count($css) < 1 )
   142     {
   142 		{
   143       unset($this->theme_list[$theme_id]);
   143 			unset($this->theme_list[$theme_id]);
   144     }
   144 		}
   145     return $css;
   145 		return $css;
   146   }
   146 	}
   147   
   147 	
   148   /**
   148 	/**
   149    * Failsafe constructor for upgrades.
   149  	* Failsafe constructor for upgrades.
   150    */
   150  	*/
   151   
   151 	
   152   function construct_compat()
   152 	function construct_compat()
   153   {
   153 	{
   154     global $db, $session, $paths, $template, $plugins; // Common objects
   154 		global $db, $session, $paths, $template, $plugins; // Common objects
   155     $this->tpl_bool    = Array();
   155 		$this->tpl_bool    = Array();
   156     $this->tpl_strings = Array();
   156 		$this->tpl_strings = Array();
   157     $this->sidebar_extra = '';
   157 		$this->sidebar_extra = '';
   158     $this->toolbar_menu = '';
   158 		$this->toolbar_menu = '';
   159     $this->additional_headers = '';
   159 		$this->additional_headers = '';
   160     $this->plugin_blocks = Array();
   160 		$this->plugin_blocks = Array();
   161     $this->theme_loaded = false;
   161 		$this->theme_loaded = false;
   162     
   162 		
   163     $this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
   163 		$this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
   164                               <a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
   164 															<a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
   165                             </div>';
   165 														</div>';
   166     
   166 		
   167     $this->theme_list = Array();
   167 		$this->theme_list = Array();
   168     $this->named_theme_list = Array();
   168 		$this->named_theme_list = Array();
   169     
   169 		
   170     $q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style FROM ' . table_prefix . 'themes;');
   170 		$q = $db->sql_query('SELECT theme_id, theme_name, enabled, default_style FROM ' . table_prefix . 'themes;');
   171     if ( !$q )
   171 		if ( !$q )
   172       $db->_die('template.php selecting theme list');
   172 			$db->_die('template.php selecting theme list');
   173     
   173 		
   174     $i = 0;
   174 		$i = 0;
   175     while ( $row = $db->fetchrow() )
   175 		while ( $row = $db->fetchrow() )
   176     {
   176 		{
   177       $this->theme_list[$i] = $row;
   177 			$this->theme_list[$i] = $row;
   178       $i++;
   178 			$i++;
   179     }
   179 		}
   180     // List out all CSS files for this theme
   180 		// List out all CSS files for this theme
   181     foreach ( $this->theme_list as $i => &$theme )
   181 		foreach ( $this->theme_list as $i => &$theme )
   182     {
   182 		{
   183       $theme['css'] = array();
   183 			$theme['css'] = array();
   184       $dir = ENANO_ROOT . "/themes/{$theme['theme_id']}/css";
   184 			$dir = ENANO_ROOT . "/themes/{$theme['theme_id']}/css";
   185       if ( $dh = @opendir($dir) )
   185 			if ( $dh = @opendir($dir) )
   186       {
   186 			{
   187         while ( ( $file = @readdir($dh) ) !== false )
   187 				while ( ( $file = @readdir($dh) ) !== false )
   188         {
   188 				{
   189           if ( preg_match('/\.css$/', $file) )
   189 					if ( preg_match('/\.css$/', $file) )
   190             $theme['css'][] = preg_replace('/\.css$/', '', $file);
   190 						$theme['css'][] = preg_replace('/\.css$/', '', $file);
   191         }
   191 				}
   192         closedir($dh);
   192 				closedir($dh);
   193       }
   193 			}
   194       // No CSS files? If so, nuke it.
   194 			// No CSS files? If so, nuke it.
   195       if ( count($theme['css']) < 1 )
   195 			if ( count($theme['css']) < 1 )
   196       {
   196 			{
   197         unset($this->theme_list[$i]);
   197 				unset($this->theme_list[$i]);
   198       }
   198 			}
   199     }
   199 		}
   200     $this->theme_list = array_values($this->theme_list);
   200 		$this->theme_list = array_values($this->theme_list);
   201     // Create associative array of themes
   201 		// Create associative array of themes
   202     foreach ( $this->theme_list as $i => &$theme )
   202 		foreach ( $this->theme_list as $i => &$theme )
   203       $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   203 			$this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   204     
   204 		
   205     $this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
   205 		$this->default_theme = ( $_ = getConfig('theme_default') ) ? $_ : $this->theme_list[0]['theme_id'];
   206     // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   206 		// Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   207     // use that. Otherwise, use the first stylesheet that comes to mind.
   207 		// use that. Otherwise, use the first stylesheet that comes to mind.
   208     $df_data =& $this->named_theme_list[ $this->default_theme ];
   208 		$df_data =& $this->named_theme_list[ $this->default_theme ];
   209     $this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   209 		$this->default_style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   210   }
   210 	}
   211   
   211 	
   212   /**
   212 	/**
   213    * Systematically deletes themes from available list if they're blocked by theme security settings. Called when session->start() finishes.
   213  	* Systematically deletes themes from available list if they're blocked by theme security settings. Called when session->start() finishes.
   214    */
   214  	*/
   215   
   215 	
   216   function process_theme_acls()
   216 	function process_theme_acls()
   217   {
   217 	{
   218     global $db, $session, $paths, $template, $plugins; // Common objects
   218 		global $db, $session, $paths, $template, $plugins; // Common objects
   219     global $lang;
   219 		global $lang;
   220     
   220 		
   221     // generate the fading button - needs to be done after sessions are started
   221 		// generate the fading button - needs to be done after sessions are started
   222     $admintitle = ( $session->user_level >= USER_LEVEL_ADMIN && is_object(@$lang) ) ? ' title="' . $lang->get('sidebar_btn_enanopowered_admin_tip') . '"' : '';
   222 		$admintitle = ( $session->user_level >= USER_LEVEL_ADMIN && is_object(@$lang) ) ? ' title="' . $lang->get('sidebar_btn_enanopowered_admin_tip') . '"' : '';
   223     $this->fading_button = '<div style="background-image: url('.cdnPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
   223 		$this->fading_button = '<div style="background-image: url('.cdnPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
   224                               <a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"' . $admintitle . '><img style="border-width: 0;" alt=" " src="'.cdnPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
   224 															<a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"' . $admintitle . '><img style="border-width: 0;" alt=" " src="'.cdnPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
   225                             </div>';
   225 														</div>';
   226     
   226 		
   227     // For each theme, check ACLs and delete from RAM if not authorized
   227 		// For each theme, check ACLs and delete from RAM if not authorized
   228     foreach ( $this->theme_list as $i => $theme )
   228 		foreach ( $this->theme_list as $i => $theme )
   229     {
   229 		{
   230       if ( !@$theme['group_list'] )
   230 			if ( !@$theme['group_list'] )
   231         continue;
   231 				continue;
   232       if ( $theme['theme_id'] === getConfig('theme_default') )
   232 			if ( $theme['theme_id'] === getConfig('theme_default') )
   233         continue;
   233 				continue;
   234       switch ( $theme['group_policy'] )
   234 			switch ( $theme['group_policy'] )
   235       {
   235 			{
   236         case 'allow_all':
   236 				case 'allow_all':
   237           // Unconditionally allowed
   237 					// Unconditionally allowed
   238           continue;
   238 					continue;
   239           break;
   239 					break;
   240         case 'whitelist':
   240 				case 'whitelist':
   241           // If we're not on the list, off to the left please
   241 					// If we're not on the list, off to the left please
   242           $list = enano_json_decode($theme['group_list']);
   242 					$list = enano_json_decode($theme['group_list']);
   243           $allowed = false;
   243 					$allowed = false;
   244           foreach ( $list as $acl )
   244 					foreach ( $list as $acl )
   245           {
   245 					{
   246             if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
   246 						if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
   247               // Invalid list entry, silently allow (maybe not a good idea but
   247 							// Invalid list entry, silently allow (maybe not a good idea but
   248               // really, these things are checked before they're inserted)
   248 							// really, these things are checked before they're inserted)
   249               continue 2;
   249 							continue 2;
   250             $mode = $match[1];
   250 						$mode = $match[1];
   251             $id = intval($match[2]);
   251 						$id = intval($match[2]);
   252             switch ( $mode )
   252 						switch ( $mode )
   253             {
   253 						{
   254               case 'u':
   254 							case 'u':
   255                 $allowed = ( $id == $session->user_id );
   255 								$allowed = ( $id == $session->user_id );
   256                 if ( $allowed )
   256 								if ( $allowed )
   257                   break 2;
   257 									break 2;
   258                 break;
   258 								break;
   259               case 'g':
   259 							case 'g':
   260                 $allowed = ( isset($session->groups[$id]) );
   260 								$allowed = ( isset($session->groups[$id]) );
   261                 if ( $allowed )
   261 								if ( $allowed )
   262                   break 2;
   262 									break 2;
   263             }
   263 						}
   264           }
   264 					}
   265           if ( !$allowed )
   265 					if ( !$allowed )
   266           {
   266 					{
   267             unset($this->theme_list[$i]);
   267 						unset($this->theme_list[$i]);
   268           }
   268 					}
   269           break;
   269 					break;
   270         case 'blacklist':
   270 				case 'blacklist':
   271           // If we're ON the list, off to the left please
   271 					// If we're ON the list, off to the left please
   272           $list = enano_json_decode($theme['group_list']);
   272 					$list = enano_json_decode($theme['group_list']);
   273           $allowed = true;
   273 					$allowed = true;
   274           foreach ( $list as $acl )
   274 					foreach ( $list as $acl )
   275           {
   275 					{
   276             if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
   276 						if ( !preg_match('/^(u|g):([0-9]+)$/', $acl, $match) )
   277               // Invalid list entry, silently allow (maybe not a good idea but
   277 							// Invalid list entry, silently allow (maybe not a good idea but
   278               // really, these things are checked before they're inserted)
   278 							// really, these things are checked before they're inserted)
   279               continue 2;
   279 							continue 2;
   280             $mode = $match[1];
   280 						$mode = $match[1];
   281             $id = intval($match[2]);
   281 						$id = intval($match[2]);
   282             switch ( $mode )
   282 						switch ( $mode )
   283             {
   283 						{
   284               case 'u':
   284 							case 'u':
   285                 $allowed = ( $id != $session->user_id );
   285 								$allowed = ( $id != $session->user_id );
   286                 if ( !$allowed )
   286 								if ( !$allowed )
   287                   break 2;
   287 									break 2;
   288                 break;
   288 								break;
   289               case 'g':
   289 							case 'g':
   290                 $allowed = ( !isset($session->groups[$id]) );
   290 								$allowed = ( !isset($session->groups[$id]) );
   291                 if ( !$allowed )
   291 								if ( !$allowed )
   292                   break 2;
   292 									break 2;
   293             }
   293 						}
   294           }
   294 					}
   295           if ( !$allowed )
   295 					if ( !$allowed )
   296           {
   296 					{
   297             unset($this->theme_list[$i]);
   297 						unset($this->theme_list[$i]);
   298           }
   298 					}
   299           break;
   299 					break;
   300       }
   300 			}
   301     }
   301 		}
   302     
   302 		
   303     $this->theme_list = array_values($this->theme_list);
   303 		$this->theme_list = array_values($this->theme_list);
   304     
   304 		
   305     // Rebuild associative theme list
   305 		// Rebuild associative theme list
   306     $this->named_theme_list = array();
   306 		$this->named_theme_list = array();
   307     foreach ( $this->theme_list as $i => &$theme )
   307 		foreach ( $this->theme_list as $i => &$theme )
   308       $this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   308 			$this->named_theme_list[ $theme['theme_id'] ] =& $this->theme_list[$i];
   309   }
   309 	}
   310   
   310 	
   311   /**
   311 	/**
   312    * Register a new sidebar block.
   312  	* Register a new sidebar block.
   313    * @param string Block title
   313  	* @param string Block title
   314    * @param string Block HTML
   314  	* @param string Block HTML
   315    * @param bool If true, the class of the block will be the same as the one used for blocks that are a list of links instead of HTML content. This can do some wacky things like make all your <a>s block level.
   315  	* @param bool If true, the class of the block will be the same as the one used for blocks that are a list of links instead of HTML content. This can do some wacky things like make all your <a>s block level.
   316    */
   316  	*/
   317   
   317 	
   318   function sidebar_widget($t, $h, $use_normal_section = false)
   318 	function sidebar_widget($t, $h, $use_normal_section = false)
   319   {
   319 	{
   320     global $db, $session, $paths, $template, $plugins; // Common objects
   320 		global $db, $session, $paths, $template, $plugins; // Common objects
   321     if ( !$this->theme_loaded )
   321 		if ( !$this->theme_loaded )
   322     {
   322 		{
   323       $this->load_theme($session->theme, $session->style);
   323 			$this->load_theme($session->theme, $session->style);
   324     }
   324 		}
   325     if(!$this->sidebar_widgets)
   325 		if(!$this->sidebar_widgets)
   326       $this->sidebar_widgets = '';
   326 			$this->sidebar_widgets = '';
   327     $tplvars = $this->extract_vars('elements.tpl');
   327 		$tplvars = $this->extract_vars('elements.tpl');
   328     
   328 		
   329     if ( $use_normal_section )
   329 		if ( $use_normal_section )
   330     {
   330 		{
   331       $parser = $this->makeParserText($tplvars['sidebar_section']);
   331 			$parser = $this->makeParserText($tplvars['sidebar_section']);
   332     }
   332 		}
   333     else
   333 		else
   334     {
   334 		{
   335       $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
   335 			$parser = $this->makeParserText($tplvars['sidebar_section_raw']);
   336     }
   336 		}
   337     
   337 		
   338     $parser->assign_vars(Array('TITLE' => '{TITLE}','CONTENT' => $h));
   338 		$parser->assign_vars(Array('TITLE' => '{TITLE}','CONTENT' => $h));
   339     $this->plugin_blocks[$t] = $parser->run();
   339 		$this->plugin_blocks[$t] = $parser->run();
   340     $this->plugin_blocks_content[$t] = $h;
   340 		$this->plugin_blocks_content[$t] = $h;
   341     $this->sidebar_widgets .= $parser->run();
   341 		$this->sidebar_widgets .= $parser->run();
   342   }
   342 	}
   343   function add_header($html)
   343 	function add_header($html)
   344   {
   344 	{
   345     /* debug only **
   345 		/* debug only **
   346     $bt = debug_backtrace();
   346 		$bt = debug_backtrace();
   347     $bt = $bt[1];
   347 		$bt = $bt[1];
   348     $this->additional_headers .= "\n    <!-- {$bt['file']}:{$bt['line']} -->\n    " . $html;
   348 		$this->additional_headers .= "\n    <!-- {$bt['file']}:{$bt['line']} -->\n    " . $html;
   349     */
   349 		*/
   350     $this->additional_headers .= "\n   " . $html;
   350 		$this->additional_headers .= "\n   " . $html;
   351   }
   351 	}
   352   function get_css($s = false)
   352 	function get_css($s = false)
   353   {
   353 	{
   354     global $db, $session, $paths, $template, $plugins; // Common objects
   354 		global $db, $session, $paths, $template, $plugins; // Common objects
   355     $this->init_vars();
   355 		$this->init_vars();
   356     
   356 		
   357     $path = ( $s ) ? 'css/'.$s : 'css/'.$this->style.'.css';
   357 		$path = ( $s ) ? 'css/'.$s : 'css/'.$this->style.'.css';
   358     
   358 		
   359     if ( !file_exists(ENANO_ROOT . '/themes/' . $this->theme . '/' . $path) )
   359 		if ( !file_exists(ENANO_ROOT . '/themes/' . $this->theme . '/' . $path) )
   360     {
   360 		{
   361       echo "/* WARNING: Falling back to default file because file $path does not exist */\n";
   361 			echo "/* WARNING: Falling back to default file because file $path does not exist */\n";
   362       $path = 'css/' . $this->style_list[0] . '.css';
   362 			$path = 'css/' . $this->style_list[0] . '.css';
   363     }
   363 		}
   364     
   364 		
   365     return $this->process_template($path);
   365 		return $this->process_template($path);
   366   }
   366 	}
   367   function load_theme($name = false, $css = false)
   367 	function load_theme($name = false, $css = false)
   368   {
   368 	{
   369     global $db, $session, $paths, $template, $plugins; // Common objects
   369 		global $db, $session, $paths, $template, $plugins; // Common objects
   370     $this->theme = ( $name ) ? $name : $session->theme;
   370 		$this->theme = ( $name ) ? $name : $session->theme;
   371     $this->style = ( $css ) ? $css : $session->style;
   371 		$this->style = ( $css ) ? $css : $session->style;
   372     if ( !$this->theme )
   372 		if ( !$this->theme )
   373     {
   373 		{
   374       $this->theme = $this->theme_list[0]['theme_id'];
   374 			$this->theme = $this->theme_list[0]['theme_id'];
   375       $this->style = preg_replace('/\.css$/', '', $this->theme_list[0]['default_style']);
   375 			$this->style = preg_replace('/\.css$/', '', $this->theme_list[0]['default_style']);
   376     }
   376 		}
   377     // Make sure we're allowed to use this theme.
   377 		// Make sure we're allowed to use this theme.
   378     if ( (
   378 		if ( (
   379         // If it was removed, it's probably blocked by an ACL, or it was uninstalled
   379 				// If it was removed, it's probably blocked by an ACL, or it was uninstalled
   380         !isset($this->named_theme_list[$this->theme]) ||
   380 				!isset($this->named_theme_list[$this->theme]) ||
   381         // Check if the theme is disabled
   381 				// Check if the theme is disabled
   382         ( isset($this->named_theme_list[$this->theme]) && isset($this->named_theme_list[$this->theme]['enabled']) && $this->named_theme_list[$this->theme]['enabled'] == 0 ) )
   382 				( isset($this->named_theme_list[$this->theme]) && isset($this->named_theme_list[$this->theme]['enabled']) && $this->named_theme_list[$this->theme]['enabled'] == 0 ) )
   383         // Above all, if it's a system theme, don't inhibit the loading process.
   383 				// Above all, if it's a system theme, don't inhibit the loading process.
   384         && !in_array($this->theme, $this->system_themes)
   384 				&& !in_array($this->theme, $this->system_themes)
   385       )
   385 			)
   386     {
   386 		{
   387       // No, something is preventing it - fall back to site default
   387 			// No, something is preventing it - fall back to site default
   388       $this->theme = $this->default_theme;
   388 			$this->theme = $this->default_theme;
   389       
   389 			
   390       // Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   390 			// Come up with the default style. If the CSS file specified in default_style exists, we're good, just
   391       // use that. Otherwise, use the first stylesheet that comes to mind.
   391 			// use that. Otherwise, use the first stylesheet that comes to mind.
   392       $df_data =& $this->named_theme_list[ $this->theme ];
   392 			$df_data =& $this->named_theme_list[ $this->theme ];
   393       $this->style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   393 			$this->style = ( in_array($df_data['default_style'], $df_data['css']) ) ? $df_data['default_style'] : $df_data['css'][0];
   394     }
   394 		}
   395     // The list of styles for the currently selected theme
   395 		// The list of styles for the currently selected theme
   396     $this->style_list =& $this->named_theme_list[ $this->theme ]['css'];
   396 		$this->style_list =& $this->named_theme_list[ $this->theme ]['css'];
   397     $this->theme_loaded = true;
   397 		$this->theme_loaded = true;
   398   }
   398 	}
   399   
   399 	
   400   /**
   400 	/**
   401    * Change the theme we're supposed to display.
   401  	* Change the theme we're supposed to display.
   402    * @param string Theme name
   402  	* @param string Theme name
   403    * @param string Style name; optional
   403  	* @param string Style name; optional
   404    */
   404  	*/
   405   
   405 	
   406   function set_theme($theme = false, $style = false)
   406 	function set_theme($theme = false, $style = false)
   407   {
   407 	{
   408     $this->theme_initted = false;
   408 		$this->theme_initted = false;
   409     $this->load_theme($theme, $style);
   409 		$this->load_theme($theme, $style);
   410   }
   410 	}
   411   
   411 	
   412   /**
   412 	/**
   413    * Change the page we're supposed to generate for
   413  	* Change the page we're supposed to generate for
   414    * @param mixed Page ID *or* PageProcessor. If a PageProcessor, pulls permission info and such from that; if not, starts a PageProcessor. YOU SHOULD USE A PageProcessor WHENEVER POSSIBLE! It improves efficiency.
   414  	* @param mixed Page ID *or* PageProcessor. If a PageProcessor, pulls permission info and such from that; if not, starts a PageProcessor. YOU SHOULD USE A PageProcessor WHENEVER POSSIBLE! It improves efficiency.
   415    * @param string Namespace; not required if including a PageProcessor.
   415  	* @param string Namespace; not required if including a PageProcessor.
   416    */
   416  	*/
   417   
   417 	
   418   function set_page($page_id_or_pp, $namespace = false)
   418 	function set_page($page_id_or_pp, $namespace = false)
   419   {
   419 	{
   420     if ( is_object($page_id_or_pp) && get_class($page_id_or_pp) === 'PageProcessor' )
   420 		if ( is_object($page_id_or_pp) && get_class($page_id_or_pp) === 'PageProcessor' )
   421     {
   421 		{
   422       $this->page_initted = false;
   422 			$this->page_initted = false;
   423       $page =& $page_id_or_pp;
   423 			$page =& $page_id_or_pp;
   424       $this->page = $page;
   424 			$this->page = $page;
   425       $this->page_id = $page->page_id;
   425 			$this->page_id = $page->page_id;
   426       $this->namespace = $page->namespace;
   426 			$this->namespace = $page->namespace;
   427     }
   427 		}
   428     else if ( is_string($page_id_or_pp) )
   428 		else if ( is_string($page_id_or_pp) )
   429     {
   429 		{
   430       if ( !is_string($namespace) )
   430 			if ( !is_string($namespace) )
   431         return false;
   431 				return false;
   432       
   432 			
   433       if ( $page_id_or_pp === $this->page_id && $namespace === $this->namespace )
   433 			if ( $page_id_or_pp === $this->page_id && $namespace === $this->namespace )
   434         return true;
   434 				return true;
   435       
   435 			
   436       $this->page_initted = false;
   436 			$this->page_initted = false;
   437       $this->page = false;
   437 			$this->page = false;
   438       $this->page_id = sanitize_page_id($page_id_or_pp);
   438 			$this->page_id = sanitize_page_id($page_id_or_pp);
   439       $this->namespace = $namespace;
   439 			$this->namespace = $namespace;
   440     }
   440 		}
   441     else
   441 		else
   442     {
   442 		{
   443       return false;
   443 			return false;
   444     }
   444 		}
   445     return true;
   445 		return true;
   446   }
   446 	}
   447   
   447 	
   448   /**
   448 	/**
   449    * Queue a Javascript file to be loaded with the page instead of on demand.
   449  	* Queue a Javascript file to be loaded with the page instead of on demand.
   450    * @param mixed Javascript file string or array thereof, extensions are optional
   450  	* @param mixed Javascript file string or array thereof, extensions are optional
   451    * @example
   451  	* @example
   452    <code>
   452  	<code>
   453    $template->preload_js(array('jquery', 'jquery-ui'));
   453  	$template->preload_js(array('jquery', 'jquery-ui'));
   454    $template->preload_js('admin-menu.js');
   454  	$template->preload_js('admin-menu.js');
   455    </code>
   455  	</code>
   456    * @return null
   456  	* @return null
   457    */
   457  	*/
   458   
   458 	
   459   function preload_js($filemixed)
   459 	function preload_js($filemixed)
   460   {
   460 	{
   461     if ( is_string($filemixed) )
   461 		if ( is_string($filemixed) )
   462       $files = array($filemixed);
   462 			$files = array($filemixed);
   463     else if ( is_array($filemixed) )
   463 		else if ( is_array($filemixed) )
   464       $files = $filemixed;
   464 			$files = $filemixed;
   465     else
   465 		else
   466       // :-/
   466 			// :-/
   467       return null;
   467 			return null;
   468       
   468 			
   469     $this->js_preload = array_values(array_merge($this->js_preload, $files));
   469 		$this->js_preload = array_values(array_merge($this->js_preload, $files));
   470   }
   470 	}
   471   
   471 	
   472   /**
   472 	/**
   473    * Queue some HTML to be inserted after the Javascript runtime.
   473  	* Queue some HTML to be inserted after the Javascript runtime.
   474    * @param string HTML glob
   474  	* @param string HTML glob
   475    */
   475  	*/
   476   
   476 	
   477   function add_header_js($html)
   477 	function add_header_js($html)
   478   {
   478 	{
   479     $this->js_append .= "$html\n    ";
   479 		$this->js_append .= "$html\n    ";
   480   }
   480 	}
   481   
   481 	
   482   /**
   482 	/**
   483    * Global, only-called-once init. Goes to all themes.
   483  	* Global, only-called-once init. Goes to all themes.
   484    */
   484  	*/
   485   
   485 	
   486   function init_global_vars()
   486 	function init_global_vars()
   487   {
   487 	{
   488     global $db, $session, $paths, $template, $plugins; // Common objects
   488 		global $db, $session, $paths, $template, $plugins; // Common objects
   489     global $lang;
   489 		global $lang;
   490     global $email;
   490 		global $email;
   491     
   491 		
   492     $is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false;
   492 		$is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false;
   493     $is_msie = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? true : false;
   493 		$is_msie = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? true : false;
   494     
   494 		
   495     $this->assign_bool(array(
   495 		$this->assign_bool(array(
   496         'auth_admin' => $session->user_level >= USER_LEVEL_ADMIN ? true : false,
   496 				'auth_admin' => $session->user_level >= USER_LEVEL_ADMIN ? true : false,
   497         'user_logged_in' => $session->user_logged_in,
   497 				'user_logged_in' => $session->user_logged_in,
   498         'opera' => $is_opera,
   498 				'opera' => $is_opera,
   499         'msie' => $is_msie
   499 				'msie' => $is_msie
   500       ));
   500 			));
   501     
   501 		
   502     if ( $session->sid_super )
   502 		if ( $session->sid_super )
   503     {
   503 		{
   504       $ash = '&amp;auth=' . $session->sid_super;
   504 			$ash = '&amp;auth=' . $session->sid_super;
   505       $asq = "?auth=" . $session->sid_super;
   505 			$asq = "?auth=" . $session->sid_super;
   506       $asa = "&auth=" . $session->sid_super;
   506 			$asa = "&auth=" . $session->sid_super;
   507       $as2 = htmlspecialchars(urlSeparator) . 'auth='.$session->sid_super;
   507 			$as2 = htmlspecialchars(urlSeparator) . 'auth='.$session->sid_super;
   508     }
   508 		}
   509     else
   509 		else
   510     {
   510 		{
   511       $asq = '';
   511 			$asq = '';
   512       $asa = '';
   512 			$asa = '';
   513       $as2 = '';
   513 			$as2 = '';
   514       $ash = '';
   514 			$ash = '';
   515     }
   515 		}
   516     
   516 		
   517     // Append the Enano version to URLs to break the cache on upgrades
   517 		// Append the Enano version to URLs to break the cache on upgrades
   518     $enano_version = enano_version();
   518 		$enano_version = enano_version();
   519     
   519 		
   520     // Set up javascript includes
   520 		// Set up javascript includes
   521     // these depend heavily on whether we have a CDN to work with or not
   521 		// these depend heavily on whether we have a CDN to work with or not
   522     if ( getConfig('cdn_path') )
   522 		if ( getConfig('cdn_path') )
   523     {
   523 		{
   524       // we're on a CDN, point to static includes
   524 			// we're on a CDN, point to static includes
   525       // CLI javascript compression script: includes/clientside/jscompress.php
   525 			// CLI javascript compression script: includes/clientside/jscompress.php
   526       $js_head = '<script type="text/javascript" src="' . cdnPath . '/includes/clientside/static/enano-lib-basic.js?' . $enano_version . '"></script>';
   526 			$js_head = '<script type="text/javascript" src="' . cdnPath . '/includes/clientside/static/enano-lib-basic.js?' . $enano_version . '"></script>';
   527       
   527 			
   528       if ( !empty($this->js_preload) )
   528 			if ( !empty($this->js_preload) )
   529       {
   529 			{
   530         $loadlines = array();
   530 				$loadlines = array();
   531         
   531 				
   532         // make unique
   532 				// make unique
   533         foreach ( $this->js_preload as &$script )
   533 				foreach ( $this->js_preload as &$script )
   534         {
   534 				{
   535           $script = preg_replace('/\.js$/', '', $script) . '.js';
   535 					$script = preg_replace('/\.js$/', '', $script) . '.js';
   536         }
   536 				}
   537         unset($script);
   537 				unset($script);
   538         $this->js_preload = array_unique($this->js_preload);
   538 				$this->js_preload = array_unique($this->js_preload);
   539         
   539 				
   540         foreach ( $this->js_preload as $script )
   540 				foreach ( $this->js_preload as $script )
   541         {
   541 				{
   542           $js_head .= "\n    <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/static/$script?$enano_version\"></script>";
   542 					$js_head .= "\n    <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/static/$script?$enano_version\"></script>";
   543           // special case for l10n: also load strings
   543 					// special case for l10n: also load strings
   544           if ( $script == 'l10n.js' )
   544 					if ( $script == 'l10n.js' )
   545           {
   545 					{
   546             global $lang;
   546 						global $lang;
   547             $js_head .= "\n    <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", "$enano_version") . "\"></script>";
   547 						$js_head .= "\n    <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", "$enano_version") . "\"></script>";
   548           }
   548 					}
   549           $loadlines[] = "loaded_components['$script'] = true;";
   549 					$loadlines[] = "loaded_components['$script'] = true;";
   550         }
   550 				}
   551         
   551 				
   552         // tell the system that this stuff is already loaded
   552 				// tell the system that this stuff is already loaded
   553         $loadlines = implode("\n      ", $loadlines);
   553 				$loadlines = implode("\n      ", $loadlines);
   554         $js_head .= "\n    <script type=\"text/javascript\">
   554 				$js_head .= "\n    <script type=\"text/javascript\">
   555       var loaded_components = loaded_components || {};
   555 			var loaded_components = loaded_components || {};
   556       $loadlines
   556 			$loadlines
   557     </script>";
   557 		</script>";
   558       }
   558 			}
   559       
   559 			
   560       $js_foot = <<<JSEOF
   560 			$js_foot = <<<JSEOF
   561     <script type="text/javascript">
   561 		<script type="text/javascript">
   562       // This initializes the Javascript runtime when the DOM is ready - not when the page is
   562 			// This initializes the Javascript runtime when the DOM is ready - not when the page is
   563       // done loading, because enano-lib-basic still has to load some 15 other script files
   563 			// done loading, because enano-lib-basic still has to load some 15 other script files
   564       // check for the init function - this is a KHTML fix
   564 			// check for the init function - this is a KHTML fix
   565       // This doesn't seem to work properly in IE in 1.1.x - there are some problems with
   565 			// This doesn't seem to work properly in IE in 1.1.x - there are some problems with
   566       // tinyMCE and l10n.
   566 			// tinyMCE and l10n.
   567       if ( typeof ( enano_init ) == 'function' && !IE )
   567 			if ( typeof ( enano_init ) == 'function' && !IE )
   568       {
   568 			{
   569         enano_init();
   569 				enano_init();
   570         window.onload = function(e) {  };
   570 				window.onload = function(e) {  };
   571       }
   571 			}
   572     </script>
   572 		</script>
   573     $this->js_append
   573 		$this->js_append
   574 JSEOF;
   574 JSEOF;
   575     }
   575 		}
   576     else
   576 		else
   577     {
   577 		{
   578       $cdnpath = cdnPath;
   578 			$cdnpath = cdnPath;
   579       $js_head = '';
   579 			$js_head = '';
   580       
   580 			
   581       // point to jsres compressor
   581 			// point to jsres compressor
   582       $js_head .= <<<JSEOF
   582 			$js_head .= <<<JSEOF
   583       <!-- Only load a basic set of functions for now. Let the rest of the API load when the page is finished. -->
   583 			<!-- Only load a basic set of functions for now. Let the rest of the API load when the page is finished. -->
   584       <script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?early&amp;$enano_version"></script>
   584 			<script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?early&amp;$enano_version"></script>
   585 JSEOF;
   585 JSEOF;
   586       $js_foot = '';
   586 			$js_foot = '';
   587       
   587 			
   588       if ( !empty($this->js_preload) )
   588 			if ( !empty($this->js_preload) )
   589       {
   589 			{
   590         foreach ( $this->js_preload as &$script )
   590 				foreach ( $this->js_preload as &$script )
   591         {
   591 				{
   592           $script = preg_replace('/\.js$/', '', $script) . '.js';
   592 					$script = preg_replace('/\.js$/', '', $script) . '.js';
   593         }
   593 				}
   594         $this->js_preload = array_unique($this->js_preload);
   594 				$this->js_preload = array_unique($this->js_preload);
   595         if ( in_array('l10n.js', $this->js_preload) )
   595 				if ( in_array('l10n.js', $this->js_preload) )
   596         {
   596 				{
   597           // special case for l10n: also load strings
   597 					// special case for l10n: also load strings
   598           global $lang;
   598 					global $lang;
   599           $js_foot .= "\n    <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", $enano_version, true) . "\"></script>";
   599 					$js_foot .= "\n    <script type=\"text/javascript\" src=\"" . makeUrlNS("Special", "LangExportJSON/$lang->lang_id", $enano_version, true) . "\"></script>";
   600         }
   600 				}
   601         $scripts = implode(',', $this->js_preload);
   601 				$scripts = implode(',', $this->js_preload);
   602         $js_foot .= "\n    <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/jsres.php?f=$scripts&amp;$enano_version\"></script>";
   602 				$js_foot .= "\n    <script type=\"text/javascript\" src=\"" . cdnPath . "/includes/clientside/jsres.php?f=$scripts&amp;$enano_version\"></script>";
   603         
   603 				
   604       }
   604 			}
   605       
   605 			
   606       $js_foot .= <<<JSEOF
   606 			$js_foot .= <<<JSEOF
   607     <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
   607 		<!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
   608     <script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?$enano_version"></script>
   608 		<script type="text/javascript" src="$cdnpath/includes/clientside/jsres.php?$enano_version"></script>
   609     <script type="text/javascript">//<![CDATA[
   609 		<script type="text/javascript">//<![CDATA[
   610       // This initializes the Javascript runtime when the DOM is ready - not when the page is
   610 			// This initializes the Javascript runtime when the DOM is ready - not when the page is
   611       // done loading, because enano-lib-basic still has to load some 15 other script files
   611 			// done loading, because enano-lib-basic still has to load some 15 other script files
   612       // check for the init function - this is a KHTML fix
   612 			// check for the init function - this is a KHTML fix
   613       // This doesn't seem to work properly in IE in 1.1.x - there are some problems with
   613 			// This doesn't seem to work properly in IE in 1.1.x - there are some problems with
   614       // tinyMCE and l10n.
   614 			// tinyMCE and l10n.
   615       if ( typeof ( enano_init ) == 'function' && !IE )
   615 			if ( typeof ( enano_init ) == 'function' && !IE )
   616       {
   616 			{
   617         enano_init();
   617 				enano_init();
   618         window.onload = function(e) {  };
   618 				window.onload = function(e) {  };
   619       }
   619 			}
   620     //]]></script>
   620 		//]]></script>
   621     $this->js_append
   621 		$this->js_append
   622 JSEOF;
   622 JSEOF;
   623     }
   623 		}
   624   
   624 	
   625     
   625 		
   626     $this->assign_bool(array(
   626 		$this->assign_bool(array(
   627         'fixed_menus' => false,
   627 				'fixed_menus' => false,
   628         'export' => false,
   628 				'export' => false,
   629         'right_sidebar' => true,
   629 				'right_sidebar' => true,
   630         'enable_uploads' => ( getConfig('enable_uploads') == '1' && $session->get_permissions('upload_files') ) ? true : false,
   630 				'enable_uploads' => ( getConfig('enable_uploads') == '1' && $session->get_permissions('upload_files') ) ? true : false,
   631         'stupid_mode' => false,
   631 				'stupid_mode' => false,
   632       ));
   632 			));
   633     
   633 		
   634     // Add the e-mail address client code to the header
   634 		// Add the e-mail address client code to the header
   635     $this->add_header($email->jscode());
   635 		$this->add_header($email->jscode());
   636     
   636 		
   637     // Assign our main variables
   637 		// Assign our main variables
   638     $this->assign_vars(array(
   638 		$this->assign_vars(array(
   639         'SITE_NAME' => htmlspecialchars(getConfig('site_name')),
   639 				'SITE_NAME' => htmlspecialchars(getConfig('site_name')),
   640         'USERNAME' => $session->username,
   640 				'USERNAME' => $session->username,
   641         'SITE_DESC' => htmlspecialchars(getConfig('site_desc')),
   641 				'SITE_DESC' => htmlspecialchars(getConfig('site_desc')),
   642         'SCRIPTPATH' => scriptPath,
   642 				'SCRIPTPATH' => scriptPath,
   643         'CONTENTPATH' => contentPath,
   643 				'CONTENTPATH' => contentPath,
   644         'CDNPATH' => cdnPath,
   644 				'CDNPATH' => cdnPath,
   645         'ADMIN_SID_QUES' => $asq,
   645 				'ADMIN_SID_QUES' => $asq,
   646         'ADMIN_SID_AMP' => $asa,
   646 				'ADMIN_SID_AMP' => $asa,
   647         'ADMIN_SID_AMP_HTML' => $ash,
   647 				'ADMIN_SID_AMP_HTML' => $ash,
   648         'ADMIN_SID_AUTO' => $as2,
   648 				'ADMIN_SID_AUTO' => $as2,
   649         'ADMIN_SID_RAW' =>  ( is_string($session->sid_super) ? $session->sid_super : '' ),
   649 				'ADMIN_SID_RAW' =>  ( is_string($session->sid_super) ? $session->sid_super : '' ),
   650         'CSRF_TOKEN' => $session->csrf_token,
   650 				'CSRF_TOKEN' => $session->csrf_token,
   651         'COPYRIGHT' => RenderMan::parse_internal_links(getConfig('copyright_notice')),
   651 				'COPYRIGHT' => RenderMan::parse_internal_links(getConfig('copyright_notice')),
   652         'REQUEST_URI' => ( defined('ENANO_CLI') ? '' : $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] ),
   652 				'REQUEST_URI' => ( defined('ENANO_CLI') ? '' : $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] ),
   653         'SEARCH_ACTION' => makeUrlNS('Special', 'Search'),
   653 				'SEARCH_ACTION' => makeUrlNS('Special', 'Search'),
   654         'INPUT_TITLE' => ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars( $paths->get_pathskey($this->page_id, $this->namespace) ) . '" />' : ''),
   654 				'INPUT_TITLE' => ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars( $paths->get_pathskey($this->page_id, $this->namespace) ) . '" />' : ''),
   655         'INPUT_AUTH' => ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : ''),
   655 				'INPUT_AUTH' => ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : ''),
   656         'MAIN_PAGE' => get_main_page(),
   656 				'MAIN_PAGE' => get_main_page(),
   657         'UNREAD_PMS' => $session->unread_pms,
   657 				'UNREAD_PMS' => $session->unread_pms,
   658         'JS_HEADER' => $js_head,
   658 				'JS_HEADER' => $js_head,
   659         'JS_FOOTER' => $js_foot,
   659 				'JS_FOOTER' => $js_foot,
   660         'URL_ABOUT_ENANO' => makeUrlNS('Special', 'About_Enano', '', true),
   660 				'URL_ABOUT_ENANO' => makeUrlNS('Special', 'About_Enano', '', true),
   661         'ENANO_VERSION' => enano_version()
   661 				'ENANO_VERSION' => enano_version()
   662       ), true);
   662 			), true);
   663     
   663 		
   664     $tpl_strings = array();
   664 		$tpl_strings = array();
   665     foreach ( $paths->nslist as $ns_id => $ns_prefix )
   665 		foreach ( $paths->nslist as $ns_id => $ns_prefix )
   666     {
   666 		{
   667       $tpl_strings[ 'NS_' . strtoupper($ns_id) ] = $ns_prefix;
   667 			$tpl_strings[ 'NS_' . strtoupper($ns_id) ] = $ns_prefix;
   668     }
   668 		}
   669     
   669 		
   670     $this->assign_vars($tpl_strings, true);
   670 		$this->assign_vars($tpl_strings, true);
   671   }
   671 	}
   672   
   672 	
   673   /**
   673 	/**
   674    * Init theme vars, like sidebar, global JS, that kind of stuff.
   674  	* Init theme vars, like sidebar, global JS, that kind of stuff.
   675    */
   675  	*/
   676   
   676 	
   677   function init_theme_vars()
   677 	function init_theme_vars()
   678   {
   678 	{
   679     global $db, $session, $paths, $template, $plugins; // Common objects
   679 		global $db, $session, $paths, $template, $plugins; // Common objects
   680     global $lang;
   680 		global $lang;
   681     
   681 		
   682     // allows conditional testing of the theme ID (a bit crude, came from my NSIS days)
   682 		// allows conditional testing of the theme ID (a bit crude, came from my NSIS days)
   683     $this->assign_bool(array(
   683 		$this->assign_bool(array(
   684         "theme_is_{$this->theme}" => true
   684 				"theme_is_{$this->theme}" => true
   685       ));
   685 			));
   686     
   686 		
   687     $this->elements = $this->extract_vars('elements.tpl');
   687 		$this->elements = $this->extract_vars('elements.tpl');
   688     
   688 		
   689     // Generate the code for the Administration and Edit Sidebar buttons
   689 		// Generate the code for the Administration and Edit Sidebar buttons
   690     // Once again, the new template parsing system can be used here
   690 		// Once again, the new template parsing system can be used here
   691     
   691 		
   692     $parser = $this->makeParserText($this->elements['sidebar_button']);
   692 		$parser = $this->makeParserText($this->elements['sidebar_button']);
   693     
   693 		
   694     $parser->assign_vars(Array(
   694 		$parser->assign_vars(Array(
   695         'HREF'=>makeUrlNS('Special', 'Administration'),
   695 				'HREF'=>makeUrlNS('Special', 'Administration'),
   696         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxStartAdminLogin()); return false; }"',
   696 				'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxStartAdminLogin()); return false; }"',
   697         'TEXT'=>$lang->get('sidebar_btn_administration'),
   697 				'TEXT'=>$lang->get('sidebar_btn_administration'),
   698       ));
   698 			));
   699     
   699 		
   700     $admin_link = $parser->run();
   700 		$admin_link = $parser->run();
   701     
   701 		
   702     $parser->assign_vars(Array(
   702 		$parser->assign_vars(Array(
   703         'HREF'=>makeUrlNS('Special', 'EditSidebar'),
   703 				'HREF'=>makeUrlNS('Special', 'EditSidebar'),
   704         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxLoginNavTo(\'Special\', \'EditSidebar\', ' . USER_LEVEL_ADMIN . ')); return false; }"',
   704 				'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxLoginNavTo(\'Special\', \'EditSidebar\', ' . USER_LEVEL_ADMIN . ')); return false; }"',
   705         'TEXT'=>$lang->get('sidebar_btn_editsidebar'),
   705 				'TEXT'=>$lang->get('sidebar_btn_editsidebar'),
   706       ));
   706 			));
   707     
   707 		
   708     $sidebar_link = $parser->run();
   708 		$sidebar_link = $parser->run();
   709     
   709 		
   710     $this->assign_vars(array(
   710 		$this->assign_vars(array(
   711         'ADMIN_LINK' => $admin_link,
   711 				'ADMIN_LINK' => $admin_link,
   712         'SIDEBAR_LINK' => $sidebar_link,
   712 				'SIDEBAR_LINK' => $sidebar_link,
   713         'THEME_ID' => $this->theme,
   713 				'THEME_ID' => $this->theme,
   714         'STYLE_ID' => $this->style
   714 				'STYLE_ID' => $this->style
   715       ));
   715 			));
   716     
   716 		
   717     // Add the site description sidebar block
   717 		// Add the site description sidebar block
   718     $this->sidebar_widget($lang->get('sidebar_title_about'), '<p>' . htmlspecialchars(getConfig('site_desc')) . '</p>');
   718 		$this->sidebar_widget($lang->get('sidebar_title_about'), '<p>' . htmlspecialchars(getConfig('site_desc')) . '</p>');
   719     
   719 		
   720     $this->theme_initted = true;
   720 		$this->theme_initted = true;
   721   }
   721 	}
   722   
   722 	
   723   /**
   723 	/**
   724    * Init page vars, like the toolbar, local JS, etc.
   724  	* Init page vars, like the toolbar, local JS, etc.
   725    */
   725  	*/
   726   
   726 	
   727   function init_page_vars()
   727 	function init_page_vars()
   728   {
   728 	{
   729     global $db, $session, $paths, $template, $plugins; // Common objects
   729 		global $db, $session, $paths, $template, $plugins; // Common objects
   730     global $lang;
   730 		global $lang;
   731     
   731 		
   732     if ( !$this->page )
   732 		if ( !$this->page )
   733     {
   733 		{
   734       $this->page = new PageProcessor($this->page_id, $this->namespace);
   734 			$this->page = new PageProcessor($this->page_id, $this->namespace);
   735     }
   735 		}
   736     
   736 		
   737     $conds = $this->page->ns->get_conds();
   737 		$conds = $this->page->ns->get_conds();
   738     
   738 		
   739     $this->assign_bool(array(
   739 		$this->assign_bool(array(
   740         'in_admin' => ( ( $this->page_id == 'Administration' && $this->namespace == 'Special' ) || $this->namespace == 'Admin' ),
   740 				'in_admin' => ( ( $this->page_id == 'Administration' && $this->namespace == 'Special' ) || $this->namespace == 'Admin' ),
   741         'auth_rename' => ( $conds['rename'] )
   741 				'auth_rename' => ( $conds['rename'] )
   742       ));
   742 			));
   743     
   743 		
   744     // Get the "article" button text (depends on namespace)
   744 		// Get the "article" button text (depends on namespace)
   745     switch ( $this->namespace )
   745 		switch ( $this->namespace )
   746     {
   746 		{
   747       case "Article":
   747 			case "Article":
   748       default:
   748 			default:
   749         $ns = $lang->get('onpage_lbl_page_article');
   749 				$ns = $lang->get('onpage_lbl_page_article');
   750         break;
   750 				break;
   751       case "Admin":
   751 			case "Admin":
   752         $ns = $lang->get('onpage_lbl_page_admin');
   752 				$ns = $lang->get('onpage_lbl_page_admin');
   753         break;
   753 				break;
   754       case "System":
   754 			case "System":
   755         $ns = $lang->get('onpage_lbl_page_system');
   755 				$ns = $lang->get('onpage_lbl_page_system');
   756         break;
   756 				break;
   757       case "File":
   757 			case "File":
   758         $ns = $lang->get('onpage_lbl_page_file');
   758 				$ns = $lang->get('onpage_lbl_page_file');
   759         break;
   759 				break;
   760       case "Help":
   760 			case "Help":
   761         $ns = $lang->get('onpage_lbl_page_help');
   761 				$ns = $lang->get('onpage_lbl_page_help');
   762         break;
   762 				break;
   763       case "User":
   763 			case "User":
   764         $ns = $lang->get('onpage_lbl_page_user');
   764 				$ns = $lang->get('onpage_lbl_page_user');
   765         break;
   765 				break;
   766       case "Special":
   766 			case "Special":
   767         $ns = $lang->get('onpage_lbl_page_special');
   767 				$ns = $lang->get('onpage_lbl_page_special');
   768         break;
   768 				break;
   769       case "Template":
   769 			case "Template":
   770         $ns = $lang->get('onpage_lbl_page_template');
   770 				$ns = $lang->get('onpage_lbl_page_template');
   771         break;
   771 				break;
   772       case "Project":
   772 			case "Project":
   773         $ns = $lang->get('onpage_lbl_page_project');
   773 				$ns = $lang->get('onpage_lbl_page_project');
   774         break;
   774 				break;
   775       case "Category":
   775 			case "Category":
   776         $ns = $lang->get('onpage_lbl_page_category');
   776 				$ns = $lang->get('onpage_lbl_page_category');
   777         break;
   777 				break;
   778       case "API":
   778 			case "API":
   779         $ns = $lang->get('onpage_lbl_page_external');
   779 				$ns = $lang->get('onpage_lbl_page_external');
   780         break;
   780 				break;
   781     }
   781 		}
   782     $this->namespace_string = $ns;
   782 		$this->namespace_string = $ns;
   783     unset($ns);
   783 		unset($ns);
   784     // compatibility
   784 		// compatibility
   785     $local_namespace =& $this->namespace;
   785 		$local_namespace =& $this->namespace;
   786     $local_page_id =& $this->page_id;
   786 		$local_page_id =& $this->page_id;
   787     $code = $plugins->setHook('page_type_string_set');
   787 		$code = $plugins->setHook('page_type_string_set');
   788     foreach ( $code as $cmd )
   788 		foreach ( $code as $cmd )
   789     {
   789 		{
   790       eval($cmd);
   790 			eval($cmd);
   791     }
   791 		}
   792     $ns =& $this->namespace_string;
   792 		$ns =& $this->namespace_string;
   793     
   793 		
   794     //
   794 		//
   795     // PAGE TOOLBAR (on-page controls/actions)
   795 		// PAGE TOOLBAR (on-page controls/actions)
   796     //
   796 		//
   797     
   797 		
   798     $local_page = $paths->get_pathskey($this->page_id, $this->namespace);
   798 		$local_page = $paths->get_pathskey($this->page_id, $this->namespace);
   799     $local_cdata = $this->page->ns->get_cdata();
   799 		$local_cdata = $this->page->ns->get_cdata();
   800     
   800 		
   801     // Initialize the toolbar
   801 		// Initialize the toolbar
   802     $tb = '';
   802 		$tb = '';
   803     $this->toolbar_menu = '';
   803 		$this->toolbar_menu = '';
   804     
   804 		
   805     // Create "xx page" button
   805 		// Create "xx page" button
   806     
   806 		
   807     $btn_selected = ( isset($this->elements['toolbar_button_selected'])) ? $this->elements['toolbar_button_selected'] : $this->elements['toolbar_button'];
   807 		$btn_selected = ( isset($this->elements['toolbar_button_selected'])) ? $this->elements['toolbar_button_selected'] : $this->elements['toolbar_button'];
   808     $parser = $this->makeParserText($btn_selected);
   808 		$parser = $this->makeParserText($btn_selected);
   809     
   809 		
   810     if ( $conds['article'] )
   810 		if ( $conds['article'] )
   811     {
   811 		{
   812       $parser->assign_vars(array(
   812 			$parser->assign_vars(array(
   813           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="' . $lang->get('onpage_tip_article') . '" accesskey="a"',
   813 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="' . $lang->get('onpage_tip_article') . '" accesskey="a"',
   814           'PARENTFLAGS' => 'id="mdgToolbar_article"',
   814 					'PARENTFLAGS' => 'id="mdgToolbar_article"',
   815           'HREF' => makeUrl($local_page, null, true),
   815 					'HREF' => makeUrl($local_page, null, true),
   816           'TEXT' => $this->namespace_string
   816 					'TEXT' => $this->namespace_string
   817         ));
   817 				));
   818       
   818 			
   819       $tb .= $parser->run();
   819 			$tb .= $parser->run();
   820     }
   820 		}
   821     
   821 		
   822     $button = $this->makeParserText($this->elements['toolbar_button']);
   822 		$button = $this->makeParserText($this->elements['toolbar_button']);
   823     
   823 		
   824     // Page toolbar
   824 		// Page toolbar
   825     // Comments button
   825 		// Comments button
   826     if ( $conds['comments'] )
   826 		if ( $conds['comments'] )
   827     {
   827 		{
   828       $cdata = $this->page->ns->get_cdata();
   828 			$cdata = $this->page->ns->get_cdata();
   829       if ( isset($cdata['comments_approved']) )
   829 			if ( isset($cdata['comments_approved']) )
   830       {
   830 			{
   831         $approval_counts = array(
   831 				$approval_counts = array(
   832             COMMENT_APPROVED => $cdata['comments_approved'],
   832 						COMMENT_APPROVED => $cdata['comments_approved'],
   833             COMMENT_UNAPPROVED => $cdata['comments_unapproved'],
   833 						COMMENT_UNAPPROVED => $cdata['comments_unapproved'],
   834             COMMENT_SPAM => $cdata['comments_spam']
   834 						COMMENT_SPAM => $cdata['comments_spam']
   835           );
   835 					);
   836         $num_comments = $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments')
   836 				$num_comments = $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments')
   837                           ? array_sum($approval_counts)
   837 													? array_sum($approval_counts)
   838                           : $approval_counts[COMMENT_APPROVED];
   838 													: $approval_counts[COMMENT_APPROVED];
   839       }
   839 			}
   840       else
   840 			else
   841       {
   841 			{
   842         $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$this->page_id.'\' AND namespace=\''.$this->namespace.'\';');
   842 				$e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$this->page_id.'\' AND namespace=\''.$this->namespace.'\';');
   843         if ( !$e )
   843 				if ( !$e )
   844         {
   844 				{
   845           $db->_die();
   845 					$db->_die();
   846         }
   846 				}
   847         $num_comments = $db->numrows();
   847 				$num_comments = $db->numrows();
   848         $approval_counts = array(COMMENT_UNAPPROVED => 0, COMMENT_APPROVED => 0, COMMENT_SPAM => 0);
   848 				$approval_counts = array(COMMENT_UNAPPROVED => 0, COMMENT_APPROVED => 0, COMMENT_SPAM => 0);
   849         
   849 				
   850         while ( $r = $db->fetchrow() )
   850 				while ( $r = $db->fetchrow() )
   851         {  
   851 				{  
   852           $approval_counts[$r['approved']]++;
   852 					$approval_counts[$r['approved']]++;
   853         }
   853 				}
   854       }
   854 			}
   855       
   855 			
   856       $db->free_result();
   856 			$db->free_result();
   857       // $n = ( $session->check_acl_scope('mod_comments', $this->namespace) && $perms->get_permissions('mod_comments') ) ? (string)$num_comments : (string)$na;
   857 			// $n = ( $session->check_acl_scope('mod_comments', $this->namespace) && $perms->get_permissions('mod_comments') ) ? (string)$num_comments : (string)$na;
   858       if ( $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments') && ( $approval_counts[COMMENT_UNAPPROVED] + $approval_counts[COMMENT_SPAM] ) > 0 )
   858 			if ( $session->check_acl_scope('mod_comments', $this->namespace) && $this->page->perms->get_permissions('mod_comments') && ( $approval_counts[COMMENT_UNAPPROVED] + $approval_counts[COMMENT_SPAM] ) > 0 )
   859       {
   859 			{
   860         $subst = array(
   860 				$subst = array(
   861             'num_comments' => $num_comments,
   861 						'num_comments' => $num_comments,
   862             'num_app' => $approval_counts[COMMENT_APPROVED],
   862 						'num_app' => $approval_counts[COMMENT_APPROVED],
   863             'num_unapp' => $approval_counts[COMMENT_UNAPPROVED],
   863 						'num_unapp' => $approval_counts[COMMENT_UNAPPROVED],
   864             'num_spam' => $approval_counts[COMMENT_SPAM]
   864 						'num_spam' => $approval_counts[COMMENT_SPAM]
   865           );
   865 					);
   866         $btn_text = $lang->get('onpage_btn_discussion_unapp', $subst);
   866 				$btn_text = $lang->get('onpage_btn_discussion_unapp', $subst);
   867       }
   867 			}
   868       else
   868 			else
   869       {
   869 			{
   870         $subst = array(
   870 				$subst = array(
   871           'num_comments' => $num_comments
   871 					'num_comments' => $num_comments
   872         );
   872 				);
   873         $btn_text = $lang->get('onpage_btn_discussion', $subst);
   873 				$btn_text = $lang->get('onpage_btn_discussion', $subst);
   874       }
   874 			}
   875       
   875 			
   876       $button->assign_vars(array(
   876 			$button->assign_vars(array(
   877           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxComments()); return false; }" title="' . $lang->get('onpage_tip_comments') . '" accesskey="c"',
   877 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxComments()); return false; }" title="' . $lang->get('onpage_tip_comments') . '" accesskey="c"',
   878           'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
   878 					'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
   879           'HREF' => makeUrl($local_page, 'do=comments', true),
   879 					'HREF' => makeUrl($local_page, 'do=comments', true),
   880           'TEXT' => $btn_text,
   880 					'TEXT' => $btn_text,
   881         ));
   881 				));
   882       
   882 			
   883       $tb .= $button->run();
   883 			$tb .= $button->run();
   884     }
   884 		}
   885     // Edit button
   885 		// Edit button
   886     if( $conds['edit'] )
   886 		if( $conds['edit'] )
   887     {
   887 		{
   888       $button->assign_vars(array(
   888 			$button->assign_vars(array(
   889         'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_edit') . '" accesskey="e"',
   889 				'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_edit') . '" accesskey="e"',
   890         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
   890 				'PARENTFLAGS' => 'id="mdgToolbar_edit"',
   891         'HREF' => makeUrl($local_page, 'do=edit', true),
   891 				'HREF' => makeUrl($local_page, 'do=edit', true),
   892         'TEXT' => $lang->get('onpage_btn_edit')
   892 				'TEXT' => $lang->get('onpage_btn_edit')
   893         ));
   893 				));
   894       $tb .= $button->run();
   894 			$tb .= $button->run();
   895     // View source button
   895 		// View source button
   896     }
   896 		}
   897     else if ( $conds['viewsource'] ) 
   897 		else if ( $conds['viewsource'] ) 
   898     {
   898 		{
   899       $button->assign_vars(array(
   899 			$button->assign_vars(array(
   900         'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_viewsource') . '" accesskey="e"',
   900 				'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_viewsource') . '" accesskey="e"',
   901         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
   901 				'PARENTFLAGS' => 'id="mdgToolbar_edit"',
   902         'HREF' => makeUrl($local_page, 'do=viewsource', true),
   902 				'HREF' => makeUrl($local_page, 'do=viewsource', true),
   903         'TEXT' => $lang->get('onpage_btn_viewsource')
   903 				'TEXT' => $lang->get('onpage_btn_viewsource')
   904         ));
   904 				));
   905       $tb .= $button->run();
   905 			$tb .= $button->run();
   906     }
   906 		}
   907     // History button
   907 		// History button
   908     if ( $conds['history'] )
   908 		if ( $conds['history'] )
   909     {
   909 		{
   910       $button->assign_vars(array(
   910 			$button->assign_vars(array(
   911         'FLAGS'       => 'onclick="if ( !KILL_SWITCH ) { void(ajaxHistory()); return false; }" title="' . $lang->get('onpage_tip_history') . '" accesskey="h"',
   911 				'FLAGS'       => 'onclick="if ( !KILL_SWITCH ) { void(ajaxHistory()); return false; }" title="' . $lang->get('onpage_tip_history') . '" accesskey="h"',
   912         'PARENTFLAGS' => 'id="mdgToolbar_history"',
   912 				'PARENTFLAGS' => 'id="mdgToolbar_history"',
   913         'HREF'        => makeUrl($local_page, 'do=history', true),
   913 				'HREF'        => makeUrl($local_page, 'do=history', true),
   914         'TEXT'        => $lang->get('onpage_btn_history')
   914 				'TEXT'        => $lang->get('onpage_btn_history')
   915         ));
   915 				));
   916       $tb .= $button->run();
   916 			$tb .= $button->run();
   917     }
   917 		}
   918     
   918 		
   919     $menubtn = $this->makeParserText($this->elements['toolbar_menu_button']);
   919 		$menubtn = $this->makeParserText($this->elements['toolbar_menu_button']);
   920     
   920 		
   921     // Additional actions menu
   921 		// Additional actions menu
   922     // Rename button
   922 		// Rename button
   923     if ( $conds['rename'] )
   923 		if ( $conds['rename'] )
   924     {
   924 		{
   925       $menubtn->assign_vars(array(
   925 			$menubtn->assign_vars(array(
   926           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxRename()); return false; }" title="' . $lang->get('onpage_tip_rename') . '" accesskey="r"',
   926 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxRename()); return false; }" title="' . $lang->get('onpage_tip_rename') . '" accesskey="r"',
   927           'HREF'  => makeUrl($local_page, 'do=rename', true),
   927 					'HREF'  => makeUrl($local_page, 'do=rename', true),
   928           'TEXT'  => $lang->get('onpage_btn_rename'),
   928 					'TEXT'  => $lang->get('onpage_btn_rename'),
   929         ));
   929 				));
   930       $this->toolbar_menu .= $menubtn->run();
   930 			$this->toolbar_menu .= $menubtn->run();
   931     }
   931 		}
   932     
   932 		
   933     // Vote-to-delete button
   933 		// Vote-to-delete button
   934     if ( $conds['delvote'] )
   934 		if ( $conds['delvote'] )
   935     {
   935 		{
   936       $menubtn->assign_vars(array(
   936 			$menubtn->assign_vars(array(
   937           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDelVote()); return false; }" title="' . $lang->get('onpage_tip_delvote') . '" accesskey="d"',
   937 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDelVote()); return false; }" title="' . $lang->get('onpage_tip_delvote') . '" accesskey="d"',
   938           'HREF'  => makeUrl($local_page, 'do=delvote', true),
   938 					'HREF'  => makeUrl($local_page, 'do=delvote', true),
   939           'TEXT'  => $lang->get('onpage_btn_votedelete'),
   939 					'TEXT'  => $lang->get('onpage_btn_votedelete'),
   940         ));
   940 				));
   941       $this->toolbar_menu .= $menubtn->run();
   941 			$this->toolbar_menu .= $menubtn->run();
   942     }
   942 		}
   943     
   943 		
   944     // Clear-votes button
   944 		// Clear-votes button
   945     if ( $conds['resetvotes'] )
   945 		if ( $conds['resetvotes'] )
   946     {
   946 		{
   947       $menubtn->assign_vars(array(
   947 			$menubtn->assign_vars(array(
   948           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxResetDelVotes()); return false; }" title="' . $lang->get('onpage_tip_resetvotes') . '" accesskey="y"',
   948 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxResetDelVotes()); return false; }" title="' . $lang->get('onpage_tip_resetvotes') . '" accesskey="y"',
   949           'HREF'  => makeUrl($local_page, 'do=resetvotes', true),
   949 					'HREF'  => makeUrl($local_page, 'do=resetvotes', true),
   950           'TEXT'  => $lang->get('onpage_btn_votedelete_reset'),
   950 					'TEXT'  => $lang->get('onpage_btn_votedelete_reset'),
   951         ));
   951 				));
   952       $this->toolbar_menu .= $menubtn->run();
   952 			$this->toolbar_menu .= $menubtn->run();
   953     }
   953 		}
   954     
   954 		
   955     // Printable page button
   955 		// Printable page button
   956     if ( $conds['printable'] )
   956 		if ( $conds['printable'] )
   957     {
   957 		{
   958       $menubtn->assign_vars(array(
   958 			$menubtn->assign_vars(array(
   959           'FLAGS' => 'title="' . $lang->get('onpage_tip_printable') . '"',
   959 					'FLAGS' => 'title="' . $lang->get('onpage_tip_printable') . '"',
   960           'HREF'  => makeUrl($local_page, 'printable=yes', true),
   960 					'HREF'  => makeUrl($local_page, 'printable=yes', true),
   961           'TEXT'  => $lang->get('onpage_btn_printable'),
   961 					'TEXT'  => $lang->get('onpage_btn_printable'),
   962         ));
   962 				));
   963       $this->toolbar_menu .= $menubtn->run();
   963 			$this->toolbar_menu .= $menubtn->run();
   964     }
   964 		}
   965     
   965 		
   966     // Protect button
   966 		// Protect button
   967     if ( $conds['protect'] )
   967 		if ( $conds['protect'] )
   968     {
   968 		{
   969       switch($this->page->ns->cdata['protected'])
   969 			switch($this->page->ns->cdata['protected'])
   970       {
   970 			{
   971         case PROTECT_FULL: $protect_status = $lang->get('onpage_btn_protect_on'); break;
   971 				case PROTECT_FULL: $protect_status = $lang->get('onpage_btn_protect_on'); break;
   972         case PROTECT_SEMI: $protect_status = $lang->get('onpage_btn_protect_semi'); break;
   972 				case PROTECT_SEMI: $protect_status = $lang->get('onpage_btn_protect_semi'); break;
   973         case PROTECT_NONE: $protect_status = $lang->get('onpage_btn_protect_off'); break;
   973 				case PROTECT_NONE: $protect_status = $lang->get('onpage_btn_protect_off'); break;
   974       }
   974 			}
   975       
   975 			
   976       $label = $this->makeParserText($this->elements['toolbar_label']);
   976 			$label = $this->makeParserText($this->elements['toolbar_label']);
   977       $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect') . ' ' . "<b><span id=\"tb_ajax_protect_status\">$protect_status</span></b>"));
   977 			$label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect') . ' ' . "<b><span id=\"tb_ajax_protect_status\">$protect_status</span></b>"));
   978       $t0 = $label->run();
   978 			$t0 = $label->run();
   979       
   979 			
   980       $menubtn->assign_vars(array(
   980 			$menubtn->assign_vars(array(
   981           'FLAGS' => 'accesskey="p" onclick="ajaxProtect(' . $this->page->ns->cdata['protected'] . '); return false;" id="tb_ajax_protect_btn" title="' . $lang->get('onpage_tip_protect') . '"',
   981 					'FLAGS' => 'accesskey="p" onclick="ajaxProtect(' . $this->page->ns->cdata['protected'] . '); return false;" id="tb_ajax_protect_btn" title="' . $lang->get('onpage_tip_protect') . '"',
   982           'HREF' => makeUrl($local_page, 'do=protect', true),
   982 					'HREF' => makeUrl($local_page, 'do=protect', true),
   983           'TEXT' => $lang->get('onpage_btn_protect_change')
   983 					'TEXT' => $lang->get('onpage_btn_protect_change')
   984         ));
   984 				));
   985       $t1 = $menubtn->run();
   985 			$t1 = $menubtn->run();
   986       
   986 			
   987       $this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
   987 			$this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
   988           <tr>
   988 					<tr>
   989             <td>'.$t0.'</td>
   989 						<td>'.$t0.'</td>
   990             <td>'.$t1.'</td>
   990 						<td>'.$t1.'</td>
   991           </tr>
   991 					</tr>
   992         </table>';
   992 				</table>';
   993     }
   993 		}
   994     
   994 		
   995     // Wiki mode button
   995 		// Wiki mode button
   996     if ( $conds['setwikimode'] )
   996 		if ( $conds['setwikimode'] )
   997     {
   997 		{
   998       // label at start
   998 			// label at start
   999       $label = $this->makeParserText($this->elements['toolbar_label']);
   999 			$label = $this->makeParserText($this->elements['toolbar_label']);
  1000       $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_wikimode')));
  1000 			$label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_wikimode')));
  1001       $t0 = $label->run();
  1001 			$t0 = $label->run();
  1002       
  1002 			
  1003       // on button
  1003 			// on button
  1004       $ctmp = '';
  1004 			$ctmp = '';
  1005       if ( $local_cdata['wiki_mode'] == 1 )
  1005 			if ( $local_cdata['wiki_mode'] == 1 )
  1006       {
  1006 			{
  1007         $ctmp = ' style="text-decoration: underline;"';
  1007 				$ctmp = ' style="text-decoration: underline;"';
  1008       }
  1008 			}
  1009       $menubtn->assign_vars(array(
  1009 			$menubtn->assign_vars(array(
  1010           'FLAGS' => $ctmp,
  1010 					'FLAGS' => $ctmp,
  1011           'HREF' => makeUrl($local_page, 'do=setwikimode&level=1', true),
  1011 					'HREF' => makeUrl($local_page, 'do=setwikimode&level=1', true),
  1012           'TEXT' => $lang->get('onpage_btn_wikimode_on')
  1012 					'TEXT' => $lang->get('onpage_btn_wikimode_on')
  1013         ));
  1013 				));
  1014       $t1 = $menubtn->run();
  1014 			$t1 = $menubtn->run();
  1015       
  1015 			
  1016       // off button
  1016 			// off button
  1017       $ctmp = '';
  1017 			$ctmp = '';
  1018       if ( $local_cdata['wiki_mode'] == 0 )
  1018 			if ( $local_cdata['wiki_mode'] == 0 )
  1019       {
  1019 			{
  1020         $ctmp=' style="text-decoration: underline;"';
  1020 				$ctmp=' style="text-decoration: underline;"';
  1021       }
  1021 			}
  1022       $menubtn->assign_vars(array(
  1022 			$menubtn->assign_vars(array(
  1023           'FLAGS' => $ctmp,
  1023 					'FLAGS' => $ctmp,
  1024           'HREF' => makeUrl($local_page, 'do=setwikimode&level=0', true),
  1024 					'HREF' => makeUrl($local_page, 'do=setwikimode&level=0', true),
  1025           'TEXT' => $lang->get('onpage_btn_wikimode_off')
  1025 					'TEXT' => $lang->get('onpage_btn_wikimode_off')
  1026         ));
  1026 				));
  1027       $t2 = $menubtn->run();
  1027 			$t2 = $menubtn->run();
  1028       
  1028 			
  1029       // global button
  1029 			// global button
  1030       $ctmp = ''; 
  1030 			$ctmp = ''; 
  1031       if ( $local_cdata['wiki_mode'] == 2 )
  1031 			if ( $local_cdata['wiki_mode'] == 2 )
  1032       {
  1032 			{
  1033         $ctmp=' style="text-decoration: underline;"';
  1033 				$ctmp=' style="text-decoration: underline;"';
  1034       }
  1034 			}
  1035       $menubtn->assign_vars(array(
  1035 			$menubtn->assign_vars(array(
  1036           'FLAGS' => $ctmp,
  1036 					'FLAGS' => $ctmp,
  1037           'HREF' => makeUrl($local_page, 'do=setwikimode&level=2', true),
  1037 					'HREF' => makeUrl($local_page, 'do=setwikimode&level=2', true),
  1038           'TEXT' => $lang->get('onpage_btn_wikimode_global')
  1038 					'TEXT' => $lang->get('onpage_btn_wikimode_global')
  1039         ));
  1039 				));
  1040       $t3 = $menubtn->run();
  1040 			$t3 = $menubtn->run();
  1041       
  1041 			
  1042       // Tack it onto the list of buttons that are already there...
  1042 			// Tack it onto the list of buttons that are already there...
  1043       $this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
  1043 			$this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
  1044           <tr>
  1044 					<tr>
  1045             <td>'.$t0.'</td>
  1045 						<td>'.$t0.'</td>
  1046             <td>'.$t1.'</td>
  1046 						<td>'.$t1.'</td>
  1047             <td>'.$t2.'</td>
  1047 						<td>'.$t2.'</td>
  1048             <td>'.$t3.'</td>
  1048 						<td>'.$t3.'</td>
  1049           </tr>
  1049 					</tr>
  1050         </table>';
  1050 				</table>';
  1051     }
  1051 		}
  1052     
  1052 		
  1053     // Clear logs button
  1053 		// Clear logs button
  1054     if ( $conds['clearlogs'] )
  1054 		if ( $conds['clearlogs'] )
  1055     {
  1055 		{
  1056       $menubtn->assign_vars(array(
  1056 			$menubtn->assign_vars(array(
  1057           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxClearLogs()); return false; }" title="' . $lang->get('onpage_tip_flushlogs') . '" accesskey="l"',
  1057 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxClearLogs()); return false; }" title="' . $lang->get('onpage_tip_flushlogs') . '" accesskey="l"',
  1058           'HREF'  => makeUrl($local_page, 'do=flushlogs', true),
  1058 					'HREF'  => makeUrl($local_page, 'do=flushlogs', true),
  1059           'TEXT'  => $lang->get('onpage_btn_clearlogs'),
  1059 					'TEXT'  => $lang->get('onpage_btn_clearlogs'),
  1060         ));
  1060 				));
  1061       $this->toolbar_menu .= $menubtn->run();
  1061 			$this->toolbar_menu .= $menubtn->run();
  1062     }
  1062 		}
  1063     
  1063 		
  1064     // Delete page button
  1064 		// Delete page button
  1065     if ( $conds['delete'] )
  1065 		if ( $conds['delete'] )
  1066     {
  1066 		{
  1067       $s = $lang->get('onpage_btn_deletepage');
  1067 			$s = $lang->get('onpage_btn_deletepage');
  1068       if ( $this->page->ns->cdata['delvotes'] == 1 )
  1068 			if ( $this->page->ns->cdata['delvotes'] == 1 )
  1069       {
  1069 			{
  1070         $subst = array(
  1070 				$subst = array(
  1071           'num_votes' => $this->page->ns->cdata['delvotes'],
  1071 					'num_votes' => $this->page->ns->cdata['delvotes'],
  1072           'plural' => ''
  1072 					'plural' => ''
  1073           );
  1073 					);
  1074         $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  1074 				$s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  1075       }
  1075 			}
  1076       else if ( $this->page->ns->cdata['delvotes'] > 1 )
  1076 			else if ( $this->page->ns->cdata['delvotes'] > 1 )
  1077       {
  1077 			{
  1078         $subst = array(
  1078 				$subst = array(
  1079           'num_votes' => $this->page->ns->cdata['delvotes'],
  1079 					'num_votes' => $this->page->ns->cdata['delvotes'],
  1080           'plural' => $lang->get('meta_plural')
  1080 					'plural' => $lang->get('meta_plural')
  1081           );
  1081 					);
  1082         $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  1082 				$s .= $lang->get('onpage_btn_deletepage_votes', $subst);
  1083       }
  1083 			}
  1084       
  1084 			
  1085       $menubtn->assign_vars(array(
  1085 			$menubtn->assign_vars(array(
  1086           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDeletePage()); return false; }" title="' . $lang->get('onpage_tip_deletepage') . '" accesskey="k"',
  1086 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDeletePage()); return false; }" title="' . $lang->get('onpage_tip_deletepage') . '" accesskey="k"',
  1087           'HREF'  => makeUrl($local_page, 'do=deletepage', true),
  1087 					'HREF'  => makeUrl($local_page, 'do=deletepage', true),
  1088           'TEXT'  => $s,
  1088 					'TEXT'  => $s,
  1089         ));
  1089 				));
  1090       $this->toolbar_menu .= $menubtn->run();
  1090 			$this->toolbar_menu .= $menubtn->run();
  1091       
  1091 			
  1092     }
  1092 		}
  1093     
  1093 		
  1094     // Password-protect button
  1094 		// Password-protect button
  1095     if ( $conds['password'] )
  1095 		if ( $conds['password'] )
  1096     {
  1096 		{
  1097       // label at start
  1097 			// label at start
  1098       $label = $this->makeParserText($this->elements['toolbar_label']);
  1098 			$label = $this->makeParserText($this->elements['toolbar_label']);
  1099       $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_password')));
  1099 			$label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_password')));
  1100       $t0 = $label->run();
  1100 			$t0 = $label->run();
  1101       
  1101 			
  1102       $menubtn->assign_vars(array(
  1102 			$menubtn->assign_vars(array(
  1103           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxSetPassword()); return false; }" title="' . $lang->get('onpage_tip_password') . '"',
  1103 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxSetPassword()); return false; }" title="' . $lang->get('onpage_tip_password') . '"',
  1104           'HREF'  => '#',
  1104 					'HREF'  => '#',
  1105           'TEXT'  => $lang->get('onpage_btn_password_set'),
  1105 					'TEXT'  => $lang->get('onpage_btn_password_set'),
  1106         ));
  1106 				));
  1107       $t = $menubtn->run();
  1107 			$t = $menubtn->run();
  1108       
  1108 			
  1109       $this->toolbar_menu .= '<table border="0" cellspacing="0" cellpadding="0"><tr><td>'.$t0.'</td><td><input type="password" id="mdgPassSetField" size="10" /></td><td>'.$t.'</td></tr></table>';
  1109 			$this->toolbar_menu .= '<table border="0" cellspacing="0" cellpadding="0"><tr><td>'.$t0.'</td><td><input type="password" id="mdgPassSetField" size="10" /></td><td>'.$t.'</td></tr></table>';
  1110     }
  1110 		}
  1111     
  1111 		
  1112     // Manage ACLs button
  1112 		// Manage ACLs button
  1113     if ( $conds['acledit'] )
  1113 		if ( $conds['acledit'] )
  1114     {
  1114 		{
  1115       $menubtn->assign_vars(array(
  1115 			$menubtn->assign_vars(array(
  1116           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { var s = ajaxOpenACLManager(); console.debug(s); return false; }" title="' . $lang->get('onpage_tip_aclmanager') . '" accesskey="m"',
  1116 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { var s = ajaxOpenACLManager(); console.debug(s); return false; }" title="' . $lang->get('onpage_tip_aclmanager') . '" accesskey="m"',
  1117           'HREF'  => makeUrl($local_page, 'do=aclmanager', true),
  1117 					'HREF'  => makeUrl($local_page, 'do=aclmanager', true),
  1118           'TEXT'  => $lang->get('onpage_btn_acl'),
  1118 					'TEXT'  => $lang->get('onpage_btn_acl'),
  1119         ));
  1119 				));
  1120       $this->toolbar_menu .= $menubtn->run();
  1120 			$this->toolbar_menu .= $menubtn->run();
  1121     }
  1121 		}
  1122     
  1122 		
  1123     // Administer page button
  1123 		// Administer page button
  1124     if ( $conds['adminpage'] )
  1124 		if ( $conds['adminpage'] )
  1125     {
  1125 		{
  1126       $menubtn->assign_vars(array(
  1126 			$menubtn->assign_vars(array(
  1127           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxAdminPage()); return false; }" title="' . $lang->get('onpage_tip_adminoptions') . '" accesskey="g"',
  1127 					'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxAdminPage()); return false; }" title="' . $lang->get('onpage_tip_adminoptions') . '" accesskey="g"',
  1128           'HREF'  => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
  1128 					'HREF'  => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
  1129           'TEXT'  => $lang->get('onpage_btn_admin'),
  1129 					'TEXT'  => $lang->get('onpage_btn_admin'),
  1130         ));
  1130 				));
  1131       $this->toolbar_menu .= $menubtn->run();
  1131 			$this->toolbar_menu .= $menubtn->run();
  1132     }
  1132 		}
  1133     
  1133 		
  1134     if ( strlen($this->toolbar_menu) > 0 )
  1134 		if ( strlen($this->toolbar_menu) > 0 )
  1135     {
  1135 		{
  1136       $button->assign_vars(array(
  1136 			$button->assign_vars(array(
  1137         'FLAGS'       => 'id="mdgToolbar_moreoptions" onclick="if ( !KILL_SWITCH ) { return false; }" title="' . $lang->get('onpage_tip_moreoptions') . '"',
  1137 				'FLAGS'       => 'id="mdgToolbar_moreoptions" onclick="if ( !KILL_SWITCH ) { return false; }" title="' . $lang->get('onpage_tip_moreoptions') . '"',
  1138         'PARENTFLAGS' => '',
  1138 				'PARENTFLAGS' => '',
  1139         'HREF'        => makeUrl($local_page, 'do=moreoptions', true),
  1139 				'HREF'        => makeUrl($local_page, 'do=moreoptions', true),
  1140         'TEXT'        => $lang->get('onpage_btn_moreoptions')
  1140 				'TEXT'        => $lang->get('onpage_btn_moreoptions')
  1141         ));
  1141 				));
  1142       $tb .= $button->run();
  1142 			$tb .= $button->run();
  1143     }
  1143 		}
  1144     
  1144 		
  1145     // Generate the code for the Log in, Log out, Change theme, Administration, and Edit Sidebar buttons
  1145 		// Generate the code for the Log in, Log out, Change theme, Administration, and Edit Sidebar buttons
  1146     // Once again, the new template parsing system can be used here
  1146 		// Once again, the new template parsing system can be used here
  1147     
  1147 		
  1148     $parser = $this->makeParserText($this->elements['sidebar_button']);
  1148 		$parser = $this->makeParserText($this->elements['sidebar_button']);
  1149     
  1149 		
  1150     $parser->assign_vars(Array(
  1150 		$parser->assign_vars(Array(
  1151         'HREF'=>makeUrlNS('Special', "Logout/{$session->csrf_token}/{$local_page}"),
  1151 				'HREF'=>makeUrlNS('Special', "Logout/{$session->csrf_token}/{$local_page}"),
  1152         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { mb_logout(); return false; }"',
  1152 				'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { mb_logout(); return false; }"',
  1153         'TEXT'=>$lang->get('sidebar_btn_logout'),
  1153 				'TEXT'=>$lang->get('sidebar_btn_logout'),
  1154       ));
  1154 			));
  1155     
  1155 		
  1156     $logout_link = $parser->run();
  1156 		$logout_link = $parser->run();
  1157     
  1157 		
  1158     $parser->assign_vars(Array(
  1158 		$parser->assign_vars(Array(
  1159         'HREF'=>makeUrlNS('Special', 'Login/' . $local_page),
  1159 				'HREF'=>makeUrlNS('Special', 'Login/' . $local_page),
  1160         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxStartLogin(); return false; }"' . ( $local_page_id == 'Login' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1160 				'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxStartLogin(); return false; }"' . ( $local_page_id == 'Login' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1161         'TEXT'=>$lang->get('sidebar_btn_login'),
  1161 				'TEXT'=>$lang->get('sidebar_btn_login'),
  1162       ));
  1162 			));
  1163     
  1163 		
  1164     $login_link = $parser->run();
  1164 		$login_link = $parser->run();
  1165     
  1165 		
  1166     $parser->assign_vars(Array(
  1166 		$parser->assign_vars(Array(
  1167         'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$local_page),
  1167 				'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$local_page),
  1168         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxChangeStyle(); return false; }"' . ( $local_page_id == 'ChangeStyle' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1168 				'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxChangeStyle(); return false; }"' . ( $local_page_id == 'ChangeStyle' && $local_namespace == 'Special' ? ' class="currentpage"' : '' ),
  1169         'TEXT'=>$lang->get('sidebar_btn_changestyle'),
  1169 				'TEXT'=>$lang->get('sidebar_btn_changestyle'),
  1170       ));
  1170 			));
  1171     
  1171 		
  1172     $theme_link = $parser->run();
  1172 		$theme_link = $parser->run();
  1173     
  1173 		
  1174     // Run hooks
  1174 		// Run hooks
  1175     $code = $plugins->setHook('tpl_compile_toolbar');
  1175 		$code = $plugins->setHook('tpl_compile_toolbar');
  1176     foreach ( $code as $cmd )
  1176 		foreach ( $code as $cmd )
  1177     {
  1177 		{
  1178       eval($cmd);
  1178 			eval($cmd);
  1179     }
  1179 		}
  1180     
  1180 		
  1181     //
  1181 		//
  1182     // ASSIGN VARIABLES
  1182 		// ASSIGN VARIABLES
  1183     //
  1183 		//
  1184     
  1184 		
  1185     $this->assign_vars(array(
  1185 		$this->assign_vars(array(
  1186         'PAGE_NAME' => htmlspecialchars($this->page->ns->cdata['name']),
  1186 				'PAGE_NAME' => htmlspecialchars($this->page->ns->cdata['name']),
  1187         'PAGE_URLNAME' => $paths->nslist[$this->namespace] . sanitize_page_id($this->page_id),
  1187 				'PAGE_URLNAME' => $paths->nslist[$this->namespace] . sanitize_page_id($this->page_id),
  1188         'TOOLBAR' => $tb,
  1188 				'TOOLBAR' => $tb,
  1189         'TOOLBAR_EXTRAS' => $this->toolbar_menu,
  1189 				'TOOLBAR_EXTRAS' => $this->toolbar_menu,
  1190         'STYLE_LINK' => makeUrlNS('Special', 'CSS', null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
  1190 				'STYLE_LINK' => makeUrlNS('Special', 'CSS', null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
  1191         'LOGIN_LINK' => $login_link,
  1191 				'LOGIN_LINK' => $login_link,
  1192         'LOGOUT_LINK' => $logout_link,
  1192 				'LOGOUT_LINK' => $logout_link,
  1193         'THEME_LINK' => $theme_link
  1193 				'THEME_LINK' => $theme_link
  1194       ), true);
  1194 			), true);
  1195     $this->page_initted = true;
  1195 		$this->page_initted = true;
  1196   }
  1196 	}
  1197   
  1197 	
  1198   /**
  1198 	/**
  1199    * Generates and assigns the Javascript system variables
  1199  	* Generates and assigns the Javascript system variables
  1200    */
  1200  	*/
  1201   
  1201 	
  1202   function generate_js_header()
  1202 	function generate_js_header()
  1203   {
  1203 	{
  1204     global $db, $session, $paths, $template, $plugins; // Common objects
  1204 		global $db, $session, $paths, $template, $plugins; // Common objects
  1205     global $lang;
  1205 		global $lang;
  1206     
  1206 		
  1207     $SID = ($session->sid_super) ? $session->sid_super : '';
  1207 		$SID = ($session->sid_super) ? $session->sid_super : '';
  1208     
  1208 		
  1209     $local_page = $paths->get_pathskey($this->page_id, $this->namespace);
  1209 		$local_page = $paths->get_pathskey($this->page_id, $this->namespace);
  1210     $local_fullpage = $paths->get_pathskey($this->page_id, $this->namespace) . substr($paths->fullpage, strlen($paths->page));
  1210 		$local_fullpage = $paths->get_pathskey($this->page_id, $this->namespace) . substr($paths->fullpage, strlen($paths->page));
  1211     
  1211 		
  1212     $urlname_clean = str_replace('\'', '\\\'', str_replace('\\', '\\\\', dirtify_page_id($local_fullpage)));
  1212 		$urlname_clean = str_replace('\'', '\\\'', str_replace('\\', '\\\\', dirtify_page_id($local_fullpage)));
  1213     $urlname_clean = strtr( $urlname_clean, array( '<' => '&lt;', '>' => '&gt;' ) );
  1213 		$urlname_clean = strtr( $urlname_clean, array( '<' => '&lt;', '>' => '&gt;' ) );
  1214     
  1214 		
  1215     $urlname_jssafe = sanitize_page_id($local_fullpage);
  1215 		$urlname_jssafe = sanitize_page_id($local_fullpage);
  1216     $physical_urlname_jssafe = sanitize_page_id($paths->fullpage);
  1216 		$physical_urlname_jssafe = sanitize_page_id($paths->fullpage);
  1217     
  1217 		
  1218     $protected = is_object($this->page) ? $this->page->ns->cdata['really_protected'] : false;
  1218 		$protected = is_object($this->page) ? $this->page->ns->cdata['really_protected'] : false;
  1219     
  1219 		
  1220     // Generate the dynamic javascript vars
  1220 		// Generate the dynamic javascript vars
  1221     // Sorry. I know. This block is a mess.
  1221 		// Sorry. I know. This block is a mess.
  1222     $js_dynamic = '    <script type="text/javascript">// <![CDATA[
  1222 		$js_dynamic = '    <script type="text/javascript">// <![CDATA[
  1223       // This section defines some basic and very important variables that are used later in the static Javascript library.
  1223 			// This section defines some basic and very important variables that are used later in the static Javascript library.
  1224       // SKIN DEVELOPERS: The template variable for this code block is {JS_DYNAMIC_VARS}. This MUST be inserted BEFORE the tag that links to the main Javascript lib.
  1224 			// SKIN DEVELOPERS: The template variable for this code block is {JS_DYNAMIC_VARS}. This MUST be inserted BEFORE the tag that links to the main Javascript lib.
  1225       var title = \''. $urlname_jssafe .'\';
  1225 			var title = \''. $urlname_jssafe .'\';
  1226       var physical_title = \'' . $physical_urlname_jssafe . '\';
  1226 			var physical_title = \'' . $physical_urlname_jssafe . '\';
  1227       var on_main_page = ' . ( $local_page == get_main_page() ? 'true' : 'false' ) . ';
  1227 			var on_main_page = ' . ( $local_page == get_main_page() ? 'true' : 'false' ) . ';
  1228       var main_page_members = \'' . addslashes(get_main_page(true)) . '\';
  1228 			var main_page_members = \'' . addslashes(get_main_page(true)) . '\';
  1229       var page_exists = '. ( ( is_object($this->page) ? $this->page->ns->exists() : true ) ? 'true' : 'false' ) .';
  1229 			var page_exists = '. ( ( is_object($this->page) ? $this->page->ns->exists() : true ) ? 'true' : 'false' ) .';
  1230       var scriptPath = \'' . addslashes(scriptPath) . '\';
  1230 			var scriptPath = \'' . addslashes(scriptPath) . '\';
  1231       var contentPath = \'' . addslashes(contentPath) . '\';
  1231 			var contentPath = \'' . addslashes(contentPath) . '\';
  1232       var cdnPath = \'' . addslashes(cdnPath) . '\';
  1232 			var cdnPath = \'' . addslashes(cdnPath) . '\';
  1233       var ENANO_SID = \'' . $SID . '\';
  1233 			var ENANO_SID = \'' . $SID . '\';
  1234       var user_level = ' . $session->user_level . ';
  1234 			var user_level = ' . $session->user_level . ';
  1235       var auth_level = ' . $session->auth_level . ';
  1235 			var auth_level = ' . $session->auth_level . ';
  1236       var USER_LEVEL_GUEST = ' . USER_LEVEL_GUEST . ';
  1236 			var USER_LEVEL_GUEST = ' . USER_LEVEL_GUEST . ';
  1237       var USER_LEVEL_MEMBER = ' . USER_LEVEL_MEMBER . ';
  1237 			var USER_LEVEL_MEMBER = ' . USER_LEVEL_MEMBER . ';
  1238       var USER_LEVEL_CHPREF = ' . USER_LEVEL_CHPREF . ';
  1238 			var USER_LEVEL_CHPREF = ' . USER_LEVEL_CHPREF . ';
  1239       var USER_LEVEL_MOD = ' . USER_LEVEL_MOD . ';
  1239 			var USER_LEVEL_MOD = ' . USER_LEVEL_MOD . ';
  1240       var USER_LEVEL_ADMIN = ' . USER_LEVEL_ADMIN . ';
  1240 			var USER_LEVEL_ADMIN = ' . USER_LEVEL_ADMIN . ';
  1241       var disable_redirect = ' . ( isset($_GET['redirect']) && $_GET['redirect'] == 'no' ? 'true' : 'false' ) . ';
  1241 			var disable_redirect = ' . ( isset($_GET['redirect']) && $_GET['redirect'] == 'no' ? 'true' : 'false' ) . ';
  1242       var pref_disable_js_fx = ' . ( @$session->user_extra['disable_js_fx'] == 1 ? 'true' : 'false' ) . ';
  1242 			var pref_disable_js_fx = ' . ( @$session->user_extra['disable_js_fx'] == 1 ? 'true' : 'false' ) . ';
  1243       var csrf_token = "' . $session->csrf_token . '";
  1243 			var csrf_token = "' . $session->csrf_token . '";
  1244       var prot = ' . ( ($protected) ? 'true' : 'false' ) .';
  1244 			var prot = ' . ( ($protected) ? 'true' : 'false' ) .';
  1245       var ENANO_SPECIAL_CREATEPAGE = \''. makeUrl($paths->nslist['Special'].'CreatePage') .'\';
  1245 			var ENANO_SPECIAL_CREATEPAGE = \''. makeUrl($paths->nslist['Special'].'CreatePage') .'\';
  1246       var ENANO_CREATEPAGE_PARAMS = \'_do=&pagename='. $this->page_id .'&namespace=' . $this->namespace . '\';
  1246 			var ENANO_CREATEPAGE_PARAMS = \'_do=&pagename='. $this->page_id .'&namespace=' . $this->namespace . '\';
  1247       var ENANO_SPECIAL_CHANGESTYLE = \''. makeUrlNS('Special', 'ChangeStyle') .'\';
  1247 			var ENANO_SPECIAL_CHANGESTYLE = \''. makeUrlNS('Special', 'ChangeStyle') .'\';
  1248       var namespace_list = [];
  1248 			var namespace_list = [];
  1249       var msg_loading_component = \'' . addslashes($lang->get('ajax_msg_loading_component')) . '\';
  1249 			var msg_loading_component = \'' . addslashes($lang->get('ajax_msg_loading_component')) . '\';
  1250       var AES_BITS = '.AES_BITS.';
  1250 			var AES_BITS = '.AES_BITS.';
  1251       var AES_BLOCKSIZE = '.AES_BLOCKSIZE.';
  1251 			var AES_BLOCKSIZE = '.AES_BLOCKSIZE.';
  1252       var pagepass = \''. ( ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '' ) .'\';
  1252 			var pagepass = \''. ( ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '' ) .'\';
  1253       var ENANO_LANG_ID = ' . $lang->lang_id . ';
  1253 			var ENANO_LANG_ID = ' . $lang->lang_id . ';
  1254       var ENANO_PAGE_TYPE = "' . addslashes($this->namespace_string) . '";
  1254 			var ENANO_PAGE_TYPE = "' . addslashes($this->namespace_string) . '";
  1255       var enano_version = "' . enano_version() . '";';
  1255 			var enano_version = "' . enano_version() . '";';
  1256     
  1256 		
  1257     foreach ( $paths->nslist as $k => $c )
  1257 		foreach ( $paths->nslist as $k => $c )
  1258     {
  1258 		{
  1259       $js_dynamic .= "namespace_list['{$k}'] = '" . addslashes($c) . "';";
  1259 			$js_dynamic .= "namespace_list['{$k}'] = '" . addslashes($c) . "';";
  1260     }
  1260 		}
  1261     $js_dynamic .= "\n    //]]>\n    </script>";
  1261 		$js_dynamic .= "\n    //]]>\n    </script>";
  1262     
  1262 		
  1263     $this->assign_vars(array(
  1263 		$this->assign_vars(array(
  1264         'JS_DYNAMIC_VARS' => $js_dynamic,
  1264 				'JS_DYNAMIC_VARS' => $js_dynamic,
  1265         'REPORT_URI' => makeUrl($local_fullpage, 'do=sql_report', true)
  1265 				'REPORT_URI' => makeUrl($local_fullpage, 'do=sql_report', true)
  1266       ), true);
  1266 			), true);
  1267   }
  1267 	}
  1268   
  1268 	
  1269   /**
  1269 	/**
  1270    * Fetches, parses, and assigns the sidebar.
  1270  	* Fetches, parses, and assigns the sidebar.
  1271    */
  1271  	*/
  1272   
  1272 	
  1273   function assign_sidebar()
  1273 	function assign_sidebar()
  1274   {
  1274 	{
  1275     //
  1275 		//
  1276     // COMPILE THE SIDEBAR
  1276 		// COMPILE THE SIDEBAR
  1277     //
  1277 		//
  1278     
  1278 		
  1279     // This is done after the big assign_vars() so that sidebar code has access to the newly assigned variables
  1279 		// This is done after the big assign_vars() so that sidebar code has access to the newly assigned variables
  1280     
  1280 		
  1281     list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar();
  1281 		list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar();
  1282     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != $min) ? true : false;
  1282 		$this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != $min) ? true : false;
  1283     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false;
  1283 		$this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false;
  1284     $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
  1284 		$this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
  1285   }
  1285 	}
  1286   
  1286 	
  1287   /**
  1287 	/**
  1288    * Initializes all variables related to on-page content. This includes sidebars and what have you.
  1288  	* Initializes all variables related to on-page content. This includes sidebars and what have you.
  1289    * @param object Optional PageProcessor object to use for passing metadata and permissions on. If omitted, uses information from $paths and $session.
  1289  	* @param object Optional PageProcessor object to use for passing metadata and permissions on. If omitted, uses information from $paths and $session.
  1290    * @param bool If true, re-inits even if already initted with this page_id and namespace
  1290  	* @param bool If true, re-inits even if already initted with this page_id and namespace
  1291    */
  1291  	*/
  1292   
  1292 	
  1293   function init_vars($page = false, $force_init = false)
  1293 	function init_vars($page = false, $force_init = false)
  1294   {
  1294 	{
  1295     global $db, $session, $paths, $template, $plugins; // Common objects
  1295 		global $db, $session, $paths, $template, $plugins; // Common objects
  1296     global $lang;
  1296 		global $lang;
  1297     
  1297 		
  1298     $need_shared_init = ( !$this->theme_initted || !$this->page_initted );
  1298 		$need_shared_init = ( !$this->theme_initted || !$this->page_initted );
  1299     
  1299 		
  1300     if ( $need_shared_init )
  1300 		if ( $need_shared_init )
  1301     {
  1301 		{
  1302       if ( !$this->theme || !$this->style )
  1302 			if ( !$this->theme || !$this->style )
  1303       {
  1303 			{
  1304         $this->load_theme();
  1304 				$this->load_theme();
  1305       }
  1305 			}
  1306       $code = $plugins->setHook('compile_template', true);
  1306 			$code = $plugins->setHook('compile_template', true);
  1307       foreach ( $code as $cmd )
  1307 			foreach ( $code as $cmd )
  1308       {
  1308 			{
  1309         eval($cmd);
  1309 				eval($cmd);
  1310       }
  1310 			}
  1311     }
  1311 		}
  1312     
  1312 		
  1313     if ( !$this->theme_loaded )
  1313 		if ( !$this->theme_loaded )
  1314       $this->load_theme();
  1314 			$this->load_theme();
  1315     
  1315 		
  1316     require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg");
  1316 		require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg");
  1317     
  1317 		
  1318     if ( !$this->page_id || !$this->namespace )
  1318 		if ( !$this->page_id || !$this->namespace )
  1319     {
  1319 		{
  1320       $this->page_id = $paths->page_id;
  1320 			$this->page_id = $paths->page_id;
  1321       $this->namespace = $paths->namespace;
  1321 			$this->namespace = $paths->namespace;
  1322     }
  1322 		}
  1323     
  1323 		
  1324     profiler_log('template: prepped for var set (loaded theme, ran compile_template hook)');
  1324 		profiler_log('template: prepped for var set (loaded theme, ran compile_template hook)');
  1325     
  1325 		
  1326     $this->init_global_vars();
  1326 		$this->init_global_vars();
  1327     profiler_log('template: global vars set');
  1327 		profiler_log('template: global vars set');
  1328     
  1328 		
  1329     if ( !$this->theme_initted )
  1329 		if ( !$this->theme_initted )
  1330       $this->init_theme_vars();
  1330 			$this->init_theme_vars();
  1331     
  1331 		
  1332     profiler_log('template: theme vars set');
  1332 		profiler_log('template: theme vars set');
  1333     
  1333 		
  1334     if ( !$this->page_initted && !empty($this->namespace) )
  1334 		if ( !$this->page_initted && !empty($this->namespace) )
  1335     {
  1335 		{
  1336       profiler_log('template: page vars set');
  1336 			profiler_log('template: page vars set');
  1337       $this->init_page_vars();
  1337 			$this->init_page_vars();
  1338     }
  1338 		}
  1339     else
  1339 		else
  1340     {
  1340 		{
  1341       profiler_message('template: skipped setting page vars');
  1341 			profiler_message('template: skipped setting page vars');
  1342     }
  1342 		}
  1343     
  1343 		
  1344     // Perform shared init (combine javascript, etc.)
  1344 		// Perform shared init (combine javascript, etc.)
  1345     if ( $need_shared_init )
  1345 		if ( $need_shared_init )
  1346     {
  1346 		{
  1347       $this->generate_js_header();
  1347 			$this->generate_js_header();
  1348       $this->assign_sidebar();
  1348 			$this->assign_sidebar();
  1349       profiler_log('template: assigned sidebar and JS');
  1349 			profiler_log('template: assigned sidebar and JS');
  1350     }
  1350 		}
  1351     
  1351 		
  1352     // and finally one string value that needs to be symlinked...
  1352 		// and finally one string value that needs to be symlinked...
  1353     if ( !isset($this->tpl_strings['ADDITIONAL_HEADERS']) )
  1353 		if ( !isset($this->tpl_strings['ADDITIONAL_HEADERS']) )
  1354     {
  1354 		{
  1355       $this->tpl_strings['ADDITIONAL_HEADERS'] =& $this->additional_headers;
  1355 			$this->tpl_strings['ADDITIONAL_HEADERS'] =& $this->additional_headers;
  1356     }
  1356 		}
  1357     
  1357 		
  1358     // done!
  1358 		// done!
  1359     $code = $plugins->setHook('template_var_init_end');
  1359 		$code = $plugins->setHook('template_var_init_end');
  1360     foreach ( $code as $cmd )
  1360 		foreach ( $code as $cmd )
  1361     {
  1361 		{
  1362       eval($cmd);
  1362 			eval($cmd);
  1363     }
  1363 		}
  1364   }
  1364 	}
  1365   
  1365 	
  1366   function header($simple = false) 
  1366 	function header($simple = false) 
  1367   {
  1367 	{
  1368     global $db, $session, $paths, $template, $plugins; // Common objects
  1368 		global $db, $session, $paths, $template, $plugins; // Common objects
  1369     global $lang;
  1369 		global $lang;
  1370     
  1370 		
  1371     define('ENANO_HEADERS_SENT', true);
  1371 		define('ENANO_HEADERS_SENT', true);
  1372     
  1372 		
  1373     echo $this->getHeader($simple);
  1373 		echo $this->getHeader($simple);
  1374   }
  1374 	}
  1375   
  1375 	
  1376   function footer($simple = false)
  1376 	function footer($simple = false)
  1377   {
  1377 	{
  1378     echo $this->getFooter($simple);
  1378 		echo $this->getFooter($simple);
  1379   }
  1379 	}
  1380   
  1380 	
  1381   function getHeader($simple = false)
  1381 	function getHeader($simple = false)
  1382   {
  1382 	{
  1383     global $db, $session, $paths, $template, $plugins; // Common objects
  1383 		global $db, $session, $paths, $template, $plugins; // Common objects
  1384     global $lang;
  1384 		global $lang;
  1385     
  1385 		
  1386     if ( !$this->theme_loaded )
  1386 		if ( !$this->theme_loaded )
  1387     {
  1387 		{
  1388       $this->load_theme($session->theme, $session->style);
  1388 			$this->load_theme($session->theme, $session->style);
  1389     }
  1389 		}
  1390     
  1390 		
  1391     if ( !$this->page_initted || !$this->theme_initted )
  1391 		if ( !$this->page_initted || !$this->theme_initted )
  1392       $this->init_vars();
  1392 			$this->init_vars();
  1393     
  1393 		
  1394     // I feel awful doing this.
  1394 		// I feel awful doing this.
  1395     if ( preg_match('/^W3C_Validator/', @$_SERVER['HTTP_USER_AGENT']) )
  1395 		if ( preg_match('/^W3C_Validator/', @$_SERVER['HTTP_USER_AGENT']) )
  1396     {
  1396 		{
  1397       header('Content-type: application/xhtml+xml');
  1397 			header('Content-type: application/xhtml+xml');
  1398     }
  1398 		}
  1399     
  1399 		
  1400     $header = '';
  1400 		$header = '';
  1401     
  1401 		
  1402     if ( !$this->no_headers )
  1402 		if ( !$this->no_headers )
  1403     {
  1403 		{
  1404       $header = ( $simple ) ?
  1404 			$header = ( $simple ) ?
  1405         $this->process_template('simple-header.tpl') :
  1405 				$this->process_template('simple-header.tpl') :
  1406         $this->process_template('header.tpl');
  1406 				$this->process_template('header.tpl');
  1407     }
  1407 		}
  1408     if ( !$simple && $session->user_logged_in && $session->unread_pms > 0 )
  1408 		if ( !$simple && $session->user_logged_in && $session->unread_pms > 0 )
  1409     {
  1409 		{
  1410       $header .= $this->notify_unread_pms();
  1410 			$header .= $this->notify_unread_pms();
  1411     }
  1411 		}
  1412     if ( !$simple && $session->sw_timed_out )
  1412 		if ( !$simple && $session->sw_timed_out )
  1413     {
  1413 		{
  1414       $login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
  1414 			$login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
  1415       $header .= '<div class="usermessage">';
  1415 			$header .= '<div class="usermessage">';
  1416       $header .= $lang->get('user_msg_elev_timed_out', array( 'login_link' => $login_link ));
  1416 			$header .= $lang->get('user_msg_elev_timed_out', array( 'login_link' => $login_link ));
  1417       $header .= '</div>';
  1417 			$header .= '</div>';
  1418     }
  1418 		}
  1419     if ( $this->site_disabled && $session->user_level >= USER_LEVEL_ADMIN && ( $paths->page != $paths->nslist['Special'] . 'Administration' ) )
  1419 		if ( $this->site_disabled && $session->user_level >= USER_LEVEL_ADMIN && ( $paths->page != $paths->nslist['Special'] . 'Administration' ) )
  1420     {
  1420 		{
  1421       $admin_link = makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'GeneralConfig', true);
  1421 			$admin_link = makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'GeneralConfig', true);
  1422       $header .= '<div class="usermessage"><b>' . $lang->get('page_sitedisabled_admin_msg_title') . '</b><br />
  1422 			$header .= '<div class="usermessage"><b>' . $lang->get('page_sitedisabled_admin_msg_title') . '</b><br />
  1423             ' . $lang->get('page_sitedisabled_admin_msg_body', array('admin_link' => $admin_link)) . '
  1423 						' . $lang->get('page_sitedisabled_admin_msg_body', array('admin_link' => $admin_link)) . '
  1424             </div>';
  1424 						</div>';
  1425     }
  1425 		}
  1426     
  1426 		
  1427     return $header;
  1427 		return $header;
  1428   }
  1428 	}
  1429   
  1429 	
  1430   function getFooter($simple = false)
  1430 	function getFooter($simple = false)
  1431   {
  1431 	{
  1432     global $db, $session, $paths, $template, $plugins; // Common objects
  1432 		global $db, $session, $paths, $template, $plugins; // Common objects
  1433     global $lang;
  1433 		global $lang;
  1434     if ( !$this->no_headers )
  1434 		if ( !$this->no_headers )
  1435     {
  1435 		{
  1436       
  1436 			
  1437       global $_starttime;
  1437 			global $_starttime;
  1438       if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
  1438 			if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
  1439       {
  1439 			{
  1440         echo '<h3>' . $lang->get('page_heading_sql_list') . '</h3><pre style="margin-left: 1em">';
  1440 				echo '<h3>' . $lang->get('page_heading_sql_list') . '</h3><pre style="margin-left: 1em">';
  1441         echo htmlspecialchars($db->sql_backtrace());
  1441 				echo htmlspecialchars($db->sql_backtrace());
  1442         echo '</pre>';
  1442 				echo '</pre>';
  1443       }
  1443 			}
  1444       
  1444 			
  1445       $t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
  1445 			$t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
  1446       
  1446 			
  1447       $f = microtime_float();
  1447 			$f = microtime_float();
  1448       $f = $f - $_starttime;
  1448 			$f = $f - $_starttime;
  1449       $f = round($f, 2);
  1449 			$f = round($f, 2);
  1450       
  1450 			
  1451       $t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
  1451 			$t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
  1452       $t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
  1452 			$t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
  1453       $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => $db->num_queries)) . '</a>';
  1453 			$q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => $db->num_queries)) . '</a>';
  1454       $dbg = $t_loc;
  1454 			$dbg = $t_loc;
  1455       $dbg_long = $t_loc_long;
  1455 			$dbg_long = $t_loc_long;
  1456       if ( $session->user_level >= USER_LEVEL_ADMIN || defined('ENANO_DEBUG') )
  1456 			if ( $session->user_level >= USER_LEVEL_ADMIN || defined('ENANO_DEBUG') )
  1457       {
  1457 			{
  1458         $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  1458 				$dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  1459         $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  1459 				$dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  1460       }
  1460 			}
  1461       
  1461 			
  1462       $t = str_replace('[[Stats]]', $dbg, $t);
  1462 			$t = str_replace('[[Stats]]', $dbg, $t);
  1463       $t = str_replace('[[StatsLong]]', $dbg_long, $t);
  1463 			$t = str_replace('[[StatsLong]]', $dbg_long, $t);
  1464       $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
  1464 			$t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
  1465       $t = str_replace('[[GenTime]]', (string)$f, $t);
  1465 			$t = str_replace('[[GenTime]]', (string)$f, $t);
  1466       $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  1466 			$t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  1467       $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  1467 			$t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  1468       $t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  1468 			$t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  1469       $t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  1469 			$t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  1470       
  1470 			
  1471       if ( defined('ENANO_PROFILE') )
  1471 			if ( defined('ENANO_PROFILE') )
  1472       {
  1472 			{
  1473         $t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
  1473 				$t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
  1474         // ob_end_clean();
  1474 				// ob_end_clean();
  1475         // return profiler_make_html();
  1475 				// return profiler_make_html();
  1476       }
  1476 			}
  1477       
  1477 			
  1478       return $t;
  1478 			return $t;
  1479     }
  1479 		}
  1480     else
  1480 		else
  1481     {
  1481 		{
  1482       return '';
  1482 			return '';
  1483     }
  1483 		}
  1484   }
  1484 	}
  1485   
  1485 	
  1486   /**
  1486 	/**
  1487    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  1487  	* Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  1488    * @param $vars array
  1488  	* @param $vars array
  1489    * @param $from_internal bool Internal switch, just omit (@todo document)
  1489  	* @param $from_internal bool Internal switch, just omit (@todo document)
  1490    */
  1490  	*/
  1491   
  1491 	
  1492   function assign_vars($vars, $from_internal = false)
  1492 	function assign_vars($vars, $from_internal = false)
  1493   {
  1493 	{
  1494     foreach ( $vars as $key => $value )
  1494 		foreach ( $vars as $key => $value )
  1495     {
  1495 		{
  1496       $replace = true;
  1496 			$replace = true;
  1497       if ( isset($this->vars_assign_history['strings'][$key]) )
  1497 			if ( isset($this->vars_assign_history['strings'][$key]) )
  1498       {
  1498 			{
  1499         if ( $this->vars_assign_history['strings'][$key] == 'api' )
  1499 				if ( $this->vars_assign_history['strings'][$key] == 'api' )
  1500         {
  1500 				{
  1501           $replace = false;
  1501 					$replace = false;
  1502         }
  1502 				}
  1503       }
  1503 			}
  1504       if ( $replace )
  1504 			if ( $replace )
  1505       {
  1505 			{
  1506         $this->tpl_strings[$key] = $value;
  1506 				$this->tpl_strings[$key] = $value;
  1507         $this->vars_assign_history['strings'][$key] = ( $from_internal ) ? 'internal' : 'api';
  1507 				$this->vars_assign_history['strings'][$key] = ( $from_internal ) ? 'internal' : 'api';
  1508       }
  1508 			}
  1509     }
  1509 		}
  1510   }
  1510 	}
  1511   
  1511 	
  1512   /**
  1512 	/**
  1513    * Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  1513  	* Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  1514    * @param $vars array
  1514  	* @param $vars array
  1515    * @param $from_internal bool Internal switch, just omit (@todo document)
  1515  	* @param $from_internal bool Internal switch, just omit (@todo document)
  1516    */
  1516  	*/
  1517   
  1517 	
  1518   function assign_bool($vars, $from_internal = false)
  1518 	function assign_bool($vars, $from_internal = false)
  1519   {
  1519 	{
  1520     foreach ( $vars as $key => $value )
  1520 		foreach ( $vars as $key => $value )
  1521     {
  1521 		{
  1522       $replace = true;
  1522 			$replace = true;
  1523       if ( isset($this->vars_assign_history['bool'][$key]) )
  1523 			if ( isset($this->vars_assign_history['bool'][$key]) )
  1524       {
  1524 			{
  1525         if ( $this->vars_assign_history['bool'][$key] == 'api' )
  1525 				if ( $this->vars_assign_history['bool'][$key] == 'api' )
  1526         {
  1526 				{
  1527           $replace = false;
  1527 					$replace = false;
  1528         }
  1528 				}
  1529       }
  1529 			}
  1530       if ( $replace )
  1530 			if ( $replace )
  1531       {
  1531 			{
  1532         $this->tpl_bool[$key] = $value;
  1532 				$this->tpl_bool[$key] = $value;
  1533         $this->vars_assign_history['bool'][$key] = ( $from_internal ) ? 'internal' : 'api';
  1533 				$this->vars_assign_history['bool'][$key] = ( $from_internal ) ? 'internal' : 'api';
  1534       }
  1534 			}
  1535     }
  1535 		}
  1536   }
  1536 	}
  1537   
  1537 	
  1538   #
  1538 	#
  1539   # COMPILER
  1539 	# COMPILER
  1540   #
  1540 	#
  1541   
  1541 	
  1542   /**
  1542 	/**
  1543    * Compiles and executes a template based on the current variables and booleans. Loads
  1543  	* Compiles and executes a template based on the current variables and booleans. Loads
  1544    * the theme and initializes variables if needed. This mostly just calls child functions.
  1544  	* the theme and initializes variables if needed. This mostly just calls child functions.
  1545    * @param string File to process
  1545  	* @param string File to process
  1546    * @return string
  1546  	* @return string
  1547    */
  1547  	*/
  1548   
  1548 	
  1549   function process_template($file)
  1549 	function process_template($file)
  1550   {
  1550 	{
  1551     global $db, $session, $paths, $template, $plugins; // Common objects
  1551 		global $db, $session, $paths, $template, $plugins; // Common objects
  1552     
  1552 		
  1553     if ( !$this->theme_initted || !$this->page_initted )
  1553 		if ( !$this->theme_initted || !$this->page_initted )
  1554     {
  1554 		{
  1555       $this->init_vars();
  1555 			$this->init_vars();
  1556     }
  1556 		}
  1557     
  1557 		
  1558     $cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $file) . '.php';
  1558 		$cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $file) . '.php';
  1559     if ( file_exists($cache_file) )
  1559 		if ( file_exists($cache_file) )
  1560     {
  1560 		{
  1561       // this is about the time of the breaking change to cache file format
  1561 			// this is about the time of the breaking change to cache file format
  1562       if ( ($m = filemtime($cache_file)) > 1215038089 )
  1562 			if ( ($m = filemtime($cache_file)) > 1215038089 )
  1563       {
  1563 			{
  1564         $result = @include($cache_file);
  1564 				$result = @include($cache_file);
  1565         if ( isset($md5) )
  1565 				if ( isset($md5) )
  1566         {
  1566 				{
  1567           if ( $m >= filemtime(ENANO_ROOT . "/themes/{$this->theme}/$file") )
  1567 					if ( $m >= filemtime(ENANO_ROOT . "/themes/{$this->theme}/$file") )
  1568           {
  1568 					{
  1569             $result = $this->compile_template_text_post($result);
  1569 						$result = $this->compile_template_text_post($result);
  1570             return $result;
  1570 						return $result;
  1571           }
  1571 					}
  1572         }
  1572 				}
  1573       }
  1573 			}
  1574     }
  1574 		}
  1575     
  1575 		
  1576     $compiled = $this->compile_template($file);
  1576 		$compiled = $this->compile_template($file);
  1577     $result = eval($compiled);
  1577 		$result = eval($compiled);
  1578     
  1578 		
  1579     return $result;
  1579 		return $result;
  1580   }
  1580 	}
  1581   
  1581 	
  1582   /**
  1582 	/**
  1583    * Loads variables from the specified template file. Returns an associative array containing the variables.
  1583  	* Loads variables from the specified template file. Returns an associative array containing the variables.
  1584    * @param string Template file to process (elements.tpl)
  1584  	* @param string Template file to process (elements.tpl)
  1585    * @return array
  1585  	* @return array
  1586    */
  1586  	*/
  1587   
  1587 	
  1588   function extract_vars($file)
  1588 	function extract_vars($file)
  1589   {
  1589 	{
  1590     global $db, $session, $paths, $template, $plugins; // Common objects
  1590 		global $db, $session, $paths, $template, $plugins; // Common objects
  1591     
  1591 		
  1592     // Sometimes this function gets called before the theme is loaded
  1592 		// Sometimes this function gets called before the theme is loaded
  1593     // This is a bad coding practice so this function will always be picky.
  1593 		// This is a bad coding practice so this function will always be picky.
  1594     if ( !$this->theme )
  1594 		if ( !$this->theme )
  1595     {
  1595 		{
  1596       die('$template->extract_vars(): theme not yet loaded, so we can\'t open template files yet...this is a bug and should be reported.<br /><br />Backtrace, most recent call first:<pre>'.enano_debug_print_backtrace(true).'</pre>');
  1596 			die('$template->extract_vars(): theme not yet loaded, so we can\'t open template files yet...this is a bug and should be reported.<br /><br />Backtrace, most recent call first:<pre>'.enano_debug_print_backtrace(true).'</pre>');
  1597     }
  1597 		}
  1598     
  1598 		
  1599     // Full pathname of template file
  1599 		// Full pathname of template file
  1600     $tpl_file_fullpath = ( strstr($file, '/') ) ? $file : ENANO_ROOT . '/themes/' . $this->theme . '/' . $file;
  1600 		$tpl_file_fullpath = ( strstr($file, '/') ) ? $file : ENANO_ROOT . '/themes/' . $this->theme . '/' . $file;
  1601     
  1601 		
  1602     // Make sure the template even exists
  1602 		// Make sure the template even exists
  1603     if ( !is_file($tpl_file_fullpath) )
  1603 		if ( !is_file($tpl_file_fullpath) )
  1604     {
  1604 		{
  1605       die_semicritical('Cannot find template file',
  1605 			die_semicritical('Cannot find template file',
  1606                        '<p>The template parser was asked to load the file "' . htmlspecialchars($tpl_file_fullpath) . '", but that file couldn\'t be found in the directory for
  1606  											'<p>The template parser was asked to load the file "' . htmlspecialchars($tpl_file_fullpath) . '", but that file couldn\'t be found in the directory for
  1607                            the current theme.</p>
  1607  													the current theme.</p>
  1608                         <p>Additional debugging information:<br />
  1608 												<p>Additional debugging information:<br />
  1609                            <b>Theme currently in use: </b>' . $this->theme . '<br />
  1609  													<b>Theme currently in use: </b>' . $this->theme . '<br />
  1610                            <b>Requested file: </b>' . $file . '
  1610  													<b>Requested file: </b>' . $file . '
  1611                            </p>');
  1611  													</p>');
  1612     }
  1612 		}
  1613     // Retrieve file contents
  1613 		// Retrieve file contents
  1614     $text = file_get_contents($tpl_file_fullpath);
  1614 		$text = file_get_contents($tpl_file_fullpath);
  1615     if ( !$text )
  1615 		if ( !$text )
  1616     {
  1616 		{
  1617       return false;
  1617 			return false;
  1618     }
  1618 		}
  1619     
  1619 		
  1620     // Get variables, regular expressions FTW
  1620 		// Get variables, regular expressions FTW
  1621     preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
  1621 		preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
  1622     
  1622 		
  1623     // Initialize return values
  1623 		// Initialize return values
  1624     $tplvars = Array();
  1624 		$tplvars = Array();
  1625     
  1625 		
  1626     // Loop through each match, setting $tplvars[ $first_subpattern ] to $second_subpattern
  1626 		// Loop through each match, setting $tplvars[ $first_subpattern ] to $second_subpattern
  1627     for ( $i = 0; $i < sizeof($matches[1]); $i++ )
  1627 		for ( $i = 0; $i < sizeof($matches[1]); $i++ )
  1628     {
  1628 		{
  1629       $tplvars[ $matches[1][$i] ] = $matches[2][$i];
  1629 			$tplvars[ $matches[1][$i] ] = $matches[2][$i];
  1630     }
  1630 		}
  1631     
  1631 		
  1632     // All done!
  1632 		// All done!
  1633     return $tplvars;
  1633 		return $tplvars;
  1634   }
  1634 	}
  1635   
  1635 	
  1636   /**
  1636 	/**
  1637    * Compiles a block of template code.
  1637  	* Compiles a block of template code.
  1638    * @param string The text to process
  1638  	* @param string The text to process
  1639    * @return string
  1639  	* @return string
  1640    */
  1640  	*/
  1641   
  1641 	
  1642   function compile_tpl_code($text)
  1642 	function compile_tpl_code($text)
  1643   {
  1643 	{
  1644     return template_compiler_core($text);  
  1644 		return template_compiler_core($text);  
  1645   }
  1645 	}
  1646   
  1646 	
  1647   /**
  1647 	/**
  1648    * Compiles the contents of a given template file, possibly using a cached copy, and returns the compiled code.
  1648  	* Compiles the contents of a given template file, possibly using a cached copy, and returns the compiled code.
  1649    * @param string Filename of template (header.tpl)
  1649  	* @param string Filename of template (header.tpl)
  1650    * @return string
  1650  	* @return string
  1651    */
  1651  	*/
  1652   
  1652 	
  1653   function compile_template($filename)
  1653 	function compile_template($filename)
  1654   {
  1654 	{
  1655     global $db, $session, $paths, $template, $plugins; // Common objects
  1655 		global $db, $session, $paths, $template, $plugins; // Common objects
  1656     
  1656 		
  1657     // Full path to template file
  1657 		// Full path to template file
  1658     $tpl_file_fullpath = ENANO_ROOT . '/themes/' . $this->theme . '/' . $filename;
  1658 		$tpl_file_fullpath = ENANO_ROOT . '/themes/' . $this->theme . '/' . $filename;
  1659     
  1659 		
  1660     // Make sure the file exists
  1660 		// Make sure the file exists
  1661     if ( !is_file($tpl_file_fullpath) )
  1661 		if ( !is_file($tpl_file_fullpath) )
  1662     {
  1662 		{
  1663       die_semicritical('Cannot find template file',
  1663 			die_semicritical('Cannot find template file',
  1664                        '<p>The template parser was asked to load the file "' . htmlspecialchars($filename) . '", but that file couldn\'t be found in the directory for
  1664  											'<p>The template parser was asked to load the file "' . htmlspecialchars($filename) . '", but that file couldn\'t be found in the directory for
  1665                            the current theme.</p>
  1665  													the current theme.</p>
  1666                         <p>Additional debugging information:<br />
  1666 												<p>Additional debugging information:<br />
  1667                            <b>Theme currently in use: </b>' . $this->theme . '<br />
  1667  													<b>Theme currently in use: </b>' . $this->theme . '<br />
  1668                            <b>Requested file: </b>' . $file . '
  1668  													<b>Requested file: </b>' . $file . '
  1669                            </p>');
  1669  													</p>');
  1670     }
  1670 		}
  1671     
  1671 		
  1672     // We won't use the cached copy here.
  1672 		// We won't use the cached copy here.
  1673     $text = file_get_contents($tpl_file_fullpath);
  1673 		$text = file_get_contents($tpl_file_fullpath);
  1674     
  1674 		
  1675     // This will be used later when writing the cached file
  1675 		// This will be used later when writing the cached file
  1676     $md5 = md5($text);
  1676 		$md5 = md5($text);
  1677     
  1677 		
  1678     // Preprocessing and checks complete - compile the code
  1678 		// Preprocessing and checks complete - compile the code
  1679     $text = $this->compile_tpl_code($text);
  1679 		$text = $this->compile_tpl_code($text);
  1680     
  1680 		
  1681     // Generate cache filename
  1681 		// Generate cache filename
  1682     $cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $filename) . '.php';
  1682 		$cache_file = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $filename) . '.php';
  1683     
  1683 		
  1684     // Perhaps caching is enabled and the admin has changed the template?
  1684 		// Perhaps caching is enabled and the admin has changed the template?
  1685     if ( is_writable( ENANO_ROOT . '/cache/' ) && getConfig('cache_thumbs') == '1' )
  1685 		if ( is_writable( ENANO_ROOT . '/cache/' ) && getConfig('cache_thumbs') == '1' )
  1686     {
  1686 		{
  1687       $h = fopen($cache_file, 'w');
  1687 			$h = fopen($cache_file, 'w');
  1688       if ( !$h )
  1688 			if ( !$h )
  1689       {
  1689 			{
  1690         // Couldn't open the file - silently ignore and return
  1690 				// Couldn't open the file - silently ignore and return
  1691         return $text;
  1691 				return $text;
  1692       }
  1692 			}
  1693       
  1693 			
  1694       // Final contents of cache file
  1694 			// Final contents of cache file
  1695       $file_contents = <<<EOF
  1695 			$file_contents = <<<EOF
  1696 <?php
  1696 <?php
  1697 
  1697 
  1698 /*
  1698 /*
  1699  * NOTE: This file was automatically generated by Enano and is based on compiled code. Do not edit this file.
  1699  * NOTE: This file was automatically generated by Enano and is based on compiled code. Do not edit this file.
  1700  * If you edit this file, any changes you make will be lost the next time the associated source template file is edited.
  1700  * If you edit this file, any changes you make will be lost the next time the associated source template file is edited.
  1702 
  1702 
  1703 \$md5 = '$md5';
  1703 \$md5 = '$md5';
  1704 
  1704 
  1705 $text
  1705 $text
  1706 EOF;
  1706 EOF;
  1707       // This is really just a normal PHP file that sets a variable or two and exits.
  1707 			// This is really just a normal PHP file that sets a variable or two and exits.
  1708       // $tpl_text actually will contain the compiled code
  1708 			// $tpl_text actually will contain the compiled code
  1709       fwrite($h, $file_contents);
  1709 			fwrite($h, $file_contents);
  1710       fclose($h);
  1710 			fclose($h);
  1711     }
  1711 		}
  1712     
  1712 		
  1713     return $this->compile_template_text_post($text); //('<pre>'.htmlspecialchars($text).'</pre>');
  1713 		return $this->compile_template_text_post($text); //('<pre>'.htmlspecialchars($text).'</pre>');
  1714   }
  1714 	}
  1715   
  1715 	
  1716   
  1716 	
  1717   /**
  1717 	/**
  1718    * Compiles (parses) some template code with the current master set of variables and booleans.
  1718  	* Compiles (parses) some template code with the current master set of variables and booleans.
  1719    * @param string Text to process
  1719  	* @param string Text to process
  1720    * @return string
  1720  	* @return string
  1721    */
  1721  	*/
  1722   
  1722 	
  1723   function compile_template_text($text)
  1723 	function compile_template_text($text)
  1724   {
  1724 	{
  1725     // this might do something else in the future, possibly cache large templates
  1725 		// this might do something else in the future, possibly cache large templates
  1726     return $this->compile_template_text_post($this->compile_tpl_code($text));
  1726 		return $this->compile_template_text_post($this->compile_tpl_code($text));
  1727   }
  1727 	}
  1728   
  1728 	
  1729   /**
  1729 	/**
  1730    * For convenience - compiles AND parses some template code.
  1730  	* For convenience - compiles AND parses some template code.
  1731    * @param string Text to process
  1731  	* @param string Text to process
  1732    * @return string
  1732  	* @return string
  1733    */
  1733  	*/
  1734   
  1734 	
  1735   function parse($text)
  1735 	function parse($text)
  1736   {
  1736 	{
  1737     $text = $this->compile_template_text($text);
  1737 		$text = $this->compile_template_text($text);
  1738     $text = $this->compile_template_text_post($text);
  1738 		$text = $this->compile_template_text_post($text);
  1739     return eval($text);
  1739 		return eval($text);
  1740   }
  1740 	}
  1741   
  1741 	
  1742   /**
  1742 	/**
  1743    * Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
  1743  	* Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
  1744    * @param string Mostly-processed TPL code
  1744  	* @param string Mostly-processed TPL code
  1745    * @param bool Post-eval switch. If true, does not escape code.
  1745  	* @param bool Post-eval switch. If true, does not escape code.
  1746    * @return string
  1746  	* @return string
  1747    */
  1747  	*/
  1748   
  1748 	
  1749   function compile_template_text_post($text, $post_eval = false)
  1749 	function compile_template_text_post($text, $post_eval = false)
  1750   {
  1750 	{
  1751     global $db, $session, $paths, $template, $plugins; // Common objects
  1751 		global $db, $session, $paths, $template, $plugins; // Common objects
  1752     global $lang;
  1752 		global $lang;
  1753     
  1753 		
  1754     // Language strings
  1754 		// Language strings
  1755     preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
  1755 		preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
  1756     foreach ( $matches[1] as $i => $string_id )
  1756 		foreach ( $matches[1] as $i => $string_id )
  1757     {
  1757 		{
  1758       $string = $lang->get($string_id);
  1758 			$string = $lang->get($string_id);
  1759       if ( !$post_eval )
  1759 			if ( !$post_eval )
  1760       {
  1760 			{
  1761         $string = str_replace('\\', '\\\\', $string);
  1761 				$string = str_replace('\\', '\\\\', $string);
  1762         $string = str_replace('\'', '\\\'', $string);
  1762 				$string = str_replace('\'', '\\\'', $string);
  1763       }
  1763 			}
  1764       $text = str_replace_once($matches[0][$i], $string, $text);
  1764 			$text = str_replace_once($matches[0][$i], $string, $text);
  1765     }
  1765 		}
  1766     
  1766 		
  1767     // URLs
  1767 		// URLs
  1768     preg_match_all('/\{url:([A-z0-9]+):([^\}]+?)(?:;([^\s\}]+?))?(?:\|(escape))?\}/i', $text, $matches);
  1768 		preg_match_all('/\{url:([A-z0-9]+):([^\}]+?)(?:;([^\s\}]+?))?(?:\|(escape))?\}/i', $text, $matches);
  1769     foreach ( $matches[1] as $i => $string_id )
  1769 		foreach ( $matches[1] as $i => $string_id )
  1770     {
  1770 		{
  1771       $namespace =& $matches[1][$i];
  1771 			$namespace =& $matches[1][$i];
  1772       $page_id =& $matches[2][$i];
  1772 			$page_id =& $matches[2][$i];
  1773       $params =& $matches[3][$i];
  1773 			$params =& $matches[3][$i];
  1774       $escape =& $matches[4][$i];
  1774 			$escape =& $matches[4][$i];
  1775       
  1775 			
  1776       if ( !$params )
  1776 			if ( !$params )
  1777         $params = false;
  1777 				$params = false;
  1778       $escape = !empty($escape);
  1778 			$escape = !empty($escape);
  1779       
  1779 			
  1780       $result = makeUrlNS($namespace, sanitize_page_id($page_id), $params, $escape);
  1780 			$result = makeUrlNS($namespace, sanitize_page_id($page_id), $params, $escape);
  1781       
  1781 			
  1782       if ( !$post_eval )
  1782 			if ( !$post_eval )
  1783       {
  1783 			{
  1784         $result = str_replace('\\', '\\\\', $result);
  1784 				$result = str_replace('\\', '\\\\', $result);
  1785         $result = str_replace('\'', '\\\'', $result);
  1785 				$result = str_replace('\'', '\\\'', $result);
  1786       }
  1786 			}
  1787       
  1787 			
  1788       $text = str_replace_once($matches[0][$i], $result, $text);
  1788 			$text = str_replace_once($matches[0][$i], $result, $text);
  1789     }
  1789 		}
  1790     
  1790 		
  1791     $code = $plugins->setHook('compie_template_text_post');
  1791 		$code = $plugins->setHook('compie_template_text_post');
  1792     foreach ( $code as $cmd )
  1792 		foreach ( $code as $cmd )
  1793     {
  1793 		{
  1794       eval($cmd);
  1794 			eval($cmd);
  1795     }
  1795 		}
  1796     
  1796 		
  1797     return $text;
  1797 		return $text;
  1798   }
  1798 	}
  1799   
  1799 	
  1800   /**
  1800 	/**
  1801    * Returns the output of a theme hook
  1801  	* Returns the output of a theme hook
  1802    * @param string Hook name
  1802  	* @param string Hook name
  1803    * @return string
  1803  	* @return string
  1804    */
  1804  	*/
  1805   
  1805 	
  1806   function get_theme_hook($hook)
  1806 	function get_theme_hook($hook)
  1807   {
  1807 	{
  1808     global $db, $session, $paths, $template, $plugins; // Common objects
  1808 		global $db, $session, $paths, $template, $plugins; // Common objects
  1809     global $lang;
  1809 		global $lang;
  1810     
  1810 		
  1811     ob_start();
  1811 		ob_start();
  1812     $code = $plugins->setHook($hook);
  1812 		$code = $plugins->setHook($hook);
  1813     foreach ( $code as $cmd )
  1813 		foreach ( $code as $cmd )
  1814     {
  1814 		{
  1815       eval($cmd);
  1815 			eval($cmd);
  1816     }
  1816 		}
  1817     $out = ob_get_contents();
  1817 		$out = ob_get_contents();
  1818     ob_end_clean();
  1818 		ob_end_clean();
  1819     
  1819 		
  1820     return $out;
  1820 		return $out;
  1821   }
  1821 	}
  1822   
  1822 	
  1823   // n00bish comments removed from here. 2008-03-13 @ 12:02AM when I had nothing else to do.
  1823 	// n00bish comments removed from here. 2008-03-13 @ 12:02AM when I had nothing else to do.
  1824   
  1824 	
  1825   /**
  1825 	/**
  1826    * Takes a blob of HTML with the specially formatted template-oriented wikitext and formats it. Does not use eval().
  1826  	* Takes a blob of HTML with the specially formatted template-oriented wikitext and formats it. Does not use eval().
  1827    * This function butchers every coding standard in Enano and should eventually be rewritten. The fact is that the
  1827  	* This function butchers every coding standard in Enano and should eventually be rewritten. The fact is that the
  1828    * code _works_ and does a good job of checking for errors and cleanly complaining about them.
  1828  	* code _works_ and does a good job of checking for errors and cleanly complaining about them.
  1829    * @param string Text to process
  1829  	* @param string Text to process
  1830    * @param bool Ignored for backwards compatibility
  1830  	* @param bool Ignored for backwards compatibility
  1831    * @param string File to get variables for sidebar data from
  1831  	* @param string File to get variables for sidebar data from
  1832    * @return string
  1832  	* @return string
  1833    */
  1833  	*/
  1834   
  1834 	
  1835   function tplWikiFormat($message, $filter_links = false, $filename = 'elements.tpl')
  1835 	function tplWikiFormat($message, $filter_links = false, $filename = 'elements.tpl')
  1836   {
  1836 	{
  1837     global $db, $session, $paths, $template, $plugins; // Common objects
  1837 		global $db, $session, $paths, $template, $plugins; // Common objects
  1838     global $lang;
  1838 		global $lang;
  1839     
  1839 		
  1840     $START = microtime_float();
  1840 		$START = microtime_float();
  1841     
  1841 		
  1842     // localize the whole string first
  1842 		// localize the whole string first
  1843     preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $message, $matches);
  1843 		preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $message, $matches);
  1844     foreach ( $matches[1] as $i => $string_id )
  1844 		foreach ( $matches[1] as $i => $string_id )
  1845     {
  1845 		{
  1846       $string = $lang->get($string_id);
  1846 			$string = $lang->get($string_id);
  1847       $string = str_replace('\\', '\\\\', $string);
  1847 			$string = str_replace('\\', '\\\\', $string);
  1848       $string = str_replace('\'', '\\\'', $string);
  1848 			$string = str_replace('\'', '\\\'', $string);
  1849       $message = str_replace_once($matches[0][$i], $string, $message);
  1849 			$message = str_replace_once($matches[0][$i], $string, $message);
  1850     }
  1850 		}
  1851     
  1851 		
  1852     // first: the hackish optimization -
  1852 		// first: the hackish optimization -
  1853     // if it's only a bunch of letters, numbers and spaces, just skip this sh*t.
  1853 		// if it's only a bunch of letters, numbers and spaces, just skip this sh*t.
  1854     
  1854 		
  1855     if ( preg_match('/^[\w\s\.]*$/i', $message) )
  1855 		if ( preg_match('/^[\w\s\.]*$/i', $message) )
  1856     {
  1856 		{
  1857       return $message;
  1857 			return $message;
  1858     }
  1858 		}
  1859     
  1859 		
  1860     $filter_links = false;
  1860 		$filter_links = false;
  1861     $tplvars = $this->extract_vars($filename);
  1861 		$tplvars = $this->extract_vars($filename);
  1862     if($session->sid_super) $as = htmlspecialchars(urlSeparator).'auth='.$session->sid_super;
  1862 		if($session->sid_super) $as = htmlspecialchars(urlSeparator).'auth='.$session->sid_super;
  1863     else $as = '';
  1863 		else $as = '';
  1864     error_reporting(E_ALL);
  1864 		error_reporting(E_ALL);
  1865     $random_id = sha1(microtime().''); // A temp value
  1865 		$random_id = sha1(microtime().''); // A temp value
  1866     
  1866 		
  1867     /*
  1867 		/*
  1868      * PREPROCESSOR
  1868  		* PREPROCESSOR
  1869      */
  1869  		*/
  1870     
  1870 		
  1871     // Variables
  1871 		// Variables
  1872     
  1872 		
  1873     preg_match_all('#\$([A-Z_-]+)\$#', $message, $links);
  1873 		preg_match_all('#\$([A-Z_-]+)\$#', $message, $links);
  1874     $links = $links[1];
  1874 		$links = $links[1];
  1875     
  1875 		
  1876     for($i=0;$i<sizeof($links);$i++)
  1876 		for($i=0;$i<sizeof($links);$i++)
  1877     {
  1877 		{
  1878       if ( isset($this->tpl_strings[$links[$i]]) )
  1878 			if ( isset($this->tpl_strings[$links[$i]]) )
  1879       {
  1879 			{
  1880         $message = str_replace('$'.$links[$i].'$', $this->tpl_strings[$links[$i]], $message);
  1880 				$message = str_replace('$'.$links[$i].'$', $this->tpl_strings[$links[$i]], $message);
  1881       }
  1881 			}
  1882     }
  1882 		}
  1883     
  1883 		
  1884     // Conditionals
  1884 		// Conditionals
  1885     
  1885 		
  1886     $message = $this->twf_parse_conditionals($message);
  1886 		$message = $this->twf_parse_conditionals($message);
  1887     
  1887 		
  1888     /*
  1888 		/*
  1889      * HTML RENDERER
  1889  		* HTML RENDERER
  1890      */
  1890  		*/
  1891      
  1891  		
  1892     // Images
  1892 		// Images
  1893     $message = RenderMan::process_image_tags($message, $taglist);
  1893 		$message = RenderMan::process_image_tags($message, $taglist);
  1894     $message = RenderMan::process_imgtags_stage2($message, $taglist);
  1894 		$message = RenderMan::process_imgtags_stage2($message, $taglist);
  1895     
  1895 		
  1896     // Internal links
  1896 		// Internal links
  1897     $message = RenderMan::parse_internal_links($message, $tplvars['sidebar_button'], false, $this->page_id, $this->namespace);
  1897 		$message = RenderMan::parse_internal_links($message, $tplvars['sidebar_button'], false, $this->page_id, $this->namespace);
  1898     
  1898 		
  1899     // External links
  1899 		// External links
  1900     
  1900 		
  1901     $url_regexp = <<<EOF
  1901 		$url_regexp = <<<EOF
  1902 (
  1902 (
  1903   (?:https?|ftp|irc):\/\/                            # protocol
  1903 	(?:https?|ftp|irc):\/\/                            # protocol
  1904   (?:[^@\s\]"\':]+@)?                                # username (FTP only but whatever)
  1904 	(?:[^@\s\]"\':]+@)?                                # username (FTP only but whatever)
  1905   (?:(?:(?:[a-z0-9-]+\.)*)[a-z0-9\[\]:]+)            # hostname
  1905 	(?:(?:(?:[a-z0-9-]+\.)*)[a-z0-9\[\]:]+)            # hostname
  1906   (?::[0-9]+)?                                       # port number
  1906 	(?::[0-9]+)?                                       # port number
  1907   (?:\/[A-z0-9_%\|~`!\!@#\$\^&?=\*\(\):;\.,\/-]*)?   # path
  1907 	(?:\/[A-z0-9_%\|~`!\!@#\$\^&?=\*\(\):;\.,\/-]*)?   # path
  1908 )
  1908 )
  1909 EOF;
  1909 EOF;
  1910 
  1910 
  1911     $text_parser = $this->makeParserText($tplvars['sidebar_button']);
  1911 		$text_parser = $this->makeParserText($tplvars['sidebar_button']);
  1912 
  1912 
  1913     preg_match_all('/\[' . $url_regexp . '[ ]([^\]]+)\]/isx', $message, $ext_link);
  1913 		preg_match_all('/\[' . $url_regexp . '[ ]([^\]]+)\]/isx', $message, $ext_link);
  1914     
  1914 		
  1915     for ( $i = 0; $i < count($ext_link[0]); $i++ )
  1915 		for ( $i = 0; $i < count($ext_link[0]); $i++ )
  1916     {
  1916 		{
  1917       $text_parser->assign_vars(Array(  
  1917 			$text_parser->assign_vars(Array(  
  1918           'HREF'  => $ext_link[1][$i],
  1918 					'HREF'  => $ext_link[1][$i],
  1919           'FLAGS' => '',
  1919 					'FLAGS' => '',
  1920           'TEXT'  => $ext_link[2][$i]
  1920 					'TEXT'  => $ext_link[2][$i]
  1921         ));
  1921 				));
  1922       $message = str_replace($ext_link[0][$i], $text_parser->run(), $message);
  1922 			$message = str_replace($ext_link[0][$i], $text_parser->run(), $message);
  1923     }
  1923 		}
  1924     
  1924 		
  1925     preg_match_all('/\[' . $url_regexp . '\]/is', $message, $ext_link);
  1925 		preg_match_all('/\[' . $url_regexp . '\]/is', $message, $ext_link);
  1926     
  1926 		
  1927     for ( $i = 0; $i < count($ext_link[0]); $i++ )
  1927 		for ( $i = 0; $i < count($ext_link[0]); $i++ )
  1928     {
  1928 		{
  1929       $text_parser->assign_vars(Array(  
  1929 			$text_parser->assign_vars(Array(  
  1930           'HREF'  => $ext_link[1][$i],
  1930 					'HREF'  => $ext_link[1][$i],
  1931           'FLAGS' => '',
  1931 					'FLAGS' => '',
  1932           'TEXT'  => htmlspecialchars($ext_link[1][$i])
  1932 					'TEXT'  => htmlspecialchars($ext_link[1][$i])
  1933         ));
  1933 				));
  1934       $message = str_replace($ext_link[0][$i], $text_parser->run(), $message);
  1934 			$message = str_replace($ext_link[0][$i], $text_parser->run(), $message);
  1935     }
  1935 		}
  1936     
  1936 		
  1937     $TIME = microtime_float() - $START;
  1937 		$TIME = microtime_float() - $START;
  1938     
  1938 		
  1939     /*
  1939 		/*
  1940     if ( $TIME > 0.02 )
  1940 		if ( $TIME > 0.02 )
  1941     {
  1941 		{
  1942       echo 'template: tplWikiFormat took a while for this one. string dump:<pre>';
  1942 			echo 'template: tplWikiFormat took a while for this one. string dump:<pre>';
  1943       echo htmlspecialchars($message);
  1943 			echo htmlspecialchars($message);
  1944       echo '</pre>';
  1944 			echo '</pre>';
  1945     }
  1945 		}
  1946     */
  1946 		*/
  1947     
  1947 		
  1948     return $message;
  1948 		return $message;
  1949   }
  1949 	}
  1950   
  1950 	
  1951   /**
  1951 	/**
  1952    * Parses conditional {if} blocks in sidebars and other tplWikiFormatted things
  1952  	* Parses conditional {if} blocks in sidebars and other tplWikiFormatted things
  1953    * @param string A string potentially containing conditional blocks
  1953  	* @param string A string potentially containing conditional blocks
  1954    * @return string Processed string
  1954  	* @return string Processed string
  1955    */
  1955  	*/
  1956   
  1956 	
  1957   function twf_parse_conditionals($message)
  1957 	function twf_parse_conditionals($message)
  1958   {
  1958 	{
  1959     if ( !preg_match_all('/\{(!?)if ([a-z0-9_\(\)\|&! ]+)\}(.*?)(?:\{else\}(.*?))?\{\/if\}/is', $message, $matches) )
  1959 		if ( !preg_match_all('/\{(!?)if ([a-z0-9_\(\)\|&! ]+)\}(.*?)(?:\{else\}(.*?))?\{\/if\}/is', $message, $matches) )
  1960     {
  1960 		{
  1961       return $message;
  1961 			return $message;
  1962     }
  1962 		}
  1963     foreach ( $matches[0] as $match_id => $full_block )
  1963 		foreach ( $matches[0] as $match_id => $full_block )
  1964     {
  1964 		{
  1965       // 1 = "not" flag
  1965 			// 1 = "not" flag
  1966       // 2 = condition
  1966 			// 2 = condition
  1967       // 3 = if true
  1967 			// 3 = if true
  1968       // 4 = else
  1968 			// 4 = else
  1969       $condresult = $this->process_condition($matches[2][$match_id]);
  1969 			$condresult = $this->process_condition($matches[2][$match_id]);
  1970       if ( !empty($matches[1][$match_id]) )
  1970 			if ( !empty($matches[1][$match_id]) )
  1971       {
  1971 			{
  1972         if ( $condresult == 1 )
  1972 				if ( $condresult == 1 )
  1973           $condresult = 2;
  1973 					$condresult = 2;
  1974         else if ( $condresult == 2 )
  1974 				else if ( $condresult == 2 )
  1975           $condresult = 1;
  1975 					$condresult = 1;
  1976       }
  1976 			}
  1977       switch($condresult)
  1977 			switch($condresult)
  1978       {
  1978 			{
  1979         case 1:
  1979 				case 1:
  1980           // evaluated to false
  1980 					// evaluated to false
  1981           $message = str_replace_once($full_block, $matches[4][$match_id], $message);
  1981 					$message = str_replace_once($full_block, $matches[4][$match_id], $message);
  1982           break;
  1982 					break;
  1983         case 2:
  1983 				case 2:
  1984           // evaluated to true
  1984 					// evaluated to true
  1985           $message = str_replace_once($full_block, $matches[3][$match_id], $message);
  1985 					$message = str_replace_once($full_block, $matches[3][$match_id], $message);
  1986           break;
  1986 					break;
  1987         case 3:
  1987 				case 3:
  1988           $message = str_replace_once($full_block, "Syntax error: mismatched parentheses (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1988 					$message = str_replace_once($full_block, "Syntax error: mismatched parentheses (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1989           break;
  1989 					break;
  1990         case 4:
  1990 				case 4:
  1991           $message = str_replace_once($full_block, "Syntax error: illegal character (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1991 					$message = str_replace_once($full_block, "Syntax error: illegal character (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1992           break;
  1992 					break;
  1993         case 5:
  1993 				case 5:
  1994           $message = str_replace_once($full_block, "Syntax error: illegal sequence (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1994 					$message = str_replace_once($full_block, "Syntax error: illegal sequence (" . htmlspecialchars($matches[2][$match_id]) . ")<br />\n", $message);
  1995           break;
  1995 					break;
  1996       }
  1996 			}
  1997     }
  1997 		}
  1998     return $message;
  1998 		return $message;
  1999   }
  1999 	}
  2000   
  2000 	
  2001   /**
  2001 	/**
  2002    * Inner-loop parser for a conditional block. Verifies a string condition to make sure it's syntactically correct, then returns what it evaluates to.
  2002  	* Inner-loop parser for a conditional block. Verifies a string condition to make sure it's syntactically correct, then returns what it evaluates to.
  2003    * Return values:
  2003  	* Return values:
  2004    *   1 - string evaluates to true
  2004  	*   1 - string evaluates to true
  2005    *   2 - string evaluates to false
  2005  	*   2 - string evaluates to false
  2006    *   3 - Syntax error - mismatched parentheses
  2006  	*   3 - Syntax error - mismatched parentheses
  2007    *   4 - Syntax error - unknown token
  2007  	*   4 - Syntax error - unknown token
  2008    *   5 - Syntax error - invalid sequence
  2008  	*   5 - Syntax error - invalid sequence
  2009    * @param string
  2009  	* @param string
  2010    * @return int
  2010  	* @return int
  2011    * 
  2011  	* 
  2012    */
  2012  	*/
  2013   
  2013 	
  2014   function process_condition($condition)
  2014 	function process_condition($condition)
  2015   {
  2015 	{
  2016     // make sure parentheses are matched
  2016 		// make sure parentheses are matched
  2017     $parentheses = preg_replace('/[^\(\)]/', '', $condition);
  2017 		$parentheses = preg_replace('/[^\(\)]/', '', $condition);
  2018     if ( !empty($parentheses) )
  2018 		if ( !empty($parentheses) )
  2019     {
  2019 		{
  2020       $i = 0;
  2020 			$i = 0;
  2021       $parentheses = enano_str_split($parentheses);
  2021 			$parentheses = enano_str_split($parentheses);
  2022       foreach ( $parentheses as $chr )
  2022 			foreach ( $parentheses as $chr )
  2023       {
  2023 			{
  2024         $inc = ( $chr == '(' ) ? 1 : -1;
  2024 				$inc = ( $chr == '(' ) ? 1 : -1;
  2025         $i += $inc;
  2025 				$i += $inc;
  2026       }
  2026 			}
  2027       if ( $i != 0 )
  2027 			if ( $i != 0 )
  2028       {
  2028 			{
  2029         // mismatched parentheses
  2029 				// mismatched parentheses
  2030         return 3;
  2030 				return 3;
  2031       }
  2031 			}
  2032     }
  2032 		}
  2033     // sequencer check
  2033 		// sequencer check
  2034     // first, pad all sequences of characters with spaces
  2034 		// first, pad all sequences of characters with spaces
  2035     $seqcheck = preg_replace('/([a-z0-9_]+)/i', '\\1 ', $condition);
  2035 		$seqcheck = preg_replace('/([a-z0-9_]+)/i', '\\1 ', $condition);
  2036     $seqcheck = preg_replace('/([&|()!])/i', '\\1 ', $seqcheck);
  2036 		$seqcheck = preg_replace('/([&|()!])/i', '\\1 ', $seqcheck);
  2037     // now shrink all spaces to one space each
  2037 		// now shrink all spaces to one space each
  2038     $seqcheck = preg_replace('/[ ]+/', ' ', $seqcheck);
  2038 		$seqcheck = preg_replace('/[ ]+/', ' ', $seqcheck);
  2039     
  2039 		
  2040     // explode it. the allowed sequences are:
  2040 		// explode it. the allowed sequences are:
  2041     //   - TOKEN_NOT + TOKEN_VARIABLE
  2041 		//   - TOKEN_NOT + TOKEN_VARIABLE
  2042     //   - TOKEN_NOT + TOKEN_PARENTHLEFT
  2042 		//   - TOKEN_NOT + TOKEN_PARENTHLEFT
  2043     //   - TOKEN_BOOLOP + TOKEN_NOT
  2043 		//   - TOKEN_BOOLOP + TOKEN_NOT
  2044     //   - TOKEN_PARENTHRIGHT + TOKEN_NOT
  2044 		//   - TOKEN_PARENTHRIGHT + TOKEN_NOT
  2045     //   - TOKEN_VARIABLE + TOKEN_BOOLOP
  2045 		//   - TOKEN_VARIABLE + TOKEN_BOOLOP
  2046     //   - TOKEN_BOOLOP + TOKEN_PARENTHLEFT
  2046 		//   - TOKEN_BOOLOP + TOKEN_PARENTHLEFT
  2047     //   - TOKEN_PARENTHLEFT + TOKEN_VARIABLE
  2047 		//   - TOKEN_PARENTHLEFT + TOKEN_VARIABLE
  2048     //   - TOKEN_BOOLOP + TOKEN_VARIABLE
  2048 		//   - TOKEN_BOOLOP + TOKEN_VARIABLE
  2049     //   - TOKEN_VARIABLE + TOKEN_PARENTHRIGHT
  2049 		//   - TOKEN_VARIABLE + TOKEN_PARENTHRIGHT
  2050     //   - TOKEN_PARENTHRIGHT + TOKEN_BOOLOP
  2050 		//   - TOKEN_PARENTHRIGHT + TOKEN_BOOLOP
  2051     $seqcheck = explode(' ', trim($seqcheck));
  2051 		$seqcheck = explode(' ', trim($seqcheck));
  2052     $last_item = TOKEN_BOOLOP;
  2052 		$last_item = TOKEN_BOOLOP;
  2053     foreach ( $seqcheck as $i => $token )
  2053 		foreach ( $seqcheck as $i => $token )
  2054     {
  2054 		{
  2055       // determine type
  2055 			// determine type
  2056       if ( $token == '(' )
  2056 			if ( $token == '(' )
  2057       {
  2057 			{
  2058         $type = TOKEN_PARENTHLEFT;
  2058 				$type = TOKEN_PARENTHLEFT;
  2059       }
  2059 			}
  2060       else if ( $token == ')' )
  2060 			else if ( $token == ')' )
  2061       {
  2061 			{
  2062         $type = TOKEN_PARENTHRIGHT;
  2062 				$type = TOKEN_PARENTHRIGHT;
  2063       }
  2063 			}
  2064       else if ( $token == '!' )
  2064 			else if ( $token == '!' )
  2065       {
  2065 			{
  2066         $type = TOKEN_NOT;
  2066 				$type = TOKEN_NOT;
  2067       }
  2067 			}
  2068       else if ( strtolower($token) == 'and' || strtolower($token) == 'or' || $token == '&&' || $token == '||' )
  2068 			else if ( strtolower($token) == 'and' || strtolower($token) == 'or' || $token == '&&' || $token == '||' )
  2069       {
  2069 			{
  2070         $type = TOKEN_BOOLOP;
  2070 				$type = TOKEN_BOOLOP;
  2071       }
  2071 			}
  2072       else if ( preg_match('/^[a-z0-9_]+$/i', $token) )
  2072 			else if ( preg_match('/^[a-z0-9_]+$/i', $token) )
  2073       {
  2073 			{
  2074         $type = TOKEN_VARIABLE;
  2074 				$type = TOKEN_VARIABLE;
  2075         // at this point it's considered safe to wrap it
  2075 				// at this point it's considered safe to wrap it
  2076         $seqcheck[$i] = "( isset(\$this->tpl_bool['$token']) && \$this->tpl_bool['$token'] )";
  2076 				$seqcheck[$i] = "( isset(\$this->tpl_bool['$token']) && \$this->tpl_bool['$token'] )";
  2077       }
  2077 			}
  2078       else
  2078 			else
  2079       {
  2079 			{
  2080         // syntax error - doesn't match known token types
  2080 				// syntax error - doesn't match known token types
  2081         return 4;
  2081 				return 4;
  2082       }
  2082 			}
  2083       // inner sequence check
  2083 			// inner sequence check
  2084       if (
  2084 			if (
  2085            ( $last_item == TOKEN_BOOLOP && $type == TOKEN_NOT ) ||
  2085  					( $last_item == TOKEN_BOOLOP && $type == TOKEN_NOT ) ||
  2086            ( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_NOT ) ||
  2086  					( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_NOT ) ||
  2087            ( $last_item == TOKEN_NOT && $type == TOKEN_VARIABLE ) ||
  2087  					( $last_item == TOKEN_NOT && $type == TOKEN_VARIABLE ) ||
  2088            ( $last_item == TOKEN_NOT && $type == TOKEN_PARENTHLEFT ) ||
  2088  					( $last_item == TOKEN_NOT && $type == TOKEN_PARENTHLEFT ) ||
  2089            ( $last_item == TOKEN_VARIABLE && $type == TOKEN_BOOLOP ) ||
  2089  					( $last_item == TOKEN_VARIABLE && $type == TOKEN_BOOLOP ) ||
  2090            ( $last_item == TOKEN_BOOLOP && $type == TOKEN_PARENTHLEFT ) ||
  2090  					( $last_item == TOKEN_BOOLOP && $type == TOKEN_PARENTHLEFT ) ||
  2091            ( $last_item == TOKEN_PARENTHLEFT && $type == TOKEN_VARIABLE ) ||
  2091  					( $last_item == TOKEN_PARENTHLEFT && $type == TOKEN_VARIABLE ) ||
  2092            ( $last_item == TOKEN_BOOLOP && $type == TOKEN_VARIABLE ) ||
  2092  					( $last_item == TOKEN_BOOLOP && $type == TOKEN_VARIABLE ) ||
  2093            ( $last_item == TOKEN_VARIABLE && $type == TOKEN_PARENTHRIGHT ) ||
  2093  					( $last_item == TOKEN_VARIABLE && $type == TOKEN_PARENTHRIGHT ) ||
  2094            ( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_BOOLOP )
  2094  					( $last_item == TOKEN_PARENTHRIGHT && $type == TOKEN_BOOLOP )
  2095          )
  2095  				)
  2096       {
  2096 			{
  2097         // sequence is good, continue
  2097 				// sequence is good, continue
  2098       }
  2098 			}
  2099       else
  2099 			else
  2100       {
  2100 			{
  2101         // sequence is invalid, break out
  2101 				// sequence is invalid, break out
  2102         return 5;
  2102 				return 5;
  2103       }
  2103 			}
  2104       $last_item = $type;
  2104 			$last_item = $type;
  2105     }
  2105 		}
  2106     // passed all checks
  2106 		// passed all checks
  2107     $seqcheck = implode(' ', $seqcheck);
  2107 		$seqcheck = implode(' ', $seqcheck);
  2108     $result = eval("return ( $seqcheck ) ? true : false;");
  2108 		$result = eval("return ( $seqcheck ) ? true : false;");
  2109     return ( $result ) ? 2 : 1;
  2109 		return ( $result ) ? 2 : 1;
  2110   }
  2110 	}
  2111   
  2111 	
  2112   /**
  2112 	/**
  2113    * Print a text field that auto-completes a username entered into it.
  2113  	* Print a text field that auto-completes a username entered into it.
  2114    * @param string $name - the name of the form field
  2114  	* @param string $name - the name of the form field
  2115    * @return string
  2115  	* @return string
  2116    */
  2116  	*/
  2117    
  2117  	
  2118   function username_field($name, $value = false)
  2118 	function username_field($name, $value = false)
  2119   {
  2119 	{
  2120     $randomid = md5( time() . microtime() . mt_rand() );
  2120 		$randomid = md5( time() . microtime() . mt_rand() );
  2121     $text = '<input name="'.$name.'" class="autofill username" onkeyup="new AutofillUsername(this);" type="text" size="30" id="userfield_'.$randomid.'" autocomplete="off"';
  2121 		$text = '<input name="'.$name.'" class="autofill username" onkeyup="new AutofillUsername(this);" type="text" size="30" id="userfield_'.$randomid.'" autocomplete="off"';
  2122     if($value) $text .= ' value="'.$value.'"';
  2122 		if($value) $text .= ' value="'.$value.'"';
  2123     $text .= ' />';
  2123 		$text .= ' />';
  2124     return $text;
  2124 		return $text;
  2125   }
  2125 	}
  2126   
  2126 	
  2127   /**
  2127 	/**
  2128    * Print a text field that auto-completes a page name entered into it.
  2128  	* Print a text field that auto-completes a page name entered into it.
  2129    * @param string $name - the name of the form field
  2129  	* @param string $name - the name of the form field
  2130    * @return string
  2130  	* @return string
  2131    */
  2131  	*/
  2132    
  2132  	
  2133   function pagename_field($name, $value = false)
  2133 	function pagename_field($name, $value = false)
  2134   {
  2134 	{
  2135     $randomid = md5( time() . microtime() . mt_rand() );
  2135 		$randomid = md5( time() . microtime() . mt_rand() );
  2136     $text = '<input name="'.$name.'" class="autofill page" onkeyup="new AutofillPage(this);" type="text" size="30" id="pagefield_'.$randomid.'" autocomplete="off"';
  2136 		$text = '<input name="'.$name.'" class="autofill page" onkeyup="new AutofillPage(this);" type="text" size="30" id="pagefield_'.$randomid.'" autocomplete="off"';
  2137     if($value) $text .= ' value="'.$value.'"';
  2137 		if($value) $text .= ' value="'.$value.'"';
  2138     $text .= ' />';
  2138 		$text .= ' />';
  2139     return $text;
  2139 		return $text;
  2140   }
  2140 	}
  2141   
  2141 	
  2142   /**
  2142 	/**
  2143    * Sends a textarea that can be converted to and from a TinyMCE widget on the fly.
  2143  	* Sends a textarea that can be converted to and from a TinyMCE widget on the fly.
  2144    * @param string The name of the form element
  2144  	* @param string The name of the form element
  2145    * @param string The initial content. Optional, defaults to blank
  2145  	* @param string The initial content. Optional, defaults to blank
  2146    * @param int Rows in textarea
  2146  	* @param int Rows in textarea
  2147    * @param int Columns in textarea
  2147  	* @param int Columns in textarea
  2148    * @return string HTML and Javascript code.
  2148  	* @return string HTML and Javascript code.
  2149    */
  2149  	*/
  2150   
  2150 	
  2151   function tinymce_textarea($name, $content = '', $rows = 20, $cols = 60)
  2151 	function tinymce_textarea($name, $content = '', $rows = 20, $cols = 60)
  2152   {
  2152 	{
  2153     global $lang;
  2153 		global $lang;
  2154     $randomid = md5(microtime() . mt_rand());
  2154 		$randomid = md5(microtime() . mt_rand());
  2155     $html = '';
  2155 		$html = '';
  2156     $html .= '<textarea name="' . $name . '" rows="'.$rows.'" cols="'.$cols.'" style="width: 100%;" id="toggleMCEroot_'.$randomid.'">' . $content . '</textarea>';
  2156 		$html .= '<textarea name="' . $name . '" rows="'.$rows.'" cols="'.$cols.'" style="width: 100%;" id="toggleMCEroot_'.$randomid.'">' . $content . '</textarea>';
  2157     $html .= '<div style="float: right; display: table;" id="mceSwitchAgent_' . $randomid . '">' . $lang->get('etc_tinymce_btn_text') . '&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">' . $lang->get('etc_tinymce_btn_graphical') . '</a></div>';
  2157 		$html .= '<div style="float: right; display: table;" id="mceSwitchAgent_' . $randomid . '">' . $lang->get('etc_tinymce_btn_text') . '&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">' . $lang->get('etc_tinymce_btn_graphical') . '</a></div>';
  2158     $html .= '<script type="text/javascript">
  2158 		$html .= '<script type="text/javascript">
  2159                 // <![CDATA[
  2159 								// <![CDATA[
  2160                 function toggleMCE_'.$randomid.'()
  2160 								function toggleMCE_'.$randomid.'()
  2161                 {
  2161 								{
  2162                   var the_obj = document.getElementById(\'toggleMCEroot_' . $randomid . '\');
  2162 									var the_obj = document.getElementById(\'toggleMCEroot_' . $randomid . '\');
  2163                   var panel = document.getElementById(\'mceSwitchAgent_' . $randomid . '\');
  2163 									var panel = document.getElementById(\'mceSwitchAgent_' . $randomid . '\');
  2164                   var text_editor = $lang.get("etc_tinymce_btn_text");
  2164 									var text_editor = $lang.get("etc_tinymce_btn_text");
  2165                   var graphical_editor = $lang.get("etc_tinymce_btn_graphical");
  2165 									var graphical_editor = $lang.get("etc_tinymce_btn_graphical");
  2166                   if ( the_obj.dnIsMCE == "yes" )
  2166 									if ( the_obj.dnIsMCE == "yes" )
  2167                   {
  2167 									{
  2168                     $dynano(the_obj).destroyMCE();
  2168 										$dynano(the_obj).destroyMCE();
  2169                     panel.innerHTML = text_editor + \'&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + graphical_editor + \'</a>\';
  2169 										panel.innerHTML = text_editor + \'&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + graphical_editor + \'</a>\';
  2170                   }
  2170 									}
  2171                   else
  2171 									else
  2172                   {
  2172 									{
  2173                     $dynano(the_obj).switchToMCE();
  2173 										$dynano(the_obj).switchToMCE();
  2174                     panel.innerHTML = \'<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + text_editor + \'</a>&nbsp;&nbsp;|&nbsp;&nbsp;\' + graphical_editor;
  2174 										panel.innerHTML = \'<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + text_editor + \'</a>&nbsp;&nbsp;|&nbsp;&nbsp;\' + graphical_editor;
  2175                   }
  2175 									}
  2176                 }
  2176 								}
  2177                 // ]]>
  2177 								// ]]>
  2178               </script>';
  2178 							</script>';
  2179     return $html;
  2179 		return $html;
  2180   }
  2180 	}
  2181   
  2181 	
  2182   /**
  2182 	/**
  2183    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  2183  	* Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  2184    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  2184  	* Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  2185    * @param $filename the filename of the template to be parsed
  2185  	* @param $filename the filename of the template to be parsed
  2186    * @return object
  2186  	* @return object
  2187    */
  2187  	*/
  2188    
  2188  	
  2189   function makeParser($filename)
  2189 	function makeParser($filename)
  2190   {
  2190 	{
  2191     global $db, $session, $paths, $template, $plugins; // Common objects
  2191 		global $db, $session, $paths, $template, $plugins; // Common objects
  2192     $filename = ENANO_ROOT.'/themes/'.$template->theme.'/'.$filename;
  2192 		$filename = ENANO_ROOT.'/themes/'.$template->theme.'/'.$filename;
  2193     if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
  2193 		if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
  2194     $code = file_get_contents($filename);
  2194 		$code = file_get_contents($filename);
  2195     $parser = new templateIndividual($code);
  2195 		$parser = new templateIndividual($code);
  2196     return $parser;
  2196 		return $parser;
  2197   }
  2197 	}
  2198   
  2198 	
  2199   /**
  2199 	/**
  2200    * Same as $template->makeParser(), but takes a string instead of a filename.
  2200  	* Same as $template->makeParser(), but takes a string instead of a filename.
  2201    * @param $text the text to parse
  2201  	* @param $text the text to parse
  2202    * @return object
  2202  	* @return object
  2203    */
  2203  	*/
  2204    
  2204  	
  2205   function makeParserText($code)
  2205 	function makeParserText($code)
  2206   {
  2206 	{
  2207     $parser = new templateIndividual($code);
  2207 		$parser = new templateIndividual($code);
  2208     return $parser;
  2208 		return $parser;
  2209   }
  2209 	}
  2210   
  2210 	
  2211   /**
  2211 	/**
  2212    * Fetch the HTML for a plugin-added sidebar block
  2212  	* Fetch the HTML for a plugin-added sidebar block
  2213    * @param $name the plugin name
  2213  	* @param $name the plugin name
  2214    * @return string
  2214  	* @return string
  2215    */
  2215  	*/
  2216    
  2216  	
  2217   function fetch_block($id, $just_the_innards_maam = false)
  2217 	function fetch_block($id, $just_the_innards_maam = false)
  2218   {
  2218 	{
  2219     if ( $just_the_innards_maam )
  2219 		if ( $just_the_innards_maam )
  2220     {
  2220 		{
  2221       $source =& $this->plugin_blocks_content;
  2221 			$source =& $this->plugin_blocks_content;
  2222     }
  2222 		}
  2223     else
  2223 		else
  2224     {
  2224 		{
  2225       $source =& $this->plugin_blocks;
  2225 			$source =& $this->plugin_blocks;
  2226     }
  2226 		}
  2227     return isset($source[$id]) ? $source[$id] : false;
  2227 		return isset($source[$id]) ? $source[$id] : false;
  2228   }
  2228 	}
  2229   
  2229 	
  2230   /**
  2230 	/**
  2231    * Fetches the contents of both sidebars.
  2231  	* Fetches the contents of both sidebars.
  2232    * @return array - key 0 is left, key 1 is right, key 2 is the HTML that makes up an empty sidebar
  2232  	* @return array - key 0 is left, key 1 is right, key 2 is the HTML that makes up an empty sidebar
  2233    * @example list($left, $right) = $template->fetch_sidebar();
  2233  	* @example list($left, $right) = $template->fetch_sidebar();
  2234    */
  2234  	*/
  2235   
  2235 	
  2236   function fetch_sidebar()
  2236 	function fetch_sidebar()
  2237   {
  2237 	{
  2238     global $db, $session, $paths, $template, $plugins; // Common objects
  2238 		global $db, $session, $paths, $template, $plugins; // Common objects
  2239     
  2239 		
  2240     // first, check the cache
  2240 		// first, check the cache
  2241     if ( $result = $this->fetch_cached_sidebar() )
  2241 		if ( $result = $this->fetch_cached_sidebar() )
  2242     {
  2242 		{
  2243       return $result;
  2243 			return $result;
  2244     }
  2244 		}
  2245     
  2245 		
  2246     require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg");
  2246 		require(ENANO_ROOT . "/themes/{$this->theme}/theme.cfg");
  2247     
  2247 		
  2248     profiler_log('Started sidebar parsing');
  2248 		profiler_log('Started sidebar parsing');
  2249     
  2249 		
  2250     // init our block contents
  2250 		// init our block contents
  2251     $left = '';
  2251 		$left = '';
  2252     $right = '';
  2252 		$right = '';
  2253     $min = '';
  2253 		$min = '';
  2254     
  2254 		
  2255     // also might want the links block
  2255 		// also might want the links block
  2256     if ( !$this->fetch_block('Links') )
  2256 		if ( !$this->fetch_block('Links') )
  2257       $this->initLinksWidget();
  2257 			$this->initLinksWidget();
  2258     
  2258 		
  2259     // templates to work with
  2259 		// templates to work with
  2260     $vars = $this->extract_vars('elements.tpl');
  2260 		$vars = $this->extract_vars('elements.tpl');
  2261     
  2261 		
  2262     // sidebar_top and sidebar_bottom are HTML that is prepended/appended to sidebar content. Themes can
  2262 		// sidebar_top and sidebar_bottom are HTML that is prepended/appended to sidebar content. Themes can
  2263     // choose whether or not to display a sidebar depending on whether the sidebar is empty ( $left == $min )
  2263 		// choose whether or not to display a sidebar depending on whether the sidebar is empty ( $left == $min )
  2264     // or not using the sidebar_left and sidebar_right template booleans (the oxygen theme does this).
  2264 		// or not using the sidebar_left and sidebar_right template booleans (the oxygen theme does this).
  2265     if ( isset($vars['sidebar_top']) ) 
  2265 		if ( isset($vars['sidebar_top']) ) 
  2266     {
  2266 		{
  2267       $top = $this->parse($vars['sidebar_top']);
  2267 			$top = $this->parse($vars['sidebar_top']);
  2268       $left  .= $top;
  2268 			$left  .= $top;
  2269       $right .= $top;
  2269 			$right .= $top;
  2270       $min .= $top;
  2270 			$min .= $top;
  2271     }
  2271 		}
  2272     
  2272 		
  2273     // grab the blocks from the DB
  2273 		// grab the blocks from the DB
  2274     $q = $db->sql_query('SELECT item_id,sidebar_id,block_name,block_type,block_content FROM '.table_prefix.'sidebar' . "\n"
  2274 		$q = $db->sql_query('SELECT item_id,sidebar_id,block_name,block_type,block_content FROM '.table_prefix.'sidebar' . "\n"
  2275                            . '  WHERE item_enabled=1 ORDER BY sidebar_id ASC, item_order ASC;');
  2275  													. '  WHERE item_enabled=1 ORDER BY sidebar_id ASC, item_order ASC;');
  2276     if ( !$q )
  2276 		if ( !$q )
  2277       $db->_die('The sidebar text data could not be selected.');
  2277 			$db->_die('The sidebar text data could not be selected.');
  2278     
  2278 		
  2279     // explicitly specify $q in case a plugin or PHP block makes a query
  2279 		// explicitly specify $q in case a plugin or PHP block makes a query
  2280     while ( $row = $db->fetchrow($q) )
  2280 		while ( $row = $db->fetchrow($q) )
  2281     {
  2281 		{
  2282       // should we skip this block?
  2282 			// should we skip this block?
  2283       if (
  2283 			if (
  2284           ( $row['item_id'] === 2 && !empty($theme['sb_hide_tools']) ) ||
  2284 					( $row['item_id'] === 2 && !empty($theme['sb_hide_tools']) ) ||
  2285           ( $row['item_id'] === 3 && !empty($theme['sb_hide_user']) ) ||
  2285 					( $row['item_id'] === 3 && !empty($theme['sb_hide_user']) ) ||
  2286           ( $row['item_id'] === 4 && !empty($theme['sb_hide_search']) )
  2286 					( $row['item_id'] === 4 && !empty($theme['sb_hide_search']) )
  2287         )
  2287 				)
  2288         continue;
  2288 				continue;
  2289       
  2289 			
  2290       // format the block
  2290 			// format the block
  2291       $block_content = $this->format_sidebar_block($row, $vars, $parser);
  2291 			$block_content = $this->format_sidebar_block($row, $vars, $parser);
  2292       
  2292 			
  2293       // is there a {restrict} or {hideif} block?
  2293 			// is there a {restrict} or {hideif} block?
  2294       if ( preg_match('/\{(restrict|hideif) ([a-z0-9_\(\)\|&! ]+)\}/', $block_content, $match) )
  2294 			if ( preg_match('/\{(restrict|hideif) ([a-z0-9_\(\)\|&! ]+)\}/', $block_content, $match) )
  2295       {
  2295 			{
  2296         // we have one, check the condition
  2296 				// we have one, check the condition
  2297         $type =& $match[1];
  2297 				$type =& $match[1];
  2298         $cond =& $match[2];
  2298 				$cond =& $match[2];
  2299         $result = $this->process_condition($cond);
  2299 				$result = $this->process_condition($cond);
  2300         if ( ( $type == 'restrict' && $result == 1 ) || ( $type == 'hideif' && $result == 2 ) )
  2300 				if ( ( $type == 'restrict' && $result == 1 ) || ( $type == 'hideif' && $result == 2 ) )
  2301         {
  2301 				{
  2302           // throw out this block, it's hidden for whatever reason by the sidebar script
  2302 					// throw out this block, it's hidden for whatever reason by the sidebar script
  2303           continue;
  2303 					continue;
  2304         }
  2304 				}
  2305         // didn't get a match, so hide the conditional logic
  2305 				// didn't get a match, so hide the conditional logic
  2306         // FIXME: this needs to be verbose about syntax errors
  2306 				// FIXME: this needs to be verbose about syntax errors
  2307         $block_content = str_replace_once($match[0], '', $block_content);
  2307 				$block_content = str_replace_once($match[0], '', $block_content);
  2308       }
  2308 			}
  2309       
  2309 			
  2310       // if we made it here, this block definitely needs to be displayed. send it to the
  2310 			// if we made it here, this block definitely needs to be displayed. send it to the
  2311       // parser (set by format_sidebar_block) and decide where to append it (but not in that order ;))
  2311 			// parser (set by format_sidebar_block) and decide where to append it (but not in that order ;))
  2312       $appender = false;
  2312 			$appender = false;
  2313       
  2313 			
  2314       if ( $row['sidebar_id'] == SIDEBAR_LEFT )
  2314 			if ( $row['sidebar_id'] == SIDEBAR_LEFT )
  2315       {
  2315 			{
  2316         $appender =& $left;
  2316 				$appender =& $left;
  2317       }
  2317 			}
  2318       else if ( $row['sidebar_id'] == SIDEBAR_RIGHT )
  2318 			else if ( $row['sidebar_id'] == SIDEBAR_RIGHT )
  2319       {
  2319 			{
  2320         $appender =& $right;
  2320 				$appender =& $right;
  2321       }
  2321 			}
  2322       else
  2322 			else
  2323       {
  2323 			{
  2324         // uhoh, block_id isn't valid. maybe a plugin wants to put this block somewhere else?
  2324 				// uhoh, block_id isn't valid. maybe a plugin wants to put this block somewhere else?
  2325         $code = $plugins->setHook('sidebar_block_id');
  2325 				$code = $plugins->setHook('sidebar_block_id');
  2326         foreach ( $code as $cmd )
  2326 				foreach ( $code as $cmd )
  2327         {
  2327 				{
  2328           eval($cmd);
  2328 					eval($cmd);
  2329         }
  2329 				}
  2330         // if $appender wasn't set by a plugin, don't parse this block to save some CPU cycles
  2330 				// if $appender wasn't set by a plugin, don't parse this block to save some CPU cycles
  2331         if ( !$appender )
  2331 				if ( !$appender )
  2332         {
  2332 				{
  2333           continue;
  2333 					continue;
  2334         }
  2334 				}
  2335       }
  2335 			}
  2336       
  2336 			
  2337       // assign variables to parser
  2337 			// assign variables to parser
  2338       $block_name = $this->tplWikiFormat($row['block_name']);
  2338 			$block_name = $this->tplWikiFormat($row['block_name']);
  2339       $parser->assign_vars(array(
  2339 			$parser->assign_vars(array(
  2340           // be nice and format the title (FIXME, does this use a lot of CPU time? still needs l10n in some cases though)
  2340 					// be nice and format the title (FIXME, does this use a lot of CPU time? still needs l10n in some cases though)
  2341           'TITLE' => $block_name,
  2341 					'TITLE' => $block_name,
  2342           'CONTENT' => $block_content
  2342 					'CONTENT' => $block_content
  2343         ));
  2343 				));
  2344       $parsed = $parser->run();
  2344 			$parsed = $parser->run();
  2345       
  2345 			
  2346       // plugins are parsed earlier due to the way disabled/missing plugins that add sidebar blocks are
  2346 			// plugins are parsed earlier due to the way disabled/missing plugins that add sidebar blocks are
  2347       // handled, so the {TITLE} var won't be replaced until now. this allows completely eliminating a
  2347 			// handled, so the {TITLE} var won't be replaced until now. this allows completely eliminating a
  2348       // block if it's not available
  2348 			// block if it's not available
  2349       if ( $row['block_type'] == BLOCK_PLUGIN )
  2349 			if ( $row['block_type'] == BLOCK_PLUGIN )
  2350       {
  2350 			{
  2351         $parsed = str_replace('{TITLE}', $block_name, $parsed);
  2351 				$parsed = str_replace('{TITLE}', $block_name, $parsed);
  2352       }
  2352 			}
  2353       
  2353 			
  2354       // done parsing - append and continue
  2354 			// done parsing - append and continue
  2355       $appender .= $parsed;
  2355 			$appender .= $parsed;
  2356       
  2356 			
  2357       // we're done with this - unset it because it's a reference and we don't want it overwritten.
  2357 			// we're done with this - unset it because it's a reference and we don't want it overwritten.
  2358       // also free the parser to get some RAM back
  2358 			// also free the parser to get some RAM back
  2359       unset($appender, $parser);
  2359 			unset($appender, $parser);
  2360     }
  2360 		}
  2361     
  2361 		
  2362     // lastly, append any footer HTML
  2362 		// lastly, append any footer HTML
  2363     if(isset($vars['sidebar_bottom'])) 
  2363 		if(isset($vars['sidebar_bottom'])) 
  2364     {
  2364 		{
  2365       $bottom = $this->parse($vars['sidebar_bottom']);
  2365 			$bottom = $this->parse($vars['sidebar_bottom']);
  2366       $left  .= $bottom;
  2366 			$left  .= $bottom;
  2367       $right .= $bottom;
  2367 			$right .= $bottom;
  2368       $min   .= $bottom;
  2368 			$min   .= $bottom;
  2369     }
  2369 		}
  2370     
  2370 		
  2371     $return = array($left, $right, $min);
  2371 		$return = array($left, $right, $min);
  2372     
  2372 		
  2373     // allow any plugins to append what they want to the return
  2373 		// allow any plugins to append what they want to the return
  2374     $code = $plugins->setHook('sidebar_fetch_return');
  2374 		$code = $plugins->setHook('sidebar_fetch_return');
  2375     foreach ( $code as $cmd )
  2375 		foreach ( $code as $cmd )
  2376     {
  2376 		{
  2377       eval($cmd);
  2377 			eval($cmd);
  2378     }
  2378 		}
  2379     
  2379 		
  2380     // cache the result if appropriate
  2380 		// cache the result if appropriate
  2381     $this->cache_compiled_sidebar($return);
  2381 		$this->cache_compiled_sidebar($return);
  2382     
  2382 		
  2383     profiler_log('Finished sidebar parsing');
  2383 		profiler_log('Finished sidebar parsing');
  2384     
  2384 		
  2385     return $return;
  2385 		return $return;
  2386   }
  2386 	}
  2387   
  2387 	
  2388   /**
  2388 	/**
  2389    * Runs the appropriate formatting routine on a sidebar row.
  2389  	* Runs the appropriate formatting routine on a sidebar row.
  2390    * @param array Row in sidebar table
  2390  	* @param array Row in sidebar table
  2391    * @param array Template variable set from elements.tpl
  2391  	* @param array Template variable set from elements.tpl
  2392    * @param null Pass by reference, will be filled with the parser according to the block's type (sidebar_section or sidebar_section_raw)
  2392  	* @param null Pass by reference, will be filled with the parser according to the block's type (sidebar_section or sidebar_section_raw)
  2393    * @return string HTML + directives like {restrict} or {hideif}
  2393  	* @return string HTML + directives like {restrict} or {hideif}
  2394    */
  2394  	*/
  2395   
  2395 	
  2396   function format_sidebar_block($row, $vars, &$parser)
  2396 	function format_sidebar_block($row, $vars, &$parser)
  2397   {
  2397 	{
  2398     // import globals in case a PHP block wants to call the Enano API
  2398 		// import globals in case a PHP block wants to call the Enano API
  2399     global $db, $session, $paths, $template, $plugins; // Common objects
  2399 		global $db, $session, $paths, $template, $plugins; // Common objects
  2400     
  2400 		
  2401     $parser = null;
  2401 		$parser = null;
  2402     
  2402 		
  2403     switch($row['block_type'])
  2403 		switch($row['block_type'])
  2404     {
  2404 		{
  2405       case BLOCK_WIKIFORMAT:
  2405 			case BLOCK_WIKIFORMAT:
  2406         $parser = $this->makeParserText($vars['sidebar_section_raw']);
  2406 				$parser = $this->makeParserText($vars['sidebar_section_raw']);
  2407         $c = RenderMan::render($row['block_content']);
  2407 				$c = RenderMan::render($row['block_content']);
  2408         break;
  2408 				break;
  2409         
  2409 				
  2410       case BLOCK_TEMPLATEFORMAT:
  2410 			case BLOCK_TEMPLATEFORMAT:
  2411         $parser = $this->makeParserText($vars['sidebar_section']);
  2411 				$parser = $this->makeParserText($vars['sidebar_section']);
  2412         $c = $this->tplWikiFormat($row['block_content']);
  2412 				$c = $this->tplWikiFormat($row['block_content']);
  2413         break;
  2413 				break;
  2414         
  2414 				
  2415       case BLOCK_HTML:
  2415 			case BLOCK_HTML:
  2416         $parser = $this->makeParserText($vars['sidebar_section_raw']);
  2416 				$parser = $this->makeParserText($vars['sidebar_section_raw']);
  2417         $c = $row['block_content'];
  2417 				$c = $row['block_content'];
  2418         break;
  2418 				break;
  2419         
  2419 				
  2420       case BLOCK_PHP:
  2420 			case BLOCK_PHP:
  2421         // PHP blocks need to be sent directly to eval()
  2421 				// PHP blocks need to be sent directly to eval()
  2422         $parser = $this->makeParserText($vars['sidebar_section_raw']);
  2422 				$parser = $this->makeParserText($vars['sidebar_section_raw']);
  2423         ob_start();
  2423 				ob_start();
  2424         @eval($row['block_content']);
  2424 				@eval($row['block_content']);
  2425         $c = ob_get_contents();
  2425 				$c = ob_get_contents();
  2426         ob_end_clean();
  2426 				ob_end_clean();
  2427         break;
  2427 				break;
  2428         
  2428 				
  2429       case BLOCK_PLUGIN:
  2429 			case BLOCK_PLUGIN:
  2430         $parser = $this->makeParserText('{CONTENT}');
  2430 				$parser = $this->makeParserText('{CONTENT}');
  2431         $c = '<!-- PLUGIN -->' . (gettype($this->fetch_block($row['block_content'])) == 'string') ?
  2431 				$c = '<!-- PLUGIN -->' . (gettype($this->fetch_block($row['block_content'])) == 'string') ?
  2432                 $this->fetch_block($row['block_content']) :
  2432 								$this->fetch_block($row['block_content']) :
  2433                 // This used to say "can't find plugin block" but I think it's more friendly to just silently hide it.
  2433 								// This used to say "can't find plugin block" but I think it's more friendly to just silently hide it.
  2434                 '';
  2434 								'';
  2435         break;
  2435 				break;
  2436       default:
  2436 			default:
  2437         // unknown block type - can a plugin handle it?
  2437 				// unknown block type - can a plugin handle it?
  2438         $code = $plugins->setHook('format_sidebar_block');
  2438 				$code = $plugins->setHook('format_sidebar_block');
  2439         foreach ( $code as $cmd )
  2439 				foreach ( $code as $cmd )
  2440         {
  2440 				{
  2441           eval($cmd);
  2441 					eval($cmd);
  2442         }
  2442 				}
  2443         if ( !isset($c) )
  2443 				if ( !isset($c) )
  2444         {
  2444 				{
  2445           // default to wiki formatting (this was going to be straight HTML but this is done for backwards compatibility reasons)
  2445 					// default to wiki formatting (this was going to be straight HTML but this is done for backwards compatibility reasons)
  2446           $c = RenderMan::render($row['block_content']);
  2446 					$c = RenderMan::render($row['block_content']);
  2447         }
  2447 				}
  2448         if ( !$parser )
  2448 				if ( !$parser )
  2449         {
  2449 				{
  2450           // no parser defined, use the "raw" section by default (plugins are more likely to want raw content
  2450 					// no parser defined, use the "raw" section by default (plugins are more likely to want raw content
  2451           // rather than a list of links, and they can set the parser to use sidebar_section if they want)
  2451 					// rather than a list of links, and they can set the parser to use sidebar_section if they want)
  2452           $parser = $this->makeParserText($vars['sidebar_section_raw']);
  2452 					$parser = $this->makeParserText($vars['sidebar_section_raw']);
  2453         }
  2453 				}
  2454         
  2454 				
  2455         break;
  2455 				break;
  2456     }
  2456 		}
  2457     
  2457 		
  2458     return $c;
  2458 		return $c;
  2459   }
  2459 	}
  2460   
  2460 	
  2461   /**
  2461 	/**
  2462    * Returns the list of things that should not be cached (sorry, I was listening to "The Thing That Should Not Be" by Metallica when I
  2462  	* Returns the list of things that should not be cached (sorry, I was listening to "The Thing That Should Not Be" by Metallica when I
  2463    * wrote this routine. You should get a copy of Master of Puppets, it's a damn good album.)
  2463  	* wrote this routine. You should get a copy of Master of Puppets, it's a damn good album.)
  2464    * @return array
  2464  	* @return array
  2465    */
  2465  	*/
  2466   
  2466 	
  2467   function get_cache_replacements()
  2467 	function get_cache_replacements()
  2468   {
  2468 	{
  2469     global $db, $session, $paths, $template, $plugins; // Common objects
  2469 		global $db, $session, $paths, $template, $plugins; // Common objects
  2470     
  2470 		
  2471     return array(
  2471 		return array(
  2472           '$LOGIN_LINK$' => $this->tpl_strings['LOGIN_LINK'],
  2472 					'$LOGIN_LINK$' => $this->tpl_strings['LOGIN_LINK'],
  2473           '$MAIN_PAGE$' => $this->tpl_strings['MAIN_PAGE'],
  2473 					'$MAIN_PAGE$' => $this->tpl_strings['MAIN_PAGE'],
  2474           '$USERNAME$' => $session->username
  2474 					'$USERNAME$' => $session->username
  2475         );
  2475 				);
  2476   }
  2476 	}
  2477   
  2477 	
  2478   /**
  2478 	/**
  2479    * Attempts to load a cached compiled sidebar.
  2479  	* Attempts to load a cached compiled sidebar.
  2480    * @return array Same format as fetch_sidebar()
  2480  	* @return array Same format as fetch_sidebar()
  2481    */
  2481  	*/
  2482   
  2482 	
  2483   function fetch_cached_sidebar()
  2483 	function fetch_cached_sidebar()
  2484   {
  2484 	{
  2485     global $db, $session, $paths, $template, $plugins; // Common objects
  2485 		global $db, $session, $paths, $template, $plugins; // Common objects
  2486     global $cache;
  2486 		global $cache;
  2487     
  2487 		
  2488     $cached = false;
  2488 		$cached = false;
  2489     if ( ($result = $cache->fetch('anon_sidebar')) && !$session->user_logged_in )
  2489 		if ( ($result = $cache->fetch('anon_sidebar')) && !$session->user_logged_in )
  2490     {
  2490 		{
  2491       if ( isset($result[$this->theme]) )
  2491 			if ( isset($result[$this->theme]) )
  2492       {
  2492 			{
  2493         $cached = $result[$this->theme];
  2493 				$cached = $result[$this->theme];
  2494       }
  2494 			}
  2495     }
  2495 		}
  2496     
  2496 		
  2497     // if we haven't been able to fetch yet, see if a plugin wants to give us something
  2497 		// if we haven't been able to fetch yet, see if a plugin wants to give us something
  2498     if ( !$cached )
  2498 		if ( !$cached )
  2499     {
  2499 		{
  2500       $code = $plugins->setHook('fetch_cached_sidebar');
  2500 			$code = $plugins->setHook('fetch_cached_sidebar');
  2501       foreach ( $code as $cmd )
  2501 			foreach ( $code as $cmd )
  2502       {
  2502 			{
  2503         eval($cmd);
  2503 				eval($cmd);
  2504       }
  2504 			}
  2505     } 
  2505 		} 
  2506     
  2506 		
  2507     if ( is_array($cached) )
  2507 		if ( is_array($cached) )
  2508     {
  2508 		{
  2509       // fetch certain variables that can't be stored in the cache and quickly substitute
  2509 			// fetch certain variables that can't be stored in the cache and quickly substitute
  2510       $replace = $this->get_cache_replacements();
  2510 			$replace = $this->get_cache_replacements();
  2511       foreach ( $cached as &$val )
  2511 			foreach ( $cached as &$val )
  2512       {
  2512 			{
  2513         $val = strtr($val, $replace);
  2513 				$val = strtr($val, $replace);
  2514       }
  2514 			}
  2515       
  2515 			
  2516       // done processing, send it back
  2516 			// done processing, send it back
  2517       return $cached;
  2517 			return $cached;
  2518     }
  2518 		}
  2519     
  2519 		
  2520     return false;
  2520 		return false;
  2521   }
  2521 	}
  2522   
  2522 	
  2523   /**
  2523 	/**
  2524    * Caches a completely compiled sidebar, if appropriate
  2524  	* Caches a completely compiled sidebar, if appropriate
  2525    * @param array Effectively, return from fetch_sidebar()
  2525  	* @param array Effectively, return from fetch_sidebar()
  2526    */
  2526  	*/
  2527   
  2527 	
  2528   function cache_compiled_sidebar($sidebar)
  2528 	function cache_compiled_sidebar($sidebar)
  2529   {
  2529 	{
  2530     global $db, $session, $paths, $template, $plugins; // Common objects
  2530 		global $db, $session, $paths, $template, $plugins; // Common objects
  2531     global $cache;
  2531 		global $cache;
  2532     
  2532 		
  2533     // check if conditions are right
  2533 		// check if conditions are right
  2534     if ( !$session->user_logged_in && getConfig('cache_thumbs') === '1' )
  2534 		if ( !$session->user_logged_in && getConfig('cache_thumbs') === '1' )
  2535     {
  2535 		{
  2536       // load any existing cache to make sure other themes' cached sidebars aren't discarded
  2536 			// load any existing cache to make sure other themes' cached sidebars aren't discarded
  2537       $cached = ( $_ = $cache->fetch('anon_sidebar') ) ? $_ : array();
  2537 			$cached = ( $_ = $cache->fetch('anon_sidebar') ) ? $_ : array();
  2538       
  2538 			
  2539       // replace variables
  2539 			// replace variables
  2540       $replace = array_flip($this->get_cache_replacements());
  2540 			$replace = array_flip($this->get_cache_replacements());
  2541       
  2541 			
  2542       foreach ( $sidebar as &$section )
  2542 			foreach ( $sidebar as &$section )
  2543       {
  2543 			{
  2544         $section = strtr($section, $replace);
  2544 				$section = strtr($section, $replace);
  2545       }
  2545 			}
  2546       
  2546 			
  2547       // compile
  2547 			// compile
  2548       $cached[$this->theme] = $sidebar;
  2548 			$cached[$this->theme] = $sidebar;
  2549       
  2549 			
  2550       // store
  2550 			// store
  2551       $cache->store('anon_sidebar', $cached, 15);
  2551 			$cache->store('anon_sidebar', $cached, 15);
  2552     }
  2552 		}
  2553   }
  2553 	}
  2554   
  2554 	
  2555   function initLinksWidget()
  2555 	function initLinksWidget()
  2556   {
  2556 	{
  2557     global $db, $session, $paths, $template, $plugins; // Common objects
  2557 		global $db, $session, $paths, $template, $plugins; // Common objects
  2558     
  2558 		
  2559     // SourceForge/W3C buttons
  2559 		// SourceForge/W3C buttons
  2560     $ob = Array();
  2560 		$ob = Array();
  2561     if(getConfig('sflogo_enabled')=='1')
  2561 		if(getConfig('sflogo_enabled')=='1')
  2562     {
  2562 		{
  2563       $sflogo_secure = ( isset($_SERVER['HTTPS']) ) ? 'https' : 'http';
  2563 			$sflogo_secure = ( isset($_SERVER['HTTPS']) ) ? 'https' : 'http';
  2564       $ob[] = '<a style="text-align: center;" href="http://sourceforge.net/" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border-width: 0px;" alt="SourceForge.net Logo" src="' . $sflogo_secure . '://sflogo.sourceforge.net/sflogo.php?group_id='.getConfig('sflogo_groupid').'&amp;type='.getConfig('sflogo_type').'" /></a>';
  2564 			$ob[] = '<a style="text-align: center;" href="http://sourceforge.net/" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border-width: 0px;" alt="SourceForge.net Logo" src="' . $sflogo_secure . '://sflogo.sourceforge.net/sflogo.php?group_id='.getConfig('sflogo_groupid').'&amp;type='.getConfig('sflogo_type').'" /></a>';
  2565     }
  2565 		}
  2566     if(getConfig('w3c_v32')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 3.2"  src="http://www.w3.org/Icons/valid-html32" /></a>';
  2566 		if(getConfig('w3c_v32')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 3.2"  src="http://www.w3.org/Icons/valid-html32" /></a>';
  2567     if(getConfig('w3c_v40')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.0"  src="http://www.w3.org/Icons/valid-html40" /></a>';
  2567 		if(getConfig('w3c_v40')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.0"  src="http://www.w3.org/Icons/valid-html40" /></a>';
  2568     if(getConfig('w3c_v401')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.01" src="http://www.w3.org/Icons/valid-html401" /></a>';
  2568 		if(getConfig('w3c_v401')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.01" src="http://www.w3.org/Icons/valid-html401" /></a>';
  2569     if(getConfig('w3c_vxhtml10')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.0" src="http://www.w3.org/Icons/valid-xhtml10" /></a>';
  2569 		if(getConfig('w3c_vxhtml10')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.0" src="http://www.w3.org/Icons/valid-xhtml10" /></a>';
  2570     if(getConfig('w3c_vxhtml11')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.1" src="http://www.w3.org/Icons/valid-xhtml11" /></a>';
  2570 		if(getConfig('w3c_vxhtml11')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.1" src="http://www.w3.org/Icons/valid-xhtml11" /></a>';
  2571     if(getConfig('w3c_vcss')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid CSS"       src="http://www.w3.org/Icons/valid-css" /></a>';
  2571 		if(getConfig('w3c_vcss')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="Valid CSS"       src="http://www.w3.org/Icons/valid-css" /></a>';
  2572     if(getConfig('dbd_button')  =='1') $ob[] = '<a style="text-align: center;" href="http://www.defectivebydesign.org/join/button" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="DRM technology restricts what you can do with your computer" src="' . cdnPath . '/images/defectivebydesign.png" /><br /><small>Protect your freedom >></small></a>';
  2572 		if(getConfig('dbd_button')  =='1') $ob[] = '<a style="text-align: center;" href="http://www.defectivebydesign.org/join/button" onclick="if ( !KILL_SWITCH ) { window.open(this.href);return false; }"><img style="border: 0px solid #FFFFFF;" alt="DRM technology restricts what you can do with your computer" src="' . cdnPath . '/images/defectivebydesign.png" /><br /><small>Protect your freedom >></small></a>';
  2573     
  2573 		
  2574     $code = $plugins->setHook('links_widget');
  2574 		$code = $plugins->setHook('links_widget');
  2575     foreach ( $code as $cmd )
  2575 		foreach ( $code as $cmd )
  2576     {
  2576 		{
  2577       eval($cmd);
  2577 			eval($cmd);
  2578     }
  2578 		}
  2579     
  2579 		
  2580     if(count($ob) > 0 || getConfig('powered_btn', '1') == '1') $sb_links = '<div style="text-align: center; padding: 5px 0;">'. ( ( getConfig('powered_btn', '1') == '1' ) ? $this->fading_button : '' ) . implode('<br />', $ob).'</div>';
  2580 		if(count($ob) > 0 || getConfig('powered_btn', '1') == '1') $sb_links = '<div style="text-align: center; padding: 5px 0;">'. ( ( getConfig('powered_btn', '1') == '1' ) ? $this->fading_button : '' ) . implode('<br />', $ob).'</div>';
  2581     else $sb_links = '';
  2581 		else $sb_links = '';
  2582     
  2582 		
  2583     $this->sidebar_widget('Links', $sb_links);
  2583 		$this->sidebar_widget('Links', $sb_links);
  2584   }
  2584 	}
  2585   
  2585 	
  2586   /**
  2586 	/**
  2587    * Builds a box showing unread private messages.
  2587  	* Builds a box showing unread private messages.
  2588    */
  2588  	*/
  2589   
  2589 	
  2590   function notify_unread_pms()
  2590 	function notify_unread_pms()
  2591   {
  2591 	{
  2592     global $db, $session, $paths, $template, $plugins; // Common objects
  2592 		global $db, $session, $paths, $template, $plugins; // Common objects
  2593     if ( ( $paths->page_id == 'PrivateMessages' || $paths->page_id == 'Preferences' ) && $paths->namespace == 'Special' )
  2593 		if ( ( $paths->page_id == 'PrivateMessages' || $paths->page_id == 'Preferences' ) && $paths->namespace == 'Special' )
  2594     {
  2594 		{
  2595       return '';
  2595 			return '';
  2596     }
  2596 		}
  2597     $ob = '<div class="usermessage">'."\n";
  2597 		$ob = '<div class="usermessage">'."\n";
  2598     $s = ( $session->unread_pms == 1 ) ? '' : 's';
  2598 		$s = ( $session->unread_pms == 1 ) ? '' : 's';
  2599     $ob .= "  <b>You have $session->unread_pms <a href=" . '"' . makeUrlNS('Special', 'PrivateMessages' ) . '"' . ">unread private message$s</a>.</b><br />\n  Messages: ";
  2599 		$ob .= "  <b>You have $session->unread_pms <a href=" . '"' . makeUrlNS('Special', 'PrivateMessages' ) . '"' . ">unread private message$s</a>.</b><br />\n  Messages: ";
  2600     $q = $db->sql_query('SELECT message_id,message_from,subject,date FROM '.table_prefix.'privmsgs WHERE message_to=\'' . $session->username . '\' AND message_read=0 ORDER BY date DESC;');
  2600 		$q = $db->sql_query('SELECT message_id,message_from,subject,date FROM '.table_prefix.'privmsgs WHERE message_to=\'' . $session->username . '\' AND message_read=0 ORDER BY date DESC;');
  2601     if ( !$q )
  2601 		if ( !$q )
  2602       $db->_die();
  2602 			$db->_die();
  2603     $messages = array();
  2603 		$messages = array();
  2604     while ( $row = $db->fetchrow() )
  2604 		while ( $row = $db->fetchrow() )
  2605     {
  2605 		{
  2606       $messages[] = '<a href="' . makeUrlNS('Special', 'PrivateMessages/View/' . $row['message_id']) . '" title="Sent ' . enano_date(ED_DATE | ED_TIME, $row['date']) . ' by ' . $row['message_from'] . '">' . $row['subject'] . '</a>';
  2606 			$messages[] = '<a href="' . makeUrlNS('Special', 'PrivateMessages/View/' . $row['message_id']) . '" title="Sent ' . enano_date(ED_DATE | ED_TIME, $row['date']) . ' by ' . $row['message_from'] . '">' . $row['subject'] . '</a>';
  2607     }
  2607 		}
  2608     $ob .= implode(",\n    " , $messages)."\n";
  2608 		$ob .= implode(",\n    " , $messages)."\n";
  2609     $ob .= '</div>'."\n";
  2609 		$ob .= '</div>'."\n";
  2610     return $ob;
  2610 		return $ob;
  2611   }
  2611 	}
  2612   
  2612 	
  2613   /**
  2613 	/**
  2614    * Parse a system message.
  2614  	* Parse a system message.
  2615    * @param string message
  2615  	* @param string message
  2616    * @return string
  2616  	* @return string
  2617    */
  2617  	*/
  2618   
  2618 	
  2619   function parse_system_message($text)
  2619 	function parse_system_message($text)
  2620   {
  2620 	{
  2621     ob_start();
  2621 		ob_start();
  2622     eval( '?>' . $text );
  2622 		eval( '?>' . $text );
  2623     $result = ob_get_contents();
  2623 		$result = ob_get_contents();
  2624     ob_end_clean();
  2624 		ob_end_clean();
  2625     return $this->parse($result);
  2625 		return $this->parse($result);
  2626   }
  2626 	}
  2627   
  2627 	
  2628   /**
  2628 	/**
  2629    * Return the wiki mode edit notice, rendered and addslashes()'ed.
  2629  	* Return the wiki mode edit notice, rendered and addslashes()'ed.
  2630    * @return string
  2630  	* @return string
  2631    */
  2631  	*/
  2632   
  2632 	
  2633   function get_wiki_edit_notice()
  2633 	function get_wiki_edit_notice()
  2634   {
  2634 	{
  2635     global $cache;
  2635 		global $cache;
  2636     
  2636 		
  2637     if ( getConfig('wiki_edit_notice', 0) != 1 )
  2637 		if ( getConfig('wiki_edit_notice', 0) != 1 )
  2638       return '';
  2638 			return '';
  2639     
  2639 		
  2640     $notice = RenderMan::render(getConfig('wiki_edit_notice_text'));
  2640 		$notice = RenderMan::render(getConfig('wiki_edit_notice_text'));
  2641     return $notice;
  2641 		return $notice;
  2642   }
  2642 	}
  2643   
  2643 	
  2644 } // class template
  2644 } // class template
  2645 
  2645 
  2646 /**
  2646 /**
  2647  * The core of the template compilation engine. Independent from the Enano API for failsafe operation.
  2647  * The core of the template compilation engine. Independent from the Enano API for failsafe operation.
  2648  * @param string text to process
  2648  * @param string text to process
  2650  * @access private
  2650  * @access private
  2651  */
  2651  */
  2652 
  2652 
  2653 function template_compiler_core($text)
  2653 function template_compiler_core($text)
  2654 {
  2654 {
  2655   global $db, $session, $paths, $template, $plugins; // Common objects
  2655 	global $db, $session, $paths, $template, $plugins; // Common objects
  2656   // A random seed used to salt tags
  2656 	// A random seed used to salt tags
  2657   $seed = md5 ( microtime() . mt_rand() );
  2657 	$seed = md5 ( microtime() . mt_rand() );
  2658   
  2658 	
  2659   // Strip out PHP sections
  2659 	// Strip out PHP sections
  2660   preg_match_all('/<\?php(.+?)\?>/is', $text, $php_matches);
  2660 	preg_match_all('/<\?php(.+?)\?>/is', $text, $php_matches);
  2661   
  2661 	
  2662   foreach ( $php_matches[0] as $i => $match )
  2662 	foreach ( $php_matches[0] as $i => $match )
  2663   {
  2663 	{
  2664     // Substitute the PHP section with a random tag
  2664 		// Substitute the PHP section with a random tag
  2665     $tag = "{PHP:$i:$seed}";
  2665 		$tag = "{PHP:$i:$seed}";
  2666     $text = str_replace_once($match, $tag, $text);
  2666 		$text = str_replace_once($match, $tag, $text);
  2667   }
  2667 	}
  2668   
  2668 	
  2669   // Escape slashes and single quotes in template code
  2669 	// Escape slashes and single quotes in template code
  2670   $text = str_replace('\\', '\\\\', $text);
  2670 	$text = str_replace('\\', '\\\\', $text);
  2671   $text = str_replace('\'', '\\\'', $text);
  2671 	$text = str_replace('\'', '\\\'', $text);
  2672   
  2672 	
  2673   // Initialize the PHP compiled code
  2673 	// Initialize the PHP compiled code
  2674   $text = 'ob_start(); global $paths, $template; echo \''.$text.'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
  2674 	$text = 'ob_start(); global $paths, $template; echo \''.$text.'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
  2675   
  2675 	
  2676   ##
  2676 	##
  2677   ## Main rules
  2677 	## Main rules
  2678   ##
  2678 	##
  2679   
  2679 	
  2680   //
  2680 	//
  2681   // Conditionals
  2681 	// Conditionals
  2682   //
  2682 	//
  2683   
  2683 	
  2684   $keywords = array('BEGIN', 'BEGINNOT', 'IFSET', 'IFPLUGIN');
  2684 	$keywords = array('BEGIN', 'BEGINNOT', 'IFSET', 'IFPLUGIN');
  2685   
  2685 	
  2686   // only do this if the plugins API is loaded
  2686 	// only do this if the plugins API is loaded
  2687   if ( is_object(@$plugins) )
  2687 	if ( is_object(@$plugins) )
  2688   {
  2688 	{
  2689     $code = $plugins->setHook('template_compile_logic_keyword');
  2689 		$code = $plugins->setHook('template_compile_logic_keyword');
  2690     foreach ( $code as $cmd )
  2690 		foreach ( $code as $cmd )
  2691     {
  2691 		{
  2692       eval($cmd);
  2692 			eval($cmd);
  2693     }
  2693 		}
  2694   }
  2694 	}
  2695   
  2695 	
  2696   $keywords = implode('|', $keywords);
  2696 	$keywords = implode('|', $keywords);
  2697   
  2697 	
  2698   // Matches
  2698 	// Matches
  2699   //          1     2                 3                 4   56                       7     8        9
  2699 	//          1     2                 3                 4   56                       7     8        9
  2700   $regexp = '/(<!-- ?(' . $keywords . ') ([A-z0-9_-]+) ?-->)([\w\W]*)((<!-- ?BEGINELSE \\3 ?-->)([\w\W]*))?(<!-- ?END(IF)? \\3 ?-->)/isU';
  2700 	$regexp = '/(<!-- ?(' . $keywords . ') ([A-z0-9_-]+) ?-->)([\w\W]*)((<!-- ?BEGINELSE \\3 ?-->)([\w\W]*))?(<!-- ?END(IF)? \\3 ?-->)/isU';
  2701   
  2701 	
  2702   /*
  2702 	/*
  2703   The way this works is: match all blocks using the standard form with a different keyword in the block each time,
  2703 	The way this works is: match all blocks using the standard form with a different keyword in the block each time,
  2704   and replace them with appropriate PHP logic. Plugin-extensible now. :-)
  2704 	and replace them with appropriate PHP logic. Plugin-extensible now. :-)
  2705   */
  2705 	*/
  2706   
  2706 	
  2707   // This is a workaround for what seems like a PCRE bug
  2707 	// This is a workaround for what seems like a PCRE bug
  2708   while ( preg_match_all($regexp, $text, $matches) )
  2708 	while ( preg_match_all($regexp, $text, $matches) )
  2709   {
  2709 	{
  2710   
  2710 	
  2711   for ( $i = 0; $i < count($matches[0]); $i++ )
  2711 	for ( $i = 0; $i < count($matches[0]); $i++ )
  2712   {
  2712 	{
  2713     $start_tag =& $matches[1][$i];
  2713 		$start_tag =& $matches[1][$i];
  2714     $type =& $matches[2][$i];
  2714 		$type =& $matches[2][$i];
  2715     $test =& $matches[3][$i];
  2715 		$test =& $matches[3][$i];
  2716     $particle_true  =& $matches[4][$i];
  2716 		$particle_true  =& $matches[4][$i];
  2717     $else_tag =& $matches[6][$i];
  2717 		$else_tag =& $matches[6][$i];
  2718     $particle_else =& $matches[7][$i];
  2718 		$particle_else =& $matches[7][$i];
  2719     $end_tag =& $matches[8][$i];
  2719 		$end_tag =& $matches[8][$i];
  2720     
  2720 		
  2721     switch($type)
  2721 		switch($type)
  2722     {
  2722 		{
  2723       case 'BEGIN':
  2723 			case 'BEGIN':
  2724         $cond = "isset(\$this->tpl_bool['$test']) && \$this->tpl_bool['$test']";
  2724 				$cond = "isset(\$this->tpl_bool['$test']) && \$this->tpl_bool['$test']";
  2725         break;
  2725 				break;
  2726       case 'BEGINNOT':
  2726 			case 'BEGINNOT':
  2727         $cond = "!isset(\$this->tpl_bool['$test']) || ( isset(\$this->tpl_bool['$test']) && !\$this->tpl_bool['$test'] )";
  2727 				$cond = "!isset(\$this->tpl_bool['$test']) || ( isset(\$this->tpl_bool['$test']) && !\$this->tpl_bool['$test'] )";
  2728         break;
  2728 				break;
  2729       case 'IFPLUGIN':
  2729 			case 'IFPLUGIN':
  2730         $cond = "getConfig('plugin_$test') == '1'";
  2730 				$cond = "getConfig('plugin_$test') == '1'";
  2731         break;
  2731 				break;
  2732       case 'IFSET':
  2732 			case 'IFSET':
  2733         $cond = "isset(\$this->tpl_strings['$test'])";
  2733 				$cond = "isset(\$this->tpl_strings['$test'])";
  2734         break;
  2734 				break;
  2735       default:
  2735 			default:
  2736         // only do this if the plugins API is loaded
  2736 				// only do this if the plugins API is loaded
  2737         if ( is_object(@$plugins) )
  2737 				if ( is_object(@$plugins) )
  2738         {
  2738 				{
  2739           $code = $plugins->setHook('template_compile_logic_cond');
  2739 					$code = $plugins->setHook('template_compile_logic_cond');
  2740           foreach ( $code as $cmd )
  2740 					foreach ( $code as $cmd )
  2741           {
  2741 					{
  2742             eval($cmd);
  2742 						eval($cmd);
  2743           }
  2743 					}
  2744         }
  2744 				}
  2745         break;
  2745 				break;
  2746     }
  2746 		}
  2747     
  2747 		
  2748     if ( !isset($cond) || ( isset($cond) && !is_string($cond) ) )
  2748 		if ( !isset($cond) || ( isset($cond) && !is_string($cond) ) )
  2749       continue;
  2749 			continue;
  2750     
  2750 		
  2751     $tag_complete = <<<TPLCODE
  2751 		$tag_complete = <<<TPLCODE
  2752 ';
  2752 ';
  2753     /* START OF CONDITION: $type ($test) */
  2753 		/* START OF CONDITION: $type ($test) */
  2754     if ( $cond )
  2754 		if ( $cond )
  2755     {
  2755 		{
  2756       echo '$particle_true';
  2756 			echo '$particle_true';
  2757     /* ELSE OF CONDITION: $type ($test) */
  2757 		/* ELSE OF CONDITION: $type ($test) */
  2758     }
  2758 		}
  2759     else
  2759 		else
  2760     {
  2760 		{
  2761       echo '$particle_else';
  2761 			echo '$particle_else';
  2762     /* END OF CONDITION: $type ($test) */
  2762 		/* END OF CONDITION: $type ($test) */
  2763     }
  2763 		}
  2764     echo '
  2764 		echo '
  2765 TPLCODE;
  2765 TPLCODE;
  2766     
  2766 		
  2767     $text = str_replace_once($matches[0][$i], $tag_complete, $text);
  2767 		$text = str_replace_once($matches[0][$i], $tag_complete, $text);
  2768   }
  2768 	}
  2769   }
  2769 	}
  2770   
  2770 	
  2771   // For debugging ;-)
  2771 	// For debugging ;-)
  2772   // die("<pre>&lt;?php\n" . htmlspecialchars($text."\n\n".print_r($matches,true)) . "\n\n?&gt;</pre>");
  2772 	// die("<pre>&lt;?php\n" . htmlspecialchars($text."\n\n".print_r($matches,true)) . "\n\n?&gt;</pre>");
  2773   
  2773 	
  2774   //
  2774 	//
  2775   // Data substitution/variables
  2775 	// Data substitution/variables
  2776   //
  2776 	//
  2777   
  2777 	
  2778   // System messages
  2778 	// System messages
  2779   $text = preg_replace('/<!-- SYSMSG ([A-z0-9\._-]+?) -->/is', '\' . $this->parse_system_message($paths->sysMsg(\'\\1\')) . \'', $text);
  2779 	$text = preg_replace('/<!-- SYSMSG ([A-z0-9\._-]+?) -->/is', '\' . $this->parse_system_message($paths->sysMsg(\'\\1\')) . \'', $text);
  2780   
  2780 	
  2781   // Hooks
  2781 	// Hooks
  2782   $text = preg_replace('/<!-- HOOK ([A-z0-9_]+) -->/', '\' . $this->get_theme_hook(\'\\1\') . \'', $text);
  2782 	$text = preg_replace('/<!-- HOOK ([A-z0-9_]+) -->/', '\' . $this->get_theme_hook(\'\\1\') . \'', $text);
  2783   
  2783 	
  2784   // only do this if the plugins API is loaded
  2784 	// only do this if the plugins API is loaded
  2785   if ( is_object(@$plugins) )
  2785 	if ( is_object(@$plugins) )
  2786   {
  2786 	{
  2787     $code = $plugins->setHook('template_compile_subst');
  2787 		$code = $plugins->setHook('template_compile_subst');
  2788     foreach ( $code as $cmd )
  2788 		foreach ( $code as $cmd )
  2789     {
  2789 		{
  2790       eval($cmd);
  2790 			eval($cmd);
  2791     }
  2791 		}
  2792   }
  2792 	}
  2793   
  2793 	
  2794   // Template variables
  2794 	// Template variables
  2795   $text = preg_replace('/\{([A-z0-9_-]+?)\}/is', '\' . $this->tpl_strings[\'\\1\'] . \'', $text);
  2795 	$text = preg_replace('/\{([A-z0-9_-]+?)\}/is', '\' . $this->tpl_strings[\'\\1\'] . \'', $text);
  2796   
  2796 	
  2797   // Reinsert PHP
  2797 	// Reinsert PHP
  2798   
  2798 	
  2799   foreach ( $php_matches[1] as $i => $match )
  2799 	foreach ( $php_matches[1] as $i => $match )
  2800   {
  2800 	{
  2801     // Substitute the random tag with the "real" PHP code
  2801 		// Substitute the random tag with the "real" PHP code
  2802     $tag = "{PHP:$i:$seed}";
  2802 		$tag = "{PHP:$i:$seed}";
  2803     $text = str_replace_once($tag, "'; $match echo '", $text);
  2803 		$text = str_replace_once($tag, "'; $match echo '", $text);
  2804   }
  2804 	}
  2805   
  2805 	
  2806   // echo('<pre>' . htmlspecialchars($text) . '</pre>');
  2806 	// echo('<pre>' . htmlspecialchars($text) . '</pre>');
  2807   
  2807 	
  2808   return $text;
  2808 	return $text;
  2809 }
  2809 }
  2810 
  2810 
  2811 /**
  2811 /**
  2812  * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
  2812  * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
  2813  *   - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
  2813  *   - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
  2818  * @access private
  2818  * @access private
  2819  */
  2819  */
  2820 
  2820 
  2821 class templateIndividual extends template
  2821 class templateIndividual extends template
  2822 {
  2822 {
  2823   var $tpl_strings, $tpl_bool, $tpl_code;
  2823 	var $tpl_strings, $tpl_bool, $tpl_code;
  2824   var $compiled = false;
  2824 	var $compiled = false;
  2825   /**
  2825 	/**
  2826    * Constructor.
  2826  	* Constructor.
  2827    */
  2827  	*/
  2828   function __construct($text)
  2828 	function __construct($text)
  2829   {
  2829 	{
  2830     global $db, $session, $paths, $template, $plugins; // Common objects
  2830 		global $db, $session, $paths, $template, $plugins; // Common objects
  2831     $this->tpl_code = $text;
  2831 		$this->tpl_code = $text;
  2832     $this->tpl_strings = $template->tpl_strings;
  2832 		$this->tpl_strings = $template->tpl_strings;
  2833     $this->tpl_bool = $template->tpl_bool;
  2833 		$this->tpl_bool = $template->tpl_bool;
  2834   }
  2834 	}
  2835   /**
  2835 	/**
  2836    * PHP 4 constructor. Deprecated in 1.1.x.
  2836  	* PHP 4 constructor. Deprecated in 1.1.x.
  2837    */
  2837  	*/
  2838   /*
  2838 	/*
  2839   function templateIndividual($text)
  2839 	function templateIndividual($text)
  2840   {
  2840 	{
  2841     $this->__construct($text);
  2841 		$this->__construct($text);
  2842   }
  2842 	}
  2843   */
  2843 	*/
  2844   
  2844 	
  2845   /**
  2845 	/**
  2846    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  2846  	* Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  2847    * @param $vars array
  2847  	* @param $vars array
  2848    */
  2848  	*/
  2849   
  2849 	
  2850   // We add the unused variable $from_internal here to silence "declaration should be compatible" errors
  2850 	// We add the unused variable $from_internal here to silence "declaration should be compatible" errors
  2851   function assign_vars($vars, $from_internal = false)
  2851 	function assign_vars($vars, $from_internal = false)
  2852   {
  2852 	{
  2853     $this->tpl_strings = array_merge($this->tpl_strings, $vars);
  2853 		$this->tpl_strings = array_merge($this->tpl_strings, $vars);
  2854   }
  2854 	}
  2855   
  2855 	
  2856   /**
  2856 	/**
  2857    * Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  2857  	* Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  2858    * @param $vars array
  2858  	* @param $vars array
  2859    */
  2859  	*/
  2860   
  2860 	
  2861   // We add the unused variable $from_internal here to silence "declaration should be compatible" errors
  2861 	// We add the unused variable $from_internal here to silence "declaration should be compatible" errors
  2862   function assign_bool($vars, $from_internal = false)
  2862 	function assign_bool($vars, $from_internal = false)
  2863   {
  2863 	{
  2864     $this->tpl_bool = array_merge($this->tpl_bool, $vars);
  2864 		$this->tpl_bool = array_merge($this->tpl_bool, $vars);
  2865   }
  2865 	}
  2866   
  2866 	
  2867   /**
  2867 	/**
  2868    * Compiles and executes the template code.
  2868  	* Compiles and executes the template code.
  2869    * @return string
  2869  	* @return string
  2870    */
  2870  	*/
  2871   function run()
  2871 	function run()
  2872   {
  2872 	{
  2873     global $db, $session, $paths, $template, $plugins; // Common objects
  2873 		global $db, $session, $paths, $template, $plugins; // Common objects
  2874     if(!$this->compiled)
  2874 		if(!$this->compiled)
  2875     {
  2875 		{
  2876       $this->tpl_code = $this->compile_template_text($this->tpl_code);
  2876 			$this->tpl_code = $this->compile_template_text($this->tpl_code);
  2877       $this->compiled = true;
  2877 			$this->compiled = true;
  2878     }
  2878 		}
  2879     return eval($this->tpl_code);
  2879 		return eval($this->tpl_code);
  2880   }
  2880 	}
  2881 }
  2881 }
  2882 
  2882 
  2883 /**
  2883 /**
  2884  * A version of the template compiler that does not rely at all on the other parts of Enano. Used during installation and for showing
  2884  * A version of the template compiler that does not rely at all on the other parts of Enano. Used during installation and for showing
  2885  * "critical error" messages. ** REQUIRES ** the Oxygen theme.
  2885  * "critical error" messages. ** REQUIRES ** the Oxygen theme.
  2886  */
  2886  */
  2887 
  2887 
  2888 class template_nodb
  2888 class template_nodb
  2889 {
  2889 {
  2890   var $fading_button, $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list;
  2890 	var $fading_button, $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list;
  2891   function __construct()
  2891 	function __construct()
  2892   {
  2892 	{
  2893     $this->tpl_bool    = Array();
  2893 		$this->tpl_bool    = Array();
  2894     $this->tpl_strings = Array();
  2894 		$this->tpl_strings = Array();
  2895     $this->sidebar_extra = '';
  2895 		$this->sidebar_extra = '';
  2896     $this->sidebar_widgets = '';
  2896 		$this->sidebar_widgets = '';
  2897     $this->toolbar_menu = '';
  2897 		$this->toolbar_menu = '';
  2898     $this->additional_headers = '<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>';
  2898 		$this->additional_headers = '<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>';
  2899     
  2899 		
  2900     $this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
  2900 		$this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
  2901                               <a href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
  2901 															<a href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
  2902                             </div>';
  2902 														</div>';
  2903     
  2903 		
  2904     // get list of themes
  2904 		// get list of themes
  2905     $this->theme_list = array();
  2905 		$this->theme_list = array();
  2906     $this->named_theme_list = array();
  2906 		$this->named_theme_list = array();
  2907     $order = 0;
  2907 		$order = 0;
  2908     
  2908 		
  2909     if ( $dir = @opendir( ENANO_ROOT . '/themes' ) )
  2909 		if ( $dir = @opendir( ENANO_ROOT . '/themes' ) )
  2910     {
  2910 		{
  2911       while ( $dh = @readdir($dir) )
  2911 			while ( $dh = @readdir($dir) )
  2912       {
  2912 			{
  2913         if ( $dh == '.' || $dh == '..' || !is_dir( ENANO_ROOT . "/themes/$dh" ) )
  2913 				if ( $dh == '.' || $dh == '..' || !is_dir( ENANO_ROOT . "/themes/$dh" ) )
  2914           continue;
  2914 					continue;
  2915         $theme_dir = ENANO_ROOT . "/themes/$dh";
  2915 				$theme_dir = ENANO_ROOT . "/themes/$dh";
  2916         if ( !file_exists("$theme_dir/theme.cfg") )
  2916 				if ( !file_exists("$theme_dir/theme.cfg") )
  2917           continue;
  2917 					continue;
  2918         $data = array(
  2918 				$data = array(
  2919             'theme_id' => $dh,
  2919 						'theme_id' => $dh,
  2920             'theme_name' => ucwords($dh),
  2920 						'theme_name' => ucwords($dh),
  2921             'enabled' => 1,
  2921 						'enabled' => 1,
  2922             'theme_order' => ++$order,
  2922 						'theme_order' => ++$order,
  2923             'default_style' => $this->get_default_style($dh)
  2923 						'default_style' => $this->get_default_style($dh)
  2924           );
  2924 					);
  2925         $this->named_theme_list[$dh] = $data;
  2925 				$this->named_theme_list[$dh] = $data;
  2926         $this->theme_list[] =& $this->named_theme_list[$dh];
  2926 				$this->theme_list[] =& $this->named_theme_list[$dh];
  2927       }
  2927 			}
  2928       @closedir($dir);
  2928 			@closedir($dir);
  2929     }
  2929 		}
  2930   }
  2930 	}
  2931   function template() {
  2931 	function template() {
  2932     $this->__construct();
  2932 		$this->__construct();
  2933   }
  2933 	}
  2934   function get_default_style($theme_id)
  2934 	function get_default_style($theme_id)
  2935   {
  2935 	{
  2936     if ( !is_dir( ENANO_ROOT . "/themes/$theme_id/css" ) )
  2936 		if ( !is_dir( ENANO_ROOT . "/themes/$theme_id/css" ) )
  2937       return false;
  2937 			return false;
  2938     $ds = false;
  2938 		$ds = false;
  2939     if ( $dh = @opendir( ENANO_ROOT . "/themes/$theme_id/css" ) )
  2939 		if ( $dh = @opendir( ENANO_ROOT . "/themes/$theme_id/css" ) )
  2940     {
  2940 		{
  2941       while ( $dir = @readdir($dh) )
  2941 			while ( $dir = @readdir($dh) )
  2942       {
  2942 			{
  2943         if ( !preg_match('/\.css$/', $dir) )
  2943 				if ( !preg_match('/\.css$/', $dir) )
  2944           continue;
  2944 					continue;
  2945         if ( $dir == '_printable.css' )
  2945 				if ( $dir == '_printable.css' )
  2946           continue;
  2946 					continue;
  2947         $ds = preg_replace('/\.css$/', '', $dir);
  2947 				$ds = preg_replace('/\.css$/', '', $dir);
  2948         break;
  2948 				break;
  2949       }
  2949 			}
  2950       closedir($dh);
  2950 			closedir($dh);
  2951     }
  2951 		}
  2952     else
  2952 		else
  2953     {
  2953 		{
  2954       return false;
  2954 			return false;
  2955     }
  2955 		}
  2956     return $ds;
  2956 		return $ds;
  2957   }
  2957 	}
  2958   function get_css($s = false)
  2958 	function get_css($s = false)
  2959   {
  2959 	{
  2960     if ( $s )
  2960 		if ( $s )
  2961       return $this->process_template('css/'.$s);
  2961 			return $this->process_template('css/'.$s);
  2962     else
  2962 		else
  2963       return $this->process_template('css/'.$this->style.'.css');
  2963 			return $this->process_template('css/'.$this->style.'.css');
  2964   }
  2964 	}
  2965   function load_theme($name, $css, $auto_init = true)
  2965 	function load_theme($name, $css, $auto_init = true)
  2966   {
  2966 	{
  2967     if ( !isset($this->named_theme_list[$name]) )
  2967 		if ( !isset($this->named_theme_list[$name]) )
  2968       $name = $this->theme_list[0]['theme_id'];
  2968 			$name = $this->theme_list[0]['theme_id'];
  2969     
  2969 		
  2970     if ( !file_exists(ENANO_ROOT . "/themes/$name/css/$css.css") )
  2970 		if ( !file_exists(ENANO_ROOT . "/themes/$name/css/$css.css") )
  2971       $css = $this->named_theme_list[$name]['default_style'];
  2971 			$css = $this->named_theme_list[$name]['default_style'];
  2972     
  2972 		
  2973     $this->theme = $name;
  2973 		$this->theme = $name;
  2974     $this->style = $css;
  2974 		$this->style = $css;
  2975     
  2975 		
  2976     $this->tpl_strings['SCRIPTPATH'] = scriptPath;
  2976 		$this->tpl_strings['SCRIPTPATH'] = scriptPath;
  2977     if ( $auto_init )
  2977 		if ( $auto_init )
  2978       $this->init_vars();
  2978 			$this->init_vars();
  2979   }
  2979 	}
  2980   function add_header($html)
  2980 	function add_header($html)
  2981   {
  2981 	{
  2982     $this->additional_headers .= "\n<!-- ----------------------------------------------------------- -->\n\n    " . $html;
  2982 		$this->additional_headers .= "\n<!-- ----------------------------------------------------------- -->\n\n    " . $html;
  2983   }
  2983 	}
  2984   function init_vars()
  2984 	function init_vars()
  2985   {
  2985 	{
  2986     global $sideinfo;
  2986 		global $sideinfo;
  2987     global $this_page;
  2987 		global $this_page;
  2988     global $lang;
  2988 		global $lang;
  2989     global $db, $session, $paths, $template, $plugins; // Common objects
  2989 		global $db, $session, $paths, $template, $plugins; // Common objects
  2990     $tplvars = $this->extract_vars('elements.tpl');
  2990 		$tplvars = $this->extract_vars('elements.tpl');
  2991     $tb = '';
  2991 		$tb = '';
  2992     // Get the "article" button text (depends on namespace)
  2992 		// Get the "article" button text (depends on namespace)
  2993     if(defined('IN_ENANO_INSTALL') && is_object($lang)) $ns = $lang->get('meta_btn_article');
  2993 		if(defined('IN_ENANO_INSTALL') && is_object($lang)) $ns = $lang->get('meta_btn_article');
  2994     else if ( isset($GLOBALS['article_btn']) ) $ns = $GLOBALS['article_btn'];
  2994 		else if ( isset($GLOBALS['article_btn']) ) $ns = $GLOBALS['article_btn'];
  2995     else $ns = 'system error page';
  2995 		else $ns = 'system error page';
  2996     $t = str_replace('{FLAGS}', 'onclick="return false;" class="current" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
  2996 		$t = str_replace('{FLAGS}', 'onclick="return false;" class="current" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
  2997     $t = str_replace('{HREF}', '#', $t);
  2997 		$t = str_replace('{HREF}', '#', $t);
  2998     $t = str_replace('{TEXT}', $ns, $t);
  2998 		$t = str_replace('{TEXT}', $ns, $t);
  2999     $tb .= $t;
  2999 		$tb .= $t;
  3000     
  3000 		
  3001     // Page toolbar
  3001 		// Page toolbar
  3002     
  3002 		
  3003     $this->tpl_bool = Array(
  3003 		$this->tpl_bool = Array(
  3004       'auth_admin'=>true,
  3004 			'auth_admin'=>true,
  3005       'user_logged_in'=>true,
  3005 			'user_logged_in'=>true,
  3006       'right_sidebar'=>false,
  3006 			'right_sidebar'=>false,
  3007       );
  3007 			);
  3008     $this->tpl_bool['in_sidebar_admin'] = false;
  3008 		$this->tpl_bool['in_sidebar_admin'] = false;
  3009     
  3009 		
  3010     $this->tpl_bool['auth_rename'] = false;
  3010 		$this->tpl_bool['auth_rename'] = false;
  3011     
  3011 		
  3012     $asq = $asa = '';
  3012 		$asq = $asa = '';
  3013     
  3013 		
  3014     $this->tpl_bool['fixed_menus'] = false;
  3014 		$this->tpl_bool['fixed_menus'] = false;
  3015     $slink = defined('IN_ENANO_INSTALL') ? scriptPath.'/install.php?mode=css' : makeUrlNS('Special', 'CSS');
  3015 		$slink = defined('IN_ENANO_INSTALL') ? scriptPath.'/install.php?mode=css' : makeUrlNS('Special', 'CSS');
  3016     
  3016 		
  3017     $title = ( is_object($paths) ) ? $paths->page : 'Critical error';
  3017 		$title = ( is_object($paths) ) ? $paths->page : 'Critical error';
  3018     
  3018 		
  3019     $headers = '<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>';
  3019 		$headers = '<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>';
  3020     
  3020 		
  3021     $js_dynamic = '';
  3021 		$js_dynamic = '';
  3022     if ( defined('IN_ENANO_INSTALL') )
  3022 		if ( defined('IN_ENANO_INSTALL') )
  3023     {
  3023 		{
  3024       $js_dynamic .= '<script type="text/javascript" src="install.php?mode=langjs"></script>';
  3024 			$js_dynamic .= '<script type="text/javascript" src="install.php?mode=langjs"></script>';
  3025     }
  3025 		}
  3026     $js_dynamic .= '<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var cdnPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\'; var ENANO_LANG_ID = 1; var enano_version = \'' . enano_version() . '\'; var msg_loading_component = \'Loading %component%...\';</script>';
  3026 		$js_dynamic .= '<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var cdnPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\'; var ENANO_LANG_ID = 1; var enano_version = \'' . enano_version() . '\'; var msg_loading_component = \'Loading %component%...\';</script>';
  3027     
  3027 		
  3028     global $site_name, $site_desc;
  3028 		global $site_name, $site_desc;
  3029     $site_default_name = ( !empty($site_name) ) ? $site_name : 'Critical error';
  3029 		$site_default_name = ( !empty($site_name) ) ? $site_name : 'Critical error';
  3030     $site_default_desc = ( !empty($site_desc) ) ? $site_desc : 'This site is experiencing a problem and cannot load.';
  3030 		$site_default_desc = ( !empty($site_desc) ) ? $site_desc : 'This site is experiencing a problem and cannot load.';
  3031     
  3031 		
  3032     $site_name_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_name') : $site_default_name;
  3032 		$site_name_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_name') : $site_default_name;
  3033     $site_desc_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_desc') : $site_default_desc;
  3033 		$site_desc_final = ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_desc') : $site_default_desc;
  3034     
  3034 		
  3035     // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
  3035 		// The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
  3036     $tpl_strings = Array(
  3036 		$tpl_strings = Array(
  3037       'PAGE_NAME'=>$this_page,
  3037 			'PAGE_NAME'=>$this_page,
  3038       'PAGE_URLNAME'=>'Null',
  3038 			'PAGE_URLNAME'=>'Null',
  3039       'SITE_NAME' => $site_name_final,
  3039 			'SITE_NAME' => $site_name_final,
  3040       'USERNAME'=>'admin',
  3040 			'USERNAME'=>'admin',
  3041       'SITE_DESC' => $site_desc_final,
  3041 			'SITE_DESC' => $site_desc_final,
  3042       'TOOLBAR'=>$tb,
  3042 			'TOOLBAR'=>$tb,
  3043       'SCRIPTPATH'=>scriptPath,
  3043 			'SCRIPTPATH'=>scriptPath,
  3044       'CONTENTPATH'=>contentPath,
  3044 			'CONTENTPATH'=>contentPath,
  3045       'CDNPATH' => scriptPath,
  3045 			'CDNPATH' => scriptPath,
  3046       'JS_HEADER' => '<script type="text/javascript" src="' . scriptPath . '/includes/clientside/static/enano-lib-basic.js"></script>',
  3046 			'JS_HEADER' => '<script type="text/javascript" src="' . scriptPath . '/includes/clientside/static/enano-lib-basic.js"></script>',
  3047       'JS_FOOTER' => '',
  3047 			'JS_FOOTER' => '',
  3048       'ADMIN_SID_QUES'=>$asq,
  3048 			'ADMIN_SID_QUES'=>$asq,
  3049       'ADMIN_SID_AMP'=>$asa,
  3049 			'ADMIN_SID_AMP'=>$asa,
  3050       'ADMIN_SID_AMP_HTML'=>'',
  3050 			'ADMIN_SID_AMP_HTML'=>'',
  3051       'ADDITIONAL_HEADERS'=>$this->additional_headers,
  3051 			'ADDITIONAL_HEADERS'=>$this->additional_headers,
  3052       'SIDEBAR_EXTRA'=>'',
  3052 			'SIDEBAR_EXTRA'=>'',
  3053       'COPYRIGHT'=>( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_enano_copyright') : ( defined('ENANO_CONFIG_FETCHED') ? getConfig('copyright_notice') : '' ),
  3053 			'COPYRIGHT'=>( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_enano_copyright') : ( defined('ENANO_CONFIG_FETCHED') ? getConfig('copyright_notice') : '' ),
  3054       'TOOLBAR_EXTRAS'=>'',
  3054 			'TOOLBAR_EXTRAS'=>'',
  3055       'REQUEST_URI'=>( isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '' ).$_SERVER['REQUEST_URI'],
  3055 			'REQUEST_URI'=>( isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '' ).$_SERVER['REQUEST_URI'],
  3056       'STYLE_LINK'=>$slink,
  3056 			'STYLE_LINK'=>$slink,
  3057       'LOGOUT_LINK'=>'',
  3057 			'LOGOUT_LINK'=>'',
  3058       'THEME_LINK'=>'',
  3058 			'THEME_LINK'=>'',
  3059       'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
  3059 			'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
  3060       'THEME_ID'=>$this->theme,
  3060 			'THEME_ID'=>$this->theme,
  3061       'STYLE_ID'=>$this->style,
  3061 			'STYLE_ID'=>$this->style,
  3062       'JS_DYNAMIC_VARS'=>$js_dynamic,
  3062 			'JS_DYNAMIC_VARS'=>$js_dynamic,
  3063       'SIDEBAR_RIGHT'=>'',
  3063 			'SIDEBAR_RIGHT'=>'',
  3064       'REPORT_URI' => '',
  3064 			'REPORT_URI' => '',
  3065       'URL_ABOUT_ENANO' => 'http://enanocms.org/',
  3065 			'URL_ABOUT_ENANO' => 'http://enanocms.org/',
  3066       'ENANO_VERSION' => enano_version()
  3066 			'ENANO_VERSION' => enano_version()
  3067       );
  3067 			);
  3068     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
  3068 		$this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
  3069     
  3069 		
  3070     $sidebar = ( is_array(@$sideinfo) ) ? $sideinfo : '';
  3070 		$sidebar = ( is_array(@$sideinfo) ) ? $sideinfo : '';
  3071     if ( $sidebar != '' )
  3071 		if ( $sidebar != '' )
  3072     {
  3072 		{
  3073       if ( isset($tplvars['sidebar_top']) )
  3073 			if ( isset($tplvars['sidebar_top']) )
  3074       {
  3074 			{
  3075         $text = $this->makeParserText($tplvars['sidebar_top']);
  3075 				$text = $this->makeParserText($tplvars['sidebar_top']);
  3076         $top = $text->run();
  3076 				$top = $text->run();
  3077       }
  3077 			}
  3078       else
  3078 			else
  3079       {
  3079 			{
  3080         $top = '';
  3080 				$top = '';
  3081       }
  3081 			}
  3082       
  3082 			
  3083       $p = $this->makeParserText($tplvars['sidebar_section']);
  3083 			$p = $this->makeParserText($tplvars['sidebar_section']);
  3084       $b = $this->makeParserText($tplvars['sidebar_button']);
  3084 			$b = $this->makeParserText($tplvars['sidebar_button']);
  3085       $sidebar_text = '';
  3085 			$sidebar_text = '';
  3086       
  3086 			
  3087       foreach ( $sidebar as $title => $links )
  3087 			foreach ( $sidebar as $title => $links )
  3088       {
  3088 			{
  3089         $p->assign_vars(array(
  3089 				$p->assign_vars(array(
  3090           'TITLE' => $title
  3090 					'TITLE' => $title
  3091         ));
  3091 				));
  3092         // build content
  3092 				// build content
  3093         $content = '';
  3093 				$content = '';
  3094         foreach ( $links as $link_text => $url )
  3094 				foreach ( $links as $link_text => $url )
  3095         {
  3095 				{
  3096           $b->assign_vars(array(
  3096 					$b->assign_vars(array(
  3097             'HREF' => htmlspecialchars($url),
  3097 						'HREF' => htmlspecialchars($url),
  3098             'FLAGS' => '',
  3098 						'FLAGS' => '',
  3099             'TEXT' => $link_text
  3099 						'TEXT' => $link_text
  3100           ));
  3100 					));
  3101           $content .= $b->run();
  3101 					$content .= $b->run();
  3102         }
  3102 				}
  3103         $p->assign_vars(array(
  3103 				$p->assign_vars(array(
  3104           'CONTENT' => $content
  3104 					'CONTENT' => $content
  3105         ));
  3105 				));
  3106         $sidebar_text .= $p->run();
  3106 				$sidebar_text .= $p->run();
  3107       }
  3107 			}
  3108       
  3108 			
  3109       if ( isset($tplvars['sidebar_bottom']) )
  3109 			if ( isset($tplvars['sidebar_bottom']) )
  3110       {
  3110 			{
  3111         $text = $this->makeParserText($tplvars['sidebar_bottom']);
  3111 				$text = $this->makeParserText($tplvars['sidebar_bottom']);
  3112         $bottom = $text->run();
  3112 				$bottom = $text->run();
  3113       }
  3113 			}
  3114       else
  3114 			else
  3115       {
  3115 			{
  3116         $bottom = '';
  3116 				$bottom = '';
  3117       }
  3117 			}
  3118       $sidebar = $top . $sidebar_text . $bottom;
  3118 			$sidebar = $top . $sidebar_text . $bottom;
  3119     }
  3119 		}
  3120     $this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
  3120 		$this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
  3121     
  3121 		
  3122     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != '') ? true : false;
  3122 		$this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != '') ? true : false;
  3123     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
  3123 		$this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
  3124     $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
  3124 		$this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
  3125     $this->tpl_bool['stupid_mode'] = true;
  3125 		$this->tpl_bool['stupid_mode'] = true;
  3126   }
  3126 	}
  3127   function header($simple = false) 
  3127 	function header($simple = false) 
  3128   {
  3128 	{
  3129     $filename = ( $simple ) ? 'simple-header.tpl' : 'header.tpl';
  3129 		$filename = ( $simple ) ? 'simple-header.tpl' : 'header.tpl';
  3130     if ( !$this->no_headers )
  3130 		if ( !$this->no_headers )
  3131     {
  3131 		{
  3132       echo $this->process_template($filename);
  3132 			echo $this->process_template($filename);
  3133     }
  3133 		}
  3134   }
  3134 	}
  3135   function footer($simple = false)
  3135 	function footer($simple = false)
  3136   {
  3136 	{
  3137     global $db, $session, $paths, $template, $plugins; // Common objects
  3137 		global $db, $session, $paths, $template, $plugins; // Common objects
  3138     global $lang;
  3138 		global $lang;
  3139     
  3139 		
  3140     if(!$this->no_headers) {
  3140 		if(!$this->no_headers) {
  3141       global $_starttime;
  3141 			global $_starttime;
  3142       
  3142 			
  3143       $filename = ( $simple ) ? 'simple-footer.tpl' : 'footer.tpl';
  3143 			$filename = ( $simple ) ? 'simple-footer.tpl' : 'footer.tpl';
  3144       $t = $this->process_template($filename);
  3144 			$t = $this->process_template($filename);
  3145       
  3145 			
  3146       $f = microtime_float();
  3146 			$f = microtime_float();
  3147       $f = $f - $_starttime;
  3147 			$f = $f - $_starttime;
  3148       $f = round($f, 4);
  3148 			$f = round($f, 4);
  3149       
  3149 			
  3150       if ( is_object($lang) )
  3150 			if ( is_object($lang) )
  3151       {
  3151 			{
  3152         $t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
  3152 				$t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
  3153         $t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
  3153 				$t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
  3154         $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => ( is_object($db) ? $db->num_queries : 'N/A' ))) . '</a>';
  3154 				$q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => ( is_object($db) ? $db->num_queries : 'N/A' ))) . '</a>';
  3155         $dbg = $t_loc;
  3155 				$dbg = $t_loc;
  3156         $dbg_long = $t_loc_long;
  3156 				$dbg_long = $t_loc_long;
  3157         if ( $session->user_level >= USER_LEVEL_ADMIN )
  3157 				if ( $session->user_level >= USER_LEVEL_ADMIN )
  3158         {
  3158 				{
  3159           $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3159 					$dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3160           $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3160 					$dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3161         }
  3161 				}
  3162         $t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  3162 				$t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  3163         $t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  3163 				$t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
  3164       }
  3164 			}
  3165       else
  3165 			else
  3166       {
  3166 			{
  3167         $t_loc = "Time: {$f}s";
  3167 				$t_loc = "Time: {$f}s";
  3168         $t_loc_long = "Generated in {$f}sec";
  3168 				$t_loc_long = "Generated in {$f}sec";
  3169         $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . ( is_object($db) ? "{$db->num_queries} SQL" : 'Queries: N/A' ) . '</a>';
  3169 				$q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . ( is_object($db) ? "{$db->num_queries} SQL" : 'Queries: N/A' ) . '</a>';
  3170         $dbg = $t_loc;
  3170 				$dbg = $t_loc;
  3171         $dbg_long = $t_loc_long;
  3171 				$dbg_long = $t_loc_long;
  3172         if ( is_object($session) )
  3172 				if ( is_object($session) )
  3173         {
  3173 				{
  3174           if ( $session->user_level >= USER_LEVEL_ADMIN )
  3174 					if ( $session->user_level >= USER_LEVEL_ADMIN )
  3175           {
  3175 					{
  3176             $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3176 						$dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3177             $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3177 						$dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
  3178           }
  3178 					}
  3179         }
  3179 				}
  3180         $t = str_replace('[[EnanoPoweredLink]]', 'Powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
  3180 				$t = str_replace('[[EnanoPoweredLink]]', 'Powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
  3181         $t = str_replace('[[EnanoPoweredLinkLong]]', 'Website engine powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
  3181 				$t = str_replace('[[EnanoPoweredLinkLong]]', 'Website engine powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
  3182       }
  3182 			}
  3183       
  3183 			
  3184       $t = str_replace('[[Stats]]', $dbg, $t);
  3184 			$t = str_replace('[[Stats]]', $dbg, $t);
  3185       $t = str_replace('[[StatsLong]]', $dbg_long, $t);
  3185 			$t = str_replace('[[StatsLong]]', $dbg_long, $t);
  3186       $t = str_replace('[[NumQueries]]', ( is_object($db) ? (string)$db->num_queries : '0' ), $t);
  3186 			$t = str_replace('[[NumQueries]]', ( is_object($db) ? (string)$db->num_queries : '0' ), $t);
  3187       $t = str_replace('[[GenTime]]', (string)$f, $t);
  3187 			$t = str_replace('[[GenTime]]', (string)$f, $t);
  3188       $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  3188 			$t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
  3189       $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  3189 			$t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
  3190       
  3190 			
  3191       if ( defined('ENANO_PROFILE') )
  3191 			if ( defined('ENANO_PROFILE') )
  3192       {
  3192 			{
  3193         $t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
  3193 				$t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
  3194       }
  3194 			}
  3195       
  3195 			
  3196       echo $t;
  3196 			echo $t;
  3197     }
  3197 		}
  3198     else return '';
  3198 		else return '';
  3199   }
  3199 	}
  3200   function getHeader()
  3200 	function getHeader()
  3201   {
  3201 	{
  3202     if(!$this->no_headers) return $this->process_template('header.tpl');
  3202 		if(!$this->no_headers) return $this->process_template('header.tpl');
  3203     else return '';
  3203 		else return '';
  3204   }
  3204 	}
  3205   function getFooter()
  3205 	function getFooter()
  3206   {
  3206 	{
  3207     global $db, $session, $paths, $template, $plugins; // Common objects
  3207 		global $db, $session, $paths, $template, $plugins; // Common objects
  3208     if(!$this->no_headers) {
  3208 		if(!$this->no_headers) {
  3209       global $_starttime;
  3209 			global $_starttime;
  3210       $f = microtime(true);
  3210 			$f = microtime(true);
  3211       $f = $f - $_starttime;
  3211 			$f = $f - $_starttime;
  3212       $f = round($f, 4);
  3212 			$f = round($f, 4);
  3213       if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
  3213 			if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
  3214       else $nq = $db->num_queries;
  3214 			else $nq = $db->num_queries;
  3215       if($nq == 0) $nq = 'N/A';
  3215 			if($nq == 0) $nq = 'N/A';
  3216       $dbg = 'Time: '.$f.'s  |  Queries: '.$nq;
  3216 			$dbg = 'Time: '.$f.'s  |  Queries: '.$nq;
  3217       if($nq == 0) $nq = 'N/A';
  3217 			if($nq == 0) $nq = 'N/A';
  3218       $t = $this->process_template('footer.tpl');
  3218 			$t = $this->process_template('footer.tpl');
  3219       $t = str_replace('[[Stats]]', $dbg, $t);
  3219 			$t = str_replace('[[Stats]]', $dbg, $t);
  3220       return $t;
  3220 			return $t;
  3221     }
  3221 		}
  3222     else return '';
  3222 		else return '';
  3223   }
  3223 	}
  3224   
  3224 	
  3225   function process_template($file)
  3225 	function process_template($file)
  3226   {
  3226 	{
  3227     $compiled = $this->compile_template($file);
  3227 		$compiled = $this->compile_template($file);
  3228     $result = eval($compiled);
  3228 		$result = eval($compiled);
  3229     return $result;
  3229 		return $result;
  3230   }
  3230 	}
  3231   
  3231 	
  3232   function extract_vars($file) {
  3232 	function extract_vars($file) {
  3233     global $db, $session, $paths, $template, $plugins; // Common objects
  3233 		global $db, $session, $paths, $template, $plugins; // Common objects
  3234     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
  3234 		if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
  3235     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
  3235 		$text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
  3236     preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
  3236 		preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
  3237     $tplvars = Array();
  3237 		$tplvars = Array();
  3238     for($i=0;$i<sizeof($matches[1]);$i++)
  3238 		for($i=0;$i<sizeof($matches[1]);$i++)
  3239     {
  3239 		{
  3240       $tplvars[$matches[1][$i]] = $matches[2][$i];
  3240 			$tplvars[$matches[1][$i]] = $matches[2][$i];
  3241     }
  3241 		}
  3242     return $tplvars;
  3242 		return $tplvars;
  3243   }
  3243 	}
  3244   function compile_template($text)
  3244 	function compile_template($text)
  3245   {
  3245 	{
  3246     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
  3246 		$text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
  3247     return $this->compile_template_text_post(template_compiler_core($text));
  3247 		return $this->compile_template_text_post(template_compiler_core($text));
  3248   }
  3248 	}
  3249   
  3249 	
  3250   function compile_template_text($text)
  3250 	function compile_template_text($text)
  3251   {
  3251 	{
  3252     return $this->compile_template_text_post(template_compiler_core($text));
  3252 		return $this->compile_template_text_post(template_compiler_core($text));
  3253   }
  3253 	}
  3254   
  3254 	
  3255   /**
  3255 	/**
  3256    * Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
  3256  	* Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
  3257    * @param string Mostly-processed TPL code
  3257  	* @param string Mostly-processed TPL code
  3258    * @return string
  3258  	* @return string
  3259    */
  3259  	*/
  3260   
  3260 	
  3261   function compile_template_text_post($text)
  3261 	function compile_template_text_post($text)
  3262   {
  3262 	{
  3263     global $lang;
  3263 		global $lang;
  3264     preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
  3264 		preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
  3265     foreach ( $matches[1] as $i => $string_id )
  3265 		foreach ( $matches[1] as $i => $string_id )
  3266     {
  3266 		{
  3267       if ( is_object(@$lang) )
  3267 			if ( is_object(@$lang) )
  3268       {
  3268 			{
  3269         $string = $lang->get($string_id);
  3269 				$string = $lang->get($string_id);
  3270       }
  3270 			}
  3271       else
  3271 			else
  3272       {
  3272 			{
  3273         $string = '[language not loaded]';
  3273 				$string = '[language not loaded]';
  3274       }
  3274 			}
  3275       $string = str_replace('\\', '\\\\', $string);
  3275 			$string = str_replace('\\', '\\\\', $string);
  3276       $string = str_replace('\'', '\\\'', $string);
  3276 			$string = str_replace('\'', '\\\'', $string);
  3277       $text = str_replace_once($matches[0][$i], $string, $text);
  3277 			$text = str_replace_once($matches[0][$i], $string, $text);
  3278     }
  3278 		}
  3279     return $text;
  3279 		return $text;
  3280   }
  3280 	}
  3281   
  3281 	
  3282   /**
  3282 	/**
  3283    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  3283  	* Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
  3284    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  3284  	* Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
  3285    * @param $filename the filename of the template to be parsed
  3285  	* @param $filename the filename of the template to be parsed
  3286    * @return object
  3286  	* @return object
  3287    */
  3287  	*/
  3288    
  3288  	
  3289   function makeParser($filename)
  3289 	function makeParser($filename)
  3290   {
  3290 	{
  3291     $filename = ENANO_ROOT.'/themes/'.$this->theme.'/'.$filename;
  3291 		$filename = ENANO_ROOT.'/themes/'.$this->theme.'/'.$filename;
  3292     if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
  3292 		if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
  3293     $code = file_get_contents($filename);
  3293 		$code = file_get_contents($filename);
  3294     $parser = new templateIndividualSafe($code, $this);
  3294 		$parser = new templateIndividualSafe($code, $this);
  3295     return $parser;
  3295 		return $parser;
  3296   }
  3296 	}
  3297   
  3297 	
  3298   /**
  3298 	/**
  3299    * Same as $template->makeParser(), but takes a string instead of a filename.
  3299  	* Same as $template->makeParser(), but takes a string instead of a filename.
  3300    * @param $text the text to parse
  3300  	* @param $text the text to parse
  3301    * @return object
  3301  	* @return object
  3302    */
  3302  	*/
  3303    
  3303  	
  3304   function makeParserText($code)
  3304 	function makeParserText($code)
  3305   {
  3305 	{
  3306     $parser = new templateIndividualSafe($code, $this);
  3306 		$parser = new templateIndividualSafe($code, $this);
  3307     return $parser;
  3307 		return $parser;
  3308   }
  3308 	}
  3309   
  3309 	
  3310   /**
  3310 	/**
  3311    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  3311  	* Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  3312    * @param $vars array
  3312  	* @param $vars array
  3313    */
  3313  	*/
  3314   function assign_vars($vars, $_ignored = false)
  3314 	function assign_vars($vars, $_ignored = false)
  3315   {
  3315 	{
  3316     if(is_array($this->tpl_strings))
  3316 		if(is_array($this->tpl_strings))
  3317       $this->tpl_strings = array_merge($this->tpl_strings, $vars);
  3317 			$this->tpl_strings = array_merge($this->tpl_strings, $vars);
  3318     else
  3318 		else
  3319       $this->tpl_strings = $vars;
  3319 			$this->tpl_strings = $vars;
  3320   }
  3320 	}
  3321   
  3321 	
  3322   function get_theme_hook()
  3322 	function get_theme_hook()
  3323   {
  3323 	{
  3324     return '';
  3324 		return '';
  3325   }
  3325 	}
  3326    
  3326  	
  3327 } // class template_nodb
  3327 } // class template_nodb
  3328 
  3328 
  3329 /**
  3329 /**
  3330  * Identical to templateIndividual, except extends template_nodb instead of template
  3330  * Identical to templateIndividual, except extends template_nodb instead of template
  3331  * @see class template
  3331  * @see class template
  3332  */
  3332  */
  3333  
  3333  
  3334 class templateIndividualSafe extends template_nodb
  3334 class templateIndividualSafe extends template_nodb
  3335 {
  3335 {
  3336   var $tpl_strings, $tpl_bool, $tpl_code;
  3336 	var $tpl_strings, $tpl_bool, $tpl_code;
  3337   var $compiled = false;
  3337 	var $compiled = false;
  3338   /**
  3338 	/**
  3339    * Constructor.
  3339  	* Constructor.
  3340    */
  3340  	*/
  3341   function __construct($text, $parent)
  3341 	function __construct($text, $parent)
  3342   {
  3342 	{
  3343     global $db, $session, $paths, $template, $plugins; // Common objects
  3343 		global $db, $session, $paths, $template, $plugins; // Common objects
  3344     $this->tpl_code = $text;
  3344 		$this->tpl_code = $text;
  3345     $this->tpl_strings = $parent->tpl_strings;
  3345 		$this->tpl_strings = $parent->tpl_strings;
  3346     $this->tpl_bool = $parent->tpl_bool;
  3346 		$this->tpl_bool = $parent->tpl_bool;
  3347   }
  3347 	}
  3348   /**
  3348 	/**
  3349    * PHP 4 constructor.
  3349  	* PHP 4 constructor.
  3350    */
  3350  	*/
  3351   function templateIndividual($text)
  3351 	function templateIndividual($text)
  3352   {
  3352 	{
  3353     $this->__construct($text);
  3353 		$this->__construct($text);
  3354   }
  3354 	}
  3355   /**
  3355 	/**
  3356    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  3356  	* Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
  3357    * @param $vars array
  3357  	* @param $vars array
  3358    */
  3358  	*/
  3359   function assign_vars($vars, $_ignored = false)
  3359 	function assign_vars($vars, $_ignored = false)
  3360   {
  3360 	{
  3361     if(is_array($this->tpl_strings))
  3361 		if(is_array($this->tpl_strings))
  3362       $this->tpl_strings = array_merge($this->tpl_strings, $vars);
  3362 			$this->tpl_strings = array_merge($this->tpl_strings, $vars);
  3363     else
  3363 		else
  3364       $this->tpl_strings = $vars;
  3364 			$this->tpl_strings = $vars;
  3365   }
  3365 	}
  3366   /**
  3366 	/**
  3367    * Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  3367  	* Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
  3368    * @param $vars array
  3368  	* @param $vars array
  3369    */
  3369  	*/
  3370   function assign_bool($vars)
  3370 	function assign_bool($vars)
  3371   {
  3371 	{
  3372     $this->tpl_bool = array_merge($this->tpl_bool, $vars);
  3372 		$this->tpl_bool = array_merge($this->tpl_bool, $vars);
  3373   }
  3373 	}
  3374   /**
  3374 	/**
  3375    * Compiles and executes the template code.
  3375  	* Compiles and executes the template code.
  3376    * @return string
  3376  	* @return string
  3377    */
  3377  	*/
  3378   function run()
  3378 	function run()
  3379   {
  3379 	{
  3380     global $db, $session, $paths, $template, $plugins; // Common objects
  3380 		global $db, $session, $paths, $template, $plugins; // Common objects
  3381     if(!$this->compiled)
  3381 		if(!$this->compiled)
  3382     {
  3382 		{
  3383       $this->tpl_code = $this->compile_template_text($this->tpl_code);
  3383 			$this->tpl_code = $this->compile_template_text($this->tpl_code);
  3384       $this->compiled = true;
  3384 			$this->compiled = true;
  3385     }
  3385 		}
  3386     return eval($this->tpl_code);
  3386 		return eval($this->tpl_code);
  3387   }
  3387 	}
  3388 }
  3388 }
  3389 
  3389 
  3390 ?>
  3390 ?>