aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/db/db_tools.php20
-rw-r--r--phpBB/includes/db/mssqlnative.php2
-rw-r--r--phpBB/includes/error_collector.php12
-rw-r--r--phpBB/includes/functions.php97
-rw-r--r--phpBB/includes/functions_content.php3
-rw-r--r--phpBB/includes/functions_display.php52
-rw-r--r--phpBB/includes/functions_messenger.php26
-rw-r--r--phpBB/includes/functions_transfer.php55
-rw-r--r--phpBB/includes/session.php33
9 files changed, 216 insertions, 84 deletions
diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php
index d23323a5b1..10ca6c0a1f 100644
--- a/phpBB/includes/db/db_tools.php
+++ b/phpBB/includes/db/db_tools.php
@@ -649,6 +649,23 @@ class phpbb_db_tools
$sqlite = true;
}
+ // Drop tables?
+ if (!empty($schema_changes['drop_tables']))
+ {
+ foreach ($schema_changes['drop_tables'] as $table)
+ {
+ // only drop table if it exists
+ if ($this->sql_table_exists($table))
+ {
+ $result = $this->sql_table_drop($table);
+ if ($this->return_statements)
+ {
+ $statements = array_merge($statements, $result);
+ }
+ }
+ }
+ }
+
// Add tables?
if (!empty($schema_changes['add_tables']))
{
@@ -1788,7 +1805,7 @@ class phpbb_db_tools
break;
case 'oracle':
- $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name;
+ $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name;
break;
case 'postgres':
@@ -1939,6 +1956,7 @@ class phpbb_db_tools
$statements[] = "DROP SEQUENCE {$row['referenced_name']}";
}
$this->db->sql_freeresult($result);
+ break;
case 'postgres':
// PGSQL does not "tightly" bind sequences and tables, we must guess...
diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php
index 6810562d17..7fbc374e77 100644
--- a/phpBB/includes/db/mssqlnative.php
+++ b/phpBB/includes/db/mssqlnative.php
@@ -396,7 +396,7 @@ class dbal_mssqlnative extends dbal
*/
function sql_affectedrows()
{
- return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->db_connect_id) : false;
+ return (!empty($this->query_result)) ? @sqlsrv_rows_affected($this->query_result) : false;
}
/**
diff --git a/phpBB/includes/error_collector.php b/phpBB/includes/error_collector.php
index 55834f354c..3c0a89a1f3 100644
--- a/phpBB/includes/error_collector.php
+++ b/phpBB/includes/error_collector.php
@@ -49,13 +49,15 @@ class phpbb_error_collector
{
$text .= "<br />\n";
}
+
list($errno, $msg_text, $errfile, $errline) = $error;
- $text .= "Errno $errno: $msg_text";
- if (defined('DEBUG_EXTRA') || defined('IN_INSTALL'))
- {
- $text .= " at $errfile line $errline";
- }
+
+ // Prevent leakage of local path to phpBB install
+ $errfile = phpbb_filter_root_path($errfile);
+
+ $text .= "Errno $errno: $msg_text at $errfile line $errline";
}
+
return $text;
}
}
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index 6b6679bde5..c2b099d48a 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -2225,6 +2225,12 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false)
{
global $_SID, $_EXTRA_URL, $phpbb_hook;
+ if ($params === '' || (is_array($params) && empty($params)))
+ {
+ // Do not append the ? if the param-list is empty anyway.
+ $params = false;
+ }
+
// Developers using the hook function need to globalise the $_SID and $_EXTRA_URL on their own and also handle it appropriately.
// They could mimic most of what is within this function
if (!empty($phpbb_hook) && $phpbb_hook->call_hook(__FUNCTION__, $url, $params, $is_amp, $session_id))
@@ -3381,61 +3387,44 @@ function add_log()
}
/**
-* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com)
+* Return a nicely formatted backtrace.
+*
+* Turns the array returned by debug_backtrace() into HTML markup.
+* Also filters out absolute paths to phpBB root.
+*
+* @return string HTML markup
*/
function get_backtrace()
{
- global $phpbb_root_path;
-
$output = '<div style="font-family: monospace;">';
$backtrace = debug_backtrace();
- $path = phpbb_realpath($phpbb_root_path);
- foreach ($backtrace as $number => $trace)
- {
- // We skip the first one, because it only shows this file/function
- if ($number == 0)
- {
- continue;
- }
+ // We skip the first one, because it only shows this file/function
+ unset($backtrace[0]);
+ foreach ($backtrace as $trace)
+ {
// Strip the current directory from path
- if (empty($trace['file']))
- {
- $trace['file'] = '';
- }
- else
- {
- $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']);
- $trace['file'] = substr($trace['file'], 1);
- }
- $args = array();
+ $trace['file'] = (empty($trace['file'])) ? '(not given by php)' : htmlspecialchars(phpbb_filter_root_path($trace['file']));
+ $trace['line'] = (empty($trace['line'])) ? '(not given by php)' : $trace['line'];
- // If include/require/include_once is not called, do not show arguments - they may contain sensible information
- if (!in_array($trace['function'], array('include', 'require', 'include_once')))
- {
- unset($trace['args']);
- }
- else
+ // Only show function arguments for include etc.
+ // Other parameters may contain sensible information
+ $argument = '';
+ if (!empty($trace['args'][0]) && in_array($trace['function'], array('include', 'require', 'include_once', 'require_once')))
{
- // Path...
- if (!empty($trace['args'][0]))
- {
- $argument = htmlspecialchars($trace['args'][0]);
- $argument = str_replace(array($path, '\\'), array('', '/'), $argument);
- $argument = substr($argument, 1);
- $args[] = "'{$argument}'";
- }
+ $argument = htmlspecialchars(phpbb_filter_root_path($trace['args'][0]));
}
$trace['class'] = (!isset($trace['class'])) ? '' : $trace['class'];
$trace['type'] = (!isset($trace['type'])) ? '' : $trace['type'];
$output .= '<br />';
- $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />';
+ $output .= '<b>FILE:</b> ' . $trace['file'] . '<br />';
$output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />';
- $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />';
+ $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']);
+ $output .= '(' . (($argument !== '') ? "'$argument'" : '') . ')<br />';
}
$output .= '</div>';
return $output;
@@ -3810,9 +3799,8 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false)
{
- // remove complete path to installation, with the risk of changing backslashes meant to be there
- $errfile = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $errfile);
- $msg_text = str_replace(array(phpbb_realpath($phpbb_root_path), '\\'), array('', '/'), $msg_text);
+ $errfile = phpbb_filter_root_path($errfile);
+ $msg_text = phpbb_filter_root_path($msg_text);
$error_name = ($errno === E_WARNING) ? 'PHP Warning' : 'PHP Notice';
echo '<b>[phpBB Debug] ' . $error_name . '</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n";
@@ -3991,6 +3979,29 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
}
/**
+* Removes absolute path to phpBB root directory from error messages
+* and converts backslashes to forward slashes.
+*
+* @param string $errfile Absolute file path
+* (e.g. /var/www/phpbb3/phpBB/includes/functions.php)
+* Please note that if $errfile is outside of the phpBB root,
+* the root path will not be found and can not be filtered.
+* @return string Relative file path
+* (e.g. /includes/functions.php)
+*/
+function phpbb_filter_root_path($errfile)
+{
+ static $root_path;
+
+ if (empty($root_path))
+ {
+ $root_path = phpbb_realpath(dirname(__FILE__) . '/../');
+ }
+
+ return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile);
+}
+
+/**
* Queries the session table to get information about online guests
* @param int $item_id Limits the search to the item with this id
* @param string $item The name of the item which is stored in the session table as session_{$item}_id
@@ -4641,6 +4652,12 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
header('Expires: 0');
header('Pragma: no-cache');
+ if (!empty($user->data['is_bot']))
+ {
+ // Let reverse proxies know we detected a bot.
+ header('X-PHPBB-IS-BOT: yes');
+ }
+
return;
}
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index b34976db2a..b7650ecd6a 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -691,9 +691,6 @@ function censor_text($text)
return '';
}
- // Strip control characters
- $text = preg_replace('/[\x00-\x0f]/', '', $text);
-
// We moved the word censor checks in here because we call this function quite often - and then only need to do the check once
if (!isset($censors) || !is_array($censors))
{
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index 7982b9908d..14d0c44dcf 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -51,6 +51,27 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$sql_where = 'left_id > ' . $root_data['left_id'] . ' AND left_id < ' . $root_data['right_id'];
}
+ // Handle marking everything read
+ if ($mark_read == 'all')
+ {
+ $redirect = build_url(array('mark', 'hash'));
+ meta_refresh(3, $redirect);
+
+ if (check_link_hash(request_var('hash', ''), 'global'))
+ {
+ markread('all');
+
+ trigger_error(
+ $user->lang['FORUMS_MARKED'] . '<br /><br />' .
+ sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>')
+ );
+ }
+ else
+ {
+ trigger_error(sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'));
+ }
+ }
+
// Display list of active topics for this category?
$show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false;
@@ -120,13 +141,14 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$forum_id = $row['forum_id'];
// Mark forums read?
- if ($mark_read == 'forums' || $mark_read == 'all')
+ if ($mark_read == 'forums')
{
if ($auth->acl_get('f_list', $forum_id))
{
$forum_ids[] = $forum_id;
- continue;
}
+
+ continue;
}
// Category with no members
@@ -152,8 +174,6 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
continue;
}
- $forum_ids[] = $forum_id;
-
if ($config['load_db_lastread'] && $user->data['is_registered'])
{
$forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark'];
@@ -255,24 +275,16 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$db->sql_freeresult($result);
// Handle marking posts
- if ($mark_read == 'forums' || $mark_read == 'all')
+ if ($mark_read == 'forums')
{
$redirect = build_url(array('mark', 'hash'));
$token = request_var('hash', '');
if (check_link_hash($token, 'global'))
{
- if ($mark_read == 'all')
- {
- markread('all');
- $message = sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>');
- }
- else
- {
- // Add 0 to forums array to mark global announcements correctly
- $forum_ids[] = 0;
- markread('topics', $forum_ids);
- $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
- }
+ // Add 0 to forums array to mark global announcements correctly
+ $forum_ids[] = 0;
+ markread('topics', $forum_ids);
+ $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
meta_refresh(3, $redirect);
trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message);
}
@@ -996,13 +1008,17 @@ function display_user_activity(&$userdata)
}
// Obtain active topic
+ // We need to exclude passworded forums here so we do not leak the topic title
+ $forum_ary_topic = array_unique(array_merge($forum_ary, $user->get_passworded_forums()));
+ $forum_sql_topic = (!empty($forum_ary_topic)) ? 'AND ' . $db->sql_in_set('forum_id', $forum_ary_topic, true) : '';
+
$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
WHERE poster_id = ' . $userdata['user_id'] . "
AND post_postcount = 1
AND (post_approved = 1
$sql_m_approve)
- $forum_sql
+ $forum_sql_topic
GROUP BY topic_id
ORDER BY num_posts DESC";
$result = $db->sql_query_limit($sql, 1);
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index b5c87094c0..08c686d9e3 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -975,9 +975,16 @@ function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false)
$smtp->add_backtrace('Connecting to ' . $config['smtp_host'] . ':' . $config['smtp_port']);
// Ok we have error checked as much as we can to this point let's get on it already.
- ob_start();
+ if (!class_exists('phpbb_error_collector'))
+ {
+ global $phpbb_root_path, $phpEx;
+ include($phpbb_root_path . 'includes/error_collector.' . $phpEx);
+ }
+ $collector = new phpbb_error_collector;
+ $collector->install();
$smtp->socket = fsockopen($config['smtp_host'], $config['smtp_port'], $errno, $errstr, 20);
- $error_contents = ob_get_clean();
+ $collector->uninstall();
+ $error_contents = $collector->format_errors();
if (!$smtp->socket)
{
@@ -1608,18 +1615,27 @@ function mail_encode($str, $eol = "\r\n")
*/
function phpbb_mail($to, $subject, $msg, $headers, $eol, &$err_msg)
{
- global $config;
+ global $config, $phpbb_root_path, $phpEx;
// We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used...
// Reference: http://bugs.php.net/bug.php?id=15841
$headers = implode($eol, $headers);
- ob_start();
+ if (!class_exists('phpbb_error_collector'))
+ {
+ include($phpbb_root_path . 'includes/error_collector.' . $phpEx);
+ }
+
+ $collector = new phpbb_error_collector;
+ $collector->install();
+
// On some PHP Versions mail() *may* fail if there are newlines within the subject.
// Newlines are used as a delimiter for lines in mail_encode() according to RFC 2045 section 6.8.
// Because PHP can't decide what is wanted we revert back to the non-RFC-compliant way of separating by one space (Use '' as parameter to mail_encode() results in SPACE used)
$result = $config['email_function_name']($to, mail_encode($subject, ''), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $headers);
- $err_msg = ob_get_clean();
+
+ $collector->uninstall();
+ $err_msg = $collector->format_errors();
return $result;
}
diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php
index 046abede8e..5ab7a87efd 100644
--- a/phpBB/includes/functions_transfer.php
+++ b/phpBB/includes/functions_transfer.php
@@ -808,23 +808,56 @@ class ftp_fsock extends transfer
*/
function _open_data_connection()
{
- $this->_send_command('PASV', '', false);
-
- if (!$ip_port = $this->_check_command(true))
+ // Try to find out whether we have a IPv4 or IPv6 (control) connection
+ if (function_exists('stream_socket_get_name'))
{
- return false;
+ $socket_name = stream_socket_get_name($this->connection, true);
+ $server_ip = substr($socket_name, 0, strrpos($socket_name, ':'));
}
- // open the connection to start sending the file
- if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
+ if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip))
{
- // bad ip and port
- return false;
+ // Passive mode
+ $this->_send_command('PASV', '', false);
+
+ if (!$ip_port = $this->_check_command(true))
+ {
+ return false;
+ }
+
+ // open the connection to start sending the file
+ if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
+ {
+ // bad ip and port
+ return false;
+ }
+
+ $temp = explode(',', $temp[0]);
+ $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
+ $server_port = $temp[4] * 256 + $temp[5];
+ }
+ else
+ {
+ // Extended Passive Mode - RFC2428
+ $this->_send_command('EPSV', '', false);
+
+ if (!$epsv_response = $this->_check_command(true))
+ {
+ return false;
+ }
+
+ // Response looks like "229 Entering Extended Passive Mode (|||12345|)"
+ // where 12345 is the tcp port for the data connection
+ if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match))
+ {
+ return false;
+ }
+ $server_port = (int) $match[1];
+
+ // fsockopen expects IPv6 address in square brackets
+ $server_ip = "[$server_ip]";
}
- $temp = explode(',', $temp[0]);
- $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
- $server_port = $temp[4] * 256 + $temp[5];
$errno = 0;
$errstr = '';
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index e9e706e2b8..caadcbafaa 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -2410,6 +2410,39 @@ class user extends session
return true;
}
+
+ /**
+ * Returns all password protected forum ids the user is currently NOT authenticated for.
+ *
+ * @return array Array of forum ids
+ * @access public
+ */
+ function get_passworded_forums()
+ {
+ global $db;
+
+ $sql = 'SELECT f.forum_id, fa.user_id
+ FROM ' . FORUMS_TABLE . ' f
+ LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
+ ON (fa.forum_id = f.forum_id
+ AND fa.session_id = '" . $db->sql_escape($this->session_id) . "')
+ WHERE f.forum_password <> ''";
+ $result = $db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $forum_id = (int) $row['forum_id'];
+
+ if ($row['user_id'] != $this->data['user_id'])
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $forum_ids;
+ }
}
?> \ No newline at end of file