diff options
Diffstat (limited to 'phpBB/includes')
50 files changed, 2966 insertions, 3556 deletions
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index ecbaff6274..a9574628e1 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -317,7 +317,7 @@ class acp_bbcodes $bbcode_tpl = trim($bbcode_tpl); $utf8 = strpos($bbcode_match, 'INTTEXT') !== false; - $utf8_pcre_properties = pcre_utf8_support(); + $utf8_pcre_properties = phpbb_pcre_utf8_support(); $fp_match = preg_quote($bbcode_match, '!'); $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php index 8116fce6f0..bef8ae0ea9 100644 --- a/phpBB/includes/acp/acp_captcha.php +++ b/phpBB/includes/acp/acp_captcha.php @@ -46,7 +46,7 @@ class acp_captcha // Delegate if ($configure) { - $config_captcha =& phpbb_captcha_factory::get_instance($selected); + $config_captcha = phpbb_captcha_factory::get_instance($selected); $config_captcha->acp_page($id, $this); } else @@ -78,11 +78,11 @@ class acp_captcha // sanity check if (isset($captchas['available'][$selected])) { - $old_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); $old_captcha->uninstall(); set_config('captcha_plugin', $selected); - $new_captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $new_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); $new_captcha->install(); add_log('admin', 'LOG_CONFIG_VISUAL'); @@ -113,7 +113,7 @@ class acp_captcha $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang[$title] . '</option>'; } - $demo_captcha =& phpbb_captcha_factory::get_instance($selected); + $demo_captcha = phpbb_captcha_factory::get_instance($selected); foreach ($config_vars as $config_var => $options) { @@ -136,7 +136,7 @@ class acp_captcha { global $db, $user, $config; - $captcha =& phpbb_captcha_factory::get_instance($selected); + $captcha = phpbb_captcha_factory::get_instance($selected); $captcha->init(CONFIRM_REG); $captcha->execute_demo(); diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 96542986d3..632578ef2d 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -486,6 +486,8 @@ class base_extractor function base_extractor($download = false, $store = false, $format, $filename, $time) { + global $request; + $this->download = $download; $this->store = $store; $this->time = $time; @@ -530,7 +532,7 @@ class base_extractor break; case 'gzip': - if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false) + if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false) { ob_start('ob_gzhandler'); } @@ -1580,7 +1582,7 @@ class mssql_extractor extends base_extractor } $this->flush($sql_data); } - + function write_data_mssqlnative($table_name) { global $db; @@ -1606,7 +1608,7 @@ class mssql_extractor extends base_extractor $row = new result_mssqlnative($result_fields); $i_num_fields = $row->num_fields(); - + for ($i = 0; $i < $i_num_fields; $i++) { $ary_type[$i] = $row->field_type($i); @@ -1619,7 +1621,7 @@ class mssql_extractor extends base_extractor WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; $result2 = $db->sql_query($sql); $row2 = $db->sql_fetchrow($result2); - + if (!empty($row2['has_identity'])) { $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; @@ -1683,8 +1685,8 @@ class mssql_extractor extends base_extractor $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; } $this->flush($sql_data); - } - + } + function write_data_odbc($table_name) { global $db; diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 4d605e1b82..854f262a0b 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -875,7 +875,7 @@ class acp_forums $errors = array(); - if (!$forum_data['forum_name']) + if ($forum_data['forum_name'] == '') { $errors[] = $user->lang['FORUM_NAME_EMPTY']; } diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 8df8e5c8e5..ffa8df1848 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -797,11 +797,6 @@ class acp_language $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; $db->sql_query($sql); - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; - $result = $db->sql_query($sql); - - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']); trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); @@ -866,66 +861,6 @@ class acp_language $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); $lang_id = $db->sql_nextid(); - $valid_localized = array( - 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', - ); - - $sql_ary = array(); - - $sql = 'SELECT * - FROM ' . STYLES_IMAGESET_TABLE; - $result = $db->sql_query($sql); - while ($imageset_row = $db->sql_fetchrow($result)) - { - if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg")) - { - $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg"); - foreach ($cfg_data_imageset_data as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - if (in_array($image_name, $valid_localized)) - { - $sql_ary[] = array( - 'image_name' => (string) $image_name, - 'image_filename' => (string) $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $imageset_row['imageset_id'], - 'image_lang' => (string) $lang_pack['iso'], - ); - } - } - } - } - } - $db->sql_freeresult($result); - - if (sizeof($sql_ary)) - { - $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - } - // Now let's copy the default language entries for custom profile fields for this new language - makes admin's life easier. $sql = 'SELECT lang_id FROM ' . LANG_TABLE . " diff --git a/phpBB/includes/acp/acp_send_statistics.php b/phpBB/includes/acp/acp_send_statistics.php index aef67a8b1a..eb7154d114 100644 --- a/phpBB/includes/acp/acp_send_statistics.php +++ b/phpBB/includes/acp/acp_send_statistics.php @@ -16,8 +16,6 @@ if (!defined('IN_PHPBB')) exit; } -include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); - /** * @package acp */ @@ -27,7 +25,9 @@ class acp_send_statistics function main($id, $mode) { - global $config, $template, $phpbb_admin_path, $phpEx; + global $config, $template, $phpbb_admin_path, $phpbb_root_path, $phpEx; + + include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx); $collect_url = "http://www.phpbb.com/stats/receive_stats.php"; diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 18a90fb8e8..fc9acbbcb8 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -26,8 +26,6 @@ class acp_styles var $style_cfg; var $template_cfg; var $theme_cfg; - var $imageset_cfg; - var $imageset_keys; function main($id, $mode) { @@ -58,7 +56,7 @@ class acp_styles $style_id = request_var('id', 0); // Fill the configuration variables - $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = ' + $this->style_cfg = $this->template_cfg = $this->theme_cfg = ' # # phpBB {MODE} configuration file # @@ -83,19 +81,6 @@ copyright = {COPYRIGHT} version = {VERSION} '; - $this->theme_cfg .= ' -# Some configuration options - -# -# You have to turn this option on if you want to use the -# path template variables ({T_IMAGESET_PATH} for example) within -# your css file. -# This is mostly the case if you want to use language specific -# images within your css file. -# -parse_css_file = {PARSE_CSS_FILE} -'; - $this->template_cfg .= ' # Some configuration options @@ -105,33 +90,6 @@ parse_css_file = {PARSE_CSS_FILE} # Templates cannot inherit from inheriting templates. #'; - $this->imageset_keys = array( - 'logos' => array( - 'site_logo', - ), - 'buttons' => array( - 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', - ), - 'icons' => array( - 'icon_post_target', 'icon_post_target_unread', 'icon_topic_attach', 'icon_topic_latest', 'icon_topic_newest', 'icon_topic_reported', 'icon_topic_unapproved', 'icon_friend', 'icon_foe', - ), - 'forums' => array( - 'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread' - ), - 'folders' => array( - 'topic_moved', 'topic_read', 'topic_read_mine', 'topic_read_hot', 'topic_read_hot_mine', 'topic_read_locked', 'topic_read_locked_mine', 'topic_unread', 'topic_unread_mine', 'topic_unread_hot', 'topic_unread_hot_mine', 'topic_unread_locked', 'topic_unread_locked_mine', 'sticky_read', 'sticky_read_mine', 'sticky_read_locked', 'sticky_read_locked_mine', 'sticky_unread', 'sticky_unread_mine', 'sticky_unread_locked', 'sticky_unread_locked_mine', 'announce_read', 'announce_read_mine', 'announce_read_locked', 'announce_read_locked_mine', 'announce_unread', 'announce_unread_mine', 'announce_unread_locked', 'announce_unread_locked_mine', 'global_read', 'global_read_mine', 'global_read_locked', 'global_read_locked_mine', 'global_unread', 'global_unread_mine', 'global_unread_locked', 'global_unread_locked_mine', 'pm_read', 'pm_unread', - ), - 'polls' => array( - 'poll_left', 'poll_center', 'poll_right', - ), - 'ui' => array( - 'upload_bar', - ), - 'user' => array( - 'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10', - ), - ); - // Execute overall actions switch ($action) { @@ -174,8 +132,6 @@ parse_css_file = {PARSE_CSS_FILE} { switch ($mode) { - case 'imageset': - return $this->edit_imageset($style_id); case 'template': return $this->edit_template($style_id); case 'theme': @@ -251,7 +207,7 @@ parse_css_file = {PARSE_CSS_FILE} switch ($action) { - // Refresh template data stored in db and clear cache + // Clear cache case 'refresh': $sql = 'SELECT * @@ -268,49 +224,13 @@ parse_css_file = {PARSE_CSS_FILE} if (confirm_box(true)) { - $template_refreshed = ''; - - // Only refresh database if the template is stored in the database - if ($template_row['template_storedb'] && file_exists("{$phpbb_root_path}styles/{$template_row['template_path']}/template/")) - { - $filelist = array('' => array()); - - $sql = 'SELECT template_filename, template_mtime - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $style_id"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { -// if (@filemtime("{$phpbb_root_path}styles/{$template_row['template_path']}/template/" . $row['template_filename']) > $row['template_mtime']) -// { - // get folder info from the filename - if (($slash_pos = strrpos($row['template_filename'], '/')) === false) - { - $filelist[''][] = $row['template_filename']; - } - else - { - $filelist[substr($row['template_filename'], 0, $slash_pos + 1)][] = substr($row['template_filename'], $slash_pos + 1, strlen($row['template_filename']) - $slash_pos - 1); - } -// } - } - $db->sql_freeresult($result); - - $this->store_templates('update', $style_id, $template_row['template_path'], $filelist); - unset($filelist); - - $template_refreshed = $user->lang['TEMPLATE_REFRESHED'] . '<br />'; - add_log('admin', 'LOG_TEMPLATE_REFRESHED', $template_row['template_name']); - } - $this->clear_template_cache($template_row); - trigger_error($template_refreshed . $user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); + trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); } else { - confirm_box(false, ($template_row['template_storedb']) ? $user->lang['CONFIRM_TEMPLATE_REFRESH'] : $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( + confirm_box(false, $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( 'i' => $id, 'mode' => $mode, 'action' => $action, @@ -325,209 +245,7 @@ parse_css_file = {PARSE_CSS_FILE} break; case 'theme': - - switch ($action) - { - // Refresh theme data stored in the database - case 'refresh': - - $sql = 'SELECT * - FROM ' . STYLES_THEME_TABLE . " - WHERE theme_id = $style_id"; - $result = $db->sql_query($sql); - $theme_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$theme_row) - { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (!$theme_row['theme_storedb']) - { - trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (confirm_box(true)) - { - if ($theme_row['theme_storedb'] && file_exists("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css")) - { - // Save CSS contents - $sql_ary = array( - 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/{$theme_row['theme_path']}/theme/stylesheet.css"), - 'theme_data' => $this->db_theme_data($theme_row) - ); - - $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE theme_id = $style_id"; - $db->sql_query($sql); - - $cache->destroy('sql', STYLES_THEME_TABLE); - - add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']); - trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action)); - } - } - else - { - confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array( - 'i' => $id, - 'mode' => $mode, - 'action' => $action, - 'id' => $style_id - ))); - } - break; - } - - $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete')); - break; - - case 'imageset': - - switch ($action) - { - case 'refresh': - - $sql = 'SELECT * - FROM ' . STYLES_IMAGESET_TABLE . " - WHERE imageset_id = $style_id"; - $result = $db->sql_query($sql); - $imageset_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$imageset_row) - { - trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (confirm_box(true)) - { - $sql_ary = array(); - - $imageset_definitions = array(); - foreach ($this->imageset_keys as $topic => $key_array) - { - $imageset_definitions = array_merge($imageset_definitions, $key_array); - } - - $cfg_data_imageset = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg"); - - $db->sql_transaction('begin'); - - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' - WHERE imageset_id = ' . $style_id; - $result = $db->sql_query($sql); - - foreach ($cfg_data_imageset as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - if (in_array($image_name, $imageset_definitions)) - { - $sql_ary[] = array( - 'image_name' => (string) $image_name, - 'image_filename' => (string) $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $style_id, - 'image_lang' => '', - ); - } - } - } - - $sql = 'SELECT lang_dir - FROM ' . LANG_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - if (@file_exists("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg")) - { - $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg"); - foreach ($cfg_data_imageset_data as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - if (in_array($image_name, $imageset_definitions)) - { - $sql_ary[] = array( - 'image_name' => (string) $image_name, - 'image_filename' => (string) $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $style_id, - 'image_lang' => (string) $row['lang_dir'], - ); - } - } - } - } - } - $db->sql_freeresult($result); - - $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); - - $db->sql_transaction('commit'); - - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - $cache->destroy('imageset_site_logo_md5'); - - add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']); - trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action)); - } - else - { - confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array( - 'i' => $id, - 'mode' => $mode, - 'action' => $action, - 'id' => $style_id - ))); - } - break; - } - - $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete')); + $this->frontend('theme', array('edit', 'details'), array('export', 'delete')); break; } } @@ -567,10 +285,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $l_prefix = strtoupper($mode); @@ -720,7 +434,7 @@ parse_css_file = {PARSE_CSS_FILE} $template_file = preg_replace('#\.{2,}#', '.', $template_file); // Retrieve some information about the template - $sql = 'SELECT template_storedb, template_path, template_name + $sql = 'SELECT template_path, template_name FROM ' . STYLES_TEMPLATE_TABLE . " WHERE template_id = $template_id"; $result = $db->sql_query($sql); @@ -732,6 +446,32 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); } + // Get the filesystem location of the current file + $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template"; + $file = "$template_path/$template_file"; + + if ($template_file) + { + $l_not_writable = sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action); + + if ($safe_mode) + { + trigger_error($l_not_writable, E_USER_WARNING); + } + + if (file_exists($file) && is_file($file) && is_readable($file)) + { + if (!phpbb_is_writable($file)) + { + trigger_error($l_not_writable, E_USER_WARNING); + } + } + else + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + if ($save_changes && !check_form_key('acp_styles')) { trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); @@ -744,50 +484,14 @@ parse_css_file = {PARSE_CSS_FILE} // save changes to the template if the user submitted any if ($save_changes && $template_file) { - // Get the filesystem location of the current file - $file = "{$phpbb_root_path}styles/{$template_info['template_path']}/template/$template_file"; - $additional = ''; - - // If the template is stored on the filesystem try to write the file else store it in the database - if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && phpbb_is_writable($file)) + // Try to write the file + if (!($fp = @fopen($file, 'wb'))) { - if (!($fp = @fopen($file, 'wb'))) - { - // File exists and is writeable, but still not able to be written to - trigger_error(sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action), E_USER_WARNING); - } - fwrite($fp, $template_data); - fclose($fp); - } - else - { - $db->sql_transaction('begin'); - - // If it's not stored in the db yet, then update the template setting and store all template files in the db - if (!$template_info['template_storedb']) - { - if ($super = $this->get_super('template', $template_id)) - { - $this->store_in_db('template', $super['template_id']); - } - else - { - $this->store_in_db('template', $template_id); - } - - add_log('admin', 'LOG_TEMPLATE_EDIT_DETAILS', $template_info['template_name']); - $additional .= '<br />' . $user->lang['EDIT_TEMPLATE_STORED_DB']; - } - - // Update the template_data table entry for this template file - $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . " - SET template_data = '" . $db->sql_escape($template_data) . "', template_mtime = " . time() . " - WHERE template_id = $template_id - AND template_filename = '" . $db->sql_escape($template_file) . "'"; - $db->sql_query($sql); - - $db->sql_transaction('commit'); + // File exists and is writeable, but still not able to be written to + trigger_error($l_not_writable, E_USER_WARNING); } + fwrite($fp, $template_data); + fclose($fp); // destroy the cached version of the template (filename without extension) $this->clear_template_cache($template_info, array(substr($template_file, 0, -5))); @@ -795,56 +499,22 @@ parse_css_file = {PARSE_CSS_FILE} $cache->destroy('sql', STYLES_TABLE); add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file); - trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); + trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); } // Generate a category array containing template filenames - if (!$template_info['template_storedb']) - { - $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template"; - $filelist = filelist($template_path, '', 'html'); - $filelist[''] = array_diff($filelist[''], array('bbcode.html')); + $filelist = filelist($template_path, '', 'html'); + $filelist[''] = array_diff($filelist[''], array('bbcode.html')); - if ($template_file) - { - if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file"))) - { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); - } - } - } - else + if ($template_file) { - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $template_id"; - $result = $db->sql_query($sql); + $template_data = file_get_contents($file); - $filelist = array('' => array()); - while ($row = $db->sql_fetchrow($result)) + if (!$template_data) { - $file_info = pathinfo($row['template_filename']); - - if (($file_info['basename'] != 'bbcode') && ($file_info['extension'] == 'html')) - { - if (($file_info['dirname'] == '.') || empty($file_info['dirname'])) - { - $filelist[''][] = $row['template_filename']; - } - else - { - $filelist[$file_info['dirname'] . '/'][] = $file_info['basename']; - } - } - - if ($row['template_filename'] == $template_file) - { - $template_data = $row['template_data']; - } + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); } - $db->sql_freeresult($result); - unset($file_info); } if (empty($filelist[''])) @@ -1015,35 +685,6 @@ parse_css_file = {PARSE_CSS_FILE} adm_page_footer(); } - $filemtime = array(); - if ($template_row['template_storedb']) - { - $ids = array(); - if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) - { - $ids[] = $template_row['template_inherits_id']; - } - $ids[] = $template_row['template_id']; - - $filemtime = array(); - $file_template_db = array(); - - foreach ($ids as $id) - { - $sql = 'SELECT template_filename, template_mtime - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $id"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $filemtime[$row['template_filename']] = $row['template_mtime']; - $file_template_db[$row['template_filename']] = $id; - } - $db->sql_freeresult($result); - } - } - // Get a list of cached template files and then retrieve additional information about them $file_ary = $this->template_cache_filelist($template_row['template_path']); @@ -1066,30 +707,10 @@ parse_css_file = {PARSE_CSS_FILE} $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html"; $inherited = false; - if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id']) - { - if (!$template_row['template_storedb']) - { - if (!file_exists($file_tpl)) - { - $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; - $inherited = true; - } - } - else - { - if ($file_template_db[$file . '.html'] == $template_row['template_inherits_id']) - { - $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; - $inherited = true; - } - } - } - - // Correct the filename if it is stored in database and the file is in a subfolder. - if ($template_row['template_storedb']) + if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'] && !file_exists($file_tpl)) { - $file = str_replace('.', '/', $file); + $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; + $inherited = true; } $template->assign_block_vars('file', array( @@ -1099,10 +720,9 @@ parse_css_file = {PARSE_CSS_FILE} 'FILENAME' => $file, 'FILENAME_PATH' => $file_tpl, 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")), - 'MODIFIED' => $user->format_date((!$template_row['template_storedb']) ? filemtime($file_tpl) : $filemtime[$file . '.html'])) - ); + 'MODIFIED' => $user->format_date(filemtime($file_tpl)), + )); } - unset($filemtime); $template->assign_vars(array( 'S_CACHE' => true, @@ -1136,7 +756,7 @@ parse_css_file = {PARSE_CSS_FILE} $theme_file = str_replace('..', '.', $theme_file); // Retrieve some information about the theme - $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data + $sql = 'SELECT theme_path, theme_name FROM ' . STYLES_THEME_TABLE . " WHERE theme_id = $theme_id"; $result = $db->sql_query($sql); @@ -1147,71 +767,62 @@ parse_css_file = {PARSE_CSS_FILE} } $db->sql_freeresult($result); - // save changes to the theme if the user submitted any - if ($save_changes) + // Get the filesystem location of the current file + $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme"; + $file = "$theme_path/$theme_file"; + + if ($theme_file) { - // Get the filesystem location of the current file - $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file"; - $additional = ''; - $message = $user->lang['THEME_UPDATED']; + $l_not_writable = sprintf($user->lang['THEME_FILE_NOT_WRITABLE'], htmlspecialchars($theme_file)) . adm_back_link($this->u_action); - // If the theme is stored on the filesystem try to write the file else store it in the database - if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && phpbb_is_writable($file)) + if ($safe_mode) { - if (!($fp = @fopen($file, 'wb'))) + trigger_error($l_not_writable, E_USER_WARNING); + } + + if (file_exists($file) && is_file($file) && is_readable($file)) + { + if (!phpbb_is_writable($file)) { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($l_not_writable, E_USER_WARNING); } - fwrite($fp, $theme_data); - fclose($fp); } else { - // Write stylesheet to db - $sql_ary = array( - 'theme_mtime' => time(), - 'theme_storedb' => 1, - 'theme_data' => $this->db_theme_data($theme_info, $theme_data), - ); - $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE theme_id = ' . $theme_id; - $db->sql_query($sql); + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } - $cache->destroy('sql', STYLES_THEME_TABLE); + // save changes to the theme if the user submitted any + if ($save_changes && $theme_file) + { + $message = $user->lang['THEME_UPDATED']; - // notify the user if the theme was not stored in the db before his modification - if (!$theme_info['theme_storedb']) - { - add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']); - $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB']; - } + if (!($fp = @fopen($file, 'wb'))) + { + trigger_error($l_not_writable, E_USER_WARNING); } + fwrite($fp, $theme_data); + fclose($fp); + $cache->destroy('sql', STYLES_THEME_TABLE); - add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : ''); + add_log('admin', 'LOG_THEME_EDIT_FILE', $theme_info['theme_name'], $theme_file); trigger_error($message . adm_back_link($this->u_action . "&action=edit&id=$theme_id&template_file=$theme_file&text_rows=$text_rows")); } // Generate a category array containing theme filenames - if (!$theme_info['theme_storedb']) - { - $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme"; + $filelist = filelist($theme_path, '', 'css'); - $filelist = filelist($theme_path, '', 'css'); + if ($theme_file) + { + $theme_data = file_get_contents($file); - if ($theme_file) + if (!$theme_data) { - if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file"))) - { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); } } - else - { - $theme_data = &$theme_info['theme_data']; - } // Now create the categories $filelist_cats[''] = array(); @@ -1274,7 +885,6 @@ parse_css_file = {PARSE_CSS_FILE} $template->assign_vars(array( 'S_EDIT_THEME' => true, 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)), - 'S_THEME_IN_DB' => $theme_info['theme_storedb'], 'S_TEMPLATES' => $tpl_options, 'U_ACTION' => $this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows", @@ -1292,289 +902,12 @@ parse_css_file = {PARSE_CSS_FILE} 'SELECTED_TEMPLATE' => $theme_info['theme_name'], 'TEMPLATE_FILE' => $theme_file, 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data), - 'TEXT_ROWS' => $text_rows) - ); - } - - /** - * Edit imagesets - * - * @param int $imageset_id specifies which imageset is being edited - */ - function edit_imageset($imageset_id) - { - global $db, $user, $phpbb_root_path, $cache, $template; - - $this->page_title = 'EDIT_IMAGESET'; - - if (!$imageset_id) - { - trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $update = (isset($_POST['update'])) ? true : false; - - $imgname = request_var('imgname', 'site_logo'); - $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); - $sql_extra = $imgnamelang = ''; - - $sql = 'SELECT imageset_path, imageset_name - FROM ' . STYLES_IMAGESET_TABLE . " - WHERE imageset_id = $imageset_id"; - $result = $db->sql_query($sql); - $imageset_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$imageset_row) - { - trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $imageset_path = $imageset_row['imageset_path']; - $imageset_name = $imageset_row['imageset_name']; - - if (strpos($imgname, '-') !== false) - { - list($imgname, $imgnamelang) = explode('-', $imgname); - $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; - } - - $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id - FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $imageset_id - AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; - $result = $db->sql_query($sql); - $imageset_data_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $image_filename = $imageset_data_row['image_filename']; - $image_width = $imageset_data_row['image_width']; - $image_height = $imageset_data_row['image_height']; - $image_lang = $imageset_data_row['image_lang']; - $image_id = $imageset_data_row['image_id']; - $imgsize = ($imageset_data_row['image_width'] && $imageset_data_row['image_height']) ? 1 : 0; - - // Check to see whether the selected image exists in the table - $valid_name = ($update) ? false : true; - - foreach ($this->imageset_keys as $category => $img_ary) - { - if (in_array($imgname, $img_ary)) - { - $valid_name = true; - break; - } - } - - if ($update && isset($_POST['imgpath']) && $valid_name) - { - // If imgwidth and imgheight are non-zero grab the actual size - // from the image itself ... we ignore width settings for the poll center image - $imgwidth = request_var('imgwidth', 0); - $imgheight = request_var('imgheight', 0); - $imgsize = request_var('imgsize', 0); - $imgpath = request_var('imgpath', ''); - $imgpath = str_replace('..', '.', $imgpath); - - // If no dimensions selected, we reset width and height to 0 ;) - if (!$imgsize) - { - $imgwidth = $imgheight = 0; - } - - $imglang = ''; - - if ($imgpath && !file_exists("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath")) - { - trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - // Determine width/height. If dimensions included and no width/height given, we detect them automatically... - if ($imgsize && $imgpath) - { - if (!$imgwidth || !$imgheight) - { - list($imgwidth_file, $imgheight_file) = getimagesize("{$phpbb_root_path}styles/$imageset_path/imageset/$imgpath"); - $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; - $imgheight = ($imgheight) ? $imgheight : $imgheight_file; - } - $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0; - $imgheight = (int) $imgheight; - } - - if (strpos($imgpath, '/') !== false) - { - list($imglang, $imgfilename) = explode('/', $imgpath); - } - else - { - $imgfilename = $imgpath; - } - - $sql_ary = array( - 'image_filename' => (string) $imgfilename, - 'image_width' => (int) $imgwidth, - 'image_height' => (int) $imgheight, - 'image_lang' => (string) $imglang, - ); - - // already exists - if ($imageset_data_row) - { - $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE image_id = $image_id"; - $db->sql_query($sql); - } - // does not exist - else if (!$imageset_data_row) - { - $sql_ary['image_name'] = $imgname; - $sql_ary['imageset_id'] = (int) $imageset_id; - $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - } - - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - - add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); - - $template->assign_var('SUCCESS', true); - - $image_filename = $imgfilename; - $image_width = $imgwidth; - $image_height = $imgheight; - $image_lang = $imglang; - } - - $imglang = ''; - $imagesetlist = array('nolang' => array(), 'lang' => array()); - $langs = array(); - - $dir = "{$phpbb_root_path}styles/$imageset_path/imageset"; - $dp = @opendir($dir); - - if ($dp) - { - while (($file = readdir($dp)) !== false) - { - if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file)) - { - $langs[] = $file; - } - else if (preg_match('#\.(?:gif|jpg|png)$#', $file)) - { - $imagesetlist['nolang'][] = $file; - } - } - - if ($sql_extra) - { - $dp2 = @opendir("$dir/$imgnamelang"); - - if ($dp2) - { - while (($file2 = readdir($dp2)) !== false) - { - if (preg_match('#\.(?:gif|jpg|png)$#', $file2)) - { - $imagesetlist['lang'][] = "$imgnamelang/$file2"; - } - } - closedir($dp2); - } - } - closedir($dp); - } - - // Generate list of image options - $img_options = ''; - foreach ($this->imageset_keys as $category => $img_ary) - { - $template->assign_block_vars('category', array( - 'NAME' => $user->lang['IMG_CAT_' . strtoupper($category)] - )); - - foreach ($img_ary as $img) - { - if ($category == 'buttons') - { - foreach ($langs as $language) - { - $template->assign_block_vars('category.images', array( - 'SELECTED' => ($img == $imgname && $language == $imgnamelang), - 'VALUE' => $img . '-' . $language, - 'TEXT' => $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]' - )); - } - } - else - { - $template->assign_block_vars('category.images', array( - 'SELECTED' => ($img == $imgname), - 'VALUE' => $img, - 'TEXT' => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)]) - )); - } - } - } - - // Make sure the list of possible images is sorted alphabetically - sort($imagesetlist['lang']); - sort($imagesetlist['nolang']); - - $image_found = false; - $img_val = ''; - foreach ($imagesetlist as $type => $img_ary) - { - if ($type !== 'lang' || $sql_extra) - { - $template->assign_block_vars('imagesetlist', array( - 'TYPE' => ($type == 'lang') - )); - } - - foreach ($img_ary as $img) - { - $imgtext = preg_replace('/^([^\/]+\/)/', '', $img); - $selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false); - if ($selected) - { - $image_found = true; - $img_val = htmlspecialchars($img); - } - $template->assign_block_vars('imagesetlist.images', array( - 'SELECTED' => $selected, - 'TEXT' => $imgtext, - 'VALUE' => htmlspecialchars($img) - )); - } - } - - $imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false; - $image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename; - - $template->assign_vars(array( - 'S_EDIT_IMAGESET' => true, - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'IMAGE_OPTIONS' => $img_options, - 'IMAGE_SIZE' => $image_width, - 'IMAGE_HEIGHT' => $image_height, - 'IMAGE_REQUEST' => (empty($image_filename)) ? 'images/no_image.png' : $image_request, - 'U_ACTION' => $this->u_action . "&action=edit&id=$imageset_id", - 'U_BACK' => $this->u_action, - 'NAME' => $imageset_name, - 'A_NAME' => addslashes($imageset_name), - 'PATH' => $imageset_path, - 'A_PATH' => addslashes($imageset_path), - 'ERROR' => !$valid_name, - 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png', - 'IMAGE_SELECT' => $image_found + 'TEXT_ROWS' => $text_rows, )); } /** - * Remove style/template/theme/imageset + * Remove style/template/theme */ function remove($mode, $style_id) { @@ -1588,23 +921,18 @@ parse_css_file = {PARSE_CSS_FILE} { case 'style': $sql_from = STYLES_TABLE; - $sql_select = 'style_id, style_name, template_id, theme_id, imageset_id'; + $sql_select = 'style_id, style_name, template_id, theme_id'; $sql_where = 'AND style_active = 1'; break; case 'template': $sql_from = STYLES_TEMPLATE_TABLE; - $sql_select = 'template_id, template_name, template_path, template_storedb'; + $sql_select = 'template_id, template_name, template_path'; break; case 'theme': $sql_from = STYLES_THEME_TABLE; - $sql_select = 'theme_id, theme_name, theme_path, theme_storedb'; - break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - $sql_select = 'imageset_id, imageset_name, imageset_path'; + $sql_select = 'theme_id, theme_name, theme_path'; break; } @@ -1658,7 +986,7 @@ parse_css_file = {PARSE_CSS_FILE} } // Remove the components - $components = array('template', 'theme', 'imageset'); + $components = array('template', 'theme'); foreach ($components as $component) { $new_id = request_var('new_' . $component . '_id', 0); @@ -1707,7 +1035,7 @@ parse_css_file = {PARSE_CSS_FILE} } /** - * Remove template/theme/imageset entry from the database + * Remove template/theme entry from the database */ function remove_component($component, $component_id, $new_id, $style_id = false) { @@ -1731,13 +1059,6 @@ parse_css_file = {PARSE_CSS_FILE} return; } - if ($component == 'imageset') - { - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $component_id"; - $db->sql_query($sql); - } - switch ($component) { case 'template': @@ -1747,10 +1068,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE;; - break; } $sql = "DELETE FROM $sql_from @@ -1764,7 +1081,7 @@ parse_css_file = {PARSE_CSS_FILE} } /** - * Display the options which can be used to replace a style/template/theme/imageset + * Display the options which can be used to replace a style/template/theme */ function display_component_options($component, $component_id, $style_row = false, $style_id = false) { @@ -1792,10 +1109,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $s_options = ''; @@ -1844,7 +1157,7 @@ parse_css_file = {PARSE_CSS_FILE} $template->assign_var('S_REPLACE_OPTIONS', $s_options); if ($component == 'style') { - $components = array('template', 'theme', 'imageset'); + $components = array('template', 'theme'); foreach ($components as $component) { $this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true); @@ -1906,7 +1219,6 @@ parse_css_file = {PARSE_CSS_FILE} $inc_template = request_var('inc_template', 0); $inc_theme = request_var('inc_theme', 0); - $inc_imageset = request_var('inc_imageset', 0); $store = request_var('store', 0); $format = request_var('format', ''); @@ -1932,7 +1244,7 @@ parse_css_file = {PARSE_CSS_FILE} switch ($mode) { case 'style': - if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1) + if ($update && ($inc_template + $inc_theme) < 1) { $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS']; } @@ -1942,9 +1254,8 @@ parse_css_file = {PARSE_CSS_FILE} $sql_select = 's.style_id, s.style_name, s.style_copyright'; $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name'; $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name'; - $sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name'; - $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i'; - $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id AND i.imageset_id = s.imageset_id"; + $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c'; + $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id"; $l_prefix = 'STYLE'; break; @@ -1968,16 +1279,6 @@ parse_css_file = {PARSE_CSS_FILE} $l_prefix = 'THEME'; break; - - case 'imageset': - $name = 'imageset_name'; - - $sql_select = '*'; - $sql_from = STYLES_IMAGESET_TABLE; - $sql_where = "imageset_id = $style_id"; - - $l_prefix = 'IMAGESET'; - break; } if ($update && !sizeof($error)) @@ -1994,7 +1295,7 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); } - $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_storedb', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); + $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright'); foreach ($var_ary as $var) { @@ -2012,7 +1313,6 @@ parse_css_file = {PARSE_CSS_FILE} $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : ''; $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : ''; - $style_cfg .= (!$inc_imageset) ? "\nrequired_imageset = {$style_row['imageset_name']}" : ''; $data[] = array( 'src' => $style_cfg, @@ -2050,31 +1350,12 @@ parse_css_file = {PARSE_CSS_FILE} ); // This is potentially nasty memory-wise ... - if (!$style_row['template_storedb']) - { - $files[] = array( - 'src' => "styles/{$style_row['template_path']}/template/", - 'prefix-' => "styles/{$style_row['template_path']}/", - 'prefix+' => false, - 'exclude' => 'template.cfg' - ); - } - else - { - $sql = 'SELECT template_filename, template_data - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = {$style_row['template_id']}"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $data[] = array( - 'src' => $row['template_data'], - 'prefix' => 'template/' . $row['template_filename'] - ); - } - $db->sql_freeresult($result); - } + $files[] = array( + 'src' => "styles/{$style_row['template_path']}/template/", + 'prefix-' => "styles/{$style_row['template_path']}/", + 'prefix+' => false, + 'exclude' => 'template.cfg' + ); unset($template_cfg); } @@ -2087,130 +1368,21 @@ parse_css_file = {PARSE_CSS_FILE} $items = $cache->obtain_cfg_items($style_row); $items = $items['theme']; - if (!isset($items['parse_css_file'])) - { - $items['parse_css_file'] = 'off'; - } - - $theme_cfg = str_replace(array('{PARSE_CSS_FILE}'), array($items['parse_css_file']), $theme_cfg); - $files[] = array( 'src' => "styles/{$style_row['theme_path']}/theme/", 'prefix-' => "styles/{$style_row['theme_path']}/", 'prefix+' => false, - 'exclude' => ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg' + 'exclude' => 'theme.cfg', ); $data[] = array( 'src' => $theme_cfg, - 'prefix' => 'theme/theme.cfg' + 'prefix' => 'theme/theme.cfg', ); - if ($style_row['theme_storedb']) - { - $data[] = array( - 'src' => $style_row['theme_data'], - 'prefix' => 'theme/stylesheet.css' - ); - } - unset($items, $theme_cfg); } - // Export imageset core code - if ($mode == 'imageset' || $inc_imageset) - { - $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); - - $imageset_main = array(); - - $sql = 'SELECT image_filename, image_name, image_height, image_width - FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $style_id - AND image_lang = ''"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $imageset_main[$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); - } - $db->sql_freeresult($result); - - foreach ($this->imageset_keys as $topic => $key_array) - { - foreach ($key_array as $key) - { - if (isset($imageset_main[$key])) - { - $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_main[$key]); - } - } - } - - $files[] = array( - 'src' => "styles/{$style_row['imageset_path']}/imageset/", - 'prefix-' => "styles/{$style_row['imageset_path']}/", - 'prefix+' => false, - 'exclude' => 'imageset.cfg' - ); - - $data[] = array( - 'src' => trim($imageset_cfg), - 'prefix' => 'imageset/imageset.cfg' - ); - - end($data); - - $imageset_root = "{$phpbb_root_path}styles/{$style_row['imageset_path']}/imageset/"; - - if ($dh = @opendir($imageset_root)) - { - while (($fname = readdir($dh)) !== false) - { - if ($fname[0] != '.' && $fname != 'CVS' && is_dir("$imageset_root$fname")) - { - $files[key($files)]['exclude'] .= ',' . $fname . '/imageset.cfg'; - } - } - closedir($dh); - } - - $imageset_lang = array(); - - $sql = 'SELECT image_filename, image_name, image_height, image_width, image_lang - FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $style_id - AND image_lang <> ''"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $imageset_lang[$row['image_lang']][$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); - } - $db->sql_freeresult($result); - - foreach ($imageset_lang as $lang => $imageset_localized) - { - $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); - - foreach ($this->imageset_keys as $topic => $key_array) - { - foreach ($key_array as $key) - { - if (isset($imageset_localized[$key])) - { - $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_localized[$key]); - } - } - } - - $data[] = array( - 'src' => trim($imageset_cfg), - 'prefix' => 'imageset/' . $lang . '/imageset.cfg' - ); - } - - unset($imageset_cfg); - } - switch ($format) { case 'tar': @@ -2335,7 +1507,7 @@ parse_css_file = {PARSE_CSS_FILE} $l_type = strtoupper($mode); $error = array(); - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); switch ($mode) { @@ -2350,10 +1522,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $sql = "SELECT * @@ -2377,11 +1545,9 @@ parse_css_file = {PARSE_CSS_FILE} $template_id = request_var('template_id', 0); $theme_id = request_var('theme_id', 0); - $imageset_id = request_var('imageset_id', 0); $style_active = request_var('style_active', 0); $style_default = request_var('style_default', 0); - $store_db = request_var('store_db', 0); // If the admin selected the style to be the default style, but forgot to activate it... we will do it for him if ($style_default) @@ -2397,7 +1563,7 @@ parse_css_file = {PARSE_CSS_FILE} $conflict = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id)) + if ($mode == 'style' && (!$template_id || !$theme_id)) { $error[] = $user->lang['STYLE_ERR_NO_IDS']; } @@ -2412,29 +1578,6 @@ parse_css_file = {PARSE_CSS_FILE} $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; } - if ($mode === 'theme' || $mode === 'template') - { - // a rather elaborate check we have to do here once to avoid trouble later - $check = "{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . (($mode === 'theme') ? '/theme/stylesheet.css' : '/template'); - if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !phpbb_is_writable($check))) - { - $error[] = $user->lang['EDIT_' . strtoupper($mode) . '_STORED_DB']; - $store_db = 1; - } - - // themes which have to be parsed have to go into db - if ($mode == 'theme') - { - $cfg = parse_cfg_file("{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . "/theme/theme.cfg"); - - if (isset($cfg['parse_css_file']) && $cfg['parse_css_file'] && !$store_db) - { - $error[] = $user->lang['EDIT_THEME_STORE_PARSED']; - $store_db = 1; - } - } - } - if (!sizeof($error)) { // Check length settings @@ -2455,9 +1598,7 @@ parse_css_file = {PARSE_CSS_FILE} $style_row = array_merge($style_row, array( 'template_id' => $template_id, 'theme_id' => $theme_id, - 'imageset_id' => $imageset_id, 'style_active' => $style_active, - $mode . '_storedb' => $store_db, $mode . '_name' => $name, $mode . '_copyright' => $copyright) ); @@ -2478,81 +1619,14 @@ parse_css_file = {PARSE_CSS_FILE} $sql_ary += array( 'template_id' => (int) $template_id, 'theme_id' => (int) $theme_id, - 'imageset_id' => (int) $imageset_id, 'style_active' => (int) $style_active, ); break; - case 'imageset': - break; - case 'theme': - - if ($style_row['theme_storedb'] != $store_db) - { - $theme_data = ''; - - if (!$style_row['theme_storedb']) - { - $theme_data = $this->db_theme_data($style_row); - } - else if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css")) - { - $store_db = 1; - $theme_data = $style_row['theme_data']; - - if ($fp = @fopen("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css", 'wb')) - { - $store_db = (@fwrite($fp, str_replace("styles/{$style_row['theme_path']}/theme/", './', $theme_data))) ? 0 : 1; - } - fclose($fp); - } - - $sql_ary += array( - 'theme_mtime' => ($store_db) ? filemtime("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css") : 0, - 'theme_storedb' => $store_db, - 'theme_data' => ($store_db) ? $theme_data : '', - ); - } break; case 'template': - - if ($style_row['template_storedb'] != $store_db) - { - if ($super = $this->get_super($mode, $style_row['template_id'])) - { - $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); - $sql_ary = array(); - } - else - { - if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) - { - $err = $this->store_in_fs('template', $style_row['template_id']); - if ($err) - { - $error += $err; - } - } - else if ($store_db) - { - $this->store_in_db('template', $style_row['template_id']); - } - else - { - // We no longer store within the db, but are also not able to update the file structure - // Since the admin want to switch this, we adhere to his decision. But we also need to remove the cache - $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $style_id"; - $db->sql_query($sql); - } - - $sql_ary += array( - 'template_storedb' => $store_db, - ); - } - } break; } @@ -2619,16 +1693,12 @@ parse_css_file = {PARSE_CSS_FILE} 'S_STYLE' => ($mode == 'style') ? true : false, 'S_TEMPLATE' => ($mode == 'template') ? true : false, 'S_THEME' => ($mode == 'theme') ? true : false, - 'S_IMAGESET' => ($mode == 'imageset') ? true : false, - 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, - 'S_STORE_DB_DISABLED' => (isset($style_row[$mode . '_inherits_id'])) ? $style_row[$mode . '_inherits_id'] : 0, 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0, 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', - 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', 'U_ACTION' => $this->u_action . '&action=details&id=' . $style_id, 'U_BACK' => $this->u_action, @@ -2636,8 +1706,6 @@ parse_css_file = {PARSE_CSS_FILE} 'L_TITLE' => $user->lang[$this->page_title], 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], 'L_NAME' => $user->lang[$l_type . '_NAME'], - 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', - 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', 'NAME' => $style_row[$mode . '_name'], @@ -2724,84 +1792,6 @@ parse_css_file = {PARSE_CSS_FILE} } /** - * Store template files into db - */ - function store_templates($mode, $style_id, $template_path, $filelist) - { - global $phpbb_root_path, $phpEx, $db; - - $template_path = $template_path . '/template/'; - $includes = array(); - foreach ($filelist as $pathfile => $file_ary) - { - foreach ($file_ary as $file) - { - if (!($fp = @fopen("{$phpbb_root_path}styles/$template_path$pathfile$file", 'r'))) - { - trigger_error("Could not open {$phpbb_root_path}styles/$template_path$pathfile$file", E_USER_ERROR); - } - - $filesize = filesize("{$phpbb_root_path}styles/$template_path$pathfile$file"); - - if ($filesize) - { - $template_data = fread($fp, $filesize); - } - - fclose($fp); - - if (!$filesize) - { - // File is empty - continue; - } - - if (preg_match_all('#<!-- INCLUDE (.*?\.html) -->#is', $template_data, $matches)) - { - foreach ($matches[1] as $match) - { - $includes[trim($match)][] = $file; - } - } - } - } - - foreach ($filelist as $pathfile => $file_ary) - { - foreach ($file_ary as $file) - { - // Skip index. - if (strpos($file, 'index.') === 0) - { - continue; - } - - // We could do this using extended inserts ... but that could be one - // heck of a lot of data ... - $sql_ary = array( - 'template_id' => (int) $style_id, - 'template_filename' => "$pathfile$file", - 'template_included' => (isset($includes[$file])) ? implode(':', $includes[$file]) . ':' : '', - 'template_mtime' => (int) filemtime("{$phpbb_root_path}styles/$template_path$pathfile$file"), - 'template_data' => (string) file_get_contents("{$phpbb_root_path}styles/$template_path$pathfile$file"), - ); - - if ($mode == 'insert') - { - $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - } - else - { - $sql = 'UPDATE ' . STYLES_TEMPLATE_DATA_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE template_id = $style_id - AND template_filename = '" . $db->sql_escape("$pathfile$file") . "'"; - } - $db->sql_query($sql); - } - } - } - - /** * Returns an array containing all template filenames for one template that are currently cached. * * @param string $template_path contains the name of the template's folder in /styles/ @@ -2876,7 +1866,7 @@ parse_css_file = {PARSE_CSS_FILE} } /** - * Install Style/Template/Theme/Imageset + * Install Style/Template/Theme */ function install($mode) { @@ -2886,7 +1876,7 @@ parse_css_file = {PARSE_CSS_FILE} $error = $installcfg = $style_row = array(); $root_path = $cfg_file = ''; - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); $install_path = request_var('path', ''); $update = (isset($_POST['update'])) ? true : false; @@ -2932,7 +1922,6 @@ parse_css_file = {PARSE_CSS_FILE} $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; - $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; // Check to see if each element is already installed, if it is grab the id foreach ($element_ary as $element => $table) @@ -2958,7 +1947,7 @@ parse_css_file = {PARSE_CSS_FILE} $cfg_contents = parse_cfg_file($cfg_file); // Merge only specific things. We may need them later. - foreach (array('inherit_from', 'parse_css_file') as $key) + foreach (array('inherit_from') as $key) { if (!empty($cfg_contents[$key]) && !isset($installcfg[$key])) { @@ -2977,10 +1966,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']); break; - - case 'imageset': - $this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']); - break; } } else @@ -2988,7 +1973,6 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); } - $style_row['store_db'] = request_var('store_db', 0); $style_row['style_active'] = request_var('style_active', 1); $style_row['style_default'] = request_var('style_default', 0); @@ -3002,19 +1986,18 @@ parse_css_file = {PARSE_CSS_FILE} ${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false; ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false; } - $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path, $imageset_root_path, $imageset_path); + $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path); } else { - $style_row['store_db'] = $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright'], $style_row['store_db']); + $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright']); } if (!sizeof($error)) { $cache->destroy('sql', STYLES_TABLE); - $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; - trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); + trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); } } @@ -3030,7 +2013,6 @@ parse_css_file = {PARSE_CSS_FILE} 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '', 'S_THEME' => ($mode == 'theme') ? true : false, - 'S_STORE_DB' => (isset($style_row[$mode . '_storedb'])) ? $style_row[$mode . '_storedb'] : 0, 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, @@ -3040,15 +2022,12 @@ parse_css_file = {PARSE_CSS_FILE} 'L_TITLE' => $user->lang[$this->page_title], 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], 'L_NAME' => $user->lang[$l_type . '_NAME'], - 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', - 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', 'NAME' => $style_row[$mode . '_name'], 'COPYRIGHT' => $style_row[$mode . '_copyright'], 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '', - 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '', - 'IMAGESET_NAME' => ($mode == 'style') ? $style_row['imageset_name'] : '') + 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '') ); } @@ -3060,7 +2039,7 @@ parse_css_file = {PARSE_CSS_FILE} global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; $l_type = strtoupper($mode); - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); $error = array(); $style_row = array( @@ -3068,8 +2047,6 @@ parse_css_file = {PARSE_CSS_FILE} $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)), 'template_id' => 0, 'theme_id' => 0, - 'imageset_id' => 0, - 'store_db' => request_var('store_db', 0), 'style_active' => request_var('style_active', 1), 'style_default' => request_var('style_default', 0), ); @@ -3082,7 +2059,7 @@ parse_css_file = {PARSE_CSS_FILE} switch ($mode) { case 'style': - $sql_select = 'template_id, theme_id, imageset_id'; + $sql_select = 'template_id, theme_id'; $sql_from = STYLES_TABLE; break; @@ -3095,11 +2072,6 @@ parse_css_file = {PARSE_CSS_FILE} $sql_select = 'theme_id'; $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_select = 'imageset_id'; - $sql_from = STYLES_IMAGESET_TABLE; - break; } $sql = "SELECT $sql_select @@ -3118,7 +2090,6 @@ parse_css_file = {PARSE_CSS_FILE} { $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id']; $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id']; - $style_row['imageset_id'] = (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id']; } } @@ -3126,9 +2097,8 @@ parse_css_file = {PARSE_CSS_FILE} { $style_row['template_id'] = request_var('template_id', $style_row['template_id']); $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']); - $style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']); - if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])) + if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'])) { $error[] = $user->lang['STYLE_ERR_NO_IDS']; } @@ -3148,8 +2118,7 @@ parse_css_file = {PARSE_CSS_FILE} { $cache->destroy('sql', STYLES_TABLE); - $message = ($style_row['store_db']) ? '_ADDED_DB' : '_ADDED'; - trigger_error($user->lang[$l_type . $message] . adm_back_link($this->u_action)); + trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); } } @@ -3183,12 +2152,10 @@ parse_css_file = {PARSE_CSS_FILE} 'S_THEME' => ($mode == 'theme') ? true : false, 'S_BASIS' => ($basis) ? true : false, - 'S_STORE_DB' => (isset($style_row['storedb'])) ? $style_row['storedb'] : 0, 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', - 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', 'U_ACTION' => $this->u_action . '&action=add&basis=' . $basis, 'U_BACK' => $this->u_action, @@ -3196,8 +2163,6 @@ parse_css_file = {PARSE_CSS_FILE} 'L_TITLE' => $user->lang[$this->page_title], 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], 'L_NAME' => $user->lang[$l_type . '_NAME'], - 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', - 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', 'NAME' => $style_row[$mode . '_name'], @@ -3210,7 +2175,6 @@ parse_css_file = {PARSE_CSS_FILE} $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; - $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; // Check to see if each element is already installed, if it is grab the id foreach ($element_ary as $element => $table) @@ -3237,10 +2201,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $l_element = strtoupper($element); @@ -3279,11 +2239,11 @@ parse_css_file = {PARSE_CSS_FILE} /** * Install/Add style */ - function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false, $imageset_root_path = false, $imageset_path = false) + function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false) { global $config, $db, $user; - $element_ary = array('template', 'theme', 'imageset'); + $element_ary = array('template', 'theme'); if (!$name) { @@ -3329,7 +2289,7 @@ parse_css_file = {PARSE_CSS_FILE} } } - if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']) + if (!$style_row['template_id'] || !$style_row['theme_id']) { $error[] = $user->lang['STYLE_ERR_NO_IDS']; } @@ -3347,7 +2307,6 @@ parse_css_file = {PARSE_CSS_FILE} 'style_active' => (int) $active, 'template_id' => (int) $style_row['template_id'], 'theme_id' => (int) $style_row['theme_id'], - 'imageset_id' => (int) $style_row['imageset_id'], ); $sql = 'INSERT INTO ' . STYLES_TABLE . ' @@ -3374,7 +2333,7 @@ parse_css_file = {PARSE_CSS_FILE} /** * Install/add an element, doing various checks as we go */ - function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0) + function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright) { global $phpbb_root_path, $db, $user; @@ -3390,10 +2349,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $l_type = strtoupper($mode); @@ -3445,7 +2400,7 @@ parse_css_file = {PARSE_CSS_FILE} $select_bf = ''; } - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, {$mode}_storedb $select_bf + $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path, $select_bf FROM $sql_from WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "' AND {$mode}_inherits_id = 0"; @@ -3461,8 +2416,6 @@ parse_css_file = {PARSE_CSS_FILE} $inherit_id = $row["{$mode}_id"]; $inherit_path = $row["{$mode}_path"]; $inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false; - $cfg_data['store_db'] = $row["{$mode}_storedb"]; - $store_db = $row["{$mode}_storedb"]; } } else @@ -3500,10 +2453,6 @@ parse_css_file = {PARSE_CSS_FILE} $sql_ary['bbcode_bitfield'] = $this->template_bitfield; } - // We set a pre-defined bitfield here which we may use further in 3.2 - $sql_ary += array( - 'template_storedb' => $store_db, - ); if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) { $sql_ary += array( @@ -3514,22 +2463,6 @@ parse_css_file = {PARSE_CSS_FILE} break; case 'theme': - // We are only interested in the theme configuration for now - - if (isset($cfg_data['parse_css_file']) && $cfg_data['parse_css_file']) - { - $store_db = 1; - } - - $sql_ary += array( - 'theme_storedb' => $store_db, - 'theme_data' => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '', - 'theme_mtime' => (int) filemtime("{$phpbb_root_path}styles/$path/theme/stylesheet.css") - ); - break; - - // all the heavy lifting is done later - case 'imageset': break; } @@ -3541,119 +2474,9 @@ parse_css_file = {PARSE_CSS_FILE} $id = $db->sql_nextid(); - if ($mode == 'template' && $store_db) - { - $filelist = filelist("{$root_path}template", '', 'html'); - $this->store_templates('insert', $id, $path, $filelist); - } - else if ($mode == 'imageset') - { - $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg"); - - $imageset_definitions = array(); - foreach ($this->imageset_keys as $topic => $key_array) - { - $imageset_definitions = array_merge($imageset_definitions, $key_array); - } - - foreach ($cfg_data as $key => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($key, 'img_') === 0 && $image_filename) - { - $key = substr($key, 4); - if (in_array($key, $imageset_definitions)) - { - $sql_ary = array( - 'image_name' => $key, - 'image_filename' => str_replace('{PATH}', "styles/$path/imageset/", trim($image_filename)), - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $id, - 'image_lang' => '', - ); - $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - } - } - } - unset($cfg_data); - - $sql = 'SELECT lang_dir - FROM ' . LANG_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - if (@file_exists("$root_path$mode/{$row['lang_dir']}/imageset.cfg")) - { - $cfg_data_imageset_data = parse_cfg_file("$root_path$mode/{$row['lang_dir']}/imageset.cfg"); - foreach ($cfg_data_imageset_data as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - if (in_array($image_name, $imageset_definitions)) - { - $sql_ary = array( - 'image_name' => $image_name, - 'image_filename' => $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $id, - 'image_lang' => $row['lang_dir'], - ); - $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); - } - } - } - unset($cfg_data_imageset_data); - } - } - $db->sql_freeresult($result); - } - $db->sql_transaction('commit'); - $log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS'; - add_log('admin', $log, $name); - - // Return store_db in case it had to be altered - return $store_db; + add_log('admin', 'LOG_' . $l_type . '_ADD_FS', $name); } /** @@ -3679,10 +2502,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path @@ -3735,10 +2554,6 @@ parse_css_file = {PARSE_CSS_FILE} case 'theme': $sql_from = STYLES_THEME_TABLE; break; - - case 'imageset': - $sql_from = STYLES_IMAGESET_TABLE; - break; } $sql = "SELECT {$mode}_inherits_id @@ -3770,180 +2585,4 @@ parse_css_file = {PARSE_CSS_FILE} return false; } - - /** - * Moves a template set and its subtemplates to the database - * - * @access public - * @param string $mode The component to move - only template is supported - * @param int $id The template id - */ - function store_in_db($mode, $id) - { - global $db, $user; - - $error = array(); - $l_type = strtoupper($mode); - if ($super = $this->get_super($mode, $id)) - { - $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); - return $error; - } - - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path - FROM " . STYLES_TEMPLATE_TABLE . ' - WHERE template_id = ' . (int) $id; - - $result = $db->sql_query_limit($sql, 1); - if ($row = $db->sql_fetchrow($result)) - { - $db->sql_freeresult($result); - $subs = $this->check_inheritance($mode, $id); - - $this->_store_in_db($mode, $id, $row["{$mode}_path"]); - if ($subs && sizeof($subs)) - { - foreach ($subs as $sub_id => $sub) - { - if ($err = $this->_store_in_db($mode, $sub["{$mode}_id"], $sub["{$mode}_path"])) - { - $error[] = $err; - } - } - } - } - if (sizeof($error)) - { - return $error; - } - - return false; - } - - /** - * Moves a template set to the database - * - * @access private - * @param string $mode The component to move - only template is supported - * @param int $id The template id - * @param string $path TThe path to the template files - */ - function _store_in_db($mode, $id, $path) - { - global $phpbb_root_path, $db; - - $filelist = filelist("{$phpbb_root_path}styles/{$path}/template", '', 'html'); - $this->store_templates('insert', $id, $path, $filelist); - - // Okay, we do the query here -shouldn't be triggered often. - $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' - SET template_storedb = 1 - WHERE template_id = ' . $id; - $db->sql_query($sql); - } - - /** - * Moves a template set and its subtemplates to the filesystem - * - * @access public - * @param string $mode The component to move - only template is supported - * @param int $id The template id - */ - function store_in_fs($mode, $id) - { - global $db, $user; - - $error = array(); - $l_type = strtoupper($mode); - if ($super = $this->get_super($mode, $id)) - { - $error[] = (sprintf($user->lang["{$l_type}_INHERITS"], $super['template_name'])); - return($error); - } - - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path - FROM " . STYLES_TEMPLATE_TABLE . ' - WHERE template_id = ' . (int) $id; - - $result = $db->sql_query_limit($sql, 1); - if ($row = $db->sql_fetchrow($result)) - { - $db->sql_freeresult($result); - if (!sizeof($error)) - { - $subs = $this->check_inheritance($mode, $id); - - $this->_store_in_fs($mode, $id, $row["{$mode}_path"]); - - if ($subs && sizeof($subs)) - { - foreach ($subs as $sub_id => $sub) - { - $this->_store_in_fs($mode, $sub["{$mode}_id"], $sub["{$mode}_path"]); - } - } - } - if (sizeof($error)) - { - $this->store_in_db($id, $mode); - return $error; - } - } - return false; - } - - /** - * Moves a template set to the filesystem - * - * @access private - * @param string $mode The component to move - only template is supported - * @param int $id The template id - * @param string $path The path to the template - */ - function _store_in_fs($mode, $id, $path) - { - global $phpbb_root_path, $db, $user, $safe_mode; - - $store_db = 0; - $error = array(); - if (!$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$path}/template")) - { - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $id"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - if (!($fp = @fopen("{$phpbb_root_path}styles/{$path}/template/" . $row['template_filename'], 'wb'))) - { - $store_db = 1; - $error[] = $user->lang['EDIT_TEMPLATE_STORED_DB']; - break; - } - - fwrite($fp, $row['template_data']); - fclose($fp); - } - $db->sql_freeresult($result); - - if (!$store_db) - { - $sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . " - WHERE template_id = $id"; - $db->sql_query($sql); - } - } - if (sizeof($error)) - { - return $error; - } - $sql = 'UPDATE ' . STYLES_TEMPLATE_TABLE . ' - SET template_storedb = 0 - WHERE template_id = ' . $id; - $db->sql_query($sql); - - return false; - } - } diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php index d6afd53cef..bdcceb1b7d 100644 --- a/phpBB/includes/acp/info/acp_styles.php +++ b/phpBB/includes/acp/info/acp_styles.php @@ -23,7 +23,6 @@ class acp_styles_info 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), 'template' => array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), 'theme' => array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), - 'imageset' => array('title' => 'ACP_IMAGESETS', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), ), ); } diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php index a148403c6f..9089703035 100644 --- a/phpBB/includes/auth/auth_apache.php +++ b/phpBB/includes/auth/auth_apache.php @@ -28,9 +28,9 @@ if (!defined('IN_PHPBB')) */ function init_apache() { - global $user; + global $user, $request; - if (!isset($_SERVER['PHP_AUTH_USER']) || $user->data['username'] !== $_SERVER['PHP_AUTH_USER']) + if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $user->data['username'] !== htmlspecialchars_decode($request->server('PHP_AUTH_USER'))) { return $user->lang['APACHE_SETUP_BEFORE_USE']; } @@ -42,7 +42,7 @@ function init_apache() */ function login_apache(&$username, &$password) { - global $db; + global $db, $request; // do not allow empty password if (!$password) @@ -63,7 +63,7 @@ function login_apache(&$username, &$password) ); } - if (!isset($_SERVER['PHP_AUTH_USER'])) + if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) { return array( 'status' => LOGIN_ERROR_EXTERNAL_AUTH, @@ -72,8 +72,8 @@ function login_apache(&$username, &$password) ); } - $php_auth_user = $_SERVER['PHP_AUTH_USER']; - $php_auth_pw = $_SERVER['PHP_AUTH_PW']; + $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER')); + $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW')); if (!empty($php_auth_user) && !empty($php_auth_pw)) { @@ -136,15 +136,15 @@ function login_apache(&$username, &$password) */ function autologin_apache() { - global $db; + global $db, $request; - if (!isset($_SERVER['PHP_AUTH_USER'])) + if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) { return array(); } - $php_auth_user = $_SERVER['PHP_AUTH_USER']; - $php_auth_pw = $_SERVER['PHP_AUTH_PW']; + $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER')); + $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW')); if (!empty($php_auth_user) && !empty($php_auth_pw)) { @@ -228,11 +228,12 @@ function user_row_apache($username, $password) */ function validate_session_apache(&$user) { + global $request; + // Check if PHP_AUTH_USER is set and handle this case - if (isset($_SERVER['PHP_AUTH_USER'])) + if ($request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER)) { - $php_auth_user = ''; - set_var($php_auth_user, $_SERVER['PHP_AUTH_USER'], 'string', true); + $php_auth_user = $request->server('PHP_AUTH_USER'); return ($php_auth_user === $user['username']) ? true : false; } diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index b4ae1911cf..a2ff9b4047 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -129,7 +129,7 @@ function login_db($username, $password, $ip = '', $browser = '', $forwarded_for include ($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); } - $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); $captcha->init(CONFIRM_LOGIN); $vc_response = $captcha->validate($row); if ($vc_response) diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index a360bcd5d1..c3367fbd46 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -30,7 +30,6 @@ class bbcode var $bbcodes = array(); var $template_bitfield; - var $template_filename = ''; /** * Constructor @@ -128,28 +127,17 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $template, $user; + global $phpbb_root_path, $phpEx, $config, $user; if (empty($this->template_filename)) { $this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']); - $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template/bbcode.html'; - if (!@file_exists($this->template_filename)) - { - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) - { - $this->template_filename = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template/bbcode.html'; - if (!@file_exists($this->template_filename)) - { - trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); - } - } - else - { - trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); - } - } + $template_locator = new phpbb_template_locator(); + $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator); + $template->set_template(); + $template_locator->set_filenames(array('bbcode.html' => 'bbcode.html')); + $this->template_filename = $template_locator->get_source_file_for_handle('bbcode.html'); } $bbcode_ids = $rowset = $sql = array(); @@ -584,6 +572,13 @@ class bbcode $code = str_replace("\t", ' ', $code); $code = str_replace(' ', ' ', $code); $code = str_replace(' ', ' ', $code); + $code = str_replace("\n ", "\n ", $code); + + // keep space at the beginning + if (!empty($code) && $code[0] == ' ') + { + $code = ' ' . substr($code, 1); + } // remove newline at the beginning if (!empty($code) && $code[0] == "\n") diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php index a3766f4054..c2ec8c5bda 100644 --- a/phpBB/includes/captcha/captcha_factory.php +++ b/phpBB/includes/captcha/captcha_factory.php @@ -26,7 +26,7 @@ class phpbb_captcha_factory /** * return an instance of class $name in file $name_plugin.php */ - function &get_instance($name) + function get_instance($name) { global $phpbb_root_path, $phpEx; diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php index add8c3959f..bb76a06371 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -50,9 +50,9 @@ class phpbb_captcha_gd extends phpbb_default_captcha } } - function &get_instance() + function get_instance() { - $instance =& new phpbb_captcha_gd(); + $instance = new phpbb_captcha_gd(); return $instance; } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php index 490a0d62ab..3e98c45d2c 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php @@ -40,9 +40,9 @@ class phpbb_captcha_nogd extends phpbb_default_captcha } } - function &get_instance() + function get_instance() { - $instance =& new phpbb_captcha_nogd(); + $instance = new phpbb_captcha_nogd(); return $instance; } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php index 3bc727da41..272c0cd4d2 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php @@ -99,9 +99,9 @@ class phpbb_captcha_qa /** * API function */ - function &get_instance() + function get_instance() { - $instance =& new phpbb_captcha_qa(); + $instance = new phpbb_captcha_qa(); return $instance; } diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php index c0db41d5a5..5cfb5df8fc 100644 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php @@ -41,7 +41,8 @@ class phpbb_recaptcha extends phpbb_default_captcha // PHP4 Constructor function phpbb_recaptcha() { - $this->recaptcha_server = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? $this->recaptcha_server_secure : $this->recaptcha_server; + global $request; + $this->recaptcha_server = $request->is_secure() ? $this->recaptcha_server_secure : $this->recaptcha_server; } function init($type) @@ -54,9 +55,9 @@ class phpbb_recaptcha extends phpbb_default_captcha $this->response = request_var('recaptcha_response_field', ''); } - function &get_instance() + function get_instance() { - $instance =& new phpbb_recaptcha(); + $instance = new phpbb_recaptcha(); return $instance; } diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 7c96965a9b..7715d2e854 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -649,6 +649,23 @@ class phpbb_db_tools $sqlite = true; } + // Drop tables? + if (!empty($schema_changes['drop_tables'])) + { + foreach ($schema_changes['drop_tables'] as $table) + { + // only drop table if it exists + if ($this->sql_table_exists($table)) + { + $result = $this->sql_table_drop($table); + if ($this->return_statements) + { + $statements = array_merge($statements, $result); + } + } + } + } + // Add tables? if (!empty($schema_changes['add_tables'])) { @@ -1788,7 +1805,7 @@ class phpbb_db_tools break; case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; + $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; break; case 'postgres': @@ -1939,6 +1956,7 @@ class phpbb_db_tools $statements[] = "DROP SEQUENCE {$row['referenced_name']}"; } $this->db->sql_freeresult($result); + break; case 'postgres': // PGSQL does not "tightly" bind sequences and tables, we must guess... diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 2287bc716e..96b4c8a8c8 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -396,7 +396,7 @@ class dbal_mssqlnative extends dbal */ function sql_affectedrows() { - return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->db_connect_id) : false; + return (!empty($this->query_result)) ? @sqlsrv_rows_affected($this->query_result) : false; } /** diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index db3846e7f7..d2781e96dd 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -249,7 +249,13 @@ class dbal_mysqli extends dbal return $cache->sql_fetchrow($query_id); } - return ($query_id !== false) ? @mysqli_fetch_assoc($query_id) : false; + if ($query_id !== false) + { + $result = @mysqli_fetch_assoc($query_id); + return $result !== null ? $result : false; + } + + return false; } /** diff --git a/phpBB/includes/error_collector.php b/phpBB/includes/error_collector.php index 55834f354c..3c0a89a1f3 100644 --- a/phpBB/includes/error_collector.php +++ b/phpBB/includes/error_collector.php @@ -49,13 +49,15 @@ class phpbb_error_collector { $text .= "<br />\n"; } + list($errno, $msg_text, $errfile, $errline) = $error; - $text .= "Errno $errno: $msg_text"; - if (defined('DEBUG_EXTRA') || defined('IN_INSTALL')) - { - $text .= " at $errfile line $errline"; - } + + // Prevent leakage of local path to phpBB install + $errfile = phpbb_filter_root_path($errfile); + + $text .= "Errno $errno: $msg_text at $errfile line $errline"; } + return $text; } } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index fb7aafe636..8f41e18db6 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -817,7 +817,7 @@ function phpbb_is_writable($file) * @param string $path Path to check absoluteness of * @return boolean */ -function is_absolute($path) +function phpbb_is_absolute($path) { return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:[/\\\]#i', $path))) ? true : false; } @@ -830,6 +830,8 @@ function is_absolute($path) */ function phpbb_own_realpath($path) { + global $request; + // Now to perform funky shizzle // Switch to use UNIX slashes @@ -837,7 +839,7 @@ function phpbb_own_realpath($path) $path_prefix = ''; // Determine what sort of path we have - if (is_absolute($path)) + if (phpbb_is_absolute($path)) { $absolute = true; @@ -873,11 +875,12 @@ function phpbb_own_realpath($path) $path_prefix = ''; } } - else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME'])) + else if ($request->server('SCRIPT_FILENAME')) { // Warning: If chdir() has been used this will lie! // Warning: This has some problems sometime (CLI can create them easily) - $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path; + $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME')); + $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path; $absolute = true; $path_prefix = ''; } @@ -1898,7 +1901,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add $start_cnt = min(max(1, $on_page - 4), $total_pages - 5); $end_cnt = max(min($total_pages, $on_page + 4), 6); - $page_string .= ($start_cnt > 1) ? ' ... ' : $separator; + $page_string .= ($start_cnt > 1) ? '<span class="page-dots"> ... </span>' : $separator; for ($i = $start_cnt + 1; $i < $end_cnt; $i++) { @@ -1909,7 +1912,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add } } - $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $separator; + $page_string .= ($end_cnt < $total_pages) ? '<span class="page-dots"> ... </span>' : $separator; } else { @@ -1948,6 +1951,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add $tpl_prefix . 'PREVIOUS_PAGE' => ($on_page == 1) ? '' : $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page), $tpl_prefix . 'NEXT_PAGE' => ($on_page == $total_pages) ? '' : $base_url . "{$url_delim}start=" . ($on_page * $per_page), $tpl_prefix . 'TOTAL_PAGES' => $total_pages, + $tpl_prefix . 'CURRENT_PAGE' => $on_page, )); return $page_string; @@ -1996,6 +2000,12 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) { global $_SID, $_EXTRA_URL, $phpbb_hook; + if ($params === '' || (is_array($params) && empty($params))) + { + // Do not append the ? if the param-list is empty anyway. + $params = false; + } + // Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately. // They could mimic most of what is within this function if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id)) @@ -2097,10 +2107,10 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) */ function generate_board_url($without_script_path = false) { - global $config, $user; + global $config, $user, $request; $server_name = $user->host; - $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); + $server_port = $request->server('SERVER_PORT', 0); // Forcing server vars is the only way to specify/override the protocol if ($config['force_server_vars'] || !$server_name) @@ -2116,7 +2126,7 @@ function generate_board_url($without_script_path = false) else { // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection - $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0; + $cookie_secure = $request->is_secure() ? 1 : 0; $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name; $script_path = $user->page['root_script_path']; @@ -2468,6 +2478,8 @@ function meta_refresh($time, $url, $disable_cd_check = false) */ function send_status_line($code, $message) { + global $request; + if (substr(strtolower(@php_sapi_name()), 0, 3) === 'cgi') { // in theory, we shouldn't need that due to php doing it. Reality offers a differing opinion, though @@ -2475,15 +2487,9 @@ function send_status_line($code, $message) } else { - if (!empty($_SERVER['SERVER_PROTOCOL'])) - { - $version = $_SERVER['SERVER_PROTOCOL']; - } - else if (!empty($_SERVER['HTTP_VERSION'])) + if ($request->server('SERVER_PROTOCOL')) { - // I cannot remember where I got this from. - // This code path may never be reachable in reality. - $version = $_SERVER['HTTP_VERSION']; + $version = $request->server('SERVER_PROTOCOL'); } else { @@ -3151,61 +3157,44 @@ function add_log() } /** -* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com) +* Return a nicely formatted backtrace. +* +* Turns the array returned by debug_backtrace() into HTML markup. +* Also filters out absolute paths to phpBB root. +* +* @return string HTML markup */ function get_backtrace() { - global $phpbb_root_path; - $output = '<div style="font-family: monospace;">'; $backtrace = debug_backtrace(); - $path = phpbb_realpath($phpbb_root_path); - foreach ($backtrace as $number => $trace) - { - // We skip the first one, because it only shows this file/function - if ($number == 0) - { - continue; - } + // We skip the first one, because it only shows this file/function + unset($backtrace[0]); + foreach ($backtrace as $trace) + { // Strip the current directory from path - if (empty($trace['file'])) - { - $trace['file'] = ''; - } - else - { - $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']); - $trace['file'] = substr($trace['file'], 1); - } - $args = array(); + $trace['file'] = (empty($trace['file'])) ? '(not given by php)' : htmlspecialchars(phpbb_filter_root_path($trace['file'])); + $trace['line'] = (empty($trace['line'])) ? '(not given by php)' : $trace['line']; - // If include/require/include_once is not called, do not show arguments - they may contain sensible information - if (!in_array($trace['function'], array('include', 'require', 'include_once'))) + // Only show function arguments for include etc. + // Other parameters may contain sensible information + $argument = ''; + if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once'))) { - unset($trace['args']); - } - else - { - // Path... - if (!empty($trace['args'][0])) - { - $argument = htmlspecialchars($trace['args'][0]); - $argument = str_replace(array($path, '\\'), array('', '/'), $argument); - $argument = substr($argument, 1); - $args[] = "'{$argument}'"; - } + $argument = htmlspecialchars(phpbb_filter_root_path($trace['args'][0])); } $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class']; $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type']; $output .= '<br />'; - $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />'; + $output .= '<b>FILE:</b> ' . $trace['file'] . '<br />'; $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />'; - $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />'; + $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']); + $output .= '(' . (($argument !== '') ? "'$argument'" : '') . ')<br />'; } $output .= '</div>'; return $output; @@ -3286,7 +3275,7 @@ function get_censor_preg_expression($word, $use_unicode = true) // Unescape the asterisk to simplify further conversions $word = str_replace('\*', '*', preg_quote($word, '#')); - if ($use_unicode && pcre_utf8_support()) + if ($use_unicode && phpbb_pcre_utf8_support()) { // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); @@ -3754,9 +3743,8 @@ function msg_handler($errno, $msg_text, $errfile, $errline) if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false) { - // remove complete path to installation, with the risk of changing backslashes meant to be there - $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile); - $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text); + $errfile = phpbb_filter_root_path($errfile); + $msg_text = phpbb_filter_root_path($msg_text); $error_name = ($errno === E_WARNING) ? 'PHP Warning' : 'PHP Notice'; echo '<b>[phpBB Debug] ' . $error_name . '</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n"; @@ -3935,6 +3923,29 @@ function msg_handler($errno, $msg_text, $errfile, $errline) } /** +* Removes absolute path to phpBB root directory from error messages +* and converts backslashes to forward slashes. +* +* @param string $errfile Absolute file path +* (e.g. /var/www/phpbb3/phpBB/includes/functions.php) +* Please note that if $errfile is outside of the phpBB root, +* the root path will not be found and can not be filtered. +* @return string Relative file path +* (e.g. /includes/functions.php) +*/ +function phpbb_filter_root_path($errfile) +{ + static $root_path; + + if (empty($root_path)) + { + $root_path = phpbb_realpath(dirname(__FILE__) . '/../'); + } + + return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); +} + +/** * Queries the session table to get information about online guests * @param int $item_id Limits the search to the item with this id * @param string $item The name of the item which is stored in the session table as session_{$item}_id @@ -4202,7 +4213,7 @@ function phpbb_optionset($bit, $set, $data) */ function phpbb_http_login($param) { - global $auth, $user; + global $auth, $user, $request; global $config; $param_defaults = array( @@ -4242,9 +4253,9 @@ function phpbb_http_login($param) $username = null; foreach ($username_keys as $k) { - if (isset($_SERVER[$k])) + if ($request->is_set($k, phpbb_request_interface::SERVER)) { - $username = $_SERVER[$k]; + $username = htmlspecialchars_decode($request->server($k)); break; } } @@ -4252,9 +4263,9 @@ function phpbb_http_login($param) $password = null; foreach ($password_keys as $k) { - if (isset($_SERVER[$k])) + if ($request->is_set($k, phpbb_request_interface::SERVER)) { - $password = $_SERVER[$k]; + $password = htmlspecialchars_decode($request->server($k)); break; } } @@ -4545,11 +4556,10 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'S_SEARCH_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields), + 'T_ASSETS_PATH' => "{$web_path}assets", 'T_THEME_PATH' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme', 'T_TEMPLATE_PATH' => "{$web_path}styles/" . $user->theme['template_path'] . '/template', 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . $user->theme['template_inherit_path'] . '/template' : "{$web_path}styles/" . $user->theme['template_path'] . '/template', - 'T_IMAGESET_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset', - 'T_IMAGESET_LANG_PATH' => "{$web_path}styles/" . $user->theme['imageset_path'] . '/imageset/' . $user->lang_name, 'T_IMAGES_PATH' => "{$web_path}images/", 'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/", 'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/", @@ -4557,14 +4567,14 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/", 'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/", 'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/", - 'T_STYLESHEET_LINK' => (!$user->theme['theme_storedb']) ? "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css' : append_sid("{$phpbb_root_path}style.$phpEx", 'id=' . $user->theme['style_id'] . '&lang=' . $user->lang_name), + 'T_STYLESHEET_LINK' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/stylesheet.css', + 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . $user->theme['theme_path'] . '/theme/' . $user->lang_name . '/stylesheet.css', 'T_STYLESHEET_NAME' => $user->theme['theme_name'], 'T_THEME_NAME' => $user->theme['theme_path'], + 'T_THEME_LANG_NAME' => $user->data['user_lang'], 'T_TEMPLATE_NAME' => $user->theme['template_path'], 'T_SUPER_TEMPLATE_NAME' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path'], - 'T_IMAGESET_NAME' => $user->theme['imageset_path'], - 'T_IMAGESET_LANG_NAME' => $user->data['user_lang'], 'T_IMAGES' => 'images', 'T_SMILIES' => $config['smilies_path'], 'T_AVATAR' => $config['avatar_path'], @@ -4585,6 +4595,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 header('Expires: 0'); header('Pragma: no-cache'); + if (!empty($user->data['is_bot'])) + { + // Let reverse proxies know we detected a bot. + header('X-PHPBB-IS-BOT: yes'); + } + return; } @@ -4743,7 +4759,7 @@ function phpbb_user_session_handler() * * @return bool Returns true if PCRE (the regular expressions library) supports UTF-8 encoding */ -function pcre_utf8_support() +function phpbb_pcre_utf8_support() { static $utf8_pcre_properties = null; if (is_null($utf8_pcre_properties)) diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 179fd3c2f8..b1294a2f14 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -1107,7 +1107,7 @@ function extension_allowed($forum_id, $extension, &$extensions) * @param int $max_length Maximum length of string (multibyte character count as 1 char / Html entity count as 1 char) * @param int $max_store_length Maximum character length of string (multibyte character count as 1 char / Html entity count as entity chars). * @param bool $allow_reply Allow Re: in front of string -* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_legnth) and is deprecated. +* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_length) and is deprecated. * @param string $append String to be appended */ function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '') diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 26a4e965a7..4e8d8f7d34 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -52,6 +52,27 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $sql_where = 'left_id > ' . $root_data['left_id'] . ' AND left_id < ' . $root_data['right_id']; } + // Handle marking everything read + if ($mark_read == 'all') + { + $redirect = build_url(array('mark', 'hash')); + meta_refresh(3, $redirect); + + if (check_link_hash(request_var('hash', ''), 'global')) + { + markread('all'); + + trigger_error( + $user->lang['FORUMS_MARKED'] . '<br /><br />' . + sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>') + ); + } + else + { + trigger_error(sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + } + // Display list of active topics for this category? $show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false; @@ -109,13 +130,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $forum_id = $row['forum_id']; // Mark forums read? - if ($mark_read == 'forums' || $mark_read == 'all') + if ($mark_read == 'forums') { if ($auth->acl_get('f_list', $forum_id)) { $forum_ids[] = $forum_id; - continue; } + + continue; } // Category with no members @@ -141,8 +163,6 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod continue; } - $forum_ids[] = $forum_id; - if ($config['load_db_lastread'] && $user->data['is_registered']) { $forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; @@ -244,22 +264,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $db->sql_freeresult($result); // Handle marking posts - if ($mark_read == 'forums' || $mark_read == 'all') + if ($mark_read == 'forums') { $redirect = build_url(array('mark', 'hash')); $token = request_var('hash', ''); if (check_link_hash($token, 'global')) { - if ($mark_read == 'all') - { - markread('all'); - $message = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>'); - } - else - { - markread('topics', $forum_ids); - $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); - } + markread('topics', $forum_ids); + $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); meta_refresh(3, $redirect); trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); } @@ -446,7 +458,6 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod $l_post_click_count => $post_click_count, 'FORUM_IMG_STYLE' => $folder_image, 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), - 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'), 'FORUM_FOLDER_IMG_ALT' => isset($user->lang[$folder_alt]) ? $user->lang[$folder_alt] : '', 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '', 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', @@ -644,7 +655,7 @@ function topic_generate_pagination($replies, $url) $pagination .= '<a href="' . $url . ($j == 0 ? '' : '&start=' . $j) . '">' . $times . '</a>'; if ($times == 1 && $total_pages > 5) { - $pagination .= ' ... '; + $pagination .= '<span class="page-dots"> ... </span>'; // Display the last three pages $times = $total_pages - 3; @@ -978,13 +989,17 @@ function display_user_activity(&$userdata) } // Obtain active topic + // We need to exclude passworded forums here so we do not leak the topic title + $forum_ary_topic = array_unique(array_merge($forum_ary, $user->get_passworded_forums())); + $forum_sql_topic = (!empty($forum_ary_topic)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary_topic, true) : ''; + $sql = 'SELECT topic_id, COUNT(post_id) AS num_posts FROM ' . POSTS_TABLE . ' WHERE poster_id = ' . $userdata['user_id'] . " AND post_postcount = 1 AND (post_approved = 1 $sql_m_approve) - $forum_sql + $forum_sql_topic GROUP BY topic_id ORDER BY num_posts DESC"; $result = $db->sql_query_limit($sql, 1); diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index 91a09608c7..b4664d74cb 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -274,7 +274,9 @@ function send_file_to_browser($attachment, $upload_dir, $category) */ function header_filename($file) { - $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + global $request; + + $user_agent = $request->header('User-Agent'); // There be dragons here. // Not many follows the RFC... @@ -292,14 +294,14 @@ function header_filename($file) */ function download_allowed() { - global $config, $user, $db; + global $config, $user, $db, $request; if (!$config['secure_downloads']) { return true; } - $url = (!empty($_SERVER['HTTP_REFERER'])) ? trim($_SERVER['HTTP_REFERER']) : trim(getenv('HTTP_REFERER')); + $url = htmlspecialchars_decode($request->header('Referer')); if (!$url) { @@ -404,8 +406,10 @@ function download_allowed() */ function set_modified_headers($stamp, $browser) { + global $request; + // let's see if we have to send the file at all - $last_load = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false; + $last_load = $request->header('Modified-Since') ? strtotime(trim($request->header('Modified-Since'))) : false; if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false)) { if ($last_load !== false && $last_load >= $stamp) @@ -473,12 +477,12 @@ function phpbb_http_byte_range($filesize) { $request_array = phpbb_find_range_request(); } - + return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize); } /** -* Searches for HTTP range request in super globals. +* Searches for HTTP range request in request headers. * * @return mixed false if no request found * array of strings containing the requested ranges otherwise @@ -486,23 +490,16 @@ function phpbb_http_byte_range($filesize) */ function phpbb_find_range_request() { - $globals = array( - array('_SERVER', 'HTTP_RANGE'), - array('_ENV', 'HTTP_RANGE'), - ); + global $request; - foreach ($globals as $array) - { - $global = $array[0]; - $key = $array[1]; + $value = $request->header('Range'); - // Make sure range request starts with "bytes=" - if (isset($GLOBALS[$global][$key]) && strpos($GLOBALS[$global][$key], 'bytes=') === 0) - { - // Strip leading 'bytes=' - // Multiple ranges can be separated by a comma - return explode(',', substr($GLOBALS[$global][$key], 6)); - } + // Make sure range request starts with "bytes=" + if (strpos($value, 'bytes=') === 0) + { + // Strip leading 'bytes=' + // Multiple ranges can be separated by a comma + return explode(',', substr($value, 6)); } return false; diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index f5d102b1da..b94957a85f 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -175,7 +175,7 @@ class messenger */ function template($template_file, $template_lang = '', $template_path = '') { - global $config, $phpbb_root_path, $user; + global $config, $phpbb_root_path, $phpEx, $user; if (!trim($template_file)) { @@ -193,7 +193,8 @@ class messenger // tpl_msg now holds a template object we can use to parse the template file if (!isset($this->tpl_msg[$template_lang . $template_file])) { - $this->tpl_msg[$template_lang . $template_file] = new template(); + $template_locator = new phpbb_template_locator(); + $this->tpl_msg[$template_lang . $template_file] = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator); $tpl = &$this->tpl_msg[$template_lang . $template_file]; $fallback_template_path = false; @@ -333,7 +334,7 @@ class messenger */ function error($type, $msg) { - global $user, $phpEx, $phpbb_root_path, $config; + global $user, $phpEx, $phpbb_root_path, $config, $request; // Session doesn't exist, create it if (!isset($user->session_id) || $user->session_id === '') @@ -341,7 +342,7 @@ class messenger $user->session_begin(); } - $calling_page = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']; + $calling_page = htmlspecialchars_decode($request->server('PHP_SELF')); $message = ''; switch ($type) @@ -975,9 +976,16 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) $smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']); // Ok we have error checked as much as we can to this point let's get on it already. - ob_start(); + if (!class_exists('phpbb_error_collector')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/error_collector.' . $phpEx); + } + $collector = new phpbb_error_collector; + $collector->install(); $smtp->socket = fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20); - $error_contents = ob_get_clean(); + $collector->uninstall(); + $error_contents = $collector->format_errors(); if (!$smtp->socket) { @@ -1608,18 +1616,27 @@ function mail_encode($str, $eol = "\r\n") */ function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg) { - global $config; + global $config, $phpbb_root_path, $phpEx; // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... // Reference: http://bugs.php.net/bug.php?id=15841 $headers = implode($eol, $headers); - ob_start(); + if (!class_exists('phpbb_error_collector')) + { + include($phpbb_root_path . 'includes/error_collector.' . $phpEx); + } + + $collector = new phpbb_error_collector; + $collector->install(); + // On some PHP Versions mail() *may* fail if there are newlines within the subject. // Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8. // Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used) $result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers); - $err_msg = ob_get_clean(); + + $collector->uninstall(); + $err_msg = $collector->format_errors(); return $result; } diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 9e81533cea..4ca76344de 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -1078,7 +1078,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id continue; } - $row =& $rowset[$post_list[$i]]; + $row = $rowset[$post_list[$i]]; $poster_id = $row['user_id']; $post_subject = $row['post_subject']; diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 9787bdfbc4..32b57a9f2e 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -19,7 +19,8 @@ if (!defined('IN_PHPBB')) Ability to simply add own rules by doing three things: 1) Add an appropriate constant 2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required) - 3) Add a new language variable to ucp.php + 3) Implement the rule logic in the check_rule() function + 4) Add a new language variable to ucp.php The user is then able to select the new rule. It will be checked against and handled as specified. To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified. @@ -57,42 +58,42 @@ define('CHECK_TO', 5); */ $global_privmsgs_rules = array( CHECK_SUBJECT => array( - RULE_IS_LIKE => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), + RULE_IS_LIKE => array('check0' => 'message_subject'), + RULE_IS_NOT_LIKE => array('check0' => 'message_subject'), + RULE_IS => array('check0' => 'message_subject'), + RULE_IS_NOT => array('check0' => 'message_subject'), + RULE_BEGINS_WITH => array('check0' => 'message_subject'), + RULE_ENDS_WITH => array('check0' => 'message_subject'), ), CHECK_SENDER => array( - RULE_IS_LIKE => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), - RULE_IS_FRIEND => array('check0' => 'friend', 'function' => '{CHECK0} == 1'), - RULE_IS_FOE => array('check0' => 'foe', 'function' => '{CHECK0} == 1'), - RULE_IS_USER => array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'), - RULE_IS_GROUP => array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'), + RULE_IS_LIKE => array('check0' => 'username'), + RULE_IS_NOT_LIKE => array('check0' => 'username'), + RULE_IS => array('check0' => 'username'), + RULE_IS_NOT => array('check0' => 'username'), + RULE_BEGINS_WITH => array('check0' => 'username'), + RULE_ENDS_WITH => array('check0' => 'username'), + RULE_IS_FRIEND => array('check0' => 'friend'), + RULE_IS_FOE => array('check0' => 'foe'), + RULE_IS_USER => array('check0' => 'author_id'), + RULE_IS_GROUP => array('check0' => 'author_in_group'), ), CHECK_MESSAGE => array( - RULE_IS_LIKE => array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'), + RULE_IS_LIKE => array('check0' => 'message_text'), + RULE_IS_NOT_LIKE => array('check0' => 'message_text'), + RULE_IS => array('check0' => 'message_text'), + RULE_IS_NOT => array('check0' => 'message_text'), ), CHECK_STATUS => array( - RULE_ANSWERED => array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'), - RULE_FORWARDED => array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'), + RULE_ANSWERED => array('check0' => 'pm_replied'), + RULE_FORWARDED => array('check0' => 'pm_forwarded'), ), CHECK_TO => array( - RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'), - RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'), + RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group'), + RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc'), ) ); @@ -260,16 +261,60 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id) $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']]; - // Replace Check Literals - $evaluate = $check_ary['function']; - $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate); + $result = false; - // Replace Rule Literals - $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate); + $check0 = $message_row[$check_ary['check0']]; + + switch ($rule_row['rule_connection']) + { + case RULE_IS_LIKE: + $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_IS_NOT_LIKE: + $result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_IS: + $result = ($check0 == $rule_row['rule_string']); + break; + + case RULE_IS_NOT: + $result = ($check0 != $rule_row['rule_string']); + break; + + case RULE_BEGINS_WITH: + $result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0); + break; + + case RULE_ENDS_WITH: + $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0); + break; + + case RULE_IS_FRIEND: + case RULE_IS_FOE: + case RULE_ANSWERED: + case RULE_FORWARDED: + $result = ($check0 == 1); + break; + + case RULE_IS_USER: + $result = ($check0 == $rule_row['rule_user_id']); + break; + + case RULE_IS_GROUP: + $result = in_array($rule_row['rule_group_id'], $check0); + break; + + case RULE_TO_GROUP: + $result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']])); + break; + + case RULE_TO_ME: + $result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']])); + break; + } - // Evil Statement - $result = false; - eval('$result = (' . $evaluate . ') ? true : false;'); if (!$result) { diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php deleted file mode 100644 index 8c58c33b0d..0000000000 --- a/phpBB/includes/functions_template.php +++ /dev/null @@ -1,812 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Extension of template class - Functions needed for compiling templates only. -* -* psoTFX, phpBB Development Team - Completion of file caching, decompilation -* routines and implementation of conditionals/keywords and associated changes -* -* The interface was inspired by PHPLib templates, and the template file (formats are -* quite similar) -* -* The keyword/conditional implementation is currently based on sections of code from -* the Smarty templating engine (c) 2001 ispi of Lincoln, Inc. which is released -* (on its own and in whole) under the LGPL. Section 3 of the LGPL states that any code -* derived from an LGPL application may be relicenced under the GPL, this applies -* to this source -* -* DEFINE directive inspired by a request by Cyberalien -* -* @package phpBB3 -*/ -class template_compile -{ - var $template; - - // Various storage arrays - var $block_names = array(); - var $block_else_level = array(); - - /** - * constuctor - */ - function template_compile(&$template) - { - $this->template = &$template; - } - - /** - * Load template source from file - * @access private - */ - function _tpl_load_file($handle, $store_in_db = false) - { - // Try and open template for read - if (!file_exists($this->template->files[$handle])) - { - trigger_error("template->_tpl_load_file(): File {$this->template->files[$handle]} does not exist or is empty", E_USER_ERROR); - } - - $this->template->compiled_code[$handle] = $this->compile(trim(@file_get_contents($this->template->files[$handle]))); - - // Actually compile the code now. - $this->compile_write($handle, $this->template->compiled_code[$handle]); - - // Store in database if required... - if ($store_in_db) - { - global $db, $user; - - $sql_ary = array( - 'template_id' => $this->template->files_template[$handle], - 'template_filename' => $this->template->filename[$handle], - 'template_included' => '', - 'template_mtime' => time(), - 'template_data' => trim(@file_get_contents($this->template->files[$handle])), - ); - - $sql = 'INSERT INTO ' . STYLES_TEMPLATE_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); - } - } - - /** - * Remove any PHP tags that do not belong, these regular expressions are derived from - * the ones that exist in zend_language_scanner.l - * @access private - */ - function remove_php_tags(&$code) - { - // This matches the information gathered from the internal PHP lexer - $match = array( - '#<([\?%])=?.*?\1>#s', - '#<script\s+language\s*=\s*(["\']?)php\1\s*>.*?</script\s*>#s', - '#<\?php(?:\r\n?|[ \n\t]).*?\?>#s' - ); - - $code = preg_replace($match, '', $code); - } - - /** - * The all seeing all doing compile method. Parts are inspired by or directly from Smarty - * @access private - */ - function compile($code, $no_echo = false, $echo_var = '') - { - global $config; - - if ($echo_var) - { - global $$echo_var; - } - - // Remove any "loose" php ... we want to give admins the ability - // to switch on/off PHP for a given template. Allowing unchecked - // php is a no-no. There is a potential issue here in that non-php - // content may be removed ... however designers should use entities - // if they wish to display < and > - $this->remove_php_tags($code); - - // Pull out all block/statement level elements and separate plain text - preg_match_all('#<!-- PHP -->(.*?)<!-- ENDPHP -->#s', $code, $matches); - $php_blocks = $matches[1]; - $code = preg_replace('#<!-- PHP -->.*?<!-- ENDPHP -->#s', '<!-- PHP -->', $code); - - preg_match_all('#<!-- INCLUDE (\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches); - $include_blocks = $matches[1]; - $code = preg_replace('#<!-- INCLUDE (?:\{\$?[A-Z0-9\-_]+\}|[a-zA-Z0-9\_\-\+\./]+) -->#', '<!-- INCLUDE -->', $code); - - preg_match_all('#<!-- INCLUDEPHP ([a-zA-Z0-9\_\-\+\./]+) -->#', $code, $matches); - $includephp_blocks = $matches[1]; - $code = preg_replace('#<!-- INCLUDEPHP [a-zA-Z0-9\_\-\+\./]+ -->#', '<!-- INCLUDEPHP -->', $code); - - preg_match_all('#<!-- ([^<].*?) (.*?)? ?-->#', $code, $blocks, PREG_SET_ORDER); - - $text_blocks = preg_split('#<!-- [^<].*? (?:.*?)? ?-->#', $code); - - for ($i = 0, $j = sizeof($text_blocks); $i < $j; $i++) - { - $this->compile_var_tags($text_blocks[$i]); - } - $compile_blocks = array(); - - for ($curr_tb = 0, $tb_size = sizeof($blocks); $curr_tb < $tb_size; $curr_tb++) - { - $block_val = &$blocks[$curr_tb]; - - switch ($block_val[1]) - { - case 'BEGIN': - $this->block_else_level[] = false; - $compile_blocks[] = '<?php ' . $this->compile_tag_block($block_val[2]) . ' ?>'; - break; - - case 'BEGINELSE': - $this->block_else_level[sizeof($this->block_else_level) - 1] = true; - $compile_blocks[] = '<?php }} else { ?>'; - break; - - case 'END': - array_pop($this->block_names); - $compile_blocks[] = '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>'; - break; - - case 'IF': - $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], false) . ' ?>'; - break; - - case 'ELSE': - $compile_blocks[] = '<?php } else { ?>'; - break; - - case 'ELSEIF': - $compile_blocks[] = '<?php ' . $this->compile_tag_if($block_val[2], true) . ' ?>'; - break; - - case 'ENDIF': - $compile_blocks[] = '<?php } ?>'; - break; - - case 'DEFINE': - $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], true) . ' ?>'; - break; - - case 'UNDEFINE': - $compile_blocks[] = '<?php ' . $this->compile_tag_define($block_val[2], false) . ' ?>'; - break; - - case 'INCLUDE': - $temp = array_shift($include_blocks); - - // Dynamic includes - // Cheap match rather than a full blown regexp, we already know - // the format of the input so just use string manipulation. - if ($temp[0] == '{') - { - $file = false; - - if ($temp[1] == '$') - { - $var = substr($temp, 2, -1); - //$file = $this->template->_tpldata['DEFINE']['.'][$var]; - $temp = "\$this->_tpldata['DEFINE']['.']['$var']"; - } - else - { - $var = substr($temp, 1, -1); - //$file = $this->template->_rootref[$var]; - $temp = "\$this->_rootref['$var']"; - } - } - else - { - $file = $temp; - } - - $compile_blocks[] = '<?php ' . $this->compile_tag_include($temp) . ' ?>'; - - // No point in checking variable includes - if ($file) - { - $this->template->_tpl_include($file, false); - } - break; - - case 'INCLUDEPHP': - $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . $this->compile_tag_include_php(array_shift($includephp_blocks)) . ' ?>' : ''; - break; - - case 'PHP': - $compile_blocks[] = ($config['tpl_allow_php']) ? '<?php ' . array_shift($php_blocks) . ' ?>' : ''; - break; - - default: - $this->compile_var_tags($block_val[0]); - $trim_check = trim($block_val[0]); - $compile_blocks[] = (!$no_echo) ? ((!empty($trim_check)) ? $block_val[0] : '') : ((!empty($trim_check)) ? $block_val[0] : ''); - break; - } - } - - $template_php = ''; - for ($i = 0, $size = sizeof($text_blocks); $i < $size; $i++) - { - $trim_check_text = trim($text_blocks[$i]); - $template_php .= (!$no_echo) ? (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : '') : (($trim_check_text != '') ? $text_blocks[$i] : '') . ((isset($compile_blocks[$i])) ? $compile_blocks[$i] : ''); - } - - // Remove unused opening/closing tags - $template_php = str_replace(' ?><?php ', ' ', $template_php); - - // Now add a newline after each php closing tag which already has a newline - // PHP itself strips a newline if a closing tag is used (this is documented behaviour) and it is mostly not intended by style authors to remove newlines - $template_php = preg_replace('#\?\>([\r\n])#', '?>\1\1', $template_php); - - // There will be a number of occasions where we switch into and out of - // PHP mode instantaneously. Rather than "burden" the parser with this - // we'll strip out such occurences, minimising such switching - if ($no_echo) - { - return "\$$echo_var .= '" . $template_php . "'"; - } - - return $template_php; - } - - /** - * Compile variables - * @access private - */ - function compile_var_tags(&$text_blocks) - { - // change template varrefs into PHP varrefs - $varrefs = array(); - - // This one will handle varrefs WITH namespaces - preg_match_all('#\{((?:[a-z0-9\-_]+\.)+)(\$)?([A-Z0-9\-_]+)\}#', $text_blocks, $varrefs, PREG_SET_ORDER); - - foreach ($varrefs as $var_val) - { - $namespace = $var_val[1]; - $varname = $var_val[3]; - $new = $this->generate_block_varref($namespace, $varname, true, $var_val[2]); - - $text_blocks = str_replace($var_val[0], $new, $text_blocks); - } - - // This will handle the remaining root-level varrefs - // transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array - if (strpos($text_blocks, '{L_') !== false) - { - $text_blocks = preg_replace('#\{L_([A-Z0-9\-_]+)\}#', "<?php echo ((isset(\$this->_rootref['L_\\1'])) ? \$this->_rootref['L_\\1'] : ((isset(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '{ \\1 }')); ?>", $text_blocks); - } - - // Handle addslashed language variables prefixed with LA_ - // If a template variable already exist, it will be used in favor of it... - if (strpos($text_blocks, '{LA_') !== false) - { - $text_blocks = preg_replace('#\{LA_([A-Z0-9\-_]+)\}#', "<?php echo ((isset(\$this->_rootref['LA_\\1'])) ? \$this->_rootref['LA_\\1'] : ((isset(\$this->_rootref['L_\\1'])) ? addslashes(\$this->_rootref['L_\\1']) : ((isset(\$user->lang['\\1'])) ? addslashes(\$user->lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks); - } - - // Handle remaining varrefs - $text_blocks = preg_replace('#\{([A-Z0-9\-_]+)\}#', "<?php echo (isset(\$this->_rootref['\\1'])) ? \$this->_rootref['\\1'] : ''; ?>", $text_blocks); - $text_blocks = preg_replace('#\{\$([A-Z0-9\-_]+)\}#', "<?php echo (isset(\$this->_tpldata['DEFINE']['.']['\\1'])) ? \$this->_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); - - return; - } - - /** - * Compile blocks - * @access private - */ - function compile_tag_block($tag_args) - { - $no_nesting = false; - - // Is the designer wanting to call another loop in a loop? - if (strpos($tag_args, '!') === 0) - { - // Count the number of ! occurrences (not allowed in vars) - $no_nesting = substr_count($tag_args, '!'); - $tag_args = substr($tag_args, $no_nesting); - } - - // Allow for control of looping (indexes start from zero): - // foo(2) : Will start the loop on the 3rd entry - // foo(-2) : Will start the loop two entries from the end - // foo(3,4) : Will start the loop on the fourth entry and end it on the fifth - // foo(3,-4) : Will start the loop on the fourth entry and end it four from last - if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#', $tag_args, $match)) - { - $tag_args = $match[1]; - - if ($match[2] < 0) - { - $loop_start = '($_' . $tag_args . '_count ' . $match[2] . ' < 0 ? 0 : $_' . $tag_args . '_count ' . $match[2] . ')'; - } - else - { - $loop_start = '($_' . $tag_args . '_count < ' . $match[2] . ' ? $_' . $tag_args . '_count : ' . $match[2] . ')'; - } - - if (strlen($match[3]) < 1 || $match[3] == -1) - { - $loop_end = '$_' . $tag_args . '_count'; - } - else if ($match[3] >= 0) - { - $loop_end = '(' . ($match[3] + 1) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ($match[3] + 1) . ')'; - } - else //if ($match[3] < -1) - { - $loop_end = '$_' . $tag_args . '_count' . ($match[3] + 1); - } - } - else - { - $loop_start = 0; - $loop_end = '$_' . $tag_args . '_count'; - } - - $tag_template_php = ''; - array_push($this->block_names, $tag_args); - - if ($no_nesting !== false) - { - // We need to implode $no_nesting times from the end... - $block = array_slice($this->block_names, -$no_nesting); - } - else - { - $block = $this->block_names; - } - - if (sizeof($block) < 2) - { - // Block is not nested. - $tag_template_php = '$_' . $tag_args . "_count = (isset(\$this->_tpldata['$tag_args'])) ? sizeof(\$this->_tpldata['$tag_args']) : 0;"; - $varref = "\$this->_tpldata['$tag_args']"; - } - else - { - // This block is nested. - // Generate a namespace string for this block. - $namespace = implode('.', $block); - - // 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. - $tag_template_php = '$_' . $tag_args . '_count = (isset(' . $varref . ')) ? sizeof(' . $varref . ') : 0;'; - } - - $tag_template_php .= 'if ($_' . $tag_args . '_count) {'; - - /** - * The following uses foreach for iteration instead of a for loop, foreach is faster but requires PHP to make a copy of the contents of the array which uses more memory - * <code> - * if (!$offset) - * { - * $tag_template_php .= 'foreach (' . $varref . ' as $_' . $tag_args . '_i => $_' . $tag_args . '_val){'; - * } - * </code> - */ - - $tag_template_php .= 'for ($_' . $tag_args . '_i = ' . $loop_start . '; $_' . $tag_args . '_i < ' . $loop_end . '; ++$_' . $tag_args . '_i){'; - $tag_template_php .= '$_'. $tag_args . '_val = &' . $varref . '[$_'. $tag_args. '_i];'; - - return $tag_template_php; - } - - /** - * Compile IF tags - much of this is from Smarty with - * some adaptions for our block level methods - * @access private - */ - 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, $size = sizeof($tokens); $i < $size; $i++) - { - $token = &$tokens[$i]; - - switch ($token) - { - case '!==': - case '===': - case '<<': - case '>>': - case '|': - case '^': - case '&': - case '~': - case ')': - case ',': - case '+': - case '-': - case '*': - case '/': - case '@': - break; - - case '==': - case 'eq': - $token = '=='; - break; - - case '!=': - case '<>': - case 'ne': - case 'neq': - $token = '!='; - break; - - case '<': - case 'lt': - $token = '<'; - break; - - case '<=': - case 'le': - case 'lte': - $token = '<='; - break; - - case '>': - case 'gt': - $token = '>'; - break; - - case '>=': - case 'ge': - case 'gte': - $token = '>='; - break; - - case '&&': - case 'and': - $token = '&&'; - break; - - case '||': - case 'or': - $token = '||'; - break; - - case '!': - case 'not': - $token = '!'; - break; - - case '%': - 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, sizeof($tokens), $new_tokens); - - $i = $is_arg_start; - - // no break - - 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[2]) . '[\'' . $varrefs[3] . '\']' : (($varrefs[2]) ? '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$this->_rootref[\'' . $varrefs[3] . '\']'); - } - else if (preg_match('#^\.((?:[a-z0-9\-_]+\.?)+)$#s', $token, $varrefs)) - { - // Allow checking if loops are set with .loopname - // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example - $blocks = explode('.', $varrefs[1]); - - // If the block is nested, we have a reference that we can grab. - // If the block is not nested, we just go and grab the block from _tpldata - if (sizeof($blocks) > 1) - { - $block = array_pop($blocks); - $namespace = implode('.', $blocks); - $varref = $this->generate_block_data_ref($namespace, true); - - // Add the block reference for the last child. - $varref .= "['" . $block . "']"; - } - else - { - $varref = '$this->_tpldata'; - - // Add the block reference for the last child. - $varref .= "['" . $blocks[0] . "']"; - } - $token = "sizeof($varref)"; - } - else if (!empty($token)) - { - $token = '(' . $token . ')'; - } - - break; - } - } - - // If there are no valid tokens left or only control/compare characters left, we do skip this statement - if (!sizeof($tokens) || str_replace(array(' ', '=', '!', '<', '>', '&', '|', '%', '(', ')'), '', implode('', $tokens)) == '') - { - $tokens = array('false'); - } - return (($elseif) ? '} else if (' : 'if (') . (implode(' ', $tokens) . ') { '); - } - - /** - * Compile DEFINE tags - * @access private - */ - function compile_tag_define($tag_args, $op) - { - preg_match('#^((?:[a-z0-9\-_]+\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (\'?)([^\']*)(\'?))?$#', $tag_args, $match); - - if (empty($match[2]) || (!isset($match[4]) && $op)) - { - return ''; - } - - if (!$op) - { - return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');'; - } - - // Are we a string? - if ($match[3] && $match[5]) - { - $match[4] = str_replace(array('\\\'', '\\\\', '\''), array('\'', '\\', '\\\''), $match[4]); - - // Compile reference, we allow template variables in defines... - $match[4] = $this->compile($match[4]); - - // Now replace the php code - $match[4] = "'" . str_replace(array('<?php echo ', '; ?>'), array("' . ", " . '"), $match[4]) . "'"; - } - else - { - preg_match('#true|false|\.#i', $match[4], $type); - - switch (strtolower($type[0])) - { - case 'true': - case 'false': - $match[4] = strtoupper($match[4]); - break; - - case '.': - $match[4] = doubleval($match[4]); - break; - - default: - $match[4] = intval($match[4]); - break; - } - } - - return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$this->_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $match[4] . ';'; - } - - /** - * Compile INCLUDE tag - * @access private - */ - function compile_tag_include($tag_args) - { - // Process dynamic includes - if ($tag_args[0] == '$') - { - return "if (isset($tag_args)) { \$this->_tpl_include($tag_args); }"; - } - - return "\$this->_tpl_include('$tag_args');"; - } - - /** - * Compile INCLUDE_PHP tag - * @access private - */ - function compile_tag_include_php($tag_args) - { - return "\$this->_php_include('$tag_args');"; - } - - /** - * parse expression - * This is from Smarty - * @access private - */ - 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 & 1)"; - } - 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 & 1)"; - } - break; - - case 'div': - if (@$tokens[$expr_end] == 'by') - { - $expr_end++; - $expr_arg = $tokens[$expr_end++]; - $expr = "!($is_arg % $expr_arg)"; - } - break; - } - - if ($negate_expr) - { - $expr = "!($expr)"; - } - - array_splice($tokens, 0, $expr_end, $expr); - - return $tokens; - } - - /** - * 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. - * @access private - */ - function generate_block_varref($namespace, $varname, $echo = true, $defop = false) - { - // Strip the trailing period. - $namespace = substr($namespace, 0, -1); - - // Get a reference to the data block for this namespace. - $varref = $this->generate_block_data_ref($namespace, true, $defop); - // Prepend the necessary code to stick this in an echo line. - - // Append the variable reference. - $varref .= "['$varname']"; - $varref = ($echo) ? "<?php echo $varref; ?>" : ((isset($varref)) ? $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. - * @access private - */ - 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; - - // DEFINE is not an element of any referenced variable, we must use _tpldata to access it - 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; - } - else if ($include_last_iterator) - { - return '$_'. $blocks[$blockcount] . '_val'; - } - else - { - return '$_'. $blocks[$blockcount - 1] . '_val[\''. $blocks[$blockcount]. '\']'; - } - } - - /** - * Write compiled file to cache directory - * @access private - */ - function compile_write($handle, $data) - { - global $phpEx; - - $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.' . $phpEx; - - $data = "<?php if (!defined('IN_PHPBB')) exit;" . ((strpos($data, '<?php') === 0) ? substr($data, 5) : ' ?>' . $data); - - if ($fp = @fopen($filename, 'wb')) - { - @flock($fp, LOCK_EX); - @fwrite ($fp, $data); - @flock($fp, LOCK_UN); - @fclose($fp); - - phpbb_chmod($filename, CHMOD_READ | CHMOD_WRITE); - } - - return; - } -} diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php index fca092a4de..2b7919a8d2 100644 --- a/phpBB/includes/functions_transfer.php +++ b/phpBB/includes/functions_transfer.php @@ -808,23 +808,56 @@ class ftp_fsock extends transfer */ function _open_data_connection() { - $this->_send_command('PASV', '', false); - - if (!$ip_port = $this->_check_command(true)) + // Try to find out whether we have a IPv4 or IPv6 (control) connection + if (function_exists('stream_socket_get_name')) { - return false; + $socket_name = stream_socket_get_name($this->connection, true); + $server_ip = substr($socket_name, 0, strrpos($socket_name, ':')); } - // open the connection to start sending the file - if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip)) { - // bad ip and port - return false; + // Passive mode + $this->_send_command('PASV', '', false); + + if (!$ip_port = $this->_check_command(true)) + { + return false; + } + + // open the connection to start sending the file + if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) + { + // bad ip and port + return false; + } + + $temp = explode(',', $temp[0]); + $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; + $server_port = $temp[4] * 256 + $temp[5]; + } + else + { + // Extended Passive Mode - RFC2428 + $this->_send_command('EPSV', '', false); + + if (!$epsv_response = $this->_check_command(true)) + { + return false; + } + + // Response looks like "229 Entering Extended Passive Mode (|||12345|)" + // where 12345 is the tcp port for the data connection + if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match)) + { + return false; + } + $server_port = (int) $match[1]; + + // fsockopen expects IPv6 address in square brackets + $server_ip = "[$server_ip]"; } - $temp = explode(',', $temp[0]); - $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; - $server_port = $temp[4] * 256 + $temp[5]; $errno = 0; $errstr = ''; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 124aac18be..930cd4625f 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1477,7 +1477,7 @@ function validate_username($username, $allowed_username = false) $mbstring = $pcre = false; // generic UTF-8 character types supported? - if (pcre_utf8_support()) + if (phpbb_pcre_utf8_support()) { $pcre = true; } @@ -1614,7 +1614,7 @@ function validate_password($password) $pcre = $mbstring = false; // generic UTF-8 character types supported? - if (pcre_utf8_support()) + if (phpbb_pcre_utf8_support()) { $upp = '\p{Lu}'; $low = '\p{Ll}'; diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index f170dd68eb..8206a183f3 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -227,7 +227,6 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), - 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php index b9231547cd..fa12d570df 100644 --- a/phpBB/includes/questionnaire/questionnaire.php +++ b/phpBB/includes/questionnaire/questionnaire.php @@ -148,23 +148,15 @@ class phpbb_questionnaire_system_data_provider */ function get_data() { - // Start discovering the IPV4 server address, if available - $server_address = '0.0.0.0'; - - if (!empty($_SERVER['SERVER_ADDR'])) - { - $server_address = $_SERVER['SERVER_ADDR']; - } + global $request; - // Running on IIS? - if (!empty($_SERVER['LOCAL_ADDR'])) - { - $server_address = $_SERVER['LOCAL_ADDR']; - } + // Start discovering the IPV4 server address, if available + // Try apache, IIS, fall back to 0.0.0.0 + $server_address = htmlspecialchars_decode($request->server('SERVER_ADDR', $request->server('LOCAL_ADDR', '0.0.0.0'))); return array( 'os' => PHP_OS, - 'httpd' => $_SERVER['SERVER_SOFTWARE'], + 'httpd' => htmlspecialchars_decode($request->server('SERVER_SOFTWARE')), // we don't want the real IP address (for privacy policy reasons) but only // a network address to see whether your installation is running on a private or public network. 'private_ip' => $this->is_private_ip($server_address), @@ -482,7 +474,7 @@ class phpbb_questionnaire_phpbb_data_provider } } - global $db; + global $db, $request; $result['dbms'] = $dbms; $result['acm_type'] = $acm_type; @@ -492,7 +484,7 @@ class phpbb_questionnaire_phpbb_data_provider // Try to get user agent vendor and version $match = array(); - $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? (string) $_SERVER['HTTP_USER_AGENT'] : ''; + $user_agent = $request->header('User-Agent'); $agents = array('firefox', 'msie', 'opera', 'chrome', 'safari', 'mozilla', 'seamonkey', 'konqueror', 'netscape', 'gecko', 'navigator', 'mosaic', 'lynx', 'amaya', 'omniweb', 'avant', 'camino', 'flock', 'aol'); // We check here 1 by 1 because some strings occur after others (for example Mozilla [...] Firefox/) diff --git a/phpBB/includes/request/interface.php b/phpBB/includes/request/interface.php index 7b5b600100..181bcb467a 100644 --- a/phpBB/includes/request/interface.php +++ b/phpBB/includes/request/interface.php @@ -29,6 +29,7 @@ interface phpbb_request_interface const GET = 1; const REQUEST = 2; const COOKIE = 3; + const SERVER = 4; /**#@-*/ /** @@ -67,6 +68,26 @@ interface phpbb_request_interface public function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST); /** + * Shortcut method to retrieve SERVER variables. + * + * @param string|array $var_name See phpbb_request_interface::variable + * @param mixed $default See phpbb_request_interface::variable + * + * @return mixed The server variable value. + */ + public function server($var_name, $default = ''); + + /** + * Shortcut method to retrieve the value of client HTTP headers. + * + * @param string|array $header_name The name of the header to retrieve. + * @param mixed $default See phpbb_request_interface::variable + * + * @return mixed The header value. + */ + public function header($var_name, $default = ''); + + /** * Checks whether a certain variable was sent via POST. * To make sure that a request was sent using POST you should call this function * on at least one variable. @@ -91,6 +112,20 @@ interface phpbb_request_interface public function is_set($var, $super_global = phpbb_request_interface::REQUEST); /** + * Checks whether the current request is an AJAX request (XMLHttpRequest) + * + * @return bool True if the current request is an ajax request + */ + public function is_ajax(); + + /** + * Checks if the current request is happening over HTTPS. + * + * @return bool True if the request is secure. + */ + public function is_secure(); + + /** * Returns all variable names for a given super global * * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global diff --git a/phpBB/includes/request/request.php b/phpBB/includes/request/request.php index 7d284a9bf7..9386088a07 100644 --- a/phpBB/includes/request/request.php +++ b/phpBB/includes/request/request.php @@ -32,7 +32,8 @@ class phpbb_request implements phpbb_request_interface phpbb_request_interface::POST => '_POST', phpbb_request_interface::GET => '_GET', phpbb_request_interface::REQUEST => '_REQUEST', - phpbb_request_interface::COOKIE => '_COOKIE' + phpbb_request_interface::COOKIE => '_COOKIE', + phpbb_request_interface::SERVER => '_SERVER', ); /** @@ -242,6 +243,47 @@ class phpbb_request implements phpbb_request_interface } /** + * Shortcut method to retrieve SERVER variables. + * + * Also fall back to getenv(), some CGI setups may need it (probably not, but + * whatever). + * + * @param string|array $var_name See phpbb_request_interface::variable + * @param mixed $Default See phpbb_request_interface::variable + * + * @return mixed The server variable value. + */ + public function server($var_name, $default = '') + { + $multibyte = true; + + if ($this->is_set($var_name, phpbb_request_interface::SERVER)) + { + return $this->variable($var_name, $default, $multibyte, phpbb_request_interface::SERVER); + } + else + { + $var = getenv($var_name); + $this->type_cast_helper->recursive_set_var($var, $default, $multibyte); + return $var; + } + } + + /** + * Shortcut method to retrieve the value of client HTTP headers. + * + * @param string|array $header_name The name of the header to retrieve. + * @param mixed $default See phpbb_request_interface::variable + * + * @return mixed The header value. + */ + public function header($header_name, $default = '') + { + $var_name = 'HTTP_' . str_replace('-', '_', strtoupper($header_name)); + return $this->server($var_name, $default); + } + + /** * Checks whether a certain variable was sent via POST. * To make sure that a request was sent using POST you should call this function * on at least one variable. @@ -272,6 +314,26 @@ class phpbb_request implements phpbb_request_interface } /** + * Checks whether the current request is an AJAX request (XMLHttpRequest) + * + * @return bool True if the current request is an ajax request + */ + public function is_ajax() + { + return $this->header('X-Requested-With') == 'XMLHttpRequest'; + } + + /** + * Checks if the current request is happening over HTTPS. + * + * @return bool True if the request is secure. + */ + public function is_secure() + { + return $this->server('HTTPS') == 'on'; + } + + /** * Returns all variable names for a given super global * * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global diff --git a/phpBB/includes/request/type_cast_helper.php b/phpBB/includes/request/type_cast_helper.php index 29855a9804..96ceb0df1d 100644 --- a/phpBB/includes/request/type_cast_helper.php +++ b/phpBB/includes/request/type_cast_helper.php @@ -88,11 +88,11 @@ class phpbb_request_type_cast_helper implements phpbb_request_type_cast_helper_i /** * Set variable $result to a particular type. * - * @param mixed &$result The variable to fill - * @param mixed $var The contents to fill with - * @param mixed $type The variable type. Will be used with {@link settype()} - * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. - * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. + * @param mixed &$result The variable to fill + * @param mixed $var The contents to fill with + * @param mixed $type The variable type. Will be used with {@link settype()} + * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. */ public function set_var(&$result, $var, $type, $multibyte = false) { @@ -101,7 +101,8 @@ class phpbb_request_type_cast_helper implements phpbb_request_type_cast_helper_i if ($type == 'string') { - $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8')); + $result = trim(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result)); + $result = htmlspecialchars($result, ENT_COMPAT, 'UTF-8'); if ($multibyte) { diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 9660fd6986..827205f20d 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -43,7 +43,7 @@ class fulltext_mysql extends search_backend $this->word_length = array('min' => $config['fulltext_mysql_min_word_len'], 'max' => $config['fulltext_mysql_max_word_len']); // PHP may not be linked with the bundled PCRE lib and instead with an older version - if (pcre_utf8_support()) + if (phpbb_pcre_utf8_support()) { $this->pcre_properties = true; } diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index e36f44ddfa..bd2257c139 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -41,16 +41,18 @@ class session */ static function extract_current_page($root_path) { + global $request; + $page_array = array(); // First of all, get the request uri... - $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); - $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); + $script_name = htmlspecialchars_decode($request->server('PHP_SELF')); + $args = explode('&', htmlspecialchars_decode($request->server('QUERY_STRING'))); // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... if (!$script_name) { - $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); + $script_name = htmlspecialchars_decode($request->server('REQUEST_URI')); $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name; $page_array['failover'] = 1; } @@ -141,10 +143,10 @@ class session */ function extract_current_hostname() { - global $config; + global $config, $request; // Get hostname - $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + $host = htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))); // Should be a string and lowered $host = (string) strtolower($host); @@ -212,9 +214,9 @@ class session $this->time_now = time(); $this->cookie_data = array('u' => 0, 'k' => ''); $this->update_session_page = $update_session_page; - $this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; - $this->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; - $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? htmlspecialchars((string) $_SERVER['HTTP_X_FORWARDED_FOR']) : ''; + $this->browser = $request->header('User-Agent'); + $this->referer = $request->header('Referer'); + $this->forwarded_for = $request->header('X-Forwarded-For'); $this->host = $this->extract_current_hostname(); $this->page = $this->extract_current_page($phpbb_root_path); @@ -268,7 +270,7 @@ class session // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip. - $this->ip = (!empty($_SERVER['REMOTE_ADDR'])) ? (string) $_SERVER['REMOTE_ADDR'] : ''; + $this->ip = htmlspecialchars_decode($request->server('REMOTE_ADDR')); $this->ip = preg_replace('# {2,}#', ' ', str_replace(',', ' ', $this->ip)); // split the list of IPs @@ -382,7 +384,7 @@ class session $referer_valid = true; // we assume HEAD and TRACE to be foul play and thus only whitelist GET - if (@$config['referer_validation'] && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) !== 'get') + if (@$config['referer_validation'] && strtolower($request->server('REQUEST_METHOD')) !== 'get') { $referer_valid = $this->validate_referer($check_referer_path); } @@ -1449,7 +1451,7 @@ class session */ function validate_referer($check_script_path = false) { - global $config; + global $config, $request; // no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason) if (empty($this->referer) || empty($this->host)) @@ -1467,7 +1469,7 @@ class session else if ($check_script_path && rtrim($this->page['root_script_path'], '/') !== '') { $ref = substr($ref, strlen($host)); - $server_port = (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); + $server_port = $request->server('SERVER_PORT', 0); if ($server_port !== 80 && $server_port !== 443 && stripos($ref, ":$server_port") === 0) { @@ -1592,9 +1594,9 @@ class user extends session * If re-enabled we need to make sure only those languages installed are checked * Commented out so we do not loose the code. - if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) + if ($request->header('Accept-Language')) { - $accept_lang_ary = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']); + $accept_lang_ary = explode(',', $request->header('Accept-Language')); foreach ($accept_lang_ary as $accept_lang) { @@ -1653,12 +1655,11 @@ class user extends session $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); } - $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i + $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_id + FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c WHERE s.style_id = $style AND t.template_id = s.template_id - AND c.theme_id = s.theme_id - AND i.imageset_id = s.imageset_id"; + AND c.theme_id = s.theme_id"; $result = $db->sql_query($sql, 3600); $this->theme = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1673,12 +1674,11 @@ class user extends session WHERE user_id = {$this->data['user_id']}"; $db->sql_query($sql); - $sql = 'SELECT s.style_id, t.template_storedb, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i + $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_id + FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c WHERE s.style_id = $style AND t.template_id = s.template_id - AND c.theme_id = s.theme_id - AND i.imageset_id = s.imageset_id"; + AND c.theme_id = s.theme_id"; $result = $db->sql_query($sql, 3600); $this->theme = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1696,7 +1696,6 @@ class user extends session $parsed_items = $parsed_items['theme']; $check_for = array( - 'parse_css_file' => (int) 0, 'pagination_sep' => (string) ', ' ); @@ -1711,143 +1710,9 @@ class user extends session } } - // If the style author specified the theme needs to be cached - // (because of the used paths and variables) than make sure it is the case. - // For example, if the theme uses language-specific images it needs to be stored in db. - if (!$this->theme['theme_storedb'] && $this->theme['parse_css_file']) - { - $this->theme['theme_storedb'] = 1; - - $stylesheet = file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/stylesheet.css"); - // Match CSS imports - $matches = array(); - preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); - - if (sizeof($matches)) - { - $content = ''; - foreach ($matches[0] as $idx => $match) - { - if ($content = @file_get_contents("{$phpbb_root_path}styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx])) - { - $content = trim($content); - } - else - { - $content = ''; - } - $stylesheet = str_replace($match, $content, $stylesheet); - } - unset($content); - } - - $stylesheet = str_replace('./', 'styles/' . $this->theme['theme_path'] . '/theme/', $stylesheet); - - $sql_ary = array( - 'theme_data' => $stylesheet, - 'theme_mtime' => time(), - 'theme_storedb' => 1 - ); - - $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' - SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE theme_id = ' . $this->theme['theme_id']; - $db->sql_query($sql); - - unset($sql_ary); - } - $template->set_template(); - $this->img_lang = (file_exists($phpbb_root_path . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : $config['default_lang']; - - // Same query in style.php - $sql = 'SELECT * - FROM ' . STYLES_IMAGESET_DATA_TABLE . ' - WHERE imageset_id = ' . $this->theme['imageset_id'] . " - AND image_filename <> '' - AND image_lang IN ('" . $db->sql_escape($this->img_lang) . "', '')"; - $result = $db->sql_query($sql, 3600); - - $localised_images = false; - while ($row = $db->sql_fetchrow($result)) - { - if ($row['image_lang']) - { - $localised_images = true; - } - - $row['image_filename'] = rawurlencode($row['image_filename']); - $this->img_array[$row['image_name']] = $row; - } - $db->sql_freeresult($result); - - // there were no localised images, try to refresh the localised imageset for the user's language - if (!$localised_images) - { - // Attention: this code ignores the image definition list from acp_styles and just takes everything - // that the config file contains - $sql_ary = array(); - - $db->sql_transaction('begin'); - - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' - WHERE imageset_id = ' . $this->theme['imageset_id'] . ' - AND image_lang = \'' . $db->sql_escape($this->img_lang) . '\''; - $result = $db->sql_query($sql); - - if (@file_exists("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg")) - { - $cfg_data_imageset_data = parse_cfg_file("{$phpbb_root_path}styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg"); - foreach ($cfg_data_imageset_data as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - $sql_ary[] = array( - 'image_name' => (string) $image_name, - 'image_filename' => (string) $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $this->theme['imageset_id'], - 'image_lang' => (string) $this->img_lang, - ); - } - } - } - - if (sizeof($sql_ary)) - { - $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); - $db->sql_transaction('commit'); - $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); - - add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang); - } - else - { - $db->sql_transaction('commit'); - add_log('admin', 'LOG_IMAGESET_LANG_MISSING', $this->theme['imageset_name'], $this->img_lang); - } - } + $this->img_lang = $this->lang_name; // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes... // After calling it we continue script execution... @@ -2282,89 +2147,11 @@ class user extends session /** * Specify/Get image - * $suffix is no longer used - we know it. ;) It is there for backward compatibility. */ - function img($img, $alt = '', $width = false, $suffix = '', $type = 'full_tag') + function img($img, $alt = '') { - static $imgs; - global $phpbb_root_path; - - $img_data = &$imgs[$img]; - - if (empty($img_data)) - { - if (!isset($this->img_array[$img])) - { - // Do not fill the image to let designers decide what to do if the image is empty - $img_data = ''; - return $img_data; - } - - // Use URL if told so - $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; - - $path = 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename']; - - $img_data['src'] = $root_path . $path; - $img_data['width'] = $this->img_array[$img]['image_width']; - $img_data['height'] = $this->img_array[$img]['image_height']; - - // We overwrite the width and height to the phpbb logo's width - // and height here if the contents of the site_logo file are - // really equal to the phpbb_logo - // This allows us to change the dimensions of the phpbb_logo without - // modifying the imageset.cfg and causing a conflict for everyone - // who modified it for their custom logo on updating - if ($img == 'site_logo' && file_exists($phpbb_root_path . $path)) - { - global $cache; - - $img_file_hashes = $cache->get('imageset_site_logo_md5'); - - if ($img_file_hashes === false) - { - $img_file_hashes = array(); - } - - $key = $this->theme['imageset_path'] . '::' . $this->img_array[$img]['image_lang']; - if (!isset($img_file_hashes[$key])) - { - $img_file_hashes[$key] = md5(file_get_contents($phpbb_root_path . $path)); - $cache->put('imageset_site_logo_md5', $img_file_hashes); - } - - $phpbb_logo_hash = '0c461a32cd3621643105f0d02a772c10'; - - if ($phpbb_logo_hash == $img_file_hashes[$key]) - { - $img_data['width'] = '149'; - $img_data['height'] = '52'; - } - } - } - $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt; - - switch ($type) - { - case 'src': - return $img_data['src']; - break; - - case 'width': - return ($width === false) ? $img_data['width'] : $width; - break; - - case 'height': - return $img_data['height']; - break; - - default: - $use_width = ($width === false) ? $img_data['width'] : $width; - - return '<img src="' . $img_data['src'] . '"' . (($use_width) ? ' width="' . $use_width . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />'; - break; - } + return '<span class="imageset ' . $img . '">' . $alt . '</span>'; } /** @@ -2441,4 +2228,37 @@ class user extends session return true; } + + /** + * Returns all password protected forum ids the user is currently NOT authenticated for. + * + * @return array Array of forum ids + * @access public + */ + function get_passworded_forums() + { + global $db; + + $sql = 'SELECT f.forum_id, fa.user_id + FROM ' . FORUMS_TABLE . ' f + LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa + ON (fa.forum_id = f.forum_id + AND fa.session_id = '" . $db->sql_escape($this->session_id) . "') + WHERE f.forum_password <> ''"; + $result = $db->sql_query($sql); + + $forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = (int) $row['forum_id']; + + if ($row['user_id'] != $this->data['user_id']) + { + $forum_ids[$forum_id] = $forum_id; + } + } + $db->sql_freeresult($result); + + return $forum_ids; + } } diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php deleted file mode 100644 index 5192c334d8..0000000000 --- a/phpBB/includes/template.php +++ /dev/null @@ -1,690 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Base Template class. -* @package phpBB3 -*/ -class template -{ - /** variable that holds all the data we'll be substituting into - * the compiled templates. Takes form: - * --> $this->_tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value - * if it's a root-level variable, it'll be like this: - * --> $this->_tpldata[.][0][varname] == value - */ - var $_tpldata = array('.' => array(0 => array())); - var $_rootref; - - // Root dir and hash of filenames for each template handle. - var $root = ''; - var $cachepath = ''; - var $files = array(); - var $filename = array(); - var $files_inherit = array(); - var $files_template = array(); - var $inherit_root = ''; - var $orig_tpl_storedb; - var $orig_tpl_inherits_id; - - // this will hash handle names to the compiled/uncompiled code for that handle. - var $compiled_code = array(); - - /** - * Set template location - * @access public - */ - function set_template() - { - global $phpbb_root_path, $user; - - if (file_exists($phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template')) - { - $this->root = $phpbb_root_path . 'styles/' . $user->theme['template_path'] . '/template'; - $this->cachepath = $phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $user->theme['template_path']) . '_'; - - if ($this->orig_tpl_storedb === null) - { - $this->orig_tpl_storedb = $user->theme['template_storedb']; - } - - if ($this->orig_tpl_inherits_id === null) - { - $this->orig_tpl_inherits_id = $user->theme['template_inherits_id']; - } - - $user->theme['template_storedb'] = $this->orig_tpl_storedb; - $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id; - - if ($user->theme['template_inherits_id']) - { - $this->inherit_root = $phpbb_root_path . 'styles/' . $user->theme['template_inherit_path'] . '/template'; - } - } - else - { - trigger_error('Template path could not be found: styles/' . $user->theme['template_path'] . '/template', E_USER_ERROR); - } - - $this->_rootref = &$this->_tpldata['.'][0]; - - return true; - } - - /** - * Set custom template location (able to use directory outside of phpBB) - * @access public - */ - function set_custom_template($template_path, $template_name, $fallback_template_path = false) - { - global $phpbb_root_path, $user; - - // Make sure $template_path has no ending slash - if (substr($template_path, -1) == '/') - { - $template_path = substr($template_path, 0, -1); - } - - $this->root = $template_path; - $this->cachepath = $phpbb_root_path . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_'; - - if ($fallback_template_path !== false) - { - if (substr($fallback_template_path, -1) == '/') - { - $fallback_template_path = substr($fallback_template_path, 0, -1); - } - - $this->inherit_root = $fallback_template_path; - $this->orig_tpl_inherits_id = true; - } - else - { - $this->orig_tpl_inherits_id = false; - } - - // the database does not store the path or name of a custom template - // so there is no way we can properly store custom templates there - $this->orig_tpl_storedb = false; - - $this->_rootref = &$this->_tpldata['.'][0]; - - return true; - } - - /** - * Sets the template filenames for handles. $filename_array - * should be a hash of handle => filename pairs. - * @access public - */ - function set_filenames($filename_array) - { - if (!is_array($filename_array)) - { - return false; - } - foreach ($filename_array as $handle => $filename) - { - if (empty($filename)) - { - trigger_error("template->set_filenames: Empty filename specified for $handle", E_USER_ERROR); - } - - $this->filename[$handle] = $filename; - $this->files[$handle] = $this->root . '/' . $filename; - - if ($this->inherit_root) - { - $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; - } - } - - return true; - } - - /** - * Destroy template data set - * @access public - */ - function destroy() - { - $this->_tpldata = array('.' => array(0 => array())); - $this->_rootref = &$this->_tpldata['.'][0]; - } - - /** - * Reset/empty complete block - * @access public - */ - function destroy_block_vars($blockname) - { - if (strpos($blockname, '.') !== false) - { - // 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]; - } - - unset($str[$blocks[$blockcount]]); - } - else - { - // Top-level block. - unset($this->_tpldata[$blockname]); - } - - return true; - } - - /** - * Display handle - * @access public - */ - function display($handle, $include_once = true) - { - global $user, $phpbb_hook; - - if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, __FUNCTION__), $handle, $include_once, $this)) - { - if ($phpbb_hook->hook_return(array(__CLASS__, __FUNCTION__))) - { - return $phpbb_hook->hook_return_result(array(__CLASS__, __FUNCTION__)); - } - } - - if (defined('IN_ERROR_HANDLER')) - { - if ((E_NOTICE & error_reporting()) == E_NOTICE) - { - error_reporting(error_reporting() ^ E_NOTICE); - } - } - - if ($filename = $this->_tpl_load($handle)) - { - ($include_once) ? include_once($filename) : include($filename); - } - else - { - eval(' ?>' . $this->compiled_code[$handle] . '<?php '); - } - - return true; - } - - /** - * Display the handle and assign the output to a template variable or return the compiled result. - * @access public - */ - function assign_display($handle, $template_var = '', $return_content = true, $include_once = false) - { - ob_start(); - $this->display($handle, $include_once); - $contents = ob_get_clean(); - - if ($return_content) - { - return $contents; - } - - $this->assign_var($template_var, $contents); - - return true; - } - - /** - * Load a compiled template if possible, if not, recompile it - * @access private - */ - function _tpl_load(&$handle) - { - global $user, $phpEx, $config; - - if (!isset($this->filename[$handle])) - { - trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR); - } - - // reload these settings to have the values they had when this object was initialised - // using set_template or set_custom_template, they might otherwise have been overwritten - // by other template class instances in between. - $user->theme['template_storedb'] = $this->orig_tpl_storedb; - $user->theme['template_inherits_id'] = $this->orig_tpl_inherits_id; - - $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . $phpEx; - $this->files_template[$handle] = (isset($user->theme['template_id'])) ? $user->theme['template_id'] : 0; - - $recompile = false; - if (!file_exists($filename) || @filesize($filename) === 0 || defined('DEBUG_EXTRA')) - { - $recompile = true; - } - else if ($config['load_tplcompile']) - { - // No way around it: we need to check inheritance here - if ($user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) - { - $this->files[$handle] = $this->files_inherit[$handle]; - $this->files_template[$handle] = $user->theme['template_inherits_id']; - } - $recompile = (@filemtime($filename) < filemtime($this->files[$handle])) ? true : false; - } - - // Recompile page if the original template is newer, otherwise load the compiled version - if (!$recompile) - { - return $filename; - } - - global $db, $phpbb_root_path; - - if (!class_exists('template_compile')) - { - include($phpbb_root_path . 'includes/functions_template.' . $phpEx); - } - - // Inheritance - we point to another template file for this one. Equality is also used for store_db - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($this->files[$handle])) - { - $this->files[$handle] = $this->files_inherit[$handle]; - $this->files_template[$handle] = $user->theme['template_inherits_id']; - } - - $compile = new template_compile($this); - - // If we don't have a file assigned to this handle, die. - if (!isset($this->files[$handle])) - { - trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR); - } - - // Just compile if no user object is present (happens within the installer) - if (!$user) - { - $compile->_tpl_load_file($handle); - return false; - } - - if (isset($user->theme['template_storedb']) && $user->theme['template_storedb']) - { - $rows = array(); - $ids = array(); - // Inheritance - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) - { - $ids[] = $user->theme['template_inherits_id']; - } - $ids[] = $user->theme['template_id']; - - foreach ($ids as $id) - { - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_DATA_TABLE . ' - WHERE template_id = ' . $id . " - AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "' - OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')'; - - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $rows[$row['template_filename']] = $row; - } - $db->sql_freeresult($result); - } - - if (sizeof($rows)) - { - foreach ($rows as $row) - { - $file = $this->root . '/' . $row['template_filename']; - $force_reload = false; - if ($row['template_id'] != $user->theme['template_id']) - { - // make sure that we are not overlooking a file not in the db yet - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) - { - $file = $this->inherit_root . '/' . $row['template_filename']; - $this->files[$row['template_filename']] = $file; - $this->files_inherit[$row['template_filename']] = $file; - $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; - } - else if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id']) - { - // Ok, we have a situation. There is a file in the subtemplate, but nothing in the DB. We have to fix that. - $force_reload = true; - $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; - } - } - else - { - $this->files_template[$row['template_filename']] = $user->theme['template_id']; - } - - if ($force_reload || $row['template_mtime'] < filemtime($file)) - { - if ($row['template_filename'] == $this->filename[$handle]) - { - $compile->_tpl_load_file($handle, true); - } - else - { - $this->files[$row['template_filename']] = $file; - $this->filename[$row['template_filename']] = $row['template_filename']; - $compile->_tpl_load_file($row['template_filename'], true); - unset($this->compiled_code[$row['template_filename']]); - unset($this->files[$row['template_filename']]); - unset($this->filename[$row['template_filename']]); - } - } - - if ($row['template_filename'] == $this->filename[$handle]) - { - $this->compiled_code[$handle] = $compile->compile(trim($row['template_data'])); - $compile->compile_write($handle, $this->compiled_code[$handle]); - } - else - { - // Only bother compiling if it doesn't already exist - if (!file_exists($this->cachepath . str_replace('/', '.', $row['template_filename']) . '.' . $phpEx)) - { - $this->filename[$row['template_filename']] = $row['template_filename']; - $compile->compile_write($row['template_filename'], $compile->compile(trim($row['template_data']))); - unset($this->filename[$row['template_filename']]); - } - } - } - } - else - { - $file = $this->root . '/' . $row['template_filename']; - - if (isset($user->theme['template_inherits_id']) && $user->theme['template_inherits_id'] && !file_exists($file)) - { - $file = $this->inherit_root . '/' . $row['template_filename']; - $this->files[$row['template_filename']] = $file; - $this->files_inherit[$row['template_filename']] = $file; - $this->files_template[$row['template_filename']] = $user->theme['template_inherits_id']; - } - // Try to load from filesystem and instruct to insert into the styles table... - $compile->_tpl_load_file($handle, true); - return false; - } - - return false; - } - - $compile->_tpl_load_file($handle); - return false; - } - - /** - * Assign key variable pairs from an array - * @access public - */ - function assign_vars($vararray) - { - foreach ($vararray as $key => $val) - { - $this->_rootref[$key] = $val; - } - - return true; - } - - /** - * Assign a single variable to a single key - * @access public - */ - function assign_var($varname, $varval) - { - $this->_rootref[$varname] = $varval; - - return true; - } - - /** - * Assign key variable pairs from an array to a specified block - * @access public - */ - function assign_block_vars($blockname, $vararray) - { - if (strpos($blockname, '.') !== false) - { - // 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]; - } - - $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0; - $vararray['S_ROW_COUNT'] = $s_row_count; - - // Assign S_FIRST_ROW - if (!$s_row_count) - { - $vararray['S_FIRST_ROW'] = true; - } - - // Now the tricky part, we always assign S_LAST_ROW and remove the entry before - // This is much more clever than going through the complete template data on display (phew) - $vararray['S_LAST_ROW'] = true; - if ($s_row_count > 0) - { - unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']); - } - - // 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. - $s_row_count = (isset($this->_tpldata[$blockname])) ? sizeof($this->_tpldata[$blockname]) : 0; - $vararray['S_ROW_COUNT'] = $s_row_count; - - // Assign S_FIRST_ROW - if (!$s_row_count) - { - $vararray['S_FIRST_ROW'] = true; - } - - // We always assign S_LAST_ROW and remove the entry before - $vararray['S_LAST_ROW'] = true; - if ($s_row_count > 0) - { - unset($this->_tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); - } - - // Add a new iteration to this block with the variable assignments we were given. - $this->_tpldata[$blockname][] = $vararray; - } - - return true; - } - - /** - * Change already assigned key variable pair (one-dimensional - single loop entry) - * - * An example of how to use this function: - * {@example alter_block_array.php} - * - * @param string $blockname the blockname, for example 'loop' - * @param array $vararray the var array to insert/add or merge - * @param mixed $key Key to search for - * - * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] - * - * int: Position [the position to change or insert at directly given] - * - * If key is false the position is set to 0 - * If key is true the position is set to the last entry - * - * @param string $mode Mode to execute (valid modes are 'insert' and 'change') - * - * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). - * - * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) - * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) - * - * @return bool false on error, true on success - * @access public - */ - function alter_block_array($blockname, $vararray, $key = false, $mode = 'insert') - { - if (strpos($blockname, '.') !== false) - { - // Nested blocks are not supported - return false; - } - - // Change key to zero (change first position) if false and to last position if true - if ($key === false || $key === true) - { - $key = ($key === false) ? 0 : sizeof($this->_tpldata[$blockname]); - } - - // Get correct position if array given - if (is_array($key)) - { - // Search array to get correct position - list($search_key, $search_value) = @each($key); - - $key = NULL; - foreach ($this->_tpldata[$blockname] as $i => $val_ary) - { - if ($val_ary[$search_key] === $search_value) - { - $key = $i; - break; - } - } - - // key/value pair not found - if ($key === NULL) - { - return false; - } - } - - // Insert Block - if ($mode == 'insert') - { - // Make sure we are not exceeding the last iteration - if ($key >= sizeof($this->_tpldata[$blockname])) - { - $key = sizeof($this->_tpldata[$blockname]); - unset($this->_tpldata[$blockname][($key - 1)]['S_LAST_ROW']); - $vararray['S_LAST_ROW'] = true; - } - else if ($key === 0) - { - unset($this->_tpldata[$blockname][0]['S_FIRST_ROW']); - $vararray['S_FIRST_ROW'] = true; - } - - // Re-position template blocks - for ($i = sizeof($this->_tpldata[$blockname]); $i > $key; $i--) - { - $this->_tpldata[$blockname][$i] = $this->_tpldata[$blockname][$i-1]; - $this->_tpldata[$blockname][$i]['S_ROW_COUNT'] = $i; - } - - // Insert vararray at given position - $vararray['S_ROW_COUNT'] = $key; - $this->_tpldata[$blockname][$key] = $vararray; - - return true; - } - - // Which block to change? - if ($mode == 'change') - { - if ($key == sizeof($this->_tpldata[$blockname])) - { - $key--; - } - - $this->_tpldata[$blockname][$key] = array_merge($this->_tpldata[$blockname][$key], $vararray); - return true; - } - - return false; - } - - /** - * Include a separate template - * @access private - */ - function _tpl_include($filename, $include = true) - { - $handle = $filename; - $this->filename[$handle] = $filename; - $this->files[$handle] = $this->root . '/' . $filename; - if ($this->inherit_root) - { - $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; - } - - $filename = $this->_tpl_load($handle); - - if ($include) - { - global $user; - - if ($filename) - { - include($filename); - return; - } - eval(' ?>' . $this->compiled_code[$handle] . '<?php '); - } - } - - /** - * Include a php-file - * @access private - */ - function _php_include($filename) - { - global $phpbb_root_path; - - $file = $phpbb_root_path . $filename; - - if (!file_exists($file)) - { - // trigger_error cannot be used here, as the output already started - echo 'template->_php_include(): File ' . htmlspecialchars($file) . ' does not exist or is empty'; - return; - } - include($file); - } -} diff --git a/phpBB/includes/template/compile.php b/phpBB/includes/template/compile.php new file mode 100644 index 0000000000..8d8560ded5 --- /dev/null +++ b/phpBB/includes/template/compile.php @@ -0,0 +1,122 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +stream_filter_register('phpbb_template', 'phpbb_template_filter'); + +/** +* Extension of template class - Functions needed for compiling templates only. +* +* @package phpBB3 +* @uses template_filter As a PHP stream filter to perform compilation of templates +*/ +class phpbb_template_compile +{ + /** + * Whether <!-- PHP --> tags are allowed + * + * @var bool + */ + private $allow_php; + + /** + * Constructor. + * + * @param bool @allow_php Whether PHP code will be allowed in templates (inline PHP code, PHP tag and INCLUDEPHP tag) + */ + public function __construct($allow_php) + { + $this->allow_php = $allow_php; + } + + /** + * Compiles template in $source_file and writes compiled template to + * cache directory + * + * @param string $handle Template handle to compile + * @param string $source_file Source template file + * @return bool Return true on success otherwise false + */ + public function compile_file_to_file($source_file, $compiled_file) + { + $source_handle = @fopen($source_file, 'rb'); + $destination_handle = @fopen($compiled_file, 'wb'); + + if (!$source_handle || !$destination_handle) + { + return false; + } + + @flock($destination_handle, LOCK_EX); + + $this->compile_stream_to_stream($source_handle, $destination_handle); + + @fclose($source_handle); + @flock($destination_handle, LOCK_UN); + @fclose($destination_handle); + + phpbb_chmod($compiled_file, CHMOD_READ | CHMOD_WRITE); + + clearstatcache(); + + return true; + } + + /** + * Compiles a template located at $source_file. + * + * Returns PHP source suitable for eval(). + * + * @param string $source_file Source template file + * @return string|bool Return compiled code on successful compilation otherwise false + */ + public function compile_file($source_file) + { + $source_handle = @fopen($source_file, 'rb'); + $destination_handle = @fopen('php://temp' ,'r+b'); + + if (!$source_handle || !$destination_handle) + { + return false; + } + + $this->compile_stream_to_stream($source_handle, $destination_handle); + + @fclose($source_handle); + + rewind($destination_handle); + $contents = stream_get_contents($destination_handle); + @fclose($dest_handle); + + return $contents; + } + + /** + * Compiles contents of $source_stream into $dest_stream. + * + * A stream filter is appended to $source_stream as part of the + * process. + * + * @param resource $source_stream Source stream + * @param resource $dest_stream Destination stream + * @return void + */ + private function compile_stream_to_stream($source_stream, $dest_stream) + { + stream_filter_append($source_stream, 'phpbb_template', null, array('allow_php' => $this->allow_php)); + stream_copy_to_stream($source_stream, $dest_stream); + } +} diff --git a/phpBB/includes/template/context.php b/phpBB/includes/template/context.php new file mode 100644 index 0000000000..f85f86a0ec --- /dev/null +++ b/phpBB/includes/template/context.php @@ -0,0 +1,342 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Stores variables assigned to template. +* +* @package phpBB3 +*/ +class phpbb_template_context +{ + /** + * variable that holds all the data we'll be substituting into + * the compiled templates. Takes form: + * --> $this->tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value + * if it's a root-level variable, it'll be like this: + * --> $this->tpldata[.][0][varname] == value + * + * @var array + */ + private $tpldata = array('.' => array(0 => array())); + + /** + * @var array Reference to template->tpldata['.'][0] + */ + private $rootref; + + public function __construct() + { + $this->clear(); + } + + /** + * Clears template data set. + */ + public function clear() + { + $this->tpldata = array('.' => array(0 => array())); + $this->rootref = &$this->tpldata['.'][0]; + } + + /** + * Assign a single variable to a single key + * + * @param string $varname Variable name + * @param string $varval Value to assign to variable + */ + public function assign_var($varname, $varval) + { + $this->rootref[$varname] = $varval; + + return true; + } + + /** + * Returns a reference to template data array. + * + * This function is public so that template renderer may invoke it. + * Users should alter template variables via functions in phpbb_template. + * + * Note: modifying returned array will affect data stored in the context. + * + * @return array template data + */ + public function &get_data_ref() + { + // returning a reference directly is not + // something php is capable of doing + $ref = &$this->tpldata; + return $ref; + } + + /** + * Returns a reference to template root scope. + * + * This function is public so that template renderer may invoke it. + * Users should not need to invoke this function. + * + * Note: modifying returned array will affect data stored in the context. + * + * @return array template data + */ + public function &get_root_ref() + { + // rootref is already a reference + return $this->rootref; + } + + /** + * Assign key variable pairs from an array to a specified block + * + * @param string $blockname Name of block to assign $vararray to + * @param array $vararray A hash of variable name => value pairs + */ + public function assign_block_vars($blockname, array $vararray) + { + if (strpos($blockname, '.') !== false) + { + // 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]; + } + + $s_row_count = isset($str[$blocks[$blockcount]]) ? sizeof($str[$blocks[$blockcount]]) : 0; + $vararray['S_ROW_COUNT'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // Now the tricky part, we always assign S_LAST_ROW and remove the entry before + // This is much more clever than going through the complete template data on display (phew) + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($str[$blocks[$blockcount]][($s_row_count - 1)]['S_LAST_ROW']); + } + + // 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. + $s_row_count = (isset($this->tpldata[$blockname])) ? sizeof($this->tpldata[$blockname]) : 0; + $vararray['S_ROW_COUNT'] = $s_row_count; + + // Assign S_FIRST_ROW + if (!$s_row_count) + { + $vararray['S_FIRST_ROW'] = true; + } + + // We always assign S_LAST_ROW and remove the entry before + $vararray['S_LAST_ROW'] = true; + if ($s_row_count > 0) + { + unset($this->tpldata[$blockname][($s_row_count - 1)]['S_LAST_ROW']); + } + + // Add a new iteration to this block with the variable assignments we were given. + $this->tpldata[$blockname][] = $vararray; + } + + return true; + } + + /** + * Change already assigned key variable pair (one-dimensional - single loop entry) + * + * An example of how to use this function: + * {@example alter_block_array.php} + * + * @param string $blockname the blockname, for example 'loop' + * @param array $vararray the var array to insert/add or merge + * @param mixed $key Key to search for + * + * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] + * + * int: Position [the position to change or insert at directly given] + * + * If key is false the position is set to 0 + * If key is true the position is set to the last entry + * + * @param string $mode Mode to execute (valid modes are 'insert' and 'change') + * + * If insert, the vararray is inserted at the given position (position counting from zero). + * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * + * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) + * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) + * + * @return bool false on error, true on success + */ + public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') + { + if (strpos($blockname, '.') !== false) + { + // Nested block. + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $block = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) + { + if (($pos = strpos($blocks[$i], '[')) !== false) + { + $name = substr($blocks[$i], 0, $pos); + + if (strpos($blocks[$i], '[]') === $pos) + { + $index = sizeof($block[$name]) - 1; + } + else + { + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); + } + } + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = &$block[$name]; + $block = &$block[$index]; + } + + $block = &$block[$blocks[$i]]; // Traverse the last block + } + else + { + // Top-level block. + $block = &$this->tpldata[$blockname]; + } + + // Change key to zero (change first position) if false and to last position if true + if ($key === false || $key === true) + { + $key = ($key === false) ? 0 : sizeof($block); + } + + // Get correct position if array given + if (is_array($key)) + { + // Search array to get correct position + list($search_key, $search_value) = @each($key); + + $key = NULL; + foreach ($block as $i => $val_ary) + { + if ($val_ary[$search_key] === $search_value) + { + $key = $i; + break; + } + } + + // key/value pair not found + if ($key === NULL) + { + return false; + } + } + + // Insert Block + if ($mode == 'insert') + { + // Make sure we are not exceeding the last iteration + if ($key >= sizeof($this->tpldata[$blockname])) + { + $key = sizeof($this->tpldata[$blockname]); + unset($this->tpldata[$blockname][($key - 1)]['S_LAST_ROW']); + $vararray['S_LAST_ROW'] = true; + } + else if ($key === 0) + { + unset($this->tpldata[$blockname][0]['S_FIRST_ROW']); + $vararray['S_FIRST_ROW'] = true; + } + + // Re-position template blocks + for ($i = sizeof($block); $i > $key; $i--) + { + $block[$i] = $block[$i-1]; + } + + // Insert vararray at given position + $block[$key] = $vararray; + + return true; + } + + // Which block to change? + if ($mode == 'change') + { + if ($key == sizeof($block)) + { + $key--; + } + + $block[$key] = array_merge($block[$key], $vararray); + + return true; + } + + return false; + } + + /** + * Reset/empty complete block + * + * @param string $blockname Name of block to destroy + */ + public function destroy_block_vars($blockname) + { + if (strpos($blockname, '.') !== false) + { + // 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]; + } + + unset($str[$blocks[$blockcount]]); + } + else + { + // Top-level block. + unset($this->tpldata[$blockname]); + } + + return true; + } +} diff --git a/phpBB/includes/template/filter.php b/phpBB/includes/template/filter.php new file mode 100644 index 0000000000..115fe21e35 --- /dev/null +++ b/phpBB/includes/template/filter.php @@ -0,0 +1,971 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group, sections (c) 2001 ispi of Lincoln Inc +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The template filter that does the actual compilation +* +* psoTFX, phpBB Development Team - Completion of file caching, decompilation +* routines and implementation of conditionals/keywords and associated changes +* +* The interface was inspired by PHPLib templates, and the template file (formats are +* quite similar) +* +* The keyword/conditional implementation is currently based on sections of code from +* the Smarty templating engine (c) 2001 ispi of Lincoln, Inc. which is released +* (on its own and in whole) under the LGPL. Section 3 of the LGPL states that any code +* derived from an LGPL application may be relicenced under the GPL, this applies +* to this source +* +* DEFINE directive inspired by a request by Cyberalien +* +* @see template_compile +* @package phpBB3 +*/ +class phpbb_template_filter extends php_user_filter +{ + const REGEX_NS = '[a-z_][a-z_0-9]+'; + + const REGEX_VAR = '[A-Z_][A-Z_0-9]+'; + const REGEX_VAR_SUFFIX = '[A-Z_0-9]+'; + + const REGEX_TAG = '<!-- ([A-Z][A-Z_0-9]+)(?: (.*?) ?)?-->'; + + const REGEX_TOKENS = '~<!-- ([A-Z][A-Z_0-9]+)(?: (.*?) ?)?-->|{((?:[a-z_][a-z_0-9]+\.)*\\$?[A-Z][A-Z_0-9]+)}~'; + + /** + * @var array + */ + private $block_names = array(); + + /** + * @var array + */ + private $block_else_level = array(); + + /** + * @var string + */ + private $chunk; + + /** + * @var bool + */ + private $in_php; + + /** + * Whether inline PHP code, <!-- PHP --> and <!-- INCLUDEPHP --> tags + * are allowed. If this is false all PHP code will be silently + * removed from the template during compilation. + * + * @var bool + */ + private $allow_php; + + /** + * Stream filter + * + * Is invoked for evey chunk of the stream, allowing us + * to work on a chunk at a time, which saves memory. + */ + public function filter($in, $out, &$consumed, $closing) + { + $written = false; + $first = false; + + while ($bucket = stream_bucket_make_writeable($in)) + { + $consumed += $bucket->datalen; + + $data = $this->chunk . $bucket->data; + $last_nl = strrpos($data, "\n"); + $this->chunk = substr($data, $last_nl); + $data = substr($data, 0, $last_nl); + + if (!strlen($data)) + { + continue; + } + + $written = true; + + $data = $this->compile($data); + if (!$first) + { + $data = $this->prepend_preamble($data); + $first = false; + } + $bucket->data = $data; + $bucket->datalen = strlen($bucket->data); + stream_bucket_append($out, $bucket); + } + + if ($closing && strlen($this->chunk)) + { + $written = true; + $bucket = stream_bucket_new($this->stream, $this->compile($this->chunk)); + stream_bucket_append($out, $bucket); + } + + return $written ? PSFS_PASS_ON : PSFS_FEED_ME; + } + + /** + * Initializer, called on creation. + * + * Get the allow_php option from params, which is passed + * to stream_filter_append. + */ + public function onCreate() + { + $this->chunk = ''; + $this->in_php = false; + $this->allow_php = $this->params['allow_php']; + return true; + } + + /** + * Compiles a chunk of template. + * + * The chunk must comprise of one or more complete lines from the source + * template. + * + * @param string $data Chunk of source template to compile + * @return string Compiled PHP/HTML code + */ + private function compile($data) + { + $block_start_in_php = $this->in_php; + + $data = preg_replace('#<(?:[\\?%]|script)#s', '<?php echo\'\\0\';?>', $data); + $data = preg_replace_callback(self::REGEX_TOKENS, array($this, 'replace'), $data); + + // Remove php + if (!$this->allow_php) + { + if ($block_start_in_php + && $this->in_php + && strpos($data, '<!-- PHP -->') === false + && strpos($data, '<!-- ENDPHP -->') === false) + { + // This is just php code + return ''; + } + $data = preg_replace('~^.*?<!-- ENDPHP -->~', '', $data); + $data = preg_replace('~<!-- PHP -->.*?<!-- ENDPHP -->~', '', $data); + $data = preg_replace('~<!-- ENDPHP -->.*?$~', '', $data); + } + + /* + Preserve whitespace. + PHP removes a newline after the closing tag (if it's there). This is by design. + + + Consider the following template: + + <!-- IF condition --> + some content + <!-- ENDIF --> + + If we were to simply preserve all whitespace, we could simply replace all "?>" tags + with "?>\n". + Doing that, would add additional newlines to the compiled tempalte in place of the + IF and ENDIF statements. These newlines are unwanted (and one is conditional). + The IF and ENDIF are usually on their own line for ease of reading. + + This replacement preserves newlines only for statements that aren't the only statement on a line. + It will NOT preserve newlines at the end of statements in the above examle. + It will preserve newlines in situations like: + + <!-- IF condition -->inline content<!-- ENDIF --> + + + */ + + $data = preg_replace('~(?<!^)(<\?php(?:(?<!\?>).)+(?<!/\*\*/)\?>)$~m', "$1\n", $data); + $data = str_replace('/**/?>', "?>\n", $data); + $data = str_replace('?><?php', '', $data); + return $data; + } + + /** + * Prepends a preamble to compiled template. + * Currently preamble checks if IN_PHPBB is defined and calls exit() if it is not. + * + * @param string $data Compiled template chunk + * @return string Compiled template chunk with preamble prepended + */ + private function prepend_preamble($data) + { + $data = "<?php if (!defined('IN_PHPBB')) exit;" . ((strncmp($data, '<?php', 5) === 0) ? substr($data, 5) : ' ?>' . $data); + return $data; + } + + /** + * Callback for replacing matched tokens with PHP code + * + * @param array $matches Regular expression matches + * @return string compiled template code + */ + private function replace($matches) + { + if ($this->in_php && $matches[1] != 'ENDPHP') + { + return ''; + } + + if (isset($matches[3])) + { + return $this->compile_var_tags($matches[0]); + } + + switch ($matches[1]) + { + case 'BEGIN': + $this->block_else_level[] = false; + return '<?php ' . $this->compile_tag_block($matches[2]) . ' ?>'; + break; + + case 'BEGINELSE': + $this->block_else_level[sizeof($this->block_else_level) - 1] = true; + return '<?php }} else { ?>'; + break; + + case 'END': + array_pop($this->block_names); + return '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>'; + break; + + case 'IF': + return '<?php ' . $this->compile_tag_if($matches[2], false) . ' ?>'; + break; + + case 'ELSE': + return '<?php } else { ?>'; + break; + + case 'ELSEIF': + return '<?php ' . $this->compile_tag_if($matches[2], true) . ' ?>'; + break; + + case 'ENDIF': + return '<?php } ?>'; + break; + + case 'DEFINE': + return '<?php ' . $this->compile_tag_define($matches[2], true) . ' ?>'; + break; + + case 'UNDEFINE': + return '<?php ' . $this->compile_tag_define($matches[2], false) . ' ?>'; + break; + + case 'INCLUDE': + return '<?php ' . $this->compile_tag_include($matches[2]) . ' ?>'; + break; + + case 'INCLUDEPHP': + return ($this->allow_php) ? '<?php ' . $this->compile_tag_include_php($matches[2]) . ' ?>' : ''; + break; + + case 'PHP': + if ($this->allow_php) + { + $this->in_php = true; + return '<?php '; + } + return '<!-- PHP -->'; + break; + + case 'ENDPHP': + if ($this->allow_php) + { + $this->in_php = false; + return ' ?>'; + } + return '<!-- ENDPHP -->'; + break; + + default: + return $matches[0]; + break; + + } + return ''; + } + + /** + * Convert template variables into PHP varrefs + * + * @param string $text_blocks Variable reference in source template + * @param bool $is_expr Returns whether the source was an expression type variable (i.e. S_FIRST_ROW) + * @return string PHP variable name + */ + private function get_varref($text_blocks, &$is_expr) + { + // change template varrefs into PHP varrefs + $varrefs = array(); + + // This one will handle varrefs WITH namespaces + preg_match_all('#\{((?:' . self::REGEX_NS . '\.)+)(\$)?(' . self::REGEX_VAR . ')\}#', $text_blocks, $varrefs, PREG_SET_ORDER); + + foreach ($varrefs as $var_val) + { + $namespace = $var_val[1]; + $varname = $var_val[3]; + $new = $this->generate_block_varref($namespace, $varname, $is_expr, $var_val[2]); + + $text_blocks = str_replace($var_val[0], $new, $text_blocks); + } + + // Language variables cannot be reduced to a single varref, so they must be skipped + // These two replacements would break language variables, so we can only run them on non-language types + if (strpos($text_blocks, '{L_') === false && strpos($text_blocks, '{LA_') === false) + { + // This will handle the remaining root-level varrefs + $text_blocks = preg_replace('#\{(' . self::REGEX_VAR . ')\}#', "\$_rootref['\\1']", $text_blocks); + $text_blocks = preg_replace('#\{\$(' . self::REGEX_VAR . ')\}#', "\$_tpldata['DEFINE']['.']['\\1']", $text_blocks); + } + + return $text_blocks; + } + + /** + * Compile variables + * + * @param string $text_blocks Variable reference in source template + * @return string compiled template code + */ + private function compile_var_tags(&$text_blocks) + { + $text_blocks = $this->get_varref($text_blocks, $is_expr); + $lang_replaced = $this->compile_language_tags($text_blocks); + + if(!$lang_replaced) + { + $text_blocks = '<?php echo ' . ($is_expr ? "$text_blocks" : "(isset($text_blocks)) ? $text_blocks : ''") . '; /**/?>'; + } + + return $text_blocks; + } + + /** + * Handles special language tags L_ and LA_ + * + * @param string $text_blocks Variable reference in source template + * @return bool Whether a replacement occurred or not + */ + private function compile_language_tags(&$text_blocks) + { + $replacements = 0; + + // transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array + if (strpos($text_blocks, '{L_') !== false) + { + $text_blocks = preg_replace('#\{L_(' . self::REGEX_VAR_SUFFIX . ')\}#', "<?php echo ((isset(\$_rootref['L_\\1'])) ? \$_rootref['L_\\1'] : ((isset(\$_lang['\\1'])) ? \$_lang['\\1'] : '{ \\1 }')); /**/?>", $text_blocks, -1, $replacements); + return (bool) $replacements; + } + + // Handle addslashed language variables prefixed with LA_ + // If a template variable already exist, it will be used in favor of it... + if (strpos($text_blocks, '{LA_') !== false) + { + $text_blocks = preg_replace('#\{LA_(' . self::REGEX_VAR_SUFFIX . '+)\}#', "<?php echo ((isset(\$_rootref['LA_\\1'])) ? \$_rootref['LA_\\1'] : ((isset(\$_rootref['L_\\1'])) ? addslashes(\$_rootref['L_\\1']) : ((isset(\$_lang['\\1'])) ? addslashes(\$_lang['\\1']) : '{ \\1 }'))); /**/?>", $text_blocks, -1, $replacements); + return (bool) $replacements; + } + + return false; + } + + /** + * Compile blocks + * + * @param string $tag_args Block contents in source template + * @return string compiled template code + */ + private function compile_tag_block($tag_args) + { + $no_nesting = false; + + // Is the designer wanting to call another loop in a loop? + // <!-- BEGIN loop --> + // <!-- BEGIN !loop2 --> + // <!-- END !loop2 --> + // <!-- END loop --> + // 'loop2' is actually on the same nesting level as 'loop' you assign + // variables to it with template->assign_block_vars('loop2', array(...)) + if (strpos($tag_args, '!') === 0) + { + // Count the number if ! occurrences (not allowed in vars) + $no_nesting = substr_count($tag_args, '!'); + $tag_args = substr($tag_args, $no_nesting); + } + + // Allow for control of looping (indexes start from zero): + // foo(2) : Will start the loop on the 3rd entry + // foo(-2) : Will start the loop two entries from the end + // foo(3,4) : Will start the loop on the fourth entry and end it on the fifth + // foo(3,-4) : Will start the loop on the fourth entry and end it four from last + $match = array(); + + if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#', $tag_args, $match)) + { + $tag_args = $match[1]; + + if ($match[2] < 0) + { + $loop_start = '($_' . $tag_args . '_count ' . $match[2] . ' < 0 ? 0 : $_' . $tag_args . '_count ' . $match[2] . ')'; + } + else + { + $loop_start = '($_' . $tag_args . '_count < ' . $match[2] . ' ? $_' . $tag_args . '_count : ' . $match[2] . ')'; + } + + if (!isset($match[3]) || strlen($match[3]) < 1 || $match[3] == -1) + { + $loop_end = '$_' . $tag_args . '_count'; + } + else if ($match[3] >= 0) + { + $loop_end = '(' . ($match[3] + 1) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ($match[3] + 1) . ')'; + } + else //if ($match[3] < -1) + { + $loop_end = '$_' . $tag_args . '_count' . ($match[3] + 1); + } + } + else + { + $loop_start = 0; + $loop_end = '$_' . $tag_args . '_count'; + } + + $tag_template_php = ''; + array_push($this->block_names, $tag_args); + + if ($no_nesting !== false) + { + // We need to implode $no_nesting times from the end... + $block = array_slice($this->block_names, -$no_nesting); + } + else + { + $block = $this->block_names; + } + + if (sizeof($block) < 2) + { + // Block is not nested. + $tag_template_php = '$_' . $tag_args . "_count = (isset(\$_tpldata['$tag_args'])) ? sizeof(\$_tpldata['$tag_args']) : 0;"; + $varref = "\$_tpldata['$tag_args']"; + } + else + { + // This block is nested. + // Generate a namespace string for this block. + $namespace = implode('.', $block); + + // 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. + $tag_template_php = '$_' . $tag_args . '_count = (isset(' . $varref . ')) ? sizeof(' . $varref . ') : 0;'; + } + + $tag_template_php .= 'if ($_' . $tag_args . '_count) {'; + + /** + * The following uses foreach for iteration instead of a for loop, foreach is faster but requires PHP to make a copy of the contents of the array which uses more memory + * <code> + * if (!$offset) + * { + * $tag_template_php .= 'foreach (' . $varref . ' as $_' . $tag_args . '_i => $_' . $tag_args . '_val){'; + * } + * </code> + */ + + $tag_template_php .= 'for ($_' . $tag_args . '_i = ' . $loop_start . '; $_' . $tag_args . '_i < ' . $loop_end . '; ++$_' . $tag_args . '_i){'; + $tag_template_php .= '$_' . $tag_args . '_val = &' . $varref . '[$_' . $tag_args . '_i];'; + + return $tag_template_php; + } + + /** + * Compile a general expression - much of this is from Smarty with + * some adaptions for our block level methods + * + * @param string $tag_args Expression (tag arguments) in source template + * @return string compiled template code + */ + private function compile_expression($tag_args) + { + $match = array(); + preg_match_all('/(?: + "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | + \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | + [(),] | + [^\s(),]+)/x', $tag_args, $match); + + $tokens = $match[0]; + $is_arg_stack = array(); + + for ($i = 0, $size = sizeof($tokens); $i < $size; $i++) + { + $token = &$tokens[$i]; + + switch ($token) + { + case '!==': + case '===': + case '<<': + case '>>': + case '|': + case '^': + case '&': + case '~': + case ')': + case ',': + case '+': + case '-': + case '*': + case '/': + case '@': + break; + + case '==': + case 'eq': + $token = '=='; + break; + + case '!=': + case '<>': + case 'ne': + case 'neq': + $token = '!='; + break; + + case '<': + case 'lt': + $token = '<'; + break; + + case '<=': + case 'le': + case 'lte': + $token = '<='; + break; + + case '>': + case 'gt': + $token = '>'; + break; + + case '>=': + case 'ge': + case 'gte': + $token = '>='; + break; + + case '&&': + case 'and': + $token = '&&'; + break; + + case '||': + case 'or': + $token = '||'; + break; + + case '!': + case 'not': + $token = '!'; + break; + + case '%': + 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, sizeof($tokens), $new_tokens); + + $i = $is_arg_start; + + // no break + + default: + $varrefs = array(); + if (preg_match('#^((?:' . self::REGEX_NS . '\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s', $token, $varrefs)) + { + if (!empty($varrefs[1])) + { + $namespace = substr($varrefs[1], 0, -1); + $dot_pos = strrchr($namespace, '.'); + if ($dot_pos !== false) + { + $namespace = substr($dot_pos, 1); + } + + // S_ROW_COUNT is deceptive, it returns the current row number not the number of rows + // hence S_ROW_COUNT is deprecated in favour of S_ROW_NUM + switch ($varrefs[3]) + { + case 'S_ROW_NUM': + case 'S_ROW_COUNT': + $token = "\$_${namespace}_i"; + break; + + case 'S_NUM_ROWS': + $token = "\$_${namespace}_count"; + break; + + case 'S_FIRST_ROW': + $token = "(\$_${namespace}_i == 0)"; + break; + + case 'S_LAST_ROW': + $token = "(\$_${namespace}_i == \$_${namespace}_count - 1)"; + break; + + case 'S_BLOCK_NAME': + $token = "'$namespace'"; + break; + + default: + $token = $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[2]) . '[\'' . $varrefs[3] . '\']'; + $token = '(isset(' . $token . ') ? ' . $token . ' : null)'; + break; + } + } + else + { + $token = ($varrefs[2]) ? '$_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$_rootref[\'' . $varrefs[3] . '\']'; + $token = '(isset(' . $token . ') ? ' . $token . ' : null)'; + } + + } + else if (preg_match('#^\.((?:' . self::REGEX_NS . '\.?)+)$#s', $token, $varrefs)) + { + // Allow checking if loops are set with .loopname + // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example + $blocks = explode('.', $varrefs[1]); + + // If the block is nested, we have a reference that we can grab. + // If the block is not nested, we just go and grab the block from _tpldata + if (sizeof($blocks) > 1) + { + $block = array_pop($blocks); + $namespace = implode('.', $blocks); + $varref = $this->generate_block_data_ref($namespace, true); + + // Add the block reference for the last child. + $varref .= "['" . $block . "']"; + } + else + { + $varref = '$_tpldata'; + + // Add the block reference for the last child. + $varref .= "['" . $blocks[0] . "']"; + } + $token = "(isset($varref) ? sizeof($varref) : 0)"; + } + + break; + } + } + + return $tokens; + } + + /** + * Compile IF tags + * + * @param string $tag_args Expression given with IF in source template + * @param bool $elseif True if compiling an IF tag, false if compiling an ELSEIF tag + * @return string compiled template code + */ + private function compile_tag_if($tag_args, $elseif) + { + $tokens = $this->compile_expression($tag_args); + + $tpl = ($elseif) ? '} else if (' : 'if ('; + + $tpl .= implode(' ', $tokens); + $tpl .= ') { '; + + return $tpl; + } + + /** + * Compile DEFINE tags + * + * @param string $tag_args Expression given with DEFINE in source template + * @param bool $op True if compiling a DEFINE tag, false if compiling an UNDEFINE tag + * @return string compiled template code + */ + private function compile_tag_define($tag_args, $op) + { + $match = array(); + preg_match('#^((?:' . self::REGEX_NS . '\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (.*?))?$#', $tag_args, $match); + + if (empty($match[2]) || (!isset($match[3]) && $op)) + { + return ''; + } + + if (!$op) + { + return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');'; + } + + $parsed_statement = implode(' ', $this->compile_expression($match[3])); + + return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $parsed_statement . ';'; + } + + /** + * Compile INCLUDE tag + * + * @param string $tag_args Expression given with INCLUDE in source template + * @return string compiled template code + */ + private function compile_tag_include($tag_args) + { + // Process dynamic includes + if ($tag_args[0] == '{') + { + $var = $this->get_varref($tag_args, $is_expr); + + // Make sure someone didn't try to include S_FIRST_ROW or similar + if (!$is_expr) + { + return "if (isset($var)) { \$_template->_tpl_include($var); }"; + } + } + + return "\$_template->_tpl_include('$tag_args');"; + } + + /** + * Compile INCLUDE_PHP tag + * + * @param string $tag_args Expression given with INCLUDEPHP in source template + * @return string compiled template code + */ + private function compile_tag_include_php($tag_args) + { + return "\$_template->_php_include('$tag_args');"; + } + + /** + * parse expression + * This is from Smarty + */ + private 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 (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!(($is_arg / $expr_arg) & 1)"; + } + else + { + $expr = "!($is_arg & 1)"; + } + break; + + case 'odd': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "(($is_arg / $expr_arg) & 1)"; + } + else + { + $expr = "($is_arg & 1)"; + } + break; + + case 'div': + if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') + { + $expr_end++; + $expr_arg = $tokens[$expr_end++]; + $expr = "!($is_arg % $expr_arg)"; + } + break; + } + + if ($negate_expr) + { + if ($expr[0] == '!') + { + // Negated expression, de-negate it. + $expr = substr($expr, 1); + } + else + { + $expr = "!($expr)"; + } + } + + array_splice($tokens, 0, $expr_end, $expr); + + return $tokens; + } + + /** + * Generates a reference to the given variable inside the given (possibly nested) + * block namespace. This is a string of the form: + * ' . $_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. + * + * @param string $namespace Namespace to access (expects a trailing "." on the namespace) + * @param string $varname Variable name to use + * @param bool $expr Returns whether the source was an expression type + * @param bool $defop If true this is a variable created with the DEFINE construct, otherwise template variable + * @return string Code to access variable or echo it if $echo is true + */ + private function generate_block_varref($namespace, $varname, &$expr, $defop = false) + { + // Strip the trailing period. + $namespace = substr($namespace, 0, -1); + + if (($pos = strrpos($namespace, '.')) !== false) + { + $local_namespace = substr($namespace, $pos + 1); + } + else + { + $local_namespace = $namespace; + } + + $expr = true; + + // S_ROW_COUNT is deceptive, it returns the current row number now the number of rows + // hence S_ROW_COUNT is deprecated in favour of S_ROW_NUM + switch ($varname) + { + case 'S_ROW_NUM': + case 'S_ROW_COUNT': + $varref = "\$_${local_namespace}_i"; + break; + + case 'S_NUM_ROWS': + $varref = "\$_${local_namespace}_count"; + break; + + case 'S_FIRST_ROW': + $varref = "(\$_${local_namespace}_i == 0)"; + break; + + case 'S_LAST_ROW': + $varref = "(\$_${local_namespace}_i == \$_${local_namespace}_count - 1)"; + break; + + case 'S_BLOCK_NAME': + $varref = "'$local_namespace'"; + break; + + default: + // Get a reference to the data block for this namespace. + $varref = $this->generate_block_data_ref($namespace, true, $defop); + // Prepend the necessary code to stick this in an echo line. + + // Append the variable reference. + $varref .= "['$varname']"; + + $expr = false; + break; + } + // @todo Test the !$expr more + + 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: + * $_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN'] + * + * @param string $blockname Block to access (does not expect a trailing "." on the blockname) + * @param bool $include_last_iterator If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above. + * @param bool $defop If true this is a variable created with the DEFINE construct, otherwise template variable + * @return string Code to access variable + */ + private 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; + + // DEFINE is not an element of any referenced variable, we must use _tpldata to access it + if ($defop) + { + $varref = '$_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; + } + else if ($include_last_iterator) + { + return '$_'. $blocks[$blockcount] . '_val'; + } + else + { + return '$_'. $blocks[$blockcount - 1] . '_val[\''. $blocks[$blockcount]. '\']'; + } + } +} diff --git a/phpBB/includes/template/locator.php b/phpBB/includes/template/locator.php new file mode 100644 index 0000000000..35e33bb9e6 --- /dev/null +++ b/phpBB/includes/template/locator.php @@ -0,0 +1,211 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + + +/** +* Template locator. Maintains mapping from template handles to source paths. +* +* Template locator is aware of template inheritance, and can return actual +* filesystem paths (i.e., the "primary" template or the "parent" template) +* depending on what files exist. +* +* @package phpBB3 +*/ +class phpbb_template_locator +{ + /** + * @var string Path to directory that templates are stored in. + */ + private $root = ''; + + /** + * @var string Path to parent/fallback template directory. + */ + private $inherit_root = ''; + + /** + * @var array Map from handles to source template file paths. + * Normally it only contains paths for handles that are used + * (or are likely to be used) by the page being rendered and not + * all templates that exist on the filesystem. + */ + private $files = array(); + + /** + * @var array Map from handles to source template file names. + * Covers the same data as $files property but maps to basenames + * instead of paths. + */ + private $filenames = array(); + + /** + * @var array Map from handles to parent/fallback source template + * file paths. Covers the same data as $files. + */ + private $files_inherit = array(); + + /** + * Set custom template location (able to use directory outside of phpBB). + * + * Note: Templates are still compiled to phpBB's cache directory. + * + * @param string $template_path Path to template directory + * @param string|bool $fallback_template_path Path to fallback template, or false to disable fallback + */ + public function set_custom_template($template_path, $fallback_template_path = false) + { + // Make sure $template_path has no ending slash + if (substr($template_path, -1) == '/') + { + $template_path = substr($template_path, 0, -1); + } + + $this->root = $template_path; + + if ($fallback_template_path !== false) + { + if (substr($fallback_template_path, -1) == '/') + { + $fallback_template_path = substr($fallback_template_path, 0, -1); + } + + $this->inherit_root = $fallback_template_path; + } + } + + /** + * Sets the template filenames for handles. $filename_array + * should be a hash of handle => filename pairs. + * + * @param array $filname_array Should be a hash of handle => filename pairs. + */ + public function set_filenames(array $filename_array) + { + foreach ($filename_array as $handle => $filename) + { + if (empty($filename)) + { + trigger_error("template locator: set_filenames: Empty filename specified for $handle", E_USER_ERROR); + } + + $this->filename[$handle] = $filename; + $this->files[$handle] = $this->root . '/' . $filename; + + if ($this->inherit_root) + { + $this->files_inherit[$handle] = $this->inherit_root . '/' . $filename; + } + } + } + + /** + * Determines the filename for a template handle. + * + * The filename comes from array used in a set_filenames call, + * which should have been performed prior to invoking this function. + * Return value is a file basename (without path). + * + * @param $handle string Template handle + * @return string Filename corresponding to the template handle + */ + public function get_filename_for_handle($handle) + { + if (!isset($this->filename[$handle])) + { + trigger_error("template locator: get_filename_for_handle: No file specified for handle $handle", E_USER_ERROR); + } + return $this->filename[$handle]; + } + + /** + * Determines the source file path for a template handle without + * regard for template inheritance. + * + * This function returns the path in "primary" template directory + * corresponding to the given template handle. That path may or + * may not actually exist on the filesystem. Because this function + * does not perform stat calls to determine whether the path it + * returns actually exists, it is faster than get_source_file_for_handle. + * + * Use get_source_file_for_handle to obtain the actual path that is + * guaranteed to exist (which might come from the parent/fallback + * template directory if template inheritance is used). + * + * This function will trigger an error if the handle was never + * associated with a template file via set_filenames. + * + * @param $handle string Template handle + * @return string Path to source file path in primary template directory + */ + public function get_virtual_source_file_for_handle($handle) + { + // If we don't have a file assigned to this handle, die. + if (!isset($this->files[$handle])) + { + trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); + } + + $source_file = $this->files[$handle]; + return $source_file; + } + + /** + * Determines the source file path for a template handle, accounting + * for template inheritance and verifying that the path exists. + * + * This function returns the actual path that may be compiled for + * the specified template handle. It will trigger an error if + * the template handle was never associated with a template path + * via set_filenames or if the template file does not exist on the + * filesystem. + * + * Use get_virtual_source_file_for_handle to just resolve a template + * handle to a path without any filesystem or inheritance checks. + * + * @param string $handle Template handle (i.e. "friendly" template name) + * @return string Source file path + */ + public function get_source_file_for_handle($handle) + { + // If we don't have a file assigned to this handle, die. + if (!isset($this->files[$handle])) + { + trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); + } + + $source_file = $this->files[$handle]; + + // Try and open template for reading + if (!file_exists($source_file)) + { + if (isset($this->files_inherit[$handle]) && $this->files_inherit[$handle]) + { + $parent_source_file = $this->files_inherit[$handle]; + if (!file_exists($parent_source_file)) + { + trigger_error("template locator: Neither $source_file nor $parent_source_file exist", E_USER_ERROR); + } + $source_file = $parent_source_file; + } + else + { + trigger_error("template locator: File $source_file does not exist", E_USER_ERROR); + } + } + return $source_file; + } +} diff --git a/phpBB/includes/template/renderer.php b/phpBB/includes/template/renderer.php new file mode 100644 index 0000000000..59c85df443 --- /dev/null +++ b/phpBB/includes/template/renderer.php @@ -0,0 +1,35 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Template renderer interface. +* +* Objects implementing this interface encapsulate a means of displaying +* a template. +* +* @package phpBB3 +*/ +interface phpbb_template_renderer +{ + /** + * Displays the template managed by this renderer. + * + * @param phpbb_template_context $context Template context to use + * @param array $lang Language entries to use + */ + public function render($context, $lang); +} diff --git a/phpBB/includes/template/renderer_eval.php b/phpBB/includes/template/renderer_eval.php new file mode 100644 index 0000000000..2c05a1c1df --- /dev/null +++ b/phpBB/includes/template/renderer_eval.php @@ -0,0 +1,60 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Template renderer that stores compiled template's php code and +* displays it via eval. +* +* @package phpBB3 +*/ +class phpbb_template_renderer_eval implements phpbb_template_renderer +{ + /** + * Template code to be eval'ed. + */ + private $code; + + /** + * Constructor. Stores provided code for future evaluation. + * Template includes are delegated to template object $template. + * + * @param string $code php code of the template + * @param phpbb_template $template template object + */ + public function __construct($code, $template) + { + $this->code = $code; + $this->template = $template; + } + + /** + * Displays the template managed by this renderer by eval'ing php code + * of the template. + * + * @param phpbb_template_context $context Template context to use + * @param array $lang Language entries to use + */ + public function render($context, $lang) + { + $_template = $this->template; + $_tpldata = &$context->get_data_ref(); + $_rootref = &$context->get_root_ref(); + $_lang = $lang; + + eval(' ?>' . $this->code . '<?php '); + } +} diff --git a/phpBB/includes/template/renderer_include.php b/phpBB/includes/template/renderer_include.php new file mode 100644 index 0000000000..40e7a3376c --- /dev/null +++ b/phpBB/includes/template/renderer_include.php @@ -0,0 +1,60 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + + +/** +* Template renderer that stores path to php file with template code +* and displays it by including the file. +* +* @package phpBB3 +*/ +class phpbb_template_renderer_include implements phpbb_template_renderer +{ + /** + * Template path to be included. + */ + private $path; + + /** + * Constructor. Stores path to the template for future inclusion. + * Template includes are delegated to template object $template. + * + * @param string $path path to the template + */ + public function __construct($path, $template) + { + $this->path = $path; + $this->template = $template; + } + + /** + * Displays the template managed by this renderer by including + * the php file containing the template. + * + * @param phpbb_template_context $context Template context to use + * @param array $lang Language entries to use + */ + public function render($context, $lang) + { + $_template = $this->template; + $_tpldata = &$context->get_data_ref(); + $_rootref = &$context->get_root_ref(); + $_lang = $lang; + + include($this->path); + } +} diff --git a/phpBB/includes/template/template.php b/phpBB/includes/template/template.php new file mode 100644 index 0000000000..ec5fbe2829 --- /dev/null +++ b/phpBB/includes/template/template.php @@ -0,0 +1,486 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @todo +* IMG_ for image substitution? +* {IMG_[key]:[alt]:[type]} +* {IMG_ICON_CONTACT:CONTACT:full} -> $user->img('icon_contact', 'CONTACT', 'full'); +* +* More in-depth... +* yadayada +*/ + +/** +* Base Template class. +* @package phpBB3 +*/ +class phpbb_template +{ + /** + * @var phpbb_template_context Template context. + * Stores template data used during template rendering. + */ + private $context; + + /** + * @var string Path of the cache directory for the template + */ + public $cachepath = ''; + + /** + * @var string phpBB root path + */ + private $phpbb_root_path; + + /** + * @var phpEx PHP file extension + */ + private $phpEx; + + /** + * @var phpbb_config phpBB config instance + */ + private $config; + + /** + * @var user current user + */ + private $user; + + /** + * @var locator template locator + */ + private $locator; + + /** + * Constructor. + * + * @param string $phpbb_root_path phpBB root path + * @param user $user current user + * @param phpbb_template_locator $locator template locator + */ + public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_template_locator $locator) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->phpEx = $phpEx; + $this->config = $config; + $this->user = $user; + $this->locator = $locator; + } + + /** + * Set template location based on (current) user's chosen style. + */ + public function set_template() + { + $style_name = $this->user->theme['template_path']; + + $relative_template_root = $this->relative_template_root_for_style($style_name); + $template_root = $this->phpbb_root_path . $relative_template_root; + if (!file_exists($template_root)) + { + trigger_error('template locator: Template path could not be found: ' . $relative_template_root, E_USER_ERROR); + } + + if ($this->user->theme['template_inherits_id']) + { + $fallback_template_path = $this->phpbb_root_path . $this->relative_template_root_for_style($this->user->theme['template_inherit_path']); + } + else + { + $fallback_template_path = null; + } + + return $this->set_custom_template($template_root, $style_name, $fallback_template_path); + } + + /** + * Set custom template location (able to use directory outside of phpBB). + * + * Note: Templates are still compiled to phpBB's cache directory. + * + * @param string $template_path Path to template directory + * @param string $template_name Name of template + * @param string $fallback_template_path Path to fallback template + */ + public function set_custom_template($template_path, $style_name, $fallback_template_path = false) + { + $this->locator->set_custom_template($template_path, $fallback_template_path); + + $this->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $style_name) . '_'; + + $this->context = new phpbb_template_context(); + + return true; + } + + /** + * Converts a style name to relative (to board root) path to + * the style's template files. + * + * @param $style_name string Style name + * @return string Path to style template files + */ + private function relative_template_root_for_style($style_name) + { + return 'styles/' . $style_name . '/template'; + } + + /** + * Sets the template filenames for handles. + * + * @param array $filname_array Should be a hash of handle => filename pairs. + */ + public function set_filenames(array $filename_array) + { + $this->locator->set_filenames($filename_array); + + return true; + } + + /** + * Clears all variables and blocks assigned to this template. + */ + public function destroy() + { + $this->context->clear(); + } + + /** + * Reset/empty complete block + * + * @param string $blockname Name of block to destroy + */ + public function destroy_block_vars($blockname) + { + $this->context->destroy_block_vars($blockname); + } + + /** + * Display a template for provided handle. + * + * The template will be loaded and compiled, if necessary, first. + * + * This function calls hooks. + * + * @param string $handle Handle to display + * @return bool True on success, false on failure + */ + public function display($handle) + { + $result = $this->call_hook($handle); + if ($result !== false) + { + return $result[0]; + } + + return $this->load_and_render($handle); + } + + /** + * Loads a template for $handle, compiling it if necessary, and + * renders the template. + * + * @param string $handle Template handle to render + * @return bool True on success, false on failure + */ + private function load_and_render($handle) + { + $renderer = $this->_tpl_load($handle); + + if ($renderer) + { + $renderer->render($this->context, $this->get_lang()); + return true; + } + else + { + return false; + } + } + + /** + * Calls hook if any is defined. + * + * @param string $handle Template handle being displayed. + */ + private function call_hook($handle) + { + global $phpbb_hook; + + if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, __FUNCTION__), $handle, $this)) + { + if ($phpbb_hook->hook_return(array(__CLASS__, __FUNCTION__))) + { + $result = $phpbb_hook->hook_return_result(array(__CLASS__, __FUNCTION__)); + return array($result); + } + } + + return false; + } + + /** + * Obtains language array. + * This is either lang property of $user property, or if + * it is not set an empty array. + * @return array language entries + */ + public function get_lang() + { + if (isset($this->user->lang)) + { + $lang = $this->user->lang; + } + else + { + $lang = array(); + } + return $lang; + } + + /** + * Display the handle and assign the output to a template variable + * or return the compiled result. + * + * @param string $handle Handle to operate on + * @param string $template_var Template variable to assign compiled handle to + * @param bool $return_content If true return compiled handle, otherwise assign to $template_var + * @return bool|string false on failure, otherwise if $return_content is true return string of the compiled handle, otherwise return true + */ + public function assign_display($handle, $template_var = '', $return_content = true) + { + ob_start(); + $result = $this->display($handle); + $contents = ob_get_clean(); + if ($result === false) + { + return false; + } + + if ($return_content) + { + return $contents; + } + + $this->assign_var($template_var, $contents); + + return true; + } + + /** + * Obtains a template renderer for a template identified by specified + * handle. The template renderer can display the template later. + * + * Template source will first be compiled into php code. + * If template cache is writable the compiled php code will be stored + * on filesystem and template will not be subsequently recompiled. + * If template cache is not writable template source will be recompiled + * every time it is needed. DEBUG_EXTRA define and load_tplcompile + * configuration setting may be used to force templates to be always + * recompiled. + * + * Returns an object implementing phpbb_template_renderer, or null + * if template loading or compilation failed. Call render() on the + * renderer to display the template. This will result in template + * contents sent to the output stream (unless, of course, output + * buffering is in effect). + * + * @param string $handle Handle of the template to load + * @return phpbb_template_renderer Template renderer object, or null on failure + * @uses template_compile is used to compile template source + */ + private function _tpl_load($handle) + { + $output_file = $this->_compiled_file_for_handle($handle); + + $recompile = defined('DEBUG_EXTRA') || + !file_exists($output_file) || + @filesize($output_file) === 0; + + if ($recompile || $this->config['load_tplcompile']) + { + // Set only if a recompile or an mtime check are required. + $source_file = $this->locator->get_source_file_for_handle($handle); + + if (!$recompile && @filemtime($output_file) < @filemtime($source_file)) + { + $recompile = true; + } + } + + // Recompile page if the original template is newer, otherwise load the compiled version + if (!$recompile) + { + return new phpbb_template_renderer_include($output_file, $this); + } + + $compile = new phpbb_template_compile($this->config['tpl_allow_php']); + + if ($compile->compile_file_to_file($source_file, $output_file) !== false) + { + $renderer = new phpbb_template_renderer_include($output_file, $this); + } + else if (($code = $compile->compile_file($source_file)) !== false) + { + $renderer = new phpbb_template_renderer_eval($code, $this); + } + else + { + $renderer = null; + } + + return $renderer; + } + + /** + * Determines compiled file path for handle $handle. + * + * @param string $handle Template handle (i.e. "friendly" template name) + * @return string Compiled file path + */ + private function _compiled_file_for_handle($handle) + { + $source_file = $this->locator->get_filename_for_handle($handle); + $compiled_file = $this->cachepath . str_replace('/', '.', $source_file) . '.' . $this->phpEx; + return $compiled_file; + } + + /** + * Assign key variable pairs from an array + * + * @param array $vararray A hash of variable name => value pairs + */ + public function assign_vars(array $vararray) + { + foreach ($vararray as $key => $val) + { + $this->assign_var($key, $val); + } + } + + /** + * Assign a single variable to a single key + * + * @param string $varname Variable name + * @param string $varval Value to assign to variable + */ + public function assign_var($varname, $varval) + { + $this->context->assign_var($varname, $varval); + } + + // Docstring is copied from phpbb_template_context method with the same name. + /** + * Assign key variable pairs from an array to a specified block + * @param string $blockname Name of block to assign $vararray to + * @param array $vararray A hash of variable name => value pairs + */ + public function assign_block_vars($blockname, array $vararray) + { + return $this->context->assign_block_vars($blockname, $vararray); + } + + // Docstring is copied from phpbb_template_context method with the same name. + /** + * Change already assigned key variable pair (one-dimensional - single loop entry) + * + * An example of how to use this function: + * {@example alter_block_array.php} + * + * @param string $blockname the blockname, for example 'loop' + * @param array $vararray the var array to insert/add or merge + * @param mixed $key Key to search for + * + * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] + * + * int: Position [the position to change or insert at directly given] + * + * If key is false the position is set to 0 + * If key is true the position is set to the last entry + * + * @param string $mode Mode to execute (valid modes are 'insert' and 'change') + * + * If insert, the vararray is inserted at the given position (position counting from zero). + * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). + * + * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) + * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) + * + * @return bool false on error, true on success + */ + public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') + { + return $this->context->alter_block_array($blockname, $vararray, $key, $mode); + } + + /** + * Include a separate template. + * + * This function is marked public due to the way the template + * implementation uses it. It is actually an implementation function + * and should not be considered part of template class's public API. + * + * @param string $filename Template filename to include + * @param bool $include True to include the file, false to just load it + * @uses template_compile is used to compile uncached templates + */ + public function _tpl_include($filename, $include = true) + { + $this->locator->set_filenames(array($filename => $filename)); + + if (!$this->load_and_render($filename)) + { + // trigger_error cannot be used here, as the output already started + echo 'template->_tpl_include(): Failed including ' . htmlspecialchars($handle) . "\n"; + } + } + + /** + * Include a PHP file. + * + * If a relative path is passed in $filename, it is considered to be + * relative to board root ($phpbb_root_path). Absolute paths are + * also allowed. + * + * This function is marked public due to the way the template + * implementation uses it. It is actually an implementation function + * and should not be considered part of template class's public API. + * + * @param string $filename Path to PHP file to include + */ + public function _php_include($filename) + { + if (phpbb_is_absolute($filename)) + { + $file = $filename; + } + else + { + $file = $this->phpbb_root_path . $filename; + } + + if (!file_exists($file)) + { + // trigger_error cannot be used here, as the output already started + echo 'template->_php_include(): File ' . htmlspecialchars($file) . " does not exist\n"; + return; + } + include($file); + } +} diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index f4fdb50ecd..738da62158 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -161,7 +161,6 @@ class ucp_main 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), - 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '', 'S_USER_POSTED' => (!empty($row['topic_posted']) && $row['topic_posted']) ? true : false, @@ -348,7 +347,6 @@ class ucp_main 'FORUM_ID' => $forum_id, 'FORUM_IMG_STYLE' => $folder_image, 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), - 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, false, '', 'src'), 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . $phpbb_root_path . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '', 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? $phpbb_root_path . $row['forum_image'] : '', 'FORUM_NAME' => $row['forum_name'], @@ -825,7 +823,6 @@ class ucp_main 'TOPIC_IMG_STYLE' => $folder_img, 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), - 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), 'TOPIC_FOLDER_IMG_ALT' => $user->lang[$folder_alt], 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 1758bb5eb1..c74574f361 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -166,7 +166,6 @@ function view_folder($id, $mode, $folder_id, $folder) 'PM_ICON_URL' => (!empty($icons[$row['icon_id']])) ? $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] : '', 'FOLDER_IMG' => $user->img($folder_img, $folder_alt), 'FOLDER_IMG_STYLE' => $folder_img, - 'FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, false, '', 'src'), 'PM_IMG' => ($row_indicator) ? $user->img('pm_' . $row_indicator, '') : '', 'ATTACH_ICON_IMG' => ($auth->acl_get('u_pm_download') && $row['message_attachment'] && $config['allow_pm_attach']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 8b288f5de1..c9451bd202 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -239,7 +239,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id) : '', 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', - 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people' . urlencode($user_info['user_icq']) . '/' : '', + 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/' . urlencode($user_info['user_icq']) . '/' : '', 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 71374a9381..3781fc6b1c 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -156,13 +156,12 @@ class ucp_register $this->tpl_name = 'ucp_agreement'; return; } - - - // The CAPTCHA kicks in here. We can't help that the information gets lost on language change. + + // The CAPTCHA kicks in here. We can't help that the information gets lost on language change. if ($config['enable_confirm']) { include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); - $captcha =& phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); $captcha->init(CONFIRM_REG); } |