aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acm/acm_apc.php2
-rw-r--r--phpBB/includes/acm/acm_eaccelerator.php4
-rw-r--r--phpBB/includes/acm/acm_memcache.php4
-rw-r--r--phpBB/includes/acm/acm_redis.php4
-rw-r--r--phpBB/includes/acm/acm_wincache.php2
-rw-r--r--phpBB/includes/acm/acm_xcache.php2
-rw-r--r--phpBB/includes/acp/acp_database.php12
-rw-r--r--phpBB/includes/acp/acp_main.php4
-rw-r--r--phpBB/includes/acp/acp_profile.php6
-rw-r--r--phpBB/includes/acp/acp_styles.php6
-rw-r--r--phpBB/includes/acp/acp_users.php8
-rw-r--r--phpBB/includes/auth/auth_ldap.php6
-rw-r--r--phpBB/includes/captcha/captcha_non_gd.php2
-rw-r--r--phpBB/includes/constants.php2
-rw-r--r--phpBB/includes/db/dbal.php55
-rw-r--r--phpBB/includes/db/firebird.php43
-rw-r--r--phpBB/includes/db/mssql.php74
-rw-r--r--phpBB/includes/db/mssql_odbc.php91
-rw-r--r--phpBB/includes/db/mssqlnative.php81
-rw-r--r--phpBB/includes/db/mysql.php45
-rw-r--r--phpBB/includes/db/mysqli.php32
-rw-r--r--phpBB/includes/db/oracle.php53
-rw-r--r--phpBB/includes/db/sqlite.php41
-rw-r--r--phpBB/includes/functions.php62
-rw-r--r--phpBB/includes/functions_admin.php20
-rw-r--r--phpBB/includes/functions_database_helper.php206
-rw-r--r--phpBB/includes/functions_install.php53
-rw-r--r--phpBB/includes/functions_messenger.php13
-rw-r--r--phpBB/includes/functions_posting.php17
-rw-r--r--phpBB/includes/functions_privmsgs.php205
-rw-r--r--phpBB/includes/functions_profile_fields.php42
-rw-r--r--phpBB/includes/functions_upload.php33
-rw-r--r--phpBB/includes/functions_user.php58
-rw-r--r--phpBB/includes/mcp/mcp_forum.php15
-rw-r--r--phpBB/includes/mcp/mcp_main.php22
-rw-r--r--phpBB/includes/mcp/mcp_pm_reports.php1
-rw-r--r--phpBB/includes/mcp/mcp_topic.php56
-rw-r--r--phpBB/includes/questionnaire/questionnaire.php2
-rw-r--r--phpBB/includes/search/fulltext_mysql.php2
-rw-r--r--phpBB/includes/session.php11
-rw-r--r--phpBB/includes/ucp/info/ucp_profile.php2
-rw-r--r--phpBB/includes/ucp/ucp_pm_compose.php3
-rw-r--r--phpBB/includes/ucp/ucp_pm_options.php17
-rw-r--r--phpBB/includes/ucp/ucp_prefs.php32
44 files changed, 1126 insertions, 325 deletions
diff --git a/phpBB/includes/acm/acm_apc.php b/phpBB/includes/acm/acm_apc.php
index 1a487f94ad..205353d3a5 100644
--- a/phpBB/includes/acm/acm_apc.php
+++ b/phpBB/includes/acm/acm_apc.php
@@ -33,7 +33,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
diff --git a/phpBB/includes/acm/acm_eaccelerator.php b/phpBB/includes/acm/acm_eaccelerator.php
index 645067c199..ecec3ac9a5 100644
--- a/phpBB/includes/acm/acm_eaccelerator.php
+++ b/phpBB/includes/acm/acm_eaccelerator.php
@@ -37,7 +37,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
@@ -54,7 +54,7 @@ class acm extends acm_memory
/**
* Perform cache garbage collection
*
- * @return void
+ * @return null
*/
function tidy()
{
diff --git a/phpBB/includes/acm/acm_memcache.php b/phpBB/includes/acm/acm_memcache.php
index e54fa36c38..70bc219952 100644
--- a/phpBB/includes/acm/acm_memcache.php
+++ b/phpBB/includes/acm/acm_memcache.php
@@ -71,7 +71,7 @@ class acm extends acm_memory
/**
* Unload the cache resources
*
- * @return void
+ * @return null
*/
function unload()
{
@@ -83,7 +83,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
diff --git a/phpBB/includes/acm/acm_redis.php b/phpBB/includes/acm/acm_redis.php
index 41533eaacb..dc11ca7768 100644
--- a/phpBB/includes/acm/acm_redis.php
+++ b/phpBB/includes/acm/acm_redis.php
@@ -80,7 +80,7 @@ class acm extends acm_memory
/**
* Unload the cache resources
*
- * @return void
+ * @return null
*/
function unload()
{
@@ -92,7 +92,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
diff --git a/phpBB/includes/acm/acm_wincache.php b/phpBB/includes/acm/acm_wincache.php
index 0501ab74c5..7faba4f5b6 100644
--- a/phpBB/includes/acm/acm_wincache.php
+++ b/phpBB/includes/acm/acm_wincache.php
@@ -32,7 +32,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
diff --git a/phpBB/includes/acm/acm_xcache.php b/phpBB/includes/acm/acm_xcache.php
index d0a614660c..e3d83f8bfa 100644
--- a/phpBB/includes/acm/acm_xcache.php
+++ b/phpBB/includes/acm/acm_xcache.php
@@ -48,7 +48,7 @@ class acm extends acm_memory
/**
* Purge cache data
*
- * @return void
+ * @return null
*/
function purge()
{
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 e529ae0e5a..ee7bd4dc45 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,7 +398,7 @@ class acp_main
// Version check
$user->add_lang('install');
- if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.2', '<'))
+ if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.3', '<'))
{
$template->assign_vars(array(
'S_PHP_VERSION_OLD' => true,
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index a591474fce..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',
@@ -757,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,
@@ -1073,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_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_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/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php
index f82896f628..2adf909b96 100644
--- a/phpBB/includes/captcha/captcha_non_gd.php
+++ b/phpBB/includes/captcha/captcha_non_gd.php
@@ -119,7 +119,7 @@ class captcha
$new_line = '';
$end = strlen($scanline) - ceil($width/2);
- for ($i = floor($width/2); $i < $end; $i++)
+ for ($i = (int) floor($width / 2); $i < $end; $i++)
{
$pixel = ord($scanline{$i});
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/dbal.php b/phpBB/includes/db/dbal.php
index 5d456c2ff0..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
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..2dd95c2508 100644
--- a/phpBB/includes/db/mssql.php
+++ b/phpBB/includes/db/mssql.php
@@ -25,11 +25,19 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
*/
class dbal_mssql extends dbal
{
+ var $connect_error = '';
+
/**
* Connect to server
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
+ if (!function_exists('mssql_connect'))
+ {
+ $this->connect_error = 'mssql_connect function does not exist, is mssql extension installed?';
+ return $this->sql_error('');
+ }
+
$this->persistency = $persistency;
$this->user = $sqluser;
$this->dbname = $database;
@@ -333,6 +341,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
*/
@@ -347,34 +363,44 @@ class dbal_mssql extends dbal
*/
function _sql_error()
{
- $error = array(
- 'message' => @mssql_get_last_message(),
- 'code' => ''
- );
-
- // Get error code number
- $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id);
- if ($result_id)
+ if (function_exists('mssql_get_last_message'))
{
- $row = @mssql_fetch_assoc($result_id);
- $error['code'] = $row['code'];
- @mssql_free_result($result_id);
- }
+ $error = array(
+ 'message' => @mssql_get_last_message(),
+ 'code' => '',
+ );
- // Get full error message if possible
- $sql = 'SELECT CAST(description as varchar(255)) as message
- FROM master.dbo.sysmessages
- WHERE error = ' . $error['code'];
- $result_id = @mssql_query($sql);
-
- if ($result_id)
- {
- $row = @mssql_fetch_assoc($result_id);
- if (!empty($row['message']))
+ // Get error code number
+ $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id);
+ if ($result_id)
{
- $error['message'] .= '<br />' . $row['message'];
+ $row = @mssql_fetch_assoc($result_id);
+ $error['code'] = $row['code'];
+ @mssql_free_result($result_id);
}
- @mssql_free_result($result_id);
+
+ // Get full error message if possible
+ $sql = 'SELECT CAST(description as varchar(255)) as message
+ FROM master.dbo.sysmessages
+ WHERE error = ' . $error['code'];
+ $result_id = @mssql_query($sql);
+
+ if ($result_id)
+ {
+ $row = @mssql_fetch_assoc($result_id);
+ if (!empty($row['message']))
+ {
+ $error['message'] .= '<br />' . $row['message'];
+ }
+ @mssql_free_result($result_id);
+ }
+ }
+ else
+ {
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
+ );
}
return $error;
diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php
index 75a080b1b7..04501cce8b 100644
--- a/phpBB/includes/db/mssql_odbc.php
+++ b/phpBB/includes/db/mssql_odbc.php
@@ -32,6 +32,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
class dbal_mssql_odbc extends dbal
{
var $last_query_text = '';
+ var $connect_error = '';
/**
* Connect to server
@@ -68,7 +69,24 @@ class dbal_mssql_odbc extends dbal
@ini_set('odbc.defaultlrl', $max_size);
}
- $this->db_connect_id = ($this->persistency) ? @odbc_pconnect($this->server, $this->user, $sqlpassword) : @odbc_connect($this->server, $this->user, $sqlpassword);
+ if ($this->persistency)
+ {
+ if (!function_exists('odbc_pconnect'))
+ {
+ $this->connect_error = 'odbc_pconnect function does not exist, is odbc extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @odbc_pconnect($this->server, $this->user, $sqlpassword);
+ }
+ else
+ {
+ if (!function_exists('odbc_connect'))
+ {
+ $this->connect_error = 'odbc_connect function does not exist, is odbc extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @odbc_connect($this->server, $this->user, $sqlpassword);
+ }
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
@@ -256,49 +274,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 +329,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
*/
@@ -377,10 +360,22 @@ class dbal_mssql_odbc extends dbal
*/
function _sql_error()
{
- return array(
- 'message' => @odbc_errormsg(),
- 'code' => @odbc_error()
- );
+ if (function_exists('odbc_errormsg'))
+ {
+ $error = array(
+ 'message' => @odbc_errormsg(),
+ 'code' => @odbc_error(),
+ );
+ }
+ else
+ {
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
+ );
+ }
+
+ return $error;
}
/**
diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php
index 7fbc374e77..b91372ac61 100644
--- a/phpBB/includes/db/mssqlnative.php
+++ b/phpBB/includes/db/mssqlnative.php
@@ -199,16 +199,18 @@ class dbal_mssqlnative extends dbal
var $m_insert_id = NULL;
var $last_query_text = '';
var $query_options = array();
+ var $connect_error = '';
/**
* Connect to server
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
- # Test for driver support, to avoid suppressed fatal error
+ // Test for driver support, to avoid suppressed fatal error
if (!function_exists('sqlsrv_connect'))
{
- trigger_error('Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx\n', E_USER_ERROR);
+ $this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx';
+ return $this->sql_error('');
}
//set up connection variables
@@ -219,7 +221,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 +437,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 +494,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
*/
@@ -525,31 +516,43 @@ class dbal_mssqlnative extends dbal
*/
function _sql_error()
{
- $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS);
- $error_message = '';
- $code = 0;
-
- if ($errors != null)
+ if (function_exists('sqlsrv_errors'))
{
- foreach ($errors as $error)
+ $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS);
+ $error_message = '';
+ $code = 0;
+
+ if ($errors != null)
{
- $error_message .= "SQLSTATE: ".$error[ 'SQLSTATE']."\n";
- $error_message .= "code: ".$error[ 'code']."\n";
- $code = $error['code'];
- $error_message .= "message: ".$error[ 'message']."\n";
+ foreach ($errors as $error)
+ {
+ $error_message .= "SQLSTATE: " . $error[ 'SQLSTATE'] . "\n";
+ $error_message .= "code: " . $error[ 'code'] . "\n";
+ $code = $error['code'];
+ $error_message .= "message: " . $error[ 'message'] . "\n";
+ }
+ $this->last_error_result = $error_message;
+ $error = $this->last_error_result;
+ }
+ else
+ {
+ $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
}
- $this->last_error_result = $error_message;
- $error = $this->last_error_result;
+
+ $error = array(
+ 'message' => $error,
+ 'code' => $code,
+ );
}
else
{
- $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
+ );
}
- return array(
- 'message' => $error,
- 'code' => $code,
- );
+ return $error;
}
/**
diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php
index 1ccb785150..252cb20bd4 100644
--- a/phpBB/includes/db/mysql.php
+++ b/phpBB/includes/db/mysql.php
@@ -30,6 +30,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
class dbal_mysql extends dbal
{
var $multi_insert = true;
+ var $connect_error = '';
/**
* Connect to server
@@ -44,7 +45,24 @@ class dbal_mysql extends dbal
$this->sql_layer = 'mysql4';
- $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link);
+ if ($this->persistency)
+ {
+ if (!function_exists('mysql_pconnect'))
+ {
+ $this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword);
+ }
+ else
+ {
+ if (!function_exists('mysql_connect'))
+ {
+ $this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link);
+ }
if ($this->db_connect_id && $this->dbname != '')
{
@@ -419,18 +437,29 @@ class dbal_mysql extends dbal
*/
function _sql_error()
{
- if (!$this->db_connect_id)
+ if ($this->db_connect_id)
+ {
+ $error = array(
+ 'message' => @mysql_error($this->db_connect_id),
+ 'code' => @mysql_errno($this->db_connect_id),
+ );
+ }
+ else if (function_exists('mysql_error'))
{
- return array(
+ $error = array(
'message' => @mysql_error(),
- 'code' => @mysql_errno()
+ 'code' => @mysql_errno(),
+ );
+ }
+ else
+ {
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
);
}
- return array(
- 'message' => @mysql_error($this->db_connect_id),
- 'code' => @mysql_errno($this->db_connect_id)
- );
+ return $error;
}
/**
diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php
index a311b8cda6..69f1d26a40 100644
--- a/phpBB/includes/db/mysqli.php
+++ b/phpBB/includes/db/mysqli.php
@@ -27,12 +27,19 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
class dbal_mysqli extends dbal
{
var $multi_insert = true;
+ var $connect_error = '';
/**
* Connect to server
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false)
{
+ if (!function_exists('mysqli_connect'))
+ {
+ $this->connect_error = 'mysqli_connect function does not exist, is mysqli extension installed?';
+ return $this->sql_error('');
+ }
+
// Mysqli extension supports persistent connection since PHP 5.3.0
$this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false;
$this->user = $sqluser;
@@ -416,18 +423,29 @@ class dbal_mysqli extends dbal
*/
function _sql_error()
{
- if (!$this->db_connect_id)
+ if ($this->db_connect_id)
+ {
+ $error = array(
+ 'message' => @mysqli_error($this->db_connect_id),
+ 'code' => @mysqli_errno($this->db_connect_id)
+ );
+ }
+ else if (function_exists('mysqli_connect_error'))
{
- return array(
+ $error = array(
'message' => @mysqli_connect_error(),
- 'code' => @mysqli_connect_errno()
+ 'code' => @mysqli_connect_errno(),
+ );
+ }
+ else
+ {
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
);
}
- return array(
- 'message' => @mysqli_error($this->db_connect_id),
- 'code' => @mysqli_errno($this->db_connect_id)
- );
+ return $error;
}
/**
diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php
index 62b36aa8bf..4a7a4ecc8c 100644
--- a/phpBB/includes/db/oracle.php
+++ b/phpBB/includes/db/oracle.php
@@ -25,6 +25,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
class dbal_oracle extends dbal
{
var $last_query_text = '';
+ var $connect_error = '';
/**
* Connect to server
@@ -48,7 +49,33 @@ class dbal_oracle extends dbal
$connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database;
}
- $this->db_connect_id = ($new_link) ? @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8') : (($this->persistency) ? @ociplogon($this->user, $sqlpassword, $connect, 'UTF8') : @ocilogon($this->user, $sqlpassword, $connect, 'UTF8'));
+ if ($new_link)
+ {
+ if (!function_exists('ocinlogon'))
+ {
+ $this->connect_error = 'ocinlogon function does not exist, is oci extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8');
+ }
+ else if ($this->persistency)
+ {
+ if (!function_exists('ociplogon'))
+ {
+ $this->connect_error = 'ociplogon function does not exist, is oci extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8');
+ }
+ else
+ {
+ if (!function_exists('ocilogon'))
+ {
+ $this->connect_error = 'ocilogon function does not exist, is oci extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8');
+ }
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
@@ -647,17 +674,27 @@ class dbal_oracle extends dbal
*/
function _sql_error()
{
- $error = @ocierror();
- $error = (!$error) ? @ocierror($this->query_result) : $error;
- $error = (!$error) ? @ocierror($this->db_connect_id) : $error;
-
- if ($error)
+ if (function_exists('ocierror'))
{
- $this->last_error_result = $error;
+ $error = @ocierror();
+ $error = (!$error) ? @ocierror($this->query_result) : $error;
+ $error = (!$error) ? @ocierror($this->db_connect_id) : $error;
+
+ if ($error)
+ {
+ $this->last_error_result = $error;
+ }
+ else
+ {
+ $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
+ }
}
else
{
- $error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
+ );
}
return $error;
diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php
index 8de72fd394..557b057cce 100644
--- a/phpBB/includes/db/sqlite.php
+++ b/phpBB/includes/db/sqlite.php
@@ -25,6 +25,8 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
*/
class dbal_sqlite extends dbal
{
+ var $connect_error = '';
+
/**
* Connect to server
*/
@@ -36,7 +38,24 @@ class dbal_sqlite extends dbal
$this->dbname = $database;
$error = '';
- $this->db_connect_id = ($this->persistency) ? @sqlite_popen($this->server, 0666, $error) : @sqlite_open($this->server, 0666, $error);
+ if ($this->persistency)
+ {
+ if (!function_exists('sqlite_popen'))
+ {
+ $this->connect_error = 'sqlite_popen function does not exist, is sqlite extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @sqlite_popen($this->server, 0666, $error);
+ }
+ else
+ {
+ if (!function_exists('sqlite_open'))
+ {
+ $this->connect_error = 'sqlite_open function does not exist, is sqlite extension installed?';
+ return $this->sql_error('');
+ }
+ $this->db_connect_id = @sqlite_open($this->server, 0666, $error);
+ }
if ($this->db_connect_id)
{
@@ -281,10 +300,22 @@ class dbal_sqlite extends dbal
*/
function _sql_error()
{
- return array(
- 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)),
- 'code' => @sqlite_last_error($this->db_connect_id)
- );
+ if (function_exists('sqlite_error_string'))
+ {
+ $error = array(
+ 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)),
+ 'code' => @sqlite_last_error($this->db_connect_id),
+ );
+ }
+ else
+ {
+ $error = array(
+ 'message' => $this->connect_error,
+ 'code' => '',
+ );
+ }
+
+ return $error;
}
/**
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index ce80dc4a66..571c863839 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -289,7 +289,8 @@ function phpbb_gmgetdate($time = false)
/**
* Return formatted string for filesizes
*
-* @param int $value filesize in bytes
+* @param mixed $value filesize in bytes
+* (non-negative number; int, float or string)
* @param bool $string_only true if language string should be returned
* @param array $allowed_units only allow these units (data array indexes)
*
@@ -301,6 +302,12 @@ function get_formatted_filesize($value, $string_only = true, $allowed_units = fa
global $user;
$available_units = array(
+ 'tb' => array(
+ 'min' => 1099511627776, // pow(2, 40)
+ 'index' => 4,
+ 'si_unit' => 'TB',
+ 'iec_unit' => 'TIB',
+ ),
'gb' => array(
'min' => 1073741824, // pow(2, 30)
'index' => 3,
@@ -1176,6 +1183,36 @@ else
}
}
+/**
+* Eliminates useless . and .. components from specified path.
+*
+* @param string $path Path to clean
+* @return string Cleaned path
+*/
+function phpbb_clean_path($path)
+{
+ $exploded = explode('/', $path);
+ $filtered = array();
+ foreach ($exploded as $part)
+ {
+ if ($part === '.' && !empty($filtered))
+ {
+ continue;
+ }
+
+ if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '..')
+ {
+ array_pop($filtered);
+ }
+ else
+ {
+ $filtered[] = $part;
+ }
+ }
+ $path = implode('/', $filtered);
+ return $path;
+}
+
if (!function_exists('htmlspecialchars_decode'))
{
/**
@@ -1918,14 +1955,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);
@@ -2705,7 +2745,7 @@ function meta_refresh($time, $url, $disable_cd_check = false)
*
* @param int $code HTTP status code
* @param string $message Message for the status code
-* @return void
+* @return null
*/
function send_status_line($code, $message)
{
@@ -2808,7 +2848,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 +3493,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\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([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\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&amp;)+@((((([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 +3958,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>&reg; Forum Software &copy; phpBB Group';
+ echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group';
echo ' </div>';
echo '</div>';
echo '</body>';
@@ -4292,7 +4332,7 @@ function phpbb_optionset($bit, $set, $data)
*
* @param array $param Parameter array, see $param_defaults array.
*
-* @return void
+* @return null
*/
function phpbb_http_login($param)
{
@@ -4738,7 +4778,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="http://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group'),
+ 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; 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..190185cfcf 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)
@@ -3327,7 +3343,7 @@ function obtain_latest_version_info($force_update = false, $warn_fail = false, $
* @param int $flag The binary flag which is OR-ed with the current column value
* @param string $sql_more This string is attached to the sql query generated to update the table.
*
- * @return void
+ * @return null
*/
function enable_bitfield_column_flag($table_name, $column_name, $flag, $sql_more = '')
{
diff --git a/phpBB/includes/functions_database_helper.php b/phpBB/includes/functions_database_helper.php
new file mode 100644
index 0000000000..664c246888
--- /dev/null
+++ b/phpBB/includes/functions_database_helper.php
@@ -0,0 +1,206 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Updates rows in given table from a set of values to a new value.
+* If this results in rows violating uniqueness constraints, the duplicate
+* rows are eliminated.
+*
+* The only supported table is bookmarks.
+*
+* @param dbal $db Database object
+* @param string $table Table on which to perform the update
+* @param string $column Column whose values to change
+* @param array $from_values An array of values that should be changed
+* @param int $to_value The new value
+* @return null
+*/
+function phpbb_update_rows_avoiding_duplicates($db, $table, $column, $from_values, $to_value)
+{
+ $sql = "SELECT $column, user_id
+ FROM $table
+ WHERE " . $db->sql_in_set($column, $from_values);
+ $result = $db->sql_query($sql);
+
+ $old_user_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $old_user_ids[$row[$column]][] = (int) $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $sql = "SELECT $column, user_id
+ FROM $table
+ WHERE $column = " . (int) $to_value;
+ $result = $db->sql_query($sql);
+
+ $new_user_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $new_user_ids[$row[$column]][] = (int) $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $queries = array();
+ foreach ($from_values as $from_value)
+ {
+ if (!isset($old_user_ids[$from_value]))
+ {
+ continue;
+ }
+ if (empty($new_user_ids))
+ {
+ $sql = "UPDATE $table
+ SET $column = " . (int) $to_value . "
+ WHERE $column = '" . $db->sql_escape($from_value) . "'";
+ $queries[] = $sql;
+ }
+ else
+ {
+ $different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]);
+ if (!empty($different_user_ids))
+ {
+ $sql = "UPDATE $table
+ SET $column = " . (int) $to_value . "
+ WHERE $column = '" . $db->sql_escape($from_value) . "'
+ AND " . $db->sql_in_set('user_id', $different_user_ids);
+ $queries[] = $sql;
+ }
+ }
+ }
+
+ if (!empty($queries))
+ {
+ $db->sql_transaction('begin');
+
+ foreach ($queries as $sql)
+ {
+ $db->sql_query($sql);
+ }
+
+ $sql = "DELETE FROM $table
+ WHERE " . $db->sql_in_set($column, $from_values);
+ $db->sql_query($sql);
+
+ $db->sql_transaction('commit');
+ }
+}
+
+/**
+* Updates rows in given table from a set of values to a new value.
+* If this results in rows violating uniqueness constraints, the duplicate
+* rows are merged respecting notify_status (0 takes precedence over 1).
+*
+* The only supported table is topics_watch.
+*
+* @param dbal $db Database object
+* @param string $table Table on which to perform the update
+* @param string $column Column whose values to change
+* @param array $from_values An array of values that should be changed
+* @param int $to_value The new value
+* @return null
+*/
+function phpbb_update_rows_avoiding_duplicates_notify_status($db, $table, $column, $from_values, $to_value)
+{
+ $sql = "SELECT $column, user_id, notify_status
+ FROM $table
+ WHERE " . $db->sql_in_set($column, $from_values);
+ $result = $db->sql_query($sql);
+
+ $old_user_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $sql = "SELECT $column, user_id
+ FROM $table
+ WHERE $column = " . (int) $to_value;
+ $result = $db->sql_query($sql);
+
+ $new_user_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $new_user_ids[$row[$column]][] = (int) $row['user_id'];
+ }
+ $db->sql_freeresult($result);
+
+ $queries = array();
+ $extra_updates = array(
+ 0 => 'notify_status = 0',
+ 1 => '',
+ );
+ foreach ($from_values as $from_value)
+ {
+ foreach ($extra_updates as $notify_status => $extra_update)
+ {
+ if (!isset($old_user_ids[$notify_status][$from_value]))
+ {
+ continue;
+ }
+ if (empty($new_user_ids))
+ {
+ $sql = "UPDATE $table
+ SET $column = " . (int) $to_value . "
+ WHERE $column = '" . $db->sql_escape($from_value) . "'";
+ $queries[] = $sql;
+ }
+ else
+ {
+ $different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]);
+ if (!empty($different_user_ids))
+ {
+ $sql = "UPDATE $table
+ SET $column = " . (int) $to_value . "
+ WHERE $column = '" . $db->sql_escape($from_value) . "'
+ AND " . $db->sql_in_set('user_id', $different_user_ids);
+ $queries[] = $sql;
+ }
+
+ if ($extra_update)
+ {
+ $same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids);
+ if (!empty($same_user_ids))
+ {
+ $sql = "UPDATE $table
+ SET $extra_update
+ WHERE $column = '" . (int) $to_value . "'
+ AND " . $db->sql_in_set('user_id', $same_user_ids);
+ $queries[] = $sql;
+ }
+ }
+ }
+ }
+ }
+
+ if (!empty($queries))
+ {
+ $db->sql_transaction('begin');
+
+ foreach ($queries as $sql)
+ {
+ $db->sql_query($sql);
+ }
+
+ $sql = "DELETE FROM $table
+ WHERE " . $db->sql_in_set($column, $from_values);
+ $db->sql_query($sql);
+
+ $db->sql_transaction('commit');
+ }
+}
diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php
index 633b2755f0..47f4eac627 100644
--- a/phpBB/includes/functions_install.php
+++ b/phpBB/includes/functions_install.php
@@ -50,15 +50,19 @@ 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,
),
+ // Note: php 5.5 alpha 2 deprecated mysql.
+ // Keep mysqli before mysql in this list.
'mysqli' => array(
'LABEL' => 'MySQL with MySQLi Extension',
'SCHEMA' => 'mysql_41',
'MODULE' => 'mysqli',
'DELIM' => ';',
+ 'COMMENTS' => 'remove_remarks',
'DRIVER' => 'mysqli',
'AVAILABLE' => true,
'2.0.x' => true,
@@ -68,6 +72,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 +82,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 +92,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 +102,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 +112,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 +122,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 +132,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 +476,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;
}
/**
@@ -519,10 +553,12 @@ function adjust_language_keys_callback($matches)
* @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)
+function phpbb_create_config_file_data($data, $dbms, $load_extensions, $debug = false, $debug_test = false)
{
$load_extensions = implode(',', $load_extensions);
@@ -559,7 +595,10 @@ function phpbb_create_config_file_data($data, $dbms, $load_extensions, $debug =
$config_data .= "// @define('DEBUG_EXTRA', true);\n";
}
- $config_data .= '?' . '>'; // Done this to prevent highlighting editors getting confused!
+ if ($debug_test)
+ {
+ $config_data .= "@define('DEBUG_TEST', true);\n";
+ }
return $config_data;
}
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 6549693333..e837811c86 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -715,14 +715,21 @@ class queue
$lock_fp = $this->lock();
- set_config('last_queue_run', time(), true);
-
- if (!file_exists($this->cache_file) || filemtime($this->cache_file) > time() - $config['queue_interval'])
+ // avoid races, check file existence once
+ $have_cache_file = file_exists($this->cache_file);
+ if (!$have_cache_file || $config['last_queue_run'] > time() - $config['queue_interval'])
{
+ if (!$have_cache_file)
+ {
+ set_config('last_queue_run', time(), true);
+ }
+
$this->unlock($lock_fp);
return;
}
+ set_config('last_queue_run', time(), true);
+
include($this->cache_file);
foreach ($this->queue_data as $object => $data_ary)
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 68b6199cf5..e5cbae0d71 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'],
@@ -1167,7 +1169,7 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id
/**
* User Notification
*/
-function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id)
+function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id, $author_name = '')
{
global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
@@ -1338,6 +1340,7 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
'USERNAME' => htmlspecialchars_decode($addr['name']),
'TOPIC_TITLE' => htmlspecialchars_decode($topic_title),
'FORUM_NAME' => htmlspecialchars_decode($forum_name),
+ 'AUTHOR_NAME' => htmlspecialchars_decode($author_name),
'U_FORUM' => generate_board_url() . "/viewforum.$phpEx?f=$forum_id",
'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=$forum_id&t=$topic_id",
@@ -1695,8 +1698,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// The variable name should be $post_approved, because it indicates if the post is approved or not
$post_approval = 1;
- // Check the permissions for post approval. Moderators are not affected.
- if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id']))
+ // Check the permissions for post approval.
+ // Moderators must go through post approval like ordinary users.
+ if (!$auth->acl_get('f_noapprove', $data['forum_id']))
{
// Post not approved, but in queue
$post_approval = 0;
@@ -2600,7 +2604,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Send Notifications
if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval)
{
- user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']);
+ $username = ($username) ? $username : $user->data['username'];
+ user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id'], $username);
}
$params = $add_anchor = '';
@@ -2637,7 +2642,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&amptopic_id=2&ampp=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 447920cfd5..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;
}
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 16c193c15a..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,12 +582,7 @@ class custom_profile
$this->get_option_lang($field_id, $lang_id, FIELD_DROPDOWN, false);
}
- // If a dropdown field is required, users
- // cannot choose the "no value" option.
- // They must choose one of the other options.
- // Therefore, here we treat a value equal to
- // the "no value" as a lack of value, i.e. NULL.
- if ($value == $ident_ary['data']['field_novalue'] && $ident_ary['data']['field_required'])
+ if ($value == $ident_ary['data']['field_novalue'] && !$ident_ary['data']['field_show_novalue'])
{
return NULL;
}
@@ -586,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];
@@ -600,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;
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 83316be2a3..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))
+ // Clean the private messages tables from the user
+ if (!function_exists('phpbb_delete_user_pms'))
{
- $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)
- {
- 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');
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index b70601b479..04e0e70f1d 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -414,13 +414,16 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
// Message and return links
$success_msg = 'POSTS_MERGED_SUCCESS';
- // If the topic no longer exist, we will update the topic watch table.
- // To not let it error out on users watching both topics, we just return on an error...
- $db->sql_return_on_error(true);
- $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
- $db->sql_return_on_error(false);
+ if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status'))
+ {
+ include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx);
+ }
+
+ // Update the topic watch table.
+ phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id);
- $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
+ // Update the bookmarks table.
+ phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_ids, $to_topic_id);
// Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index ffede11d37..0cef8933fc 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -1231,6 +1231,7 @@ function mcp_fork_topic($topic_ids)
}
}
+ // Copy topic subscriptions to new topic
$sql = 'SELECT user_id, notify_status
FROM ' . TOPICS_WATCH_TABLE . '
WHERE topic_id = ' . $topic_id;
@@ -1251,6 +1252,27 @@ function mcp_fork_topic($topic_ids)
{
$db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
}
+
+ // Copy bookmarks to new topic
+ $sql = 'SELECT user_id
+ FROM ' . BOOKMARKS_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query($sql);
+
+ $sql_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $sql_ary[] = array(
+ 'topic_id' => (int) $new_topic_id,
+ 'user_id' => (int) $row['user_id'],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($sql_ary))
+ {
+ $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
+ }
}
// Sync new topics, parent forums and board stats
diff --git a/phpBB/includes/mcp/mcp_pm_reports.php b/phpBB/includes/mcp/mcp_pm_reports.php
index 72f77fae7c..77bc7680e6 100644
--- a/phpBB/includes/mcp/mcp_pm_reports.php
+++ b/phpBB/includes/mcp/mcp_pm_reports.php
@@ -123,6 +123,7 @@ class mcp_pm_reports
$message = bbcode_nl2br($message);
$message = smiley_text($message);
+ $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text']));
if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download'))
{
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 7d4edaf362..76985488b7 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -517,6 +517,49 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
WHERE post_id = {$post_id_list[0]}";
$db->sql_query($sql);
+ // Copy topic subscriptions to new topic
+ $sql = 'SELECT user_id, notify_status
+ FROM ' . TOPICS_WATCH_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query($sql);
+
+ $sql_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $sql_ary[] = array(
+ 'topic_id' => (int) $to_topic_id,
+ 'user_id' => (int) $row['user_id'],
+ 'notify_status' => (int) $row['notify_status'],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($sql_ary))
+ {
+ $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
+ }
+
+ // Copy bookmarks to new topic
+ $sql = 'SELECT user_id
+ FROM ' . BOOKMARKS_TABLE . '
+ WHERE topic_id = ' . $topic_id;
+ $result = $db->sql_query($sql);
+
+ $sql_ary = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $sql_ary[] = array(
+ 'topic_id' => (int) $to_topic_id,
+ 'user_id' => (int) $row['user_id'],
+ );
+ }
+ $db->sql_freeresult($result);
+
+ if (sizeof($sql_ary))
+ {
+ $db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
+ }
+
$success_msg = 'TOPIC_SPLIT_SUCCESS';
// Update forum statistics
@@ -619,13 +662,16 @@ function merge_posts($topic_id, $to_topic_id)
}
else
{
+ if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status'))
+ {
+ include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx);
+ }
+
// If the topic no longer exist, we will update the topic watch table.
- // To not let it error out on users watching both topics, we just return on an error...
- $db->sql_return_on_error(true);
- $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id);
- $db->sql_return_on_error(false);
+ phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id);
- $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id);
+ // If the topic no longer exist, we will update the bookmarks table.
+ phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_id, $to_topic_id);
}
// Link to the new topic
diff --git a/phpBB/includes/questionnaire/questionnaire.php b/phpBB/includes/questionnaire/questionnaire.php
index cbd7638809..3268775cb6 100644
--- a/phpBB/includes/questionnaire/questionnaire.php
+++ b/phpBB/includes/questionnaire/questionnaire.php
@@ -71,7 +71,7 @@ class phpbb_questionnaire_data_collector
/**
* Collect info into the data property.
*
- * @return void
+ * @return null
*/
function collect()
{
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index 779ec1d216..bd4c003397 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -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
{
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/ucp/info/ucp_profile.php b/phpBB/includes/ucp/info/ucp_profile.php
index d19b80f4c0..4591776768 100644
--- a/phpBB/includes/ucp/info/ucp_profile.php
+++ b/phpBB/includes/ucp/info/ucp_profile.php
@@ -21,7 +21,7 @@ class ucp_profile_info
'version' => '1.0.0',
'modes' => array(
'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')),
- 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')),
+ 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => 'acl_u_sig', 'cat' => array('UCP_PROFILE')),
'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => 'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)', 'cat' => array('UCP_PROFILE')),
'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')),
),
diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php
index 05243e3d7a..d1786dd9ba 100644
--- a/phpBB/includes/ucp/ucp_pm_compose.php
+++ b/phpBB/includes/ucp/ucp_pm_compose.php
@@ -755,7 +755,8 @@ function compose_pm($id, $mode, $action, $user_folders = array())
$return_box_lang = ($action === 'post' || $action === 'edit') ? 'PM_OUTBOX' : 'PM_INBOX';
- $message = $user->lang['MESSAGE_STORED'] . '<br /><br />' . sprintf($user->lang['VIEW_PRIVATE_MESSAGE'], '<a href="' . $return_message_url . '">', '</a>');
+ $save_message = ($action === 'edit') ? $user->lang['MESSAGE_EDITED'] : $user->lang['MESSAGE_STORED'];
+ $message = $save_message . '<br /><br />' . $user->lang('VIEW_PRIVATE_MESSAGE', '<a href="' . $return_message_url . '">', '</a>');
$last_click_type = 'CLICK_RETURN_FOLDER';
if ($folder_url)
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 17d7d23f02..c6e43b831c 100644
--- a/phpBB/includes/ucp/ucp_prefs.php
+++ b/phpBB/includes/ucp/ucp_prefs.php
@@ -134,6 +134,35 @@ class ucp_prefs
}
$dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>';
+ // check if there are any user-selectable languages
+ $sql = 'SELECT COUNT(lang_id) as languages_count
+ FROM ' . LANG_TABLE;
+ $result = $db->sql_query($sql);
+ if ($db->sql_fetchfield('languages_count') > 1)
+ {
+ $s_more_languages = true;
+ }
+ else
+ {
+ $s_more_languages = false;
+ }
+ $db->sql_freeresult($result);
+
+ // check if there are any user-selectable styles
+ $sql = 'SELECT COUNT(style_id) as styles_count
+ FROM ' . STYLES_TABLE . '
+ WHERE style_active = 1';
+ $result = $db->sql_query($sql);
+ if ($db->sql_fetchfield('styles_count') > 1)
+ {
+ $s_more_styles = true;
+ }
+ else
+ {
+ $s_more_styles = false;
+ }
+ $db->sql_freeresult($result);
+
$template->assign_vars(array(
'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '',
@@ -155,6 +184,9 @@ class ucp_prefs
'DEFAULT_DATEFORMAT' => $config['default_dateformat'],
'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']),
+ 'S_MORE_LANGUAGES' => $s_more_languages,
+ 'S_MORE_STYLES' => $s_more_styles,
+
'S_LANG_OPTIONS' => language_select($data['lang']),
'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']),
'S_TZ_OPTIONS' => tz_select($data['tz'], true),