]> git.vanrenterghem.biz Git - www.vanrenterghem.biz.git/blob - phpBB2_old/includes/template.php
Add link to photos section.
[www.vanrenterghem.biz.git] / phpBB2_old / includes / template.php
1 <?php
3 /***************************************************************************
4  *                               template.php
5  *                            ------------------
6  *   copyright            : (C) 2001 The phpBB Group
7  *   email                : support@phpbb.com
8  *
9  *   phpBB version        : 2.0.x
10  *   eXtreme Styles mod   : 2.0.1
11  *   Support              : http://www.phpbbstyles.com
12  *
13  *   file revision        : 48
14  *   project revision     : 51
15  *   last modified        : 25 Aug 2004  11:51:47
16  *
17  ***************************************************************************/
19 /***************************************************************************
20  *
21  *   This program is free software; you can redistribute it and/or modify
22  *   it under the terms of the GNU General Public License as published by
23  *   the Free Software Foundation; either version 2 of the License, or
24  *   (at your option) any later version.
25  *
26  ***************************************************************************/
28 /**
29  *
30  * Template class. By Nathan Codding of the phpBB group.
31  * The interface was originally inspired by PHPLib templates,
32  * and the template file formats are quite similar.
33  *
34  * eXtreme Styles mod by CyberAlien.
35  *
36  * IF, ELSEIF, ENDIF tags are backported from phpBB 2.2
37  *
38  * Documentation for this mod can be found here:
39  * http://www.phpbbstyles.com
40  *
41  * Support for eXtreme Styles mod is provided at http://www.phpbbstyles.com
42  *
43  * Thanks to DMaJ007 for idea on how to include some extra tags.
44  *
45  */
47 define('XS_SEPARATOR', '.');
48 define('XS_DIR_CACHE', 'cache');
49 define('XS_USE_ISSET', '1');
51 // cache filenames prefix
52 define('XS_TPL_PREFIX', 'tpl_');
53 define('XS_TPL_PREFIX2', 'tpl2_');
55 // templates directory
56 define('XS_TPL_START', 'templates/');
57 define('XS_TPL_ANY', '/templates/');
59 // internal xs mod definitions. do not edit.
60 define('XS_TAG_NONE', 0);
61 define('XS_TAG_PHP', 1);
62 define('XS_TAG_BEGIN', 2);
63 define('XS_TAG_END', 3);
64 define('XS_TAG_INCLUDE', 4);
65 define('XS_TAG_IF', 5);
66 define('XS_TAG_ELSE', 6);
67 define('XS_TAG_ELSEIF', 7);
68 define('XS_TAG_ENDIF', 8);
69 define('XS_TAG_DEFINE', 9);
70 define('XS_TAG_UNDEFINE', 10);
73 class Template {
74         var $classname = "Template";
76         // variable that holds all the data we'll be substituting into
77         // the compiled templates.
78         // ...
79         // This will end up being a multi-dimensional array like this:
80         // $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value
81         // if it's a root-level variable, it'll be like this:
82         // $this->vars[varname] == value  or  $this->_tpldata['.'][0][varname] == value
83         // array "vars" is added for easier access to data
84         var $_tpldata = array('.' => array(0 => array()));
85         var $vars;
87         // Hash of filenames for each template handle.
88         var $files = array();
89         var $files_cache = array(); // array of cache files that exists
90         var $files_cache2 = array(); // array of cache files (exists or not exists)
92         // Root template directory.
93         var $root = '';
95         // Cache directory (compatible with default cache mod)
96         var $cachedir = '';
98         // Search/replace for unknown files
99         var $cache_search = array();
100         var $cache_replace = array();
102         // Template root directory (generated by set_rootdir)
103         var $tpldir = '';
104         var $tpldir_len = 0;
106         // Default template directory.
107         // If file for default template isn't found file from this template is used.
108         var $tpldef = 'subSilver';
110         // this will hash handle names to the compiled code for that handle.
111         var $compiled_code = array();
113         // This will hold the uncompiled code for that handle.
114         var $uncompiled_code = array();
116         // Cache settings
117         var $use_cache = 1;
118         var $cache_writable = 1;
120         // Auto-compile setting
121         var $auto_compile = 1;
123         // Current template name
124         var $tpl = '';
126         // List of replacements. tpl files in this list will be replaced with other tpl files
127         // according to configuration in xs.cfg
128         var $replace = array();
130         // counter for include
131         var $include_count = 0;
133         // php extension. will be replaced by $phpEx in Template() function unless you disable it there
134         var $php = 'php';
136         // True if check switches
137         var $xs_check_switches = 1;
139         // eXtreme Styles variables
140         var $xs_started = 0;
141         var $xs_version = 5; // number version. internal. do not change.
142         var $xs_versiontxt = '2.0.1'; // text version
144         // These handles will be parsed if pparse() is executed.
145         // Can be used to automatically include header/footer if there is any content.
146         var $preparse = '';
147         var $postparse = '';
149         // subtemplates mod detection
150         var $subtemplates = false;
152         // list of switches that are known typos in some mods.
153         // when error checking is enabled these errors will be auto-fixed.
154         // format:
155         //  array(start_tag, end_tag)
156         var $bugs = array(
157                 // ezportal typo:
158                 array('fetchpost_row', 'fetch_post_row'),
159                 // mycalendar 2.2.7 typos:
160                 array('date_cell', 'date_cells'),
161                 array('date_row', 'date_rows'),
162                 // history mod typo:
163                 array('site_today', 'site_week'),
164                 );
166         /**
167          * Constructor. Installs XS mod on first run or updates it and sets the root dir.
168          */
169         function Template($root = '.')
170         {
171                 // setting pointer "vars"
172                 $this->vars = &$this->_tpldata['.'][0];
173                 // load configuration
174                 $this->load_config($root, true);
175         }
177         /**
178          * Load mod configuration
179          */
180         function load_config($root, $edit_db)
181         {
182                 global $board_config, $phpbb_root_path, $phpEx;
183                 // getting mod version from config and comparing with real data
184                 $ver = isset($board_config['xs_version']) ? $board_config['xs_version'] : 0;
185                 // check configuration
186                 // set config values if there aren't any
187                 $add = array();
188                 $del = array();
189                 $up = array();
190                 // list of outdated variables
191                 $outdated = array(
192                         'xs_versoin',   // was a typo in one of previous versions
193                         'xs_separator', // no longer used
194                         'xs_cache_dir_absolute',        // no longer used
195                         'xs_cache_dir', // no longer used
196                         'xs_use_isset', // no longer used
197                         );
198                 // list of default values
199                 $default = array(
200                         'xs_auto_compile'                       => 1,
201                         'xs_auto_recompile'                     => 1,
202                         'xs_use_cache'                          => 1,
203                         'xs_php'                                        => $phpEx,
204                         'xs_def_template'                       => 'subSilver',
205                         'xs_check_switches'                     => 1,
206                         'xs_warn_includes'                      => 1,
207                         'xs_add_comments'                       => 0,
208                         'xs_ftp_host'                           => '',
209                         'xs_ftp_login'                          => '',
210                         'xs_ftp_path'                           => '',
211                         'xs_downloads_count'            => '0',
212                         'xs_downloads_default'          => '0',
213                         'xs_shownav'                            => '1',
214                         'xs_template_time'                      => '0',
215                         );
216                 // checking if all variables exist
217                 foreach($default as $var => $value)
218                 {
219                         if(!isset($board_config[$var]))
220                         {
221                                 $board_config[$var] = $value;
222                                 $add[] = $var;
223                         }
224                 }
225                 // checking if there are any outdated variables that should be deleted
226                 for($i=0; $i<count($outdated); $i++)
227                 {
228                         if(isset($board_config[$outdated[$i]]))
229                         {
230                                 $del[] = $outdated[$i];
231                         }
232                 }
233                 if(!isset($board_config['xs_version']))
234                 {
235                         $board_config['xs_version'] = $this->xs_version;
236                         $add[] = 'xs_version';
237                 }
238                 elseif($board_config['xs_version'] != $this->xs_version)
239                 {
240                         $board_config['xs_version'] = $this->xs_version;
241                         $up[] = 'xs_version';
242                 }
243                 // check config
244                 if(!empty($board_config['xs_auto_recompile']))
245                 {
246                         if(!$board_config['xs_auto_compile'])
247                         {
248                                 $board_config['xs_auto_compile'] = 1;
249                                 if(!in_array('xs_auto_compile', $up) && !in_array('xs_auto_compile', $add))
250                                 {
251                                         $up[] = 'xs_auto_compile';
252                                 }
253                         }
254                 }
255                 // install/upgrade
256                 if($edit_db && ((count($add) > 0) || (count($up) > 0) || (count($del) > 0)))
257                 {
258                         $board_config['xs_template_time'] = time();
259                         if(!in_array('xs_template_time', $up))
260                         {
261                                 $up[] = 'xs_template_time';
262                         }
263                         global $db;
264                         if(isset($db) && (@get_class($db) === 'sql_db'))
265                         {
266                                 // adding new config values
267                                 for($i=0; $i<count($add); $i++)
268                                 {
269                                         $sql = "INSERT INTO " . CONFIG_TABLE . " (config_name, config_value) VALUES ('" . $add[$i] . "', '" . str_replace("'", "''", $board_config[$add[$i]]) . "')";
270                                         $db->sql_query($sql);
271                                 }
272                                 // removing old configuration variables that aren't used
273                                 for($i=0; $i<count($del); $i++)
274                                 {
275                                         $sql = "DELETE FROM " . CONFIG_TABLE . " WHERE config_name='" . $del[$i] . "'";
276                                         $db->sql_query($sql);
277                                 }
278                                 // updating variables that should be overwritten
279                                 for($i=0; $i<count($up); $i++)
280                                 {
281                                         $sql = "UPDATE " . CONFIG_TABLE . " SET config_value='" . str_replace("'", "''", $board_config[$up[$i]]) . "' WHERE config_name='" . $up[$i] . "'";
282                                         $db->sql_query($sql);
283                                 }
284                         }
285                 }
286                 $this->php = $board_config['xs_php'];
287                 $this->tpldef = $board_config['xs_def_template'];
288                 $this->use_cache = $board_config['xs_use_cache'];
289                 $this->auto_compile = $board_config['xs_auto_compile'];
290                 $this->xs_check_switches = $board_config['xs_check_switches'];
291                 $this->cache_search = array('.', '\\', '/', '_tpl');
292                 $this->cache_replace = array('_', XS_SEPARATOR, XS_SEPARATOR, '.'.$this->php);
293                 $old_root = $this->root;
294                 $this->set_rootdir($root);
295                 if(!empty($this->tpl))
296                 {
297                         $this->load_replacements($this->tpldir . $this->tpl . '/xs.cfg');
298                 }
299                 if($old_root !== $this->root)
300                 {
301                         $this->clear_files();
302                 }
303         }
305         /**
306          * Sets the template root directory for this Template object.
307          */
308         function set_rootdir($dir)
309         {
310                 global $board_config, $phpbb_root_path;
311                 if (!@is_dir($dir))
312                 {
313                         return false;
314                 }
315                 $dir = str_replace('\\', '/', $dir);
316                 // creating absolute path for cache
317                 $this->cachedir = $phpbb_root_path . XS_DIR_CACHE . '/';
318                 // creating absolute path for current template and root dir
319                 $this->tpldir = $phpbb_root_path . 'templates/';
320                 $this->tpldir_len = strlen($this->tpldir);
321                 $this->root = $dir;
322                 $this->tpl = $this->template_name($dir);
323                 // check subtemplates mod
324                 $sub_templates_cfg = $this->root . '/sub_templates.cfg';
325                 if(defined('LANG_EXTEND_DONE') && @file_exists($sub_templates_cfg))
326                 {
327                         $this->subtemplates = true;
328                 }
329                 return true;
330         }
332         /**
333          * Destroys this template object. Should be called when you're done with it, in order
334          * to clear out the template data so you can load/parse a new template set.
335          */
336         function destroy()
337         {
338                 $this->_tpldata = array('.' => array(0 => array()));
339                 $this->vars = &$this->_tpldata['.'][0];
340                 $this->xs_started = 0;
341         }
343         /**
344          * Clears list of compiled files.
345          */
346         function clear_files()
347         {
348                 $this->files = array();
349                 $this->files_cache = array();
350                 $this->files_cache2 = array();
351                 $this->compiled_code = array();
352                 $this->uncompiled_code = array();
353         }
355         /**
356          * Loads replacements from .cfg file
357          */
358         function load_replacements($file)
359         {
360                 if(@file_exists($file))
361                 {
362                         $replace = array();
363                         @include($file);
364                         $this->replace = array_merge($this->replace, $replace);
365                 }
366         }
368         /**
369          * Extracts template name from path
370          */
371         function template_name($dir)
372         {
373                 $tpl = XS_TPL_ANY; // can start at any position
374                 $tpl_null = XS_TPL_START; // can start only at zero position
375                 // searching for 'templates/' and removing everything before it
376                 $pos = strpos($dir, $tpl);
377                 if($pos === false)
378                 {
379                         if(substr($dir, 0, strlen($tpl_null)) !== $tpl_null)
380                         {
381                                 return '';
382                         }
383                         $str = substr($dir, strlen($tpl_null), strlen($dir));
384                 }
385                 else
386                 {
387                         $str = substr($dir, $pos + strlen($tpl), strlen($dir));
388                 }
389                 // searching for one more 'templates/'
390                 // that can happen if full path is like /home/some_dude/templates/phpbb/templates/subSilver/
391                 $dir = $this->template_name($str);
392                 if(!$dir)
393                 {
394                         $dir = $str;
395                 }
396                 if(strpos($str, $tpl) !== false)
397                 {
398                         $dir = $this->template_name($str);
399                 }
400                 // check for another subdirectory
401                 $pos = strpos($dir, '/');
402                 if($pos)
403                 {
404                         $dir = substr($dir, 0, $pos);
405                 }
406                 return $dir;
407         }
409         function subtemplates_make_filename($filename)
410         {
411                 global $HTTP_GET_VARS, $HTTP_POST_VARS, $db, $board_config, $images, $theme;
412                 global $sub_template_key_image, $sub_templates;
413                 global $tree;
415                 // initiate the sub-template image pack that will be use
416                 $sub_template_key_image = POST_CAT_URL . '0';
418                 // Check if sub_templates are defined for this theme
419                 if ( $board_config['version'] > '.0.5' )
420                 {
421                         $sub_templates_cfg = @phpbb_realpath($this->root . '/sub_templates.cfg');
422                 }
423                 else
424                 {
425                         $sub_templates_cfg = $this->root . '/sub_templates.cfg';
426                 }
427                 @include($sub_templates_cfg);
428                 if ( isset($sub_templates) )
429                 {
430                         // search an id
431                         $cat_id = 0;
432                         $forum_id = 0;
433                         $topic_id = 0;
434                         $post_id = 0;
436                         if ( !defined('IN_PRIVMSG') && ( isset($HTTP_GET_VARS[POST_POST_URL]) || isset($HTTP_POST_VARS[POST_POST_URL]) ) )
437                         {
438                                 $post_id = isset($HTTP_GET_VARS[POST_POST_URL]) ? intval($HTTP_GET_VARS[POST_POST_URL]) : intval($HTTP_POST_VARS[POST_POST_URL]);
439                         }
441                         if ( isset($HTTP_GET_VARS[POST_TOPIC_URL]) || isset($HTTP_POST_VARS[POST_TOPIC_URL]) )
442                         {
443                                 $topic_id = intval($HTTP_GET_VARS[POST_TOPIC_URL]) ? intval($HTTP_GET_VARS[POST_TOPIC_URL]) : intval($HTTP_POST_VARS[POST_TOPIC_URL]);
444                         }
446                         if ( isset($HTTP_GET_VARS[POST_FORUM_URL]) || isset($HTTP_POST_VARS[POST_FORUM_URL]) )
447                         {
448                                 $forum_id = isset($HTTP_GET_VARS[POST_FORUM_URL]) ? intval($HTTP_GET_VARS[POST_FORUM_URL]) : intval($HTTP_POST_VARS[POST_FORUM_URL]);
449                         }
451                         if ( isset($HTTP_GET_VARS[POST_CAT_URL]) || isset($HTTP_POST_VARS[POST_CAT_URL]) )
452                         {
453                                 $cat_id = isset($HTTP_GET_VARS[POST_CAT_URL]) ? intval($HTTP_GET_VARS[POST_CAT_URL]) : intval($HTTP_POST_VARS[POST_CAT_URL]);
454                         }
456                         if ( isset($HTTP_GET_VARS['selected_id']) || isset($HTTP_POST_VARS['selected_id']) )
457                         {
458                                 $selected_id = isset($HTTP_GET_VARS['selected_id']) ? $HTTP_GET_VARS['selected_id'] : $HTTP_POST_VARS['selected_id'];
459                                 $type = substr($selected_id, 0, 1);
460                                 $id = intval(substr($selected_id, 1));
461                                 if (!empty($id)) switch ($type)
462                                 {
463                                         case POST_CAT_URL:
464                                                 $cat_id = $id;
465                                                 break;
466                                         case POST_FORUM_URL:
467                                                 $forum_id = $id;
468                                                 break;
469                                         case POST_TOPIC_URL:
470                                                 $topic_id = $id;
471                                                 break;
472                                         case POST_POST_URL:
473                                                 if ( !defined('IN_PRIVMSG') )
474                                                 {
475                                                         $post_id = $id;
476                                                         break;
477                                                 }
478                                         default:
479                                                 break;
480                                 }
481                         }
483                         // find the forum
484                         if ( ($forum_id <= 0) && ($cat_id <= 0) )
485                         {
486                                 if ($post_id > 0)
487                                 {
488                                         $sql = "SELECT * FROM " . POSTS_TABLE . " WHERE post_id=$post_id";                      
489                                         if ( !($result = $db->sql_query($sql)) )
490                                         {
491                                                 message_die(GENERAL_ERROR, 'Wasn\'t able to access posts', '', __LINE__, __FILE__, $sql);
492                                         }
493                                         if ( $row = $db->sql_fetchrow($result) )
494                                         {
495                                                 $forum_id = $row['forum_id'];
496                                         }
497                                 }
499                                 if ($topic_id > 0)
500                                 {
501                                         $sql = "SELECT * FROM " . TOPICS_TABLE . " WHERE topic_id=$topic_id";                   
502                                         if ( !($result = $db->sql_query($sql)) )
503                                         {
504                                                 message_die(GENERAL_ERROR, 'Wasn\'t able to access topics', '', __LINE__, __FILE__, $sql);
505                                         }
506                                         if ( $row = $db->sql_fetchrow($result) )
507                                         {
508                                                 $forum_id = $row['forum_id'];
509                                         }
510                                 }
511                         }
513                         // is the categories hierarchy v 2 installed ?
514                         $cat_hierarchy = function_exists(get_auth_keys);
516                         // get the ids (forums and cats)
517                         $fids = array();
518                         if (!$cat_hierarchy)
519                         {
520                                 if ($forum_id > 0)
521                                 {
522                                         // add the forum_id
523                                         $fids[] = POST_FORUM_URL . $forum_id;
525                                         // get the cat_id
526                                         $sql = "SELECT * FROM " . FORUMS_TABLE . " WHERE forum_id=$forum_id";
527                                         if ( !($result = $db->sql_query($sql)) )
528                                         {
529                                                 message_die(GENERAL_ERROR, 'Wasn\'t able to access forums', '', __LINE__, __FILE__, $sql);
530                                         }
531                                         if ( $row = $db->sql_fetchrow($result) )
532                                         {
533                                                 $cat_id = $row['cat_id'];
534                                         }
535                                 }
537                                 // add the cat_id
538                                 if ($cat_id > 0)
539                                 {
540                                         $fids[] = POST_CAT_URL . $cat_id;
541                                 }
543                                 // add the root level
544                                 $fids[] = 'Root';
545                         }
546                         else
547                         {
548                                 // categories hierarchy v 2 compliancy
549                                 $cur = 'Root';
550                                 if ($forum_id > 0)
551                                 {
552                                         $cur = POST_FORUM_URL . $forum_id;
553                                 }
554                                 else if ($cat_id > 0)
555                                 {
556                                         $cur = POST_CAT_URL . $cat_id;
557                                 }
559                                 // add start
560                                 $fids[] = $cur;
561                                 while ( ($cur != 'Root') && !empty($cur) )
562                                 {
563                                         // get parent level
564                                         $cur = (isset($tree['main'][ $tree['keys'][$cur] ])) ? $tree['main'][ $tree['keys'][$cur] ] : 'Root';
566                                         // add the parent level
567                                         if ( !empty($cur) )
568                                         {
569                                                 $fids[] = $cur;
570                                         }
571                                 }
572                         }
574                         // search if this file is part of a sub-template
575                         $sub_tpl_file = '';
576                         $sub_css_file = '';
577                         $sub_img_file = '';
578                         $sub_img_path = '';
579                         $template_path = 'templates/';
580                         $template_name = substr( $this->root, strpos($this->root, $template_path) + strlen($template_path) );
581                         $real_root = $this->root;
582                         if ( $board_config['version'] > '.0.5' )
583                         {
584                                 $real_root = @phpbb_realpath($this->root);
585                         }
586                         if (substr($filename, 0, 1) != '/')
587                         {
588                                 $found = false;
589                                 $num_fids = count($fids);
590                                 for ($i = 0; !$found && ($i < $num_fids); $i++)
591                                 {
592                                         $key = $fids[$i];
594                                         // convert root into c0 category
595                                         if ( ($key == 'Root') || empty($key) )
596                                         {
597                                                 $key = POST_CAT_URL . '0';
598                                         }
600                                         if ( isset($sub_templates[$key]) )
601                                         {
602                                                 // get the sub-template path
603                                                 $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir'];
604                                                 $root_template_path = $real_root . '/' . $sub_templates[$key]['dir'];
606                                                 // set the filename
607                                                 if ( empty($sub_tpl_file) && file_exists($root_template_path . '/' . $filename) )
608                                                 {
609                                                         $found = true;
610                                                         $sub_tpl_file = $sub_templates[$key]['dir'] . '/' . $filename;
611                                                         break;
612                                                 }
613                                         }
614                                 }
616                                 // set the css file name
617                                 $found = false;
618                                 $num_fids = count($fids);
619                                 for ($i = 0; !$found && ($i < $num_fids); $i++)
620                                 {
621                                         $key = $fids[$i];
623                                         // convert root into c0 category
624                                         if ( ($key == 'Root') || empty($key) )
625                                         {
626                                                 $key = POST_CAT_URL . '0';
627                                         }
629                                         if ( isset($sub_templates[$key]) )
630                                         {
631                                                 // get the sub-template path
632                                                 $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir'];
633                                                 $root_template_path = $real_root . '/' . $sub_templates[$key]['dir'];
634                                                 if ( empty($sub_css_file) && isset($sub_templates[$key]['head_stylesheet']) && file_exists($root_template_path . '/' . $sub_templates[$key]['head_stylesheet']) )
635                                                 {
636                                                         $found = true;
637                                                         $sub_css_file = $sub_templates[$key]['dir'] . '/' . $sub_templates[$key]['head_stylesheet'];
638                                                         break;
639                                                 }
640                                         }
641                                 }
643                                 // set the img file name
644                                 $found = false;
645                                 $num_fids = count($fids);
646                                 for ($i = 0; !$found && ($i < $num_fids); $i++)
647                                 {
648                                         $key = $fids[$i];
650                                         // convert root into c0 category
651                                         if ( ($key == 'Root') || empty($key) )
652                                         {
653                                                 $key = POST_CAT_URL . '0';
654                                         }
656                                         if ( isset($sub_templates[$key]) )
657                                         {
658                                                 // get the sub-template path
659                                                 $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir'];
660                                                 $root_template_path = $real_root . '/' . $sub_templates[$key]['dir'];
661                                                 if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) )
662                                                 {
663                                                         $sub_img_path = $sub_templates[$key]['dir'];
664                                                         $sub_img_file = $sub_templates[$key]['imagefile'];
666                                                         // send back the lowest level of the images file
667                                                         $found = true;
668                                                         $sub_template_key_image = $key;
669                                                         break;
670                                                 }
671                                         }
672                                 }
673                         }
675                         // set the tpl file
676                         if ( !empty($sub_tpl_file) )
677                         {
678                                 $filename = $sub_tpl_file;
679                         }
681                         // set the css file
682                         if ( !empty($sub_css_file) )
683                         {
684                                 $theme['head_stylesheet'] = $sub_css_file;
685                         }
687                         // get the root level images
688                         $key = POST_CAT_URL . '0';
689                         if ( isset($sub_templates[$key]) )
690                         {
691                                 // get the sub-template path
692                                 $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir'];
693                                 $root_template_path = $real_root . '/' . $sub_templates[$key]['dir'];
694                                 if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) )
695                                 {
696                                         $sav_images = $images;
697                                         $images = array();
698                                         @include($root_template_path . '/' . $sub_templates[$key]['imagefile']);
699                                         $img_lang = ( file_exists($root_template_path . '/images/lang_' . $board_config['default_lang']) ) ? $board_config['default_lang'] : 'english';
700                                         foreach($images as $key => $value)
701                                         {
702                                                 if ( !is_array($value) )
703                                                 {
704                                                         $images[$key] = str_replace('{LANG}', 'lang_' . $img_lang, $value);
705                                                 }
706                                                 $sav_images[$key] = $images[$key];
707                                         }
708                                         $images = $sav_images;
709                                         $sav_images = array();
710                                 }
711                         }
713                         // get the current images
714                         if ( !empty($sub_template_key_image) && ($sub_template_key_image != POST_CAT_URL . '0') )
715                         {
716                                 $key = $sub_template_key_image;
718                                 // get the sub-template path
719                                 $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir'];
720                                 $root_template_path = $real_root . '/' . $sub_templates[$key]['dir'];
721                                 if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) )
722                                 {
723                                         $sav_images = $images;
724                                         $images = array();
725                                         @include($root_template_path . '/' . $sub_templates[$key]['imagefile']);
726                                         $img_lang = ( file_exists($root_template_path . '/images/lang_' . $board_config['default_lang']) ) ? $board_config['default_lang'] : 'english';
727                                         foreach($images as $key => $value)
728                                         {
729                                                 if ( !is_array($value) )
730                                                 {
731                                                         $images[$key] = str_replace('{LANG}', 'lang_' . $img_lang, $value);
732                                                 }
733                                                 $sav_images[$key] = $images[$key];
734                                         }
735                                         $images = $sav_images;
736                                         $sav_images = array();
737                                 }
738                         }
739                 }
740                 return $filename;
741         }
743         /**
744          * Generates a full path+filename for the given filename, which can either
745          * be an absolute name, or a name relative to the rootdir for this Template
746          * object.
747          */
748         function make_filename($filename, $xs_include = false)
749         {
750                 if($this->subtemplates)
751                 {
752                         $filename = $this->subtemplates_make_filename($filename);
753                 }
754                 // Check replacements list
755                 if(!$xs_include && isset($this->replace[$filename]))
756                 {
757                         $filename = $this->replace[$filename];
758                 }
759                 // Check if it's an absolute or relative path.
760                 if ((substr($filename, 0, 1) !== '/') && (substr($filename, 1, 1) !== ':'))
761                 {
762                 return $this->root . '/' . $filename;
763                 }
764                 else
765                 {
766                         return str_replace('\\', '/', $filename);
767                 }
768         }
770         /**
771          * Converts template filename to cache filename.
772          * Returns empty string if non-cachable (for tpl files outside of root dir).
773          * $file should be absolute filename
774          */
775         function make_filename_cache($file)
776         {
777                 $str = str_replace($this->cache_search, $this->cache_replace, $file);
778                 if(substr($file, 0, $this->tpldir_len) !== $this->tpldir || empty($this->tpl))
779                 {
780                         return $this->cachedir . XS_TPL_PREFIX2 . $str;
781                 }
782                 // removing not needed part
783                 $file = substr($file, $this->tpldir_len, strlen($file));
784                 // creating filename
785                 return $this->cachedir . XS_TPL_PREFIX . str_replace($this->cache_search, $this->cache_replace, $file);
786         }
788         /**
789          * Sets the template filenames for handles. $filename_array
790          * should be a hash of handle => filename pairs.
791          */
792         function set_filenames($filename_array)
793         {
794                 if (!is_array($filename_array))
795                 {
796                         return false;
797                 }
799                 foreach($filename_array as $handle => $filename)
800                 {
801                         $this->set_filename($handle, $filename);
802                 }
804                 return true;
805         }
808         /**
809          * Assigns template filename for handle.
810          */
811         function set_filename($handle, $filename, $xs_include = false, $quiet = false)
812         {
813                 global $board_config;
814                 $can_cache = $this->use_cache;
815                 if(strpos($filename, '..') !== false)
816                 {
817                         $can_cache = false;
818                 }
819                 $this->files[$handle] = $this->make_filename($filename, $xs_include);
820                 $this->files_cache[$handle] = '';
821                 $this->files_cache2[$handle] = '';
822                 // check if we are in admin control panel and override extreme styles mod controls if needed
823                 if(defined('XS_ADMIN_OVERRIDE') && XS_ADMIN_OVERRIDE === true && @function_exists('xs_admin_override'))
824                 {
825                         xs_admin_override();
826                 }
827                 // checking if we have valid filename
828                 if(!$this->files[$handle])
829                 {
830                         if($xs_include || $quiet)
831                         {
832                                 return false;
833                         }
834                         else
835                         {
836                                 die("Template->make_filename(): Error - invalid template $filename");
837                         }
838                 }
839                 // creating cache filename
840                 if($can_cache)
841                 {
842                         $this->files_cache2[$handle] = $this->make_filename_cache($this->files[$handle]);
843                         if(@file_exists($this->files_cache2[$handle]))
844                         {
845                                 $this->files_cache[$handle] = $this->files_cache2[$handle];
846                         }
847                 }
848                 // checking if tpl and/or php file exists
849                 if(empty($this->files_cache[$handle]) && !@file_exists($this->files[$handle]))
850                 {
851                         // trying to load alternative filename (usually subSilver)
852                         if(!empty($this->tpldef) && !empty($this->tpl) && ($this->tpldef !== $this->tpl))
853                         {
854                                 $this->files[$handle] = '';
855                                 // save old configuration
856                                 $root = $this->root;
857                                 $tpl_name = $this->tpl;
858                                 // set temporary configuration
859                                 $this->root = $this->tpldir . $this->tpldef;
860                                 $this->tpl = $this->tpldef;
861                                 // recursively run set_filename
862                                 $res = $this->set_filename($handle, $filename, $xs_include, $quiet);
863                                 // restore old configuration
864                                 $this->root = $root;
865                                 $this->tpl = $tpl_name;
866                                 return $res;
867                         }
868                         if($quiet)
869                         {
870                                 return false;
871                         }
872                         if($xs_include)
873                         {
874                                 if($board_config['xs_warn_includes'])
875                                 {
876                                         die('Template->make_filename(): Error - included template file not found: ' . $filename);
877                                 }
878                                 return false;
879                         }
880                         else
881                         {
882                                 die('Template->make_filename(): Error - template file not found: ' . $filename);
883                         }
884                 }
885                 // checking if we should recompile cache
886                 if(!empty($this->files_cache[$handle]) && !empty($board_config['xs_auto_recompile']))
887                 {
888                         $cache_time = @filemtime($this->files_cache[$handle]);
889                         if(@filemtime($this->files[$handle]) > $cache_time || $board_config['xs_template_time'] > $cache_time)
890                         {       
891                                 // file was changed. don't use cache file (will be recompled if configuration allowes it)
892                                 $this->files_cache[$handle] = '';
893                         }
894                 }
895                 return true;
896         }
898         /**
899          * includes file or executes code
900          */
901         function execute($filename, $code, $handle)
902         {
903                 global $lang, $theme, $board_config;
904                 $template = $theme['template_name'];
905                 global $$template;
906                 $theme_info = &$$template;
907                 if($board_config['xs_add_comments'] && $handle)
908                 {
909                         echo '<!-- template ', $this->files[$handle], ' start -->';
910                 }
911                 if($filename)
912                 {
913                         include($filename);
914                 }
915                 else
916                 {
917                         eval($code);
918                 }
919                 if($board_config['xs_add_comments'] && $handle)
920                 {
921                         echo '<!-- template ', $this->files[$handle], ' end -->';
922                 }
923                 return true;
924         }
926         /**
927          * Load the file for the handle, compile the file,
928          * and run the compiled code. This will print out
929          * the results of executing the template.
930          */
931         function pparse($handle)
932         {
933                 global $board_config;
934                 // parsing header if there is one
935                 if($this->preparse || $this->postparse)
936                 {
937                         $preparse = $this->preparse;
938                         $postparse = $this->postparse;
939                         $this->preparse = $this->postparse = '';
940                         if($preparse)
941                         {
942                                 $this->pparse($preparse);
943                         }
944                         if($postparse)
945                         {
946                                 $str = $handle;
947                                 $handle = $postparse;
948                                 $this->pparse($str);
949                         }
950                 }
951                 // checking if handle exists
952                 if (empty($this->files[$handle]) && empty($this->files_cache[$handle]))
953                 {
954                         die("Template->loadfile(): No files found for handle $handle");
955                 }
956                 $this->xs_startup();
957                 $force_recompile = empty($this->uncompiled_code[$handle]) ? false : true;
958                 // checking if php file exists.
959                 if (!empty($this->files_cache[$handle]) && !$force_recompile)
960                 {
961                         // php file exists - running it instead of tpl
962                         $this->execute($this->files_cache[$handle], '', $handle);
963                         return true;
964                 }
965                 if (!$this->loadfile($handle))
966                 {
967                         die("Template->pparse(): Couldn't load template file for handle $handle");
968                 }
969                 // actually compile the template now.
970                 if (empty($this->compiled_code[$handle]))
971                 {
972                         // Actually compile the code now.
973                         if(!empty($this->files_cache2[$handle]) && empty($this->files_cache[$handle]) && !$force_recompile)
974                         {
975                                 $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], $handle, $this->files_cache2[$handle]);
976                         }
977                         else
978                         {
979                                 $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], '', '');
980                         }
981                 }
982                 // Run the compiled code.
983                 if (empty($this->files_cache[$handle]) || $force_recompile)
984                 {
985                         $this->execute('', $this->compiled_code[$handle], $handle);
986                 }
987                 else
988                 {
989                         $this->execute($this->files_cache[$handle], '', $handle);
990                 }
991                 return true;
992         }
994         /**
995          * Precompile file
996          */
997         function precompile($template, $filename)
998         {
999                 global $precompile_num, $board_config;
1000                 if(empty($precompile_num))
1001                 {
1002                         $precompile_num = 0;
1003                 }
1004                 $precompile_num ++;
1005                 $handle = 'precompile_' . $precompile_num;
1006                 // save old configuration
1007                 $root = $this->root;
1008                 $tpl_name = $this->tpl;
1009                 $old_config = $this->use_cache;
1010                 $old_autosave = $this->auto_compile;
1011                 // set temporary configuration
1012                 $this->root = $this->tpldir . $template;
1013                 $this->tpl = $template;
1014                 $this->use_cache = 1;
1015                 $this->auto_compile = 1;
1016                 // set filename
1017                 $res = $this->set_filename($handle, $filename, true, true);
1018                 if(!$res || !$this->files_cache2[$handle])
1019                 {
1020                         $this->root = $root;
1021                         $this->tpl = $tpl_name;
1022                         $this->use_cache = $old_config;
1023                         $this->auto_compile = $old_autosave;
1024                         return false;
1025                 }
1026                 $this->files_cache[$handle] = '';
1027                 // load template
1028                 $res = $this->loadfile($handle);
1029                 if(!$res || empty($this->uncompiled_code[$handle]))
1030                 {
1031                         $this->root = $root;
1032                         $this->tpl = $tpl_name;
1033                         $this->use_cache = $old_config;
1034                         $this->auto_compile = $old_autosave;
1035                         return false;
1036                 }
1037                 // compile the code
1038                 $this->compile2($this->uncompiled_code[$handle], $handle, $this->files_cache2[$handle]);
1039                 // restore confirugation
1040                 $this->root = $root;
1041                 $this->tpl = $tpl_name;
1042                 $this->use_cache = $old_config;
1043                 $this->auto_compile = $old_autosave;
1044                 return true;
1045         }
1047         /**
1048          * Inserts the uncompiled code for $handle as the
1049          * value of $varname in the root-level. This can be used
1050          * to effectively include a template in the middle of another
1051          * template.
1052          * Note that all desired assignments to the variables in $handle should be done
1053          * BEFORE calling this function.
1054          */
1055         function assign_var_from_handle($varname, $handle)
1056         {
1057                 ob_start();
1058                 $res = $this->pparse($handle);
1059                 $this->vars[$varname] = ob_get_contents();
1060                 ob_end_clean();
1061                 return $res;
1062         }
1064         /**
1065          * Block-level variable assignment. Adds a new block iteration with the given
1066          * variable assignments. Note that this should only be called once per block
1067          * iteration.
1068          */
1069         function assign_block_vars($blockname, $vararray)
1070         {
1071                 if (strstr($blockname, '.'))
1072                 {
1073                         // Nested block.
1074                         $blocks = explode('.', $blockname);
1075                         $blockcount = sizeof($blocks) - 1;
1077                         $str = &$this->_tpldata; 
1078                         for($i = 0; $i < $blockcount; $i++) 
1079                         { 
1080                                 $str = &$str[$blocks[$i].'.']; 
1081                                 $str = &$str[sizeof($str)-1]; 
1082                         } 
1083                         // Now we add the block that we're actually assigning to. 
1084                         // We're adding a new iteration to this block with the given 
1085                         //      variable assignments. 
1086                         $str[$blocks[$blockcount].'.'][] = $vararray;
1087                 }
1088                 else
1089                 {
1090                         // Top-level block.
1091                         // Add a new iteration to this block with the variable assignments
1092                         // we were given.
1093                         $this->_tpldata[$blockname.'.'][] = $vararray;
1094                 }
1096                 return true;
1097         }
1099         /**
1100          * Root-level variable assignment. Adds to current assignments, overriding
1101          * any existing variable assignment with the same name.
1102          */
1103         function assign_vars($vararray)
1104         {
1105                 foreach($vararray as $key => $val)
1106                 {
1107                         $this->vars[$key] = $val;
1108                 }
1109                 return true;
1110         }
1112         /**
1113          * Root-level variable assignment. Adds to current assignments, overriding
1114          * any existing variable assignment with the same name.
1115          */
1116         function assign_var($varname, $varval)
1117         {
1118                 $this->vars[$varname] = $varval;
1120                 return true;
1121         }
1123         /**
1124          * If not already done, load the file for the given handle and populate
1125          * the uncompiled_code[] hash with its code. Do not compile.
1126          */
1127         function loadfile($handle)
1128         {
1129                 global $board_config;
1130                 // If cached file exists do nothing - it will be included via include()
1131                 if(!empty($this->files_cache[$handle]))
1132                 {
1133                         return true;
1134                 }
1136                 // If the file for this handle is already loaded and compiled, do nothing.
1137                 if (!empty($this->uncompiled_code[$handle]))
1138                 {
1139                         return true;
1140                 }
1142                 // If we don't have a file assigned to this handle, die.
1143                 if (empty($this->files[$handle]))
1144                 {
1145                         die("Template->loadfile(): No file specified for handle $handle");
1146                 }
1148                 $filename = $this->files[$handle];
1150                 $str = implode('', @file($filename));
1151                 if (empty($str))
1152                 {
1153                         die("Template->loadfile(): File $filename for handle $handle is empty");
1154                 }
1156                 $this->uncompiled_code[$handle] = $str;
1158                 return true;
1159         }
1163         /**
1164          * Generates a reference to the given variable inside the given (possibly nested)
1165          * block namespace. This is a string of the form:
1166          * ' . $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['varname'] . '
1167          * It's ready to be inserted into an "echo" line in one of the templates.
1168          * NOTE: expects a trailing "." on the namespace.
1169          */
1170         function generate_block_varref($namespace, $varname, $use_isset = true)
1171         {
1172                 // Strip the trailing period.
1173                 $namespace = substr($namespace, 0, strlen($namespace) - 1);
1175                 // Get a reference to the data block for this namespace.
1176                 $varref = $this->generate_block_data_ref($namespace, true);
1177                 // Prepend the necessary code to stick this in an echo line.
1179                 // Append the variable reference.
1180                 $varref .= '[\'' . $varname . '\']';
1182                 if($use_isset)
1183                 {
1184                         $varref = '<'.'?php echo isset(' . $varref . ') ? ' . $varref . ' : \'\'; ?'.'>';
1185                 }
1186                 else
1187                 {
1188                         $varref = '<'.'?php echo ' . $varref . '; ?'.'>';
1189                 }
1191                 return $varref;
1193         }
1196         /**
1197          * Generates a reference to the array of data values for the given
1198          * (possibly nested) block namespace. This is a string of the form:
1199          * $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['$childN.']
1200          *
1201          * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
1202          * NOTE: does not expect a trailing "." on the blockname.
1203          */
1204         function generate_block_data_ref($blockname, $include_last_iterator, $defop = false)
1205         {
1206                 // Get an array of the blocks involved.
1207                 $blocks = explode('.', $blockname);
1208                 $blockcount = sizeof($blocks) - 1;
1209                 if($defop)
1210                 {
1211                         $varref = '$this->_tpldata[\'DEFINE\']';
1212                         // Build up the string with everything but the last child.
1213                         for ($i = 0; $i < $blockcount; $i++)
1214                         {
1215                                 $varref .= "['" . $blocks[$i] . ".'][\$" . $blocks[$i] . '_i]';
1216                         }
1217                         // Add the block reference for the last child.
1218                         $varref .= "['" . $blocks[$blockcount] . ".']";
1219                         // Add the iterator for the last child if requried.
1220                         if ($include_last_iterator)
1221                         {
1222                                 $varref .= '[$' . $blocks[$blockcount] . '_i]';
1223                         }
1224                         return $varref;
1225                 }
1226                 if($include_last_iterator)
1227                 {
1228                         return '$'. $blocks[$blockcount]. '_item';
1229                 }
1230                 else
1231                 {
1232                         return '$'. $blocks[$blockcount-1]. '_item[\''. $blocks[$blockcount]. '.\']';
1233                 }
1234         }
1236         function compile_code($filename, $code, $use_isset = false)
1237         {
1238                 //      $filename - file to load code from. used if $code is empty
1239                 //      $code - tpl code
1240                 //      $use_isset - if false then compiled code looks more beautiful and easier
1241                 //      to understand and it adds error_reporting() to supress php warnings.
1242                 //      if true then isset() is used to check variables instead of supressing
1243                 //          php warnings. note: for extreme styles mod 2.x it works only for
1244                 //              block variables and for usual variables its always true.
1246                 // load code from file
1247                 if(!$code && !empty($filename))
1248                 {
1249                         $code = @implode('', @file($filename));
1250                 }
1252                 // Replace phpBB 2.2 <!-- (END)PHP --> tags
1253                 $search = array('<!-- PHP -->', '<!-- ENDPHP -->');
1254                 $replace = array('<'.'?php ', ' ?'.'>');
1255                 $code = str_replace($search, $replace, $code);
1257                 // Break it up into lines and put " -->" back.
1258                 $code_lines = explode(' -->', $code);
1259                 $count = count($code_lines);
1260                 for ($i = 0; $i < ($count - 1); $i++)
1261                 {
1262                         $code_lines[$i] .= ' -->';
1263                 }
1265                 $block_nesting_level = 0;
1266                 $block_names = array();
1267                 $block_names[0] = ".";
1268                 $block_items = array();
1269                 $count_if = 0;
1271                 // prepare array for compiled code
1272                 $compiled = array();
1273                 $count_bugs = count($this->bugs);
1275                 // array of switches
1276                 $sw = array();
1278                 // replace all short php tags
1279                 $new_code = array();
1280                 $line_count = count($code_lines);
1281                 for($i=0; $i<$line_count; $i++)
1282                 {
1283                         $line = $code_lines[$i];
1284                         $pos = strpos($line, '<?');
1285                         if($pos === false)
1286                         {
1287                                 $new_code[] = $line;
1288                                 continue;
1289                         }
1290                         if(substr($line, $pos, 5) === '<?php')
1291                         {
1292                                 // valid php tag. skip it
1293                                 $new_code[] = substr($line, 0, $pos + 5);
1294                                 $code_lines[$i] = substr($line, $pos + 5);
1295                                 $i --;
1296                                 continue;
1297                         }
1298                         // invalid php tag
1299                         $new_code[] = substr($line, 0, $pos) . '<?php echo \'<?\'; ?>';
1300                         $code_lines[$i] = substr($line, $pos + 2);
1301                         $i --;
1302                 }
1303                 $code_lines = $new_code;
1305                 // main loop
1306                 $line_count = count($code_lines);
1307                 for($i=0; $i<$line_count; $i++)
1308                 {
1309                         $line = $code_lines[$i];
1310                         // reset keyword type
1311                         $keyword_type = XS_TAG_NONE;
1312                         // check if we have valid keyword in current line
1313                         $pos1 = strpos($line, '<!-- ');
1314                         if($pos1 === false)
1315                         {
1316                                 // no keywords in this line
1317                                 $compiled[] = $this->_compile_text($line, $use_isset);
1318                                 continue;
1319                         }
1320                         // find end of html comment
1321                         $pos2 = strpos($line, ' -->', $pos1);
1322                         if($pos2 !== false)
1323                         {
1324                                 // find end of keyword in comment
1325                                 $pos3 = strpos($line, ' ', $pos1 + 5);
1326                                 if($pos3 !== false && $pos3 <= $pos2)
1327                                 {
1328                                         $keyword = substr($line, $pos1 + 5, $pos3 - $pos1 - 5);
1329                                         // check keyword against list of supported keywords. case-sensitive
1330                                         if($keyword === 'BEGIN')
1331                                         {
1332                                                 $keyword_type = XS_TAG_BEGIN;
1333                                         }
1334                                         elseif($keyword === 'END')
1335                                         {
1336                                                 $keyword_type = XS_TAG_END;
1337                                         }
1338                                         elseif($keyword === 'INCLUDE')
1339                                         {
1340                                                 $keyword_type = XS_TAG_INCLUDE;
1341                                         }
1342                                         elseif($keyword === 'IF')
1343                                         {
1344                                                 $keyword_type = XS_TAG_IF;
1345                                         }
1346                                         elseif($keyword === 'ELSE')
1347                                         {
1348                                                 $keyword_type = XS_TAG_ELSE;
1349                                         }
1350                                         elseif($keyword === 'ELSEIF')
1351                                         {
1352                                                 $keyword_type = XS_TAG_ELSEIF;
1353                                         }
1354                                         elseif($keyword === 'ENDIF')
1355                                         {
1356                                                 $keyword_type = XS_TAG_ENDIF;
1357                                         }
1358                                         elseif($keyword === 'DEFINE')
1359                                         {
1360                                                 $keyword_type = XS_TAG_DEFINE;
1361                                         }
1362                                         elseif($keyword === 'UNDEFINE')
1363                                         {
1364                                                 $keyword_type = XS_TAG_UNDEFINE;
1365                                         }
1366                                 }
1367                         }
1368                         if(!$keyword_type)
1369                         {
1370                                 // not valid keyword. process the rest of line
1371                                 $compiled[] = $this->_compile_text(substr($line, 0, $pos1 + 4), $use_isset);
1372                                 $code_lines[$i] = substr($line, $pos1 + 4);
1373                                 $i --;
1374                                 continue;
1375                         }
1376                         // remove code before keyword
1377                         if($pos1 > 0)
1378                         {
1379                                 $compiled[] = $this->_compile_text(substr($line, 0, $pos1), $use_isset);
1380                         }
1381                         // remove keyword
1382                         $keyword_str = substr($line, $pos1, $pos2 - $pos1 + 4);
1383                         $params_str = $pos2 == $pos3 ? '' : substr($line, $pos3 + 1, $pos2 - $pos3 - 1);
1384                         $code_lines[$i] = substr($line, $pos2 + 4);
1385                         $i--;
1386                         // Check keywords
1388                         /*
1389                         * <!-- BEGIN -->
1390                         */
1391                         if($keyword_type == XS_TAG_BEGIN)
1392                         {
1393                                 $params = explode(' ', $params_str);
1394                                 $num_params = count($params);
1395                                 // get variable name
1396                                 if($num_params == 1)
1397                                 {
1398                                         $var = $params[0];
1399                                 }
1400                                 elseif($num_params == 2)
1401                                 {
1402                                         if($params[0] === '')
1403                                         {
1404                                                 $var = $params[1];
1405                                         }
1406                                         elseif($params[1] === '')
1407                                         {
1408                                                 $var = $params[0];
1409                                         }
1410                                         else
1411                                         {
1412                                                 // invalid tag
1413                                                 $compiled[] = $keyword_str;
1414                                                 continue;
1415                                         }
1416                                 }
1417                                 else
1418                                 {
1419                                         // invalid tag
1420                                         $compiled[] = $keyword_str;
1421                                         continue;
1422                                 }
1423                                 // check variable for matching end
1424                                 if($this->xs_check_switches)
1425                                 {
1426                                         $found = 0;
1427                                         $str = '<!-- END ' . $var . ' -->';
1428                                         for ($j = $i+1; ($j < $line_count) && !$found; $j++)
1429                                         {
1430                                                 $pos = strpos($code_lines[$j], $str);
1431                                                 if($pos !== false)
1432                                                 {
1433                                                         $found = 1;
1434                                                         $found_var = $var;
1435                                                 }
1436                                         }
1437                                         if(!$found && ($this->xs_check_switches == 1))
1438                                         {
1439                                                 // checking list of known buggy switches
1440                                                 $item = -1;
1441                                                 for($j=0; $j<$count_bugs; $j++)
1442                                                 {
1443                                                         if($this->bugs[$j][0] === $var)
1444                                                         {
1445                                                                 $item = $j;
1446                                                         }
1447                                                 }
1448                                                 if($item >= 0)
1449                                                 {
1450                                                         $str1 = '<!-- END ' . $this->bugs[$item][1] . ' -->';
1451                                                         for ($j = $i+1; ($j < $line_count) && !$found; $j++)
1452                                                         {
1453                                                                 $pos = strpos($code_lines[$j], $str1);
1454                                                                 if($pos !== false)
1455                                                                 {
1456                                                                         $found_var = $this->bugs[$item][1];
1457                                                                         $found = 1;
1458                                                                         $code_lines[$j] = str_replace($str, $str1, $code_lines[$j]);
1459                                                                 }
1460                                                         }
1461                                                 }
1462                                         }
1463                                         if(!$found)
1464                                         {
1465                                                 $compiled[] = $keyword_str;
1466                                                 continue;
1467                                         }
1468                                         // adding to list of switches
1469                                         if(isset($sw[$found_var]))
1470                                         {
1471                                                 $sw[$found_var] ++;
1472                                         }
1473                                         else
1474                                         {
1475                                                 $sw[$found_var] = 1;
1476                                         }
1477                                 }
1478                                 // adding code
1479                                 $block_nesting_level++;
1480                                 $block_names[$block_nesting_level] = $var;
1481                                 if(isset($block_items[$var]))
1482                                 {
1483                                         $block_items[$var] ++;
1484                                 }
1485                                 else
1486                                 {
1487                                         $block_items[$var] = 1;
1488                                 }
1489                                 if ($block_nesting_level < 2)
1490                                 {
1491                                         // Block is not nested.
1492                                         $line = '<'."?php\n\n";
1493                                         if($use_isset)
1494                                         {
1495                                                 $line .= '$'. $var. '_count = ( isset($this->_tpldata[\''. $var. '.\']) ) ?  sizeof($this->_tpldata[\''. $var. '.\']) : 0;';
1496                                         }
1497                                         else
1498                                         {
1499                                                 $line .= '$'. $var. '_count = sizeof($this->_tpldata[\''. $var. '.\']);';
1500                                         }
1501                                         $line .= "\n" . 'for ($'. $var. '_i = 0; $'. $var. '_i < $'. $var. '_count; $'. $var. '_i++)';
1502                                         $line .= "\n". '{'. "\n";
1503                                         $line .= ' $'. $var. '_item = &$this->_tpldata[\''. $var. '.\'][$'. $var. '_i];'."\n";
1504                                         $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n";
1505                                         $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n";
1506                                         $line .= "\n?".">";
1507                                 }
1508                                 else
1509                                 {
1510                                         // This block is nested.
1511                                         // Generate a namespace string for this block.
1512                                         $namespace = implode('.', $block_names);
1513                                         // strip leading period from root level..
1514                                         $namespace = substr($namespace, 2);
1515                                         // Get a reference to the data array for this block that depends on the
1516                                         // current indices of all parent blocks.
1517                                         $varref = $this->generate_block_data_ref($namespace, false);
1518                                         // Create the for loop code to iterate over this block.
1519                                         $line = '<'."?php\n\n";
1520                                         if($use_isset)
1521                                         {
1522                                                 $line .= '$'. $var. '_count = ( isset('. $varref. ') ) ? sizeof('. $varref. ') : 0;';
1523                                         }
1524                                         else
1525                                         {
1526                                                 $line .= '$'. $var. '_count = sizeof('. $varref. ');';
1527                                         }
1528                                         $line .= "\n". 'for ($'. $var. '_i = 0; $'. $var. '_i < $'. $var. '_count; $'. $var. '_i++)';
1529                                         $line .= "\n". '{'. "\n";
1530                                         $line .= ' $'. $var. '_item = &'. $varref. '[$'. $var. '_i];'."\n";
1531                                         $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n";
1532                                         $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n";
1533                                         $line .= "\n?".">";
1534                                 }
1535                                 $compiled[] = $line;
1536                                 continue;
1537                         }
1538                         /*
1539                         * <!-- END -->
1540                         */
1541                         if($keyword_type == XS_TAG_END)
1542                         {
1543                                 $params = explode(' ', $params_str);
1544                                 $num_params = count($params);
1545                                 if($num_params == 1)
1546                                 {
1547                                         $var = $params[0];
1548                                 }
1549                                 elseif($num_params == 2 && $params[0] === '')
1550                                 {
1551                                         $var = $params[1];
1552                                 }
1553                                 elseif($num_params == 2 && $params[1] === '')
1554                                 {
1555                                         $var = $params[0];
1556                                 }
1557                                 else
1558                                 {
1559                                         $compiled[] = $keyword_str;
1560                                         continue;
1561                                 }
1562                                 if($this->xs_check_switches)
1563                                 {       
1564                                         // checking if this switch was opened
1565                                         if(!isset($sw[$var]) || ($sw[$var] < 1))
1566                                         {       
1567                                                 // there is no opening switch
1568                                                 $compiled[] = $keyword_str;
1569                                                 continue;
1570                                         }
1571                                         $sw[$var] --;
1572                                 }
1573                                 // We have the end of a block.
1574                                 $line = '<'."?php\n\n";
1575                                 $line .= '} // END ' . $var . "\n\n";
1576                                 $line .= 'if(isset($' . $var . '_item)) { unset($' . $var . '_item); } ';
1577                                 $line .= "\n\n?".">";
1578                                 if(isset($block_items[$var]))
1579                                 {
1580                                         $block_items[$var] --;
1581                                 }
1582                                 else
1583                                 {
1584                                         $block_items[$var] = -1;
1585                                 }
1586                                 unset($block_names[$block_nesting_level]);
1587                                 $block_nesting_level--;
1588                                 $compiled[] = $line;
1589                                 continue;
1590                         }
1591                         /*
1592                         * <!-- INCLUDE -->
1593                         */
1594                         if($keyword_type == XS_TAG_INCLUDE)
1595                         {
1596                                 $params = explode(' ', $params_str);
1597                                 $num_params = count($params);
1598                                 if($num_params != 1)
1599                                 {
1600                                         $compiled[] = $keyword_str;
1601                                         continue;
1602                                 }
1603                                 $line = '<'.'?php ';
1604                                 $line .= ' $this->set_filename(\'xs_include' . $this->include_count . '\', \'' . $params_str .'\', true); ';
1605                                 $line .= ' $this->pparse(\'xs_include' . $this->include_count . '\'); ';
1606                                 $line .= ' ?'.'>';
1607                                 $this->include_count ++;
1608                                 $compiled[] = $line;
1609                                 continue;
1610                         }
1611                         /*
1612                         * <!-- IF -->
1613                         */
1614                         if($keyword_type == XS_TAG_IF || $keyword_type == XS_TAG_ELSEIF)
1615                         {
1616                                 if(!$count_if)
1617                                 {
1618                                         $keyword_type = XS_TAG_IF;
1619                                 }
1620                                 $str = $this->compile_tag_if($params_str, $keyword_type == XS_TAG_IF ? false : true);
1621                                 if($str)
1622                                 {
1623                                         $compiled[] = '<?php ' . $str . ' ?>';
1624                                         if($keyword_type == XS_TAG_IF)
1625                                         {
1626                                                 $count_if ++;
1627                                         }
1628                                 }
1629                                 else
1630                                 {
1631                                         $compiled[] = $keyword_str;
1632                                 }
1633                                 continue;
1634                         }
1635                         /*
1636                         * <!-- ELSE -->
1637                         */
1638                         if($keyword_type == XS_TAG_ELSE && $count_if > 0)
1639                         {
1640                                 $compiled[] = '<?php } else { ?>';
1641                                 continue;
1642                         }
1643                         /*
1644                         * <!-- ENDIF -->
1645                         */
1646                         if($keyword_type == XS_TAG_ENDIF && $count_if > 0)
1647                         {
1648                                 $compiled[] = '<?php } ?>';
1649                                 $count_if --;
1650                                 continue;
1651                         }
1652                         /*
1653                         * <!-- DEFINE -->
1654                         */
1655                         if($keyword_type == XS_TAG_DEFINE)
1656                         {
1657                                 $str = $this->compile_tag_define($params_str);
1658                                 if($str)
1659                                 {
1660                                         $compiled[] = '<?php ' . $str . ' ?>';
1661                                 }
1662                                 else
1663                                 {
1664                                         $compiled[] = $keyword_str;
1665                                 }
1666                         }
1667                         /*
1668                         * <!-- UNDEFINE -->
1669                         */
1670                         if($keyword_type == XS_TAG_UNDEFINE)
1671                         {
1672                                 $str = $this->compile_tag_undefine($params_str);
1673                                 if($str)
1674                                 {
1675                                         $compiled[] = '<?php ' . $str . ' ?>';
1676                                 }
1677                                 else
1678                                 {
1679                                         $compiled[] = $keyword_str;
1680                                 }
1681                         }
1682                 }
1683                 
1684                 // bring it back into a single string.
1685                 $code_header = '';
1686                 $code_footer = '';
1687                 if(!$use_isset)
1688                 {
1689                         $code_header =  "<". "?php\n\$old_level = @error_reporting(E_ERROR | E_WARNING | E_PARSE); \n?".">";
1690                         $code_footer = '<'."?php @error_reporting(\$old_level); ?".'>';
1691                 }
1693                 return $code_header . implode('', $compiled) . $code_footer;
1694         }
1696         /*
1697         * Compile code between tags
1698         */
1699         function _compile_text($code, $use_isset)
1700         {
1701                 if(strlen($code) < 3)
1702                 {
1703                         return $code;
1704                 }
1705                 // change template varrefs into PHP varrefs
1706                 // This one will handle varrefs WITH namespaces
1707                 $varrefs = array();
1708                 preg_match_all('#\{(([a-z0-9\-_]+?\.)+?)([a-z0-9\-_]+?)\}#is', $code, $varrefs);
1709                 $varcount = sizeof($varrefs[1]);
1710                 $search = array();
1711                 $replace = array();
1712                 for ($i = 0; $i < $varcount; $i++)
1713                 {
1714                         $namespace = $varrefs[1][$i];
1715                         $varname = $varrefs[3][$i];
1716                         $new = $this->generate_block_varref($namespace, $varname, $use_isset);
1717                         $search[] = $varrefs[0][$i];
1718                         $replace[] = $new;
1719                 }
1720                 if(count($search) > 0)
1721                 {
1722                         $code = str_replace($search, $replace, $code);
1723                 }
1724                 // This will handle the remaining root-level varrefs
1725                 $code = preg_replace('#\{([a-z0-9\-_]*?)\}#is', '<'.'?php echo isset($this->vars[\'\1\']) ? $this->vars[\'\1\'] : $this->lang(\'\1\'); ?'.'>', $code);
1726                 $code = preg_replace('#\{\$([a-z0-9\-_]*?)\}#is', '<'.'?php echo isset($this->_tpldata[\'DEFINE\'][\'.\'][\'\\1\']) ? $this->_tpldata[\'DEFINE\'][\'.\'][\'\\1\'] : \'\'; ?'.'>', $code);
1727                 return $code;
1728         }
1730         //
1731         // Compile IF tags - much of this is from Smarty with
1732         // some adaptions for our block level methods
1733         //
1734         function compile_tag_if($tag_args, $elseif)
1735         {
1736         /* Tokenize args for 'if' tag. */
1737         preg_match_all('/(?:
1738                          "[^"\\\\]*(?:\\\\.[^"\\\\]*)*"         |
1739                          \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'     |
1740                          [(),]                                  |
1741                          [^\s(),]+)/x', $tag_args, $match);
1743         $tokens = $match[0];
1744         $is_arg_stack = array();
1746         for ($i = 0; $i < count($tokens); $i++)
1747                 {
1748                         $token = &$tokens[$i];
1750                         switch ($token)
1751                         {
1752                 case '!':
1753                 case '%':
1754                 case '!==':
1755                 case '==':
1756                 case '===':
1757                 case '>':
1758                 case '<':
1759                 case '!=':
1760                 case '<>':
1761                 case '<<':
1762                 case '>>':
1763                 case '<=':
1764                 case '>=':
1765                 case '&&':
1766                 case '||':
1767                                 case '|':
1768                                 case '^':
1769                                 case '&':
1770                                 case '~':
1771                                 case ')':
1772                                 case ',':
1773                                 case '+':
1774                                 case '-':
1775                                 case '*':
1776                                 case '/':
1777                                 case '@':
1778                                         break;  
1780                                 case 'eq':
1781                                         $token = '==';
1782                                         break;
1784                                 case 'ne':
1785                                 case 'neq':
1786                                         $token = '!=';
1787                                         break;
1789                                 case 'lt':
1790                                         $token = '<';
1791                                         break;
1793                                 case 'le':
1794                                 case 'lte':
1795                                         $token = '<=';
1796                                         break;
1798                                 case 'gt':
1799                                         $token = '>';
1800                                         break;
1802                                 case 'ge':
1803                                 case 'gte':
1804                                         $token = '>=';
1805                                         break;
1807                                 case 'and':
1808                                         $token = '&&';
1809                                         break;
1811                                 case 'or':
1812                                         $token = '||';
1813                                         break;
1815                                 case 'not':
1816                                         $token = '!';
1817                                         break;
1819                                 case 'mod':
1820                                         $token = '%';
1821                                         break;
1823                                 case '(':
1824                                         array_push($is_arg_stack, $i);
1825                                         break;
1827                                 case 'is':
1828                                         $is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1;
1829                                         $is_arg = implode('     ', array_slice($tokens, $is_arg_start, $i -     $is_arg_start));
1831                                         $new_tokens     = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
1833                                         array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
1835                                         $i = $is_arg_start;
1837                                 default:
1838                                         if (preg_match('#^(([a-z0-9\-_]+?\.)+?)?(\$)?([A-Z]+[A-Z0-9\-_]+)$#s', $token, $varrefs))
1839                                         {
1840                                                 $token = (!empty($varrefs[1])) ? $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[3]) . '[\'' . $varrefs[4] . '\']' : (($varrefs[3]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[4] . '\']' : '$this->vars[\'' . $varrefs[4] . '\']');
1841                                         }
1842                                         break;
1843             }
1844         }
1846                 $code = (($elseif) ? '} elseif (' : 'if (') . (implode(' ', $tokens) . ') { ');
1847         
1848                 return $code;
1849         }
1851         // This is from Smarty
1852         function _parse_is_expr($is_arg, $tokens)
1853         {
1854                 $expr_end =     0;
1855                 $negate_expr = false;
1857                 if (($first_token = array_shift($tokens)) == 'not')
1858                 {
1859                         $negate_expr = true;
1860                         $expr_type = array_shift($tokens);
1861                 }
1862                 else
1863                 {
1864                         $expr_type = $first_token;
1865                 }
1867                 switch ($expr_type)
1868                 {
1869                         case 'even':
1870                                 if (@$tokens[$expr_end] == 'by')
1871                                 {
1872                                         $expr_end++;
1873                                         $expr_arg =     $tokens[$expr_end++];
1874                                         $expr = "!(($is_arg     / $expr_arg) % $expr_arg)";
1875                                 }
1876                                 else
1877                                 {
1878                                         $expr = "!($is_arg % 2)";
1879                                 }
1880                                 break;
1882                         case 'odd':
1883                                 if (@$tokens[$expr_end] == 'by')
1884                                 {
1885                                         $expr_end++;
1886                                         $expr_arg =     $tokens[$expr_end++];
1887                                         $expr = "(($is_arg / $expr_arg) % $expr_arg)";
1888                                 }
1889                                 else
1890                                 {
1891                                         $expr = "($is_arg %     2)";
1892                                 }
1893                                 break;
1895                         case 'div':
1896                                 if (@$tokens[$expr_end] == 'by')
1897                                 {
1898                                         $expr_end++;
1899                                         $expr_arg =     $tokens[$expr_end++];
1900                                         $expr = "!($is_arg % $expr_arg)";
1901                                 }
1902                                 break;
1904                         default:
1905                                 break;
1906                 }
1908                 if ($negate_expr)
1909                 {
1910                         $expr = "!($expr)";
1911                 }
1913                 array_splice($tokens, 0, $expr_end,     $expr);
1915                 return $tokens;
1916         }
1919         function compile_tag_define($tag_args)
1920         {
1921                 preg_match('#^(([a-z0-9\-_]+?\.)+?)?\$([A-Z][A-Z0-9_\-]*?) = (\'?)(.*?)(\'?)$#', $tag_args, $match);
1923                 if (empty($match[3]) || empty($match[5]))
1924                 {
1925                         return '';
1926                 }
1928                 // Are we a string?
1929                 if ($match[4] && $match[6])
1930                 {
1931                         $match[5] = "'" . addslashes(str_replace(array('\\\'', '\\\\'), array('\'', '\\'), $match[5])) . "'";
1932                 }
1933                 else
1934                 {
1935                         preg_match('#(true|false|\.)#i', $match[5], $type);
1937                         switch (strtolower($type[1]))
1938                         {
1939                                 case 'true':
1940                                 case 'false':
1941                                         $match[5] = strtoupper($match[5]);
1942                                         break;
1943                                 case '.';
1944                                         $match[5] = doubleval($match[5]);
1945                                         break;
1946                                 default:
1947                                         $match[5] = intval($match[5]);
1948                                         break;
1949                         }
1950                 }
1952                 return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[3] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[3] . '\']') . ' = ' . $match[5] . ';';
1953         }
1955         function compile_tag_undefine($tag_args)
1956         {
1957                 preg_match('#^(([a-z0-9\-_]+?\.)+?)?\$([A-Z][A-Z0-9_\-]*?)$#', $tag_args, $match);
1958                 if (empty($match[3]))
1959                 {
1960                         return '';
1961                 }
1962                 return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[3] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[3] . '\']') . ');';
1963         }
1965         /**
1966          * Compiles code and writes to cache if needed
1967          */
1968         function compile2($code, $handle, $cache_file)
1969         {
1970                 $code = $this->compile_code('', $code, XS_USE_ISSET);
1971                 if($cache_file && !empty($this->use_cache) && !empty($this->auto_compile))
1972                 {
1973                         $res = $this->write_cache($cache_file, $code);
1974                         if($handle && $res)
1975                         {
1976                                 $this->files_cache[$handle] = $cache_file;
1977                         }
1978                 }
1979                 $code = '?'.'>'.$code.'<'."?php\n";
1980                 return $code;
1981         }
1983         /**
1984          * Compiles the given string of code, and returns
1985          * the result in a string.
1986          * If "do_not_echo" is true, the returned code will not be directly
1987          * executable, but can be used as part of a variable assignment
1988          * for use in assign_code_from_handle().
1989          * This function isn't used and kept only for compatibility with original template.php
1990          */
1991         function compile($code, $do_not_echo = false, $retvar = '')
1992         {
1993                 $code = ' ?'.'>' . $this->compile_code('', $code, true) . '<'."?php \n";
1994                 if($do_not_echo)
1995                 {
1996                         $code = "ob_start();\n". $code. "\n\${$retvar} = ob_get_contents();\nob_end_clean();\n";
1997                 }
1998                 return $code;
1999         }
2001         /**
2002          * Write cache to disk
2003          */
2004         function write_cache($filename, $code)
2005         {
2006                 // check if cache is writable
2007                 if(!$this->cache_writable)
2008                 {
2009                         return false;
2010                 }
2011                 // check if filename is valid
2012                 if(substr($filename, 0, strlen($this->cachedir)) !== $this->cachedir)
2013                 {
2014                         return false;
2015                 }
2016                 // try to open file
2017                 $file = @fopen($filename, 'w');
2018                 if(!$file)
2019                 {
2020                         // try to create directories
2021                         $dir = substr($filename, strlen($this->cachedir), strlen($filename));
2022                         $dirs = explode('/', $dir);
2023                         $path = $this->cachedir; 
2024                         @umask(0);
2025                         if(!@is_dir($path))
2026                         {
2027                                 if(!@mkdir($path))
2028                                 {
2029                                         $this->cache_writable = 0;
2030                                         return false;
2031                                 }
2032                                 else
2033                                 {
2034                                         @chmod($path, 0777);
2035                                 }
2036                         }
2037                         $count = count($dirs);
2038                         if($count > 0)
2039                         for($i=0; $i<$count-1; $i++)
2040                         {
2041                                 if($i>0)
2042                                 {
2043                                         $path .= '/';
2044                                 }
2045                                 $path .= $dirs[$i];
2046                                 if(!@is_dir($path))
2047                                 {
2048                                         if(!@mkdir($path))
2049                                         {
2050                                                 $this->cache_writable = 0;
2051                                                 return false;
2052                                         }
2053                                         else
2054                                         {
2055                                                 @chmod($path, 0777);
2056                                         }
2057                                 }
2058                         }
2059                         // try to open file again after directories were created
2060                         $file = @fopen($filename, 'w');
2061                 }
2062                 if(!$file)
2063                 {
2064                         $this->cache_writable = 0;
2065                         return false;
2066                 }
2067                 fputs($file, "<?php\n\n// eXtreme Styles mod cache. Generated on " . date('r') . " (time=" . time() . ")\n\n?>");
2068                 fputs($file, $code);
2069                 fclose($file);
2070                 @chmod($filename, 0777);
2071                 return true;
2072         }
2074         function xs_startup()
2075         {
2076                 global $phpEx, $board_config, $phpbb_root_path;
2077                 if(empty($this->xs_started))
2078                 {       // adding predefined variables
2079                         $this->xs_started = 1;
2080                         // file extension with session ID (eg: "php?sid=123&" or "php?")
2081                         // can be used to make custom URLs without modding phpbb
2082                         // contains "&" or "?" at the end so you can easily append paramenters
2083                         $php = append_sid($phpEx);
2084                         if(strpos($php, '?'))
2085                         {
2086                                 $php .= '&';
2087                         }
2088                         else
2089                         {
2090                                 $php .= '?';
2091                         }
2092                         $this->vars['PHP'] = $php;
2093                         // adding language variable (eg: "english" or "german")
2094                         // can be used to make truly multi-lingual templates
2095                         $this->vars['LANG'] = $board_config['default_lang'];
2096                         // adding current template
2097                         $tpl = $this->root . '/'; // $phpbb_root_path . 'templates/' . $this->tpl . '/';
2098                         if(substr($tpl, 0, 2) === './')
2099                         {
2100                                 $tpl = substr($tpl, 2, strlen($tpl));
2101                         }
2102                         $this->vars['TEMPLATE'] = $tpl;
2103                         $this->vars['TEMPLATE_NAME'] = $this->tpl;
2104                         $this->_tpldata['switch_xs_enabled.'] = array(array('version' => $this->xs_versiontxt));
2105                 }
2106         }
2108         /**
2109          * Checks for empty variable and shows language variable if possible.
2110          */
2111         function lang($var)
2112         {
2113                 global $lang;
2114                 if(substr($var, 0, 2) === 'L_')
2115                 {
2116                         $var = substr($var, 2);
2117                         // check variable as it is
2118                         if(isset($lang[$var]))
2119                         {
2120                                 return $lang[$var];
2121                         }
2122                         // check variable in lower case
2123                         if(isset($lang[strtolower($var)]))
2124                         {
2125                                 return $lang[strtolower($var)];
2126                         }
2127                         // check variable with first letter in upper case
2128                         $str = ucfirst(strtolower($var));
2129                         if(isset($lang[$str]))
2130                         {
2131                                 return $lang[$str];
2132                         }
2133                         return ''; //str_replace('_', ' ', $var);
2134                 }
2135                 return '';
2136         }
2138         //
2139         //
2140         // Functions added for USERGROUP MOD (optimized)
2141         //
2142         //
2143         function append_var_from_handle_to_block($blockname, $varname, $handle)
2144         {
2145                 $this->assign_var_from_handle('_tmp', $handle);
2146                 // assign the value of the generated variable to the given varname.
2147                 $this->append_block_vars($blockname, array($varname => $this->vars['_tmp']));
2148                 return true;
2149         }
2151         function append_block_vars($blockname, $vararray)
2152         {
2153                 if(strstr($blockname, '.'))
2154                 {
2155                         // Nested block.
2156                         $blocks = explode('.', $blockname);
2157                         $blockcount = sizeof($blocks) - 1;
2158                         $str = &$this->_tpldata;
2159                         for($i = 0; $i < $blockcount; $i++)
2160                         {
2161                                 $str = &$str[$blocks[$i].'.'];
2162                                 $str = &$str[sizeof($str)-1];
2163                         }
2164                         // Now we add the block that we're actually assigning to.
2165                         // We're adding a new iteration to this block with the given
2166                         //   variable assignments.
2167                         $str = &$str[$blocks[$blockcount].'.'];
2168                         $count = sizeof($str) - 1;
2169                         if($count >= 0)
2170                         {
2171                                 // adding only if there is at least one item
2172                                 $str[$count] = array_merge($str[$count], $vararray);
2173                         }
2174                 }
2175                 else
2176                 {
2177                         // Top-level block.
2178                         // Add a new iteration to this block with the variable assignments
2179                         // we were given.
2180                         $str = &$this->_tpldata[$blockname.'.'];
2181                         $count = sizeof($str) - 1;
2182                         if($count >= 0)
2183                         {
2184                                 // adding only if there is at least one item
2185                                 $str[$count] = array_merge($str[$count], $vararray);
2186                         }
2187                 }
2188                 return true;
2189         }
2191         /*
2192         * Flush a root level block, so it becomes empty.
2193         */
2194         function flush_block_vars($blockname)
2195         {
2196                 // Top-level block.
2197                 // flush a existing block we were given.
2198                 $current_iteration = sizeof($this->_tpldata[$blockname . '.']) - 1;
2199                 unset($this->_tpldata[$blockname . '.']);
2200                 return true;
2201         }
2204 function xs_switch($tpl, $name)
2206         return (isset($tpl->_tpldata[$name.'.']) && count($tpl->_tpldata[$name.'.']) > 0);
2209 ?>