diff options
Diffstat (limited to 'phpBB')
| -rw-r--r-- | phpBB/assets/javascript/core.js | 6 | ||||
| -rw-r--r-- | phpBB/composer.json | 4 | ||||
| -rw-r--r-- | phpBB/composer.lock | 20 | ||||
| -rw-r--r-- | phpBB/config/default/container/services_text_formatter.yml | 5 | ||||
| -rw-r--r-- | phpBB/download/file.php | 4 | ||||
| -rw-r--r-- | phpBB/includes/functions_download.php | 6 | ||||
| -rw-r--r-- | phpBB/includes/functions_mcp.php | 6 | ||||
| -rw-r--r-- | phpBB/includes/ucp/ucp_register.php | 32 | ||||
| -rw-r--r-- | phpBB/phpbb/content_visibility.php | 126 | ||||
| -rw-r--r-- | phpBB/phpbb/datetime.php | 6 | ||||
| -rw-r--r-- | phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php | 75 | ||||
| -rw-r--r-- | phpBB/phpbb/search/fulltext_mysql.php | 19 | ||||
| -rw-r--r-- | phpBB/phpbb/textformatter/s9e/bbcode_merger.php | 180 | ||||
| -rw-r--r-- | phpBB/phpbb/textformatter/s9e/factory.php | 7 | ||||
| -rw-r--r-- | phpBB/phpbb/textformatter/s9e/parser.php | 6 | ||||
| -rw-r--r-- | phpBB/search.php | 20 | ||||
| -rw-r--r-- | phpBB/styles/prosilver/template/ucp_footer.html | 2 | ||||
| -rw-r--r-- | phpBB/styles/prosilver/theme/content.css | 1 | ||||
| -rw-r--r-- | phpBB/viewforum.php | 2 | ||||
| -rw-r--r-- | phpBB/viewtopic.php | 2 |
20 files changed, 440 insertions, 89 deletions
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js index 359afb1ec4..069f9089c2 100644 --- a/phpBB/assets/javascript/core.js +++ b/phpBB/assets/javascript/core.js @@ -27,9 +27,9 @@ phpbb.isTouch = (window && typeof window.ontouchstart !== 'undefined'); */ phpbb.loadingIndicator = function() { if (!$loadingIndicator) { - $loadingIndicator = $('<div />', { - id: 'loading_indicator', - class: 'loading_indicator', + $loadingIndicator = $('<div />', { + 'id': 'loading_indicator', + 'class': 'loading_indicator' }); $loadingIndicator.appendTo('#page-footer'); } diff --git a/phpBB/composer.json b/phpBB/composer.json index 5bc8f5dc0d..926fad5188 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -33,7 +33,7 @@ "marc1706/fast-image-size": "^1.1", "paragonie/random_compat": "^1.4", "patchwork/utf8": "^1.1", - "s9e/text-formatter": "~0.11.0", + "s9e/text-formatter": "~0.13.0", "symfony/config": "^2.8", "symfony/console": "^2.8", "symfony/debug": "^2.8", @@ -69,7 +69,7 @@ }, "config": { "platform": { - "php": "5.4" + "php": "5.4.7" } } } diff --git a/phpBB/composer.lock b/phpBB/composer.lock index c1bdf26e02..59143a1fa7 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7c30306b2abcb79a206bf6497ef45a02", - "content-hash": "d559dd0af2317fb0fc15720a18834e33", + "hash": "f14915a2ccaf76ccd6d3ea725721a8a8", + "content-hash": "c843abc1344cd9df37f63c08a125cad0", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -661,27 +661,27 @@ }, { "name": "s9e/text-formatter", - "version": "0.11.2", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "735a56076e29348d838ce6c2658996daae86718f" + "reference": "804ed8fdfa9fd0c8d99f5a33000d4f7e5ed90c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/735a56076e29348d838ce6c2658996daae86718f", - "reference": "735a56076e29348d838ce6c2658996daae86718f", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/804ed8fdfa9fd0c8d99f5a33000d4f7e5ed90c6f", + "reference": "804ed8fdfa9fd0c8d99f5a33000d4f7e5ed90c6f", "shasum": "" }, "require": { "ext-dom": "*", "ext-filter": "*", "lib-pcre": ">=7.2", - "php": ">=5.3.3" + "php": ">=5.4.7" }, "require-dev": { "matthiasmullie/minify": "*", - "php": ">=5.3.3", + "php": ">=5.4.7", "s9e/regexp-builder": ">=1.3.0" }, "suggest": { @@ -722,7 +722,7 @@ "parser", "shortcodes" ], - "time": "2017-10-02 16:58:51" + "time": "2017-12-10 00:55:53" }, { "name": "symfony/config", @@ -3577,6 +3577,6 @@ }, "platform-dev": [], "platform-overrides": { - "php": "5.4" + "php": "5.4.7" } } diff --git a/phpBB/config/default/container/services_text_formatter.yml b/phpBB/config/default/container/services_text_formatter.yml index a9f2efdb16..74624ea4e4 100644 --- a/phpBB/config/default/container/services_text_formatter.yml +++ b/phpBB/config/default/container/services_text_formatter.yml @@ -26,6 +26,11 @@ services: text_formatter.utils: alias: text_formatter.s9e.utils + text_formatter.s9e.bbcode_merger: + class: phpbb\textformatter\s9e\bbcode_merger + arguments: + - '@text_formatter.s9e.factory' + text_formatter.s9e.factory: class: phpbb\textformatter\s9e\factory arguments: diff --git a/phpBB/download/file.php b/phpBB/download/file.php index a9cd4a3b3c..9ee489cef4 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -159,6 +159,8 @@ $user->session_begin(false); $auth->acl($user->data); $user->setup('viewtopic'); +$phpbb_content_visibility = $phpbb_container->get('content.visibility'); + if (!$config['allow_attachments'] && !$config['allow_pm_attach']) { send_status_line(404, 'Not Found'); @@ -225,7 +227,7 @@ else $post_row = $db->sql_fetchrow($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 send_status_line(404, 'Not Found'); diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index e00be1e01a..e3af294b75 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -662,6 +662,8 @@ function phpbb_increment_downloads($db, $ids) */ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) { + global $phpbb_container; + $sql_array = array( 'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id', 'FROM' => array( @@ -677,7 +679,9 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id) $row = $db->sql_fetchrow($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'); trigger_error('ERROR_NO_ATTACHMENT'); diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php index dfe3fefbd0..7ab2da8e5c 100644 --- a/phpBB/includes/functions_mcp.php +++ b/phpBB/includes/functions_mcp.php @@ -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) { - global $db, $auth, $config, $user; + global $db, $auth, $config, $user, $phpbb_container; $rowset = array(); @@ -246,6 +246,8 @@ function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = fals $result = $db->sql_query($sql); unset($sql_array); + $phpbb_content_visibility = $phpbb_container->get('content.visibility'); + while ($row = $db->sql_fetchrow($result)) { 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; } - 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. ;) continue; diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 6e010a0852..a7a93d6115 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -166,7 +166,7 @@ class ucp_register ->format($user->lang['DATE_FORMAT'], true); unset($now); - $template->assign_vars(array( + $template_vars = array( 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', 'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), 'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), @@ -180,11 +180,11 @@ class ucp_register 'COOKIE_NAME' => $config['cookie_name'], 'COOKIE_PATH' => $config['cookie_path'], - )); + ); } else { - $template->assign_vars(array( + $template_vars = array( 'S_LANG_OPTIONS' => (sizeof($lang_row) > 1) ? language_select($user_lang) : '', 'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()), @@ -195,11 +195,32 @@ class ucp_register 'COOKIE_NAME' => $config['cookie_name'], 'COOKIE_PATH' => $config['cookie_path'], - ) ); } + + $tpl_name = 'ucp_agreement'; + + /** + * Allows to modify the agreements. + * + * @event core.ucp_register_agreement_modify_template_data + * @var string tpl_name Template file + * @var array template_vars Array with data about to be assigned to the template + * @var array s_hidden_fields Array with hidden form elements + * @var array lang_row Array with available languages, read only + * @since 3.2.2-RC1 + */ + $vars = array('tpl_name', 'template_vars', 's_hidden_fields', 'lang_row'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_agreement_modify_template_data', compact($vars))); + unset($lang_row); + $template_vars = array_merge($template_vars, array( + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + )); + + $template->assign_vars($template_vars); + /** * Allows to modify the agreements. * @@ -207,10 +228,11 @@ class ucp_register * * @event core.ucp_register_agreement * @since 3.1.6-RC1 + * @deprecated 3.2.2-RC1 Replaced by core.ucp_register_agreement_modify_template_data and to be removed in 3.3.0-RC1 */ $phpbb_dispatcher->dispatch('core.ucp_register_agreement'); - $this->tpl_name = 'ucp_agreement'; + $this->tpl_name = $tpl_name; return; } diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index bf7dc2c703..237300894b 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -131,6 +131,42 @@ class content_visibility 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 * @@ -176,10 +212,14 @@ class content_visibility 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 = '') { - $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; /** * Allow changing the result of calling get_forums_visibility_sql * * @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 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 @@ -229,33 +274,13 @@ class content_visibility return $get_forums_visibility_sql_overwrite; } - if (sizeof($approve_forums)) - { - // Remove moderator forums from the rest - $forum_ids = array_diff($forum_ids, $approve_forums); - - if (!sizeof($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) . ')'; - } - + // 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 '; + // Normal user can view approved items only $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 * * @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 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 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 */ $vars = array( @@ -304,24 +329,17 @@ class content_visibility return $visibility_sql_overwrite; } - if (sizeof($exclude_forum_ids)) - { - $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . ' - AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')'; - } - else - { - $where_sqls[] = $table_alias . $mode . '_visibility = ' . ITEM_APPROVED; - } + // 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) . ' + AND ' . $table_alias . $mode . '_visibility = ' . ITEM_APPROVED . ')'; + // If user has moderator permissions, add everything in the moderated forums if (sizeof($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 $where_sqls[0]; + return '(' . implode(' OR ', $where_sqls) . ')'; } /** @@ -437,12 +455,13 @@ class content_visibility * @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 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 bool is_starter Are we changing the topic's starter? * @var bool is_latest Are we changing the topic's latest post? * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', @@ -450,7 +469,7 @@ class content_visibility 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'is_starter', 'is_latest', @@ -622,12 +641,13 @@ class content_visibility * @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 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 bool is_starter Are we changing the topic's starter? * @var bool is_latest Are we changing the topic's latest post? * @var array data The data array for this action. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', @@ -635,7 +655,7 @@ class content_visibility 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'is_starter', 'is_latest', @@ -709,18 +729,19 @@ class content_visibility * @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 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 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. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'force_update_all', 'data', @@ -758,18 +779,19 @@ class content_visibility * @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 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 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. * @since 3.1.10-RC1 + * @changed 3.2.2-RC1 Use time instead of non-existent timestamp */ $vars = array( 'visibility', 'topic_id', 'forum_id', 'user_id', - 'timestamp', + 'time', 'reason', 'force_update_all', 'data', diff --git a/phpBB/phpbb/datetime.php b/phpBB/phpbb/datetime.php index 63cdba90fd..4b799b6219 100644 --- a/phpBB/phpbb/datetime.php +++ b/phpBB/phpbb/datetime.php @@ -60,6 +60,12 @@ class datetime extends \DateTime public function format($format = '', $force_absolute = false) { $format = $format ? $format : $this->user->date_format; + + if (substr($this->user->lang_name, 0,2) != 'en') + { + $format = preg_replace('/([^\\\])S/','$1', $format); + } + $format = self::format_cache($format, $this->user); $relative = ($format['is_short'] && !$force_absolute); $now = new self($this->user, 'now', $this->user->timezone); diff --git a/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php b/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php new file mode 100644 index 0000000000..3bf442bab5 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/merge_duplicate_bbcodes.php @@ -0,0 +1,75 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v32x; + +class merge_duplicate_bbcodes extends \phpbb\db\migration\migration +{ + public function update_data() + { + return [ + ['custom', [[$this, 'update_bbcodes_table']]], + ]; + } + + public function update_bbcodes_table() + { + $sql = 'SELECT bbcode_id, bbcode_tag, bbcode_helpline, bbcode_match, bbcode_tpl FROM ' . BBCODES_TABLE; + $result = $this->sql_query($sql); + $bbcodes = []; + while ($row = $this->db->sql_fetchrow($result)) + { + $variant = (substr($row['bbcode_tag'], -1) === '=') ? 'with': 'without'; + $bbcode_name = rtrim($row['bbcode_tag'], '='); + $bbcodes[$bbcode_name][$variant] = $row; + } + $this->db->sql_freeresult($result); + + foreach ($bbcodes as $bbcode_name => $variants) + { + if (count($variants) === 2) + { + $this->merge_bbcodes($variants['without'], $variants['with']); + } + } + } + + protected function merge_bbcodes(array $without, array $with) + { + $merged = $this->container->get('text_formatter.s9e.bbcode_merger')->merge_bbcodes( + [ + 'usage' => $without['bbcode_match'], + 'template' => $without['bbcode_tpl'] + ], + [ + 'usage' => $with['bbcode_match'], + 'template' => $with['bbcode_tpl'] + ] + ); + $bbcode_data = [ + 'bbcode_tag' => $without['bbcode_tag'], + 'bbcode_helpline' => $without['bbcode_helpline'] . ' | ' . $with['bbcode_helpline'], + 'bbcode_match' => $merged['usage'], + 'bbcode_tpl' => $merged['template'] + ]; + + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $bbcode_data) . ' + WHERE bbcode_id = ' . $without['bbcode_id']; + $this->sql_query($sql); + + $sql = 'DELETE FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . $with['bbcode_id']; + $this->sql_query($sql); + } +} diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index da1aad1c3a..c8df1951e3 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -591,6 +591,7 @@ class fulltext_mysql extends \phpbb\search\base WHERE MATCH ($sql_match) AGAINST ('" . $this->db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE) $sql_where_options ORDER BY $sql_sort"; + $this->db->sql_return_on_error(true); $result = $this->db->sql_query_limit($sql, $this->config['search_block_size'], $start); while ($row = $this->db->sql_fetchrow($result)) @@ -602,7 +603,7 @@ class fulltext_mysql extends \phpbb\search\base $id_ary = array_unique($id_ary); // if the total result count is not cached yet, retrieve it from the db - if (!$result_count) + if (!$result_count && count($id_ary)) { $sql_found_rows = 'SELECT FOUND_ROWS() as result_count'; $result = $this->db->sql_query($sql_found_rows); @@ -1004,6 +1005,11 @@ class fulltext_mysql extends \phpbb\search\base } } + if (!isset($this->stats['post_text'])) + { + $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ADD FULLTEXT post_text (post_text)'); + } + $this->db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); return false; @@ -1039,6 +1045,11 @@ class fulltext_mysql extends \phpbb\search\base $alter[] = 'DROP INDEX post_content'; } + if (isset($this->stats['post_text'])) + { + $alter[] = 'DROP INDEX post_text'; + } + if (sizeof($alter)) { $this->db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); @@ -1059,7 +1070,7 @@ class fulltext_mysql extends \phpbb\search\base $this->get_stats(); } - return isset($this->stats['post_subject']) && isset($this->stats['post_content']); + return isset($this->stats['post_subject']) && isset($this->stats['post_content']) && isset($this->stats['post_text']); } /** @@ -1103,6 +1114,10 @@ class fulltext_mysql extends \phpbb\search\base { $this->stats['post_subject'] = $row; } + else if ($row['Key_name'] == 'post_text') + { + $this->stats['post_text'] = $row; + } else if ($row['Key_name'] == 'post_content') { $this->stats['post_content'] = $row; diff --git a/phpBB/phpbb/textformatter/s9e/bbcode_merger.php b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php new file mode 100644 index 0000000000..72b1473751 --- /dev/null +++ b/phpBB/phpbb/textformatter/s9e/bbcode_merger.php @@ -0,0 +1,180 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\textformatter\s9e; + +use phpbb\textformatter\s9e\factory; +use s9e\TextFormatter\Configurator\Helpers\TemplateHelper; +use s9e\TextFormatter\Configurator\Items\UnsafeTemplate; + +class bbcode_merger +{ + /** + * @var \s9e\TextFormatter\Configurator $configurator Configurator instance used to inspect BBCodes + */ + protected $configurator; + + /** + * @param \phpbb\textformatter\s9e\factory $factory + */ + public function __construct(factory $factory) + { + $this->configurator = $factory->get_configurator(); + } + + /** + * Merge two BBCode definitions + * + * All of the arrays contain a "usage" element and a "template" element + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + public function merge_bbcodes(array $without, array $with) + { + $without = $this->create_bbcode($without); + $with = $this->create_bbcode($with); + + // Select the appropriate strategy for merging this BBCode + if ($this->is_content_bbcode($without, $with)) + { + $merged = $this->merge_content_bbcode($without, $with); + } + else + { + $merged = $this->merge_optional_bbcode($without, $with); + } + + $merged['template'] = $this->normalize_template($merged['template']); + + return $merged; + } + + /** + * Create a custom BBCode for inspection + * + * @param array $definition Original BBCode definition + * @return array Updated definition containing a BBCode object and a Tag + */ + protected function create_bbcode(array $definition) + { + $bbcode = $this->configurator->BBCodes->addCustom( + $definition['usage'], + new UnsafeTemplate($definition['template']) + ); + + $definition['bbcode'] = $bbcode; + $definition['tag'] = $this->configurator->tags[$bbcode->tagName]; + + return $definition; + } + + /** + * Indent given template for readability + * + * @param string $template + * @return string + */ + protected function indent_template($template) + { + $dom = TemplateHelper::loadTemplate($template); + $dom->formatOutput = true; + $template = TemplateHelper::saveTemplate($dom); + + // Remove the first level of indentation if the template starts with whitespace + if (preg_match('(^\\n +)', $template, $m)) + { + $template = str_replace($m[0], "\n", $template); + } + + return trim($template); + } + + /** + * Test whether the two definitions form a "content"-style BBCode + * + * Such BBCodes include the [URL] BBCode, which uses its text content as + * attribute if none is provided + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function is_content_bbcode(array $without, array $with) + { + // Test whether we find the same non-TEXT token between "]" and "[" in the usage + // as between ">" and "<" in the template + return (preg_match('(\\]\\s*(\\{(?!TEXT)[^}]+\\})\\s*\\[)', $without['usage'], $m) + && preg_match('(>[^<]*?' . preg_quote($m[1]) . '[^>]*?<)s', $without['template'])); + } + + /** + * Merge the two BBCode definitions of a "content"-style BBCode + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function merge_content_bbcode(array $without, array $with) + { + // Convert [X={X}] into [X={X;useContent}] + $usage = preg_replace('(\\})', ';useContent}', $with['usage'], 1); + + // Use the template from the definition that uses an attribute + $template = $with['tag']->template; + + return ['usage' => $usage, 'template' => $template]; + } + + /** + * Merge the two BBCode definitions of a BBCode with an optional argument + * + * Such BBCodes include the [QUOTE] BBCode, which takes an optional argument + * but otherwise does not behave differently + * + * @param array $without BBCode definition without an attribute + * @param array $with BBCode definition with an attribute + * @return array Merged definition + */ + protected function merge_optional_bbcode(array $without, array $with) + { + // Convert [X={X}] into [X={X?}] + $usage = preg_replace('(\\})', '?}', $with['usage'], 1); + + // Build a template for both versions + $template = '<xsl:choose><xsl:when test="@' . $with['bbcode']->defaultAttribute . '">' . $with['tag']->template . '</xsl:when><xsl:otherwise>' . $without['tag']->template . '</xsl:otherwise></xsl:choose>'; + + return ['usage' => $usage, 'template' => $template]; + } + + /** + * Normalize a template + * + * @param string $template + * @return string + */ + protected function normalize_template($template) + { + // Normalize the template to simplify it + $template = $this->configurator->templateNormalizer->normalizeTemplate($template); + + // Convert xsl:value-of elements back to {L_} tokens where applicable + $template = preg_replace('(<xsl:value-of select="\\$(L_\\w+)"/>)', '{$1}', $template); + + // Beautify the template + $template = $this->indent_template($template); + + return $template; + } +} diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 15d0a5e3e5..1e85856898 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -266,12 +266,13 @@ class factory implements \phpbb\textformatter\cache_interface ->addParameterByName('logger') ->addParameterByName('max_img_height') ->addParameterByName('max_img_width') - ->markAsSafeAsURL(); + ->markAsSafeAsURL() + ->setJS('UrlFilter.filter'); // Add default BBCodes foreach ($this->get_default_bbcodes($configurator) as $bbcode) { - $configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']); + $configurator->BBCodes->addCustom($bbcode['usage'], new UnsafeTemplate($bbcode['template'])); } if (isset($configurator->tags['QUOTE'])) { @@ -355,8 +356,6 @@ class factory implements \phpbb\textformatter\cache_interface $configurator->registeredVars['max_img_width'] = 0; // Load the Emoji plugin and modify its tag's template to obey viewsmilies - $configurator->Emoji->omitImageSize(); - $configurator->Emoji->useSVG(); $tag = $configurator->Emoji->getTag(); $tag->template = '<xsl:choose><xsl:when test="$S_VIEWSMILIES">' . str_replace('class="emoji"', 'class="emoji smilies"', $tag->template) . '</xsl:when><xsl:otherwise><xsl:value-of select="."/></xsl:otherwise></xsl:choose>'; diff --git a/phpBB/phpbb/textformatter/s9e/parser.php b/phpBB/phpbb/textformatter/s9e/parser.php index 05ddfffa11..3698dca224 100644 --- a/phpBB/phpbb/textformatter/s9e/parser.php +++ b/phpBB/phpbb/textformatter/s9e/parser.php @@ -13,7 +13,7 @@ namespace phpbb\textformatter\s9e; -use s9e\TextFormatter\Parser\BuiltInFilters; +use s9e\TextFormatter\Parser\AttributeFilters\UrlFilter; use s9e\TextFormatter\Parser\Logger; /** @@ -196,7 +196,7 @@ class parser implements \phpbb\textformatter\parser_interface public function get_errors() { $errors = array(); - foreach ($this->parser->getLogger()->get() as $entry) + foreach ($this->parser->getLogger()->getLogs() as $entry) { list(, $msg, $context) = $entry; @@ -365,7 +365,7 @@ class parser implements \phpbb\textformatter\parser_interface static public function filter_img_url($url, array $url_config, Logger $logger, $max_height, $max_width) { // Validate the URL - $url = BuiltInFilters::filterUrl($url, $url_config, $logger); + $url = UrlFilter::filter($url, $url_config, $logger); if ($url === false) { return false; diff --git a/phpBB/search.php b/phpBB/search.php index 0d9b2bbfe8..eabb1fc96e 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -932,6 +932,26 @@ if ($keywords || $author || $author_id || $search_id || $submit) while ($row = $db->sql_fetchrow($result)) { + /** + * Modify the row of a post result before the post_text is trimmed + * + * @event core.search_modify_post_row + * @var string hilit String to highlight + * @var array row Array with the post data + * @var string u_hilit Highlight string to be injected into URL + * @var string view Search results view mode + * @var array zebra Array with zebra data for the current user + * @since 3.2.2-RC1 + */ + $vars = array( + 'hilit', + 'row', + 'u_hilit', + 'view', + 'zebra', + ); + extract($phpbb_dispatcher->trigger_event('core.search_modify_post_row', compact($vars))); + // We pre-process some variables here for later usage $row['post_text'] = censor_text($row['post_text']); diff --git a/phpBB/styles/prosilver/template/ucp_footer.html b/phpBB/styles/prosilver/template/ucp_footer.html index f2f1a68db3..eb07f52e05 100644 --- a/phpBB/styles/prosilver/template/ucp_footer.html +++ b/phpBB/styles/prosilver/template/ucp_footer.html @@ -9,6 +9,4 @@ </form> <!-- ENDIF --> -<!-- INCLUDE jumpbox.html --> - <!-- INCLUDE overall_footer.html --> diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index cd420b7614..807633864c 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -529,6 +529,7 @@ blockquote .codebox { /* Attachments ----------------------------------------*/ .attachbox { + font-size: 13px; float: left; width: auto; max-width: 100%; diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 79d75a18f8..e4cf08d548 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -538,7 +538,7 @@ if ($forum_data['forum_type'] == FORUM_POST) 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. continue; diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 3f117eef6b..9037918a20 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -268,7 +268,7 @@ $forum_id = (int) $topic_data['forum_id']; $user->page['forum'] = $forum_id; // 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'); } |
