Merge branch '3.2.x'

This commit is contained in:
Marc Alexander 2017-12-27 14:39:46 +01:00
commit 93beaa8a3a
No known key found for this signature in database
GPG key ID: 50E0D2423696F995
6 changed files with 88 additions and 58 deletions

View file

@ -164,6 +164,8 @@ $user->session_begin(false);
$auth->acl($user->data); $auth->acl($user->data);
$user->setup('viewtopic'); $user->setup('viewtopic');
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
if (!$config['allow_attachments'] && !$config['allow_pm_attach']) if (!$config['allow_attachments'] && !$config['allow_pm_attach'])
{ {
send_status_line(404, 'Not Found'); send_status_line(404, 'Not Found');
@ -230,7 +232,7 @@ else
$post_row = $db->sql_fetchrow($result); $post_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result); $db->sql_freeresult($result);
if (!$post_row || ($post_row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $post_row['forum_id']))) if (!$post_row || !$phpbb_content_visibility->is_visible('post', $post_row['forum_id'], $post_row))
{ {
// Attachment of a soft deleted post and the user is not allowed to see the post // Attachment of a soft deleted post and the user is not allowed to see the post
send_status_line(404, 'Not Found'); send_status_line(404, 'Not Found');

View file

@ -661,6 +661,8 @@ function phpbb_increment_downloads($db, $ids)
*/ */
function phpbb_download_handle_forum_auth($db, $auth, $topic_id) function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
{ {
global $phpbb_container;
$sql_array = array( $sql_array = array(
'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id', 'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
'FROM' => array( 'FROM' => array(
@ -676,7 +678,9 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
$row = $db->sql_fetchrow($result); $row = $db->sql_fetchrow($result);
$db->sql_freeresult($result); $db->sql_freeresult($result);
if ($row && $row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) $phpbb_content_visibility = $phpbb_container->get('content.visibility');
if ($row && !$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
{ {
send_status_line(404, 'Not Found'); send_status_line(404, 'Not Found');
trigger_error('ERROR_NO_ATTACHMENT'); trigger_error('ERROR_NO_ATTACHMENT');

View file

@ -197,7 +197,7 @@ function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = fa
*/ */
function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = false) function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = false)
{ {
global $db, $auth, $config, $user; global $db, $auth, $config, $user, $phpbb_container;
$rowset = array(); $rowset = array();
@ -246,6 +246,8 @@ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = fals
$result = $db->sql_query($sql); $result = $db->sql_query($sql);
unset($sql_array); unset($sql_array);
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id'])) if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
@ -253,7 +255,7 @@ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = fals
continue; continue;
} }
if ($row['post_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) if (!$phpbb_content_visibility->is_visible('post', $row['forum_id'], $row))
{ {
// Moderators without the permission to approve post should at least not see them. ;) // Moderators without the permission to approve post should at least not see them. ;)
continue; continue;

View file

@ -131,6 +131,42 @@ class content_visibility
return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted']; return (int) $data[$mode . '_approved'] + (int) $data[$mode . '_unapproved'] + (int) $data[$mode . '_softdeleted'];
} }
/**
* Check topic/post visibility for a given forum ID
*
* Note: Read permissions are not checked.
*
* @param $mode string Either "topic" or "post"
* @param $forum_id int The forum id is used for permission checks
* @param $data array Array with item information to check visibility
* @return bool True if the item is visible, false if not
*/
public function is_visible($mode, $forum_id, $data)
{
$is_visible = $this->auth->acl_get('m_approve', $forum_id) || $data[$mode . '_visibility'] == ITEM_APPROVED;
/**
* Allow changing the result of calling is_visible
*
* @event core.phpbb_content_visibility_is_visible
* @var bool is_visible Default visibility condition, to be modified by extensions if needed.
* @var string mode Either "topic" or "post"
* @var int forum_id Forum id of the current item
* @var array data Array of item information
* @since 3.2.2-RC1
*/
$vars = array(
'is_visible',
'mode',
'forum_id',
'data',
);
extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_is_visible', compact($vars)));
return $is_visible;
}
/** /**
* Create topic/post visibility SQL for a given forum ID * Create topic/post visibility SQL for a given forum ID
* *
@ -176,10 +212,14 @@ class content_visibility
if ($this->auth->acl_get('m_approve', $forum_id)) if ($this->auth->acl_get('m_approve', $forum_id))
{ {
return $where_sql . '1 = 1'; $where_sql .= '1 = 1';
}
else
{
$where_sql .= $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
} }
return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; return '(' . $where_sql . ')';
} }
/** /**
@ -195,16 +235,21 @@ class content_visibility
*/ */
public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '') public function get_forums_visibility_sql($mode, $forum_ids = array(), $table_alias = '')
{ {
$where_sql = '('; $where_sql = '';
$approve_forums = array_intersect($forum_ids, array_keys($this->auth->acl_getf('m_approve', true))); $approve_forums = array_keys($this->auth->acl_getf('m_approve', true));
if (!empty($forum_ids) && !empty($approve_forums))
{
$approve_forums = array_intersect($forum_ids, $approve_forums);
$forum_ids = array_diff($forum_ids, $approve_forums);
}
$get_forums_visibility_sql_overwrite = false; $get_forums_visibility_sql_overwrite = false;
/** /**
* Allow changing the result of calling get_forums_visibility_sql * Allow changing the result of calling get_forums_visibility_sql
* *
* @event core.phpbb_content_visibility_get_forums_visibility_before * @event core.phpbb_content_visibility_get_forums_visibility_before
* @var string where_sql The action the user tried to execute * @var string where_sql Extra visibility conditions. It must end with either an SQL "AND" or an "OR"
* @var string mode Either "topic" or "post" depending on the query this is being used in * @var string mode Either "topic" or "post" depending on the query this is being used in
* @var array forum_ids Array of forum ids which the posts/topics are limited to * @var array forum_ids Array of forum ids which the posts/topics are limited to
* @var string table_alias Table alias to prefix in SQL queries * @var string table_alias Table alias to prefix in SQL queries
@ -229,33 +274,13 @@ class content_visibility
return $get_forums_visibility_sql_overwrite; return $get_forums_visibility_sql_overwrite;
} }
if (count($approve_forums)) // Moderator can view all posts/topics in the moderated forums
{ $where_sql .= '(' . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums, false, true) . ' OR ';
// Remove moderator forums from the rest // Normal user can view approved items only
$forum_ids = array_diff($forum_ids, $approve_forums);
if (!count($forum_ids))
{
// The user can see all posts/topics in all specified forums
return $where_sql . $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ')';
}
else
{
// Moderator can view all posts/topics in some forums
$where_sql .= $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums) . ' OR ';
}
}
else
{
// The user is just a normal user
return $where_sql . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . ')';
}
$where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ' $where_sql .= '(' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . '
AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids) . '))'; AND ' . $this->db->sql_in_set($table_alias . 'forum_id', $forum_ids, false, true) . '))';
return $where_sql; return '(' . $where_sql . ')';
} }
/** /**
@ -281,12 +306,12 @@ class content_visibility
* Allow changing the result of calling get_global_visibility_sql * Allow changing the result of calling get_global_visibility_sql
* *
* @event core.phpbb_content_visibility_get_global_visibility_before * @event core.phpbb_content_visibility_get_global_visibility_before
* @var array where_sqls The action the user tried to execute * @var array where_sqls Array of extra visibility conditions. Will be joined by imploding with "OR".
* @var string mode Either "topic" or "post" depending on the query this is being used in * @var string mode Either "topic" or "post" depending on the query this is being used in
* @var array exclude_forum_ids Array of forum ids the current user doesn't have access to * @var array exclude_forum_ids Array of forum ids the current user doesn't have access to
* @var string table_alias Table alias to prefix in SQL queries * @var string table_alias Table alias to prefix in SQL queries
* @var array approve_forums Array of forums where the user has m_approve permissions * @var array approve_forums Array of forums where the user has m_approve permissions
* @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR") * @var string visibility_sql_overwrite If not empty, forces the function to return visibility_sql_overwrite after executing the event
* @since 3.1.3-RC1 * @since 3.1.3-RC1
*/ */
$vars = array( $vars = array(
@ -304,24 +329,17 @@ class content_visibility
return $visibility_sql_overwrite; return $visibility_sql_overwrite;
} }
if (count($exclude_forum_ids)) // Include approved items in all forums but the excluded
{ $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true, true) . '
$where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . ' AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')';
AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')';
}
else
{
$where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED;
}
// If user has moderator permissions, add everything in the moderated forums
if (count($approve_forums)) if (count($approve_forums))
{ {
$where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums); $where_sqls[] = $this->db->sql_in_set($table_alias . 'forum_id', $approve_forums);
return '(' . implode(' OR ', $where_sqls) . ')';
} }
// There is only one element, so we just return that one return '(' . implode(' OR ', $where_sqls) . ')';
return $where_sqls[0];
} }
/** /**
@ -437,12 +455,13 @@ class content_visibility
* @var int topic_id Topic of the post IDs to be modified. * @var int topic_id Topic of the post IDs to be modified.
* @var int forum_id Forum ID that the topic_id resides in. * @var int forum_id Forum ID that the topic_id resides in.
* @var int user_id User ID doing this action. * @var int user_id User ID doing this action.
* @var int timestamp Timestamp of this action. * @var int time Timestamp of this action.
* @var string reason Reason specified by the user for this change. * @var string reason Reason specified by the user for this change.
* @var bool is_starter Are we changing the topic's starter? * @var bool is_starter Are we changing the topic's starter?
* @var bool is_latest Are we changing the topic's latest post? * @var bool is_latest Are we changing the topic's latest post?
* @var array data The data array for this action. * @var array data The data array for this action.
* @since 3.1.10-RC1 * @since 3.1.10-RC1
* @changed 3.2.2-RC1 Use time instead of non-existent timestamp
*/ */
$vars = array( $vars = array(
'visibility', 'visibility',
@ -450,7 +469,7 @@ class content_visibility
'topic_id', 'topic_id',
'forum_id', 'forum_id',
'user_id', 'user_id',
'timestamp', 'time',
'reason', 'reason',
'is_starter', 'is_starter',
'is_latest', 'is_latest',
@ -622,12 +641,13 @@ class content_visibility
* @var int topic_id Topic of the post IDs to be modified. * @var int topic_id Topic of the post IDs to be modified.
* @var int forum_id Forum ID that the topic_id resides in. * @var int forum_id Forum ID that the topic_id resides in.
* @var int user_id User ID doing this action. * @var int user_id User ID doing this action.
* @var int timestamp Timestamp of this action. * @var int time Timestamp of this action.
* @var string reason Reason specified by the user for this change. * @var string reason Reason specified by the user for this change.
* @var bool is_starter Are we changing the topic's starter? * @var bool is_starter Are we changing the topic's starter?
* @var bool is_latest Are we changing the topic's latest post? * @var bool is_latest Are we changing the topic's latest post?
* @var array data The data array for this action. * @var array data The data array for this action.
* @since 3.1.10-RC1 * @since 3.1.10-RC1
* @changed 3.2.2-RC1 Use time instead of non-existent timestamp
*/ */
$vars = array( $vars = array(
'visibility', 'visibility',
@ -635,7 +655,7 @@ class content_visibility
'topic_id', 'topic_id',
'forum_id', 'forum_id',
'user_id', 'user_id',
'timestamp', 'time',
'reason', 'reason',
'is_starter', 'is_starter',
'is_latest', 'is_latest',
@ -709,18 +729,19 @@ class content_visibility
* @var int topic_id Topic of the post IDs to be modified. * @var int topic_id Topic of the post IDs to be modified.
* @var int forum_id Forum ID that the topic_id resides in. * @var int forum_id Forum ID that the topic_id resides in.
* @var int user_id User ID doing this action. * @var int user_id User ID doing this action.
* @var int timestamp Timestamp of this action. * @var int time Timestamp of this action.
* @var string reason Reason specified by the user for this change. * @var string reason Reason specified by the user for this change.
* @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
* @var array data The data array for this action. * @var array data The data array for this action.
* @since 3.1.10-RC1 * @since 3.1.10-RC1
* @changed 3.2.2-RC1 Use time instead of non-existent timestamp
*/ */
$vars = array( $vars = array(
'visibility', 'visibility',
'topic_id', 'topic_id',
'forum_id', 'forum_id',
'user_id', 'user_id',
'timestamp', 'time',
'reason', 'reason',
'force_update_all', 'force_update_all',
'data', 'data',
@ -758,18 +779,19 @@ class content_visibility
* @var int topic_id Topic of the post IDs to be modified. * @var int topic_id Topic of the post IDs to be modified.
* @var int forum_id Forum ID that the topic_id resides in. * @var int forum_id Forum ID that the topic_id resides in.
* @var int user_id User ID doing this action. * @var int user_id User ID doing this action.
* @var int timestamp Timestamp of this action. * @var int time Timestamp of this action.
* @var string reason Reason specified by the user for this change. * @var string reason Reason specified by the user for this change.
* @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state. * @var bool force_update_all Force an update on all posts within the topic, regardless of their current approval state.
* @var array data The data array for this action. * @var array data The data array for this action.
* @since 3.1.10-RC1 * @since 3.1.10-RC1
* @changed 3.2.2-RC1 Use time instead of non-existent timestamp
*/ */
$vars = array( $vars = array(
'visibility', 'visibility',
'topic_id', 'topic_id',
'forum_id', 'forum_id',
'user_id', 'user_id',
'timestamp', 'time',
'reason', 'reason',
'force_update_all', 'force_update_all',
'data', 'data',

View file

@ -538,7 +538,7 @@ if ($forum_data['forum_type'] == FORUM_POST)
while ($row = $db->sql_fetchrow($result)) while ($row = $db->sql_fetchrow($result))
{ {
if ($row['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $row['forum_id'])) if (!$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
{ {
// Do not display announcements that are waiting for approval or soft deleted. // Do not display announcements that are waiting for approval or soft deleted.
continue; continue;

View file

@ -268,7 +268,7 @@ $forum_id = (int) $topic_data['forum_id'];
$user->page['forum'] = $forum_id; $user->page['forum'] = $forum_id;
// Now we know the forum_id and can check the permissions // Now we know the forum_id and can check the permissions
if ($topic_data['topic_visibility'] != ITEM_APPROVED && !$auth->acl_get('m_approve', $forum_id)) if (!$phpbb_content_visibility->is_visible('topic', $forum_id, $topic_data))
{ {
trigger_error('NO_TOPIC'); trigger_error('NO_TOPIC');
} }