diff options
72 files changed, 1001 insertions, 207 deletions
diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php index 7dc8e4b13d..d27f56f28b 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -41,6 +41,7 @@ if (!isset($user->data['session_admin']) || !$user->data['session_admin']) // check specific permissions but this is a catchall if (!$auth->acl_get('a_')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_ADMIN'); } diff --git a/phpBB/adm/style/acp_posting_buttons.html b/phpBB/adm/style/acp_posting_buttons.html index 70b6259689..c3c42f8e82 100644 --- a/phpBB/adm/style/acp_posting_buttons.html +++ b/phpBB/adm/style/acp_posting_buttons.html @@ -63,6 +63,7 @@ <!-- ENDIF --> <!-- ENDIF --> </select> + <!-- EVENT acp_posting_buttons_custom_tags_before --> <!-- BEGIN custom_tags --> <input type="button" class="button2" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}" /> <!-- END custom_tags --> diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml index cf51ebdab8..ba1fdb4c9a 100644 --- a/phpBB/config/default/container/services_files.yml +++ b/phpBB/config/default/container/services_files.yml @@ -37,7 +37,7 @@ services: - '@request' files.types.local: - class: phpbb\files\types\form + class: phpbb\files\types\local shared: false arguments: - '@files.factory' diff --git a/phpBB/config/installer/routing/installer.yml b/phpBB/config/installer/routing/installer.yml index 47e16aa454..66b8893ad9 100644 --- a/phpBB/config/installer/routing/installer.yml +++ b/phpBB/config/installer/routing/installer.yml @@ -43,7 +43,7 @@ phpbb_convert_intro: start_new: 0 phpbb_convert_settings: - path: /convert/settings/{convertor} + path: /convert/settings/{converter} defaults: _controller: phpbb.installer.controller.convert:settings requirements: diff --git a/phpBB/docs/CREDITS.txt b/phpBB/docs/CREDITS.txt index deb36339b0..471e6b3c88 100644 --- a/phpBB/docs/CREDITS.txt +++ b/phpBB/docs/CREDITS.txt @@ -1,6 +1,6 @@ /** * -* phpBB © Copyright phpBB Limited 2003-2014 +* phpBB © Copyright phpBB Limited 2003-2016 * http://www.phpbb.com * * phpBB is free software. You can redistribute it and/or modify it @@ -20,13 +20,13 @@ phpBB Project Manager: Marshalrusty (Yuriy Rusko) -phpBB Lead Developer: naderman (Nils Adermann) +phpBB Product Manager: naderman (Nils Adermann) + +phpBB Lead Developer: Marc (Marc Alexander) phpBB Developers: bantu (Andreas Fischer) CHItA (Máté Bartus) - dhruv.goel92 (Dhruv Goel) Elsensee (Oliver Schramm) - marc1706 (Marc Alexander) nickvergessen (Joas Schilling) Nicofuma (Tristan Darricau) prototech (Cesar Gallegos) @@ -54,6 +54,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010] ckwalsh (Cullen Walsh) [01/2010 - 07/2011] DavidMJ (David M.) [12/2005 - 08/2009] dhn (Dominik Dröscher) [05/2007 - 01/2011] + dhruv.goel92 (Dhruv Goel) [04/2013 - 05/2016] EXreaction (Nathan Guse) [07/2012 - 05/2014] GrahamJE (Graham Eames) [09/2005 - 11/2006] igorw (Igor Wiedler) [08/2010 - 02/2013] diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index d5aa0c3aec..4903d0dfb2 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -343,6 +343,13 @@ acp_posting_buttons_before * Since: 3.1.0-b4 * Purpose: Add content before BBCode posting buttons in the ACP +acp_posting_buttons_custom_tags_before +=== +* Locations: + + adm/style/acp_posting_buttons.html +* Since: 3.1.10-RC1 +* Purpose: Add content before the custom BBCodes in the ACP + acp_profile_contact_before === * Locations: @@ -835,6 +842,20 @@ mcp_topic_options_before * Since: 3.1.6-RC1 * Purpose: Add some options (field, checkbox, ...) before the subject field when split a subject +mcp_topic_postrow_post_details_after +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.1.10-RC1 +* Purpose: Add content after post details in topic moderation + +mcp_topic_postrow_post_details_before +=== +* Locations: + + styles/prosilver/template/mcp_topic.html +* Since: 3.1.10-RC1 +* Purpose: Add content before post details in topic moderation + mcp_topic_topic_title_after === * Locations: @@ -1386,6 +1407,13 @@ posting_editor_subject_after * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen after the subject +posting_editor_subject_append +=== +* Locations: + + styles/prosilver/template/posting_editor.html +* Since: 3.1.10-RC1 +* Purpose: Add field, text, etc. to the posting after the subject text box + posting_editor_subject_before === * Locations: @@ -1393,6 +1421,13 @@ posting_editor_subject_before * Since: 3.1.0-a2 * Purpose: Add field (e.g. textbox) to the posting screen before the subject +posting_editor_subject_prepend +=== +* Locations: + + styles/prosilver/template/posting_editor.html +* Since: 3.1.10-RC1 +* Purpose: Add field, text, etc. to the posting before the subject text box + posting_editor_submit_buttons === * Locations: @@ -1449,6 +1484,20 @@ posting_preview_poll_after * Since: 3.1.7-RC1 * Purpose: Add content after the poll preview block +posting_topic_review_row_post_details_after +=== +* Locations: + + styles/prosilver/template/posting_topic_review.html +* Since: 3.1.10-RC1 +* Purpose: Add content after post details in topic review + +posting_topic_review_row_post_details_before +=== +* Locations: + + styles/prosilver/template/posting_topic_review.html +* Since: 3.1.10-RC1 +* Purpose: Add content before post details in topic review + posting_topic_title_after === * Locations: @@ -2057,6 +2106,13 @@ viewforum_body_topic_row_prepend * Since: 3.1.7-RC1 * Purpose: Add content at the end of the topic list item. +viewforum_body_topicrow_row_before +=== +* Locations: + + styles/prosilver/template/viewforum_body.html +* Since: 3.1.10-RC1 +* Purpose: Add content before list of topics. + viewforum_buttons_bottom_before === * Locations: diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index c9d24f9254..982310fb05 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -38,6 +38,14 @@ class acp_database $action = $request->variable('action', ''); + $form_key = 'acp_database'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $template->assign_vars(array( 'MODE' => $mode )); diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 3ea9d81887..66bb630241 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -843,9 +843,26 @@ class acp_forums ORDER BY left_id"; $result = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result)) + $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $rowset[(int) $row['forum_id']] = $row; + } + $db->sql_freeresult($result); + + /** + * Modify the forum list data + * + * @event core.acp_manage_forums_modify_forum_list + * @var array rowset Array with the forums list data + * @since 3.1.10-RC1 + */ + $vars = array('rowset'); + extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_modify_forum_list', compact($vars))); + + if (!empty($rowset)) { - do + foreach ($rowset as $row) { $forum_type = $row['forum_type']; @@ -889,7 +906,6 @@ class acp_forums 'U_SYNC' => $url . '&action=sync') ); } - while ($row = $db->sql_fetchrow($result)); } else if ($this->parent_id) { @@ -905,7 +921,7 @@ class acp_forums 'U_SYNC' => $url . '&action=sync') ); } - $db->sql_freeresult($result); + unset($rowset); $template->assign_vars(array( 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php index 6bd3e71c2e..305296d013 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -223,6 +223,7 @@ class acp_groups } else if ($action === 'delete' && $group_row['group_type'] == GROUP_SPECIAL) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -235,6 +236,7 @@ class acp_groups case 'delete': if (!$auth->acl_get('a_groupdel')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -313,6 +315,7 @@ class acp_groups if ($action == 'add' && !$auth->acl_get('a_groupadd')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 0293dca9d3..bea8da221c 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -40,6 +40,15 @@ class acp_icons $action = (isset($_POST['edit'])) ? 'edit' : $action; $action = (isset($_POST['import'])) ? 'import' : $action; $icon_id = $request->variable('id', 0); + $submit = $request->is_set_post('submit', false); + + $form_key = 'acp_icons'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } $mode = ($mode == 'smilies') ? 'smilies' : 'icons'; @@ -822,6 +831,11 @@ class acp_icons case 'move_up': case 'move_down': + if (!check_link_hash($request->variable('hash', ''), 'acp_icons')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + // Get current order id... $sql = "SELECT {$fields}_order as current_order FROM $table @@ -941,8 +955,8 @@ class acp_icons 'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '', 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row[$fields . '_id'], 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row[$fields . '_id'], - 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start, - 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start, + 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start . '&hash=' . generate_link_hash('acp_icons'), + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start . '&hash=' . generate_link_hash('acp_icons'), )); if (!$spacer && !$row['display_on_posting']) diff --git a/phpBB/includes/acp/acp_inactive.php b/phpBB/includes/acp/acp_inactive.php index 7ec43f45cc..ec256e93ef 100644 --- a/phpBB/includes/acp/acp_inactive.php +++ b/phpBB/includes/acp/acp_inactive.php @@ -164,6 +164,7 @@ class acp_inactive { if (!$auth->acl_get('a_userdel')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 03172e475a..4baff921b6 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -244,6 +244,11 @@ class acp_language break; case 'install': + if (!check_link_hash($request->variable('hash', ''), 'acp_language')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $lang_iso = $request->variable('iso', ''); $lang_iso = basename($lang_iso); @@ -405,7 +410,7 @@ class acp_language 'ISO' => htmlspecialchars($lang_ary['iso']), 'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'), 'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'), - 'U_INSTALL' => $this->u_action . '&action=install&iso=' . urlencode($lang_ary['iso'])) + 'U_INSTALL' => $this->u_action . '&action=install&iso=' . urlencode($lang_ary['iso']) . '&hash=' . generate_link_hash('acp_language')) ); } } diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index f44bbbc88d..8697504c77 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -118,6 +118,7 @@ class acp_main case 'online': if (!$auth->acl_get('a_board')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -134,6 +135,7 @@ class acp_main case 'stats': if (!$auth->acl_get('a_board')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -189,6 +191,7 @@ class acp_main case 'user': if (!$auth->acl_get('a_board')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -256,6 +259,7 @@ class acp_main case 'date': if (!$auth->acl_get('a_board')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -372,6 +376,7 @@ class acp_main case 'purge_sessions': if ((int) $user->data['user_type'] !== USER_FOUNDER) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php index d3ecffe81e..4d90b2da8b 100644 --- a/phpBB/includes/acp/acp_modules.php +++ b/phpBB/includes/acp/acp_modules.php @@ -50,6 +50,9 @@ class acp_modules $user->add_lang('acp/modules'); $this->tpl_name = 'acp_modules'; + $form_key = 'acp_modules'; + add_form_key($form_key); + // module class $this->module_class = $mode; @@ -130,6 +133,11 @@ class acp_modules trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } + if (!check_link_hash($request->variable('hash', ''), 'acp_modules')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + $sql = 'SELECT * FROM ' . MODULES_TABLE . " WHERE module_class = '" . $db->sql_escape($this->module_class) . "' @@ -161,6 +169,11 @@ class acp_modules trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); } + if (!check_link_hash($request->variable('hash', ''), 'acp_modules')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + $sql = 'SELECT * FROM ' . MODULES_TABLE . " WHERE module_class = '" . $db->sql_escape($this->module_class) . "' @@ -305,6 +318,11 @@ class acp_modules if ($submit) { + if (!check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + if (!$module_data['module_langname']) { trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); @@ -506,12 +524,12 @@ class acp_modules 'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false, 'U_MODULE' => $this->u_action . '&parent_id=' . $row['module_id'], - 'U_MOVE_UP' => $url . '&action=move_up', - 'U_MOVE_DOWN' => $url . '&action=move_down', + 'U_MOVE_UP' => $url . '&action=move_up&hash=' . generate_link_hash('acp_modules'), + 'U_MOVE_DOWN' => $url . '&action=move_down&hash=' . generate_link_hash('acp_modules'), 'U_EDIT' => $url . '&action=edit', 'U_DELETE' => $url . '&action=delete', - 'U_ENABLE' => $url . '&action=enable', - 'U_DISABLE' => $url . '&action=disable') + 'U_ENABLE' => $url . '&action=enable&hash=' . generate_link_hash('acp_modules'), + 'U_DISABLE' => $url . '&action=disable&hash=' . generate_link_hash('acp_modules')) ); } while ($row = $db->sql_fetchrow($result)); @@ -538,8 +556,8 @@ class acp_modules 'U_EDIT' => $url . '&action=edit', 'U_DELETE' => $url . '&action=delete', - 'U_ENABLE' => $url . '&action=enable', - 'U_DISABLE' => $url . '&action=disable') + 'U_ENABLE' => $url . '&action=enable&hash=' . generate_link_hash('acp_modules'), + 'U_DISABLE' => $url . '&action=disable&hash=' . generate_link_hash('acp_modules')) ); } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php index 93aca295d7..0bfe67830f 100644 --- a/phpBB/includes/acp/acp_permission_roles.php +++ b/phpBB/includes/acp/acp_permission_roles.php @@ -367,6 +367,11 @@ class acp_permission_roles case 'move_up': case 'move_down': + if (!check_link_hash($request->variable('hash', ''), 'acp_permission_roles')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'SELECT role_order FROM ' . ACL_ROLES_TABLE . " WHERE role_id = $role_id"; @@ -441,8 +446,8 @@ class acp_permission_roles 'U_EDIT' => $this->u_action . '&action=edit&role_id=' . $row['role_id'], 'U_REMOVE' => $this->u_action . '&action=remove&role_id=' . $row['role_id'], - 'U_MOVE_UP' => $this->u_action . '&action=move_up&role_id=' . $row['role_id'], - 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&role_id=' . $row['role_id'], + 'U_MOVE_UP' => $this->u_action . '&action=move_up&role_id=' . $row['role_id'] . '&hash=' . generate_link_hash('acp_permission_roles'), + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&role_id=' . $row['role_id'] . '&hash=' . generate_link_hash('acp_permission_roles'), 'U_DISPLAY_ITEMS' => ($row['role_id'] == $display_item) ? '' : $this->u_action . '&display_item=' . $row['role_id'] . '#assigned_to') ); diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index fdac7c4d00..df3e238bcc 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -315,6 +315,7 @@ class acp_permissions case 'apply_permissions': if (!isset($_POST['setting'])) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } if (!check_form_key($form_name)) @@ -328,6 +329,7 @@ class acp_permissions case 'apply_all_permissions': if (!isset($_POST['setting'])) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } if (!check_form_key($form_name)) @@ -687,6 +689,7 @@ class acp_permissions // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -772,6 +775,7 @@ class acp_permissions // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -884,6 +888,7 @@ class acp_permissions // Check the permission setting again if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 69672ebec0..c4888cfc7c 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -56,6 +56,9 @@ class acp_profile $error = array(); + $form_key = 'acp_profile'; + add_form_key($form_key); + if (!$field_id && in_array($action, array('delete','activate', 'deactivate', 'move_up', 'move_down', 'edit'))) { trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); @@ -166,6 +169,11 @@ class acp_profile case 'activate': + if (!check_link_hash($request->variable('hash', ''), 'acp_profile')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'SELECT lang_id FROM ' . LANG_TABLE . " WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; @@ -206,6 +214,11 @@ class acp_profile case 'deactivate': + if (!check_link_hash($request->variable('hash', ''), 'acp_profile')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " SET field_active = 0 WHERE field_id = $field_id"; @@ -235,6 +248,11 @@ class acp_profile case 'move_up': case 'move_down': + if (!check_link_hash($request->variable('hash', ''), 'acp_profile')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'SELECT field_order FROM ' . PROFILE_FIELDS_TABLE . " WHERE field_id = $field_id"; @@ -584,6 +602,11 @@ class acp_profile if (!sizeof($error)) { + if (!check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + if (($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save)) { $this->save_profile_field($cp, $field_type, $action); @@ -740,12 +763,12 @@ class acp_profile 'FIELD_TYPE' => $profile_field->get_name(), 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang], - 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&action=$active_value&field_id=$id", + 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&action=$active_value&field_id=$id" . '&hash=' . generate_link_hash('acp_profile'), 'U_EDIT' => $this->u_action . "&action=edit&field_id=$id", 'U_TRANSLATE' => $this->u_action . "&action=edit&field_id=$id&step=3", 'U_DELETE' => $this->u_action . "&action=delete&field_id=$id", - 'U_MOVE_UP' => $this->u_action . "&action=move_up&field_id=$id", - 'U_MOVE_DOWN' => $this->u_action . "&action=move_down&field_id=$id", + 'U_MOVE_UP' => $this->u_action . "&action=move_up&field_id=$id" . '&hash=' . generate_link_hash('acp_profile'), + 'U_MOVE_DOWN' => $this->u_action . "&action=move_down&field_id=$id" . '&hash=' . generate_link_hash('acp_profile'), 'S_NEED_EDIT' => $s_need_edit) ); diff --git a/phpBB/includes/acp/acp_reasons.php b/phpBB/includes/acp/acp_reasons.php index 0d221bba3c..b9b313c9db 100644 --- a/phpBB/includes/acp/acp_reasons.php +++ b/phpBB/includes/acp/acp_reasons.php @@ -281,6 +281,11 @@ class acp_reasons case 'move_up': case 'move_down': + if (!check_link_hash($request->variable('hash', ''), 'acp_reasons')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'SELECT reason_order FROM ' . REPORTS_REASONS_TABLE . " WHERE reason_id = $reason_id"; @@ -382,8 +387,8 @@ class acp_reasons 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['reason_id'], 'U_DELETE' => (!$other_reason) ? $this->u_action . '&action=delete&id=' . $row['reason_id'] : '', - 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row['reason_id'], - 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row['reason_id']) + 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row['reason_id'] . '&hash=' . generate_link_hash('acp_reasons'), + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row['reason_id'] . '&hash=' . generate_link_hash('acp_reasons')) ); } $db->sql_freeresult($result); diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 1f0e8ef539..9a72162c29 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -54,6 +54,13 @@ class acp_search global $config, $phpbb_admin_path, $phpEx; $submit = (isset($_POST['submit'])) ? true : false; + $form_key = 'acp_search'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } $search_types = $this->get_search_types(); @@ -244,6 +251,15 @@ class acp_search $this->state = array(); $this->save_state(); } + $submit = $request->is_set_post('submit', false); + + $form_key = 'acp_search'; + add_form_key($form_key); + + if (!check_form_key($form_key) && in_array($action, array('delete', 'create'))) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } if ($action) { diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php index e42367d8a1..b88e6d3984 100644 --- a/phpBB/includes/acp/acp_update.php +++ b/phpBB/includes/acp/acp_update.php @@ -67,7 +67,7 @@ class acp_update // Incomplete update? if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<')) { - $database_update_link = append_sid($phpbb_root_path . 'install/database_update.' . $phpEx); + $database_update_link = $phpbb_root_path . 'install/app.php/update'; $template->assign_vars(array( 'S_UPDATE_INCOMPLETE' => true, diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 5091fcae7e..a37396a713 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -205,6 +205,7 @@ class acp_users { if (!$auth->acl_get('a_userdel')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 5f8519bb41..bec4dbc27a 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2264,6 +2264,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_ADMIN'); } @@ -2280,6 +2281,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); } + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_ADMIN'); } @@ -2301,6 +2303,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa { // We log the attempt to use a different username... $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_ADMIN_AUTH_FAIL'); + + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_ADMIN_USER_DIFFER'); } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 5cf65e04ba..13b2b29274 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -65,7 +65,7 @@ function recalc_nested_sets(&$new_id, $pkey, $table, $parent_id = 0, $where = ar */ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false) { - global $db, $auth; + global $db, $auth, $phpbb_dispatcher; // This query is identical to the jumpbox one $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, forum_flags, forum_options, left_id, right_id @@ -73,16 +73,33 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = ORDER BY left_id ASC'; $result = $db->sql_query($sql, 600); + $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $rowset[(int) $row['forum_id']] = $row; + } + $db->sql_freeresult($result); + $right = 0; $padding_store = array('0' => ''); $padding = ''; $forum_list = ($return_array) ? array() : ''; + /** + * Modify the forum list data + * + * @event core.make_forum_select_modify_forum_list + * @var array rowset Array with the forums list data + * @since 3.1.10-RC1 + */ + $vars = array('rowset'); + extract($phpbb_dispatcher->trigger_event('core.make_forum_select_modify_forum_list', compact($vars))); + // Sometimes it could happen that forums will be displayed here not be displayed within the index page // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions. // If this happens, the padding could be "broken" - while ($row = $db->sql_fetchrow($result)) + foreach ($rowset as $row) { if ($row['left_id'] < $right) { @@ -133,8 +150,7 @@ function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = $forum_list .= '<option value="' . $row['forum_id'] . '"' . (($disabled) ? ' disabled="disabled" class="disabled-option"' : $selected) . '>' . $padding . $row['forum_name'] . '</option>'; } } - $db->sql_freeresult($result); - unset($padding_store); + unset($padding_store, $rowset); return $forum_list; } diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 173ea49acc..e36eb8119b 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -163,16 +163,33 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list ORDER BY left_id ASC'; $result = $db->sql_query($sql, 600); + $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $rowset[(int) $row['forum_id']] = $row; + } + $db->sql_freeresult($result); + $right = $padding = 0; $padding_store = array('0' => 0); $display_jumpbox = false; $iteration = 0; + /** + * Modify the jumpbox forum list data + * + * @event core.make_jumpbox_modify_forum_list + * @var array rowset Array with the forums list data + * @since 3.1.10-RC1 + */ + $vars = array('rowset'); + extract($phpbb_dispatcher->trigger_event('core.make_jumpbox_modify_forum_list', compact($vars))); + // Sometimes it could happen that forums will be displayed here not be displayed within the index page // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions. // If this happens, the padding could be "broken" - while ($row = $db->sql_fetchrow($result)) + foreach ($rowset as $row) { if ($row['left_id'] < $right) { @@ -254,8 +271,7 @@ function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list } $iteration++; } - $db->sql_freeresult($result); - unset($padding_store); + unset($padding_store, $rowset); $url_parts = $phpbb_path_helper->get_url_parts($action); diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php index 1659d4b252..d61ce3d098 100644 --- a/phpBB/includes/functions_download.php +++ b/phpBB/includes/functions_download.php @@ -254,11 +254,21 @@ function send_file_to_browser($attachment, $upload_dir, $category) send_status_line(206, 'Partial Content'); header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']); header('Content-Length: ' . $range['bytes_requested']); - } - while (!feof($fp)) + // First read chunks + while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192) + { + echo fread($fp, 8192); + } + // Then, read the remainder + echo fread($fp, $range['bytes_requested'] % 8192); + } + else { - echo fread($fp, 8192); + while (!feof($fp)) + { + echo fread($fp, 8192); + } } fclose($fp); } @@ -284,7 +294,7 @@ function header_filename($file) // There be dragons here. // Not many follows the RFC... - if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Safari') !== false || strpos($user_agent, 'Konqueror') !== false) + if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false) { return "filename=" . rawurlencode($file); } @@ -529,6 +539,9 @@ function phpbb_find_range_request() */ function phpbb_parse_range_request($request_array, $filesize) { + $first_byte_pos = -1; + $last_byte_pos = -1; + // Go through all ranges foreach ($request_array as $range_string) { @@ -540,62 +553,61 @@ function phpbb_parse_range_request($request_array, $filesize) continue; } + // Substitute defaults if ($range[0] === '') { - // Return last $range[1] bytes. - - if (!$range[1]) - { - continue; - } + $range[0] = 0; + } - if ($range[1] >= $filesize) - { - return false; - } + if ($range[1] === '') + { + $range[1] = $filesize - 1; + } - $first_byte_pos = $filesize - (int) $range[1]; - $last_byte_pos = $filesize - 1; + if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0]) + { + // We only support contiguous ranges, no multipart stuff :( + return false; } - else + + if ($range[1] && $range[1] < $range[0]) { - // Return bytes from $range[0] to $range[1] + // The requested range contains 0 bytes. + continue; + } + // Return bytes from $range[0] to $range[1] + if ($first_byte_pos < 0) + { $first_byte_pos = (int) $range[0]; - $last_byte_pos = (int) $range[1]; - - if ($last_byte_pos && $last_byte_pos < $first_byte_pos) - { - // The requested range contains 0 bytes. - continue; - } + } - if ($first_byte_pos >= $filesize) - { - // Requested range not satisfiable - return false; - } + $last_byte_pos = (int) $range[1]; - // Adjust last-byte-pos if it is absent or greater than the content. - if ($range[1] === '' || $last_byte_pos >= $filesize) - { - $last_byte_pos = $filesize - 1; - } + if ($first_byte_pos >= $filesize) + { + // Requested range not satisfiable + return false; } - // We currently do not support range requests that end before the end of the file - if ($last_byte_pos != $filesize - 1) + // Adjust last-byte-pos if it is absent or greater than the content. + if ($range[1] === '' || $last_byte_pos >= $filesize) { - continue; + $last_byte_pos = $filesize - 1; } + } - return array( - 'byte_pos_start' => $first_byte_pos, - 'byte_pos_end' => $last_byte_pos, - 'bytes_requested' => $last_byte_pos - $first_byte_pos + 1, - 'bytes_total' => $filesize, - ); + if ($first_byte_pos < 0 || $last_byte_pos < 0) + { + return false; } + + return array( + 'byte_pos_start' => $first_byte_pos, + 'byte_pos_end' => $last_byte_pos, + 'bytes_requested' => $last_byte_pos - $first_byte_pos + 1, + 'bytes_total' => $filesize, + ); } /** diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index d92934e59e..69c3dad9e6 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -801,6 +801,7 @@ function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_fol if (!$row) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } @@ -965,6 +966,7 @@ function handle_mark_actions($user_id, $mark_action) if (!$auth->acl_get('u_pm_delete')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_DELETE_MESSAGE'); } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index a3dfafb000..f29f974ccf 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -3020,7 +3020,7 @@ function remove_default_rank($group_id, $user_ids) */ function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false) { - global $db, $auth, $user, $phpbb_container, $phpbb_log; + global $db, $auth, $user, $phpbb_container, $phpbb_log, $phpbb_dispatcher; // We need both username and user_id info $result = user_get_id_name($user_id_ary, $username_ary); @@ -3152,6 +3152,28 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna break; } + /** + * Event to perform additional actions on setting user group attributes + * + * @event core.user_set_group_attributes + * @var int group_id ID of the group + * @var string group_name Name of the group + * @var array user_id_ary IDs of the users to set group attributes + * @var array username_ary Names of the users to set group attributes + * @var array group_attributes Group attributes which were changed + * @var string action Action to perform over the group members + * @since 3.1.10-RC1 + */ + $vars = array( + 'group_id', + 'group_name', + 'user_id_ary', + 'username_ary', + 'group_attributes', + 'action', + ); + extract($phpbb_dispatcher->trigger_event('core.user_set_group_attributes', compact($vars))); + // Clear permissions cache of relevant users $auth->acl_clear_prefetch($user_id_ary); diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index dc4d59cc46..e381210331 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -274,7 +274,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['width'] : '', 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['height'] : '', 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', - 'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'POSTS_DELETED') : '', + 'DELETED_IMG' => ($topic_deleted) ? $user->img('icon_topic_deleted', 'TOPIC_DELETED') : '', 'TOPIC_AUTHOR' => get_username_string('username', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']), diff --git a/phpBB/includes/mcp/mcp_logs.php b/phpBB/includes/mcp/mcp_logs.php index fca0412321..c34c915a40 100644 --- a/phpBB/includes/mcp/mcp_logs.php +++ b/phpBB/includes/mcp/mcp_logs.php @@ -83,6 +83,7 @@ class mcp_logs if (!in_array($forum_id, $forum_list)) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } @@ -101,6 +102,7 @@ class mcp_logs if (!in_array($forum_id, $forum_list)) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 1ccced7a2f..9060cc1098 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -622,6 +622,7 @@ class mcp_queue if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } @@ -877,6 +878,7 @@ class mcp_queue if (!phpbb_check_ids($topic_id_list, TOPICS_TABLE, 'topic_id', array('m_approve'))) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } @@ -1074,6 +1076,7 @@ class mcp_queue if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index 3809ea2616..1462acf110 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -542,6 +542,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) { if (!$auth->acl_getf_global('m_report')) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } } @@ -549,6 +550,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) { if (!phpbb_check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report'))) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } } diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 00044340df..1e54c18dc1 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -67,6 +67,7 @@ class ucp_activate { login_box('', $user->lang['NO_AUTH_OPERATION']); } + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_OPERATION'); } diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index faffbe5bdc..352b7d1ec3 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -87,6 +87,7 @@ class ucp_groups if (!$auth->acl_get('u_chggrp')) { + send_status_line(403, 'Forbidden'); trigger_error($user->lang['NOT_AUTHORISED'] . $return_page); } diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index 217d46b767..77ac1dfb54 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -35,7 +35,7 @@ class ucp_main function main($id, $mode) { - global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $phpbb_dispatcher; global $request; switch ($mode) @@ -215,6 +215,14 @@ class ucp_main $unwatch = (isset($_POST['unwatch'])) ? true : false; + /** + * Read and potentially modify the post data used to remove subscriptions to forums/topics + * + * @event core.ucp_main_subscribed_post_data + * @since 3.1.10-RC1 + */ + $phpbb_dispatcher->dispatch('core.ucp_main_subscribed_post_data'); + if ($unwatch) { if (check_form_key('ucp_front_subscribed')) @@ -299,6 +307,20 @@ class ucp_main $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); } + /** + * Modify the query used to retrieve a list of subscribed forums + * + * @event core.ucp_main_subscribed_forums_modify_query + * @var array sql_array The subscribed forums query + * @var array forbidden_forums The list of forbidden forums + * @since 3.1.10-RC1 + */ + $vars = array( + 'sql_array', + 'forbidden_forums', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_subscribed_forums_modify_query', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql); @@ -340,7 +362,7 @@ class ucp_main $last_post_time = $last_post_url = ''; } - $template->assign_block_vars('forumrow', array( + $template_vars = array( 'FORUM_ID' => $forum_id, 'FORUM_IMG_STYLE' => $folder_image, 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), @@ -359,8 +381,36 @@ class ucp_main 'S_UNREAD_FORUM' => $unread_forum, 'U_LAST_POST' => $last_post_url, - 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id'])) + 'U_VIEWFORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) + ); + + /** + * Add template variables to a subscribed forum row. + * + * @event core.ucp_main_subscribed_forum_modify_template_vars + * @var array template_vars Array containing the template variables for the row + * @var array row Array containing the subscribed forum row data + * @var int forum_id Forum ID + * @var string folder_image Folder image + * @var string folder_alt Alt text for the folder image + * @var bool unread_forum Whether the forum has unread content or not + * @var string last_post_time The time of the most recent post, expressed as a formatted date string + * @var string last_post_url The URL of the most recent post in the forum + * @since 3.1.10-RC1 + */ + $vars = array( + 'template_vars', + 'row', + 'forum_id', + 'folder_image', + 'folder_alt', + 'unread_forum', + 'last_post_time', + 'last_post_url', ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_subscribed_forum_modify_template_vars', compact($vars))); + + $template->assign_block_vars('forumrow', $template_vars); } $db->sql_freeresult($result); } @@ -642,7 +692,7 @@ class ucp_main */ function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array()) { - global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container, $request; + global $user, $db, $template, $config, $cache, $auth, $phpbb_root_path, $phpEx, $phpbb_container, $request, $phpbb_dispatcher; /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); @@ -664,6 +714,23 @@ class ucp_main AND i.user_id = ' . $user->data['user_id'] . ' AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), ); + + /** + * Modify the query used to retrieve the count of subscribed/bookmarked topics + * + * @event core.ucp_main_topiclist_count_modify_query + * @var array sql_array The subscribed/bookmarked topics query + * @var array forbidden_forum_ary The list of forbidden forums + * @var string mode The type of topic list ('subscribed' or 'bookmarks') + * @since 3.1.10-RC1 + */ + $vars = array( + 'sql_array', + 'forbidden_forum_ary', + 'mode', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_count_modify_query', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query($sql); $topics_count = (int) $db->sql_fetchfield('topics_count'); @@ -732,6 +799,22 @@ class ucp_main $sql_array['SELECT'] .= ', tp.topic_posted'; } + /** + * Modify the query used to retrieve the list of subscribed/bookmarked topics + * + * @event core.ucp_main_topiclist_modify_query + * @var array sql_array The subscribed/bookmarked topics query + * @var array forbidden_forum_ary The list of forbidden forums + * @var string mode The type of topic list ('subscribed' or 'bookmarks') + * @since 3.1.10-RC1 + */ + $vars = array( + 'sql_array', + 'forbidden_forum_ary', + 'mode', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_modify_query', compact($vars))); + $sql = $db->sql_build_query('SELECT', $sql_array); $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); @@ -797,7 +880,7 @@ class ucp_main $view_topic_url = append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params); // Send vars to template - $template->assign_block_vars('topicrow', array( + $template_vars = array( 'FORUM_ID' => $forum_id, 'TOPIC_ID' => $topic_id, 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), @@ -839,7 +922,41 @@ class ucp_main 'U_LAST_POST' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", $view_topic_url_params . '&p=' . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], 'U_VIEW_TOPIC' => $view_topic_url, 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_id), - )); + ); + + /** + * Add template variables to a subscribed/bookmarked topic row. + * + * @event core.ucp_main_topiclist_topic_modify_template_vars + * @var array template_vars Array containing the template variables for the row + * @var array row Array containing the subscribed/bookmarked topic row data + * @var int forum_id ID of the forum containing the topic + * @var int topic_id Topic ID + * @var int replies Number of replies in the topic + * @var string topic_type Topic type + * @var string folder_img Folder image + * @var string folder_alt Alt text for the folder image + * @var array icons Array containing topic icons + * @var bool unread_topic Whether the topic has unread content or not + * @var string view_topic_url The URL of the topic + * @since 3.1.10-RC1 + */ + $vars = array( + 'template_vars', + 'row', + 'forum_id', + 'topic_id', + 'replies', + 'topic_type', + 'folder_img', + 'folder_alt', + 'icons', + 'unread_topic', + 'view_topic_url', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_main_topiclist_topic_modify_template_vars', compact($vars))); + + $template->assign_block_vars('topicrow', $template_vars); $pagination->generate_template_pagination(append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $row['forum_id'] . "&t=$topic_id"), 'topicrow.pagination', 'start', $replies + 1, $config['posts_per_page'], 1, true, true); } diff --git a/phpBB/includes/ucp/ucp_pm.php b/phpBB/includes/ucp/ucp_pm.php index 33dff97fe6..d145d66f59 100644 --- a/phpBB/includes/ucp/ucp_pm.php +++ b/phpBB/includes/ucp/ucp_pm.php @@ -166,6 +166,7 @@ class ucp_pm if (!$auth->acl_get('u_readpm')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_READ_MESSAGE'); } diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index ad9a99204f..b61a9fab9f 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -171,6 +171,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) case 'post': if (!$auth->acl_get('u_sendpm')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_SEND_MESSAGE'); } break; @@ -186,6 +187,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if (!$auth->acl_get('u_sendpm')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_SEND_MESSAGE'); } @@ -226,6 +228,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) case 'delete': if (!$auth->acl_get('u_pm_delete')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_DELETE_MESSAGE'); } @@ -251,11 +254,13 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward'))) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_FORWARD_MESSAGE'); } if ($action == 'edit' && !$auth->acl_get('u_pm_edit')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_EDIT_MESSAGE'); } @@ -321,6 +326,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { if (($post['forum_id'] && !$auth->acl_get('f_read', $post['forum_id'])) || (!$post['forum_id'] && !$auth->acl_getf_global('f_read'))) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } @@ -456,6 +462,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group'))) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_GROUP_MESSAGE'); } diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 2457ea9a2e..48d14a133c 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -41,6 +41,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) $message = $user->lang['NO_AUTH_READ_REMOVED_MESSAGE']; $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>'); + send_status_line(403, 'Forbidden'); trigger_error($message); } diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index a9f8e10eef..a86c4f2672 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -279,6 +279,7 @@ class ucp_profile // Do not display profile information panel if not authed to do so if (!$auth->acl_get('u_chgprofileinfo')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_PROFILEINFO'); } @@ -464,6 +465,7 @@ class ucp_profile if (!$auth->acl_get('u_sig')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_SIGNATURE'); } diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 0a46674fb1..a44f077693 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -79,6 +79,7 @@ class ucp_remind if (!$auth2->acl_get('u_chgpasswd')) { + send_status_line(403, 'Forbidden'); trigger_error('NO_AUTH_PASSWORD_REMINDER'); } diff --git a/phpBB/language/en/acp/search.php b/phpBB/language/en/acp/search.php index bda965b615..c52b71c121 100644 --- a/phpBB/language/en/acp/search.php +++ b/phpBB/language/en/acp/search.php @@ -54,7 +54,7 @@ $lang = array_merge($lang, array( 'DELETING_INDEX_IN_PROGRESS_EXPLAIN' => 'The search backend is currently cleaning its index. This can take a few minutes.', 'FULLTEXT_MYSQL_INCOMPATIBLE_DATABASE' => 'The MySQL fulltext backend can only be used with MySQL4 and above.', - 'FULLTEXT_MYSQL_NOT_SUPPORTED' => 'MySQL fulltext indexes can only be used with MyISAM or InnoDB tables. MySQL 5.6.4 or later is required for fulltext indexes on InnoDB tables.', + 'FULLTEXT_MYSQL_NOT_SUPPORTED' => 'MySQL fulltext indexes can only be used with MyISAM or InnoDB tables. MySQL 5.6.8 or later is required for fulltext indexes on InnoDB tables.', 'FULLTEXT_MYSQL_TOTAL_POSTS' => 'Total number of indexed posts', 'FULLTEXT_MYSQL_MIN_SEARCH_CHARS_EXPLAIN' => 'Words with at least this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.', 'FULLTEXT_MYSQL_MAX_SEARCH_CHARS_EXPLAIN' => 'Words with no more than this many characters will be indexed for searching. You or your host can only change this setting by changing the mysql configuration.', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index b67b87959d..a6aef9797a 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -222,7 +222,7 @@ $lang = array_merge($lang, array( 'UPDATE_INCOMPLETE_MORE' => 'Please read the information below in order to fix this error.', 'UPDATE_INCOMPLETE_EXPLAIN' => '<h1>Incomplete update</h1> - <p>We noticed that the last update of your phpBB installation hasn’t been completed. Visit the <a href="%1$s" title="%1$s">database_update script</a> and run it. If it is missing, please <a href="https://www.phpbb.com/downloads/" title="phpBB downloads">download your package version</a>, upload the "install" folder to your phpBB root directory (where your config.php file is) and <a href="%1$s" title="%1$s">run the database update script</a>.</p>', + <p>We noticed that the last update of your phpBB installation hasn’t been completed. Visit the <a href="%1$s" title="%1$s">database updater</a>, ensure <em>Update database only</em> is selected and click on <strong>Submit</strong>. Don\'t forget to delete the "install"-directory after you have updated the database sucessfully.</p>', // // Server data diff --git a/phpBB/language/en/migrator.php b/phpBB/language/en/migrator.php index 78364319a1..8a82d40be5 100644 --- a/phpBB/language/en/migrator.php +++ b/phpBB/language/en/migrator.php @@ -69,9 +69,12 @@ $lang = array_merge($lang, array( 'MIGRATION_INVALID_DATA_UNDEFINED_METHOD' => 'A migration is invalid. An undefined migration tool method was encountered.', 'MODULE_ERROR' => 'An error occurred while creating a module: %s', + 'MODULE_EXISTS' => 'A module already exists: %s', + 'MODULE_EXIST_MULTIPLE' => 'Several modules with the given parent module langname already exist: %s. Try using before/after keys to clarify the module placement.', 'MODULE_INFO_FILE_NOT_EXIST' => 'A required module info file is missing: %2$s', 'MODULE_NOT_EXIST' => 'A required module does not exist: %s', + 'PARENT_MODULE_FIND_ERROR' => 'Unable to determine the parent module identifier: %s', 'PERMISSION_NOT_EXIST' => 'The permission setting "%s" unexpectedly does not exist.', 'ROLE_NOT_EXIST' => 'The permission role "%s" unexpectedly does not exist.', diff --git a/phpBB/mcp.php b/phpBB/mcp.php index a5fa09ba2b..a5464f4a73 100644 --- a/phpBB/mcp.php +++ b/phpBB/mcp.php @@ -127,6 +127,7 @@ if (!$auth->acl_getf_global('m_')) if (!$allow_user) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } } @@ -134,6 +135,7 @@ if (!$auth->acl_getf_global('m_')) // if the user cannot read the forum he tries to access then we won't allow mcp access either if ($forum_id && !$auth->acl_get('f_read', $forum_id)) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index bfa28d8d11..e816e06488 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -75,6 +75,7 @@ switch ($mode) { if ($user->data['user_id'] != ANONYMOUS) { + send_status_line(403, 'Forbidden'); trigger_error('NO_VIEW_USERS'); } @@ -372,6 +373,7 @@ switch ($mode) if (!$auth->acl_get('u_sendim')) { + send_status_line(403, 'Forbidden'); trigger_error('NOT_AUTHORISED'); } diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index 147b8ebbff..bf7dc2c703 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -428,7 +428,35 @@ class content_visibility 'post_delete_time' => ((int) $time) ?: time(), 'post_delete_reason' => truncate_string($reason, 255, 255, false), ); - + /** + * Perform actions right before the query to change post visibility + * + * @event core.set_post_visibility_before_sql + * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} + * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are 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 user_id User ID doing this action. + * @var int timestamp 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 + */ + $vars = array( + 'visibility', + 'post_id', + 'topic_id', + 'forum_id', + 'user_id', + 'timestamp', + 'reason', + 'is_starter', + 'is_latest', + 'data', + ); + extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_before_sql', compact($vars))); $sql = 'UPDATE ' . $this->posts_table . ' SET ' . $this->db->sql_build_array('UPDATE', $data) . ' WHERE ' . $this->db->sql_in_set('post_id', $post_ids); @@ -585,7 +613,35 @@ class content_visibility WHERE topic_id = ' . (int) $topic_id; $this->db->sql_query($sql); } - + /** + * Perform actions after all steps to changing post visibility + * + * @event core.set_post_visibility_after + * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} + * @var array post_id Array containing all post IDs to be modified. If blank, all posts within the topic are 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 user_id User ID doing this action. + * @var int timestamp 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 + */ + $vars = array( + 'visibility', + 'post_id', + 'topic_id', + 'forum_id', + 'user_id', + 'timestamp', + 'reason', + 'is_starter', + 'is_latest', + 'data', + ); + extract($this->phpbb_dispatcher->trigger_event('core.set_post_visibility_after', compact($vars))); return $data; } @@ -645,7 +701,31 @@ class content_visibility 'topic_delete_time' => ((int) $time) ?: time(), 'topic_delete_reason' => truncate_string($reason, 255, 255, false), ); - + /** + * Perform actions right before the query to change topic visibility + * + * @event core.set_topic_visibility_before_sql + * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} + * @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 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 + */ + $vars = array( + 'visibility', + 'topic_id', + 'forum_id', + 'user_id', + 'timestamp', + 'reason', + 'force_update_all', + 'data', + ); + extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_before_sql', compact($vars))); $sql = 'UPDATE ' . $this->topics_table . ' SET ' . $this->db->sql_build_array('UPDATE', $data) . ' WHERE topic_id = ' . (int) $topic_id; @@ -670,7 +750,31 @@ class content_visibility { $this->set_post_visibility($visibility, false, $topic_id, $forum_id, $user_id, $time, '', true, true); } - + /** + * Perform actions after all steps to changing topic visibility + * + * @event core.set_topic_visibility_after + * @var int visibility Element of {ITEM_APPROVED, ITEM_DELETED, ITEM_REAPPROVE} + * @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 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 + */ + $vars = array( + 'visibility', + 'topic_id', + 'forum_id', + 'user_id', + 'timestamp', + 'reason', + 'force_update_all', + 'data', + ); + extract($this->phpbb_dispatcher->trigger_event('core.set_topic_visibility_after', compact($vars))); return $data; } diff --git a/phpBB/phpbb/db/migration/data/v310/timezone.php b/phpBB/phpbb/db/migration/data/v310/timezone.php index b1a7504c06..03a8d1ab34 100644 --- a/phpBB/phpbb/db/migration/data/v310/timezone.php +++ b/phpBB/phpbb/db/migration/data/v310/timezone.php @@ -103,7 +103,7 @@ class timezone extends \phpbb\db\migration\migration */ public function convert_phpbb30_timezone($timezone, $dst) { - $offset = (int) $timezone + (int) $dst; + $offset = (float) $timezone + (int) $dst; switch ($timezone) { diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index 90ed63e2e6..a7dffbb7f2 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -41,6 +41,9 @@ class module implements \phpbb\db\migration\tool\tool_interface /** @var string */ protected $modules_table; + /** @var array */ + protected $module_categories = array(); + /** * Constructor * @@ -94,30 +97,8 @@ class module implements \phpbb\db\migration\tool\tool_interface $parent_sql = ''; if ($parent !== false) { - // Allows '' to be sent as 0 - $parent = $parent ?: 0; - - if (!is_numeric($parent)) - { - $sql = 'SELECT module_id - FROM ' . $this->modules_table . " - WHERE module_langname = '" . $this->db->sql_escape($parent) . "' - AND module_class = '" . $this->db->sql_escape($class) . "'"; - $result = $this->db->sql_query($sql); - $module_id = $this->db->sql_fetchfield('module_id'); - $this->db->sql_freeresult($result); - - if (!$module_id) - { - return false; - } - - $parent_sql = 'AND parent_id = ' . (int) $module_id; - } - else - { - $parent_sql = 'AND parent_id = ' . (int) $parent; - } + $parent = $this->get_parent_module_id($parent, $module); + $parent_sql = 'AND parent_id = ' . (int) $parent; } $sql = 'SELECT module_id @@ -180,15 +161,14 @@ class module implements \phpbb\db\migration\tool\tool_interface { global $user, $phpbb_log; - // Allows '' to be sent as 0 - $parent = $parent ?: 0; - // allow sending the name as a string in $data to create a category if (!is_array($data)) { $data = array('module_langname' => $data); } + $parent = $data['parent_id'] = $this->get_parent_module_id($parent, $data); + if (!isset($data['module_langname'])) { // The "automatic" way @@ -218,31 +198,14 @@ class module implements \phpbb\db\migration\tool\tool_interface } // The "manual" way - if (!is_numeric($parent)) - { - $sql = 'SELECT module_id - FROM ' . $this->modules_table . " - WHERE module_langname = '" . $this->db->sql_escape($parent) . "' - AND module_class = '" . $this->db->sql_escape($class) . "'"; - $result = $this->db->sql_query($sql); - $module_id = $this->db->sql_fetchfield('module_id'); - $this->db->sql_freeresult($result); - - if (!$module_id) - { - throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); - } - - $parent = $data['parent_id'] = $module_id; - } - else if (!$this->exists($class, false, $parent)) + if (!$this->exists($class, false, $parent)) { throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent); } if ($this->exists($class, $parent, $data['module_langname'])) { - return; + throw new \phpbb\db\migration\exception('MODULE_EXISTS', $module_id); } $module_data = array( @@ -374,26 +337,8 @@ class module implements \phpbb\db\migration\tool\tool_interface $parent_sql = ''; if ($parent !== false) { - // Allows '' to be sent as 0 - $parent = ($parent) ?: 0; - - if (!is_numeric($parent)) - { - $sql = 'SELECT module_id - FROM ' . $this->modules_table . " - WHERE module_langname = '" . $this->db->sql_escape($parent) . "' - AND module_class = '" . $this->db->sql_escape($class) . "'"; - $result = $this->db->sql_query($sql); - $module_id = $this->db->sql_fetchfield('module_id'); - $this->db->sql_freeresult($result); - - // we know it exists from the module_exists check - $parent_sql = 'AND parent_id = ' . (int) $module_id; - } - else - { - $parent_sql = 'AND parent_id = ' . (int) $parent; - } + $parent = $this->get_parent_module_id($parent, $module); + $parent_sql = 'AND parent_id = ' . (int) $parent; } $module_ids = array(); @@ -475,4 +420,110 @@ class module implements \phpbb\db\migration\tool\tool_interface return array_pop($module); } + + /** + * Get the list of installed module categories + * key - module_id + * value - module_langname + * + * @return null + */ + protected function get_categories_list() + { + // Select the top level categories + // and 2nd level [sub]categories which exist for ACP only + $sql = 'SELECT m2.module_id, m2.module_langname + FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2 + WHERE m1.parent_id = 0 + AND (m1.module_id = m2.module_id + OR m2.module_class = 'acp' AND m2.parent_id = m1.module_id) + ORDER BY m1.module_id, m2.module_id ASC"; + + $result = $this->db->sql_query($sql); + while ($row = $this->db->sql_fetchrow($result)) + { + $this->module_categories[(int) $row['module_id']] = $row['module_langname']; + } + $this->db->sql_freeresult($result); + } + + /** + * Get parent module id + * + * @param string|int $parent_id The parent module_id|module_langname + * @param int|string|array $data The module_id, module_langname for existance checking or module data array for adding + * @return int The parent module_id + * @throws \phpbb\db\migration\exception + */ + public function get_parent_module_id($parent_id, $data = '') + { + // Allow '' to be sent as 0 + $parent_id = $parent_id ?: 0; + + // If automatic adding is in action, convert array back to string to simplify things + if (is_array($data) && sizeof($data) == 1) + { + $data = $data['module_langname']; + } + + if (!is_numeric($parent_id)) + { + // Refresh the $module_categories array + $this->get_categories_list(); + + // Search for the parent module_langname + $ids = array_keys($this->module_categories, $parent_id); + + switch (sizeof($ids)) + { + // No parent with the given module_langname exist + case 0: + throw new \phpbb\db\migration\exception('MODULE_NOT_EXIST', $parent_id); + break; + + // Return the module id + case 1: + $parent_id = (int) $ids[0]; + break; + + // Several modules with the given module_langname were found + // Try to determine the parent_id by the neighbour module parent + default: + if (is_array($data) && (isset($data['before']) || isset($data['after']))) + { + $neighbour_module_langname = isset($data['before']) ? $data['before'] : $data['after']; + $sql = 'SELECT parent_id + FROM ' . $this->modules_table . " + WHERE module_langname = '" . $this->db->sql_escape($neighbour_module_langname) . "' + AND " . $this->db->sql_in_set('parent_id', $ids); + $result = $this->db->sql_query($sql); + $parent_id = (int) $this->db->sql_fetchfield('parent_id'); + if (!$parent_id) + { + throw new \phpbb\db\migration\exception('PARENT_MODULE_FIND_ERROR', $data['parent_id']); + } + } + else if (!empty($data) && !is_array($data)) + { + // The module_langname is set, checking for the module existance + // As more than 1 parents were found already, there's no way for null parent_id here + $sql = 'SELECT m2.module_id as module_parent_id + FROM ' . $this->modules_table . ' m1, ' . $this->modules_table . " m2 + WHERE " . ((is_numeric($data)) ? 'm1.module_id = ' . (int) $data : "m1.module_langname = '" . $this->db->sql_escape($data)) . "' + AND m2.module_id = m1.parent_id + AND " . $this->db->sql_in_set('m2.module_id', $ids); + $result = $this->db->sql_query($sql); + $parent_id = (int) $this->db->sql_fetchfield('module_parent_id'); + } + else + { + //Unable to get the parent module id, throwing an exception + throw new \phpbb\db\migration\exception('MODULE_EXIST_MULTIPLE', $parent_id); + } + break; + } + } + + return $parent_id; + } } diff --git a/phpBB/phpbb/feed/forum.php b/phpBB/phpbb/feed/forum.php index 6701c4d9e7..f522e91169 100644 --- a/phpBB/phpbb/feed/forum.php +++ b/phpBB/phpbb/feed/forum.php @@ -74,6 +74,14 @@ class forum extends post_base // Make sure we can read this forum if (!$this->auth->acl_get('f_read', $this->forum_id)) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } throw new unauthorized_forum_exception($this->forum_id); } @@ -84,6 +92,14 @@ class forum extends post_base if (isset($forum_ids_passworded[$this->forum_id])) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } throw new unauthorized_forum_exception($this->forum_id); } diff --git a/phpBB/phpbb/feed/topic.php b/phpBB/phpbb/feed/topic.php index f029c2b00e..e5f2c41468 100644 --- a/phpBB/phpbb/feed/topic.php +++ b/phpBB/phpbb/feed/topic.php @@ -66,6 +66,14 @@ class topic extends post_base // Make sure topic is either approved or user authed if ($this->topic_data['topic_visibility'] != ITEM_APPROVED && !$this->auth->acl_get('m_approve', $this->forum_id)) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } throw new unauthorized_topic_exception($this->topic_id); } @@ -78,6 +86,14 @@ class topic extends post_base // Make sure we can read this forum if (!$this->auth->acl_get('f_read', $this->forum_id)) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } throw new unauthorized_forum_exception($this->forum_id); } @@ -88,6 +104,14 @@ class topic extends post_base if (isset($forum_ids_passworded[$this->forum_id])) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } throw new unauthorized_forum_exception($this->forum_id); } diff --git a/phpBB/phpbb/message/topic_form.php b/phpBB/phpbb/message/topic_form.php index 174643bb81..dbb883c142 100644 --- a/phpBB/phpbb/message/topic_form.php +++ b/phpBB/phpbb/message/topic_form.php @@ -71,6 +71,14 @@ class topic_form extends form if (!$this->auth->acl_get('f_read', $this->topic_row['forum_id'])) { + if ($this->user->data['user_id'] != ANONYMOUS) + { + send_status_line(403, 'Forbidden'); + } + else + { + send_status_line(401, 'Unauthorized'); + } return 'SORRY_AUTH_READ'; } diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index d1962bc8cc..73d7bc1574 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -177,8 +177,10 @@ class fulltext_mysql extends \phpbb\search\base $engine === 'MyISAM' || // FULLTEXT is supported on InnoDB since MySQL 5.6.4 according to // http://dev.mysql.com/doc/refman/5.6/en/innodb-storage-engine.html + // We also require https://bugs.mysql.com/bug.php?id=67004 to be + // fixed for proper overall operation. Hence we require 5.6.8. $engine === 'InnoDB' && - phpbb_version_compare($this->db->sql_server_info(true), '5.6.4', '>='); + phpbb_version_compare($this->db->sql_server_info(true), '5.6.8', '>='); if (!$fulltext_supported) { diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 0fec092d52..580d9b6878 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -1261,7 +1261,7 @@ class fulltext_native extends \phpbb\search\base if (!$total_results && $is_mysql) { // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it. - $sql_calc = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql); + $sql_calc = str_replace('SELECT ' . $select, 'SELECT SQL_CALC_FOUND_ROWS ' . $select, $sql); $result = $this->db->sql_query($sql_calc); $this->db->sql_freeresult($result); diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 12031bda03..518cee4705 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1602,7 +1602,7 @@ class session $this->data = array_merge($this->data, $sql_ary); - if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) + if ($this->data['user_id'] != ANONYMOUS && isset($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) { $this->leave_newly_registered(); } diff --git a/phpBB/search.php b/phpBB/search.php index 3d8c05fed9..fdd4aec7ae 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -129,6 +129,26 @@ $phpbb_content_visibility = $phpbb_container->get('content.visibility'); /* @var $pagination \phpbb\pagination */ $pagination = $phpbb_container->get('pagination'); +/** +* This event allows you to alter the above parameters, such as keywords and submit +* +* @event core.search_modify_submit_parameters +* @var string keywords The search keywords +* @var string author Specifies the author match, when ANONYMOUS is also a search-match +* @var int author_id ID of the author to search by +* @var string search_id Predefined search type name +* @var bool submit Whether or not the form has been submitted +* @since 3.1.10-RC1 +*/ +$vars = array( + 'keywords', + 'author', + 'author_id', + 'search_id', + 'submit', +); +extract($phpbb_dispatcher->trigger_event('core.search_modify_submit_parameters', compact($vars))); + if ($keywords || $author || $author_id || $search_id || $submit) { // clear arrays @@ -628,11 +648,16 @@ if ($keywords || $author || $author_id || $search_id || $submit) * @event core.search_modify_url_parameters * @var string u_search Search URL parameters string * @var string search_id Predefined search type name + * @var string sql_where The SQL WHERE string used by search to get topic data + * @var int total_match_count The total number of search matches * @since 3.1.7-RC1 + * @changed 3.1.10-RC1 Added sql_where, total_match_count */ $vars = array( 'u_search', 'search_id', + 'sql_where', + 'total_match_count', ); extract($phpbb_dispatcher->trigger_event('core.search_modify_url_parameters', compact($vars))); diff --git a/phpBB/styles/prosilver/template/forumlist_body.html b/phpBB/styles/prosilver/template/forumlist_body.html index 5cbb177455..211f402503 100644 --- a/phpBB/styles/prosilver/template/forumlist_body.html +++ b/phpBB/styles/prosilver/template/forumlist_body.html @@ -79,12 +79,12 @@ <dd class="lastpost"> <span> <!-- IF forumrow.U_UNAPPROVED_TOPICS --> - <a href="{forumrow.U_UNAPPROVED_TOPICS}" title="{TOPICS_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPICS_UNAPPROVED}</span> + <a href="{forumrow.U_UNAPPROVED_TOPICS}" title="{L_TOPICS_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPICS_UNAPPROVED}</span> </a> <!-- ELSEIF forumrow.U_UNAPPROVED_POSTS --> - <a href="{forumrow.U_UNAPPROVED_POSTS}" title="{POSTS_UNAPPROVED_FORUM}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{POSTS_UNAPPROVED_FORUM}</span> + <a href="{forumrow.U_UNAPPROVED_POSTS}" title="{L_POSTS_UNAPPROVED_FORUM}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_POSTS_UNAPPROVED_FORUM}</span> </a> <!-- ENDIF --> <!-- IF forumrow.LAST_POST_TIME --> @@ -95,8 +95,8 @@ <!-- ENDIF --> {L_POST_BY_AUTHOR} {forumrow.LAST_POSTER_FULL} <!-- IF not S_IS_BOT --> - <a href="{forumrow.U_LAST_POST}" title="{VIEW_LATEST_POST}"> - <i class="icon fa-external-link-square fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{VIEW_LATEST_POST}</span> + <a href="{forumrow.U_LAST_POST}" title="{L_VIEW_LATEST_POST}"> + <i class="icon fa-external-link-square fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{L_VIEW_LATEST_POST}</span> </a> <!-- ENDIF --> <br />{forumrow.LAST_POST_TIME} diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html index acef09dc47..8f24c4128e 100644 --- a/phpBB/styles/prosilver/template/mcp_forum.html +++ b/phpBB/styles/prosilver/template/mcp_forum.html @@ -46,18 +46,18 @@ <a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a> <!-- EVENT mcp_forum_topic_title_after --> <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPIC_UNAPPROVED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_DELETED or topicrow.S_POSTS_DELETED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_DELETED"> - <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{TOPIC_DELETED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}"> + <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_REPORTED --> - <a href="{topicrow.U_MCP_REPORT}" title="{TOPIC_REPORTED}"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> + <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}"> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_MOVED_TOPIC and S_CAN_DELETE --> <a href="{topicrow.U_DELETE_TOPIC}" class="topictitle">[ {L_DELETE_SHADOW_TOPIC} ]</a><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index c7b52bb3a5..a0de554e21 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -102,7 +102,7 @@ <!-- IF S_MESSAGE_REPORTED --> <p class="post-notice reported"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> <a href="{U_MCP_REPORT}"><strong>{L_MESSAGE_REPORTED}</strong></a> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> <a href="{U_MCP_REPORT}"><strong>{L_MESSAGE_REPORTED}</strong></a> </p> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html index 32e5f0236c..d64c9c9a21 100644 --- a/phpBB/styles/prosilver/template/mcp_topic.html +++ b/phpBB/styles/prosilver/template/mcp_topic.html @@ -73,7 +73,7 @@ <dl> <dt><label for="to_topic_id">{L_MERGE_TOPIC_ID}{L_COLON}</label></dt> <dd> - <input class="inputbox autowidth" type="number" min="0" max="999999" name="to_topic_id" id="to_topic_id" value="{TO_TOPIC_ID}" /> + <input class="inputbox autowidth" type="number" min="0" max="9999999999" name="to_topic_id" id="to_topic_id" value="{TO_TOPIC_ID}" /> <a href="{U_SELECT_TOPIC}" >{L_SELECT_TOPIC}</a> </dd> <!-- IF TO_TOPIC_INFO --><dd>{TO_TOPIC_INFO}</dd><!-- ENDIF --> @@ -112,11 +112,15 @@ </ul> <h3><a href="{postrow.U_POST_DETAILS}">{postrow.POST_SUBJECT}</a></h3> + + <!-- EVENT mcp_topic_postrow_post_details_before --> <p class="author"> <a href="#pr{postrow.POST_ID}" title="{postrow.MINI_POST}"> <i class="icon fa-file fa-fw icon-lightgray icon-tiny" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span> </a> {L_POSTED} {postrow.POST_DATE} {L_POST_BY_AUTHOR} <strong>{postrow.POST_AUTHOR_FULL}</strong><!-- IF postrow.U_MCP_DETAILS --> [ <a href="{postrow.U_MCP_DETAILS}">{L_POST_DETAILS}</a> ]<!-- ENDIF --> </p> + <!-- EVENT mcp_topic_postrow_post_details_after --> + <!-- IF postrow.S_POST_UNAPPROVED --> <p class="post-notice unapproved"> <a href="{postrow.U_MCP_APPROVE}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_UNAPPROVED}</strong></a> diff --git a/phpBB/styles/prosilver/template/posting_editor.html b/phpBB/styles/prosilver/template/posting_editor.html index 0d526cd72f..d963c98e08 100644 --- a/phpBB/styles/prosilver/template/posting_editor.html +++ b/phpBB/styles/prosilver/template/posting_editor.html @@ -23,7 +23,11 @@ <!-- IF S_POST_ACTION or S_PRIVMSGS or S_EDIT_DRAFT --> <dl style="clear: left;"> <dt><label for="subject">{L_SUBJECT}{L_COLON}</label></dt> - <dd><input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /></dd> + <dd> + <!-- EVENT posting_editor_subject_prepend --> + <input type="text" name="subject" id="subject" size="45" maxlength="<!-- IF S_NEW_MESSAGE -->120<!-- ELSE -->124<!-- ENDIF -->" tabindex="2" value="{SUBJECT}{DRAFT_SUBJECT}" class="inputbox autowidth" /> + <!-- EVENT posting_editor_subject_append --> + </dd> </dl> <!-- IF CAPTCHA_TEMPLATE and S_CONFIRM_CODE --> <!-- DEFINE $CAPTCHA_TAB_INDEX = 3 --> diff --git a/phpBB/styles/prosilver/template/posting_topic_review.html b/phpBB/styles/prosilver/template/posting_topic_review.html index dae0095105..3d7856d27a 100644 --- a/phpBB/styles/prosilver/template/posting_topic_review.html +++ b/phpBB/styles/prosilver/template/posting_topic_review.html @@ -43,6 +43,7 @@ </ul> <!-- ENDIF --> + <!-- EVENT posting_topic_review_row_post_details_before --> <p class="author"> <!-- IF S_IS_BOT --> <span><i class="icon fa-file fa-fw icon-lightgray icon-md" aria-hidden="true"></i><span class="sr-only">{topic_review_row.MINI_POST}</span></span> @@ -53,6 +54,8 @@ <!-- ENDIF --> {L_POST_BY_AUTHOR} <strong>{topic_review_row.POST_AUTHOR_FULL}</strong> » {topic_review_row.POST_DATE} </p> + <!-- EVENT posting_topic_review_row_post_details_after --> + <div class="content">{topic_review_row.MESSAGE}</div> <!-- IF topic_review_row.S_HAS_ATTACHMENTS --> diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html index 8dc91555dc..f7114567e5 100644 --- a/phpBB/styles/prosilver/template/search_results.html +++ b/phpBB/styles/prosilver/template/search_results.html @@ -84,23 +84,23 @@ <!-- EVENT topiclist_row_prepend --> <!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT --> <a class="unread" href="{searchresults.U_NEWEST_POST}"> - <i class="icon fa-file fa-fw icon-red icon-md" aria-hidden="true"></i><span class="sr-only">{NEW_POST}</span> + <i class="icon fa-file fa-fw icon-red icon-md" aria-hidden="true"></i><span class="sr-only">{L_NEW_POST}</span> </a> <!-- ENDIF --> <a href="{searchresults.U_VIEW_TOPIC}" class="topictitle">{searchresults.TOPIC_TITLE}</a> <!-- IF searchresults.S_TOPIC_UNAPPROVED or searchresults.S_POSTS_UNAPPROVED --> - <a href="{searchresults.U_MCP_QUEUE}" title="{TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPIC_UNAPPROVED}</span> + <a href="{searchresults.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> </a> <!-- ENDIF --> <!-- IF searchresults.S_TOPIC_DELETED --> - <a href="{searchresults.U_MCP_QUEUE}" title="{TOPIC_DELETED}"> - <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{TOPIC_DELETED}</span> + <a href="{searchresults.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}"> + <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span> </a> <!-- ENDIF --> <!-- IF searchresults.S_TOPIC_REPORTED --> - <a href="{searchresults.U_MCP_REPORT}" title="{TOPIC_REPORTED}"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> + <a href="{searchresults.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}"> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> </a> <!-- ENDIF --> <br /> diff --git a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html index c4b7abdd55..25647afe1a 100644 --- a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html +++ b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html @@ -44,13 +44,13 @@ </a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a> <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPIC_UNAPPROVED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_REPORTED --> - <a href="{topicrow.U_MCP_REPORT}" title="{TOPIC_REPORTED}"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> + <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}"> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> </a> <!-- ENDIF --> <br /> diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html index 03c06b84e2..3bd1d5ca14 100644 --- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html +++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html @@ -87,13 +87,13 @@ </a> <!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a> <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPIC_UNAPPROVED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_REPORTED --> - <a href="{topicrow.U_MCP_REPORT}" title="{TOPIC_REPORTED}"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> + <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}"> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> </a> <!-- ENDIF --> <br /> diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 446a9906dd..9824989687 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -126,6 +126,8 @@ <!-- ENDIF --> +<!-- EVENT viewforum_body_topic_row_before --> + <!-- BEGIN topicrow --> <!-- IF not topicrow.S_TOPIC_TYPE_SWITCH and not topicrow.S_FIRST_ROW --> @@ -150,7 +152,7 @@ <ul class="topiclist topics"> <!-- ENDIF --> - <!-- EVENT viewforum_body_topic_row_before --> + <!-- EVENT viewforum_body_topicrow_row_before --> <li class="row<!-- IF topicrow.S_ROW_COUNT is even --> bg1<!-- ELSE --> bg2<!-- ENDIF --><!-- IF topicrow.S_POST_GLOBAL --> global-announce<!-- ENDIF --><!-- IF topicrow.S_POST_ANNOUNCE --> announce<!-- ENDIF --><!-- IF topicrow.S_POST_STICKY --> sticky<!-- ENDIF --><!-- IF topicrow.S_TOPIC_REPORTED --> reported<!-- ENDIF -->"> <!-- EVENT viewforum_body_topic_row_prepend --> <dl class="row-item {topicrow.TOPIC_IMG_STYLE}"> @@ -165,18 +167,18 @@ <!-- ENDIF --> <a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a> <!-- IF topicrow.S_TOPIC_UNAPPROVED or topicrow.S_POSTS_UNAPPROVED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_UNAPPROVED}"> - <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{TOPIC_UNAPPROVED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_UNAPPROVED}"> + <i class="icon fa-question fa-fw icon-blue" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_UNAPPROVED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_DELETED --> - <a href="{topicrow.U_MCP_QUEUE}" title="{TOPIC_DELETED}"> - <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{TOPIC_DELETED}</span> + <a href="{topicrow.U_MCP_QUEUE}" title="{L_TOPIC_DELETED}"> + <i class="icon fa-recycle fa-fw icon-green" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_DELETED}</span> </a> <!-- ENDIF --> <!-- IF topicrow.S_TOPIC_REPORTED --> - <a href="{topicrow.U_MCP_REPORT}" title="{TOPIC_REPORTED}"> - <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{TOPIC_REPORTED}</span> + <a href="{topicrow.U_MCP_REPORT}" title="{L_TOPIC_REPORTED}"> + <i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><span class="sr-only">{L_TOPIC_REPORTED}</span> </a> <!-- ENDIF --> <br /> diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css index a6d4bef6f4..f09493ab3b 100644 --- a/phpBB/styles/prosilver/theme/bidi.css +++ b/phpBB/styles/prosilver/theme/bidi.css @@ -922,6 +922,7 @@ li.breadcrumbs span:first-child > a { .rtl .search-header .button-search-end { border: 0; + border-radius: 4px 0 0 4px; } .rtl .search-header { diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php index 812df396fa..cdffe69155 100644 --- a/phpBB/viewforum.php +++ b/phpBB/viewforum.php @@ -91,6 +91,7 @@ if (!$auth->acl_gets('f_list', 'f_read', $forum_id) || ($forum_data['forum_type' { if ($user->data['user_id'] != ANONYMOUS) { + send_status_line(403, 'Forbidden'); trigger_error('SORRY_AUTH_READ'); } diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index e8698d9916..3f35ac541e 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -37,6 +37,7 @@ if (!$auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) { if ($user->data['user_id'] != ANONYMOUS) { + send_status_line(403, 'Forbidden'); trigger_error('NO_VIEW_USERS'); } diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index ded0f9aacc..4325fafb43 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -376,6 +376,7 @@ if (!$overrides_f_read_check && !$auth->acl_get('f_read', $forum_id)) { if ($user->data['user_id'] != ANONYMOUS) { + send_status_line(403, 'Forbidden'); trigger_error('SORRY_AUTH_READ'); } diff --git a/tests/dbal/fixtures/migrator_module.xml b/tests/dbal/fixtures/migrator_module.xml index 32afe7e6f3..e172d7a145 100644 --- a/tests/dbal/fixtures/migrator_module.xml +++ b/tests/dbal/fixtures/migrator_module.xml @@ -20,7 +20,7 @@ <value>acp</value> <value>0</value> <value>1</value> - <value>4</value> + <value>6</value> <value>ACP_CAT</value> <value></value> <value></value> @@ -38,5 +38,57 @@ <value>test</value> <value></value> </row> + <row> + <value>3</value> + <value>1</value> + <value>1</value> + <value></value> + <value>acp</value> + <value>1</value> + <value>4</value> + <value>5</value> + <value>ACP_FORUM_BASED_PERMISSIONS</value> + <value></value> + <value></value> + </row> + <row> + <value>4</value> + <value>1</value> + <value>1</value> + <value></value> + <value>acp</value> + <value>0</value> + <value>7</value> + <value>12</value> + <value>ACP_CAT_FORUMS</value> + <value></value> + <value></value> + </row> + <row> + <value>5</value> + <value>1</value> + <value>1</value> + <value></value> + <value>acp</value> + <value>4</value> + <value>8</value> + <value>11</value> + <value>ACP_FORUM_BASED_PERMISSIONS</value> + <value></value> + <value></value> + </row> + <row> + <value>6</value> + <value>1</value> + <value>1</value> + <value></value> + <value>acp</value> + <value>5</value> + <value>9</value> + <value>10</value> + <value>ACP_FORUM_BASED_PERMISSIONS_CHILD_1</value> + <value></value> + <value></value> + </row> </table> </dataset> diff --git a/tests/dbal/migrator_tool_module_test.php b/tests/dbal/migrator_tool_module_test.php index c2252c8d10..1744b7e92d 100644 --- a/tests/dbal/migrator_tool_module_test.php +++ b/tests/dbal/migrator_tool_module_test.php @@ -121,6 +121,44 @@ class phpbb_dbal_migrator_tool_module_test extends phpbb_database_test_case $this->fail($e); } $this->assertEquals(true, $this->tool->exists('acp', 'ACP_NEW_CAT', 'ACP_NEW_MODULE')); + + // Test adding module when plural parent module_langname exists + // PHPBB3-14703 + // Adding fail + try + { + $this->tool->add('acp', 'ACP_FORUM_BASED_PERMISSIONS', array( + 'module_basename' => 'acp_new_permissions_module', + 'module_langname' => 'ACP_NEW_PERMISSIONS_MODULE', + 'module_mode' => 'test', + 'module_auth' => '', + )); + $this->fail('Exception not thrown'); + } + catch (Exception $e) + { + $this->assertEquals('phpbb\db\migration\exception', get_class($e)); + $this->assertEquals('MODULE_EXIST_MULTIPLE', $e->getMessage()); + } + + // Test adding module when plural parent module_langname exists + // PHPBB3-14703 + // Adding success + try + { + $this->tool->add('acp', 'ACP_FORUM_BASED_PERMISSIONS', array( + 'module_basename' => 'acp_new_permissions_module', + 'module_langname' => 'ACP_NEW_PERMISSIONS_MODULE', + 'module_mode' => 'test', + 'module_auth' => '', + 'after' => 'ACP_FORUM_BASED_PERMISSIONS_CHILD_1', + )); + } + catch (Exception $e) + { + $this->fail($e); + } + $this->assertEquals(true, $this->tool->exists('acp', 'ACP_FORUM_BASED_PERMISSIONS', 'ACP_NEW_PERMISSIONS_MODULE')); } public function test_remove() diff --git a/tests/download/http_byte_range_test.php b/tests/download/http_byte_range_test.php index f920299048..8975ec1799 100644 --- a/tests/download/http_byte_range_test.php +++ b/tests/download/http_byte_range_test.php @@ -45,24 +45,72 @@ class phpbb_download_http_byte_range_test extends phpbb_test_case public function parse_range_request_data() { return array( - // Does not read until the end of file. + // Valid request array( array('3-4'), 10, - false, + array( + 'byte_pos_start' => 3, + 'byte_pos_end' => 4, + 'bytes_requested' => 2, + 'bytes_total' => 10, + ), ), - // Valid request, handle second range. + // Get the beginning array( - array('0-0', '120-125'), - 125, + array('-5'), + 10, array( - 'byte_pos_start' => 120, - 'byte_pos_end' => 124, + 'byte_pos_start' => 0, + 'byte_pos_end' => 5, + 'bytes_requested' => 6, + 'bytes_total' => 10, + ), + ), + + // Get the end + array( + array('5-'), + 10, + array( + 'byte_pos_start' => 5, + 'byte_pos_end' => 9, 'bytes_requested' => 5, + 'bytes_total' => 10, + ), + ), + + // Overlong request + array( + array('3-20'), + 10, + array( + 'byte_pos_start' => 3, + 'byte_pos_end' => 9, + 'bytes_requested' => 7, + 'bytes_total' => 10, + ), + ), + + // Multiple, contiguous range + array( + array('10-20', '21-30'), + 125, + array( + 'byte_pos_start' => 10, + 'byte_pos_end' => 30, + 'bytes_requested' => 21, 'bytes_total' => 125, ) ), + + // We don't do multiple, non-contiguous range + array( + array('0-0', '120-125'), + 125, + false, + ), ); } } diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php index a3cac381d2..fc6f4c0a0b 100644 --- a/tests/functional/search/base.php +++ b/tests/functional/search/base.php @@ -78,6 +78,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case protected function create_search_index($backend = null) { $this->add_lang('acp/search'); + $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid); + $form_values = $crawler->selectButton('Create index')->form()->getValues(); $crawler = self::request( 'POST', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid, @@ -85,6 +87,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case 'search_type' => ( ($backend === null) ? $this->search_backend : $backend ), 'action' => 'create', 'submit' => true, + 'form_token' => $form_values['form_token'], + 'creation_time' => $form_values['creation_time'], ) ); $this->assertContainsLang('SEARCH_INDEX_CREATED', $crawler->text()); @@ -93,6 +97,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case protected function delete_search_index() { $this->add_lang('acp/search'); + $crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid); + $form_values = $crawler->selectButton('Delete index')->form()->getValues(); $crawler = self::request( 'POST', 'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid, @@ -100,6 +106,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case 'search_type' => $this->search_backend, 'action' => 'delete', 'submit' => true, + 'form_token' => $form_values['form_token'], + 'creation_time' => $form_values['creation_time'], ) ); $this->assertContainsLang('SEARCH_INDEX_REMOVED', $crawler->text()); |
