_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value // if it's a root-level variable, it'll be like this: // $this->vars[varname] == value or $this->_tpldata['.'][0][varname] == value // array "vars" is added for easier access to data var $_tpldata = array('.' => array(0 => array())); var $vars; // Hash of filenames for each template handle. var $files = array(); var $files_cache = array(); // array of cache files that exists var $files_cache2 = array(); // array of cache files (exists or not exists) // Root template directory. var $root = ''; // Cache directory (compatible with default cache mod) var $cachedir = ''; // Search/replace for unknown files var $cache_search = array(); var $cache_replace = array(); // Template root directory (generated by set_rootdir) var $tpldir = ''; var $tpldir_len = 0; // Default template directory. // If file for default template isn't found file from this template is used. var $tpldef = 'subSilver'; // this will hash handle names to the compiled code for that handle. var $compiled_code = array(); // This will hold the uncompiled code for that handle. var $uncompiled_code = array(); // Cache settings var $use_cache = 1; var $cache_writable = 1; // Auto-compile setting var $auto_compile = 1; // Current template name var $tpl = ''; // List of replacements. tpl files in this list will be replaced with other tpl files // according to configuration in xs.cfg var $replace = array(); // counter for include var $include_count = 0; // php extension. will be replaced by $phpEx in Template() function unless you disable it there var $php = 'php'; // True if check switches var $xs_check_switches = 1; // eXtreme Styles variables var $xs_started = 0; var $xs_version = 8; // number version. internal. do not change. var $xs_versiontxt = '2.3.1'; // text version // These handles will be parsed if pparse() is executed. // Can be used to automatically include header/footer if there is any content. var $preparse = ''; var $postparse = ''; // subtemplates mod detection var $subtemplates = false; // style configuration var $style_config = array(); // list of switches that are known typos in some mods. // when error checking is enabled these errors will be auto-fixed. // format: // array(start_tag, end_tag) var $bugs = array( // ezportal typo: array('fetchpost_row', 'fetch_post_row'), // mycalendar 2.2.7 typos: array('date_cell', 'date_cells'), array('date_row', 'date_rows'), // history mod typo: array('site_today', 'site_week'), ); /** * Constructor. Installs XS mod on first run or updates it and sets the root dir. */ function Template($root = '.') { // setting pointer "vars" $this->vars = &$this->_tpldata['.'][0]; // load configuration $this->load_config($root, true); } /** * Load mod configuration */ function load_config($root, $edit_db) { global $board_config, $phpbb_root_path, $phpEx; // getting mod version from config and comparing with real data $ver = isset($board_config['xs_version']) ? $board_config['xs_version'] : 0; // check configuration // set config values if there aren't any $add = array(); $del = array(); $up = array(); // list of outdated variables $outdated = array( 'xs_versoin', // was a typo in one of previous versions 'xs_separator', // no longer used 'xs_cache_dir_absolute', // no longer used 'xs_cache_dir', // no longer used 'xs_use_isset', // no longer used ); // list of default values $default = array( 'xs_auto_compile' => 1, 'xs_auto_recompile' => 1, 'xs_use_cache' => 1, 'xs_php' => $phpEx, 'xs_def_template' => 'subSilver', 'xs_check_switches' => 1, 'xs_warn_includes' => 1, 'xs_add_comments' => 0, 'xs_ftp_host' => '', 'xs_ftp_login' => '', 'xs_ftp_path' => '', 'xs_downloads_count' => '0', 'xs_downloads_default' => '0', 'xs_shownav' => '1', 'xs_template_time' => '0', ); // checking if all variables exist foreach($default as $var => $value) { if(!isset($board_config[$var])) { $board_config[$var] = $value; $add[] = $var; } } // checking if there are any outdated variables that should be deleted for($i=0; $ixs_version; $add[] = 'xs_version'; } elseif($board_config['xs_version'] != $this->xs_version) { $board_config['xs_version'] = $this->xs_version; $up[] = 'xs_version'; } // check config if(!empty($board_config['xs_auto_recompile'])) { if(!$board_config['xs_auto_compile']) { $board_config['xs_auto_compile'] = 1; if(!in_array('xs_auto_compile', $up) && !in_array('xs_auto_compile', $add)) { $up[] = 'xs_auto_compile'; } } } // install/upgrade if($edit_db && ((count($add) > 0) || (count($up) > 0) || (count($del) > 0))) { $board_config['xs_template_time'] = time(); if(!in_array('xs_template_time', $up)) { $up[] = 'xs_template_time'; } global $db; if(!empty($db)) { // adding new config values for($i=0; $isql_query($sql); } // removing old configuration variables that aren't used for($i=0; $isql_query($sql); } // updating variables that should be overwritten for($i=0; $isql_query($sql); } // recache config table for cat_hierarchy 2.1.0 global $config; if(isset($config->data) && $config->data === $board_config && isset($config->data['mod_cat_hierarchy'])) { $config->read(true); } } } $this->php = $board_config['xs_php']; $this->tpldef = $board_config['xs_def_template']; $this->use_cache = $board_config['xs_use_cache']; $this->auto_compile = $board_config['xs_auto_compile']; $this->xs_check_switches = $board_config['xs_check_switches']; $this->cache_search = array('.', '\\', '/', '_tpl'); $this->cache_replace = array('_', XS_SEPARATOR, XS_SEPARATOR, '.'.$this->php); $old_root = $this->root; $this->set_rootdir($root); if(!empty($this->tpl)) { $this->load_replacements($this->tpldir . $this->tpl . '/xs.cfg'); } if($old_root !== $this->root) { $this->clear_files(); } } /** * Sets the template root directory for this Template object. */ function set_rootdir($dir) { global $board_config, $phpbb_root_path; if (!@is_dir($dir)) { return false; } $dir = str_replace('\\', '/', $dir); // creating absolute path for cache $this->cachedir = $phpbb_root_path . XS_DIR_CACHE . '/'; // creating absolute path for current template and root dir $this->tpldir = $phpbb_root_path . 'templates/'; $this->tpldir_len = strlen($this->tpldir); $this->root = $dir; $this->tpl = $this->template_name($dir); // check configuration $this->get_config(); // check subtemplates mod $sub_templates_cfg = $this->root . '/sub_templates.cfg'; if(defined('LANG_EXTEND_DONE') && @file_exists($sub_templates_cfg)) { $this->subtemplates = true; } return true; } /** * Destroys this template object. Should be called when you're done with it, in order * to clear out the template data so you can load/parse a new template set. */ function destroy() { $this->_tpldata = array('.' => array(0 => array())); $this->vars = &$this->_tpldata['.'][0]; $this->xs_started = 0; } /** * Clears list of compiled files. */ function clear_files() { $this->files = array(); $this->files_cache = array(); $this->files_cache2 = array(); $this->compiled_code = array(); $this->uncompiled_code = array(); } /** * Loads replacements from .cfg file */ function load_replacements($file) { if(@file_exists($file)) { $replace = array(); @include($file); $this->replace = array_merge($this->replace, $replace); } } /** * Extracts template name from path */ function template_name($dir) { $tpl = XS_TPL_ANY; // can start at any position $tpl_null = XS_TPL_START; // can start only at zero position // searching for 'templates/' and removing everything before it $pos = strpos($dir, $tpl); if($pos === false) { if(substr($dir, 0, strlen($tpl_null)) !== $tpl_null) { return ''; } $str = substr($dir, strlen($tpl_null), strlen($dir)); } else { $str = substr($dir, $pos + strlen($tpl), strlen($dir)); } // searching for one more 'templates/' // that can happen if full path is like /home/some_dude/templates/phpbb/templates/subSilver/ $dir = $this->template_name($str); if(!$dir) { $dir = $str; } if(strpos($str, $tpl) !== false) { $dir = $this->template_name($str); } // check for another subdirectory $pos = strpos($dir, '/'); if($pos) { $dir = substr($dir, 0, $pos); } return $dir; } function subtemplates_make_filename($filename) { global $HTTP_GET_VARS, $HTTP_POST_VARS, $db, $board_config, $images, $theme; global $sub_template_key_image, $sub_templates; global $tree; // initiate the sub-template image pack that will be use $sub_template_key_image = POST_CAT_URL . '0'; // Check if sub_templates are defined for this theme if ( $board_config['version'] > '.0.5' ) { $sub_templates_cfg = @phpbb_realpath($this->root . '/sub_templates.cfg'); } else { $sub_templates_cfg = $this->root . '/sub_templates.cfg'; } @include($sub_templates_cfg); if ( isset($sub_templates) ) { // search an id $cat_id = 0; $forum_id = 0; $topic_id = 0; $post_id = 0; if ( !defined('IN_PRIVMSG') && ( isset($HTTP_GET_VARS[POST_POST_URL]) || isset($HTTP_POST_VARS[POST_POST_URL]) ) ) { $post_id = isset($HTTP_GET_VARS[POST_POST_URL]) ? intval($HTTP_GET_VARS[POST_POST_URL]) : intval($HTTP_POST_VARS[POST_POST_URL]); } if ( isset($HTTP_GET_VARS[POST_TOPIC_URL]) || isset($HTTP_POST_VARS[POST_TOPIC_URL]) ) { $topic_id = intval($HTTP_GET_VARS[POST_TOPIC_URL]) ? intval($HTTP_GET_VARS[POST_TOPIC_URL]) : intval($HTTP_POST_VARS[POST_TOPIC_URL]); } if ( isset($HTTP_GET_VARS[POST_FORUM_URL]) || isset($HTTP_POST_VARS[POST_FORUM_URL]) ) { $forum_id = isset($HTTP_GET_VARS[POST_FORUM_URL]) ? intval($HTTP_GET_VARS[POST_FORUM_URL]) : intval($HTTP_POST_VARS[POST_FORUM_URL]); } if ( isset($HTTP_GET_VARS[POST_CAT_URL]) || isset($HTTP_POST_VARS[POST_CAT_URL]) ) { $cat_id = isset($HTTP_GET_VARS[POST_CAT_URL]) ? intval($HTTP_GET_VARS[POST_CAT_URL]) : intval($HTTP_POST_VARS[POST_CAT_URL]); } if ( isset($HTTP_GET_VARS['selected_id']) || isset($HTTP_POST_VARS['selected_id']) ) { $selected_id = isset($HTTP_GET_VARS['selected_id']) ? $HTTP_GET_VARS['selected_id'] : $HTTP_POST_VARS['selected_id']; $type = substr($selected_id, 0, 1); $id = intval(substr($selected_id, 1)); if (!empty($id)) switch ($type) { case POST_CAT_URL: $cat_id = $id; break; case POST_FORUM_URL: $forum_id = $id; break; case POST_TOPIC_URL: $topic_id = $id; break; case POST_POST_URL: if ( !defined('IN_PRIVMSG') ) { $post_id = $id; break; } default: break; } } // find the forum if ( ($forum_id <= 0) && ($cat_id <= 0) ) { if ($post_id > 0) { $sql = "SELECT * FROM " . POSTS_TABLE . " WHERE post_id=$post_id"; if ( !($result = $db->sql_query($sql)) ) { message_die(GENERAL_ERROR, 'Wasn\'t able to access posts', '', __LINE__, __FILE__, $sql); } if ( $row = $db->sql_fetchrow($result) ) { $forum_id = $row['forum_id']; } } if ($topic_id > 0) { $sql = "SELECT * FROM " . TOPICS_TABLE . " WHERE topic_id=$topic_id"; if ( !($result = $db->sql_query($sql)) ) { message_die(GENERAL_ERROR, 'Wasn\'t able to access topics', '', __LINE__, __FILE__, $sql); } if ( $row = $db->sql_fetchrow($result) ) { $forum_id = $row['forum_id']; } } } // is the categories hierarchy v 2 installed ? $cat_hierarchy = function_exists('get_auth_keys'); // get the ids (forums and cats) $fids = array(); if (!$cat_hierarchy) { if ($forum_id > 0) { // add the forum_id $fids[] = POST_FORUM_URL . $forum_id; // get the cat_id $sql = "SELECT * FROM " . FORUMS_TABLE . " WHERE forum_id=$forum_id"; if ( !($result = $db->sql_query($sql)) ) { message_die(GENERAL_ERROR, 'Wasn\'t able to access forums', '', __LINE__, __FILE__, $sql); } if ( $row = $db->sql_fetchrow($result) ) { $cat_id = $row['cat_id']; } } // add the cat_id if ($cat_id > 0) { $fids[] = POST_CAT_URL . $cat_id; } // add the root level $fids[] = 'Root'; } else { // categories hierarchy v 2 compliancy $cur = 'Root'; if ($forum_id > 0) { $cur = POST_FORUM_URL . $forum_id; } else if ($cat_id > 0) { $cur = POST_CAT_URL . $cat_id; } // add start $fids[] = $cur; while ( ($cur != 'Root') && !empty($cur) ) { // get parent level $cur = (isset($tree['main'][ $tree['keys'][$cur] ])) ? $tree['main'][ $tree['keys'][$cur] ] : 'Root'; // add the parent level if ( !empty($cur) ) { $fids[] = $cur; } } } // search if this file is part of a sub-template $sub_tpl_file = ''; $sub_css_file = ''; $sub_img_file = ''; $sub_img_path = ''; $template_path = 'templates/'; $template_name = substr( $this->root, strpos($this->root, $template_path) + strlen($template_path) ); $real_root = $this->root; if ( $board_config['version'] > '.0.5' ) { $real_root = @phpbb_realpath($this->root); } if (substr($filename, 0, 1) != '/') { $found = false; $num_fids = count($fids); for ($i = 0; !$found && ($i < $num_fids); $i++) { $key = $fids[$i]; // convert root into c0 category if ( ($key == 'Root') || empty($key) ) { $key = POST_CAT_URL . '0'; } if ( isset($sub_templates[$key]) ) { // get the sub-template path $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir']; $root_template_path = $real_root . '/' . $sub_templates[$key]['dir']; // set the filename if ( empty($sub_tpl_file) && file_exists($root_template_path . '/' . $filename) ) { $found = true; $sub_tpl_file = $sub_templates[$key]['dir'] . '/' . $filename; break; } } } // set the css file name $found = false; $num_fids = count($fids); for ($i = 0; !$found && ($i < $num_fids); $i++) { $key = $fids[$i]; // convert root into c0 category if ( ($key == 'Root') || empty($key) ) { $key = POST_CAT_URL . '0'; } if ( isset($sub_templates[$key]) ) { // get the sub-template path $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir']; $root_template_path = $real_root . '/' . $sub_templates[$key]['dir']; if ( empty($sub_css_file) && isset($sub_templates[$key]['head_stylesheet']) && file_exists($root_template_path . '/' . $sub_templates[$key]['head_stylesheet']) ) { $found = true; $sub_css_file = $sub_templates[$key]['dir'] . '/' . $sub_templates[$key]['head_stylesheet']; break; } } } // set the img file name $found = false; $num_fids = count($fids); for ($i = 0; !$found && ($i < $num_fids); $i++) { $key = $fids[$i]; // convert root into c0 category if ( ($key == 'Root') || empty($key) ) { $key = POST_CAT_URL . '0'; } if ( isset($sub_templates[$key]) ) { // get the sub-template path $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir']; $root_template_path = $real_root . '/' . $sub_templates[$key]['dir']; if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) ) { $sub_img_path = $sub_templates[$key]['dir']; $sub_img_file = $sub_templates[$key]['imagefile']; // send back the lowest level of the images file $found = true; $sub_template_key_image = $key; break; } } } } // set the tpl file if ( !empty($sub_tpl_file) ) { $filename = $sub_tpl_file; } // set the css file if ( !empty($sub_css_file) ) { $theme['head_stylesheet'] = $sub_css_file; } // get the root level images $key = POST_CAT_URL . '0'; if ( isset($sub_templates[$key]) ) { // get the sub-template path $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir']; $root_template_path = $real_root . '/' . $sub_templates[$key]['dir']; if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) ) { $sav_images = $images; $images = array(); @include($root_template_path . '/' . $sub_templates[$key]['imagefile']); $img_lang = ( file_exists($root_template_path . '/images/lang_' . $board_config['default_lang']) ) ? $board_config['default_lang'] : 'english'; foreach($images as $key => $value) { if ( !is_array($value) ) { $images[$key] = str_replace('{LANG}', 'lang_' . $img_lang, $value); } $sav_images[$key] = $images[$key]; } $images = $sav_images; $sav_images = array(); } } // get the current images if ( !empty($sub_template_key_image) && ($sub_template_key_image != POST_CAT_URL . '0') ) { $key = $sub_template_key_image; // get the sub-template path $current_template_path = $template_path . $template_name . '/' . $sub_templates[$key]['dir']; $root_template_path = $real_root . '/' . $sub_templates[$key]['dir']; if ( isset($sub_templates[$key]['imagefile']) && file_exists($root_template_path . '/' . $sub_templates[$key]['imagefile']) ) { $sav_images = $images; $images = array(); @include($root_template_path . '/' . $sub_templates[$key]['imagefile']); $img_lang = ( file_exists($root_template_path . '/images/lang_' . $board_config['default_lang']) ) ? $board_config['default_lang'] : 'english'; foreach($images as $key => $value) { if ( !is_array($value) ) { $images[$key] = str_replace('{LANG}', 'lang_' . $img_lang, $value); } $sav_images[$key] = $images[$key]; } $images = $sav_images; $sav_images = array(); } } } return $filename; } /** * Generates a full path+filename for the given filename, which can either * be an absolute name, or a name relative to the rootdir for this Template * object. */ function make_filename($filename, $xs_include = false) { if($this->subtemplates) { $filename = $this->subtemplates_make_filename($filename); } // Check replacements list if(!$xs_include && isset($this->replace[$filename])) { $filename = $this->replace[$filename]; } // Check if it's an absolute or relative path. if ((substr($filename, 0, 1) !== '/') && (substr($filename, 1, 1) !== ':')) { return $this->root . '/' . $filename; } else { return str_replace('\\', '/', $filename); } } /** * Converts template filename to cache filename. * Returns empty string if non-cachable (for tpl files outside of root dir). * $file should be absolute filename */ function make_filename_cache($file) { $str = str_replace($this->cache_search, $this->cache_replace, $file); if(substr($file, 0, $this->tpldir_len) !== $this->tpldir || empty($this->tpl)) { return $this->cachedir . XS_TPL_PREFIX2 . $str; } // removing not needed part $file = substr($file, $this->tpldir_len, strlen($file)); // creating filename return $this->cachedir . XS_TPL_PREFIX . str_replace($this->cache_search, $this->cache_replace, $file); } /** * Sets the template filenames for handles. $filename_array * should be a hash of handle => filename pairs. */ function set_filenames($filename_array) { if (!is_array($filename_array)) { return false; } foreach($filename_array as $handle => $filename) { $this->set_filename($handle, $filename); } return true; } /** * Assigns template filename for handle. */ function set_filename($handle, $filename, $xs_include = false, $quiet = false) { global $board_config; $can_cache = $this->use_cache; if(strpos($filename, '..') !== false) { $can_cache = false; } $this->files[$handle] = $this->make_filename($filename, $xs_include); $this->files_cache[$handle] = ''; $this->files_cache2[$handle] = ''; // check if we are in admin control panel and override extreme styles mod controls if needed if(defined('XS_ADMIN_OVERRIDE') && XS_ADMIN_OVERRIDE === true && @function_exists('xs_admin_override')) { xs_admin_override(); } // checking if we have valid filename if(!$this->files[$handle]) { if($xs_include || $quiet) { return false; } else { die("Template->make_filename(): Error - invalid template $filename"); } } // creating cache filename if($can_cache) { $this->files_cache2[$handle] = $this->make_filename_cache($this->files[$handle]); if(@file_exists($this->files_cache2[$handle])) { $this->files_cache[$handle] = $this->files_cache2[$handle]; } } // checking if tpl and/or php file exists if(empty($this->files_cache[$handle]) && !@file_exists($this->files[$handle])) { // trying to load alternative filename (usually subSilver) if(!empty($this->tpldef) && !empty($this->tpl) && ($this->tpldef !== $this->tpl)) { $this->files[$handle] = ''; // save old configuration $root = $this->root; $tpl_name = $this->tpl; // set temporary configuration $this->root = $this->tpldir . $this->tpldef; $this->tpl = $this->tpldef; // recursively run set_filename $res = $this->set_filename($handle, $filename, $xs_include, $quiet); // restore old configuration $this->root = $root; $this->tpl = $tpl_name; return $res; } if($quiet) { return false; } if($xs_include) { if($board_config['xs_warn_includes']) { die('Template->make_filename(): Error - included template file not found: ' . $filename); } return false; } else { die('Template->make_filename(): Error - template file not found: ' . $filename); } } // checking if we should recompile cache if(!empty($this->files_cache[$handle]) && !empty($board_config['xs_auto_recompile'])) { $cache_time = @filemtime($this->files_cache[$handle]); if(@filemtime($this->files[$handle]) > $cache_time || $board_config['xs_template_time'] > $cache_time) { // file was changed. don't use cache file (will be recompled if configuration allowes it) $this->files_cache[$handle] = ''; } } return true; } /** * includes file or executes code */ function execute($filename, $code, $handle) { global $lang, $theme, $board_config; $template = $theme['template_name']; global $$template; $theme_info = &$$template; if($board_config['xs_add_comments'] && $handle) { echo ''; } if($filename) { include($filename); } else { eval($code); } if($board_config['xs_add_comments'] && $handle) { echo ''; } return true; } /** * Load the file for the handle, compile the file, * and run the compiled code. This will print out * the results of executing the template. */ function pparse($handle) { global $board_config; // parsing header if there is one if($this->preparse || $this->postparse) { $preparse = $this->preparse; $postparse = $this->postparse; $this->preparse = ''; $this->postparse = ''; if($preparse) { $this->pparse($preparse); } if($postparse) { $str = $handle; $handle = $postparse; $this->pparse($str); } } // checking if handle exists if (empty($this->files[$handle]) && empty($this->files_cache[$handle])) { die("Template->loadfile(): No files found for handle $handle"); } $this->xs_startup(); $force_recompile = empty($this->uncompiled_code[$handle]) ? false : true; // checking if php file exists. if (!empty($this->files_cache[$handle]) && !$force_recompile) { // php file exists - running it instead of tpl $this->execute($this->files_cache[$handle], '', $handle); return true; } if (!$this->loadfile($handle)) { die("Template->pparse(): Couldn't load template file for handle $handle"); } // actually compile the template now. if (empty($this->compiled_code[$handle])) { // Actually compile the code now. if(!empty($this->files_cache2[$handle]) && empty($this->files_cache[$handle]) && !$force_recompile) { $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], $handle, $this->files_cache2[$handle]); } else { $this->compiled_code[$handle] = $this->compile2($this->uncompiled_code[$handle], '', ''); } } // Run the compiled code. if (empty($this->files_cache[$handle]) || $force_recompile) { $this->execute('', $this->compiled_code[$handle], $handle); } else { $this->execute($this->files_cache[$handle], '', $handle); } return true; } /** * Precompile file */ function precompile($template, $filename) { global $precompile_num, $board_config; if(empty($precompile_num)) { $precompile_num = 0; } $precompile_num ++; $handle = 'precompile_' . $precompile_num; // save old configuration $root = $this->root; $tpl_name = $this->tpl; $old_config = $this->use_cache; $old_autosave = $this->auto_compile; // set temporary configuration $this->root = $this->tpldir . $template; $this->tpl = $template; $this->use_cache = 1; $this->auto_compile = 1; // set filename $res = $this->set_filename($handle, $filename, true, true); if(!$res || !$this->files_cache2[$handle]) { $this->root = $root; $this->tpl = $tpl_name; $this->use_cache = $old_config; $this->auto_compile = $old_autosave; return false; } $this->files_cache[$handle] = ''; // load template $res = $this->loadfile($handle); if(!$res || empty($this->uncompiled_code[$handle])) { $this->root = $root; $this->tpl = $tpl_name; $this->use_cache = $old_config; $this->auto_compile = $old_autosave; return false; } // compile the code $this->compile2($this->uncompiled_code[$handle], $handle, $this->files_cache2[$handle]); // restore confirugation $this->root = $root; $this->tpl = $tpl_name; $this->use_cache = $old_config; $this->auto_compile = $old_autosave; return true; } /** * Inserts the uncompiled code for $handle as the * value of $varname in the root-level. This can be used * to effectively include a template in the middle of another * template. * Note that all desired assignments to the variables in $handle should be done * BEFORE calling this function. */ function assign_var_from_handle($varname, $handle) { ob_start(); $res = $this->pparse($handle); $this->vars[$varname] = ob_get_contents(); ob_end_clean(); return $res; } /** * Block-level variable assignment. Adds a new block iteration with the given * variable assignments. Note that this should only be called once per block * iteration. */ function assign_block_vars($blockname, $vararray) { if (strstr($blockname, '.')) { // Nested block. $blocks = explode('.', $blockname); $blockcount = sizeof($blocks) - 1; $str = &$this->_tpldata; for($i = 0; $i < $blockcount; $i++) { $str = &$str[$blocks[$i].'.']; $str = &$str[sizeof($str)-1]; } // Now we add the block that we're actually assigning to. // We're adding a new iteration to this block with the given // variable assignments. $str[$blocks[$blockcount].'.'][] = $vararray; } else { // Top-level block. // Add a new iteration to this block with the variable assignments // we were given. $this->_tpldata[$blockname.'.'][] = $vararray; } return true; } /** * Root-level variable assignment. Adds to current assignments, overriding * any existing variable assignment with the same name. */ function assign_vars($vararray) { foreach($vararray as $key => $val) { $this->vars[$key] = $val; } return true; } /** * Root-level variable assignment. Adds to current assignments, overriding * any existing variable assignment with the same name. */ function assign_var($varname, $varval) { $this->vars[$varname] = $varval; return true; } /** * If not already done, load the file for the given handle and populate * the uncompiled_code[] hash with its code. Do not compile. */ function loadfile($handle) { global $board_config; // If cached file exists do nothing - it will be included via include() if(!empty($this->files_cache[$handle])) { return true; } // If the file for this handle is already loaded and compiled, do nothing. if (!empty($this->uncompiled_code[$handle])) { return true; } // If we don't have a file assigned to this handle, die. if (empty($this->files[$handle])) { die("Template->loadfile(): No file specified for handle $handle"); } $filename = $this->files[$handle]; $str = implode('', @file($filename)); if (empty($str)) { die("Template->loadfile(): File $filename for handle $handle is empty"); } $this->uncompiled_code[$handle] = $str; return true; } /** * Generates a reference to the given variable inside the given (possibly nested) * block namespace. This is a string of the form: * ' . $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['varname'] . ' * It's ready to be inserted into an "echo" line in one of the templates. * NOTE: expects a trailing "." on the namespace. */ function generate_block_varref($namespace, $varname, $use_isset = true) { // Strip the trailing period. $namespace = substr($namespace, 0, strlen($namespace) - 1); // Get a reference to the data block for this namespace. $varref = $this->generate_block_data_ref($namespace, true); // Prepend the necessary code to stick this in an echo line. // Append the variable reference. $varref .= '[\'' . $varname . '\']'; if($use_isset) { $varref = '<'.'?php echo isset(' . $varref . ') ? ' . $varref . ' : \'\'; ?'.'>'; } else { $varref = '<'.'?php echo ' . $varref . '; ?'.'>'; } return $varref; } /** * Generates a reference to the array of data values for the given * (possibly nested) block namespace. This is a string of the form: * $this->_tpldata['parent.'][$_parent_i]['$child1.'][$_child1_i]['$child2.'][$_child2_i]...['$childN.'] * * If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above. * NOTE: does not expect a trailing "." on the blockname. */ function generate_block_data_ref($blockname, $include_last_iterator, $defop = false) { // Get an array of the blocks involved. $blocks = explode('.', $blockname); $blockcount = sizeof($blocks) - 1; if($defop) { $varref = '$this->_tpldata[\'DEFINE\']'; // Build up the string with everything but the last child. for ($i = 0; $i < $blockcount; $i++) { $varref .= "['" . $blocks[$i] . ".'][\$" . $blocks[$i] . '_i]'; } // Add the block reference for the last child. $varref .= "['" . $blocks[$blockcount] . ".']"; // Add the iterator for the last child if requried. if ($include_last_iterator) { $varref .= '[$' . $blocks[$blockcount] . '_i]'; } return $varref; } if($include_last_iterator) { return '$'. $blocks[$blockcount]. '_item'; } else { return '$'. $blocks[$blockcount-1]. '_item[\''. $blocks[$blockcount]. '.\']'; } } function compile_code($filename, $code, $use_isset = false) { // $filename - file to load code from. used if $code is empty // $code - tpl code // $use_isset - if false then compiled code looks more beautiful and easier // to understand and it adds error_reporting() to supress php warnings. // if true then isset() is used to check variables instead of supressing // php warnings. note: for extreme styles mod 2.x it works only for // block variables and for usual variables its always true. // load code from file if(!$code && !empty($filename)) { $code = @implode('', @file($filename)); } // Replace phpBB 2.2 tags $search = array('', ''); $replace = array('<'.'?php ', ' ?'.'>'); $code = str_replace($search, $replace, $code); // Break it up into lines and put " -->" back. $code_lines = explode(' -->', $code); $count = count($code_lines); for ($i = 0; $i < ($count - 1); $i++) { $code_lines[$i] .= ' -->'; } $block_nesting_level = 0; $block_names = array(); $block_names[0] = "."; $block_items = array(); $count_if = 0; // prepare array for compiled code $compiled = array(); $count_bugs = count($this->bugs); // array of switches $sw = array(); // replace all short php tags $new_code = array(); $line_count = count($code_lines); for($i=0; $i<$line_count; $i++) { $line = $code_lines[$i]; $pos = strpos($line, ''; $code_lines[$i] = substr($line, $pos + 2); $i --; } $code_lines = $new_code; // main loop $line_count = count($code_lines); for($i=0; $i<$line_count; $i++) { $line = $code_lines[$i]; // reset keyword type $keyword_type = XS_TAG_NONE; // check if we have valid keyword in current line $pos1 = strpos($line, '', $pos1); if($pos2 !== false) { // find end of keyword in comment $pos3 = strpos($line, ' ', $pos1 + 5); if($pos3 !== false && $pos3 <= $pos2) { $keyword = substr($line, $pos1 + 5, $pos3 - $pos1 - 5); // check keyword against list of supported keywords. case-sensitive if($keyword === 'BEGIN') { $keyword_type = XS_TAG_BEGIN; } elseif($keyword === 'END') { $keyword_type = XS_TAG_END; } elseif($keyword === 'INCLUDE') { $keyword_type = XS_TAG_INCLUDE; } elseif($keyword === 'IF') { $keyword_type = XS_TAG_IF; } elseif($keyword === 'ELSE') { $keyword_type = XS_TAG_ELSE; } elseif($keyword === 'ELSEIF') { $keyword_type = XS_TAG_ELSEIF; } elseif($keyword === 'ENDIF') { $keyword_type = XS_TAG_ENDIF; } elseif($keyword === 'DEFINE') { $keyword_type = XS_TAG_DEFINE; } elseif($keyword === 'UNDEFINE') { $keyword_type = XS_TAG_UNDEFINE; } elseif($keyword === 'BEGINELSE') { $keyword_type = XS_TAG_BEGINELSE; } } } if(!$keyword_type) { // not valid keyword. process the rest of line $compiled[] = $this->_compile_text(substr($line, 0, $pos1 + 4), $use_isset); $code_lines[$i] = substr($line, $pos1 + 4); $i --; continue; } // remove code before keyword if($pos1 > 0) { $compiled[] = $this->_compile_text(substr($line, 0, $pos1), $use_isset); } // remove keyword $keyword_str = substr($line, $pos1, $pos2 - $pos1 + 4); $params_str = $pos2 == $pos3 ? '' : substr($line, $pos3 + 1, $pos2 - $pos3 - 1); $code_lines[$i] = substr($line, $pos2 + 4); $i--; // Check keywords /* * */ if($keyword_type == XS_TAG_BEGIN) { $params = explode(' ', $params_str); $num_params = count($params); // get variable name if($num_params == 1) { $var = $params[0]; } elseif($num_params == 2) { if($params[0] === '') { $var = $params[1]; } elseif($params[1] === '') { $var = $params[0]; } else { // invalid tag $compiled[] = $keyword_str; continue; } } else { // invalid tag $compiled[] = $keyword_str; continue; } // check variable for matching end if($this->xs_check_switches) { $found = 0; $str = ''; for ($j = $i+1; ($j < $line_count) && !$found; $j++) { $pos = strpos($code_lines[$j], $str); if($pos !== false) { $found = 1; $found_var = $var; } } if(!$found && ($this->xs_check_switches == 1)) { // checking list of known buggy switches $item = -1; for($j=0; $j<$count_bugs; $j++) { if($this->bugs[$j][0] === $var) { $item = $j; } } if($item >= 0) { $str1 = ''; for ($j = $i+1; ($j < $line_count) && !$found; $j++) { $pos = strpos($code_lines[$j], $str1); if($pos !== false) { $found_var = $this->bugs[$item][1]; $found = 1; $code_lines[$j] = str_replace($str, $str1, $code_lines[$j]); } } } } if(!$found) { $compiled[] = $keyword_str; continue; } // adding to list of switches if(isset($sw[$found_var])) { $sw[$found_var] ++; } else { $sw[$found_var] = 1; } } // adding code $block_nesting_level++; $block_names[$block_nesting_level] = $var; if(isset($block_items[$var])) { $block_items[$var] ++; } else { $block_items[$var] = 1; } if ($block_nesting_level < 2) { // Block is not nested. $line = '<'."?php\n\n"; if($use_isset) { $line .= '$'. $var. '_count = ( isset($this->_tpldata[\''. $var. '.\']) ) ? sizeof($this->_tpldata[\''. $var. '.\']) : 0;'; } else { $line .= '$'. $var. '_count = sizeof($this->_tpldata[\''. $var. '.\']);'; } $line .= "\n" . 'for ($'. $var. '_i = 0; $'. $var. '_i < $'. $var. '_count; $'. $var. '_i++)'; $line .= "\n". '{'. "\n"; $line .= ' $'. $var. '_item = &$this->_tpldata[\''. $var. '.\'][$'. $var. '_i];'."\n"; $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n"; $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n"; $line .= "\n?".">"; } else { // This block is nested. // Generate a namespace string for this block. $namespace = implode('.', $block_names); // strip leading period from root level.. $namespace = substr($namespace, 2); // Get a reference to the data array for this block that depends on the // current indices of all parent blocks. $varref = $this->generate_block_data_ref($namespace, false); // Create the for loop code to iterate over this block. $line = '<'."?php\n\n"; if($use_isset) { $line .= '$'. $var. '_count = ( isset('. $varref. ') ) ? sizeof('. $varref. ') : 0;'; } else { $line .= '$'. $var. '_count = sizeof('. $varref. ');'; } $line .= "\n". 'for ($'. $var. '_i = 0; $'. $var. '_i < $'. $var. '_count; $'. $var. '_i++)'; $line .= "\n". '{'. "\n"; $line .= ' $'. $var. '_item = &'. $varref. '[$'. $var. '_i];'."\n"; $line .= " \${$var}_item['S_ROW_COUNT'] = \${$var}_i;\n"; $line .= " \${$var}_item['S_NUM_ROWS'] = \${$var}_count;\n"; $line .= "\n?".">"; } $compiled[] = $line; continue; } /* * */ if($keyword_type == XS_TAG_END) { $params = explode(' ', $params_str); $num_params = count($params); if($num_params == 1) { $var = $params[0]; } elseif($num_params == 2 && $params[0] === '') { $var = $params[1]; } elseif($num_params == 2 && $params[1] === '') { $var = $params[0]; } else { $compiled[] = $keyword_str; continue; } if($this->xs_check_switches) { // checking if this switch was opened if(!isset($sw[$var]) || ($sw[$var] < 1)) { // there is no opening switch $compiled[] = $keyword_str; continue; } $sw[$var] --; } // We have the end of a block. $line = '<'."?php\n\n"; $line .= '} // END ' . $var . "\n\n"; $line .= 'if(isset($' . $var . '_item)) { unset($' . $var . '_item); } '; $line .= "\n\n?".">"; if(isset($block_items[$var])) { $block_items[$var] --; } else { $block_items[$var] = -1; } unset($block_names[$block_nesting_level]); $block_nesting_level--; $compiled[] = $line; continue; } /* * */ if($keyword_type == XS_TAG_BEGINELSE) { if($block_nesting_level) { $var = $block_names[$block_nesting_level]; $compiled[] = '<' . '?php } if(!$' . $var . '_count) { ?' . '>'; } else { $compiled[] = $keyword_str; continue; } } /* * */ if($keyword_type == XS_TAG_INCLUDE) { $params = explode(' ', $params_str); $num_params = count($params); if($num_params != 1) { $compiled[] = $keyword_str; continue; } $line = '<'.'?php '; $filehash = md5($params_str . $this->include_count . time()); $line .= ' $this->set_filename(\'xs_include_' . $filehash . '\', \'' . $params_str .'\', true); '; $line .= ' $this->pparse(\'xs_include_' . $filehash . '\'); '; $line .= ' ?'.'>'; $this->include_count ++; $compiled[] = $line; continue; } /* * */ if($keyword_type == XS_TAG_IF || $keyword_type == XS_TAG_ELSEIF) { if(!$count_if) { $keyword_type = XS_TAG_IF; } $str = $this->compile_tag_if($params_str, $keyword_type == XS_TAG_IF ? false : true); if($str) { $compiled[] = ''; if($keyword_type == XS_TAG_IF) { $count_if ++; } } else { $compiled[] = $keyword_str; } continue; } /* * */ if($keyword_type == XS_TAG_ELSE && $count_if > 0) { $compiled[] = ''; continue; } /* * */ if($keyword_type == XS_TAG_ENDIF && $count_if > 0) { $compiled[] = ''; $count_if --; continue; } /* * */ if($keyword_type == XS_TAG_DEFINE) { $str = $this->compile_tag_define($params_str); if($str) { $compiled[] = ''; } else { $compiled[] = $keyword_str; } } /* * */ if($keyword_type == XS_TAG_UNDEFINE) { $str = $this->compile_tag_undefine($params_str); if($str) { $compiled[] = ''; } else { $compiled[] = $keyword_str; } } } // bring it back into a single string. $code_header = ''; $code_footer = ''; if(!$use_isset) { $code_header = "<". "?php\n\$old_level = @error_reporting(E_ERROR | E_WARNING | E_PARSE); \n?".">"; $code_footer = '<'."?php @error_reporting(\$old_level); ?".'>'; } return $code_header . implode('', $compiled) . $code_footer; } /* * Compile code between tags */ function _compile_text($code, $use_isset) { if(strlen($code) < 3) { return $code; } // change template varrefs into PHP varrefs // This one will handle varrefs WITH namespaces $varrefs = array(); preg_match_all('#\{(([a-z0-9\-_]+?\.)+?)([a-z0-9\-_]+?)\}#is', $code, $varrefs); $varcount = sizeof($varrefs[1]); $search = array(); $replace = array(); for ($i = 0; $i < $varcount; $i++) { $namespace = $varrefs[1][$i]; $varname = $varrefs[3][$i]; $new = $this->generate_block_varref($namespace, $varname, $use_isset); $search[] = $varrefs[0][$i]; $replace[] = $new; } if(count($search) > 0) { $code = str_replace($search, $replace, $code); } // This will handle the remaining root-level varrefs $code = preg_replace('#\{([a-z0-9\-_]*?)\}#is', '<'.'?php echo isset($this->vars[\'\1\']) ? $this->vars[\'\1\'] : $this->lang(\'\1\'); ?'.'>', $code); $code = preg_replace('#\{\$([a-z0-9\-_]*?)\}#is', '<'.'?php echo isset($this->_tpldata[\'DEFINE\'][\'.\'][\'\\1\']) ? $this->_tpldata[\'DEFINE\'][\'.\'][\'\\1\'] : \'\'; ?'.'>', $code); return $code; } // // Compile IF tags - much of this is from Smarty with // some adaptions for our block level methods // function compile_tag_if($tag_args, $elseif) { /* Tokenize args for 'if' tag. */ preg_match_all('/(?: "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | [(),] | [^\s(),]+)/x', $tag_args, $match); $tokens = $match[0]; $is_arg_stack = array(); for ($i = 0; $i < count($tokens); $i++) { $token = &$tokens[$i]; switch ($token) { case '!': case '%': case '!==': case '==': case '===': case '>': case '<': case '!=': case '<>': case '<<': case '>>': case '<=': case '>=': case '&&': case '||': case '|': case '^': case '&': case '~': case ')': case ',': case '+': case '-': case '*': case '/': case '@': break; case 'eq': $token = '=='; break; case 'ne': case 'neq': $token = '!='; break; case 'lt': $token = '<'; break; case 'le': case 'lte': $token = '<='; break; case 'gt': $token = '>'; break; case 'ge': case 'gte': $token = '>='; break; case 'and': $token = '&&'; break; case 'or': $token = '||'; break; case 'not': $token = '!'; break; case 'mod': $token = '%'; break; case '(': array_push($is_arg_stack, $i); break; case 'is': $is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1; $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); array_splice($tokens, $is_arg_start, count($tokens), $new_tokens); $i = $is_arg_start; default: if (preg_match('#^(([a-z0-9\-_]+?\.)+?)?(\$)?([A-Z]+[A-Z0-9\-_]+)$#s', $token, $varrefs)) { $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] . '\']'); } break; } } $code = (($elseif) ? '} elseif (' : 'if (') . (implode(' ', $tokens) . ') { '); return $code; } // This is from Smarty function _parse_is_expr($is_arg, $tokens) { $expr_end = 0; $negate_expr = false; if (($first_token = array_shift($tokens)) == 'not') { $negate_expr = true; $expr_type = array_shift($tokens); } else { $expr_type = $first_token; } switch ($expr_type) { case 'even': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "!(($is_arg / $expr_arg) % $expr_arg)"; } else { $expr = "!($is_arg % 2)"; } break; case 'odd': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "(($is_arg / $expr_arg) % $expr_arg)"; } else { $expr = "($is_arg % 2)"; } break; case 'div': if (@$tokens[$expr_end] == 'by') { $expr_end++; $expr_arg = $tokens[$expr_end++]; $expr = "!($is_arg % $expr_arg)"; } break; default: break; } if ($negate_expr) { $expr = "!($expr)"; } array_splice($tokens, 0, $expr_end, $expr); return $tokens; } function compile_tag_define($tag_args) { preg_match('#^(([a-z0-9\-_]+?\.)+?)?\$([A-Z][A-Z0-9_\-]*?) = (\'?)(.*?)(\'?)$#', $tag_args, $match); if (empty($match[3]) || empty($match[5])) { return ''; } // Are we a string? if ($match[4] && $match[6]) { $match[5] = "'" . addslashes(str_replace(array('\\\'', '\\\\'), array('\'', '\\'), $match[5])) . "'"; } else { preg_match('#(true|false|\.)#i', $match[5], $type); switch (strtolower($type[1])) { case 'true': case 'false': $match[5] = strtoupper($match[5]); break; case '.'; $match[5] = doubleval($match[5]); break; default: $match[5] = intval($match[5]); break; } } return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[3] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[3] . '\']') . ' = ' . $match[5] . ';'; } function compile_tag_undefine($tag_args) { preg_match('#^(([a-z0-9\-_]+?\.)+?)?\$([A-Z][A-Z0-9_\-]*?)$#', $tag_args, $match); if (empty($match[3])) { return ''; } return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[3] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[3] . '\']') . ');'; } /** * Compiles code and writes to cache if needed */ function compile2($code, $handle, $cache_file) { $code = $this->compile_code('', $code, XS_USE_ISSET); if($cache_file && !empty($this->use_cache) && !empty($this->auto_compile)) { $res = $this->write_cache($cache_file, $code); if($handle && $res) { $this->files_cache[$handle] = $cache_file; } } $code = '?'.'>'.$code.'<'."?php\n"; return $code; } /** * Compiles the given string of code, and returns * the result in a string. * If "do_not_echo" is true, the returned code will not be directly * executable, but can be used as part of a variable assignment * for use in assign_code_from_handle(). * This function isn't used and kept only for compatibility with original template.php */ function compile($code, $do_not_echo = false, $retvar = '') { $code = ' ?'.'>' . $this->compile_code('', $code, true) . '<'."?php \n"; if($do_not_echo) { $code = "ob_start();\n". $code. "\n\${$retvar} = ob_get_contents();\nob_end_clean();\n"; } return $code; } /** * Write cache to disk */ function write_cache($filename, $code) { // check if cache is writable if(!$this->cache_writable) { return false; } // check if filename is valid if(substr($filename, 0, strlen($this->cachedir)) !== $this->cachedir) { return false; } // try to open file $file = @fopen($filename, 'w'); if(!$file) { // try to create directories $dir = substr($filename, strlen($this->cachedir), strlen($filename)); $dirs = explode('/', $dir); $path = $this->cachedir; @umask(0); if(!@is_dir($path)) { if(!@mkdir($path)) { $this->cache_writable = 0; return false; } else { @chmod($path, 0777); } } $count = count($dirs); if($count > 0) for($i=0; $i<$count-1; $i++) { if($i>0) { $path .= '/'; } $path .= $dirs[$i]; if(!@is_dir($path)) { if(!@mkdir($path)) { $this->cache_writable = 0; return false; } else { @chmod($path, 0777); } } } // try to open file again after directories were created $file = @fopen($filename, 'w'); } if(!$file) { $this->cache_writable = 0; return false; } fputs($file, ""); fputs($file, $code); fclose($file); @chmod($filename, 0777); return true; } function xs_startup() { global $phpEx, $board_config, $phpbb_root_path; if(empty($this->xs_started)) { // adding predefined variables $this->xs_started = 1; // file extension with session ID (eg: "php?sid=123&" or "php?") // can be used to make custom URLs without modding phpbb // contains "&" or "?" at the end so you can easily append paramenters $php = append_sid($phpEx); if(strpos($php, '?')) { $php .= '&'; } else { $php .= '?'; } $this->vars['PHP'] = isset($this->vars['PHP']) ? $this->vars['PHP'] : $php; // adding language variable (eg: "english" or "german") // can be used to make truly multi-lingual templates $this->vars['LANG'] = isset($this->vars['LANG']) ? $this->vars['LANG'] : $board_config['default_lang']; // adding current template $tpl = $this->root . '/'; // $phpbb_root_path . 'templates/' . $this->tpl . '/'; if(substr($tpl, 0, 2) === './') { $tpl = substr($tpl, 2, strlen($tpl)); } $this->vars['TEMPLATE'] = isset($this->vars['TEMPLATE']) ? $this->vars['TEMPLATE'] : $tpl; $this->vars['TEMPLATE_NAME'] = isset($this->vars['TEMPLATE_NAME']) ? $this->vars['TEMPLATE_NAME'] : $this->tpl; $this->_tpldata['switch_xs_enabled.'] = array(array('version' => $this->xs_versiontxt)); } } /** * Checks for empty variable and shows language variable if possible. */ function lang($var) { global $lang; if(substr($var, 0, 2) === 'L_') { $var = substr($var, 2); // check variable as it is if(isset($lang[$var])) { return $lang[$var]; } // check variable in lower case if(isset($lang[strtolower($var)])) { return $lang[strtolower($var)]; } // check variable with first letter in upper case $str = ucfirst(strtolower($var)); if(isset($lang[$str])) { return $lang[$str]; } return ''; //str_replace('_', ' ', $var); } return ''; } // // // Functions added for USERGROUP MOD (optimized) // // function append_var_from_handle_to_block($blockname, $varname, $handle) { $this->assign_var_from_handle('_tmp', $handle); // assign the value of the generated variable to the given varname. $this->append_block_vars($blockname, array($varname => $this->vars['_tmp'])); return true; } function append_block_vars($blockname, $vararray) { if(strstr($blockname, '.')) { // Nested block. $blocks = explode('.', $blockname); $blockcount = sizeof($blocks) - 1; $str = &$this->_tpldata; for($i = 0; $i < $blockcount; $i++) { $str = &$str[$blocks[$i].'.']; $str = &$str[sizeof($str)-1]; } // Now we add the block that we're actually assigning to. // We're adding a new iteration to this block with the given // variable assignments. $str = &$str[$blocks[$blockcount].'.']; $count = sizeof($str) - 1; if($count >= 0) { // adding only if there is at least one item $str[$count] = array_merge($str[$count], $vararray); } } else { // Top-level block. // Add a new iteration to this block with the variable assignments // we were given. $str = &$this->_tpldata[$blockname.'.']; $count = sizeof($str) - 1; if($count >= 0) { // adding only if there is at least one item $str[$count] = array_merge($str[$count], $vararray); } } return true; } /* * Flush a root level block, so it becomes empty. */ function flush_block_vars($blockname) { // Top-level block. // flush a existing block we were given. $current_iteration = sizeof($this->_tpldata[$blockname . '.']) - 1; unset($this->_tpldata[$blockname . '.']); return true; } /* * Add style configuration */ function _add_config($tpl, $add_vars = true) { global $phpbb_root_path; if(@file_exists($phpbb_root_path . 'templates/' . $tpl . '/xs_config.cfg')) { $style_config = array(); include($phpbb_root_path . 'templates/' . $tpl . '/xs_config.cfg'); if(count($style_config)) { global $board_config, $db; for($i=0; $istyle_config[$style_config[$i]['var']] = $style_config[$i]['default']; if($add_vars) { $this->vars['TPL_CFG_' . strtoupper($style_config[$i]['var'])] = $style_config[$i]['default']; } } $str = $this->_serialize($this->style_config); $config_name = 'xs_style_' . $tpl; $board_config[$config_name] = $str; $sql = "INSERT INTO " . CONFIG_TABLE . " (config_name, config_value) VALUES ('" . str_replace('\\\'', '\'\'', addslashes($config_name)) . "', '" . str_replace('\\\'', '\'\'', addslashes($str)) . "')"; $db->sql_query($sql); // recache config table for cat_hierarchy 2.1.0 global $config; if(isset($config->data) && $config->data === $board_config && isset($config->data['mod_cat_hierarchy'])) { $config->read(true); } return true; } } return false; } function add_config($tpl) { $config_name = 'xs_style_' . $tpl; global $board_config; $result = false; if(empty($board_config[$config_name])) { $old = $this->style_config; $result = $this->_add_config($tpl, false); $this->style_config = $old; } return $result; } /* * Refresh config data */ function _refresh_config($tpl, $add_vars = false) { global $phpbb_root_path; if(@file_exists($phpbb_root_path . 'templates/' . $tpl . '/xs_config.cfg')) { $style_config = array(); include($phpbb_root_path . 'templates/' . $tpl . '/xs_config.cfg'); if(count($style_config)) { global $board_config, $db; for($i=0; $istyle_config[$style_config[$i]['var']])) { $this->style_config[$style_config[$i]['var']] = $style_config[$i]['default']; if($add_vars) { $this->vars['TPL_CFG_' . strtoupper($style_config[$i]['var'])] = $style_config[$i]['default']; } } } $str = $this->_serialize($this->style_config); $config_name = 'xs_style_' . $tpl; if(isset($board_config[$config_name])) { $sql = "UPDATE " . CONFIG_TABLE . " SET config_value='" . str_replace('\\\'', '\'\'', addslashes($str)) . "' WHERE config_name='" . str_replace('\\\'', '\'\'', addslashes($config_name)) . "'"; } else { $sql = "INSERT INTO " . CONFIG_TABLE . " (config_name, config_value) VALUES ('" . str_replace('\\\'', '\'\'', addslashes($config_name)) . "', '" . str_replace('\\\'', '\'\'', addslashes($str)) . "')"; } $db->sql_query($sql); $board_config[$config_name] = $str; // recache config table for cat_hierarchy 2.1.0 global $config; if(isset($config->data) && $config->data === $board_config && isset($config->data['mod_cat_hierarchy'])) { $config->read(true); } return true; } } return false; } function refresh_config($tpl = '') { if($tpl === '') { $tpl = $this->tpl; } if($tpl == $this->tpl) { $result = $this->_refresh_config($tpl, true); } else { $old = $this->style_config; $result = $this->_refresh_config($tpl, false); $this->style_config = $old; } return $result; } /* * Get style configuration */ function _get_config($tpl, $add_config) { $this->style_config = array(); if(empty($tpl)) { $tpl = $this->tpl; } $config_name = 'xs_style_' . $tpl; global $board_config; if(empty($board_config[$config_name])) { if($add_config) { $this->_add_config($tpl, $tpl === $this->tpl ? true : false); } return $this->style_config; } $this->style_config = $this->_unserialize($board_config[$config_name]); if($tpl === $this->tpl) { foreach($this->style_config as $var => $value) { $this->vars['TPL_CFG_' . strtoupper($var)] = $value; } } return $this->style_config; } function get_config($tpl = '', $add_config = true) { if(empty($tpl)) { if(empty($this->tpl)) { return array(); } $this->_get_config($this->tpl, $add_config); return $this->style_config; } else { $old_config = $this->style_config; $result = $this->_get_config($tpl, $add_config); $this->style_config = $old_config; return $result; } } /* * Split/merge config data. * Using this function instead of (un)serialize because it generates smaller string so it can be stored in phpbb_config */ function _serialize($array) { if(!is_array($array)) { return ''; } $str = ''; foreach($array as $var => $value) { if($str) { $str .= '|'; } $str .= $var . '=' . str_replace('|', '', $value); } return $str; } function _unserialize($str) { $array = array(); $list = explode('|', $str); for($i=0; $i_tpldata[$name.'.']) && count($tpl->_tpldata[$name.'.']) > 0); } ?>