diff options
Diffstat (limited to 'phpBB/includes')
34 files changed, 886 insertions, 277 deletions
diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 62bcd43a47..758cd10434 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -21,6 +21,7 @@ if (!defined('IN_PHPBB')) */ class acp_database { + var $db_tools; var $u_action; function main($id, $mode) @@ -28,6 +29,12 @@ class acp_database global $cache, $db, $user, $auth, $template, $table_prefix; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + if (!class_exists('phpbb_db_tools')) + { + require($phpbb_root_path . 'includes/db/db_tools.' . $phpEx); + } + $this->db_tools = new phpbb_db_tools($db); + $user->add_lang('acp/database'); $this->tpl_name = 'acp_database'; @@ -50,7 +57,7 @@ class acp_database { case 'download': $type = request_var('type', ''); - $table = request_var('table', array('')); + $table = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array(''))); $format = request_var('method', ''); $where = request_var('where', ''); @@ -173,8 +180,7 @@ class acp_database break; default: - include($phpbb_root_path . 'includes/functions_install.' . $phpEx); - $tables = get_tables($db); + $tables = $this->db_tools->sql_list_tables(); asort($tables); foreach ($tables as $table_name) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c8df21f5a9..cffe296651 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -201,7 +201,7 @@ class acp_main // No maximum post id? :o if (!$max_post_id) { - $sql = 'SELECT MAX(post_id) + $sql = 'SELECT MAX(post_id) as max_post_id FROM ' . POSTS_TABLE; $result = $db->sql_query($sql); $max_post_id = (int) $db->sql_fetchfield('max_post_id'); @@ -398,11 +398,11 @@ class acp_main // Version check $user->add_lang('install'); - if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.2.0', '<')) + if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.2', '<')) { $template->assign_vars(array( 'S_PHP_VERSION_OLD' => true, - 'L_PHP_VERSION_OLD' => sprintf($user->lang['PHP_VERSION_OLD'], '<a href="http://www.phpbb.com/community/viewtopic.php?f=14&t=1958605">', '</a>'), + 'L_PHP_VERSION_OLD' => sprintf($user->lang['PHP_VERSION_OLD'], '<a href="http://www.phpbb.com/community/viewtopic.php?f=14&t=2152375">', '</a>'), )); } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 2e43b0545a..19223847f0 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -365,6 +365,7 @@ class acp_profile $field_row = array_merge($default_values[$field_type], array( 'field_ident' => str_replace(' ', '_', utf8_clean_string(request_var('field_ident', '', true))), 'field_required' => 0, + 'field_show_novalue'=> 0, 'field_hide' => 0, 'field_show_profile'=> 0, 'field_no_view' => 0, @@ -380,7 +381,7 @@ class acp_profile // $exclude contains the data we gather in each step $exclude = array( - 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_hide', 'field_show_profile', 'field_no_view'), + 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_vt', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view'), 2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'), 3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options') ); @@ -405,6 +406,7 @@ class acp_profile // Visibility Options... $visibility_ary = array( 'field_required', + 'field_show_novalue', 'field_show_on_reg', 'field_show_on_vt', 'field_show_profile', @@ -504,11 +506,34 @@ class acp_profile } } } - /* else if ($field_type == FIELD_BOOL && $key == 'field_default_value') + else if ($field_type == FIELD_BOOL && $key == 'field_default_value') { - // Get the number of options if this key is 'field_maxlen' - $var = request_var('field_default_value', 0); - }*/ + // 'field_length' == 1 defines radio buttons. Possible values are 1 or 2 only. + // 'field_length' == 2 defines checkbox. Possible values are 0 or 1 only. + // If we switch the type on step 2, we have to adjust field value. + // 1 is a common value for the checkbox and radio buttons. + + // Adjust unchecked checkbox value. + // If we return or save settings from 2nd/3rd page + // and the checkbox is unchecked, set the value to 0. + if (isset($_REQUEST['step']) && !isset($_REQUEST[$key])) + { + $var = 0; + } + + // If we switch to the checkbox type but former radio buttons value was 2, + // which is not the case for the checkbox, set it to 0 (unchecked). + if ($cp->vars['field_length'] == 2 && $var == 2) + { + $var = 0; + } + // If we switch to the radio buttons but the former checkbox value was 0, + // which is not the case for the radio buttons, set it to 0. + else if ($cp->vars['field_length'] == 1 && $var == 0) + { + $var = 2; + } + } else if ($field_type == FIELD_INT && $key == 'field_default_value') { // Permit an empty string @@ -676,6 +701,10 @@ class acp_profile { $_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(array('')), true)); } + else if ($field_type == FIELD_BOOL && $key == 'field_default_value') + { + $_new_key_ary[$key] = request_var($key, $cp->vars[$key]); + } else { if (!isset($_REQUEST[$key])) @@ -730,6 +759,7 @@ class acp_profile $template->assign_vars(array( 'S_STEP_ONE' => true, 'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false, + 'S_FIELD_SHOW_NOVALUE'=> ($cp->vars['field_show_novalue']) ? true : false, 'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false, 'S_SHOW_ON_VT' => ($cp->vars['field_show_on_vt']) ? true : false, 'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false, @@ -1046,6 +1076,7 @@ class acp_profile 'field_default_value' => $cp->vars['field_default_value'], 'field_validation' => $cp->vars['field_validation'], 'field_required' => $cp->vars['field_required'], + 'field_show_novalue' => $cp->vars['field_show_novalue'], 'field_show_on_reg' => $cp->vars['field_show_on_reg'], 'field_show_on_vt' => $cp->vars['field_show_on_vt'], 'field_hide' => $cp->vars['field_hide'], diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php index dfd7511427..ea057cd84c 100644 --- a/phpBB/includes/acp/acp_ranks.php +++ b/phpBB/includes/acp/acp_ranks.php @@ -52,7 +52,7 @@ class acp_ranks } $rank_title = utf8_normalize_nfc(request_var('title', '', true)); $special_rank = request_var('special_rank', 0); - $min_posts = ($special_rank) ? 0 : request_var('min_posts', 0); + $min_posts = ($special_rank) ? 0 : max(0, request_var('min_posts', 0)); $rank_image = request_var('rank_image', ''); // The rank image has to be a jpg, gif or png diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index d7b0484af8..47cd02bca7 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -667,7 +667,9 @@ inherit_from = {INHERIT_FROM} if ($name && !in_array($name, $installed)) { - $new_ary[] = array( + // The array key is used for sorting later on. + // $file is appended because $name doesn't have to be unique. + $new_ary[$name . $file] = array( 'path' => $file, 'name' => $name, 'copyright' => $items['copyright'], @@ -683,6 +685,8 @@ inherit_from = {INHERIT_FROM} if (sizeof($new_ary)) { + ksort($new_ary); + foreach ($new_ary as $cfg) { $template->assign_block_vars('uninstalled', array( diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 363c900edc..70e08f79f2 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1009,6 +1009,13 @@ class acp_users $user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); $db->sql_freeresult($result); + $sql = 'SELECT post_id + FROM ' . POSTS_TABLE . ' + WHERE poster_id = '. $user_id; + $result = $db->sql_query_limit($sql, 1); + $user_row['user_has_posts'] = (bool) $db->sql_fetchfield('post_id'); + $db->sql_freeresult($result); + $template->assign_vars(array( 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), @@ -1036,6 +1043,7 @@ class acp_users 'USER_EMAIL' => $user_row['user_email'], 'USER_WARNINGS' => $user_row['user_warnings'], 'USER_POSTS' => $user_row['user_posts'], + 'USER_HAS_POSTS' => $user_row['user_has_posts'], 'USER_INACTIVE_REASON' => $inactive_reason, )); diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index c20196d019..1c6cdf7832 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -163,7 +163,7 @@ function login_db($username, $password, $ip = '', $browser = '', $forwarded_for $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format; $password_new_format = ''; - set_var($password_new_format, stripslashes($password_old_format), 'string'); + set_var($password_new_format, stripslashes($password_old_format), 'string', true); if ($password == $password_new_format) { diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php index 5dfa74ddab..eebf147d48 100644 --- a/phpBB/includes/auth/auth_ldap.php +++ b/phpBB/includes/auth/auth_ldap.php @@ -156,7 +156,11 @@ function login_ldap(&$username, &$password) { if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password']))) { - return $user->lang['LDAP_NO_SERVER_CONNECTION']; + return array( + 'status' => LOGIN_ERROR_EXTERNAL_AUTH, + 'error_msg' => 'LDAP_NO_SERVER_CONNECTION', + 'user_row' => array('user_id' => ANONYMOUS), + ); } } diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index a0444ea594..17c25ee3c6 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -25,7 +25,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -define('PHPBB_VERSION', '3.0.11-dev'); +define('PHPBB_VERSION', '3.0.12-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index 2cba11133a..c6dd23e6bd 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -2115,7 +2115,7 @@ class phpbb_db_tools case 'mysql_40': case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX (' . implode(', ', $column) . ')'; + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD UNIQUE INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; break; case 'mssql': diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index 230c9c8ed7..9cc337955b 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -195,6 +195,49 @@ class dbal } /** + * Seek to given row number + * rownum is zero-based + */ + function sql_rowseek($rownum, &$query_id) + { + global $cache; + + if ($query_id === false) + { + $query_id = $this->query_result; + } + + if (isset($cache->sql_rowset[$query_id])) + { + return $cache->sql_rowseek($rownum, $query_id); + } + + if ($query_id === false) + { + return false; + } + + $this->sql_freeresult($query_id); + $query_id = $this->sql_query($this->last_query_text); + + if ($query_id === false) + { + return false; + } + + // We do not fetch the row for rownum == 0 because then the next resultset would be the second row + for ($i = 0; $i < $rownum; $i++) + { + if (!$this->sql_fetchrow($query_id)) + { + return false; + } + } + + return true; + } + + /** * Fetch field * if rownum is false, the current row is used, else it is pointing to the row (zero-based) */ @@ -458,6 +501,18 @@ class dbal } /** + * Run LOWER() on DB column of type text (i.e. neither varchar nor char). + * + * @param string $column_name The column name to use + * + * @return string A SQL statement like "LOWER($column_name)" + */ + function sql_lower_text($column_name) + { + return "LOWER($column_name)"; + } + + /** * Run more than one insert statement. * * @param string $table table name to run the statements on @@ -900,6 +955,41 @@ class dbal return true; } + + /** + * Gets the estimated number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Number of rows in $table_name. + * Prefixed with ~ if estimated (otherwise exact). + * + * @access public + */ + function get_estimated_row_count($table_name) + { + return $this->get_row_count($table_name); + } + + /** + * Gets the exact number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Exact number of rows in $table_name. + * + * @access public + */ + function get_row_count($table_name) + { + $sql = 'SELECT COUNT(*) AS rows_total + FROM ' . $this->sql_escape($table_name); + $result = $this->sql_query($sql); + $rows_total = $this->sql_fetchfield('rows_total'); + $this->sql_freeresult($result); + + return $rows_total; + } } /** diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index 7e3f15ed1d..7072c58ac0 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -360,49 +360,6 @@ class dbal_firebird extends dbal } /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - if ($query_id === false) - { - return; - } - - $this->sql_freeresult($query_id); - $query_id = $this->sql_query($this->last_query_text); - - if ($query_id === false) - { - return false; - } - - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $rownum; $i++) - { - if (!$this->sql_fetchrow($query_id)) - { - return false; - } - } - - return true; - } - - /** * Get last inserted id after insert statement */ function sql_nextid() diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php index 6899a73902..b7178593dc 100644 --- a/phpBB/includes/db/mssql.php +++ b/phpBB/includes/db/mssql.php @@ -333,6 +333,14 @@ class dbal_mssql extends dbal } /** + * {@inheritDoc} + */ + function sql_lower_text($column_name) + { + return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; + } + + /** * Build LIKE expression * @access private */ diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php index 75a080b1b7..2ecc42cadf 100644 --- a/phpBB/includes/db/mssql_odbc.php +++ b/phpBB/includes/db/mssql_odbc.php @@ -256,49 +256,6 @@ class dbal_mssql_odbc extends dbal } /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - if ($query_id === false) - { - return false; - } - - $this->sql_freeresult($query_id); - $query_id = $this->sql_query($this->last_query_text); - - if ($query_id === false) - { - return false; - } - - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $rownum; $i++) - { - if (!$this->sql_fetchrow($query_id)) - { - return false; - } - } - - return true; - } - - /** * Get last inserted id after insert statement */ function sql_nextid() @@ -354,6 +311,14 @@ class dbal_mssql_odbc extends dbal } /** + * {@inheritDoc} + */ + function sql_lower_text($column_name) + { + return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; + } + + /** * Build LIKE expression * @access private */ diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 7fbc374e77..3ad0ff3e11 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -219,7 +219,6 @@ class dbal_mssqlnative extends dbal $this->server = $sqlserver . (($port) ? $port_delimiter . $port : ''); //connect to database - error_reporting(E_ALL); $this->db_connect_id = sqlsrv_connect($this->server, array( 'Database' => $this->dbname, 'UID' => $this->user, @@ -436,25 +435,7 @@ class dbal_mssqlnative extends dbal unset($row['line2'], $row['line3']); } } - return $row; - } - - /** - * Seek to given row number - * rownum is zero-based - */ - function sql_rowseek($rownum, &$query_id) - { - global $cache; - - if (isset($cache->sql_rowset[$query_id])) - { - return $cache->sql_rowseek($rownum, $query_id); - } - - $seek = new result_mssqlnative($query_id); - $row = $seek->seek($rownum); - return ($row = $seek->fetch()) ? $row : false; + return (sizeof($row)) ? $row : false; } /** @@ -511,6 +492,14 @@ class dbal_mssqlnative extends dbal } /** + * {@inheritDoc} + */ + function sql_lower_text($column_name) + { + return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))"; + } + + /** * Build LIKE expression * @access private */ diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php index 1e24c79577..1ccb785150 100644 --- a/phpBB/includes/db/mysql.php +++ b/phpBB/includes/db/mysql.php @@ -319,6 +319,76 @@ class dbal_mysql extends dbal } /** + * Gets the estimated number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Number of rows in $table_name. + * Prefixed with ~ if estimated (otherwise exact). + * + * @access public + */ + function get_estimated_row_count($table_name) + { + $table_status = $this->get_table_status($table_name); + + if (isset($table_status['Engine'])) + { + if ($table_status['Engine'] === 'MyISAM') + { + return $table_status['Rows']; + } + else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) + { + return '~' . $table_status['Rows']; + } + } + + return parent::get_row_count($table_name); + } + + /** + * Gets the exact number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Exact number of rows in $table_name. + * + * @access public + */ + function get_row_count($table_name) + { + $table_status = $this->get_table_status($table_name); + + if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') + { + return $table_status['Rows']; + } + + return parent::get_row_count($table_name); + } + + /** + * Gets some information about the specified table. + * + * @param string $table_name Table name + * + * @return array + * + * @access protected + */ + function get_table_status($table_name) + { + $sql = "SHOW TABLE STATUS + LIKE '" . $this->sql_escape($table_name) . "'"; + $result = $this->sql_query($sql); + $table_status = $this->sql_fetchrow($result); + $this->sql_freeresult($result); + + return $table_status; + } + + /** * Build LIKE expression * @access private */ diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php index 456ce906d0..a311b8cda6 100644 --- a/phpBB/includes/db/mysqli.php +++ b/phpBB/includes/db/mysqli.php @@ -316,6 +316,76 @@ class dbal_mysqli extends dbal } /** + * Gets the estimated number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Number of rows in $table_name. + * Prefixed with ~ if estimated (otherwise exact). + * + * @access public + */ + function get_estimated_row_count($table_name) + { + $table_status = $this->get_table_status($table_name); + + if (isset($table_status['Engine'])) + { + if ($table_status['Engine'] === 'MyISAM') + { + return $table_status['Rows']; + } + else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000) + { + return '~' . $table_status['Rows']; + } + } + + return parent::get_row_count($table_name); + } + + /** + * Gets the exact number of rows in a specified table. + * + * @param string $table_name Table name + * + * @return string Exact number of rows in $table_name. + * + * @access public + */ + function get_row_count($table_name) + { + $table_status = $this->get_table_status($table_name); + + if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM') + { + return $table_status['Rows']; + } + + return parent::get_row_count($table_name); + } + + /** + * Gets some information about the specified table. + * + * @param string $table_name Table name + * + * @return array + * + * @access protected + */ + function get_table_status($table_name) + { + $sql = "SHOW TABLE STATUS + LIKE '" . $this->sql_escape($table_name) . "'"; + $result = $this->sql_query($sql); + $table_status = $this->sql_fetchrow($result); + $this->sql_freeresult($result); + + return $table_status; + } + + /** * Build LIKE expression * @access private */ diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 0320230a7d..ca58220619 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1918,14 +1918,17 @@ function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_ti } else { - $sql = 'SELECT t.forum_id FROM ' . TOPICS_TABLE . ' t - LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ') + $sql = 'SELECT t.forum_id + FROM ' . TOPICS_TABLE . ' t + LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt + ON (tt.topic_id = t.topic_id + AND tt.user_id = ' . $user->data['user_id'] . ') WHERE t.forum_id = ' . $forum_id . ' AND t.topic_last_post_time > ' . $mark_time_forum . ' AND t.topic_moved_id = 0 ' . $sql_update_unapproved . ' - AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time) - GROUP BY t.forum_id'; + AND (tt.topic_id IS NULL + OR tt.mark_time < t.topic_last_post_time)'; $result = $db->sql_query_limit($sql, 1); $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -2808,7 +2811,7 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg $diff = time() - $creation_time; // If creation_time and the time() now is zero we can assume it was not a human doing this (the check for if ($diff)... - if ($diff && ($diff <= $timespan || $timespan === -1)) + if (defined('DEBUG_TEST') || $diff && ($diff <= $timespan || $timespan === -1)) { $token_sid = ($user->data['user_id'] == ANONYMOUS && !empty($config['form_token_sid_guests'])) ? $user->session_id : ''; $key = sha1($creation_time . $user->data['user_form_salt'] . $form_name . $token_sid); @@ -3453,7 +3456,7 @@ function get_preg_expression($mode) case 'email': // Regex written by James Watts and Francisco Jose Martin Moreno // http://fightingforalostcause.net/misc/2006/compare-email-regex.php - return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; + return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; break; case 'bbcode_htm': @@ -3918,7 +3921,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) echo ' </div>'; echo ' </div>'; echo ' <div id="page-footer">'; - echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'; + echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'; echo ' </div>'; echo '</div>'; echo '</body>'; @@ -4738,6 +4741,7 @@ function page_footer($run_cron = true) $template->assign_vars(array( 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '', 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', + 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Group'), 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') ); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 0e1a11b4aa..7352b3d1f3 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2294,6 +2294,21 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr } /** +* remove_comments will strip the sql comment lines out of an uploaded sql file +* specifically for mssql and postgres type files in the install.... +* +* @deprecated Use phpbb_remove_comments() instead. +*/ +function remove_comments(&$output) +{ + // Remove /* */ comments (http://ostermiller.org/findcomment.html) + $output = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $output); + + // Return by reference and value. + return $output; +} + +/** * Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username * and group names must be carried through for the moderators table */ @@ -2557,7 +2572,8 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id { $sql_keywords .= $db->sql_in_set('l.log_operation', $operations) . ' OR '; } - $sql_keywords .= 'LOWER(l.log_data) ' . implode(' OR LOWER(l.log_data) ', $keywords) . ')'; + $sql_lower = $db->sql_lower_text('l.log_data'); + $sql_keywords .= "$sql_lower " . implode(" OR $sql_lower ", $keywords) . ')'; } if ($log_count !== false) diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 6caa5c943f..eae136808c 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -50,6 +50,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'firebird', 'MODULE' => 'interbase', 'DELIM' => ';;', + 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'firebird', 'AVAILABLE' => true, '2.0.x' => false, @@ -59,6 +60,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mysql_41', 'MODULE' => 'mysqli', 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'mysqli', 'AVAILABLE' => true, '2.0.x' => true, @@ -68,6 +70,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mysql', 'MODULE' => 'mysql', 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'mysql', 'AVAILABLE' => true, '2.0.x' => true, @@ -77,6 +80,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'mssql', 'DELIM' => 'GO', + 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssql', 'AVAILABLE' => true, '2.0.x' => true, @@ -86,6 +90,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'odbc', 'DELIM' => 'GO', + 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssql_odbc', 'AVAILABLE' => true, '2.0.x' => true, @@ -95,6 +100,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'mssql', 'MODULE' => 'sqlsrv', 'DELIM' => 'GO', + 'COMMENTS' => 'remove_comments', 'DRIVER' => 'mssqlnative', 'AVAILABLE' => true, '2.0.x' => false, @@ -104,6 +110,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'oracle', 'MODULE' => 'oci8', 'DELIM' => '/', + 'COMMENTS' => 'remove_comments', 'DRIVER' => 'oracle', 'AVAILABLE' => true, '2.0.x' => false, @@ -113,6 +120,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'postgres', 'MODULE' => 'pgsql', 'DELIM' => ';', + 'COMMENTS' => 'remove_comments', 'DRIVER' => 'postgres', 'AVAILABLE' => true, '2.0.x' => true, @@ -122,6 +130,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20 'SCHEMA' => 'sqlite', 'MODULE' => 'sqlite', 'DELIM' => ';', + 'COMMENTS' => 'remove_remarks', 'DRIVER' => 'sqlite', 'AVAILABLE' => true, '2.0.x' => false, @@ -465,16 +474,39 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, /** * Removes comments from schema files +* +* @deprecated Use phpbb_remove_comments() instead. */ -function remove_comments($sql) +function remove_remarks(&$sql) { - // Remove /* */ comments (http://ostermiller.org/findcomment.html) - $sql = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql); - // Remove # style comments $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql)); - return $sql; + // Return by reference +} + +/** +* Removes "/* style" as well as "# style" comments from $input. +* +* @param string $input Input string +* +* @return string Input string with comments removed +*/ +function phpbb_remove_comments($input) +{ + if (!function_exists('remove_comments')) + { + global $phpbb_root_path, $phpEx; + require($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + // Remove /* */ comments + remove_comments($input); + + // Remove # style comments + remove_remarks($input); + + return $input; } /** @@ -512,4 +544,61 @@ function adjust_language_keys_callback($matches) } } +/** +* Creates the output to be stored in a phpBB config.php file +* +* @param array $data Array containing the database connection information +* @param string $dbms The name of the DBAL class to use +* @param array $load_extensions Array of additional extensions that should be loaded +* @param bool $debug If the debug constants should be enabled by default or not +* @param bool $debug_test If the DEBUG_TEST constant should be added +* NOTE: Only for use within the testing framework +* +* @return string The output to write to the file +*/ +function phpbb_create_config_file_data($data, $dbms, $load_extensions, $debug = false, $debug_test = false) +{ + $load_extensions = implode(',', $load_extensions); + + $config_data = "<?php\n"; + $config_data .= "// phpBB 3.0.x auto-generated configuration file\n// Do not change anything in this file!\n"; + + $config_data_array = array( + 'dbms' => $dbms, + 'dbhost' => $data['dbhost'], + 'dbport' => $data['dbport'], + 'dbname' => $data['dbname'], + 'dbuser' => $data['dbuser'], + 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), + 'table_prefix' => $data['table_prefix'], + 'acm_type' => 'file', + 'load_extensions' => $load_extensions, + ); + + foreach ($config_data_array as $key => $value) + { + $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; + } + + $config_data .= "\n@define('PHPBB_INSTALLED', true);\n"; + + if ($debug) + { + $config_data .= "@define('DEBUG', true);\n"; + $config_data .= "@define('DEBUG_EXTRA', true);\n"; + } + else + { + $config_data .= "// @define('DEBUG', true);\n"; + $config_data .= "// @define('DEBUG_EXTRA', true);\n"; + } + + if ($debug_test) + { + $config_data .= "@define('DEBUG_TEST', true);\n"; + } + + return $config_data; +} + ?>
\ No newline at end of file diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index be3aa844fe..a1029ab97a 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -288,13 +288,15 @@ function posting_gen_topic_icons($mode, $icon_id) if (sizeof($icons)) { + $root_path = (defined('PHPBB_USE_BOARD_URL_PATH') && PHPBB_USE_BOARD_URL_PATH) ? generate_board_url() . '/' : $phpbb_root_path; + foreach ($icons as $id => $data) { if ($data['display']) { $template->assign_block_vars('topic_icon', array( 'ICON_ID' => $id, - 'ICON_IMG' => $phpbb_root_path . $config['icons_path'] . '/' . $data['img'], + 'ICON_IMG' => $root_path . $config['icons_path'] . '/' . $data['img'], 'ICON_WIDTH' => $data['width'], 'ICON_HEIGHT' => $data['height'], @@ -497,7 +499,14 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage { if ($free_space <= $file->get('filesize')) { - $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; + if ($auth->acl_get('a_')) + { + $filedata['error'][] = $user->lang['ATTACH_DISK_FULL']; + } + else + { + $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED']; + } $filedata['post_attach'] = false; $file->remove(); @@ -1180,36 +1189,32 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id $topic_title = ($topic_notification) ? $topic_title : $subject; $topic_title = censor_text($topic_title); - // Get banned User ID's - $sql = 'SELECT ban_userid - FROM ' . BANLIST_TABLE . ' - WHERE ban_userid <> 0 - AND ban_exclude <> 1'; - $result = $db->sql_query($sql); - - $sql_ignore_users = ANONYMOUS . ', ' . $user->data['user_id']; - while ($row = $db->sql_fetchrow($result)) + // Exclude guests, current user and banned users from notifications + if (!function_exists('phpbb_get_banned_user_ids')) { - $sql_ignore_users .= ', ' . (int) $row['ban_userid']; + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); } - $db->sql_freeresult($result); + $sql_ignore_users = phpbb_get_banned_user_ids(); + $sql_ignore_users[ANONYMOUS] = ANONYMOUS; + $sql_ignore_users[$user->data['user_id']] = $user->data['user_id']; $notify_rows = array(); // -- get forum_userids || topic_userids $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u - WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . " - AND w.user_id NOT IN ($sql_ignore_users) - AND w.notify_status = " . NOTIFY_YES . ' + WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . ' + AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . ' + AND w.notify_status = ' . NOTIFY_YES . ' AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') AND u.user_id = w.user_id'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { - $notify_rows[$row['user_id']] = array( - 'user_id' => $row['user_id'], + $notify_user_id = (int) $row['user_id']; + $notify_rows[$notify_user_id] = array( + 'user_id' => $notify_user_id, 'username' => $row['username'], 'user_email' => $row['user_email'], 'user_jabber' => $row['user_jabber'], @@ -1219,30 +1224,29 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id 'method' => $row['user_notify_type'], 'allowed' => false ); + + // Add users who have been already notified to ignore list + $sql_ignore_users[$notify_user_id] = $notify_user_id; } $db->sql_freeresult($result); // forum notification is sent to those not already receiving topic notifications if ($topic_notification) { - if (sizeof($notify_rows)) - { - $sql_ignore_users .= ', ' . implode(', ', array_keys($notify_rows)); - } - $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u WHERE fw.forum_id = $forum_id - AND fw.user_id NOT IN ($sql_ignore_users) - AND fw.notify_status = " . NOTIFY_YES . ' + AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . ' + AND fw.notify_status = ' . NOTIFY_YES . ' AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') AND u.user_id = fw.user_id'; $result = $db->sql_query($sql); while ($row = $db->sql_fetchrow($result)) { - $notify_rows[$row['user_id']] = array( - 'user_id' => $row['user_id'], + $notify_user_id = (int) $row['user_id']; + $notify_rows[$notify_user_id] = array( + 'user_id' => $notify_user_id, 'username' => $row['username'], 'user_email' => $row['user_email'], 'user_jabber' => $row['user_jabber'], @@ -1273,7 +1277,6 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id } } - // Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;) $msg_users = $delete_ids = $update_notification = array(); foreach ($notify_rows as $user_id => $row) @@ -1286,6 +1289,20 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id { $msg_users[] = $row; $update_notification[$row['notify_type']][] = $row['user_id']; + + /* + * We also update the forums watch table for this user when we are + * sending out a topic notification to prevent sending out another + * notification in case this user is also subscribed to the forum + * this topic was posted in. + * Since an UPDATE query is used, this has no effect on users only + * subscribed to the topic (i.e. no row is created) and should not + * be a performance issue. + */ + if ($row['notify_type'] === 'topic') + { + $update_notification['forum'][] = $row['user_id']; + } } } unset($notify_rows); @@ -2624,7 +2641,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u * - 'topic_last_post_subject' * - 'topic_last_poster_name' * - 'topic_last_poster_colour' -* @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time(). +* @param int $bump_time The time at which topic was bumped, usually it is a current time as obtained via time(). * @return string An URL to the bumped topic, example: ./viewtopic.php?forum_id=1&topic_id=2&p=3#p3 */ function phpbb_bump_topic($forum_id, $topic_id, $post_data, $bump_time = false) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index c40ceb088f..b08d6e7f5c 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1084,6 +1084,205 @@ function delete_pm($user_id, $msg_ids, $folder_id) } /** +* Delete all PM(s) for a given user and delete the ones without references +* +* @param int $user_id ID of the user whose private messages we want to delete +* +* @return boolean False if there were no pms found, true otherwise. +*/ +function phpbb_delete_user_pms($user_id) +{ + global $db, $user, $phpbb_root_path, $phpEx; + + $user_id = (int) $user_id; + + if (!$user_id) + { + return false; + } + + // Get PM Information for later deleting + // The two queries where split, so we can use our indexes + $undelivered_msg = $delete_ids = array(); + + // Part 1: get PMs the user received + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $msg_id = (int) $row['msg_id']; + $delete_ids[$msg_id] = $msg_id; + } + $db->sql_freeresult($result); + + // Part 2: get PMs the user sent, but have yet to be received + // We cannot simply delete them. First we have to check, + // whether another user already received and read the message. + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE author_id = ' . $user_id . ' + AND folder_id = ' . PRIVMSGS_NO_BOX; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $msg_id = (int) $row['msg_id']; + $undelivered_msg[$msg_id] = $msg_id; + } + $db->sql_freeresult($result); + + if (empty($delete_ids) && empty($undelivered_msg)) + { + return false; + } + + $db->sql_transaction('begin'); + + if (!empty($undelivered_msg)) + { + // A pm is delivered, if for any recipient the message was moved + // from their NO_BOX to another folder. We do not delete such + // messages, but only delete them for users, who have not yet + // received them. + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE author_id = ' . $user_id . ' + AND folder_id <> ' . PRIVMSGS_NO_BOX . ' + AND folder_id <> ' . PRIVMSGS_OUTBOX . ' + AND folder_id <> ' . PRIVMSGS_SENTBOX; + $result = $db->sql_query($sql); + + $delivered_msg = array(); + while ($row = $db->sql_fetchrow($result)) + { + $msg_id = (int) $row['msg_id']; + $delivered_msg[$msg_id] = $msg_id; + unset($undelivered_msg[$msg_id]); + } + $db->sql_freeresult($result); + + $undelivered_user = array(); + + // Count the messages we delete, so we can correct the user pm data + $sql = 'SELECT user_id, COUNT(msg_id) as num_undelivered_privmsgs + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE author_id = ' . $user_id . ' + AND folder_id = ' . PRIVMSGS_NO_BOX . ' + AND ' . $db->sql_in_set('msg_id', array_merge($undelivered_msg, $delivered_msg)) . ' + GROUP BY user_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $num_pms = (int) $row['num_undelivered_privmsgs']; + $undelivered_user[$num_pms][] = (int) $row['user_id']; + + if (sizeof($undelivered_user[$num_pms]) > 50) + { + // If there are too many users affected the query might get + // too long, so we update the value for the first bunch here. + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ', + user_unread_privmsg = user_unread_privmsg - ' . $num_pms . ' + WHERE ' . $db->sql_in_set('user_id', $undelivered_user[$num_pms]); + $db->sql_query($sql); + unset($undelivered_user[$num_pms]); + } + } + $db->sql_freeresult($result); + + foreach ($undelivered_user as $num_pms => $undelivered_user_set) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_new_privmsg = user_new_privmsg - ' . $num_pms . ', + user_unread_privmsg = user_unread_privmsg - ' . $num_pms . ' + WHERE ' . $db->sql_in_set('user_id', $undelivered_user_set); + $db->sql_query($sql); + } + + if (!empty($delivered_msg)) + { + $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE folder_id = ' . PRIVMSGS_NO_BOX . ' + AND ' . $db->sql_in_set('msg_id', $delivered_msg); + $db->sql_query($sql); + } + + if (!empty($undelivered_msg)) + { + $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); + $db->sql_query($sql); + } + } + + // Reset the user's pm count to 0 + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_new_privmsg = 0, + user_unread_privmsg = 0 + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + + // Delete private message data of the user + $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . (int) $user_id; + $db->sql_query($sql); + + if (!empty($delete_ids)) + { + // Now we have to check which messages we can delete completely + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $delete_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + unset($delete_ids[$row['msg_id']]); + } + $db->sql_freeresult($result); + + if (!empty($delete_ids)) + { + // Check if there are any attachments we need to remove + if (!function_exists('delete_attachments')) + { + include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + } + + delete_attachments('message', $delete_ids, false); + + $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' + WHERE ' . $db->sql_in_set('msg_id', $delete_ids); + $db->sql_query($sql); + } + } + + // Set the remaining author id to anonymous + // This way users are still able to read messages from users being removed + $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' + SET author_id = ' . ANONYMOUS . ' + WHERE author_id = ' . $user_id; + $db->sql_query($sql); + + $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' + SET author_id = ' . ANONYMOUS . ' + WHERE author_id = ' . $user_id; + $db->sql_query($sql); + + $db->sql_transaction('commit'); + + return true; +} + +/** * Rebuild message header */ function rebuild_header($check_ary) @@ -1362,12 +1561,6 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) while ($row = $db->sql_fetchrow($result)) { - // Additionally, do not include the sender if he is in the group he wants to send to. ;) - if ($row['user_id'] === $user->data['user_id']) - { - continue; - } - $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; $recipients[$row['user_id']] = $field; } @@ -1622,6 +1815,7 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i $subject = censor_text($subject); + // Exclude guests, current user and banned users from notifications unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]); if (!sizeof($recipients)) @@ -1629,18 +1823,12 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i return; } - // Get banned User ID's - $sql = 'SELECT ban_userid - FROM ' . BANLIST_TABLE . ' - WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . ' - AND ban_exclude = 0'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) + if (!function_exists('phpbb_get_banned_user_ids')) { - unset($recipients[$row['ban_userid']]); + include($phpbb_root_path . 'includes/functions_user.' . $phpEx); } - $db->sql_freeresult($result); + $banned_users = phpbb_get_banned_user_ids(array_keys($recipients)); + $recipients = array_diff(array_keys($recipients), $banned_users); if (!sizeof($recipients)) { @@ -1649,7 +1837,7 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber FROM ' . USERS_TABLE . ' - WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients))); + WHERE ' . $db->sql_in_set('user_id', $recipients); $result = $db->sql_query($sql); $msg_list_ary = array(); diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index 1eae2a9ad6..8573533c2c 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -122,7 +122,7 @@ class custom_profile case FIELD_BOOL: $field_value = (bool) $field_value; - + if (!$field_value && $field_data['field_required']) { return 'FIELD_REQUIRED'; @@ -134,7 +134,7 @@ class custom_profile { return false; } - + $field_value = (int) $field_value; if ($field_value < $field_data['field_minlen']) @@ -456,6 +456,8 @@ class custom_profile $user_fields = array(); + $user_ids = $user_id; + // Go through the fields in correct order foreach (array_keys($this->profile_cache) as $used_ident) { @@ -464,6 +466,15 @@ class custom_profile $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident]; $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; } + + foreach ($user_ids as $user_id) + { + if (!isset($user_fields[$user_id][$used_ident]) && $this->profile_cache[$used_ident]['field_show_novalue']) + { + $user_fields[$user_id][$used_ident]['value'] = ''; + $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; + } + } } return $user_fields; @@ -521,7 +532,7 @@ class custom_profile switch ($this->profile_types[$field_type]) { case 'int': - if ($value === '') + if ($value === '' && !$ident_ary['data']['field_show_novalue']) { return NULL; } @@ -530,7 +541,7 @@ class custom_profile case 'string': case 'text': - if (!$value) + if (!$value && !$ident_ary['data']['field_show_novalue']) { return NULL; } @@ -548,7 +559,7 @@ class custom_profile $month = (isset($date[1])) ? (int) $date[1] : 0; $year = (isset($date[2])) ? (int) $date[2] : 0; - if (!$day && !$month && !$year) + if (!$day && !$month && !$year && !$ident_ary['data']['field_show_novalue']) { return NULL; } @@ -571,7 +582,7 @@ class custom_profile $this->get_option_lang($field_id, $lang_id, FIELD_DROPDOWN, false); } - if ($value == $ident_ary['data']['field_novalue']) + if ($value == $ident_ary['data']['field_novalue'] && !$ident_ary['data']['field_show_novalue']) { return NULL; } @@ -581,7 +592,14 @@ class custom_profile // User not having a value assigned if (!isset($this->options_lang[$field_id][$lang_id][$value])) { - return NULL; + if ($ident_ary['data']['field_show_novalue']) + { + $value = $ident_ary['data']['field_novalue']; + } + else + { + return NULL; + } } return $this->options_lang[$field_id][$lang_id][$value]; @@ -595,6 +613,11 @@ class custom_profile $this->get_option_lang($field_id, $lang_id, FIELD_BOOL, false); } + if (!$value && $ident_ary['data']['field_show_novalue']) + { + $value = $ident_ary['data']['field_default_value']; + } + if ($ident_ary['data']['field_length'] == 1) { return (isset($this->options_lang[$field_id][$lang_id][(int) $value])) ? $this->options_lang[$field_id][$lang_id][(int) $value] : NULL; @@ -625,10 +648,10 @@ class custom_profile $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; $user_ident = $profile_row['field_ident']; - // checkbox - only testing for isset + // checkbox - set the value to "true" if it has been set to 1 if ($profile_row['field_type'] == FIELD_BOOL && $profile_row['field_length'] == 2) { - $value = (isset($_REQUEST[$profile_row['field_ident']])) ? true : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]); + $value = (isset($_REQUEST[$profile_row['field_ident']]) && request_var($profile_row['field_ident'], $default_value) == 1) ? true : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]); } else if ($profile_row['field_type'] == FIELD_INT) { diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index d5bbd80242..73ac1df2d2 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -751,6 +751,31 @@ class fileupload $filename = $url['path']; $filesize = 0; + $remote_max_filesize = $this->max_filesize; + if (!$remote_max_filesize) + { + $max_filesize = @ini_get('upload_max_filesize'); + + if (!empty($max_filesize)) + { + $unit = strtolower(substr($max_filesize, -1, 1)); + $remote_max_filesize = (int) $max_filesize; + + switch ($unit) + { + case 'g': + $remote_max_filesize *= 1024; + // no break + case 'm': + $remote_max_filesize *= 1024; + // no break + case 'k': + $remote_max_filesize *= 1024; + // no break + } + } + } + $errno = 0; $errstr = ''; @@ -779,9 +804,9 @@ class fileupload $block = @fread($fsock, 1024); $filesize += strlen($block); - if ($this->max_filesize && $filesize > $this->max_filesize) + if ($remote_max_filesize && $filesize > $remote_max_filesize) { - $max_filesize = get_formatted_filesize($this->max_filesize, false); + $max_filesize = get_formatted_filesize($remote_max_filesize, false); $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit'])); return $file; @@ -807,9 +832,9 @@ class fileupload { $length = (int) str_replace('content-length: ', '', strtolower($line)); - if ($length && $length > $this->max_filesize) + if ($remote_max_filesize && $length && $length > $remote_max_filesize) { - $max_filesize = get_formatted_filesize($this->max_filesize, false); + $max_filesize = get_formatted_filesize($remote_max_filesize, false); $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit'])); return $file; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 6b5cca8abb..5a6a0b4a05 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -528,62 +528,12 @@ function user_delete($mode, $user_id, $post_username = false) WHERE session_user_id = ' . $user_id; $db->sql_query($sql); - // Remove any undelivered mails... - $sql = 'SELECT msg_id, user_id - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE author_id = ' . $user_id . ' - AND folder_id = ' . PRIVMSGS_NO_BOX; - $result = $db->sql_query($sql); - - $undelivered_msg = $undelivered_user = array(); - while ($row = $db->sql_fetchrow($result)) - { - $undelivered_msg[] = $row['msg_id']; - $undelivered_user[$row['user_id']][] = true; - } - $db->sql_freeresult($result); - - if (sizeof($undelivered_msg)) - { - $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' - WHERE ' . $db->sql_in_set('msg_id', $undelivered_msg); - $db->sql_query($sql); - } - - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE author_id = ' . $user_id . ' - AND folder_id = ' . PRIVMSGS_NO_BOX; - $db->sql_query($sql); - - // Delete all to-information - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE user_id = ' . $user_id; - $db->sql_query($sql); - - // Set the remaining author id to anonymous - this way users are still able to read messages from users being removed - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET author_id = ' . ANONYMOUS . ' - WHERE author_id = ' . $user_id; - $db->sql_query($sql); - - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET author_id = ' . ANONYMOUS . ' - WHERE author_id = ' . $user_id; - $db->sql_query($sql); - - foreach ($undelivered_user as $_user_id => $ary) + // Clean the private messages tables from the user + if (!function_exists('phpbb_delete_user_pms')) { - if ($_user_id == $user_id) - { - continue; - } - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_new_privmsg = user_new_privmsg - ' . sizeof($ary) . ', - user_unread_privmsg = user_unread_privmsg - ' . sizeof($ary) . ' - WHERE user_id = ' . $_user_id; - $db->sql_query($sql); + include($phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx); } + phpbb_delete_user_pms($user_id); $db->sql_transaction('commit'); @@ -1949,6 +1899,27 @@ function validate_jabber($jid) } /** +* Verifies whether a style ID corresponds to an active style. +* +* @param int $style_id The style_id of a style which should be checked if activated or not. +* @return boolean +*/ +function phpbb_style_is_active($style_id) +{ + global $db; + + $sql = 'SELECT style_active + FROM ' . STYLES_TABLE . ' + WHERE style_id = '. (int) $style_id; + $result = $db->sql_query($sql); + + $style_is_active = (bool) $db->sql_fetchfield('style_active'); + $db->sql_freeresult($result); + + return $style_is_active; +} + +/** * Remove avatar */ function avatar_delete($mode, $row, $clean_db = false) @@ -3587,4 +3558,37 @@ function remove_newly_registered($user_id, $user_data = false) return $user_data['group_id']; } +/** +* Gets user ids of currently banned registered users. +* +* @param array $user_ids Array of users' ids to check for banning, +* leave empty to get complete list of banned ids +* @return array Array of banned users' ids if any, empty array otherwise +*/ +function phpbb_get_banned_user_ids($user_ids = array()) +{ + global $db; + + $sql_user_ids = (!empty($user_ids)) ? $db->sql_in_set('ban_userid', $user_ids) : 'ban_userid <> 0'; + + // Get banned User ID's + // Ignore stale bans which were not wiped yet + $banned_ids_list = array(); + $sql = 'SELECT ban_userid + FROM ' . BANLIST_TABLE . " + WHERE $sql_user_ids + AND ban_exclude <> 1 + AND (ban_end > " . time() . ' + OR ban_end = 0)'; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $user_id = (int) $row['ban_userid']; + $banned_ids_list[$user_id] = $user_id; + } + $db->sql_freeresult($result); + + return $banned_ids_list; +} + ?>
\ No newline at end of file diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index d7cc1e795a..7d4edaf362 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -50,6 +50,16 @@ function mcp_topic_view($id, $mode, $action) $submitted_id_list = request_var('post_ids', array(0)); $checked_ids = $post_id_list = request_var('post_id_list', array(0)); + // Resync Topic? + if ($action == 'resync') + { + if (!function_exists('mcp_resync_topics')) + { + include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx); + } + mcp_resync_topics(array($topic_id)); + } + // Split Topic? if ($action == 'split_all' || $action == 'split_beyond') { @@ -320,6 +330,7 @@ function mcp_topic_view($id, $mode, $action) 'S_CAN_APPROVE' => ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false, 'S_CAN_LOCK' => ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false, 'S_CAN_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? true : false, + 'S_CAN_SYNC' => $auth->acl_get('m_', $topic_info['forum_id']), 'S_REPORT_VIEW' => ($action == 'reports') ? true : false, 'S_MERGE_VIEW' => ($action == 'merge') ? true : false, 'S_SPLIT_VIEW' => ($action == 'split') ? true : false, diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php index 63e5b19155..1016204ff8 100644 --- a/phpBB/includes/mcp/mcp_warn.php +++ b/phpBB/includes/mcp/mcp_warn.php @@ -308,7 +308,7 @@ class mcp_warn include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - $rank_title = $rank_img = ''; + get_user_rank($user_row['user_rank'], $user_row['user_posts'], $rank_title, $rank_img, $rank_img_src); $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); $template->assign_vars(array( @@ -413,7 +413,7 @@ class mcp_warn include($phpbb_root_path . 'includes/functions_display.' . $phpEx); } - $rank_title = $rank_img = ''; + get_user_rank($user_row['user_rank'], $user_row['user_posts'], $rank_title, $rank_img, $rank_img_src); $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); // OK, they didn't submit a warning so lets build the page for them to do so diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php index 29cdd8ee9a..bd4c003397 100644 --- a/phpBB/includes/search/fulltext_mysql.php +++ b/phpBB/includes/search/fulltext_mysql.php @@ -707,7 +707,7 @@ class fulltext_mysql extends search_backend */ function index_remove($post_ids, $author_ids, $forum_ids) { - $this->destroy_cache(array(), $author_ids); + $this->destroy_cache(array(), array_unique($author_ids)); } /** @@ -747,7 +747,7 @@ class fulltext_mysql extends search_backend { if ($db->sql_layer == 'mysqli' || version_compare($db->sql_server_info(true), '4.1.3', '>=')) { - //$alter[] = 'MODIFY post_subject varchar(100) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; + $alter[] = 'MODIFY post_subject varchar(255) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; } else { @@ -896,11 +896,7 @@ class fulltext_mysql extends search_backend } $db->sql_freeresult($result); - $sql = 'SELECT COUNT(post_id) as total_posts - FROM ' . POSTS_TABLE; - $result = $db->sql_query($sql); - $this->stats['total_posts'] = (int) $db->sql_fetchfield('total_posts'); - $db->sql_freeresult($result); + $this->stats['total_posts'] = empty($this->stats) ? 0 : $db->get_estimated_row_count(POSTS_TABLE); } /** diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index 727e3aaffb..dc961f3c8a 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -1334,7 +1334,7 @@ class fulltext_native extends search_backend $db->sql_query($sql); } - $this->destroy_cache(array_unique($word_texts), $author_ids); + $this->destroy_cache(array_unique($word_texts), array_unique($author_ids)); } /** @@ -1461,17 +1461,8 @@ class fulltext_native extends search_backend { global $db; - $sql = 'SELECT COUNT(*) as total_words - FROM ' . SEARCH_WORDLIST_TABLE; - $result = $db->sql_query($sql); - $this->stats['total_words'] = (int) $db->sql_fetchfield('total_words'); - $db->sql_freeresult($result); - - $sql = 'SELECT COUNT(*) as total_matches - FROM ' . SEARCH_WORDMATCH_TABLE; - $result = $db->sql_query($sql); - $this->stats['total_matches'] = (int) $db->sql_fetchfield('total_matches'); - $db->sql_freeresult($result); + $this->stats['total_words'] = $db->get_estimated_row_count(SEARCH_WORDLIST_TABLE); + $this->stats['total_matches'] = $db->get_estimated_row_count(SEARCH_WORDMATCH_TABLE); } /** diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php index 2f20d11495..df7c8a0892 100644 --- a/phpBB/includes/search/search.php +++ b/phpBB/includes/search/search.php @@ -295,7 +295,7 @@ class search_backend $sql_where = ''; foreach ($authors as $author) { - $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors LIKE \'% ' . (int) $author . ' %\''; + $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $db->sql_like_expression($db->any_char . ' ' . (int) $author . ' ' . $db->any_char); } $sql = 'SELECT search_key diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index a894242a39..496c12a0d1 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -322,8 +322,15 @@ class session } } - // Is session_id is set or session_id is set and matches the url param if required - if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid']))) + // if no session id is set, redirect to index.php + if (defined('NEED_SID') && (!isset($_GET['sid']) || $this->session_id !== $_GET['sid'])) + { + send_status_line(401, 'Not authorized'); + redirect(append_sid("{$phpbb_root_path}index.$phpEx")); + } + + // if session id is set + if (!empty($this->session_id)) { $sql = 'SELECT u.*, s.* FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php index bbe2f127f1..cf216a65db 100644 --- a/phpBB/includes/startup.php +++ b/phpBB/includes/startup.php @@ -19,7 +19,23 @@ if (!defined('E_DEPRECATED')) { define('E_DEPRECATED', 8192); } -error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED); +$level = E_ALL & ~E_NOTICE & ~E_DEPRECATED; +if (version_compare(PHP_VERSION, '5.4.0-dev', '>=')) +{ + // PHP 5.4 adds E_STRICT to E_ALL. + // Our utf8 normalizer triggers E_STRICT output on PHP 5.4. + // Unfortunately it cannot be made E_STRICT-clean while + // continuing to work on PHP 4. + // Therefore, in phpBB 3.0.x we disable E_STRICT on PHP 5.4+, + // while phpBB 3.1 will fix utf8 normalizer. + // E_STRICT is defined starting with PHP 5 + if (!defined('E_STRICT')) + { + define('E_STRICT', 2048); + } + $level &= ~E_STRICT; +} +error_reporting($level); /* * Remove variables created by register_globals from the global scope diff --git a/phpBB/includes/ucp/ucp_pm_options.php b/phpBB/includes/ucp/ucp_pm_options.php index 58c2d087c8..efa390ed87 100644 --- a/phpBB/includes/ucp/ucp_pm_options.php +++ b/phpBB/includes/ucp/ucp_pm_options.php @@ -328,10 +328,23 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit trigger_error('RULE_ALREADY_DEFINED'); } + // Prevent users from flooding the rules table + $sql = 'SELECT COUNT(rule_id) AS num_rules + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . (int) $user->data['user_id']; + $result = $db->sql_query($sql); + $num_rules = (int) $db->sql_fetchfield('num_rules'); + $db->sql_freeresult($result); + + if ($num_rules >= 5000) + { + trigger_error('RULE_LIMIT_REACHED'); + } + $sql = 'INSERT INTO ' . PRIVMSGS_RULES_TABLE . ' ' . $db->sql_build_array('INSERT', $rule_ary); $db->sql_query($sql); - // Update users message rules + // Set the user_message_rules bit $sql = 'UPDATE ' . USERS_TABLE . ' SET user_message_rules = 1 WHERE user_id = ' . $user->data['user_id']; @@ -378,7 +391,7 @@ function message_options($id, $mode, $global_privmsgs_rules, $global_rule_condit $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - // Update users message rules + // Unset the user_message_rules bit if (!$row) { $sql = 'UPDATE ' . USERS_TABLE . ' diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index 13167b2b3d..17d7d23f02 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -61,7 +61,14 @@ class ucp_prefs if ($submit) { - $data['style'] = ($config['override_user_style']) ? $config['default_style'] : $data['style']; + if ($config['override_user_style']) + { + $data['style'] = (int) $config['default_style']; + } + else if (!phpbb_style_is_active($data['style'])) + { + $data['style'] = (int) $user->data['user_style']; + } $error = validate_data($data, array( 'dateformat' => array('string', false, 1, 30), |