aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/build.xml6
-rw-r--r--phpBB/adm/style/acp_ban.html2
-rw-r--r--phpBB/adm/style/acp_captcha.html7
-rw-r--r--phpBB/adm/style/acp_email.html4
-rw-r--r--phpBB/adm/style/acp_forums.html2
-rw-r--r--phpBB/adm/style/acp_groups.html4
-rw-r--r--phpBB/adm/style/acp_groups_position.html4
-rw-r--r--phpBB/adm/style/acp_logs.html2
-rw-r--r--phpBB/adm/style/acp_permissions.html12
-rw-r--r--phpBB/adm/style/acp_prune_forums.html2
-rw-r--r--phpBB/adm/style/acp_prune_users.html2
-rw-r--r--phpBB/adm/style/acp_users.html2
-rw-r--r--phpBB/adm/style/install_convert.html134
-rw-r--r--phpBB/adm/style/install_error.html8
-rw-r--r--phpBB/adm/style/install_footer.html21
-rw-r--r--phpBB/adm/style/install_header.html53
-rw-r--r--phpBB/adm/style/install_install.html77
-rw-r--r--phpBB/adm/style/install_main.html6
-rw-r--r--phpBB/adm/style/install_update.html491
-rw-r--r--phpBB/adm/style/install_update_diff.html254
-rw-r--r--phpBB/adm/style/permission_forum_copy.html4
-rw-r--r--phpBB/assets/javascript/core.js4
-rw-r--r--phpBB/assets/javascript/installer.js14
-rw-r--r--phpBB/common.php2
-rw-r--r--phpBB/composer.lock358
-rw-r--r--phpBB/config/default/container/services_files.yml1
-rw-r--r--phpBB/config/default/container/services_notification.yml2
-rw-r--r--phpBB/config/default/container/services_text_reparser.yml7
-rw-r--r--phpBB/config/default/container/tables.yml51
-rw-r--r--phpBB/config/installer/container/parameters.yml3
-rw-r--r--phpBB/config/installer/container/services.yml5
-rw-r--r--phpBB/config/installer/container/services_install_filesystem.yml1
-rw-r--r--phpBB/config/installer/container/services_installer.yml1
-rw-r--r--phpBB/develop/lang_migrate_help_lang.php17
-rw-r--r--phpBB/docs/CHANGELOG.html238
-rw-r--r--phpBB/docs/events.md342
-rw-r--r--phpBB/includes/acp/acp_captcha.php65
-rw-r--r--phpBB/includes/acp/acp_forums.php81
-rw-r--r--phpBB/includes/acp/acp_update.php2
-rw-r--r--phpBB/includes/constants.php5
-rw-r--r--phpBB/includes/functions_acp.php37
-rw-r--r--phpBB/includes/functions_content.php21
-rw-r--r--phpBB/includes/functions_display.php68
-rw-r--r--phpBB/includes/functions_install.php540
-rw-r--r--phpBB/includes/functions_mcp.php95
-rw-r--r--phpBB/includes/functions_posting.php349
-rw-r--r--phpBB/includes/functions_privmsgs.php114
-rw-r--r--phpBB/includes/mcp/mcp_forum.php97
-rw-r--r--phpBB/includes/mcp/mcp_post.php21
-rw-r--r--phpBB/includes/mcp/mcp_queue.php5
-rw-r--r--phpBB/index.php63
-rw-r--r--phpBB/install/app.php (renamed from phpBB/install_new/app.php)13
-rw-r--r--phpBB/install/convertors/convert_phpbb20.php2
-rw-r--r--phpBB/install/database_update.php270
-rw-r--r--phpBB/install/index.php874
-rw-r--r--phpBB/install/install_convert.php2153
-rw-r--r--phpBB/install/install_install.php2368
-rw-r--r--phpBB/install/install_main.php78
-rw-r--r--phpBB/install/install_update.php1789
-rwxr-xr-x[-rw-r--r--]phpBB/install/phpbbcli.php (renamed from phpBB/install_new/phpbbcli.php)10
-rw-r--r--phpBB/install/phpinfo.php14
-rw-r--r--phpBB/install/schemas/schema_data.sql2
-rw-r--r--phpBB/install/startup.php (renamed from phpBB/install_new/startup.php)45
-rw-r--r--phpBB/language/en/acp/common.php8
-rw-r--r--phpBB/language/en/common.php2
-rw-r--r--phpBB/language/en/help/bbcode.php4
-rw-r--r--phpBB/language/en/install.php834
-rw-r--r--phpBB/language/en/install_new.php411
-rw-r--r--phpBB/language/en/memberlist.php1
-rw-r--r--phpBB/memberlist.php35
-rw-r--r--phpBB/phpbb/db/driver/sqlite3.php24
-rw-r--r--phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php7
-rw-r--r--phpBB/phpbb/db/migration/data/v320/announce_global_permission.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v320/dev.php36
-rw-r--r--phpBB/phpbb/db/migration/data/v320/font_awesome_update.php7
-rw-r--r--phpBB/phpbb/db/migration/data/v320/icons_alt.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v320/log_post_id.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v320/notifications_board.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php7
-rw-r--r--phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php4
-rw-r--r--phpBB/phpbb/db/migration/data/v320/v320a1.php44
-rw-r--r--phpBB/phpbb/db/migration/tool/module.php2
-rw-r--r--phpBB/phpbb/files/upload.php7
-rw-r--r--phpBB/phpbb/install/console/command/install/config/show.php2
-rw-r--r--phpBB/phpbb/install/console/command/install/install.php4
-rw-r--r--phpBB/phpbb/install/controller/helper.php3
-rw-r--r--phpBB/phpbb/install/installer.php15
-rw-r--r--phpBB/phpbb/install/module/install_data/task/add_bots.php5
-rw-r--r--phpBB/phpbb/install/module/install_database/task/add_config_settings.php2
-rw-r--r--phpBB/phpbb/install/module/install_database/task/create_schema.php13
-rw-r--r--phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php29
-rw-r--r--phpBB/phpbb/install/module/install_finish/task/notify_user.php15
-rw-r--r--phpBB/phpbb/install/module/install_finish/task/populate_migrations.php2
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php2
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php10
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php2
-rw-r--r--phpBB/phpbb/install/module/update_database/task/update.php2
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php2
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/update_files.php10
-rw-r--r--phpBB/phpbb/language/language.php14
-rw-r--r--phpBB/phpbb/notification/manager.php30
-rw-r--r--phpBB/phpbb/notification/method/board.php1
-rw-r--r--phpBB/phpbb/notification/method/messenger_base.php1
-rw-r--r--phpBB/phpbb/notification/type/admin_activate_user.php2
-rw-r--r--phpBB/phpbb/notification/type/base.php64
-rw-r--r--phpBB/phpbb/notification/type/disapprove_post.php6
-rw-r--r--phpBB/phpbb/notification/type/disapprove_topic.php6
-rw-r--r--phpBB/phpbb/notification/type/group_request.php2
-rw-r--r--phpBB/phpbb/notification/type/group_request_approved.php2
-rw-r--r--phpBB/phpbb/notification/type/pm.php4
-rw-r--r--phpBB/phpbb/notification/type/post.php11
-rw-r--r--phpBB/phpbb/notification/type/quote.php1
-rw-r--r--phpBB/phpbb/notification/type/report_pm.php23
-rw-r--r--phpBB/phpbb/notification/type/report_pm_closed.php4
-rw-r--r--phpBB/phpbb/notification/type/report_post.php16
-rw-r--r--phpBB/phpbb/notification/type/report_post_closed.php4
-rw-r--r--phpBB/phpbb/notification/type/topic.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/forum_description.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/forum_rules.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/group_description.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/pm_text.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/poll_title.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/post_text.php8
-rw-r--r--phpBB/phpbb/textreparser/plugins/user_signature.php8
-rw-r--r--phpBB/phpbb/textreparser/row_based_plugin.php22
-rw-r--r--phpBB/styles/prosilver/style.cfg4
-rw-r--r--phpBB/styles/prosilver/template/ajax.js2
-rw-r--r--phpBB/styles/prosilver/template/display_options.html27
-rw-r--r--phpBB/styles/prosilver/template/mcp_forum.html11
-rw-r--r--phpBB/styles/prosilver/template/mcp_logs.html11
-rw-r--r--phpBB/styles/prosilver/template/mcp_notes_user.html12
-rw-r--r--phpBB/styles/prosilver/template/mcp_post.html2
-rw-r--r--phpBB/styles/prosilver/template/mcp_queue.html12
-rw-r--r--phpBB/styles/prosilver/template/mcp_reports.html12
-rw-r--r--phpBB/styles/prosilver/template/mcp_topic.html4
-rw-r--r--phpBB/styles/prosilver/template/mcp_warn_list.html10
-rw-r--r--phpBB/styles/prosilver/template/memberlist_body.html4
-rw-r--r--phpBB/styles/prosilver/template/search_body.html13
-rw-r--r--phpBB/styles/prosilver/template/search_results.html22
-rw-r--r--phpBB/styles/prosilver/template/ucp_attachments.html12
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_bookmarks.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_front.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_main_subscribed.html2
-rw-r--r--phpBB/styles/prosilver/template/ucp_pm_viewfolder.html15
-rw-r--r--phpBB/styles/prosilver/template/viewforum_body.html36
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_body.html26
-rw-r--r--phpBB/styles/prosilver/theme/bidi.css5
-rw-r--r--phpBB/styles/prosilver/theme/common.css16
-rw-r--r--phpBB/styles/prosilver/theme/content.css6
-rw-r--r--phpBB/styles/prosilver/theme/forms.css18
-rw-r--r--phpBB/styles/prosilver/theme/links.css1
-rw-r--r--phpBB/styles/prosilver/theme/responsive.css33
-rw-r--r--phpBB/viewforum.php2
-rw-r--r--phpBB/viewtopic.php3
-rw-r--r--tests/bootstrap.php2
-rw-r--r--tests/datetime/from_format_test.php4
-rw-r--r--tests/functional/search/base.php7
-rw-r--r--tests/functions_install/ignore_new_file_on_update_test.php45
-rw-r--r--tests/mock/notification_type_post.php3
-rw-r--r--tests/notification/base.php2
-rw-r--r--tests/notification/fixtures/services_notification.yml3
-rw-r--r--tests/notification/submit_post_base.php10
-rw-r--r--tests/notification/user_list_trim_test.php4
-rw-r--r--tests/test_framework/mock/phpbb_mock_null_installer_task.php30
-rw-r--r--tests/test_framework/phpbb_database_test_connection_manager.php8
-rw-r--r--tests/test_framework/phpbb_functional_test_case.php190
-rw-r--r--tests/test_framework/phpbb_ui_test_case.php160
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13451.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-13451.txt1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9791.html1
-rw-r--r--tests/text_processing/tickets_data/PHPBB3-9791.txt1
-rw-r--r--tests/text_reparser/plugins/forum_description_test.php2
-rw-r--r--tests/text_reparser/plugins/forum_rules_test.php2
-rw-r--r--tests/text_reparser/plugins/group_description_test.php2
-rw-r--r--tests/text_reparser/plugins/pm_text_test.php2
-rw-r--r--tests/text_reparser/plugins/poll_title_test.php2
-rw-r--r--tests/text_reparser/plugins/post_text_test.php2
-rw-r--r--tests/text_reparser/plugins/test_row_based_plugin.php7
-rw-r--r--tests/text_reparser/plugins/user_signature_test.php2
-rwxr-xr-xtravis/check-executable-files.sh2
180 files changed, 2693 insertions, 11295 deletions
diff --git a/build/build.xml b/build/build.xml
index 2985218e7b..b85f9b49cb 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -2,9 +2,9 @@
<project name="phpBB" description="The phpBB forum software" default="all" basedir="../">
<!-- a few settings for the build -->
- <property name="newversion" value="3.2.0-a1-dev" />
- <property name="prevversion" value="3.1.6" />
- <property name="olderversions" value="3.0.14, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5" />
+ <property name="newversion" value="3.2.0-a2-dev" />
+ <property name="prevversion" value="3.2.0-a1" />
+ <property name="olderversions" value="3.0.14, 3.1.0, 3.1.1, 3.1.2, 3.1.3, 3.1.4, 3.1.5, 3.1.6" />
<!-- no configuration should be needed beyond this point -->
<property name="oldversions" value="${olderversions}, ${prevversion}" />
diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html
index 9e9f05120a..f2249941a5 100644
--- a/phpBB/adm/style/acp_ban.html
+++ b/phpBB/adm/style/acp_ban.html
@@ -52,7 +52,7 @@
<legend>{L_TITLE}</legend>
<dl>
<dt><label for="ban">{L_BAN_CELL}{L_COLON}</label></dt>
- <dd><textarea name="ban" cols="40" rows="3" id="ban"></textarea></dd>
+ <dd><!-- EVENT acp_ban_cell_prepend --><textarea name="ban" cols="40" rows="3" id="ban"></textarea><!-- EVENT acp_ban_cell_append --></dd>
<!-- IF S_USERNAME_BAN --><dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd><!-- ENDIF -->
</dl>
<dl>
diff --git a/phpBB/adm/style/acp_captcha.html b/phpBB/adm/style/acp_captcha.html
index f4866653c3..0efbbac51e 100644
--- a/phpBB/adm/style/acp_captcha.html
+++ b/phpBB/adm/style/acp_captcha.html
@@ -8,6 +8,13 @@
<p>{L_ACP_VC_EXT_GET_MORE}</p>
+<!-- IF ERROR_MSG -->
+<div class="errorbox">
+ <h3>{L_WARNING}</h3>
+ <p>{ERROR_MSG}</p>
+</div>
+<!-- ENDIF -->
+
<form id="acp_captcha" method="post" action="{U_ACTION}">
<fieldset>
diff --git a/phpBB/adm/style/acp_email.html b/phpBB/adm/style/acp_email.html
index 63acd7fcc1..e14c56ab47 100644
--- a/phpBB/adm/style/acp_email.html
+++ b/phpBB/adm/style/acp_email.html
@@ -19,12 +19,14 @@
<legend>{L_COMPOSE}</legend>
<dl>
<dt><label for="group">{L_SEND_TO_GROUP}{L_COLON}</label></dt>
+ <!-- EVENT acp_email_group_options_prepend -->
<dd><select id="group" name="g">{S_GROUP_OPTIONS}</select></dd>
+ <!-- EVENT acp_email_group_options_append -->
</dl>
<dl>
<dt><label for="usernames">{L_SEND_TO_USERS}{L_COLON}</label><br /><span>{L_SEND_TO_USERS_EXPLAIN}</span></dt>
<dd><textarea name="usernames" id="usernames" rows="5" cols="40">{USERNAMES}</textarea></dd>
- <dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd>
+ <dd><!-- EVENT acp_email_find_username_prepend -->[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]<!-- EVENT acp_email_find_username_append --></dd>
</dl>
<dl>
<dt><label for="subject">{L_SUBJECT}{L_COLON}</label></dt>
diff --git a/phpBB/adm/style/acp_forums.html b/phpBB/adm/style/acp_forums.html
index 0d8b8ad583..dcad90d7bc 100644
--- a/phpBB/adm/style/acp_forums.html
+++ b/phpBB/adm/style/acp_forums.html
@@ -498,7 +498,7 @@
<fieldset class="quick">
{L_SELECT_FORUM}{L_COLON} <select name="parent_id" onchange="if(this.options[this.selectedIndex].value != -1){ this.form.submit(); }">{FORUM_BOX}</select>
- <input class="button2" type="submit" value="{L_GO}" />
+ <!-- EVENT acp_forums_quick_select_button_prepend --><input class="button2" type="submit" value="{L_GO}" /><!-- EVENT acp_forums_quick_select_button_append -->
{S_FORM_TOKEN}
</fieldset>
</form>
diff --git a/phpBB/adm/style/acp_groups.html b/phpBB/adm/style/acp_groups.html
index d24d62497d..23f6e744c0 100644
--- a/phpBB/adm/style/acp_groups.html
+++ b/phpBB/adm/style/acp_groups.html
@@ -236,7 +236,7 @@
<dl>
<dt><label for="usernames">{L_USERNAME}{L_COLON}</label><br /><span>{L_USERNAMES_EXPLAIN}</span></dt>
<dd><textarea id="usernames" name="usernames" cols="40" rows="5"></textarea></dd>
- <dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd>
+ <dd><!-- EVENT acp_groups_find_username_prepend -->[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]<!-- EVENT acp_groups_find_username_append --></dd>
</dl>
<p class="quick">
@@ -265,6 +265,7 @@
<form id="acp_groups" method="post" action="{U_ACTION}">
+ <!-- EVENT acp_groups_manage_before -->
<table class="table1">
<col class="col1" /><col class="col1" /><col class="col2" /><col class="col2" /><col class="col2" />
<thead>
@@ -285,6 +286,7 @@
<!-- ENDIF -->
</tbody>
</table>
+ <!-- EVENT acp_groups_manage_after -->
<fieldset class="quick">
<!-- IF S_GROUP_ADD -->
diff --git a/phpBB/adm/style/acp_groups_position.html b/phpBB/adm/style/acp_groups_position.html
index c01f7aeb03..20ed9521f0 100644
--- a/phpBB/adm/style/acp_groups_position.html
+++ b/phpBB/adm/style/acp_groups_position.html
@@ -65,8 +65,10 @@
<option<!-- IF add_legend.GROUP_SPECIAL --> class="sep"<!-- ENDIF --> value="{add_legend.GROUP_ID}">{add_legend.GROUP_NAME}</option>
<!-- END add_legend -->
</select>
+ <!-- EVENT acp_groups_position_legend_add_button_before -->
<input class="button2" type="submit" name="submit" value="{L_ADD}" />
<input type="hidden" name="action" value="add" />
+ <!-- EVENT acp_groups_position_legend_add_button_after -->
{S_FORM_TOKEN}
</fieldset>
</form>
@@ -162,8 +164,10 @@
<option<!-- IF add_teampage.GROUP_SPECIAL --> class="sep"<!-- ENDIF --> value="{add_teampage.GROUP_ID}">{add_teampage.GROUP_NAME}</option>
<!-- END add_teampage -->
</select>
+ <!-- EVENT acp_groups_position_teampage_add_button_before -->
<input class="button2" type="submit" name="submit" value="{L_ADD}" />
<input type="hidden" name="action" value="add" />
+ <!-- EVENT acp_groups_position_teampage_add_button_after -->
{S_FORM_TOKEN}
</fieldset>
</form>
diff --git a/phpBB/adm/style/acp_logs.html b/phpBB/adm/style/acp_logs.html
index 76ea801de0..cb15a8f51d 100644
--- a/phpBB/adm/style/acp_logs.html
+++ b/phpBB/adm/style/acp_logs.html
@@ -73,7 +73,7 @@
<!-- IF S_SHOW_FORUMS -->
<fieldset class="quick">
{L_SELECT_FORUM}{L_COLON} <select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ this.form.submit(); }">{S_FORUM_BOX}</select>
- <input class="button2" type="submit" value="{L_GO}" />
+ <!-- EVENT acp_logs_quick_select_forum_button_prepend --><input class="button2" type="submit" value="{L_GO}" /><!-- EVENT acp_logs_quick_select_forum_button_append -->
</fieldset>
<!-- ENDIF -->
diff --git a/phpBB/adm/style/acp_permissions.html b/phpBB/adm/style/acp_permissions.html
index 004027df41..7766052c59 100644
--- a/phpBB/adm/style/acp_permissions.html
+++ b/phpBB/adm/style/acp_permissions.html
@@ -30,7 +30,7 @@
<legend>{L_LOOK_UP_FORUM}</legend>
<!-- IF S_FORUM_MULTIPLE --><p>{L_LOOK_UP_FORUMS_EXPLAIN}</p><!-- ENDIF -->
<dl>
- <dt><label for="forum">{L_LOOK_UP_FORUM}{L_COLON}</label></dt>
+ <dt><!-- EVENT acp_permissions_select_multiple_forum_prepend --><label for="forum">{L_LOOK_UP_FORUM}{L_COLON}</label><!-- EVENT acp_permissions_select_multiple_forum_append --></dt>
<dd><select id="forum" name="forum_id[]"<!-- IF S_FORUM_MULTIPLE --> multiple="multiple"<!-- ENDIF --> size="10">{S_FORUM_OPTIONS}</select></dd>
<!-- IF S_FORUM_ALL --><dd><label><input type="checkbox" class="radio" name="all_forums" value="1" /> {L_ALL_FORUMS}</label></dd><!-- ENDIF -->
</dl>
@@ -52,7 +52,7 @@
<legend>{L_LOOK_UP_FORUM}</legend>
<p>{L_SELECT_FORUM_SUBFORUM_EXPLAIN}</p>
<dl>
- <dt><label for="sforum">{L_LOOK_UP_FORUM}{L_COLON}</label></dt>
+ <dt><!-- EVENT acp_permissions_select_forum_prepend --><label for="sforum">{L_LOOK_UP_FORUM}{L_COLON}</label><!-- EVENT acp_permissions_select_forum_append --></dt>
<dd><select id="sforum" name="subforum_id">{S_SUBFORUM_OPTIONS}</select></dd>
</dl>
@@ -95,7 +95,7 @@
<fieldset>
<legend>{L_LOOK_UP_GROUP}</legend>
<dl>
- <dt><label for="group">{L_LOOK_UP_GROUP}{L_COLON}</label></dt>
+ <dt><!-- EVENT acp_permissions_select_group_prepend --><label for="group">{L_LOOK_UP_GROUP}{L_COLON}</label><!-- EVENT acp_permissions_select_group_append --></dt>
<dd><select name="group_id[]" id="group">{S_GROUP_OPTIONS}</select></dd>
</dl>
@@ -140,7 +140,7 @@
<p>{L_USERNAMES_EXPLAIN}</p>
<dl>
<dd class="full"><textarea id="username" name="usernames" rows="5" cols="5" style="width: 100%; height: 60px;"></textarea></dd>
- <dd class="full" style="text-align: left;"><div style="float: {S_CONTENT_FLOW_END};">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</div><label><input type="checkbox" class="radio" id="anonymous" name="user_id[]" value="{ANONYMOUS_USER_ID}" /> {L_SELECT_ANONYMOUS}</label></dd>
+ <dd class="full" style="text-align: left;"><!-- EVENT acp_permissions_find_username_prepend --><div style="float: {S_CONTENT_FLOW_END};">[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</div><!-- EVENT acp_permissions_find_username_append --><label><input type="checkbox" class="radio" id="anonymous" name="user_id[]" value="{ANONYMOUS_USER_ID}" /> {L_SELECT_ANONYMOUS}</label></dd>
</dl>
</fieldset>
@@ -183,7 +183,7 @@
<fieldset>
<legend>{L_ADD_GROUPS}</legend>
<dl>
- <dd class="full"><select name="group_id[]" style="width: 100%; height: 107px;" multiple="multiple">{S_ADD_GROUP_OPTIONS}</select></dd>
+ <dd class="full"><!-- EVENT acp_permissions_add_group_options_prepend --><select name="group_id[]" style="width: 100%; height: 107px;" multiple="multiple">{S_ADD_GROUP_OPTIONS}</select><!-- EVENT acp_permissions_add_group_options_append --></dd>
</dl>
</fieldset>
@@ -267,7 +267,9 @@
<legend>{L_LOOK_UP_GROUP}</legend>
<dl>
<dt><label for="group_select">{L_LOOK_UP_GROUP}{L_COLON}</label></dt>
+ <!-- EVENT acp_permissions_select_group_before -->
<dd><select name="group_id[]" id="group_select">{S_ADD_GROUP_OPTIONS}</select></dd>
+ <!-- EVENT acp_permissions_select_group_after -->
<dd>&nbsp;</dd>
</dl>
</fieldset>
diff --git a/phpBB/adm/style/acp_prune_forums.html b/phpBB/adm/style/acp_prune_forums.html
index 4d748f1cce..b8c681ea00 100644
--- a/phpBB/adm/style/acp_prune_forums.html
+++ b/phpBB/adm/style/acp_prune_forums.html
@@ -43,7 +43,7 @@
<legend>{L_SELECT_FORUM}</legend>
<p>{L_LOOK_UP_FORUMS_EXPLAIN}</p>
<dl>
- <dt><label for="forum">{L_LOOK_UP_FORUM}{L_COLON}</label></dt>
+ <dt><!-- EVENT acp_prune_forums_prepend --><label for="forum">{L_LOOK_UP_FORUM}{L_COLON}</label><!-- EVENT acp_prune_forums_append --></dt>
<dd><select id="forum" name="f[]" multiple="multiple" size="10">{S_FORUM_OPTIONS}</select></dd>
<dd><label><input type="checkbox" class="radio" name="all_forums" value="1" /> {L_ALL_FORUMS}</label></dd>
</dl>
diff --git a/phpBB/adm/style/acp_prune_users.html b/phpBB/adm/style/acp_prune_users.html
index b8c271355b..6e8b2e4214 100644
--- a/phpBB/adm/style/acp_prune_users.html
+++ b/phpBB/adm/style/acp_prune_users.html
@@ -50,7 +50,7 @@
<dl>
<dt><label for="users">{L_ACP_PRUNE_USERS}{L_COLON}</label><br /><span>{L_SELECT_USERS_EXPLAIN}</span></dt>
<dd><textarea id="users" name="users" cols="40" rows="5"></textarea></dd>
- <dd>[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]</dd>
+ <dd><!-- EVENT acp_prune_users_find_username_prepend -->[ <a href="{U_FIND_USERNAME}" onclick="find_username(this.href); return false;">{L_FIND_USERNAME}</a> ]<!-- EVENT acp_prune_users_find_username_append --></dd>
</dl>
</fieldset>
diff --git a/phpBB/adm/style/acp_users.html b/phpBB/adm/style/acp_users.html
index 25064c6f3a..18c3d84f96 100644
--- a/phpBB/adm/style/acp_users.html
+++ b/phpBB/adm/style/acp_users.html
@@ -146,7 +146,9 @@
<!-- IF S_GROUP_OPTIONS -->
<fieldset class="quick">
+ <!-- EVENT acp_users_select_group_before -->
{L_USER_GROUP_ADD}{L_COLON} <select name="g">{S_GROUP_OPTIONS}</select> <input class="button1" type="submit" name="update" value="{L_SUBMIT}" />
+ <!-- EVENT acp_users_select_group_after -->
{S_FORM_TOKEN}
</fieldset>
<!-- ENDIF -->
diff --git a/phpBB/adm/style/install_convert.html b/phpBB/adm/style/install_convert.html
deleted file mode 100644
index 7e22404f56..0000000000
--- a/phpBB/adm/style/install_convert.html
+++ /dev/null
@@ -1,134 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<!-- IF S_NOT_INSTALLED -->
-
- <h1>{TITLE}</h1>
-
- <p>{BODY}</p>
-
-<!-- ELSE -->
-
- <form id="install_convert" method="post" action="{U_ACTION}">
-
- <h1>{TITLE}</h1>
-
- <p>{BODY}</p>
-
- <!-- IF S_ERROR_BOX -->
- <div class="errorbox">
- <h3>{ERROR_TITLE}</h3>
- <p>{ERROR_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <!-- IF S_LIST -->
- <table class="table1">
- <caption>{L_AVAILABLE_CONVERTORS}</caption>
- <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
- <thead>
- <tr>
- <th>{L_SOFTWARE}</th>
- <th>{L_VERSION}</th>
- <th>{L_AUTHOR}</th>
- <th>{L_OPTIONS}</th>
- </tr>
- </thead>
- <tbody>
- <!-- IF .convertors -->
- <!-- BEGIN convertors -->
- <tr>
- <td>{convertors.SOFTWARE}</td>
- <td>{convertors.VERSION}</td>
- <td>{convertors.AUTHOR}</td>
- <td><a href="{convertors.U_CONVERT}">{L_CONVERT}</a></td>
- </tr>
- <!-- END convertors -->
- <!-- ELSE -->
- <tr>
- <td>{L_NO_CONVERTORS}</td>
- <td>-</td>
- <td>-</td>
- <td>-</td>
- </tr>
- <!-- ENDIF -->
- </tbody>
- </table>
- <!-- ENDIF -->
-
- <!-- IF S_CONTINUE -->
- </form>
-
- <fieldset class="submit-buttons">
- <form method="post" action="{U_NEW_ACTION}">
- <input class="button1" type="submit" name="submit_new" value="{L_NEW}" />
- </form>
- <br />
- <form method="post" action="{U_CONTINUE_ACTION}">
- <input class="button1" type="submit" name="submit_cont" value="{L_CONTINUE}" />
- </form>
- </fieldset>
-
- <form method="post" action="{U_ACTION}">
- <!-- ENDIF -->
-
- <!-- IF .checks -->
- <fieldset>
-
- <!-- BEGIN checks -->
- <!-- IF checks.S_LEGEND -->
- <!-- IF not checks.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{checks.LEGEND}</legend>
- <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF -->
- <!-- ELSE -->
-
- <dl>
- <dt><label>{checks.TITLE}{L_COLON}</label><!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{checks.RESULT}</dd>
- </dl>
- <!-- ENDIF -->
- <!-- END checks -->
-
- </fieldset>
- <!-- ENDIF -->
-
- <!-- IF .options -->
- <fieldset>
-
- <!-- BEGIN options -->
- <!-- IF options.S_LEGEND -->
- <!-- IF not options.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{options.LEGEND}</legend>
- <!-- ELSE -->
-
- <dl>
- <dt><label for="{options.KEY}">{options.TITLE}{L_COLON}</label><!-- IF options.S_EXPLAIN --><br /><span class="explain">{options.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{options.CONTENT}</dd>
- </dl>
-
- <!-- ENDIF -->
- <!-- END options -->
-
- </fieldset>
- <!-- ENDIF -->
-
- <!-- IF L_SUBMIT -->
- <!-- IF L_MESSAGE --><p>{L_MESSAGE}</p><!-- ENDIF -->
-
- <fieldset class="submit-buttons">
- {S_HIDDEN}
- <!-- IF L_SUBMIT --><input class="button1<!-- IF S_REFRESH --> disabled<!-- ENDIF -->" type="submit" id="submit" <!-- IF S_REFRESH -->disabled="disabled" <!-- ELSE --> onclick="this.className = 'button1 disabled';" onsubmit="this.disabled = 'disabled';" <!-- ENDIF -->name="submit" value="{L_SUBMIT}" /><!-- ENDIF -->
- </fieldset>
- <!-- ENDIF -->
-
- </form>
-<!-- ENDIF -->
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_error.html b/phpBB/adm/style/install_error.html
deleted file mode 100644
index 3f7c8b9ed4..0000000000
--- a/phpBB/adm/style/install_error.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<div class="errorbox">
- <h3>{MESSAGE_TITLE}</h3>
- <p>{MESSAGE_TEXT}</p>
-</div>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html
deleted file mode 100644
index a29fce6c5a..0000000000
--- a/phpBB/adm/style/install_footer.html
+++ /dev/null
@@ -1,21 +0,0 @@
- </div>
- </div><!-- /#main -->
- </div>
- </div><!-- /#acp -->
- </div>
-
- <div id="page-footer">
- <div class="copyright">
- Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
- </div>
- </div>
-</div>
-
-<script type="text/javascript" src="{T_JQUERY_LINK}"></script>
-<!-- IF S_ALLOW_CDN --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.min.js" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
-<script type="text/javascript" src="{T_ASSETS_PATH}/javascript/core.js?assets_version={T_ASSETS_VERSION}"></script>
-<!-- INCLUDEJS admin.js -->
-{$SCRIPTS}
-
-</body>
-</html>
diff --git a/phpBB/adm/style/install_header.html b/phpBB/adm/style/install_header.html
deleted file mode 100644
index 6f7f129d39..0000000000
--- a/phpBB/adm/style/install_header.html
+++ /dev/null
@@ -1,53 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<!-- IF META -->{META}<!-- ENDIF -->
-<title>{PAGE_TITLE}</title>
-
-<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
-</head>
-
-<body class="{S_CONTENT_DIRECTION} nojs">
-<div id="wrap">
- <div id="page-header">
- <h1>{L_INSTALL_PANEL}</h1>
- <p id="skip"><a href="#acp">{L_SKIP}</a></p>
- <!-- IF S_LANG_SELECT -->
- <form method="post" action="#">
- <fieldset class="nobg">
- <label for="language">{L_SELECT_LANG}{L_COLON}</label>
- {S_LANG_SELECT}
- <input class="button1" type="submit" id="change_lang" name="change_lang" value="{L_CHANGE}" />
- </fieldset>
- </form>
- <!-- ENDIF -->
- </div>
-
- <div id="page-body">
- <div id="tabs">
- <ul>
- <!-- BEGIN t_block1 -->
- <li class="tab<!-- IF t_block1.S_SELECTED --> activetab<!-- ENDIF -->"><a href="{t_block1.U_TITLE}">{t_block1.L_TITLE}</a></li>
- <!-- END t_block1 -->
- </ul>
- </div>
-
- <div id="acp">
- <div id="content">
- <div id="menu">
- <div class="menu-block no-header">
- <ul>
- <!-- BEGIN l_block1 -->
- <li<!-- IF l_block1.S_SELECTED --> id="activemenu"<!-- ENDIF -->><a href="{l_block1.U_TITLE}"><span>{l_block1.L_TITLE}</span></a></li>
- <!-- END l_block1 -->
- <!-- BEGIN l_block2 -->
- <li<!-- IF l_block2.S_SELECTED --> id="activemenu"<!-- ENDIF -->><span<!-- IF l_block2.S_COMPLETE --> class="completed"<!-- ENDIF -->>{l_block2.L_TITLE}</span></li>
- <!-- END l_block2 -->
- </ul>
- </div>
- </div>
-
- <div id="main" class="install-body">
- <div class="main">
diff --git a/phpBB/adm/style/install_install.html b/phpBB/adm/style/install_install.html
deleted file mode 100644
index 1a809a3588..0000000000
--- a/phpBB/adm/style/install_install.html
+++ /dev/null
@@ -1,77 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<form id="install_install" method="post" action="{U_ACTION}" onsubmit="submit.disabled = 'disabled';">
-
-<!-- IF TITLE --><h1>{TITLE}</h1><!-- ENDIF -->
-<!-- IF BODY --><p>{BODY}</p><!-- ENDIF -->
-
-<!-- IF .checks -->
- <fieldset>
-
- <!-- BEGIN checks -->
- <!-- IF checks.S_LEGEND -->
- <!-- IF not checks.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{checks.LEGEND}</legend>
- <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF -->
- <!-- ELSE -->
-
- <dl>
- <dt>{checks.TITLE}{L_COLON}<!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{checks.RESULT}</dd>
- </dl>
- <!-- ENDIF -->
- <!-- END checks -->
-
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF .options -->
- <fieldset>
-
- <!-- BEGIN options -->
- <!-- IF options.S_LEGEND -->
- <!-- IF not options.S_FIRST_ROW -->
- </fieldset>
-
- <fieldset>
- <!-- ENDIF -->
- <legend>{options.LEGEND}</legend>
- <!-- ELSE -->
-
- <dl>
- <dt><label for="{options.KEY}">{options.TITLE}{L_COLON}</label><!-- IF options.S_EXPLAIN --><br /><span class="explain">{options.TITLE_EXPLAIN}</span><!-- ENDIF --></dt>
- <dd>{options.CONTENT}</dd>
- </dl>
-
- <!-- ENDIF -->
- <!-- END options -->
-
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF S_SHOW_DOWNLOAD -->
- <h1>{L_DL_CONFIG}</h1>
- <p>{L_DL_CONFIG_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <legend>{L_DL_CONFIG}</legend>
- {S_HIDDEN}
- <input class="button1" type="submit" id="dlconfig" name="dlconfig" value="{L_DL_DOWNLOAD}" />&nbsp;<input class="button1" type="submit" id="dldone" name="dldone" value="{L_DL_DONE}" />
- </fieldset>
-<!-- ENDIF -->
-
-<!-- IF L_SUBMIT -->
- <fieldset class="submit-buttons">
- <legend>{L_SUBMIT}</legend>
- {S_HIDDEN}
- <!-- IF L_SUBMIT --><input class="button1" type="submit" id="submit" onclick="this.className = 'button1 disabled';" name="submit" value="{L_SUBMIT}" /><!-- ENDIF -->
- </fieldset>
-<!-- ENDIF -->
-
-</form>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_main.html b/phpBB/adm/style/install_main.html
deleted file mode 100644
index 73e73ad578..0000000000
--- a/phpBB/adm/style/install_main.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
- <h1>{TITLE}</h1>
- <p>{BODY}</p>
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_update.html b/phpBB/adm/style/install_update.html
deleted file mode 100644
index 898233f72d..0000000000
--- a/phpBB/adm/style/install_update.html
+++ /dev/null
@@ -1,491 +0,0 @@
-<!-- INCLUDE install_header.html -->
-
-<script type="text/javascript">
-// <![CDATA[
- function popup(url, width, height, name)
- {
- if (!name)
- {
- name = '_popup';
- }
-
- window.open(url.replace(/&amp;/g, '&'), name, 'height=' + height + ',resizable=yes,scrollbars=yes, width=' + width);
- return false;
- }
-
- function diff_popup(url)
- {
- popup(url, 950, 600, '_diff');
- return false;
- }
-// ]]>
-</script>
-
-<!-- IF S_ERROR -->
- <div class="errorbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{ERROR_MSG}</p>
- </div>
-<!-- ENDIF -->
-
-<!-- IF S_IN_PROGRESS -->
-
- <div class="successbox" style="margin-top: 0;">
- <h3>{L_IN_PROGRESS}</h3>
- <p>{L_IN_PROGRESS_EXPLAIN}</p>
- </div>
-
-<!-- ELSEIF S_INTRO -->
-
- <!-- IF S_WARNING -->
- <div class="successbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{WARNING_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <div class="errorbox" style="margin-top: 0;">
- <h3>{L_NOTICE}</h3>
- <p>{L_BACKUP_NOTICE}</p>
- </div>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <h1>{L_UPDATE_INSTALLATION}</h1>
- <p>{L_UPDATE_INSTALLATION_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="submit" value="{L_NEXT_STEP}" />
- </fieldset>
-
- </form>
-
-<!-- ELSEIF S_UPLOAD_SUCCESS -->
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <h1>{L_UPDATE_SUCCESS}</h1>
- <p>{L_UPDATE_SUCCESS_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="check_again" value="{L_CONTINUE_UPDATE}" />
- </fieldset>
-
- </form>
-
-<!-- ENDIF -->
-
-<!-- IF S_VERSION_CHECK -->
-
- <h1>{L_VERSION_CHECK}</h1>
-
- <p>{L_VERSION_CHECK_EXPLAIN}</p>
-
- <!-- IF S_UP_TO_DATE -->
- <div class="successbox">
- <p>{L_VERSION_UP_TO_DATE}</p>
- </div>
- <!-- ELSE -->
- <div class="errorbox">
- <p>{L_VERSION_NOT_UP_TO_DATE}</p>
- </div>
- <!-- ENDIF -->
-
- <fieldset>
- <legend></legend>
- <dl>
- <dt><label>{L_CURRENT_VERSION}</label></dt>
- <dd><strong>{CURRENT_VERSION}</strong></dd>
- </dl>
- <dl>
- <dt><label>{L_LATEST_VERSION}</label></dt>
- <dd><strong>{LATEST_VERSION}</strong></dd>
- </dl>
- <!-- IF PACKAGE_VERSION and not S_UP_TO_DATE -->
- <dl>
- <dt><label>{L_PACKAGE_UPDATES_TO}</label></dt>
- <dd><strong>{PACKAGE_VERSION}</strong></dd>
- </dl>
- <!-- ENDIF -->
- </fieldset>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <fieldset class="submit-buttons">
- <p>{L_CHECK_FILES_EXPLAIN}</p>
- <input class="button1" type="submit" name="submit" value="{L_CHECK_FILES}" />
- </fieldset>
-
- </form>
-
-<!-- ELSEIF S_DB_UPDATE -->
-
- <!-- IF not S_DB_UPDATE_FINISHED -->
-
- <h1>{L_PERFORM_DATABASE_UPDATE}</h1>
-
- <p>
- {L_PERFORM_DATABASE_UPDATE_EXPLAIN}<br />
- </p>
-
- <br /><br />
-
- <form id="install_dbupdate" method="post" action="{U_DB_UPDATE_ACTION}">
-
- <fieldset class="submit-buttons">
- <a href="{U_DB_UPDATE}" class="button1">{L_RUN_DATABASE_SCRIPT}</a>
-
- <!-- input class="button1" type="submit" name="db_update" value="{L_CHECK_UPDATE_DATABASE}" / -->
- </fieldset>
-
- </form>
-
- <!-- ELSE -->
-
- <div class="successbox">
- <h3>{L_UPDATE_SUCCESS}</h3>
- <p>{L_EVERYTHING_UP_TO_DATE}</p>
- </div>
-
- <!-- ENDIF -->
-
-<!-- ELSEIF S_FILE_CHECK -->
-
- <!-- IF S_ALL_UP_TO_DATE -->
-
- <h1>{L_UPDATE_FILE_SUCCESS}</h1>
- <p>{L_ALL_FILES_UP_TO_DATE}</p>
-
- <p>{L_UPDATE_DATABASE_EXPLAIN}</p>
-
- <form id="install_dbupdate" method="post" action="{U_DB_UPDATE_ACTION}">
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="db_update" value="{L_UPDATE_DATABASE}" />
- </fieldset>
-
- </form>
-
- <!-- ELSE -->
- <h1>{L_COLLECTED_INFORMATION}</h1>
-
- <p>{L_COLLECTED_INFORMATION_EXPLAIN}</p>
-
- <!-- IF S_NO_UPDATE_FILES -->
- <div class="errorbox">
- <h3>{L_NO_UPDATE_FILES}</h3>
-
- <p>{L_NO_UPDATE_FILES_EXPLAIN}</p><br />
-
- <strong>{NO_UPDATE_FILES}</strong>
-
- </div>
- <!-- ENDIF -->
-
- <form id="install_update" method="post" action="{U_UPDATE_ACTION}">
-
- <!-- IF .deleted -->
- <h2>{L_FILES_DELETED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('deleted', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_DELETED_EXPLAIN}</p>
-
- <fieldset id="deleted">
- <legend><img src="{T_IMAGE_PATH}icon_delete.gif" alt="{L_STATUS_DELETED}" /></legend>
- <!-- BEGIN deleted -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF deleted.DIR_PART -->{deleted.DIR_PART}<br /><!-- ENDIF -->{deleted.FILE_PART}</strong></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}: 60%;">
- <!-- IF not deleted.S_BINARY -->[<a href="{deleted.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{deleted.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- </dl>
- <!-- END deleted -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .conflict -->
- <h2>{L_FILES_CONFLICT}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('conflict', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_CONFLICT_EXPLAIN}</p>
-
- <!-- BEGIN conflict -->
- <fieldset id="conflict">
- <legend><img src="{T_IMAGE_PATH}file_conflict.gif" alt="{L_STATUS_CONFLICT}" /></legend>
- <dl>
- <dt style="width: 60%;"><strong><!-- IF conflict.DIR_PART -->{conflict.DIR_PART}<br /><!-- ENDIF -->{conflict.FILE_PART}</strong>
- <!-- IF conflict.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{conflict.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- <!-- IF conflict.NUM_CONFLICTS --><br /><span>{L_NUM_CONFLICTS}{L_COLON} {conflict.NUM_CONFLICTS}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not conflict.S_BINARY -->[<a href="{conflict.U_SHOW_DIFF}">{L_DOWNLOAD_CONFLICTS}</a>]<br />{L_DOWNLOAD_CONFLICTS_EXPLAIN}
- <!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF conflict.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{conflict.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- IF conflict.S_BINARY -->
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="1" checked="checked" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">&nbsp;</dd>
- </dl>
- <!-- ELSE -->
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="3" checked="checked" /> {L_MERGE_NEW_FILE_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NEW_FILE}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_MODIFIED}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="4" /> {L_MERGE_MOD_FILE_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_MOD_FILE}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_MODIFIED}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="1" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NO_MERGE_NEW}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]</dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="conflict[{conflict.FILENAME}]" value="2" /> {L_MERGE_NO_MERGE_MOD_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">[<a href="{conflict.U_VIEW_NO_MERGE_MOD}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]</dd>
- </dl>
- <!-- ENDIF -->
- </fieldset>
- <!-- END conflict -->
-
- <!-- ENDIF -->
-
- <!-- IF .new_conflict -->
- <h2>{L_FILES_NEW_CONFLICT}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('new_conflict', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NEW_CONFLICT_EXPLAIN}</p>
-
- <fieldset id="new_conflict">
- <legend><img src="{T_IMAGE_PATH}file_new_conflict.gif" alt="{L_STATUS_NEW_CONFLICT}" /></legend>
- <!-- BEGIN new_conflict -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF new_conflict.DIR_PART -->{new_conflict.DIR_PART}<br /><!-- ENDIF -->{new_conflict.FILE_PART}</strong>
- <!-- IF new_conflict.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{new_conflict.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not new_conflict.S_BINARY -->[<a href="{new_conflict.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new_conflict.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF new_conflict.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{new_conflict.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END new_conflict -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .modified -->
- <h2>{L_FILES_MODIFIED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_MODIFIED_EXPLAIN}</p>
-
- <!-- BEGIN modified -->
- <fieldset id="modified">
- <legend><img src="{T_IMAGE_PATH}file_modified.gif" alt="{L_STATUS_MODIFIED}" /></legend>
- <dl>
- <dt style="width: 60%;"><strong><!-- IF modified.DIR_PART -->{modified.DIR_PART}<br /><!-- ENDIF -->{modified.FILE_PART}</strong>
- <!-- IF modified.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{modified.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">&nbsp;</dd>
- <!-- IF modified.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{modified.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="0" checked="checked" /> {L_MERGE_MODIFICATIONS_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="1" /> {L_MERGE_NO_MERGE_NEW_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_VIEW_NO_MERGE_NEW}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]<!-- ELSE -->&nbsp;<!-- ENDIF --></dd>
- </dl>
- <dl>
- <dt style="width: 60%"><label><input type="radio" class="radio" name="modified[{modified.FILENAME}]" value="2" /> {L_MERGE_NO_MERGE_MOD_OPTION}</label></dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not modified.S_BINARY -->[<a href="{modified.U_VIEW_NO_MERGE_MOD}" onclick="diff_popup(this.href); return false;">{L_SHOW_DIFF_FINAL}</a>]<!-- ELSE -->&nbsp;<!-- ENDIF --></dd>
- </dl>
- </fieldset>
- <!-- END modified -->
-
- <!-- ENDIF -->
-
- <!-- IF .new -->
- <h2>{L_FILES_NEW}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('new_files', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NEW_EXPLAIN}</p>
-
- <fieldset id="new_files" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_new.gif" alt="{L_STATUS_NEW}" /></legend>
- <!-- BEGIN new -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF new.DIR_PART -->{new.DIR_PART}<br /><!-- ENDIF -->{new.FILE_PART}</strong>
- <!-- IF new.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{new.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;">
- <!-- IF not new.S_BINARY -->[<a href="{new.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{new.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF -->
- </dd>
- <!-- IF new.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{new.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END new -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .not_modified -->
- <h2>{L_FILES_NOT_MODIFIED}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('not_modified', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_NOT_MODIFIED_EXPLAIN}</p>
-
- <fieldset id="not_modified" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_not_modified.gif" alt="{L_STATUS_NOT_MODIFIED}" /></legend>
- <!-- BEGIN not_modified -->
- <dl>
- <dt style="width: 60%;"><strong><!-- IF not_modified.DIR_PART -->{not_modified.DIR_PART}<br /><!-- ENDIF -->{not_modified.FILE_PART}</strong>
- <!-- IF not_modified.S_CUSTOM --><br /><span><em>{L_FILE_USED}{L_COLON} </em>{not_modified.CUSTOM_ORIGINAL}</span><!-- ENDIF -->
- </dt>
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><!-- IF not not_modified.S_BINARY -->[<a href="{not_modified.U_SHOW_DIFF}" onclick="diff_popup(this.href); return false;">{not_modified.L_SHOW_DIFF}</a>]<!-- ELSE -->{L_BINARY_FILE}<!-- ENDIF --></dd>
- <!-- IF not_modified.S_CUSTOM -->
- <dd style="margin-{S_CONTENT_FLOW_BEGIN}{L_COLON} 60%;"><label><input type="checkbox" name="no_update[]" value="{not_modified.FILENAME}" class="radio" /> {L_DO_NOT_UPDATE}</label></dd>
- <!-- ENDIF -->
- </dl>
- <!-- END not_modified -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <!-- IF .up_to_date -->
- <h2>{L_FILES_UP_TO_DATE}</h2>
- <div style="float: {S_CONTENT_FLOW_END};">&raquo; <a href="#" onclick="phpbb.toggleDisplay('up_to_date', 0); return false;">{L_TOGGLE_DISPLAY}</a></div>
- <p>{L_FILES_UP_TO_DATE_EXPLAIN}</p>
-
- <fieldset id="up_to_date" style="display: none;">
- <legend><img src="{T_IMAGE_PATH}file_up_to_date.gif" alt="{L_STATUS_UP_TO_DATE}" /></legend>
- <!-- BEGIN up_to_date -->
- <dl>
- <dd class="full" style="text-align: {S_CONTENT_FLOW_BEGIN};"><strong>{up_to_date.FILENAME}</strong></dd>
- </dl>
- <!-- END up_to_date -->
- </fieldset>
-
- <!-- ENDIF -->
-
- <br />
-
- <fieldset class="quick">
- <input class="button1" type="submit" name="check_again" value="{L_CHECK_FILES_AGAIN}" />
- </fieldset>
-
- <br />
-
- <h1>{L_UPDATE_METHOD}</h1>
-
- <p>{L_UPDATE_METHOD_EXPLAIN}</p>
-
- <fieldset class="submit-buttons">
- <input class="button1" type="submit" name="ftp_upload" value="{L_FTP_UPDATE_METHOD}" />&nbsp; &nbsp;<input class="button1" type="submit" name="download" value="{L_DOWNLOAD_UPDATE_METHOD_BUTTON}" />
- </fieldset>
-
- </form>
-
- <!-- ENDIF -->
-
-<!-- ELSEIF S_DOWNLOAD_FILES -->
-
- <h1>{L_DOWNLOAD_UPDATE_METHOD}</h1>
-
- <p>{L_DOWNLOAD_UPDATE_METHOD_EXPLAIN}</p>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <fieldset>
- <legend>{L_SELECT_DOWNLOAD_FORMAT}</legend>
- <dl>
- <dt><label for="use_method">{L_DOWNLOAD_AS}{L_COLON}</label></dt>
- <dd>{RADIO_BUTTONS}</dd>
- </dl>
- </fieldset>
-
- <fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}
- <input type="submit" class="button2" value="{L_CONTINUE_UPDATE}" name="check_again" />&nbsp; &nbsp;<input type="submit" class="button1" value="{L_DOWNLOAD}" name="download" />
- </fieldset>
-
- </form>
-
- <br /><br />
-
- <p>{L_MAPPING_FILE_STRUCTURE}</p>
-
- <table class="table1">
- <col class="row1" /><col class="row2" /><col class="row1" />
- <thead>
- <tr>
- <th style="width: 49%">{L_ARCHIVE_FILE}</th>
- <th style="width: 2%">&nbsp;</th>
- <th style="width: 49%">{L_DESTINATION}</th>
- </tr>
- </thead>
- <tbody>
- <!-- BEGIN location -->
- <tr>
- <td>{location.SOURCE}</td>
- <td><strong>&raquo;</strong></td>
- <td>{location.DESTINATION}</td>
- </tr>
- <!-- END location -->
- </tbody>
- </table>
-
-<!-- ELSEIF S_FTP_UPLOAD -->
-
- <h1>{L_SELECT_FTP_SETTINGS}</h1>
-
- <form id="install_update" method="post" action="{U_ACTION}">
-
- <!-- IF S_CONNECTION_SUCCESS -->
- <div class="successbox">
- <p>{L_CONNECTION_SUCCESS}</p>
- </div>
- <!-- ELSEIF S_CONNECTION_FAILED -->
- <div class="successbox">
- <p>{L_TRY_DOWNLOAD_METHOD}</p>
-
- <fieldset class="quick">
- <input class="button1" type="submit" name="download" value="{L_TRY_DOWNLOAD_METHOD_BUTTON}" />
- </fieldset>
- </div>
-
- <div class="errorbox">
- <p>{L_CONNECTION_FAILED}<br />{ERROR_MSG}</p>
- </div>
- <!-- ENDIF -->
-
- <fieldset>
- <legend>{L_FTP_SETTINGS}</legend>
- <dl>
- <dt><label>{L_UPLOAD_METHOD}{L_COLON}</label></dt>
- <dd><strong>{UPLOAD_METHOD}</strong></dd>
- </dl>
- <!-- BEGIN data -->
- <dl>
- <dt><label for="{data.DATA}">{data.NAME}{L_COLON}</label><br /><span>{data.EXPLAIN}</span></dt>
- <dd><input type="<!-- IF data.DATA == 'password' -->password<!-- ELSE -->text<!-- ENDIF -->" id="{data.DATA}" name="{data.DATA}" value="{data.DEFAULT}" /></dd>
- </dl>
- <!-- END data -->
- </fieldset>
-
- <fieldset class="submit-buttons">
- {S_HIDDEN_FIELDS}
- <input class="button2" type="submit" name="check_again" value="{L_BACK}" />
- <input class="button1" type="submit" name="test_connection" value="{L_TEST_CONNECTION}" />
- <input class="button1" type="submit" name="submit" value="{L_UPDATE_FILES}" />
- </fieldset>
-
- </form>
-
-<!-- ENDIF -->
-
-<!-- INCLUDE install_footer.html -->
diff --git a/phpBB/adm/style/install_update_diff.html b/phpBB/adm/style/install_update_diff.html
deleted file mode 100644
index 5f80084705..0000000000
--- a/phpBB/adm/style/install_update_diff.html
+++ /dev/null
@@ -1,254 +0,0 @@
-<!DOCTYPE html>
-<html dir="{S_CONTENT_DIRECTION}" lang="{S_USER_LANG}">
-<head>
-<meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<!-- IF META -->{META}<!-- ENDIF -->
-<title>{PAGE_TITLE}</title>
-
-<link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
-
-<script type="text/javascript">
-// <![CDATA[
-function resize_panel()
-{
- var block = document.getElementById('diff_content');
- var height;
-
- if (window.innerHeight)
- {
- height = window.innerHeight - 200;
- block.style.height = height + 'px';
- }
- else
- {
- //whatever IE needs to do this
- }
-}
-
-window.onresize = resize_panel;
-
-// ]]>
-</script>
-
-<style type="text/css">
-/* <![CDATA[ */
-
-#main, .rtl #main {
- font-size: 1em;
- line-height: 0.7em;
- margin: 0;
- padding: 0;
- width: 99%;
-}
-
-#diff_content {
- padding: 30px 10px 10px;
- overflow: hidden;
-}
-
-<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
-div#codepanel {
- width: 100%;
-}
-<!-- ELSE -->
-div#codepanel {
- background-color: #eee;
-}
-<!-- ENDIF -->
-
-<!-- IF DIFF_MODE neq 'unified' and DIFF_MODE neq 'side_by_side' -->
-div#diff_content pre {
- overflow: auto;
- height: 414px;
- width: 100% !important;
-}
-<!-- ENDIF -->
-
-<!-- IF not S_DIFF_NEW_FILE -->
-/**
-* Unified Diff
-*/
-.file {
- line-height: .7em;
- overflow: auto;
- height: 414px;
-}
-
-.diff {
- margin: 0;
-}
-
-.added {
- background-color: #dfd;
-}
-
-.removed {
- background-color: #fdd;
-}
-
-.info {
- color: #888;
-}
-
-.context {
- background-color: #eee;
-}
-
-/**
-* Inline Diff
-*/
-.ins {
- background-color: #dfd;
- text-decoration: underline;
-}
-
-.del {
- background-color: #fdd;
- text-decoration: line-through;
-}
-
-/**
-* Column Diff
-*/
-table.hrdiff {
- margin: 0 0 8px 5px;
- width: 100%;
- overflow: hidden;
- border-bottom: 1px solid #999;
- table-layout: fixed;
- background: transparent;
-}
-
-table.hrdiff th {
- text-align: left;
- width: 50%;
- color: #333;
- font-family: Verdana,Helvetica,sans-serif;
- font-size: 11px;
- border-bottom: 1px solid #999;
- border-right: 1px solid #999;
- background: #D9D9D9;
-}
-
-table.hrdiff thead th {
- font-weight: bold;
- font-size: 110%;
- padding: 2px;
-}
-
-table.hrdiff tr:first-child th {
- border-top: none;
-}
-
-table.hrdiff tbody th {
- font-size: 80%;
- border-top: 1px solid #999;
-}
-
-table.hrdiff tbody td {
- border-right: 1px solid #999;
-}
-
-table.hrdiff td pre {
- font-family: "Consolas", monospace;
- font-size: 1.1em;
- white-space: pre-wrap; /* css-3 */
- word-wrap: break-word; /* Internet Explorer 5.5+ */
-}
-
-table.hrdiff .unmodified {
- background: transparent;
-}
-
-table.hrdiff .added {
- background: #9f9;
-}
-
-table.hrdiff .added_empty {
- background: #cfc;
-}
-
-table.hrdiff .modified {
- background: #fd9;
-}
-
-table.hrdiff .removed {
- background: #f99;
-}
-
-table.hrdiff .removed_empty {
- background: #fcc;
-}
-
-table.hrdiff caption {
- caption-side: top;
- text-align: left;
- margin: 0 0 8px 5px;
- font-size: 90%;
- font-weight: bold;
- padding: 5px;
-}
-
-table.hrdiff caption span {
- height: 10px;
- width: 10px;
- line-height: 10px;
- letter-spacing: 10px;
- border: 1px solid #000;
- margin-left: 0.5em;
- vertical-align: baseline;
-}
-
-<!-- ENDIF -->
-
-/* ]]> */
-</style>
-
-</head>
-
-<!-- IF DIFF_MODE neq 'side_by_side' and DIFF_MODE neq 'raw' -->
-<body onload="resize_panel();">
-<!-- ELSE -->
-<body>
-<!-- ENDIF -->
-
-<div id="wrap">
- <div id="page-header">
-<!-- IF S_DIFF_NEW_FILE -->
-
- <h1>{L_VIEWING_FILE_CONTENTS}</h1>
-<!-- ELSE -->
- <h1>{L_VIEWING_FILE_DIFF}</h1>
-<!-- ENDIF -->
-<!-- IF not S_DIFF_NEW_FILE -->
- <p id="skip"><a href="#acp">{L_SKIP}</a></p>
- <form method="post" action="#">
- <fieldset class="quick">
- <label for="diff_mode">{L_SELECT_DIFF_MODE}{L_COLON}</label>
- <select name="diff_mode" id="diff_mode">{S_DIFF_MODE_OPTIONS}</select>
-
- <input class="button1" type="submit" id="submit" name="submit" value="{L_CHANGE}" />
- </fieldset>
- </form>
-<!-- ENDIF -->
-<!-- IF S_DIFF_CONFLICT_FILE -->
- <div style="float: {S_CONTENT_FLOW_BEGIN};"><strong>{L_NUM_CONFLICTS}{L_COLON} {NUM_CONFLICTS}</strong></div>
- <br style="clear: both;" />
-<!-- ENDIF -->
- </div>
-
- <div id="page-body">
- <div id="acp">
- <div id="codepanel">
- <div id="diff_content">
- <div id="main">
- {DIFF_CONTENT}
- </div>
- </div>
- </div>
- </div>
- </div>
-
-
-<!-- INCLUDE simple_footer.html -->
diff --git a/phpBB/adm/style/permission_forum_copy.html b/phpBB/adm/style/permission_forum_copy.html
index 1e012a9347..b1539aff12 100644
--- a/phpBB/adm/style/permission_forum_copy.html
+++ b/phpBB/adm/style/permission_forum_copy.html
@@ -12,7 +12,7 @@
<legend>{L_LOOK_UP_FORUM}</legend>
<dl>
- <dt><label for="src_forum">{L_COPY_PERMISSIONS_FROM}{L_COLON}</label><br /><span>{L_COPY_PERMISSIONS_FORUM_FROM_EXPLAIN}</span></dt>
+ <dt><!-- EVENT acp_permission_forum_copy_src_forum_prepend --><label for="src_forum">{L_COPY_PERMISSIONS_FROM}{L_COLON}</label><br /><span>{L_COPY_PERMISSIONS_FORUM_FROM_EXPLAIN}</span><!-- EVENT acp_permission_forum_copy_src_forum_append --></dt>
<dd><select id="src_forum" name="src_forum_id"><option value="0">{L_SELECT_FORUM}</option><option value="-1">------------------</option>{S_FORUM_OPTIONS}</select></dd>
</dl>
</fieldset>
@@ -22,7 +22,7 @@
<p>{L_LOOK_UP_FORUMS_EXPLAIN}</p>
<dl>
- <dt><label for="dest_forums">{L_COPY_PERMISSIONS_TO}{L_COLON}</label><br /><span>{L_COPY_PERMISSIONS_FORUM_TO_EXPLAIN}</span></dt>
+ <dt><!-- EVENT acp_permission_forum_copy_dest_forum_prepend --><label for="dest_forums">{L_COPY_PERMISSIONS_TO}{L_COLON}</label><br /><span>{L_COPY_PERMISSIONS_FORUM_TO_EXPLAIN}</span><!-- EVENT acp_permission_forum_copy_dest_forum_append --></dt>
<dd><select id="dest_forums" name="dest_forum_ids[]" multiple="multiple" size="10">{S_FORUM_OPTIONS}</select></dd>
</dl>
</fieldset>
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js
index 6a008ba1ec..91f5521c7a 100644
--- a/phpBB/assets/javascript/core.js
+++ b/phpBB/assets/javascript/core.js
@@ -306,6 +306,10 @@ phpbb.ajaxify = function(options) {
alert = phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT);
} else {
$dark.fadeOut(phpbb.alertTime);
+
+ if ($loadingIndicator) {
+ $loadingIndicator.fadeOut(phpbb.alertTime);
+ }
}
if (typeof phpbb.ajaxCallbacks[callback] === 'function') {
diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js
index e61adc7f99..4fc2e55b66 100644
--- a/phpBB/assets/javascript/installer.js
+++ b/phpBB/assets/javascript/installer.js
@@ -243,8 +243,20 @@
*/
function parseMessage(messageJSON) {
$('#loading_indicator').css('display', 'none');
+ var responseObject;
- var responseObject = JSON.parse(messageJSON);
+ try {
+ responseObject = JSON.parse(messageJSON);
+ } catch (err) {
+ if (window.console) {
+ console.log('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
+ } else {
+ alert('Failed to parse JSON object\n\nMessage: ' + err.message + '\n\nServer Response: ' + messageJSON);
+ }
+
+ resetPolling();
+ return;
+ }
// Parse object
if (responseObject.hasOwnProperty('errors')) {
diff --git a/phpBB/common.php b/phpBB/common.php
index 0b898d9553..38761cfadc 100644
--- a/phpBB/common.php
+++ b/phpBB/common.php
@@ -52,7 +52,7 @@ if (!defined('PHPBB_INSTALLED'))
}
// $phpbb_root_path accounts for redirects from e.g. /adm
- $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/index.' . $phpEx;
+ $script_path = trim(dirname($script_name)) . '/' . $phpbb_root_path . 'install/app.' . $phpEx;
// Replace any number of consecutive backslashes and/or slashes with a single slash
// (could happen on some proxy setups and/or Windows servers)
$script_path = preg_replace('#[\\\\/]{2,}#', '/', $script_path);
diff --git a/phpBB/composer.lock b/phpBB/composer.lock
index 5ea4af4d75..b85c590552 100644
--- a/phpBB/composer.lock
+++ b/phpBB/composer.lock
@@ -271,7 +271,7 @@
"Psr\\Log\\": ""
}
},
- "notification-url": "http://packagist.org/downloads/",
+ "notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
@@ -354,12 +354,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "647a2a148d8ce2847ea75e58608b0a89f5a1dd1b"
+ "reference": "f21c97aec1b5302d2dc0d17047ea8f4e4ff93aae"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/647a2a148d8ce2847ea75e58608b0a89f5a1dd1b",
- "reference": "647a2a148d8ce2847ea75e58608b0a89f5a1dd1b",
+ "url": "https://api.github.com/repos/symfony/config/zipball/f21c97aec1b5302d2dc0d17047ea8f4e4ff93aae",
+ "reference": "f21c97aec1b5302d2dc0d17047ea8f4e4ff93aae",
"shasum": ""
},
"require": {
@@ -375,7 +375,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Config\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -393,7 +396,7 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-23 20:38:01"
},
{
"name": "symfony/console",
@@ -401,16 +404,17 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "89a795226477f66745e8ea10415e769304114920"
+ "reference": "ee86b4579c9e8ad3859cd33f3ef1572f85eda537"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/89a795226477f66745e8ea10415e769304114920",
- "reference": "89a795226477f66745e8ea10415e769304114920",
+ "url": "https://api.github.com/repos/symfony/console/zipball/ee86b4579c9e8ad3859cd33f3ef1572f85eda537",
+ "reference": "ee86b4579c9e8ad3859cd33f3ef1572f85eda537",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": ">=5.3.9",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"psr/log": "~1.0",
@@ -431,7 +435,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -449,7 +456,7 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2015-10-12 10:31:17"
+ "time": "2015-11-18 13:45:00"
},
{
"name": "symfony/debug",
@@ -457,12 +464,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/debug.git",
- "reference": "0c250fd873c7ceb31a9e7ad629b4a7048c931c28"
+ "reference": "441bd03c6d08132cc8329dde904657d0e5f59748"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/debug/zipball/0c250fd873c7ceb31a9e7ad629b4a7048c931c28",
- "reference": "0c250fd873c7ceb31a9e7ad629b4a7048c931c28",
+ "url": "https://api.github.com/repos/symfony/debug/zipball/441bd03c6d08132cc8329dde904657d0e5f59748",
+ "reference": "441bd03c6d08132cc8329dde904657d0e5f59748",
"shasum": ""
},
"require": {
@@ -485,7 +492,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Debug\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -503,7 +513,7 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-10-30 20:15:42"
},
{
"name": "symfony/dependency-injection",
@@ -511,12 +521,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "dc1fb82df24dfd4e13735265d18d027f28a72a3e"
+ "reference": "4eb9fce835b5d179b4e996b57504a6d90bf3ba5b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/dc1fb82df24dfd4e13735265d18d027f28a72a3e",
- "reference": "dc1fb82df24dfd4e13735265d18d027f28a72a3e",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4eb9fce835b5d179b4e996b57504a6d90bf3ba5b",
+ "reference": "4eb9fce835b5d179b4e996b57504a6d90bf3ba5b",
"shasum": ""
},
"require": {
@@ -544,7 +554,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\DependencyInjection\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -562,7 +575,7 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-23 10:34:41"
},
{
"name": "symfony/event-dispatcher",
@@ -570,12 +583,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "41899a21d196332ab23e40f76e1276f2b7aa4d0d"
+ "reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/41899a21d196332ab23e40f76e1276f2b7aa4d0d",
- "reference": "41899a21d196332ab23e40f76e1276f2b7aa4d0d",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a5eb815363c0388e83247e7e9853e5dbc14999cc",
+ "reference": "a5eb815363c0388e83247e7e9853e5dbc14999cc",
"shasum": ""
},
"require": {
@@ -601,7 +614,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\EventDispatcher\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -619,7 +635,7 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2015-10-12 10:13:39"
+ "time": "2015-10-30 20:15:42"
},
{
"name": "symfony/filesystem",
@@ -627,12 +643,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "fc3fe52fef85e1f3e7775ffad92539e16c20e0af"
+ "reference": "3e661a0d521ac67496515fa6e6704bd61bcfff60"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/fc3fe52fef85e1f3e7775ffad92539e16c20e0af",
- "reference": "fc3fe52fef85e1f3e7775ffad92539e16c20e0af",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/3e661a0d521ac67496515fa6e6704bd61bcfff60",
+ "reference": "3e661a0d521ac67496515fa6e6704bd61bcfff60",
"shasum": ""
},
"require": {
@@ -647,7 +663,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -665,7 +684,7 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-23 10:19:46"
},
{
"name": "symfony/finder",
@@ -673,12 +692,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "dcd5aaba34ca332abb7f33ec554ebd4d829cb202"
+ "reference": "ead9b07af4ba77b6507bee697396a5c79e633f08"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/dcd5aaba34ca332abb7f33ec554ebd4d829cb202",
- "reference": "dcd5aaba34ca332abb7f33ec554ebd4d829cb202",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/ead9b07af4ba77b6507bee697396a5c79e633f08",
+ "reference": "ead9b07af4ba77b6507bee697396a5c79e633f08",
"shasum": ""
},
"require": {
@@ -693,7 +712,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Finder\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -711,7 +733,7 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-10-30 20:15:42"
},
{
"name": "symfony/http-foundation",
@@ -719,16 +741,17 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
- "reference": "7e8c33e9e6464d75091296e4615852ec4981ed80"
+ "reference": "0d7031746341f4fa9233aaab616bd9361dac98ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7e8c33e9e6464d75091296e4615852ec4981ed80",
- "reference": "7e8c33e9e6464d75091296e4615852ec4981ed80",
+ "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0d7031746341f4fa9233aaab616bd9361dac98ce",
+ "reference": "0d7031746341f4fa9233aaab616bd9361dac98ce",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": ">=5.3.9",
+ "symfony/polyfill-php54": "~1.0"
},
"require-dev": {
"symfony/expression-language": "~2.4|~3.0.0"
@@ -743,8 +766,8 @@
"psr-4": {
"Symfony\\Component\\HttpFoundation\\": ""
},
- "classmap": [
- "Resources/stubs"
+ "exclude-from-classmap": [
+ "/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
@@ -763,7 +786,7 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
- "time": "2015-10-13 16:11:28"
+ "time": "2015-11-20 17:41:52"
},
{
"name": "symfony/http-kernel",
@@ -771,12 +794,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/http-kernel.git",
- "reference": "8f2cb3dfac5090be80fdf71e13f41aadaefc31e0"
+ "reference": "2c7b16ca290d42d33b9931318ff9531ad769901f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-kernel/zipball/8f2cb3dfac5090be80fdf71e13f41aadaefc31e0",
- "reference": "8f2cb3dfac5090be80fdf71e13f41aadaefc31e0",
+ "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2c7b16ca290d42d33b9931318ff9531ad769901f",
+ "reference": "2c7b16ca290d42d33b9931318ff9531ad769901f",
"shasum": ""
},
"require": {
@@ -824,7 +847,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\HttpKernel\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -842,7 +868,121 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
- "time": "2015-10-13 16:11:28"
+ "time": "2015-11-20 12:20:48"
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "0b6a8940385311a24e060ec1fe35680e17c74497"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/0b6a8940385311a24e060ec1fe35680e17c74497",
+ "reference": "0b6a8940385311a24e060ec1fe35680e17c74497",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Mbstring\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2015-11-04 20:28:58"
+ },
+ {
+ "name": "symfony/polyfill-php54",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php54.git",
+ "reference": "2c9f6d98eb30dc04fe0b06f9cc92a55acea5bdcc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/2c9f6d98eb30dc04fe0b06f9cc92a55acea5bdcc",
+ "reference": "2c9f6d98eb30dc04fe0b06f9cc92a55acea5bdcc",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Polyfill\\Php54\\": ""
+ },
+ "files": [
+ "bootstrap.php"
+ ],
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 5.4+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "time": "2015-11-04 20:28:58"
},
{
"name": "symfony/routing",
@@ -850,12 +990,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
- "reference": "765f56756fdd425e73224980693c97d4862e4b6f"
+ "reference": "2a7a2196ab427f0ed97efaad2cf940e21613c943"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/routing/zipball/765f56756fdd425e73224980693c97d4862e4b6f",
- "reference": "765f56756fdd425e73224980693c97d4862e4b6f",
+ "url": "https://api.github.com/repos/symfony/routing/zipball/2a7a2196ab427f0ed97efaad2cf940e21613c943",
+ "reference": "2a7a2196ab427f0ed97efaad2cf940e21613c943",
"shasum": ""
},
"require": {
@@ -889,7 +1029,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Routing\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -913,7 +1056,7 @@
"uri",
"url"
],
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-23 09:29:40"
},
{
"name": "symfony/security",
@@ -997,17 +1140,17 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/twig-bridge.git",
- "reference": "ff97292bc36ca33214e7bdff355085143ead11f6"
+ "reference": "49788ae22cf167db21a441ed3f9aae5fb2bdfc0f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/ff97292bc36ca33214e7bdff355085143ead11f6",
- "reference": "ff97292bc36ca33214e7bdff355085143ead11f6",
+ "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/49788ae22cf167db21a441ed3f9aae5fb2bdfc0f",
+ "reference": "49788ae22cf167db21a441ed3f9aae5fb2bdfc0f",
"shasum": ""
},
"require": {
"php": ">=5.3.9",
- "twig/twig": "~1.20|~2.0"
+ "twig/twig": "~1.23|~2.0"
},
"require-dev": {
"symfony/asset": "~2.7|~3.0.0",
@@ -1016,7 +1159,7 @@
"symfony/finder": "~2.3|~3.0.0",
"symfony/form": "~2.8",
"symfony/http-kernel": "~2.8|~3.0.0",
- "symfony/intl": "~2.3|~3.0.0",
+ "symfony/polyfill-intl-icu": "~1.0",
"symfony/routing": "~2.2|~3.0.0",
"symfony/security": "~2.6|~3.0.0",
"symfony/security-acl": "~2.6|~3.0.0",
@@ -1049,7 +1192,10 @@
"autoload": {
"psr-4": {
"Symfony\\Bridge\\Twig\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1067,7 +1213,7 @@
],
"description": "Symfony Twig Bridge",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-02 20:29:24"
},
{
"name": "symfony/yaml",
@@ -1075,12 +1221,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "ff7f886a33f5b7a26a94d62f6e14bb9cf0e3bf5d"
+ "reference": "f65177d7093bc29aefebfbdbe496b9e3a6292653"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/ff7f886a33f5b7a26a94d62f6e14bb9cf0e3bf5d",
- "reference": "ff7f886a33f5b7a26a94d62f6e14bb9cf0e3bf5d",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/f65177d7093bc29aefebfbdbe496b9e3a6292653",
+ "reference": "f65177d7093bc29aefebfbdbe496b9e3a6292653",
"shasum": ""
},
"require": {
@@ -1095,7 +1241,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Yaml\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1113,29 +1262,33 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
- "time": "2015-10-12 11:16:35"
+ "time": "2015-11-18 13:45:00"
},
{
"name": "twig/twig",
- "version": "v1.20.0",
+ "version": "v1.23.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844"
+ "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
- "reference": "1ea4e5f81c6d005fe84d0b38e1c4f1955eb86844",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/d9b6333ae8dd2c8e3fd256e127548def0bc614c6",
+ "reference": "d9b6333ae8dd2c8e3fd256e127548def0bc614c6",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
+ "require-dev": {
+ "symfony/debug": "~2.7",
+ "symfony/phpunit-bridge": "~2.7"
+ },
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.20-dev"
+ "dev-master": "1.23-dev"
}
},
"autoload": {
@@ -1170,7 +1323,7 @@
"keywords": [
"templating"
],
- "time": "2015-08-12 15:56:39"
+ "time": "2015-11-05 12:49:06"
}
],
"packages-dev": [
@@ -2022,12 +2175,12 @@
"version": "v1.0.2",
"source": {
"type": "git",
- "url": "https://github.com/fabpot/Pimple.git",
+ "url": "https://github.com/silexphp/Pimple.git",
"reference": "ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fabpot/Pimple/zipball/ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94",
+ "url": "https://api.github.com/repos/silexphp/Pimple/zipball/ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94",
"reference": "ae11e57e8c2bb414b2ff93396dbbfc0eb92feb94",
"shasum": ""
},
@@ -2470,12 +2623,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
- "reference": "35bde11fc81eecb2409eb60c5f7920659ad7e00a"
+ "reference": "589f32fe4f43155ea303d505171634c45f15e876"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/browser-kit/zipball/35bde11fc81eecb2409eb60c5f7920659ad7e00a",
- "reference": "35bde11fc81eecb2409eb60c5f7920659ad7e00a",
+ "url": "https://api.github.com/repos/symfony/browser-kit/zipball/589f32fe4f43155ea303d505171634c45f15e876",
+ "reference": "589f32fe4f43155ea303d505171634c45f15e876",
"shasum": ""
},
"require": {
@@ -2484,7 +2637,7 @@
},
"require-dev": {
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
- "symfony/process": "~2.0,>=2.0.5|~3.0.0"
+ "symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0"
},
"suggest": {
"symfony/process": ""
@@ -2498,7 +2651,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\BrowserKit\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2516,7 +2672,7 @@
],
"description": "Symfony BrowserKit Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-02 20:29:24"
},
{
"name": "symfony/css-selector",
@@ -2524,12 +2680,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
- "reference": "01e341a68e06e540e0322017506b58b0e072c626"
+ "reference": "b600fec37c0efca08046d481d79e7eabc07108ff"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/css-selector/zipball/01e341a68e06e540e0322017506b58b0e072c626",
- "reference": "01e341a68e06e540e0322017506b58b0e072c626",
+ "url": "https://api.github.com/repos/symfony/css-selector/zipball/b600fec37c0efca08046d481d79e7eabc07108ff",
+ "reference": "b600fec37c0efca08046d481d79e7eabc07108ff",
"shasum": ""
},
"require": {
@@ -2544,7 +2700,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\CssSelector\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2566,7 +2725,7 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-10-30 20:15:42"
},
{
"name": "symfony/dom-crawler",
@@ -2574,16 +2733,17 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
- "reference": "93bfc2cc94cdfc16c728c663658117a25acd1aa5"
+ "reference": "740c98235f5b6e2b0b13df2fb97c7a1c7d1a18fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/93bfc2cc94cdfc16c728c663658117a25acd1aa5",
- "reference": "93bfc2cc94cdfc16c728c663658117a25acd1aa5",
+ "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/740c98235f5b6e2b0b13df2fb97c7a1c7d1a18fc",
+ "reference": "740c98235f5b6e2b0b13df2fb97c7a1c7d1a18fc",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": ">=5.3.9",
+ "symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"symfony/css-selector": "~2.8|~3.0.0"
@@ -2600,7 +2760,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\DomCrawler\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2618,7 +2781,7 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-02 20:29:39"
},
{
"name": "symfony/process",
@@ -2626,12 +2789,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
- "reference": "4e1daf58b375ea7c506d525dc7801df1c9a6ebbd"
+ "reference": "63573e0afb71aa3ea2381d70d96b8d9063627794"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/4e1daf58b375ea7c506d525dc7801df1c9a6ebbd",
- "reference": "4e1daf58b375ea7c506d525dc7801df1c9a6ebbd",
+ "url": "https://api.github.com/repos/symfony/process/zipball/63573e0afb71aa3ea2381d70d96b8d9063627794",
+ "reference": "63573e0afb71aa3ea2381d70d96b8d9063627794",
"shasum": ""
},
"require": {
@@ -2646,7 +2809,10 @@
"autoload": {
"psr-4": {
"Symfony\\Component\\Process\\": ""
- }
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -2664,7 +2830,7 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
- "time": "2015-10-11 08:29:26"
+ "time": "2015-11-20 07:33:53"
}
],
"aliases": [],
diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml
index 425df6dc9b..2624ae5e06 100644
--- a/phpBB/config/default/container/services_files.yml
+++ b/phpBB/config/default/container/services_files.yml
@@ -25,7 +25,6 @@ services:
- @language
- @php_ini
- @request
- - %core.root_path%
files.types.form:
class: phpbb\files\types\form
diff --git a/phpBB/config/default/container/services_notification.yml b/phpBB/config/default/container/services_notification.yml
index c842656575..7337dd7904 100644
--- a/phpBB/config/default/container/services_notification.yml
+++ b/phpBB/config/default/container/services_notification.yml
@@ -9,6 +9,7 @@ services:
- @dispatcher
- @dbal.conn
- @cache
+ - @language
- @user
- %tables.notification_types%
- %tables.user_notifications%
@@ -26,6 +27,7 @@ services:
abstract: true
arguments:
- @dbal.conn
+ - @language
- @user
- @auth
- %core.root_path%
diff --git a/phpBB/config/default/container/services_text_reparser.yml b/phpBB/config/default/container/services_text_reparser.yml
index d753775451..3c3707e7cf 100644
--- a/phpBB/config/default/container/services_text_reparser.yml
+++ b/phpBB/config/default/container/services_text_reparser.yml
@@ -31,6 +31,7 @@ services:
class: phpbb\textreparser\plugins\forum_description
arguments:
- @dbal.conn
+ - %tables.forums%
tags:
- { name: text_reparser.plugin }
@@ -38,6 +39,7 @@ services:
class: phpbb\textreparser\plugins\forum_rules
arguments:
- @dbal.conn
+ - %tables.forums%
tags:
- { name: text_reparser.plugin }
@@ -45,6 +47,7 @@ services:
class: phpbb\textreparser\plugins\group_description
arguments:
- @dbal.conn
+ - %tables.groups%
tags:
- { name: text_reparser.plugin }
@@ -52,6 +55,7 @@ services:
class: phpbb\textreparser\plugins\pm_text
arguments:
- @dbal.conn
+ - %tables.privmsgs%
tags:
- { name: text_reparser.plugin }
@@ -66,6 +70,7 @@ services:
class: phpbb\textreparser\plugins\poll_title
arguments:
- @dbal.conn
+ - %tables.topics%
tags:
- { name: text_reparser.plugin }
@@ -73,6 +78,7 @@ services:
class: phpbb\textreparser\plugins\post_text
arguments:
- @dbal.conn
+ - %tables.posts%
tags:
- { name: text_reparser.plugin }
@@ -80,5 +86,6 @@ services:
class: phpbb\textreparser\plugins\user_signature
arguments:
- @dbal.conn
+ - %tables.users%
tags:
- { name: text_reparser.plugin }
diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml
index c4b5ac2375..ec3bf95d1f 100644
--- a/phpBB/config/default/container/tables.yml
+++ b/phpBB/config/default/container/tables.yml
@@ -1,28 +1,77 @@
parameters:
+ tables.acl_groups: %core.table_prefix%acl_groups
+ tables.acl_options: %core.table_prefix%acl_options
+ tables.acl_roles: %core.table_prefix%acl_roles
+ tables.acl_roles_data: %core.table_prefix%acl_roles_data
+ tables.acl_users: %core.table_prefix%acl_users
+ tables.attachments: %core.table_prefix%attachments
tables.auth_provider_oauth_token_storage: %core.table_prefix%oauth_tokens
tables.auth_provider_oauth_account_assoc: %core.table_prefix%oauth_accounts
+ tables.banlist: %core.table_prefix%banlist
tables.bbcodes: %core.table_prefix%bbcodes
+ tables.bookmarks: %core.table_prefix%bookmarks
+ tables.bots: %core.table_prefix%bots
tables.captcha_qa_questions: %core.table_prefix%captcha_questions
tables.captcha_qa_answers: %core.table_prefix%captcha_answers
tables.captcha_qa_confirm: %core.table_prefix%qa_confirm
tables.config: %core.table_prefix%config
tables.config_text: %core.table_prefix%config_text
+ tables.confirm: %core.table_prefix%confirm
+ tables.disallow: %core.table_prefix%disallow
+ tables.drafts: %core.table_prefix%drafts
tables.ext: %core.table_prefix%ext
+ tables.extensions: %core.table_prefix%extensions
+ tables.extension_groups: %core.table_prefix%extension_groups
tables.forums: %core.table_prefix%forums
+ tables.forums_access: %core.table_prefix%forums_access
+ tables.forums_track: %core.table_prefix%forums_track
+ tables.forums_watch: %core.table_prefix%forums_watch
+ tables.groups: %core.table_prefix%groups
+ tables.icons: %core.table_prefix%icons
+ tables.lang: %core.table_prefix%lang
tables.log: %core.table_prefix%log
+ tables.login_attempts: %core.table_prefix%login_attempts
tables.migrations: %core.table_prefix%migrations
tables.moderator_cache: %core.table_prefix%moderator_cache
tables.modules: %core.table_prefix%modules
tables.notification_types: %core.table_prefix%notification_types
tables.notifications: %core.table_prefix%notifications
+ tables.poll_options: %core.table_prefix%poll_options
+ tables.poll_votes: %core.table_prefix%poll_votes
+ tables.posts: %core.table_prefix%posts
+ tables.privmsgs: %core.table_prefix%privmsgs
+ tables.privmsgs_folder: %core.table_prefix%privmsgs_folder
+ tables.privmsgs_rules: %core.table_prefix%privmsgs_rules
+ tables.privmsgs_to: %core.table_prefix%privmsgs_to
tables.profile_fields: %core.table_prefix%profile_fields
tables.profile_fields_data: %core.table_prefix%profile_fields_data
tables.profile_fields_options_language: %core.table_prefix%profile_fields_lang
tables.profile_fields_language: %core.table_prefix%profile_lang
- tables.posts: %core.table_prefix%posts
+ tables.ranks: %core.table_prefix%ranks
+ tables.reports: %core.table_prefix%reports
+ tables.reports_reasons: %core.table_prefix%reports_reasons
+ tables.search_results: %core.table_prefix%search_results
+ tables.search_wordlist: %core.table_prefix%search_wordlist
+ tables.search_wordmatch: %core.table_prefix%search_wordmatch
+ tables.sessions: %core.table_prefix%sessions
+ tables.sessions_keys: %core.table_prefix%sessions_keys
+ tables.sitelist: %core.table_prefix%sitelist
tables.smilies: %core.table_prefix%smilies
+ tables.sphinx: %core.table_prefix%sphinx
tables.styles: %core.table_prefix%styles
+ tables.styles_template: %core.table_prefix%styles_template
+ tables.styles_template_data: %core.table_prefix%styles_template_data
+ tables.styles_theme: %core.table_prefix%styles_theme
+ tables.styles_imageset: %core.table_prefix%styles_imageset
+ tables.styles_imageset_data: %core.table_prefix%styles_imageset_data
+ tables.teampage: %core.table_prefix%teampage
tables.topics: %core.table_prefix%topics
+ tables.topics_posted: %core.table_prefix%topics_posted
+ tables.topics_track: %core.table_prefix%topics_track
+ tables.topics_watch: %core.table_prefix%topics_watch
+ tables.user_group: %core.table_prefix%user_group
tables.user_notifications: %core.table_prefix%user_notifications
tables.users: %core.table_prefix%users
+ tables.warnings: %core.table_prefix%warnings
tables.words: %core.table_prefix%words
+ tables.zebra: %core.table_prefix%zebra
diff --git a/phpBB/config/installer/container/parameters.yml b/phpBB/config/installer/container/parameters.yml
index 0447646806..f11f7e2d84 100644
--- a/phpBB/config/installer/container/parameters.yml
+++ b/phpBB/config/installer/container/parameters.yml
@@ -1,2 +1,5 @@
imports:
- { resource: ../../default/container/parameters.yml }
+
+parameters:
+ installer.create_config_file.options: []
diff --git a/phpBB/config/installer/container/services.yml b/phpBB/config/installer/container/services.yml
index e7325399ad..5626724dd0 100644
--- a/phpBB/config/installer/container/services.yml
+++ b/phpBB/config/installer/container/services.yml
@@ -9,6 +9,11 @@ imports:
- { resource: ../../default/container/services_twig.yml }
services:
+ cache.driver:
+ class: %cache.driver.class%
+ arguments:
+ - "%core.root_path%/cache/installer/"
+
config:
class: phpbb\config\config
arguments:
diff --git a/phpBB/config/installer/container/services_install_filesystem.yml b/phpBB/config/installer/container/services_install_filesystem.yml
index 776d7b9198..0d52f07b5c 100644
--- a/phpBB/config/installer/container/services_install_filesystem.yml
+++ b/phpBB/config/installer/container/services_install_filesystem.yml
@@ -8,6 +8,7 @@ services:
- @installer.helper.iohandler
- %core.root_path%
- %core.php_ext%
+ - %installer.create_config_file.options%
tags:
- { name: install_filesystem_install, order: 10 }
diff --git a/phpBB/config/installer/container/services_installer.yml b/phpBB/config/installer/container/services_installer.yml
index 667ff2bafd..c2c730e62c 100644
--- a/phpBB/config/installer/container/services_installer.yml
+++ b/phpBB/config/installer/container/services_installer.yml
@@ -86,6 +86,7 @@ services:
class: phpbb\install\installer
abstract: true
arguments:
+ - @cache.driver
- @installer.helper.config
- @path_helper
diff --git a/phpBB/develop/lang_migrate_help_lang.php b/phpBB/develop/lang_migrate_help_lang.php
index d5a2573ee0..81b71398e1 100644
--- a/phpBB/develop/lang_migrate_help_lang.php
+++ b/phpBB/develop/lang_migrate_help_lang.php
@@ -11,18 +11,13 @@
*
*/
-//
-// Security message:
-//
-// This script is potentially dangerous.
-// Remove or comment the next line (die(".... ) to enable this script.
-// Do NOT FORGET to either remove this script or disable it after you have used it.
-//
-#die("Please read the first lines of this script for instructions on how to enable it");
+define('LANGUAGE_TO_MIGRATE', 'en');
+
+# NO CHANGES BELOW THIS LINE
define('IN_PHPBB', true);
$phpEx = substr(strrchr(__FILE__, '.'), 1);
-$phpbb_root_path='./../';
+$phpbb_root_path = './../';
include($phpbb_root_path . 'common.'.$phpEx);
$help_bbcode = load_help('bbcode');
@@ -239,7 +234,7 @@ trigger_error('Successfully migrated help_bbcode and help_faq to help/bbcode and
function load_help($help)
{
global $phpbb_root_path;
- include($phpbb_root_path . 'language/en/help_' . $help . '.php');
+ include($phpbb_root_path . 'language/' . LANGUAGE_TO_MIGRATE . '/help_' . $help . '.php');
return $help;
}
@@ -250,7 +245,7 @@ function load_help($help)
function write_help($help, array $lang)
{
global $phpbb_root_path;
- $fp = fopen($phpbb_root_path . 'language/en/help/' . $help . '.php', 'wb');
+ $fp = fopen($phpbb_root_path . 'language/' . LANGUAGE_TO_MIGRATE . '/help/' . $help . '.php', 'wb');
fwrite($fp, get_language_file_header());
fwrite($fp, '$lang = array_merge($lang, array(' . "\n");
diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html
index b1db7b6f36..85828d91f8 100644
--- a/phpBB/docs/CHANGELOG.html
+++ b/phpBB/docs/CHANGELOG.html
@@ -49,6 +49,7 @@
<ol>
<li><a href="#changelog">Changelog</a>
<ul>
+ <li><a href="#v31x">Changes since 3.1.x</a></li>
<li><a href="#v315">Changes since 3.1.5</a></li>
<li><a href="#v314">Changes since 3.1.4</a></li>
<li><a href="#v313">Changes since 3.1.3</a></li>
@@ -113,6 +114,243 @@
<div class="content">
+ <a name="v31x"></a><h3>Changes since 3.1.x</h3>
+ <h4>Bug</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-6466">PHPBB3-6466</a>] - Permission Role Tooltips do not display in Safari</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7187">PHPBB3-7187</a>] - Quote smilies error</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-7275">PHPBB3-7275</a>] - Custom bbodes trim('${1}')</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8064">PHPBB3-8064</a>] - forum author sort not using username_clean</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8419">PHPBB3-8419</a>] - custom tag eats up space character</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8420">PHPBB3-8420</a>] - emoticon removes space before itself when using preview</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8613">PHPBB3-8613</a>] - BBCode_uid- and censor-bug</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9073">PHPBB3-9073</a>] - Word censoring in URLs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9109">PHPBB3-9109</a>] - Maximum allowed recepients restriction precedence</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9377">PHPBB3-9377</a>] - Custom BB Code Nesting</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10002">PHPBB3-10002</a>] - (incomplete) BBCode usage of [quote] - and [list] - forces closing [/list] - and [/quote] -s, ultimately breaking HTML/Design</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10388">PHPBB3-10388</a>] - Template engine should use json_encode() to properly escape JS properties</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10572">PHPBB3-10572</a>] - Unguarded includes in acp/</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10989">PHPBB3-10989</a>] - Bug in BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11444">PHPBB3-11444</a>] - Unnecessary notify column in phpbb_user_notifications table</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11967">PHPBB3-11967</a>] - Notification settings are not respected</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12143">PHPBB3-12143</a>] - Untranslated group name from index if not special group</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12195">PHPBB3-12195</a>] - Double-slash URLs not supported</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12387">PHPBB3-12387</a>] - mysqli_free_result is called with false value</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12554">PHPBB3-12554</a>] - Quotes do not display correctly as list elements</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12698">PHPBB3-12698</a>] - Replace all instances of magic numbers with constants in javascript</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12957">PHPBB3-12957</a>] - The template engine is not constructed properly in install/index</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12974">PHPBB3-12974</a>] - Update nightly version of develop to 3.2.0-a1-dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13101">PHPBB3-13101</a>] - Remove WLM contact from profile</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13238">PHPBB3-13238</a>] - \phpbb\db\migration\data\v310\mysql_fulltext_drop tries to drop non existent indexes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13359">PHPBB3-13359</a>] - Develop tests fail due to wrong template set up in tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13362">PHPBB3-13362</a>] - The whole cache dir (excluding the .htaccess and index.html files) should be ignored by git</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13371">PHPBB3-13371</a>] - Lang vars not loaded during install process</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13372">PHPBB3-13372</a>] - Environment Bug - Routing broken for extensions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13377">PHPBB3-13377</a>] - Function decode_message() incorrectly decodes www type URLs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13425">PHPBB3-13425</a>] - Smiley code at start of text being quoted doesn't show smiley image in quote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13513">PHPBB3-13513</a>] - Mixed routing file paths in the router</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13555">PHPBB3-13555</a>] - Poll options preview rendered incorrectly by &lt;br /&gt; collision</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13619">PHPBB3-13619</a>] - Remove unneeded folders/files from vendor folder in release package</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13638">PHPBB3-13638</a>] - INCLUDECSS and INCLUDEJS Broken in 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13670">PHPBB3-13670</a>] - Fix fatal function name must be a string in functional tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13680">PHPBB3-13680</a>] - Notification for a quote within a quote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13718">PHPBB3-13718</a>] - Spambot countermeasures/CAPTCHA admin panel won't load</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13749">PHPBB3-13749</a>] - Add missing slash to base uri in helper route tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13766">PHPBB3-13766</a>] - Missing style_parent_id in textformater's data_access::get_styles()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13769">PHPBB3-13769</a>] - bin/phpbbcli.php ignores PHPBB_ENVIRONMENT constant from config.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13772">PHPBB3-13772</a>] - Error in @param variable type for phpbb\passwords\manager</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13782">PHPBB3-13782</a>] - ACM null caching driver class is named with the reserved word 'null'</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13792">PHPBB3-13792</a>] - Travis fails installing hhvm-nigthly</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13814">PHPBB3-13814</a>] - phpbb_is_writable() method of the new filesystem class truncates files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13825">PHPBB3-13825</a>] - create_thumbnail() incorrectly calls phpbb\filesystem::phpbb_chmod</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13828">PHPBB3-13828</a>] - Rename null driver to dummy for PHP7 compatibility in tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13829">PHPBB3-13829</a>] - Router requires cache directory to be writable</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13839">PHPBB3-13839</a>] - Failing test when the phpBB root directory isn't named phpbb</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13849">PHPBB3-13849</a>] - Development environment broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13860">PHPBB3-13860</a>] - Array to string conversion in parser service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13871">PHPBB3-13871</a>] - Call to a member function realpath() on a non-object in functions.php on line 3474</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13875">PHPBB3-13875</a>] - Lint test should ignore cache, ext, and store folder</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13890">PHPBB3-13890</a>] - Failling tests in master</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13896">PHPBB3-13896</a>] - Coding style issue in master</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13897">PHPBB3-13897</a>] - Non-existent environment causes fatal error</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13906">PHPBB3-13906</a>] - BBCodes in signatures are not correctly parsed in post preview</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13990">PHPBB3-13990</a>] - Reparse markup inside of forum rules/description</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13993">PHPBB3-13993</a>] - Signature Editing Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14008">PHPBB3-14008</a>] - Do not add a user_id value to quotes from guests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14033">PHPBB3-14033</a>] - Correct docblock errors</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14034">PHPBB3-14034</a>] - Fix reparser names that contain &quot;text_reparser&quot; in the middle</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14036">PHPBB3-14036</a>] - Replace path_helper with a mock</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14052">PHPBB3-14052</a>] - New installer - The commands are not translated</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14074">PHPBB3-14074</a>] - Not possible to clear notification (mark as read)</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14076">PHPBB3-14076</a>] - Notifications settings are not correctly handled when a non default setting is set</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14078">PHPBB3-14078</a>] - Notification related sql general error on submission of editing post</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14079">PHPBB3-14079</a>] - Cannot mark notification as read from the dropdown</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14094">PHPBB3-14094</a>] - Current master branch is getting segmentation fault error on PHP 7 tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14128">PHPBB3-14128</a>] - Image posting overflow regression</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14137">PHPBB3-14137</a>] - Fix Notification Menu Settings spacing issue caused by new jump-box improvements</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14138">PHPBB3-14138</a>] - Use span tags instead of abbr tags in the footer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14165">PHPBB3-14165</a>] - Fix layout of ucp/mcp after 14139</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14178">PHPBB3-14178</a>] - Installer database helper tests fail if sqlite3 is not present</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14180">PHPBB3-14180</a>] - Use unix line ending in files classes tests</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14182">PHPBB3-14182</a>] - Move the v310\notifications_board migration to v320\notifications_board</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14183">PHPBB3-14183</a>] - Remove deprecated max-device-width</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14193">PHPBB3-14193</a>] - Custom BBCode Buttons Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14194">PHPBB3-14194</a>] - Responsive Quick Links Menu Broken</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14195">PHPBB3-14195</a>] - Plupload Attachments Not Quite Working</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14199">PHPBB3-14199</a>] - We need to hide icons from screen readers</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14202">PHPBB3-14202</a>] - Add missing sr-only classes to icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14216">PHPBB3-14216</a>] - Do not run thumbnail test if gd is not enabled</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14221">PHPBB3-14221</a>] - Fix viewforum header issue</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14222">PHPBB3-14222</a>] - ACP users page tries to cast deactivated_super_global to int</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14225">PHPBB3-14225</a>] - Inject the resolver in routing loaders when using them</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14230">PHPBB3-14230</a>] - Unread posts' icons don't have different color in viewtopic</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14234">PHPBB3-14234</a>] - Do not use references in trigger_event()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14235">PHPBB3-14235</a>] - Font Awesome not available with simple_header.html</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14240">PHPBB3-14240</a>] - Always include all config files in the update package</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14274">PHPBB3-14274</a>] - New installer has weak inclusion of user functions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14277">PHPBB3-14277</a>] - Don't use user_id in migrations as it is not defined</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14278">PHPBB3-14278</a>] - Don't use user_id in installer if not available</li>
+ </ul>
+ <h4>Improvement</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8672">PHPBB3-8672</a>] - No file size limit in getimagesize() and remote upload</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-8708">PHPBB3-8708</a>] - Splitting global announcements from f_announce</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9485">PHPBB3-9485</a>] - Please include link to specific post in moderator's activity logs.</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10268">PHPBB3-10268</a>] - extend function make_clickable() to also recognize semicolons as leading URL borders</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10620">PHPBB3-10620</a>] - Quote tag improvement</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10922">PHPBB3-10922</a>] - Allow parameters for [email] - BBCode content instead of addresses only</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11649">PHPBB3-11649</a>] - Move construction of twig environment to DIC</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11742">PHPBB3-11742</a>] - BBCode 'code' doesn't support tabs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12466">PHPBB3-12466</a>] - Move classes from acp_database.php to their own files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12487">PHPBB3-12487</a>] - Update PHP code</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12608">PHPBB3-12608</a>] - Improve notifications drop-down menu styling in header</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12654">PHPBB3-12654</a>] - Improve header search-box styling</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12681">PHPBB3-12681</a>] - Cache the compiled routes and dump the url_generator</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12719">PHPBB3-12719</a>] - Convert to Normalize &amp; SUITCSS - base for reset</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12745">PHPBB3-12745</a>] - Allow Emoji characters in posts</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12769">PHPBB3-12769</a>] - Add and use Font-Awesome to handle proSilver icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12821">PHPBB3-12821</a>] - Use CSS instead of images for gradients</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12958">PHPBB3-12958</a>] - Remove subsilver2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13063">PHPBB3-13063</a>] - Move functions_url_matcher to a proper class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13132">PHPBB3-13132</a>] - Twig: move the loops content from loops. to the root context</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13137">PHPBB3-13137</a>] - Remove schema.json from repository</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13178">PHPBB3-13178</a>] - Allow posting Emoji characters if the database supports it</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13206">PHPBB3-13206</a>] - DEBUG mode should automatically recompile stale style components</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13266">PHPBB3-13266</a>] - Enabling twig dump function if DEBUG is defined</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13388">PHPBB3-13388</a>] - Integrate routing and di parameters resolution</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13450">PHPBB3-13450</a>] - Type-hint return value of $phpbb_container-&gt;get()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13455">PHPBB3-13455</a>] - Change request_var() calls with $request-&gt;variable()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13468">PHPBB3-13468</a>] - Change add_log() calls with $phpbb_log-&gt;add()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13494">PHPBB3-13494</a>] - Replace set_config() calls with $config-&gt;set()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13496">PHPBB3-13496</a>] - Replace set_config_count() calls with $config-&gt;increment()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13497">PHPBB3-13497</a>] - Change get_tables() calls with $db_tools-&gt;sql_list_tables()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13498">PHPBB3-13498</a>] - Change get_user_avatar() calls with phpbb_get_avatar()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13499">PHPBB3-13499</a>] - Move get_remote_file() to functions_compatibility.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13595">PHPBB3-13595</a>] - Remove unused instances of the bbcode class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13614">PHPBB3-13614</a>] - Remove phpbb_pcre_utf8_support() and assume Unicode is supported by PCRE</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13652">PHPBB3-13652</a>] - Extend SQL query builder functionality</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13697">PHPBB3-13697</a>] - Rewriting/moving file system functions to filesystem class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13740">PHPBB3-13740</a>] - Refactoring installer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13762">PHPBB3-13762</a>] - Moving translation loading and language related functions into a service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13770">PHPBB3-13770</a>] - Make DI Container builder constructor dependency free</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13789">PHPBB3-13789</a>] - Implement Googles noCAPTCHA reCAPTCHA</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13801">PHPBB3-13801</a>] - Decouple the user object from the text_formatter.s9e.parser service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13803">PHPBB3-13803</a>] - Implement a generic and scalable way to reparse rich text</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13805">PHPBB3-13805</a>] - Make generate_text_for_storage() match the signature and feature set of message_parser::parse()</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13844">PHPBB3-13844</a>] - Replace help_ language magic with a help manager and normal language files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13847">PHPBB3-13847</a>] - Move quote generation to text_formatter.utils</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13891">PHPBB3-13891</a>] - Add CLI commands for reparsing text</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13901">PHPBB3-13901</a>] - Give quotes more whitespace in the posting form for readability</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13902">PHPBB3-13902</a>] - Increase the CSS margin around blockquote</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13904">PHPBB3-13904</a>] - Refactor attachment upload functions into service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13921">PHPBB3-13921</a>] - Try harder to fix block elements BBCodes used inside of inline elements BBCodes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13946">PHPBB3-13946</a>] - Increase the CSS margin around [code] - and [list] -</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13970">PHPBB3-13970</a>] - Save the value of the optional parameter in [code] - BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13986">PHPBB3-13986</a>] - Add --resume option to reparser CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13987">PHPBB3-13987</a>] - Add --dry-run option to reparser CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14000">PHPBB3-14000</a>] - Make it possible to use emojis in posts</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14097">PHPBB3-14097</a>] - Catch and show all exceptions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14107">PHPBB3-14107</a>] - dropdown rendering on rtl</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14124">PHPBB3-14124</a>] - Automatically translate exception in CLI</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14139">PHPBB3-14139</a>] - stop styling IDs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14157">PHPBB3-14157</a>] - Allow administrators to set an alt attribute for topic icons</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14162">PHPBB3-14162</a>] - Add CLI commands to manage migrations</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14168">PHPBB3-14168</a>] - Refactor attachment management functions into classes</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14174">PHPBB3-14174</a>] - issues in language\en\install_new.php </li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14175">PHPBB3-14175</a>] - Refactor responsive implementation for easier manipulation</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14206">PHPBB3-14206</a>] - Fix jumpbox incosistencies</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14220">PHPBB3-14220</a>] - Adding routing file locator and route loader services</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14231">PHPBB3-14231</a>] - Fix double home icon in breadcrumbs</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14237">PHPBB3-14237</a>] - Use language class in the notifications component</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14264">PHPBB3-14264</a>] - Don't use constants in textreparser plugins</li>
+ </ul>
+ <h4>New Feature</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10165">PHPBB3-10165</a>] - Send test email feature on email settings ACP page</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11768">PHPBB3-11768</a>] - Integrate s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12516">PHPBB3-12516</a>] - Always preview signature in UCP/ACP module</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12620">PHPBB3-12620</a>] - Allow the user to define multiples environments</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12692">PHPBB3-12692</a>] - Add a console command to manage the thumbnail</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13329">PHPBB3-13329</a>] - Rely on Intl and mbstring, use patchwork/utf8 as fallback</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13641">PHPBB3-13641</a>] - problem with custom BBCode</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13961">PHPBB3-13961</a>] - Add orderable service collections</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14125">PHPBB3-14125</a>] - Add --env option to all CLI commands</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14158">PHPBB3-14158</a>] - Add a lang_array function to the language service to avoid using call_user_func</li>
+ </ul>
+ <h4>Sub-task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12577">PHPBB3-12577</a>] - Use a lazy service to delay the construction of the passwords_manager</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12581">PHPBB3-12581</a>] - Use the proxy pattern for the template lexer</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12632">PHPBB3-12632</a>] - Use a twig.debug environment config value to enable Twig debug</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12633">PHPBB3-12633</a>] - Add debug.template.events</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12699">PHPBB3-12699</a>] - Replace instances in the message textarea keydown callback</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13421">PHPBB3-13421</a>] - Create an interface for db\tools.php</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13487">PHPBB3-13487</a>] - Add factory for db tool class</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13645">PHPBB3-13645</a>] - Moving feeds to controllers</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13647">PHPBB3-13647</a>] - Move FAQ to controller</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13654">PHPBB3-13654</a>] - Moving reports to controller</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13881">PHPBB3-13881</a>] - Unify quote removal in 3.1 and 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13935">PHPBB3-13935</a>] - Allow more admin-configurable schemes in post links</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14039">PHPBB3-14039</a>] - Refactoring the updater</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14044">PHPBB3-14044</a>] - Deduplicate the installers</li>
+ </ul>
+ <h4>Task</h4>
+ <ul>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9457">PHPBB3-9457</a>] - [Accessibility] - Add WAI-ARIA landmarks to the Prosilver template files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11528">PHPBB3-11528</a>] - Use mink for acceptance tests involving javascript execution</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12384">PHPBB3-12384</a>] - Run Travis CI HHVM tests against MySQLi instead of MySQL</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12505">PHPBB3-12505</a>] - Remove outdated media handling in attachment.html</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12564">PHPBB3-12564</a>] - Remove obsolete version definitions from module info files</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12916">PHPBB3-12916</a>] - Add separate nightly builds for 3.1 and 3.2</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13130">PHPBB3-13130</a>] - Update dependencies to Symfony 2.5</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13139">PHPBB3-13139</a>] - Update Twig to 1.18.0</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13363">PHPBB3-13363</a>] - Replace phpbb\php\ini with composer package bantu/ini-get-wrapper</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13407">PHPBB3-13407</a>] - Update Symfony Components to 2.7.x</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13572">PHPBB3-13572</a>] - Upgrade composer to 1.0.0-alpha9</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13634">PHPBB3-13634</a>] - Update README to show new branch names</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13725">PHPBB3-13725</a>] - Coding guidelines: static public</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13767">PHPBB3-13767</a>] - Remove .git from vendor/s9e/text-formatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13768">PHPBB3-13768</a>] - Update to Symfony 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13774">PHPBB3-13774</a>] - Update s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13777">PHPBB3-13777</a>] - Move acp/modules module handling code into a service</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13793">PHPBB3-13793</a>] - Remove message translation from exceptions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13800">PHPBB3-13800</a>] - Make extension manager an optional dependency for the router</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13804">PHPBB3-13804</a>] - Make template's user dependency optional</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13832">PHPBB3-13832</a>] - Replace use of deprecated e modifier of preg_replace in bbcode functions</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13985">PHPBB3-13985</a>] - Update s9e\TextFormatter</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14015">PHPBB3-14015</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14053">PHPBB3-14053</a>] - Remove @covers annotations from installer config test</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14056">PHPBB3-14056</a>] - Keep install schema resources in the install folder</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14096">PHPBB3-14096</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14140">PHPBB3-14140</a>] - Update Symfony to benefit from improvement to the console component</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14150">PHPBB3-14150</a>] - Update fast-image-size to newest release</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14205">PHPBB3-14205</a>] - Bump PHP requirement to 5.4</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14238">PHPBB3-14238</a>] - Update Symfony to the latest 2.8@dev</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14243">PHPBB3-14243</a>] - Exclude every .git directory from the pakages</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14256">PHPBB3-14256</a>] - Remove PHP7 from the allowed failures</li>
+ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14265">PHPBB3-14265</a>] - Make all tables available in the container</li>
+ </ul>
+
<a name="v315"></a><h3>Changes since 3.1.5</h3>
<h4>Bug</h4>
diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md
index 81a43b5664..a785c6d81c 100644
--- a/phpBB/docs/events.md
+++ b/phpBB/docs/events.md
@@ -1,3 +1,15 @@
+acp_ban_cell_append
+===
+* Location: adm/style/acp_ban.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the end of the ban cell area
+
+acp_ban_cell_prepend
+===
+* Location: adm/style/acp_ban.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the start of the ban cell area
+
acp_bbcodes_actions_append
===
* Location: adm/style/acp_bbcodes.html
@@ -16,6 +28,30 @@ acp_bbcodes_edit_fieldsets_after
* Since: 3.1.0-a3
* Purpose: Add settings to BBCode add/edit form
+acp_email_group_options_append
+===
+* Location: adm/style/acp_email.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the end of the group options select box
+
+acp_email_group_options_prepend
+===
+* Location: adm/style/acp_email.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the start of the group options select box
+
+acp_email_find_username_append
+===
+* Location: adm/style/acp_email.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the end of the fimd username link
+
+acp_email_find_username_prepend
+===
+* Location: adm/style/acp_email.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the start of the fimd username link
+
acp_email_options_after
===
* Location: adm/style/acp_email.html
@@ -64,6 +100,18 @@ acp_forums_prune_settings_prepend
* Since: 3.1.2-RC1
* Purpose: Add settings to forums before prune settings section
+acp_forums_quick_select_button_append
+===
+* Location: adm/style/acp_forums.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the quick select forum submit button
+
+acp_forums_quick_select_button_prepend
+===
+* Location: adm/style/acp_forums.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the quick select forum submit button
+
acp_forums_rules_settings_append
===
* Location: adm/style/acp_forums.html
@@ -88,6 +136,66 @@ acp_group_options_after
* Since: 3.1.0-b4
* Purpose: Add addtional options to group settings (after GROUP_RECEIVE_PM)
+acp_groups_find_username_append
+===
+* Location: adm/style/acp_groups.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the end of the find username link
+
+acp_groups_find_username_prepend
+===
+* Location: adm/style/acp_groups.html
+* Since: 3.1.7-RC1
+* Purpose: Add content at the start of the find username link
+
+acp_groups_manage_after
+===
+* Location: adm/style/acp_groups.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the manage groups table
+
+acp_groups_manage_before
+===
+* Location: adm/style/acp_groups.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the manage groups table
+
+acp_groups_position_legend_add_button_after
+===
+* Location: adm/style/acp_groups_position.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after adding group to legend submit button
+
+acp_groups_position_legend_add_button_before
+===
+* Location: adm/style/acp_groups_position.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before adding group to legend submit button
+
+acp_groups_position_teampage_add_button_after
+===
+* Location: adm/style/acp_groups_position.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after adding group to teampage submit button
+
+acp_groups_position_teampage_add_button_before
+===
+* Location: adm/style/acp_groups_position.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before adding group to teampage submit button
+
+acp_logs_quick_select_forum_button_append
+===
+* Location: adm/style/acp_logs.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the quick forum select form submit button
+
+acp_logs_quick_select_forum_button_prepend
+===
+* Location: adm/style/acp_logs.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the quick forum select form submit button
+
acp_main_actions_append
===
* Location: adm/style/acp_main.html
@@ -125,6 +233,102 @@ acp_overall_header_stylesheets_after
* Purpose: Add assets after stylesheets within the `<head>` tags in the ACP.
Note that INCLUDECSS will not work with this event.
+acp_permission_forum_copy_src_forum_append
+===
+* Location: adm/style/permission_forum_copy.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the sourse forum select form
+
+acp_permission_forum_copy_src_forum_prepend
+===
+* Location: adm/style/permission_forum_copy.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the sourse forum select form
+
+acp_permission_forum_copy_dest_forum_append
+===
+* Location: adm/style/permission_forum_copy.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the destiny forum select form
+
+acp_permission_forum_copy_dest_forum_prepend
+===
+* Location: adm/style/permission_forum_copy.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the destiny forum select form
+
+acp_permissions_add_group_options_append
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the group multiple select form
+
+acp_permissions_add_group_options_prepend
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the group multiple select form
+
+acp_permissions_find_username_append
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the find username link
+
+acp_permissions_find_username_prepend
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the find username link
+
+acp_permissions_select_forum_append
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the forum select form label
+
+acp_permissions_select_forum_prepend
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the forum select form label
+
+acp_permissions_select_group_after
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the group select form in usergroup view
+
+acp_permissions_select_group_append
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the group select form label
+
+acp_permissions_select_group_before
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the group select form in usergroup view
+
+acp_permissions_select_group_prepend
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the group select form label
+
+acp_permissions_select_multiple_forum_append
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the forum multiple select form label
+
+acp_permissions_select_multiple_forum_prepend
+===
+* Location: adm/style/acp_permissions.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the forum multiple select form label
+
acp_posting_buttons_after
===
* Locations:
@@ -146,6 +350,34 @@ acp_profile_contact_before
* Since: 3.1.6-RC1
* Purpose: Add extra options to custom profile field configuration in the ACP
+acp_prune_forums_append
+===
+* Locations:
+ + adm/style/acp_prune_forums.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the forum select form label
+
+acp_prune_forums_prepend
+===
+* Locations:
+ + adm/style/acp_prune_forums.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the forum select form label
+
+acp_prune_users_find_username_append
+===
+* Locations:
+ + adm/style/acp_prune_users.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the find username link
+
+acp_prune_users_find_username_prepend
+===
+* Locations:
+ + adm/style/acp_prune_users.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the find username link
+
acp_ranks_edit_after
===
* Locations:
@@ -297,6 +529,18 @@ acp_users_prefs_view_prepend
* Since: 3.1.0-b3
* Purpose: Add user options fieldset to the top of ACP users view prefs settings
+acp_users_select_group_after
+===
+* Location: adm/style/acp_users.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after group select form
+
+acp_users_select_group_before
+===
+* Location: adm/style/acp_users.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before group select form
+
attachment_file_after
===
* Locations:
@@ -1184,6 +1428,13 @@ quickreply_editor_subject_before
* Since: 3.1.7-RC1
* Purpose: Add content before the quick reply subject textbox
+search_body_form_after
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the search form
+
search_body_form_before
===
* Locations:
@@ -1191,6 +1442,90 @@ search_body_form_before
* Since: 3.1.5-RC1
* Purpose: Add content before the search form
+search_body_recent_search_after
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the recent search queries list
+
+search_body_recent_search_before
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the recent search queries list
+
+search_body_search_display_options_append
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the bottom of the search query display options fields set
+
+search_body_search_display_options_prepend
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the top of the search query display options fields set
+
+search_body_search_options_after
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the search query options fields set
+
+search_body_search_options_append
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the bottom of the search query options fields set
+
+search_body_search_options_before
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the search query options fields set
+
+search_body_search_options_prepend
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the top of the search query options fields set
+
+search_body_search_query_after
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content after the search query fields set
+
+search_body_search_query_append
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the bottom of the search query fields set
+
+search_body_search_query_before
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add content before the search query fields set
+
+search_body_search_query_prepend
+===
+* Locations:
+ + styles/prosilver/template/search_body.html
+* Since: 3.1.7-RC1
+* Purpose: Put content at the top of the search query fields set
+
search_results_header_after
===
* Locations:
@@ -1883,6 +2218,13 @@ viewtopic_body_post_buttons_list_before
* Purpose: Add post button custom list to posts (next to edit, quote etc),
before the original list.
+viewtopic_body_post_subject_before
+===
+* Locations:
+ + styles/prosilver/template/viewtopic_body.html
+* Since: 3.1.7-RC1
+* Purpose: Add data before post icon and subject
+
viewtopic_body_postrow_custom_fields_after
===
* Locations:
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index 1f6fbc2cae..9a3b86a16a 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -25,7 +25,7 @@ class acp_captcha
function main($id, $mode)
{
- global $db, $user, $auth, $template, $phpbb_log, $request;
+ global $user, $auth, $template, $phpbb_log, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;
$user->add_lang('acp/board');
@@ -53,11 +53,36 @@ class acp_captcha
else
{
$config_vars = array(
- 'enable_confirm' => array('tpl' => 'REG_ENABLE', 'default' => false),
- 'enable_post_confirm' => array('tpl' => 'POST_ENABLE', 'default' => false),
- 'confirm_refresh' => array('tpl' => 'CONFIRM_REFRESH', 'default' => false),
- 'max_reg_attempts' => array('tpl' => 'REG_LIMIT', 'default' => 0),
- 'max_login_attempts' => array('tpl' => 'MAX_LOGIN_ATTEMPTS', 'default' => 0),
+ 'enable_confirm' => array(
+ 'tpl' => 'REG_ENABLE',
+ 'default' => false,
+ 'validate' => 'bool',
+ 'lang' => 'VISUAL_CONFIRM_REG',
+ ),
+ 'enable_post_confirm' => array(
+ 'tpl' => 'POST_ENABLE',
+ 'default' => false,
+ 'validate' => 'bool',
+ 'lang' => 'VISUAL_CONFIRM_POST',
+ ),
+ 'confirm_refresh' => array(
+ 'tpl' => 'CONFIRM_REFRESH',
+ 'default' => false,
+ 'validate' => 'bool',
+ 'lang' => 'VISUAL_CONFIRM_REFRESH',
+ ),
+ 'max_reg_attempts' => array(
+ 'tpl' => 'REG_LIMIT',
+ 'default' => 0,
+ 'validate' => 'int:0:99999',
+ 'lang' => 'REG_LIMIT',
+ ),
+ 'max_login_attempts' => array(
+ 'tpl' => 'MAX_LOGIN_ATTEMPTS',
+ 'default' => 0,
+ 'validate' => 'int:0:99999',
+ 'lang' => 'MAX_LOGIN_ATTEMPTS',
+ ),
);
$this->tpl_name = 'acp_captcha';
@@ -66,12 +91,31 @@ class acp_captcha
add_form_key($form_key);
$submit = $request->variable('main_submit', false);
+ $error = $cfg_array = array();
- if ($submit && check_form_key($form_key))
+ if ($submit)
{
foreach ($config_vars as $config_var => $options)
{
- $config->set($config_var, $request->variable($config_var, $options['default']));
+ $cfg_array[$config_var] = $request->variable($config_var, $options['default']);
+ }
+ validate_config_vars($config_vars, $cfg_array, $error);
+
+ if (!check_form_key($form_key))
+ {
+ $error[] = $user->lang['FORM_INVALID'];
+ }
+ if ($error)
+ {
+ $submit = false;
+ }
+ }
+
+ if ($submit)
+ {
+ foreach ($cfg_array as $key => $value)
+ {
+ $config->set($key, $value);
}
if ($selected !== $config['captcha_plugin'])
@@ -95,10 +139,6 @@ class acp_captcha
}
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
}
- else if ($submit)
- {
- trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
else
{
$captcha_select = '';
@@ -125,6 +165,7 @@ class acp_captcha
'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
'CAPTCHA_SELECT' => $captcha_select,
+ 'ERROR_MSG' => implode('<br />', $error),
'U_ACTION' => $this->u_action,
));
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index dd9ff37773..7f1e629875 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -944,63 +944,62 @@ class acp_forums
/**
* Update forum data
*/
- function update_forum_data(&$forum_data)
+ function update_forum_data(&$forum_data_ary)
{
global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
$errors = array();
- $forum_data_ary = $forum_data;
+ $forum_data = $forum_data_ary;
/**
* Validate the forum data before we create/update the forum
*
* @event core.acp_manage_forums_validate_data
- * @var array forum_data_ary Array with new forum data
+ * @var array forum_data Array with new forum data
* @var array errors Array of errors, should be strings and not
* language key.
* @since 3.1.0-a1
- * @change 3.2.0-a1 Replaced forum_data with forum_data_ary
*/
- $vars = array('forum_data_ary', 'errors');
+ $vars = array('forum_data', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_validate_data', compact($vars)));
- $forum_data = $forum_data_ary;
- unset($forum_data_ary);
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
- if ($forum_data['forum_name'] == '')
+ if ($forum_data_ary['forum_name'] == '')
{
$errors[] = $user->lang['FORUM_NAME_EMPTY'];
}
- if (utf8_strlen($forum_data['forum_desc']) > 4000)
+ if (utf8_strlen($forum_data_ary['forum_desc']) > 4000)
{
$errors[] = $user->lang['FORUM_DESC_TOO_LONG'];
}
- if (utf8_strlen($forum_data['forum_rules']) > 4000)
+ if (utf8_strlen($forum_data_ary['forum_rules']) > 4000)
{
$errors[] = $user->lang['FORUM_RULES_TOO_LONG'];
}
- if ($forum_data['forum_password'] || $forum_data['forum_password_confirm'])
+ if ($forum_data_ary['forum_password'] || $forum_data_ary['forum_password_confirm'])
{
- if ($forum_data['forum_password'] != $forum_data['forum_password_confirm'])
+ if ($forum_data_ary['forum_password'] != $forum_data_ary['forum_password_confirm'])
{
- $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = '';
+ $forum_data_ary['forum_password'] = $forum_data_ary['forum_password_confirm'] = '';
$errors[] = $user->lang['FORUM_PASSWORD_MISMATCH'];
}
}
- if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0)
+ if ($forum_data_ary['prune_days'] < 0 || $forum_data_ary['prune_viewed'] < 0 || $forum_data_ary['prune_freq'] < 0)
{
- $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0;
+ $forum_data_ary['prune_days'] = $forum_data_ary['prune_viewed'] = $forum_data_ary['prune_freq'] = 0;
$errors[] = $user->lang['FORUM_DATA_NEGATIVE'];
}
$range_test_ary = array(
- array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'),
+ array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data_ary['forum_topics_per_page'], 'column_type' => 'TINT:0'),
);
- if (!empty($forum_data['forum_image']) && !file_exists($phpbb_root_path . $forum_data['forum_image']))
+ if (!empty($forum_data_ary['forum_image']) && !file_exists($phpbb_root_path . $forum_data_ary['forum_image']))
{
$errors[] = $user->lang['FORUM_IMAGE_NO_EXIST'];
}
@@ -1014,17 +1013,17 @@ class acp_forums
// 8 = prune stickies
// 16 = show active topics
// 32 = enable post review
- $forum_data['forum_flags'] = 0;
- $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
- $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
- $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
- $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
- $forum_data['forum_flags'] += ($forum_data['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
+ $forum_data_ary['forum_flags'] = 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0;
+ $forum_data_ary['forum_flags'] += ($forum_data_ary['enable_quick_reply']) ? FORUM_FLAG_QUICK_REPLY : 0;
// Unset data that are not database fields
- $forum_data_sql = $forum_data;
+ $forum_data_sql = $forum_data_ary;
unset($forum_data_sql['forum_link_track']);
unset($forum_data_sql['prune_old_polls']);
@@ -1062,22 +1061,21 @@ class acp_forums
}
unset($forum_data_sql['forum_password_unset']);
- $forum_data_ary = $forum_data;
+ $forum_data = $forum_data_ary;
/**
* Remove invalid values from forum_data_sql that should not be updated
*
* @event core.acp_manage_forums_update_data_before
- * @var array forum_data_ary Array with forum data
+ * @var array forum_data Array with forum data
* @var array forum_data_sql Array with data we are going to update
* If forum_data_sql[forum_id] is set, we update
* that forum, otherwise a new one is created.
* @since 3.1.0-a1
- * @change 3.2.0-a1 Replaced forum_data by forum_data_ary
*/
- $vars = array('forum_data_ary', 'forum_data_sql');
+ $vars = array('forum_data', 'forum_data_sql');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_before', compact($vars)));
- $forum_data = $forum_data_ary;
- unset($forum_data_ary);
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
$is_new_forum = !isset($forum_data_sql['forum_id']);
@@ -1134,9 +1132,9 @@ class acp_forums
$sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql);
$db->sql_query($sql);
- $forum_data['forum_id'] = $db->sql_nextid();
+ $forum_data_ary['forum_id'] = $db->sql_nextid();
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data['forum_name']));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_ADD', false, array($forum_data_ary['forum_name']));
}
else
{
@@ -1351,17 +1349,17 @@ class acp_forums
$db->sql_query($sql);
// Add it back
- $forum_data['forum_id'] = $forum_id;
+ $forum_data_ary['forum_id'] = $forum_id;
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data['forum_name']));
+ $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_FORUM_EDIT', false, array($forum_data_ary['forum_name']));
}
- $forum_data_ary = $forum_data;
+ $forum_data = $forum_data_ary;
/**
* Event after a forum was updated or created
*
* @event core.acp_manage_forums_update_data_after
- * @var array forum_data_ary Array with forum data
+ * @var array forum_data Array with forum data
* @var array forum_data_sql Array with data we updated
* @var bool is_new_forum Did we create a forum or update one
* If you want to overwrite this value,
@@ -1369,12 +1367,11 @@ class acp_forums
* @var array errors Array of errors, should be strings and not
* language key.
* @since 3.1.0-a1
- * @change 3.2.0-a1 Replaced forum_data with forum_data_ary
*/
- $vars = array('forum_data_ary', 'forum_data_sql', 'is_new_forum', 'errors');
+ $vars = array('forum_data', 'forum_data_sql', 'is_new_forum', 'errors');
extract($phpbb_dispatcher->trigger_event('core.acp_manage_forums_update_data_after', compact($vars)));
- $forum_data = $forum_data_ary;
- unset($forum_data_ary);
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
return $errors;
}
diff --git a/phpBB/includes/acp/acp_update.php b/phpBB/includes/acp/acp_update.php
index 83604b8261..52897e1043 100644
--- a/phpBB/includes/acp/acp_update.php
+++ b/phpBB/includes/acp/acp_update.php
@@ -52,7 +52,7 @@ class acp_update
$template->assign_block_vars('updates_available', $version_data);
}
- $update_link = append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update');
+ $update_link = $phpbb_root_path . 'install/app.' . $phpEx;
$template->assign_vars(array(
'S_UP_TO_DATE' => empty($updates_available),
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index bd73201290..680d5a2b4e 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -28,7 +28,7 @@ if (!defined('IN_PHPBB'))
*/
// phpBB Version
-define('PHPBB_VERSION', '3.2.0-a1-dev');
+define('PHPBB_VERSION', '3.2.0-a2-dev');
// QA-related
// define('PHPBB_QA', 1);
@@ -221,6 +221,9 @@ define('CAPTCHA_MAX_CHARS', 7);
// Additional constants
define('VOTE_CONVERTED', 127);
+// BC global FTW
+global $table_prefix;
+
// Table names
define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups');
define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options');
diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php
index 390b59b9e9..f6c01c46ff 100644
--- a/phpBB/includes/functions_acp.php
+++ b/phpBB/includes/functions_acp.php
@@ -230,7 +230,7 @@ function h_radio($name, $input_ary, $input_default = false, $id = false, $key =
/**
* Build configuration template for acp configuration pages
*/
-function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
+function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars)
{
global $user, $module, $phpbb_dispatcher;
@@ -238,18 +238,18 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$name = 'config[' . $config_key . ']';
// Make sure there is no notice printed out for non-existent config options (we simply set them)
- if (!isset($new[$config_key]))
+ if (!isset($new_ary[$config_key]))
{
- $new[$config_key] = '';
+ $new_ary[$config_key] = '';
}
switch ($tpl_type[0])
{
case 'password':
- if ($new[$config_key] !== '')
+ if ($new_ary[$config_key] !== '')
{
// replace passwords with asterixes
- $new[$config_key] = '********';
+ $new_ary[$config_key] = '********';
}
case 'text':
case 'url':
@@ -267,7 +267,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$size = (int) $tpl_type[1];
$maxlength = (int) $tpl_type[2];
- $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
+ $tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new_ary[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
break;
case 'number':
@@ -279,7 +279,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$maxlength = strlen( (string) $max );
}
- $tpl = '<input id="' . $key . '" type="number" maxlength="' . (( $maxlength != '' ) ? $maxlength : 255) . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new[$config_key] . '" />';
+ $tpl = '<input id="' . $key . '" type="number" maxlength="' . (( $maxlength != '' ) ? $maxlength : 255) . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new_ary[$config_key] . '" />';
break;
case 'dimension':
@@ -293,19 +293,19 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$size = $maxlength = strlen( (string) $max );
}
- $tpl = '<input id="' . $key . '" type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new[$config_key . '_width'] . '" /> x <input type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new[$config_key . '_height'] . '" />';
+ $tpl = '<input id="' . $key . '" type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new_ary[$config_key . '_width'] . '" /> x <input type="number"' . (( $size != '' ) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength != '') ? $maxlength : 255) . '"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new_ary[$config_key . '_height'] . '" />';
break;
case 'textarea':
$rows = (int) $tpl_type[1];
$cols = (int) $tpl_type[2];
- $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new[$config_key] . '</textarea>';
+ $tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new_ary[$config_key] . '</textarea>';
break;
case 'radio':
- $key_yes = ($new[$config_key]) ? ' checked="checked"' : '';
- $key_no = (!$new[$config_key]) ? ' checked="checked"' : '';
+ $key_yes = ($new_ary[$config_key]) ? ' checked="checked"' : '';
+ $key_no = (!$new_ary[$config_key]) ? ' checked="checked"' : '';
$tpl_type_cond = explode('_', $tpl_type[1]);
$type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
@@ -342,7 +342,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
switch ($value)
{
case '{CONFIG_VALUE}':
- $value = $new[$config_key];
+ $value = $new_ary[$config_key];
break;
case '{KEY}':
@@ -355,7 +355,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
}
else
{
- $args = array($new[$config_key], $key);
+ $args = array($new_ary[$config_key], $key);
}
$return = call_user_func_array($call, $args);
@@ -383,7 +383,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
$tpl .= $vars['append'];
}
- $new_ary = $new;
+ $new = $new_ary;
/**
* Overwrite the html code we display for the config value
*
@@ -393,17 +393,16 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars)
* 1 [optional] => string: size, int: minimum
* 2 [optional] => string: max. length, int: maximum
* @var string key Should be used for the id attribute in html
- * @var array new_ary Array with the config values we display
+ * @var array new Array with the config values we display
* @var string name Should be used for the name attribute
* @var array vars Array with the options for the config
* @var string tpl The resulting html code we display
* @since 3.1.0-a1
- * @change 3.2.0-a1 Replaced new with new_ary
*/
- $vars = array('tpl_type', 'key', 'new_ary', 'name', 'vars', 'tpl');
+ $vars = array('tpl_type', 'key', 'new', 'name', 'vars', 'tpl');
extract($phpbb_dispatcher->trigger_event('core.build_config_template', compact($vars)));
- $new = $new_ary;
- unset($new_ary);
+ $new_ary = $new;
+ unset($new);
return $tpl;
}
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index b87220caa5..997cafdea4 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -957,10 +957,10 @@ function smiley_text($text, $force_option = false)
* @param mixed $forum_id The forum id the attachments are displayed in (false if in private message)
* @param string &$message The post/private message
* @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing.
-* @param array &$update_count The attachment counts to be updated - will be filled
+* @param array &$update_count_ary The attachment counts to be updated - will be filled
* @param bool $preview If set to true the attachments are parsed for preview. Within preview mode the comments are fetched from the given $attachments array and not fetched from the database.
*/
-function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false)
+function parse_attachments($forum_id, &$message, &$attachments, &$update_count_ary, $preview = false)
{
if (!sizeof($attachments))
{
@@ -1159,7 +1159,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'U_INLINE_LINK' => $inline_link,
);
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
// Images, but display Thumbnail
@@ -1172,7 +1172,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'THUMB_IMAGE' => $thumbnail_link,
);
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
// Macromedia Flash Files
@@ -1187,7 +1187,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
);
// Viewed/Heared File ... update the download count
- $update_count[] = $attachment['attach_id'];
+ $update_count_ary[] = $attachment['attach_id'];
break;
default:
@@ -1210,7 +1210,7 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
);
}
- $update_count_ary = $update_count;
+ $update_count = $update_count_ary;
/**
* Use this event to modify the attachment template data.
*
@@ -1224,9 +1224,8 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
* @var array extensions Array with attachment extensions data
* @var mixed forum_id The forum id the attachments are displayed in (false if in private message)
* @var bool preview Flag indicating if we are in post preview mode
- * @var array update_count_ary Array with attachment ids to update download count
+ * @var array update_count Array with attachment ids to update download count
* @since 3.1.0-RC5
- * @change 3.2.0-a1 Replaced update_count with update_count_ary
*/
$vars = array(
'attachment',
@@ -1236,11 +1235,11 @@ function parse_attachments($forum_id, &$message, &$attachments, &$update_count,
'extensions',
'forum_id',
'preview',
- 'update_count_ary',
+ 'update_count',
);
extract($phpbb_dispatcher->trigger_event('core.parse_attachments_modify_template_data', compact($vars)));
- $update_count = $update_count_ary;
- unset($update_count_ary);
+ $update_count_ary = $update_count;
+ unset($update_count);
$template->assign_block_vars('_file', $block_array);
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index 9e45f32689..e3412c9875 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -750,12 +750,12 @@ function generate_forum_rules(&$forum_data)
* Create forum navigation links for given forum, create parent
* list if currently null, assign basic forum info to template
*/
-function generate_forum_nav(&$forum_data)
+function generate_forum_nav(&$forum_data_ary)
{
global $db, $user, $template, $auth, $config;
global $phpEx, $phpbb_root_path, $phpbb_dispatcher;
- if (!$auth->acl_get('f_list', $forum_data['forum_id']))
+ if (!$auth->acl_get('f_list', $forum_data_ary['forum_id']))
{
return;
}
@@ -763,7 +763,7 @@ function generate_forum_nav(&$forum_data)
$navlinks = $navlinks_parents = $forum_template_data = array();
// Get forum parents
- $forum_parents = get_forum_parents($forum_data);
+ $forum_parents = get_forum_parents($forum_data_ary);
$microdata_attr = 'data-forum-id';
@@ -793,46 +793,45 @@ function generate_forum_nav(&$forum_data)
}
$navlinks = array(
- 'S_IS_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false,
- 'S_IS_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false,
- 'S_IS_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false,
- 'FORUM_NAME' => $forum_data['forum_name'],
- 'FORUM_ID' => $forum_data['forum_id'],
- 'MICRODATA' => $microdata_attr . '="' . $forum_data['forum_id'] . '"',
- 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id']),
+ 'S_IS_CAT' => ($forum_data_ary['forum_type'] == FORUM_CAT) ? true : false,
+ 'S_IS_LINK' => ($forum_data_ary['forum_type'] == FORUM_LINK) ? true : false,
+ 'S_IS_POST' => ($forum_data_ary['forum_type'] == FORUM_POST) ? true : false,
+ 'FORUM_NAME' => $forum_data_ary['forum_name'],
+ 'FORUM_ID' => $forum_data_ary['forum_id'],
+ 'MICRODATA' => $microdata_attr . '="' . $forum_data_ary['forum_id'] . '"',
+ 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data_ary['forum_id']),
);
$forum_template_data = array(
- 'FORUM_ID' => $forum_data['forum_id'],
- 'FORUM_NAME' => $forum_data['forum_name'],
- 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']),
+ 'FORUM_ID' => $forum_data_ary['forum_id'],
+ 'FORUM_NAME' => $forum_data_ary['forum_name'],
+ 'FORUM_DESC' => generate_text_for_display($forum_data_ary['forum_desc'], $forum_data_ary['forum_desc_uid'], $forum_data_ary['forum_desc_bitfield'], $forum_data_ary['forum_desc_options']),
- 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false,
+ 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data_ary['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data_ary['forum_options'])) ? true : false,
);
- $forum_data_ary = $forum_data;
+ $forum_data = $forum_data_ary;
/**
* Event to modify the navlinks text
*
* @event core.generate_forum_nav
- * @var array forum_data_ary Array with the forum data
+ * @var array forum_data Array with the forum data
* @var array forum_template_data Array with generic forum template data
* @var string microdata_attr The microdata attribute
* @var array navlinks_parents Array with the forum parents navlinks data
* @var array navlinks Array with the forum navlinks data
* @since 3.1.5-RC1
- * @change 3.2.0-a1 Replaced forum_data with forum_data_ary
*/
$vars = array(
- 'forum_data_ary',
+ 'forum_data',
'forum_template_data',
'microdata_attr',
'navlinks_parents',
'navlinks',
);
extract($phpbb_dispatcher->trigger_event('core.generate_forum_nav', compact($vars)));
- $forum_data = $forum_data_ary;
- unset($forum_data_ary);
+ $forum_data_ary = $forum_data;
+ unset($forum_data);
$template->assign_block_vars_array('navlinks', $navlinks_parents);
$template->assign_block_vars('navlinks', $navlinks);
@@ -1164,14 +1163,14 @@ function display_reasons($reason_id = 0)
/**
* Display user activity (action forum/topic)
*/
-function display_user_activity(&$userdata)
+function display_user_activity(&$userdata_ary)
{
global $auth, $template, $db, $user;
global $phpbb_root_path, $phpEx;
global $phpbb_container, $phpbb_dispatcher;
// Do not display user activity for users having more than 5000 posts...
- if ($userdata['user_posts'] > 5000)
+ if ($userdata_ary['user_posts'] > 5000)
{
return;
}
@@ -1198,7 +1197,7 @@ function display_user_activity(&$userdata)
// Obtain active forum
$sql = 'SELECT forum_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $userdata['user_id'] . '
+ WHERE poster_id = ' . $userdata_ary['user_id'] . '
AND post_postcount = 1
AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . '
GROUP BY forum_id
@@ -1220,7 +1219,7 @@ function display_user_activity(&$userdata)
// Obtain active topic
$sql = 'SELECT topic_id, COUNT(post_id) AS num_posts
FROM ' . POSTS_TABLE . '
- WHERE poster_id = ' . $userdata['user_id'] . '
+ WHERE poster_id = ' . $userdata_ary['user_id'] . '
AND post_postcount = 1
AND ' . $phpbb_content_visibility->get_forums_visibility_sql('post', $forum_ary) . '
GROUP BY topic_id
@@ -1240,24 +1239,23 @@ function display_user_activity(&$userdata)
}
}
- $userdata_ary = $userdata;
+ $userdata = $userdata_ary;
/**
* Alter list of forums and topics to display as active
*
* @event core.display_user_activity_modify_actives
- * @var array userdata_ary User's data
+ * @var array userdata User's data
* @var array active_f_row List of active forums
* @var array active_t_row List of active posts
* @since 3.1.0-RC3
- * @change 3.2.0-a1 Replaced userdata with userdata_ary
*/
- $vars = array('userdata_ary', 'active_f_row', 'active_t_row');
+ $vars = array('userdata', 'active_f_row', 'active_t_row');
extract($phpbb_dispatcher->trigger_event('core.display_user_activity_modify_actives', compact($vars)));
- $userdata = $userdata_ary;
- unset($userdata_ary);
+ $userdata_ary = $userdata;
+ unset($userdata);
- $userdata['active_t_row'] = $active_t_row;
- $userdata['active_f_row'] = $active_f_row;
+ $userdata_ary['active_t_row'] = $active_t_row;
+ $userdata_ary['active_f_row'] = $active_f_row;
$active_f_name = $active_f_id = $active_f_count = $active_f_pct = '';
if (!empty($active_f_row['num_posts']))
@@ -1265,7 +1263,7 @@ function display_user_activity(&$userdata)
$active_f_name = $active_f_row['forum_name'];
$active_f_id = $active_f_row['forum_id'];
$active_f_count = $active_f_row['num_posts'];
- $active_f_pct = ($userdata['user_posts']) ? ($active_f_count / $userdata['user_posts']) * 100 : 0;
+ $active_f_pct = ($userdata_ary['user_posts']) ? ($active_f_count / $userdata_ary['user_posts']) * 100 : 0;
}
$active_t_name = $active_t_id = $active_t_count = $active_t_pct = '';
@@ -1274,10 +1272,10 @@ function display_user_activity(&$userdata)
$active_t_name = $active_t_row['topic_title'];
$active_t_id = $active_t_row['topic_id'];
$active_t_count = $active_t_row['num_posts'];
- $active_t_pct = ($userdata['user_posts']) ? ($active_t_count / $userdata['user_posts']) * 100 : 0;
+ $active_t_pct = ($userdata_ary['user_posts']) ? ($active_t_count / $userdata_ary['user_posts']) * 100 : 0;
}
- $l_active_pct = ($userdata['user_id'] != ANONYMOUS && $userdata['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE'];
+ $l_active_pct = ($userdata_ary['user_id'] != ANONYMOUS && $userdata_ary['user_id'] == $user->data['user_id']) ? $user->lang['POST_PCT_ACTIVE_OWN'] : $user->lang['POST_PCT_ACTIVE'];
$template->assign_vars(array(
'ACTIVE_FORUM' => $active_f_name,
diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php
deleted file mode 100644
index d9d073e984..0000000000
--- a/phpBB/includes/functions_install.php
+++ /dev/null
@@ -1,540 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Returns an array of available DBMS with some data, if a DBMS is specified it will only
-* return data for that DBMS and will load its extension if necessary.
-*/
-function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false)
-{
- global $lang;
- $available_dbms = array(
- // Note: php 5.5 alpha 2 deprecated mysql.
- // Keep mysqli before mysql in this list.
- 'mysqli' => array(
- 'LABEL' => 'MySQL with MySQLi Extension',
- 'SCHEMA' => 'mysql_41',
- 'MODULE' => 'mysqli',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\mysqli',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mysql' => array(
- 'LABEL' => 'MySQL',
- 'SCHEMA' => 'mysql',
- 'MODULE' => 'mysql',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\mysql',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssql' => array(
- 'LABEL' => 'MS SQL Server 2000+',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'mssql',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssql',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssql_odbc'=> array(
- 'LABEL' => 'MS SQL Server [ ODBC ]',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'odbc',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssql_odbc',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'mssqlnative' => array(
- 'LABEL' => 'MS SQL Server 2005+ [ Native ]',
- 'SCHEMA' => 'mssql',
- 'MODULE' => 'sqlsrv',
- 'DELIM' => 'GO',
- 'DRIVER' => 'phpbb\db\driver\mssqlnative',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'oracle' => array(
- 'LABEL' => 'Oracle',
- 'SCHEMA' => 'oracle',
- 'MODULE' => 'oci8',
- 'DELIM' => '/',
- 'DRIVER' => 'phpbb\db\driver\oracle',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'postgres' => array(
- 'LABEL' => 'PostgreSQL 8.3+',
- 'SCHEMA' => 'postgres',
- 'MODULE' => 'pgsql',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\postgres',
- 'AVAILABLE' => true,
- '2.0.x' => true,
- ),
- 'sqlite' => array(
- 'LABEL' => 'SQLite',
- 'SCHEMA' => 'sqlite',
- 'MODULE' => 'sqlite',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\sqlite',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- 'sqlite3' => array(
- 'LABEL' => 'SQLite3',
- 'SCHEMA' => 'sqlite',
- 'MODULE' => 'sqlite3',
- 'DELIM' => ';',
- 'DRIVER' => 'phpbb\db\driver\sqlite3',
- 'AVAILABLE' => true,
- '2.0.x' => false,
- ),
- );
-
- if ($dbms)
- {
- if (isset($available_dbms[$dbms]))
- {
- $available_dbms = array($dbms => $available_dbms[$dbms]);
- }
- else
- {
- return array();
- }
- }
-
- // now perform some checks whether they are really available
- foreach ($available_dbms as $db_name => $db_ary)
- {
- if ($only_20x_options && !$db_ary['2.0.x'])
- {
- if ($return_unavailable)
- {
- $available_dbms[$db_name]['AVAILABLE'] = false;
- }
- else
- {
- unset($available_dbms[$db_name]);
- }
- continue;
- }
-
- $dll = $db_ary['MODULE'];
-
- if (!@extension_loaded($dll))
- {
- if ($return_unavailable)
- {
- $available_dbms[$db_name]['AVAILABLE'] = false;
- }
- else
- {
- unset($available_dbms[$db_name]);
- }
- continue;
- }
- $any_db_support = true;
- }
-
- if ($return_unavailable)
- {
- $available_dbms['ANY_DB_SUPPORT'] = $any_db_support;
- }
- return $available_dbms;
-}
-
-/**
-* Generate the drop down of available database options
-*/
-function dbms_select($default = '', $only_20x_options = false)
-{
- global $lang;
-
- $available_dbms = get_available_dbms(false, false, $only_20x_options);
- $dbms_options = '';
- foreach ($available_dbms as $dbms_name => $details)
- {
- $selected = ($dbms_name == $default) ? ' selected="selected"' : '';
- $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . $lang['DLL_' . strtoupper($dbms_name)] . '</option>';
- }
- return $dbms_options;
-}
-
-/**
-* Used to test whether we are able to connect to the database the user has specified
-* and identify any problems (eg there are already tables with the names we want to use
-* @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()}
-* necessary extensions should be loaded already
-*/
-function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true)
-{
- global $phpbb_root_path, $phpEx, $config, $lang, $phpbb_filesystem;
-
- $dbms = $dbms_details['DRIVER'];
-
- // Instantiate it and set return on error true
- $db = new $dbms();
- $db->sql_return_on_error(true);
-
- // Check that we actually have a database name before going any further.....
- if ($dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite' && $dbms_details['DRIVER'] != 'phpbb\db\driver\sqlite3' && $dbms_details['DRIVER'] != 'phpbb\db\driver\oracle' && $dbname === '')
- {
- $error[] = $lang['INST_ERR_DB_NO_NAME'];
- return false;
- }
-
- // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
- if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos($phpbb_filesystem->realpath($dbhost), $phpbb_filesystem->realpath('../')) === 0)
- {
- $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
- return false;
- }
-
- // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
- switch ($dbms_details['DRIVER'])
- {
- case 'phpbb\db\driver\mysql':
- case 'phpbb\db\driver\mysqli':
- if (strspn($table_prefix, '-./\\') !== 0)
- {
- $error[] = $lang['INST_ERR_PREFIX_INVALID'];
- return false;
- }
-
- // no break;
-
- case 'phpbb\db\driver\postgres':
- $prefix_length = 36;
- break;
-
- case 'phpbb\db\driver\mssql':
- case 'phpbb\db\driver\mssql_odbc':
- case 'phpbb\db\driver\mssqlnative':
- $prefix_length = 90;
- break;
-
- case 'phpbb\db\driver\sqlite':
- case 'phpbb\db\driver\sqlite3':
- $prefix_length = 200;
- break;
-
- case 'phpbb\db\driver\oracle':
- $prefix_length = 6;
- break;
- }
-
- if (strlen($table_prefix) > $prefix_length)
- {
- $error[] = sprintf($lang['INST_ERR_PREFIX_TOO_LONG'], $prefix_length);
- return false;
- }
-
- // Try and connect ...
- if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true)))
- {
- $db_error = $db->sql_error();
- $error[] = $lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? utf8_convert_message($db_error['message']) : $lang['INST_ERR_DB_NO_ERROR']);
- }
- else
- {
- // Likely matches for an existing phpBB installation
- if (!$prefix_may_exist)
- {
- $temp_prefix = strtolower($table_prefix);
- $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users');
-
- $db_tools_factory = new \phpbb\db\tools\factory();
- $db_tools = $db_tools_factory->get($db);
- $tables = $db_tools->sql_list_tables();
- $tables = array_map('strtolower', $tables);
- $table_intersect = array_intersect($tables, $table_ary);
-
- if (sizeof($table_intersect))
- {
- $error[] = $lang['INST_ERR_PREFIX'];
- }
- }
-
- // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
- switch ($dbms_details['DRIVER'])
- {
- case 'phpbb\db\driver\mysqli':
- if (version_compare(mysqli_get_server_info($db->get_db_connect_id()), '4.1.3', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
- }
- break;
-
- case 'phpbb\db\driver\sqlite':
- if (version_compare(sqlite_libversion(), '2.8.2', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
- }
- break;
-
- case 'phpbb\db\driver\sqlite3':
- $version = \SQLite3::version();
- if (version_compare($version['versionString'], '3.6.15', '<'))
- {
- $error[] = $lang['INST_ERR_DB_NO_SQLITE3'];
- }
- break;
-
- case 'phpbb\db\driver\oracle':
- if ($unicode_check)
- {
- $sql = "SELECT *
- FROM NLS_DATABASE_PARAMETERS
- WHERE PARAMETER = 'NLS_RDBMS_VERSION'
- OR PARAMETER = 'NLS_CHARACTERSET'";
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $stats[$row['parameter']] = $row['value'];
- }
- $db->sql_freeresult($result);
-
- if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8')
- {
- $error[] = $lang['INST_ERR_DB_NO_ORACLE'];
- }
- }
- break;
-
- case 'phpbb\db\driver\postgres':
- if ($unicode_check)
- {
- $sql = "SHOW server_encoding;";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8')
- {
- $error[] = $lang['INST_ERR_DB_NO_POSTGRES'];
- }
- }
- break;
- }
-
- }
-
- if ($error_connect && (!isset($error) || !sizeof($error)))
- {
- return true;
- }
- return false;
-}
-
-/**
-* Removes "/* style" as well as "# style" comments from $input.
-*
-* @param string $input Input string
-*
-* @return string Input string with comments removed
-*/
-function phpbb_remove_comments($input)
-{
- // Remove /* */ comments (http://ostermiller.org/findcomment.html)
- $input = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $input);
-
- // Remove # style comments
- $input = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $input));
-
- return $input;
-}
-
-/**
-* split_sql_file will split an uploaded sql file into single sql statements.
-* Note: expects trim() to have already been run on $sql.
-*/
-function split_sql_file($sql, $delimiter)
-{
- $sql = str_replace("\r" , '', $sql);
- $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql);
-
- $data = array_map('trim', $data);
-
- // The empty case
- $end_data = end($data);
-
- if (empty($end_data))
- {
- unset($data[key($data)]);
- }
-
- return $data;
-}
-
-/**
-* For replacing {L_*} strings with preg_replace_callback
-*/
-function adjust_language_keys_callback($matches)
-{
- if (!empty($matches[1]))
- {
- global $lang, $db;
-
- return (!empty($lang[$matches[1]])) ? $db->sql_escape($lang[$matches[1]]) : $db->sql_escape($matches[1]);
- }
-}
-
-/**
-* Creates the output to be stored in a phpBB config.php file
-*
-* @param array $data Array containing the database connection information
-* @param string $dbms The name of the DBAL class to use
-* @param bool $debug If the debug constants should be enabled by default or not
-* @param bool $debug_container If the container should be compiled on
-* every page load or not
-* @param bool $debug_test If the DEBUG_TEST constant should be added
-* NOTE: Only for use within the testing framework
-*
-* @return string The output to write to the file
-*/
-function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_container = false, $debug_test = false)
-{
- $config_data = "<?php\n";
- $config_data .= "// phpBB 3.1.x auto-generated configuration file\n// Do not change anything in this file!\n";
-
- $config_data_array = array(
- 'dbms' => $dbms,
- 'dbhost' => $data['dbhost'],
- 'dbport' => $data['dbport'],
- 'dbname' => $data['dbname'],
- 'dbuser' => $data['dbuser'],
- 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']),
- 'table_prefix' => $data['table_prefix'],
-
- 'phpbb_adm_relative_path' => 'adm/',
-
- 'acm_type' => 'phpbb\cache\driver\file',
- );
-
- foreach ($config_data_array as $key => $value)
- {
- $config_data .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n";
- }
-
- $config_data .= "\n@define('PHPBB_INSTALLED', true);\n";
- $config_data .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";
-
- if ($debug_test)
- {
- $config_data .= "@define('PHPBB_ENVIRONMENT', 'test');\n";
- }
- else if ($debug)
- {
- $config_data .= "@define('PHPBB_ENVIRONMENT', 'development');\n";
- }
- else
- {
- $config_data .= "@define('PHPBB_ENVIRONMENT', 'production');\n";
- }
-
- if ($debug_container)
- {
- $config_data .= "@define('DEBUG_CONTAINER', true);\n";
- }
- else
- {
- $config_data .= "// @define('DEBUG_CONTAINER', true);\n";
- }
-
- if ($debug_test)
- {
- $config_data .= "@define('DEBUG_TEST', true);\n";
- $config_data .= "@define('DEBUG', true);\n"; // Mandatory for the functional tests, will be removed by PHPBB3-12623
- }
-
- return $config_data;
-}
-
-/**
-* Check whether a file should be ignored on update
-*
-* We ignore new files in some circumstances:
-* 1. The file is a language file, but the language is not installed
-* 2. The file is a style file, but the style is not installed
-* 3. The file is a style language file, but the language is not installed
-*
-* @param string $phpbb_root_path phpBB root path
-* @param string $file File including path from phpbb root
-* @return bool Should we ignore the new file or add it to the board?
-*/
-function phpbb_ignore_new_file_on_update($phpbb_root_path, $file)
-{
- $ignore_new_file = false;
-
- // We ignore new files in some circumstances:
- // 1. The file is a language file, but the language is not installed
- if (!$ignore_new_file && strpos($file, 'language/') === 0)
- {
- list($language_dir, $language_iso) = explode('/', $file);
- $ignore_new_file = !file_exists($phpbb_root_path . $language_dir . '/' . $language_iso);
- }
-
- // 2. The file is a style file, but the style is not installed
- if (!$ignore_new_file && strpos($file, 'styles/') === 0)
- {
- list($styles_dir, $style_name) = explode('/', $file);
- $ignore_new_file = !file_exists($phpbb_root_path . $styles_dir . '/' . $style_name);
- }
-
- // 3. The file is a style language file, but the language is not installed
- if (!$ignore_new_file && strpos($file, 'styles/') === 0)
- {
- $dirs = explode('/', $file);
- if (sizeof($dirs) >= 5)
- {
- list($styles_dir, $style_name, $template_component, $language_iso) = explode('/', $file);
- if ($template_component == 'theme' && $language_iso !== 'images')
- {
- $ignore_new_file = !file_exists($phpbb_root_path . 'language/' . $language_iso);
- }
- }
- }
-
- return $ignore_new_file;
-}
-
-/**
-* Check whether phpBB is installed.
-*
-* @param string $phpbb_root_path Path to the phpBB board root.
-* @param string $php_ext PHP file extension.
-*
-* @return bool Returns true if phpBB is installed.
-*/
-function phpbb_check_installation_exists($phpbb_root_path, $php_ext)
-{
- // Try opening config file
- if (file_exists($phpbb_root_path . 'config.' . $php_ext))
- {
- include($phpbb_root_path . 'config.' . $php_ext);
- }
-
- return defined('PHPBB_INSTALLED');
-}
diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php
index f9e38e8aa0..dfe3fefbd0 100644
--- a/phpBB/includes/functions_mcp.php
+++ b/phpBB/includes/functions_mcp.php
@@ -367,12 +367,12 @@ function phpbb_get_pm_data($pm_ids)
* $mode reports and reports_closed: the $where parameters uses aliases p for posts table and r for report table
* $mode unapproved_posts: the $where parameters uses aliases p for posts table and t for topic table
*/
-function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, &$sort_order_sql, &$total, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE')
+function phpbb_mcp_sorting($mode, &$sort_days_val, &$sort_key_val, &$sort_dir_val, &$sort_by_sql_ary, &$sort_order_sql, &$total_val, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE')
{
global $db, $user, $auth, $template, $request, $phpbb_dispatcher;
- $sort_days = $request->variable('st', 0);
- $min_time = ($sort_days) ? time() - ($sort_days * 86400) : 0;
+ $sort_days_val = $request->variable('st', 0);
+ $min_time = ($sort_days_val) ? time() - ($sort_days_val * 86400) : 0;
switch ($mode)
{
@@ -512,8 +512,8 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
break;
}
- $sort_key = $request->variable('sk', $default_key);
- $sort_dir = $request->variable('sd', $default_dir);
+ $sort_key_val = $request->variable('sk', $default_key);
+ $sort_dir_val = $request->variable('sd', $default_dir);
$sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
switch ($type)
@@ -522,46 +522,46 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
$limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'tt' => $user->lang['TOPIC_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']);
- $sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'tt' => 't.topic_time', 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 't.topic_title', 'v' => 't.topic_views');
+ $sort_by_sql_ary = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'tt' => 't.topic_time', 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 't.topic_title', 'v' => 't.topic_views');
$limit_time_sql = ($min_time) ? "AND t.topic_last_post_time >= $min_time" : '';
break;
case 'posts':
$limit_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject');
$limit_time_sql = ($min_time) ? "AND p.post_time >= $min_time" : '';
break;
case 'reports':
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject');
break;
case 'pm_reports':
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
- $sort_by_sql = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject');
+ $sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject');
break;
case 'logs':
$limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']);
- $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation');
+ $sort_by_sql_ary = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation');
$limit_time_sql = ($min_time) ? "AND l.log_time >= $min_time" : '';
break;
}
// Default total to -1 to allow editing by the event
- $total = -1;
+ $total_val = -1;
- $sort_by_sql_ary = $sort_by_sql;
- $sort_days_val = $sort_days;
- $sort_dir_val = $sort_dir;
- $sort_key_val = $sort_key;
- $total_val = $total;
+ $sort_by_sql = $sort_by_sql_ary;
+ $sort_days = $sort_days_val;
+ $sort_dir = $sort_dir_val;
+ $sort_key = $sort_key_val;
+ $total = $total_val;
/**
* This event allows you to control the SQL query used to get the total number
* of reports the user can access.
@@ -576,20 +576,19 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
* @var string type Which kind of information is this being used for displaying. Posts, topics, etc...
* @var int forum_id The forum id of the posts the user is trying to access, if not 0
* @var int topic_id The topic id of the posts the user is trying to access, if not 0
- * @var int sort_days_val The max age of the oldest report to be shown, in days
- * @var string sort_key_val The way the user has decided to sort the data.
+ * @var int sort_days The max age of the oldest report to be shown, in days
+ * @var string sort_key The way the user has decided to sort the data.
* The valid values must be in the keys of the sort_by_* variables
- * @var string sort_dir_val Either 'd' for "DESC" or 'a' for 'ASC' in the SQL query
+ * @var string sort_dir Either 'd' for "DESC" or 'a' for 'ASC' in the SQL query
* @var int limit_days The possible max ages of the oldest report for the user to choose, in days.
- * @var array sort_by_sql_ary SQL text (values) for the possible names of the ways of sorting data (keys).
+ * @var array sort_by_sql SQL text (values) for the possible names of the ways of sorting data (keys).
* @var array sort_by_text Language text (values) for the possible names of the ways of sorting data (keys).
* @var int min_time Integer with the minimum post time that the user is searching for
* @var int limit_time_sql Time limiting options used in the SQL query.
- * @var int total_val The total number of reports that exist. Only set if you want to override the result
+ * @var int total The total number of reports that exist. Only set if you want to override the result
* @var string where_sql Extra information included in the WHERE clause. It must end with "WHERE" or "AND" or "OR".
* Set to "WHERE" and set total above -1 to override the total value
* @since 3.1.4-RC1
- * @change 3.2.0-a1 Replaced sort_days, sort_key, sort_dir, sort_by_sql, total with replacement variables
*/
$vars = array(
'sql',
@@ -597,47 +596,47 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
'type',
'forum_id',
'topic_id',
- 'sort_days_val',
- 'sort_key_val',
- 'sort_dir_val',
+ 'sort_days',
+ 'sort_key',
+ 'sort_dir',
'limit_days',
- 'sort_by_sql_ary',
+ 'sort_by_sql',
'sort_by_text',
'min_time',
'limit_time_sql',
- 'total_val',
+ 'total',
'where_sql',
);
extract($phpbb_dispatcher->trigger_event('core.mcp_sorting_query_before', compact($vars)));
- $sort_by_sql = $sort_by_sql_ary;
- $sort_days = $sort_days_val;
- $sort_key = $sort_key_val;
- $sort_dir = $sort_dir_val;
- $total = $total_val;
- unset($sort_by_sql_ary);
- unset($sort_days_val);
- unset($sort_key_val);
- unset($sort_dir_val);
- unset($total_val);
+ $sort_by_sql_ary = $sort_by_sql;
+ $sort_days_val = $sort_days;
+ $sort_key_val = $sort_key;
+ $sort_dir_val = $sort_dir;
+ $total_val = $total;
+ unset($sort_by_sql);
+ unset($sort_days);
+ unset($sort_key);
+ unset($sort_dir);
+ unset($total);
- if (!isset($sort_by_sql[$sort_key]))
+ if (!isset($sort_by_sql_ary[$sort_key_val]))
{
- $sort_key = $default_key;
+ $sort_key_val = $default_key;
}
- $direction = ($sort_dir == 'd') ? 'DESC' : 'ASC';
+ $direction = ($sort_dir_val == 'd') ? 'DESC' : 'ASC';
- if (is_array($sort_by_sql[$sort_key]))
+ if (is_array($sort_by_sql_ary[$sort_key_val]))
{
- $sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql[$sort_key]) . ' ' . $direction;
+ $sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql_ary[$sort_key_val]) . ' ' . $direction;
}
else
{
- $sort_order_sql = $sort_by_sql[$sort_key] . ' ' . $direction;
+ $sort_order_sql = $sort_by_sql_ary[$sort_key_val] . ' ' . $direction;
}
$s_limit_days = $s_sort_key = $s_sort_dir = $sort_url = '';
- gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url);
+ gen_sort_selects($limit_days, $sort_by_text, $sort_days_val, $sort_key_val, $sort_dir_val, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url);
$template->assign_vars(array(
'S_SELECT_SORT_DIR' => $s_sort_dir,
@@ -645,15 +644,15 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by
'S_SELECT_SORT_DAYS' => $s_limit_days)
);
- if (($sort_days && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE')
+ if (($sort_days_val && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE')
{
$result = $db->sql_query($sql);
- $total = (int) $db->sql_fetchfield('total');
+ $total_val = (int) $db->sql_fetchfield('total');
$db->sql_freeresult($result);
}
- else if ($total < -1)
+ else if ($total_val < -1)
{
- $total = -1;
+ $total_val = -1;
}
}
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 4f14dc8683..66140a5278 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -1360,12 +1360,12 @@ function delete_post($forum_id, $topic_id, $post_id, &$data, $is_soft = false, $
* Submit Post
* @todo Split up and create lightweight, simple API for this.
*/
-function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
+function submit_post($mode, $subject, $username, $topic_type, &$poll_ary, &$data_ary, $update_message = true, $update_search_index = true)
{
global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $phpbb_log, $request;
- $poll_ary = $poll;
- $data_ary = $data;
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* Modify the data for post submitting
*
@@ -1374,28 +1374,27 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
* @var string subject Variable containing post subject value
* @var string username Variable containing post author name
* @var int topic_type Variable containing topic type value
- * @var array poll_ary Array with the poll data for the post
- * @var array data_ary Array with the data for the post
+ * @var array poll Array with the poll data for the post
+ * @var array data Array with the data for the post
* @var bool update_message Flag indicating if the post will be updated
* @var bool update_search_index Flag indicating if the search index will be updated
* @since 3.1.0-a4
- * @change 3.2.0-a1 Replaced poll and data with poll_ary and data_ary
*/
$vars = array(
'mode',
'subject',
'username',
'topic_type',
- 'poll_ary',
- 'data_ary',
+ 'poll',
+ 'data',
'update_message',
'update_search_index',
);
extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
- $poll = $poll_ary;
- $data = $data_ary;
- unset($poll_ary);
- unset($data_ary);
+ $poll_ary = $poll;
+ $data_ary = $data;
+ unset($poll);
+ unset($data);
// We do not handle erasing posts here
if ($mode == 'delete')
@@ -1403,9 +1402,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
return false;
}
- if (!empty($data['post_time']))
+ if (!empty($data_ary['post_time']))
{
- $current_time = $data['post_time'];
+ $current_time = $data_ary['post_time'];
}
else
{
@@ -1424,31 +1423,31 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
else if ($mode == 'edit')
{
- $post_mode = ($data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit'));
+ $post_mode = ($data_ary['topic_posts_approved'] + $data_ary['topic_posts_unapproved'] + $data_ary['topic_posts_softdeleted'] == 1) ? 'edit_topic' : (($data_ary['topic_first_post_id'] == $data_ary['post_id']) ? 'edit_first_post' : (($data_ary['topic_last_post_id'] == $data_ary['post_id']) ? 'edit_last_post' : 'edit'));
}
// First of all make sure the subject and topic title are having the correct length.
// To achieve this without cutting off between special chars we convert to an array and then count the elements.
$subject = truncate_string($subject, 120);
- $data['topic_title'] = truncate_string($data['topic_title'], 120);
+ $data_ary['topic_title'] = truncate_string($data_ary['topic_title'], 120);
// Collect some basic information about which tables and which rows to update/insert
$sql_data = $topic_row = array();
- $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];
+ $poster_id = ($mode == 'edit') ? $data_ary['poster_id'] : (int) $user->data['user_id'];
// Retrieve some additional information if not present
- if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false))
+ if ($mode == 'edit' && (!isset($data_ary['post_visibility']) || !isset($data_ary['topic_visibility']) || $data_ary['post_visibility'] === false || $data_ary['topic_visibility'] === false))
{
$sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
WHERE t.topic_id = p.topic_id
- AND p.post_id = ' . $data['post_id'];
+ AND p.post_id = ' . $data_ary['post_id'];
$result = $db->sql_query($sql);
$topic_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- $data['topic_visibility'] = $topic_row['topic_visibility'];
- $data['post_visibility'] = $topic_row['post_visibility'];
+ $data_ary['topic_visibility'] = $topic_row['topic_visibility'];
+ $data_ary['post_visibility'] = $topic_row['post_visibility'];
}
// This variable indicates if the user is able to post or put into the queue
@@ -1456,7 +1455,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Check the permissions for post approval.
// Moderators must go through post approval like ordinary users.
- if (!$auth->acl_get('f_noapprove', $data['forum_id']))
+ if (!$auth->acl_get('f_noapprove', $data_ary['forum_id']))
{
// Post not approved, but in queue
$post_visibility = ITEM_UNAPPROVED;
@@ -1472,13 +1471,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// MODs/Extensions are able to force any visibility on posts
- if (isset($data['force_approved_state']))
+ if (isset($data_ary['force_approved_state']))
{
- $post_visibility = (in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_approved_state'] : $post_visibility;
+ $post_visibility = (in_array((int) $data_ary['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_approved_state'] : $post_visibility;
}
- if (isset($data['force_visibility']))
+ if (isset($data_ary['force_visibility']))
{
- $post_visibility = (in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data['force_visibility'] : $post_visibility;
+ $post_visibility = (in_array((int) $data_ary['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE))) ? (int) $data_ary['force_visibility'] : $post_visibility;
}
// Start the transaction here
@@ -1490,25 +1489,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
case 'post':
case 'reply':
$sql_data[POSTS_TABLE]['sql'] = array(
- 'forum_id' => $data['forum_id'],
+ 'forum_id' => $data_ary['forum_id'],
'poster_id' => (int) $user->data['user_id'],
- 'icon_id' => $data['icon_id'],
+ 'icon_id' => $data_ary['icon_id'],
'poster_ip' => $user->ip,
'post_time' => $current_time,
'post_visibility' => $post_visibility,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'post_username' => (!$user->data['is_registered']) ? $username : '',
'post_subject' => $subject,
- 'post_text' => $data['message'],
- 'post_checksum' => $data['message_md5'],
- 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
- 'post_postcount' => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
- 'post_edit_locked' => $data['post_edit_locked']
+ 'post_text' => $data_ary['message'],
+ 'post_checksum' => $data_ary['message_md5'],
+ 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
+ 'post_postcount' => ($auth->acl_get('f_postcount', $data_ary['forum_id'])) ? 1 : 0,
+ 'post_edit_locked' => $data_ary['post_edit_locked']
);
break;
@@ -1525,19 +1524,19 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// If normal edit display edit info
// Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
- if ($data['post_edit_reason'] || (!$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
+ if ($data_ary['post_edit_reason'] || (!$auth->acl_get('m_edit', $data_ary['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')))
{
- $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
+ $data_ary['post_edit_reason'] = truncate_string($data_ary['post_edit_reason'], 255, 255, false);
$sql_data[POSTS_TABLE]['sql'] = array(
'post_edit_time' => $current_time,
- 'post_edit_reason' => $data['post_edit_reason'],
- 'post_edit_user' => (int) $data['post_edit_user'],
+ 'post_edit_reason' => $data_ary['post_edit_reason'],
+ 'post_edit_user' => (int) $data_ary['post_edit_user'],
);
$sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
}
- else if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id']))
+ else if (!$data_ary['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data_ary['forum_id']))
{
$sql_data[POSTS_TABLE]['sql'] = array(
'post_edit_reason' => '',
@@ -1548,14 +1547,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
if ($user->data['user_id'] != $poster_id)
{
- $log_subject = ($subject) ? $subject : $data['topic_title'];
+ $log_subject = ($subject) ? $subject : $data_ary['topic_title'];
$phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_POST_EDITED', false, array(
- 'forum_id' => $data['forum_id'],
- 'topic_id' => $data['topic_id'],
- 'post_id' => $data['post_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'topic_id' => $data_ary['topic_id'],
+ 'post_id' => $data_ary['post_id'],
$log_subject,
(!empty($username)) ? $username : $user->lang['GUEST'],
- $data['post_edit_reason']
+ $data_ary['post_edit_reason']
));
}
@@ -1565,27 +1564,27 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'forum_id' => $data['forum_id'],
- 'poster_id' => $data['poster_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'poster_id' => $data_ary['poster_id'],
+ 'icon_id' => $data_ary['icon_id'],
// We will change the visibility later
//'post_visibility' => $post_visibility,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
- 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '',
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
+ 'post_username' => ($username && $data_ary['poster_id'] == ANONYMOUS) ? $username : '',
'post_subject' => $subject,
- 'post_checksum' => $data['message_md5'],
- 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
- 'post_edit_locked' => $data['post_edit_locked'])
+ 'post_checksum' => $data_ary['message_md5'],
+ 'post_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
+ 'post_edit_locked' => $data_ary['post_edit_locked'])
);
if ($update_message)
{
- $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
+ $sql_data[POSTS_TABLE]['sql']['post_text'] = $data_ary['message'];
}
break;
@@ -1600,8 +1599,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_poster' => (int) $user->data['user_id'],
'topic_time' => $current_time,
'topic_last_view_time' => $current_time,
- 'forum_id' => $data['forum_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'icon_id' => $data_ary['icon_id'],
'topic_posts_approved' => ($post_visibility == ITEM_APPROVED) ? 1 : 0,
'topic_posts_softdeleted' => ($post_visibility == ITEM_DELETED) ? 1 : 0,
'topic_posts_unapproved' => ($post_visibility == ITEM_UNAPPROVED) ? 1 : 0,
@@ -1611,15 +1610,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'topic_first_poster_name' => (!$user->data['is_registered'] && $username) ? $username : (($user->data['user_id'] != ANONYMOUS) ? $user->data['username'] : ''),
'topic_first_poster_colour' => $user->data['user_colour'],
'topic_type' => $topic_type,
- 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
- 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0,
- 'topic_status' => (isset($data['topic_status'])) ? $data['topic_status'] : ITEM_UNLOCKED,
+ 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0,
+ 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'topic_status' => (isset($data_ary['topic_status'])) ? $data_ary['topic_status'] : ITEM_UNLOCKED,
);
- if (isset($poll['poll_options']) && !empty($poll['poll_options']))
+ if (isset($poll_ary['poll_options']) && !empty($poll_ary['poll_options']))
{
- $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time;
- $poll_length = $poll['poll_length'] * 86400;
+ $poll_start = ($poll_ary['poll_start']) ? $poll_ary['poll_start'] : $current_time;
+ $poll_length = $poll_ary['poll_length'] * 86400;
if ($poll_length < 0)
{
$poll_start = $poll_start + $poll_length;
@@ -1631,15 +1630,15 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array(
- 'poll_title' => $poll['poll_title'],
+ 'poll_title' => $poll_ary['poll_title'],
'poll_start' => $poll_start,
- 'poll_max_options' => $poll['poll_max_options'],
+ 'poll_max_options' => $poll_ary['poll_max_options'],
'poll_length' => $poll_length,
- 'poll_vote_change' => $poll['poll_vote_change'])
+ 'poll_vote_change' => $poll_ary['poll_vote_change'])
);
}
- $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
+ $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
if ($post_visibility == ITEM_APPROVED)
{
@@ -1665,9 +1664,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
(($post_visibility == ITEM_APPROVED) ? ', topic_posts_approved = topic_posts_approved + 1' : '') .
(($post_visibility == ITEM_UNAPPROVED) ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') .
(($post_visibility == ITEM_DELETED) ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') .
- ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : '');
+ ((!empty($data_ary['attachment_data']) || (isset($data_ary['topic_attachment']) && $data_ary['topic_attachment'])) ? ', topic_attachment = 1' : '');
- $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
+ $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . (($auth->acl_get('f_postcount', $data_ary['forum_id']) && $post_visibility == ITEM_APPROVED) ? ', user_posts = user_posts + 1' : '');
if ($post_visibility == ITEM_APPROVED)
{
@@ -1685,10 +1684,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
case 'edit_topic':
case 'edit_first_post':
- if (isset($poll['poll_options']))
+ if (isset($poll_ary['poll_options']))
{
- $poll_start = ($poll['poll_start'] || empty($poll['poll_options'])) ? $poll['poll_start'] : $current_time;
- $poll_length = $poll['poll_length'] * 86400;
+ $poll_start = ($poll_ary['poll_start'] || empty($poll_ary['poll_options'])) ? $poll_ary['poll_start'] : $current_time;
+ $poll_length = $poll_ary['poll_length'] * 86400;
if ($poll_length < 0)
{
$poll_start = $poll_start + $poll_length;
@@ -1701,44 +1700,43 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$sql_data[TOPICS_TABLE]['sql'] = array(
- 'forum_id' => $data['forum_id'],
- 'icon_id' => $data['icon_id'],
+ 'forum_id' => $data_ary['forum_id'],
+ 'icon_id' => $data_ary['icon_id'],
'topic_title' => $subject,
'topic_first_poster_name' => $username,
'topic_type' => $topic_type,
- 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0,
- 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '',
- 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0,
- 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1,
- 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0,
- 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0,
+ 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data_ary['topic_time_limit'] * 86400) : 0,
+ 'poll_title' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_title'] : '',
+ 'poll_start' => (isset($poll_ary['poll_options'])) ? $poll_start : 0,
+ 'poll_max_options' => (isset($poll_ary['poll_options'])) ? $poll_ary['poll_max_options'] : 1,
+ 'poll_length' => (isset($poll_ary['poll_options'])) ? $poll_length : 0,
+ 'poll_vote_change' => (isset($poll_ary['poll_vote_change'])) ? $poll_ary['poll_vote_change'] : 0,
'topic_last_view_time' => $current_time,
- 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0),
+ 'topic_attachment' => (!empty($data_ary['attachment_data'])) ? 1 : (isset($data_ary['topic_attachment']) ? $data_ary['topic_attachment'] : 0),
);
break;
}
- $poll_ary = $poll;
- $data_ary = $data;
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* Modify sql query data for post submitting
*
* @event core.submit_post_modify_sql_data
- * @var array data_ary Array with the data for the post
- * @var array poll_ary Array with the poll data for the post
+ * @var array data Array with the data for the post
+ * @var array poll Array with the poll data for the post
* @var string post_mode Variable containing posting mode value
* @var bool sql_data Array with the data for the posting SQL query
* @var string subject Variable containing post subject value
* @var int topic_type Variable containing topic type value
* @var string username Variable containing post author name
* @since 3.1.3-RC1
- * @change 3.2.0-a1 Replace poll and data with poll_ary and data_ary
*/
$vars = array(
- 'data_ary',
- 'poll_ary',
+ 'data',
+ 'poll',
'post_mode',
'sql_data',
'subject',
@@ -1746,10 +1744,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
'username',
);
extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
- $poll = $poll_ary;
- $data = $data_ary;
- unset($poll_ary);
- unset($data_ary);
+ $poll_ary = $poll;
+ $data_ary = $data;
+ unset($poll);
+ unset($data);
// Submit new topic
if ($post_mode == 'post')
@@ -1758,10 +1756,10 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
$db->sql_query($sql);
- $data['topic_id'] = $db->sql_nextid();
+ $data_ary['topic_id'] = $db->sql_nextid();
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'topic_id' => $data['topic_id'])
+ 'topic_id' => $data_ary['topic_id'])
);
unset($sql_data[TOPICS_TABLE]['sql']);
}
@@ -1772,18 +1770,18 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($post_mode == 'reply')
{
$sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array(
- 'topic_id' => $data['topic_id'],
+ 'topic_id' => $data_ary['topic_id'],
));
}
$sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
$db->sql_query($sql);
- $data['post_id'] = $db->sql_nextid();
+ $data_ary['post_id'] = $db->sql_nextid();
if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED)
{
$sql_data[TOPICS_TABLE]['sql'] = array(
- 'topic_last_post_id' => $data['post_id'],
+ 'topic_last_post_id' => $data_ary['post_id'],
'topic_last_post_time' => $current_time,
'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'],
'topic_last_poster_name' => ($user->data['user_id'] == ANONYMOUS) ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'],
@@ -1794,7 +1792,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($post_mode == 'post')
{
- $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id'];
+ $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data_ary['post_id'];
}
// Update total post count and forum information
@@ -1806,7 +1804,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$config->increment('num_posts', 1, false);
- $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
+ $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data_ary['post_id'];
$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
$sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
@@ -1822,7 +1820,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'UPDATE ' . TOPICS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
- WHERE topic_id = ' . $data['topic_id'];
+ WHERE topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
unset($sql_data[TOPICS_TABLE]['sql']);
@@ -1833,14 +1831,14 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'UPDATE ' . POSTS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
- WHERE post_id = ' . $data['post_id'];
+ WHERE post_id = ' . $data_ary['post_id'];
$db->sql_query($sql);
unset($sql_data[POSTS_TABLE]['sql']);
}
// Update Poll Tables
- if (isset($poll['poll_options']))
+ if (isset($poll_ary['poll_options']))
{
$cur_poll_options = array();
@@ -1848,7 +1846,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
{
$sql = 'SELECT *
FROM ' . POLL_OPTIONS_TABLE . '
- WHERE topic_id = ' . $data['topic_id'] . '
+ WHERE topic_id = ' . $data_ary['topic_id'] . '
ORDER BY poll_option_id';
$result = $db->sql_query($sql);
@@ -1862,25 +1860,25 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$sql_insert_ary = array();
- for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++)
+ for ($i = 0, $size = sizeof($poll_ary['poll_options']); $i < $size; $i++)
{
- if (strlen(trim($poll['poll_options'][$i])))
+ if (strlen(trim($poll_ary['poll_options'][$i])))
{
if (empty($cur_poll_options[$i]))
{
// If we add options we need to put them to the end to be able to preserve votes...
$sql_insert_ary[] = array(
'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary),
- 'topic_id' => (int) $data['topic_id'],
- 'poll_option_text' => (string) $poll['poll_options'][$i]
+ 'topic_id' => (int) $data_ary['topic_id'],
+ 'poll_option_text' => (string) $poll_ary['poll_options'][$i]
);
}
- else if ($poll['poll_options'][$i] != $cur_poll_options[$i])
+ else if ($poll_ary['poll_options'][$i] != $cur_poll_options[$i])
{
$sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "
- SET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'
+ SET poll_option_text = '" . $db->sql_escape($poll_ary['poll_options'][$i]) . "'
WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
- AND topic_id = ' . $data['topic_id'];
+ AND topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
}
@@ -1888,29 +1886,29 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
- if (sizeof($poll['poll_options']) < sizeof($cur_poll_options))
+ if (sizeof($poll_ary['poll_options']) < sizeof($cur_poll_options))
{
$sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
- WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
- AND topic_id = ' . $data['topic_id'];
+ WHERE poll_option_id > ' . sizeof($poll_ary['poll_options']) . '
+ AND topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
// If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
- if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options))
+ if ($mode == 'edit' && sizeof($poll_ary['poll_options']) != sizeof($cur_poll_options))
{
- $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
- $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
+ $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data_ary['topic_id']);
+ $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data_ary['topic_id']);
}
}
// Submit Attachments
- if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
+ if (!empty($data_ary['attachment_data']) && $data_ary['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit')))
{
$space_taken = $files_added = 0;
$orphan_rows = array();
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
$orphan_rows[(int) $attach_row['attach_id']] = array();
}
@@ -1932,7 +1930,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$db->sql_freeresult($result);
}
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
{
@@ -1960,8 +1958,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$files_added++;
$attach_sql = array(
- 'post_msg_id' => $data['post_id'],
- 'topic_id' => $data['topic_id'],
+ 'post_msg_id' => $data_ary['post_id'],
+ 'topic_id' => $data_ary['topic_id'],
'is_orphan' => 0,
'poster_id' => $poster_id,
'attach_comment' => $attach_row['attach_comment'],
@@ -1983,32 +1981,32 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
$first_post_has_topic_info = ($post_mode == 'edit_first_post' &&
- (($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1) ||
- ($post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1) ||
- ($post_visibility == ITEM_REAPPROVE && $data['topic_posts_unapproved'] == 1) ||
- ($post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1)));
+ (($post_visibility == ITEM_DELETED && $data_ary['topic_posts_softdeleted'] == 1) ||
+ ($post_visibility == ITEM_UNAPPROVED && $data_ary['topic_posts_unapproved'] == 1) ||
+ ($post_visibility == ITEM_REAPPROVE && $data_ary['topic_posts_unapproved'] == 1) ||
+ ($post_visibility == ITEM_APPROVED && $data_ary['topic_posts_approved'] == 1)));
// Fix the post's and topic's visibility and first/last post information, when the post is edited
- if (($post_mode != 'post' && $post_mode != 'reply') && $data['post_visibility'] != $post_visibility)
+ if (($post_mode != 'post' && $post_mode != 'reply') && $data_ary['post_visibility'] != $post_visibility)
{
// If the post was not approved, it could also be the starter,
// so we sync the starter after approving/restoring, to ensure that the stats are correct
// Same applies for the last post
- $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
- $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED);
+ $is_starter = ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
+ $is_latest = ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data_ary['post_visibility'] != ITEM_APPROVED);
/* @var $phpbb_content_visibility \phpbb\content_visibility */
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
- $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
+ $phpbb_content_visibility->set_post_visibility($post_visibility, $data_ary['post_id'], $data_ary['topic_id'], $data_ary['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
}
else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info)
{
- if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility)
+ if ($post_visibility == ITEM_APPROVED || $data_ary['topic_visibility'] == $post_visibility)
{
// only the subject can be changed from edit
$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
// Maybe not only the subject, but also changing anonymous usernames. ;)
- if ($data['poster_id'] == ANONYMOUS)
+ if ($data_ary['poster_id'] == ANONYMOUS)
{
$sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
}
@@ -2019,13 +2017,13 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// it just means that we might have to
$sql = 'SELECT forum_last_post_id, forum_last_post_subject
FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . (int) $data['forum_id'];
+ WHERE forum_id = ' . (int) $data_ary['forum_id'];
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
// this post is the latest post in the forum, better update
- if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS))
+ if ($row['forum_last_post_id'] == $data_ary['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data_ary['poster_id'] == ANONYMOUS))
{
// the post's subject changed
if ($row['forum_last_post_subject'] !== $subject)
@@ -2034,7 +2032,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Update the user name if poster is anonymous... just in case a moderator changed it
- if ($data['poster_id'] == ANONYMOUS)
+ if ($data_ary['poster_id'] == ANONYMOUS)
{
$sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
}
@@ -2045,9 +2043,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Update forum stats
$where_sql = array(
- POSTS_TABLE => 'post_id = ' . $data['post_id'],
- TOPICS_TABLE => 'topic_id = ' . $data['topic_id'],
- FORUMS_TABLE => 'forum_id = ' . $data['forum_id'],
+ POSTS_TABLE => 'post_id = ' . $data_ary['post_id'],
+ TOPICS_TABLE => 'topic_id = ' . $data_ary['topic_id'],
+ FORUMS_TABLE => 'forum_id = ' . $data_ary['forum_id'],
USERS_TABLE => 'user_id = ' . $poster_id
);
@@ -2064,7 +2062,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($topic_type == POST_GLOBAL)
{
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
- WHERE topic_moved_id = ' . $data['topic_id'];
+ WHERE topic_moved_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
@@ -2082,7 +2080,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
}
// Index message contents
- if ($update_search_index && $data['enable_indexing'])
+ if ($update_search_index && $data_ary['enable_indexing'])
{
// Select the search method and do some additional checks to ensure it can actually be utilised
$search_type = $config['search_type'];
@@ -2100,23 +2098,23 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
trigger_error($error);
}
- $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
+ $search->index($mode, $data_ary['post_id'], $data_ary['message'], $subject, $poster_id, $data_ary['forum_id']);
}
// Topic Notification, do not change if moderator is changing other users posts...
if ($user->data['user_id'] == $poster_id)
{
- if (!$data['notify_set'] && $data['notify'])
+ if (!$data_ary['notify_set'] && $data_ary['notify'])
{
$sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
- VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
+ VALUES (' . $user->data['user_id'] . ', ' . $data_ary['topic_id'] . ')';
$db->sql_query($sql);
}
- else if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify'])
+ else if (($config['email_enable'] || $config['jab_enable']) && $data_ary['notify_set'] && !$data_ary['notify'])
{
$sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
- AND topic_id = ' . $data['topic_id'];
+ AND topic_id = ' . $data_ary['topic_id'];
$db->sql_query($sql);
}
}
@@ -2124,12 +2122,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
{
// Mark this topic as posted to
- markread('post', $data['forum_id'], $data['topic_id']);
+ markread('post', $data_ary['forum_id'], $data_ary['topic_id']);
}
// Mark this topic as read
// We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
- markread('topic', $data['forum_id'], $data['topic_id'], time());
+ markread('topic', $data_ary['forum_id'], $data_ary['topic_id'], time());
//
if ($config['load_db_lastread'] && $user->data['is_registered'])
@@ -2137,7 +2135,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$sql = 'SELECT mark_time
FROM ' . FORUMS_TRACK_TABLE . '
WHERE user_id = ' . $user->data['user_id'] . '
- AND forum_id = ' . $data['forum_id'];
+ AND forum_id = ' . $data_ary['forum_id'];
$result = $db->sql_query($sql);
$f_mark_time = (int) $db->sql_fetchfield('mark_time');
$db->sql_freeresult($result);
@@ -2152,12 +2150,12 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// Update forum info
$sql = 'SELECT forum_last_post_time
FROM ' . FORUMS_TABLE . '
- WHERE forum_id = ' . $data['forum_id'];
+ WHERE forum_id = ' . $data_ary['forum_id'];
$result = $db->sql_query($sql);
$forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
$db->sql_freeresult($result);
- update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
+ update_forum_tracking_info($data_ary['forum_id'], $forum_last_post_time, $f_mark_time, false);
}
// If a username was supplied or the poster is a guest, we will use the supplied username.
@@ -2166,11 +2164,11 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
$username = ($username !== '' || !$user->data['is_registered']) ? $username : $user->data['username'];
// Send Notifications
- $notification_data = array_merge($data, array(
- 'topic_title' => (isset($data['topic_title'])) ? $data['topic_title'] : $subject,
+ $notification_data = array_merge($data_ary, array(
+ 'topic_title' => (isset($data_ary['topic_title'])) ? $data_ary['topic_title'] : $subject,
'post_username' => $username,
'poster_id' => $poster_id,
- 'post_text' => $data['message'],
+ 'post_text' => $data_ary['message'],
'post_time' => $current_time,
'post_subject' => $subject,
));
@@ -2281,24 +2279,24 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($post_visibility == ITEM_APPROVED)
{
- $params .= '&amp;t=' . $data['topic_id'];
+ $params .= '&amp;t=' . $data_ary['topic_id'];
if ($mode != 'post')
{
- $params .= '&amp;p=' . $data['post_id'];
- $add_anchor = '#p' . $data['post_id'];
+ $params .= '&amp;p=' . $data_ary['post_id'];
+ $add_anchor = '#p' . $data_ary['post_id'];
}
}
else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic')
{
- $params .= '&amp;t=' . $data['topic_id'];
+ $params .= '&amp;t=' . $data_ary['topic_id'];
}
$url = (!$params) ? "{$phpbb_root_path}viewforum.$phpEx" : "{$phpbb_root_path}viewtopic.$phpEx";
- $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
+ $url = append_sid($url, 'f=' . $data_ary['forum_id'] . $params) . $add_anchor;
- $poll_ary = $poll;
- $data_ary = $data;
+ $poll = $poll_ary;
+ $data = $data_ary;
/**
* This event is used for performing actions directly after a post or topic
* has been submitted. When a new topic is posted, the topic ID is
@@ -2312,8 +2310,8 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
* @var string subject Variable containing post subject value
* @var string username Variable containing post author name
* @var int topic_type Variable containing topic type value
- * @var array poll_ary Array with the poll data for the post
- * @var array data_ary Array with the data for the post
+ * @var array poll Array with the poll data for the post
+ * @var array data Array with the data for the post
* @var int post_visibility Variable containing up to date post visibility
* @var bool update_message Flag indicating if the post will be updated
* @var bool update_search_index Flag indicating if the search index will be updated
@@ -2322,25 +2320,24 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
* @since 3.1.0-a3
* @change 3.1.0-RC3 Added vars mode, subject, username, topic_type,
* poll, update_message, update_search_index
- * @change 3.2.0-a1 Replaced data and poll with data_ary and poll_ary
*/
$vars = array(
'mode',
'subject',
'username',
'topic_type',
- 'poll_ary',
- 'data_ary',
+ 'poll',
+ 'data',
'post_visibility',
'update_message',
'update_search_index',
'url',
);
extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
- $data = $data_ary;
- $poll = $poll_ary;
- unset($data_ary);
- unset($poll_ary);
+ $data_ary = $data;
+ $poll_ary = $poll;
+ unset($data);
+ unset($poll);
return $url;
}
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index b2928d5df8..f5cbb093d6 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -1596,7 +1596,7 @@ function get_folder_status($folder_id, $folder)
'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? floor(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0,
);
- $return['message'] = $user->lang('FOLDER_STATUS_MSG', $user->lang('MESSAGES_COUNT', (int) $return['max']), $return['cur'], $return['percent']);
+ $return['message'] = $user->lang('FOLDER_STATUS_MSG', $user->lang('MESSAGES_COUNT', (int) $return['max']), (int) $return['cur'], $return['percent']);
return $return;
}
@@ -1608,7 +1608,7 @@ function get_folder_status($folder_id, $folder)
/**
* Submit PM
*/
-function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
+function submit_pm($mode, $subject, &$data_ary, $put_in_outbox = true)
{
global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher, $request;
@@ -1620,21 +1620,20 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$current_time = time();
- $data_ary = $data;
+ $data = $data_ary;
/**
* Get all parts of the PM that are to be submited to the DB.
*
* @event core.submit_pm_before
* @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit
* @var string subject Subject of the private message
- * @var array data_ary The whole row data of the PM.
+ * @var array data The whole row data of the PM.
* @since 3.1.0-b3
- * @change 3.2.0-a1 Replaced data with data_ary
*/
- $vars = array('mode', 'subject', 'data_ary');
+ $vars = array('mode', 'subject', 'data');
extract($phpbb_dispatcher->trigger_event('core.submit_pm_before', compact($vars)));
- $data = $data_ary;
- unset($data_ary);
+ $data_ary = $data;
+ unset($data);
// Collect some basic information about which tables and which rows to update/insert
$sql_data = array();
@@ -1650,9 +1649,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$_types = array('u', 'g');
foreach ($_types as $ug_type)
{
- if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
+ if (isset($data_ary['address_list'][$ug_type]) && sizeof($data_ary['address_list'][$ug_type]))
{
- foreach ($data['address_list'][$ug_type] as $id => $field)
+ foreach ($data_ary['address_list'][$ug_type] as $id => $field)
{
$id = (int) $id;
@@ -1672,7 +1671,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
}
}
- if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
+ if (isset($data_ary['address_list']['g']) && sizeof($data_ary['address_list']['g']))
{
// We need to check the PM status of group members (do they want to receive PM's?)
// Only check if not a moderator or admin, since they are allowed to override this user setting
@@ -1680,7 +1679,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$sql = 'SELECT u.user_type, ug.group_id, ug.user_id
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
- WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
+ WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data_ary['address_list']['g'])) . '
AND ug.user_pending = 0
AND u.user_id = ug.user_id
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' .
@@ -1689,7 +1688,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
while ($row = $db->sql_fetchrow($result))
{
- $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
+ $field = ($data_ary['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
$recipients[$row['user_id']] = $field;
}
$db->sql_freeresult($result);
@@ -1712,13 +1711,13 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
case 'reply':
case 'quote':
- $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
+ $root_level = ($data_ary['reply_from_root_level']) ? $data_ary['reply_from_root_level'] : $data_ary['reply_from_msg_id'];
// Set message_replied switch for this user
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
SET pm_replied = 1
- WHERE user_id = ' . $data['from_user_id'] . '
- AND msg_id = ' . $data['reply_from_msg_id'];
+ WHERE user_id = ' . $data_ary['from_user_id'] . '
+ AND msg_id = ' . $data_ary['reply_from_msg_id'];
// no break
@@ -1727,19 +1726,19 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
case 'quotepost':
$sql_data = array(
'root_level' => $root_level,
- 'author_id' => $data['from_user_id'],
- 'icon_id' => $data['icon_id'],
- 'author_ip' => $data['from_user_ip'],
+ 'author_id' => $data_ary['from_user_id'],
+ 'icon_id' => $data_ary['icon_id'],
+ 'author_ip' => $data_ary['from_user_ip'],
'message_time' => $current_time,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'message_subject' => $subject,
- 'message_text' => $data['message'],
- 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid'],
+ 'message_text' => $data_ary['message'],
+ 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid'],
'to_address' => implode(':', $to),
'bcc_address' => implode(':', $bcc),
'message_reported' => 0,
@@ -1748,17 +1747,17 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
case 'edit':
$sql_data = array(
- 'icon_id' => $data['icon_id'],
+ 'icon_id' => $data_ary['icon_id'],
'message_edit_time' => $current_time,
- 'enable_bbcode' => $data['enable_bbcode'],
- 'enable_smilies' => $data['enable_smilies'],
- 'enable_magic_url' => $data['enable_urls'],
- 'enable_sig' => $data['enable_sig'],
+ 'enable_bbcode' => $data_ary['enable_bbcode'],
+ 'enable_smilies' => $data_ary['enable_smilies'],
+ 'enable_magic_url' => $data_ary['enable_urls'],
+ 'enable_sig' => $data_ary['enable_sig'],
'message_subject' => $subject,
- 'message_text' => $data['message'],
- 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
- 'bbcode_bitfield' => $data['bbcode_bitfield'],
- 'bbcode_uid' => $data['bbcode_uid']
+ 'message_text' => $data_ary['message'],
+ 'message_attachment'=> (!empty($data_ary['attachment_data'])) ? 1 : 0,
+ 'bbcode_bitfield' => $data_ary['bbcode_bitfield'],
+ 'bbcode_uid' => $data_ary['bbcode_uid']
);
break;
}
@@ -1770,13 +1769,13 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
{
$db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
- $data['msg_id'] = $db->sql_nextid();
+ $data_ary['msg_id'] = $db->sql_nextid();
}
else if ($mode == 'edit')
{
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
- WHERE msg_id = ' . $data['msg_id'];
+ WHERE msg_id = ' . $data_ary['msg_id'];
$db->sql_query($sql);
}
}
@@ -1793,9 +1792,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
foreach ($recipients as $user_id => $type)
{
$sql_ary[] = array(
- 'msg_id' => (int) $data['msg_id'],
+ 'msg_id' => (int) $data_ary['msg_id'],
'user_id' => (int) $user_id,
- 'author_id' => (int) $data['from_user_id'],
+ 'author_id' => (int) $data_ary['from_user_id'],
'folder_id' => PRIVMSGS_NO_BOX,
'pm_new' => 1,
'pm_unread' => 1,
@@ -1814,9 +1813,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
if ($put_in_outbox)
{
$db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'msg_id' => (int) $data['msg_id'],
- 'user_id' => (int) $data['from_user_id'],
- 'author_id' => (int) $data['from_user_id'],
+ 'msg_id' => (int) $data_ary['msg_id'],
+ 'user_id' => (int) $data_ary['from_user_id'],
+ 'author_id' => (int) $data_ary['from_user_id'],
'folder_id' => PRIVMSGS_OUTBOX,
'pm_new' => 0,
'pm_unread' => 0,
@@ -1830,17 +1829,17 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_lastpost_time = $current_time
- WHERE user_id = " . $data['from_user_id'];
+ WHERE user_id = " . $data_ary['from_user_id'];
$db->sql_query($sql);
}
// Submit Attachments
- if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
+ if (!empty($data_ary['attachment_data']) && $data_ary['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
{
$space_taken = $files_added = 0;
$orphan_rows = array();
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
$orphan_rows[(int) $attach_row['attach_id']] = array();
}
@@ -1863,7 +1862,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$db->sql_freeresult($result);
}
- foreach ($data['attachment_data'] as $pos => $attach_row)
+ foreach ($data_ary['attachment_data'] as $pos => $attach_row)
{
if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
{
@@ -1891,10 +1890,10 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$files_added++;
$attach_sql = array(
- 'post_msg_id' => $data['msg_id'],
+ 'post_msg_id' => $data_ary['msg_id'],
'topic_id' => 0,
'is_orphan' => 0,
- 'poster_id' => $data['from_user_id'],
+ 'poster_id' => $data_ary['from_user_id'],
'attach_comment' => $attach_row['attach_comment'],
);
@@ -1919,14 +1918,14 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
$sql = 'DELETE FROM ' . DRAFTS_TABLE . "
WHERE draft_id = $draft_id
- AND user_id = " . $data['from_user_id'];
+ AND user_id = " . $data_ary['from_user_id'];
$db->sql_query($sql);
}
$db->sql_transaction('commit');
// Send Notifications
- $pm_data = array_merge($data, array(
+ $pm_data = array_merge($data_ary, array(
'message_subject' => $subject,
'recipients' => $recipients,
));
@@ -1943,24 +1942,23 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
$phpbb_notifications->add_notifications('notification.type.pm', $pm_data);
}
- $data_ary = $data;
+ $data = $data_ary;
/**
* Get PM message ID after submission to DB
*
* @event core.submit_pm_after
* @var string mode PM Post mode - post|reply|quote|quotepost|forward|edit
* @var string subject Subject of the private message
- * @var array data_ary The whole row data of the PM.
+ * @var array data The whole row data of the PM.
* @var array pm_data The data sent to notification class
* @since 3.1.0-b5
- * @change 3.2.0-a1 Replaced data with data_ary
*/
- $vars = array('mode', 'subject', 'data_ary', 'pm_data');
+ $vars = array('mode', 'subject', 'data', 'pm_data');
extract($phpbb_dispatcher->trigger_event('core.submit_pm_after', compact($vars)));
- $data = $data_ary;
- unset($data_ary);
+ $data_ary = $data;
+ unset($data);
- return $data['msg_id'];
+ return $data_ary['msg_id'];
}
/**
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index 8237b834d6..90a3db0949 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -203,9 +203,9 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
$topic_list = $topic_tracking_info = array();
- while ($row = $db->sql_fetchrow($result))
+ while ($row_ary = $db->sql_fetchrow($result))
{
- $topic_list[] = $row['topic_id'];
+ $topic_list[] = $row_ary['topic_id'];
}
$db->sql_freeresult($result);
@@ -214,9 +214,9 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
WHERE " . $db->sql_in_set('t.topic_id', $topic_list, false, true);
$result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
+ while ($row_ary = $db->sql_fetchrow($result))
{
- $topic_rows[$row['topic_id']] = $row;
+ $topic_rows[$row_ary['topic_id']] = $row_ary;
}
$db->sql_freeresult($result);
@@ -243,111 +243,110 @@ function mcp_forum_view($id, $mode, $action, $forum_info)
{
$topic_title = '';
- $row = &$topic_rows[$topic_id];
+ $row_ary = &$topic_rows[$topic_id];
- $replies = $phpbb_content_visibility->get_count('topic_posts', $row, $forum_id) - 1;
+ $replies = $phpbb_content_visibility->get_count('topic_posts', $row_ary, $forum_id) - 1;
- if ($row['topic_status'] == ITEM_MOVED)
+ if ($row_ary['topic_status'] == ITEM_MOVED)
{
$unread_topic = false;
}
else
{
- $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
+ $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row_ary['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false;
}
// Get folder img, topic status/type related information
$folder_img = $folder_alt = $topic_type = '';
- topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
+ topic_status($row_ary, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type);
- $topic_title = censor_text($row['topic_title']);
+ $topic_title = censor_text($row_ary['topic_title']);
- $topic_unapproved = (($row['topic_visibility'] == ITEM_UNAPPROVED || $row['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
- $posts_unapproved = ($row['topic_visibility'] == ITEM_APPROVED && $row['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false;
- $topic_deleted = $row['topic_visibility'] == ITEM_DELETED;
- $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;t=' . $row['topic_id'] : '';
+ $topic_unapproved = (($row_ary['topic_visibility'] == ITEM_UNAPPROVED || $row_ary['topic_visibility'] == ITEM_REAPPROVE) && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false;
+ $posts_unapproved = ($row_ary['topic_visibility'] == ITEM_APPROVED && $row_ary['topic_posts_unapproved'] && $auth->acl_get('m_approve', $row_ary['forum_id'])) ? true : false;
+ $topic_deleted = $row_ary['topic_visibility'] == ITEM_DELETED;
+ $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&amp;i=queue&amp;mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&amp;t=' . $row_ary['topic_id'] : '';
$u_mcp_queue = (!$u_mcp_queue && $topic_deleted) ? $url . '&amp;i=queue&amp;mode=deleted_topics&amp;t=' . $topic_id : $u_mcp_queue;
$topic_row = array(
- 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
+ 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row_ary['forum_id']) && $row_ary['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '',
'TOPIC_IMG_STYLE' => $folder_img,
'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt),
- 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '',
- 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '',
- 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '',
+ 'TOPIC_ICON_IMG' => (!empty($icons[$row_ary['icon_id']])) ? $icons[$row_ary['icon_id']]['img'] : '',
+ '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') : '',
- 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
- 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']),
+ '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']),
+ 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
+ 'U_TOPIC_AUTHOR' => get_username_string('profile', $row_ary['topic_poster'], $row_ary['topic_first_poster_name'], $row_ary['topic_first_poster_colour']),
- 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
- 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR' => get_username_string('username', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
+ 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row_ary['topic_last_poster_id'], $row_ary['topic_last_poster_name'], $row_ary['topic_last_poster_colour']),
'TOPIC_TYPE' => $topic_type,
'TOPIC_TITLE' => $topic_title,
- 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row, $row['forum_id']) - 1,
- 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']),
- 'FIRST_POST_TIME' => $user->format_date($row['topic_time']),
- 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'],
- 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']),
+ 'REPLIES' => $phpbb_content_visibility->get_count('topic_posts', $row_ary, $row_ary['forum_id']) - 1,
+ 'LAST_POST_TIME' => $user->format_date($row_ary['topic_last_post_time']),
+ 'FIRST_POST_TIME' => $user->format_date($row_ary['topic_time']),
+ 'LAST_POST_SUBJECT' => $row_ary['topic_last_post_subject'],
+ 'LAST_VIEW_TIME' => $user->format_date($row_ary['topic_last_view_time']),
- 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false,
+ 'S_TOPIC_REPORTED' => (!empty($row_ary['topic_reported']) && empty($row_ary['topic_moved_id']) && $auth->acl_get('m_report', $row_ary['forum_id'])) ? true : false,
'S_TOPIC_UNAPPROVED' => $topic_unapproved,
'S_POSTS_UNAPPROVED' => $posts_unapproved,
'S_TOPIC_DELETED' => $topic_deleted,
'S_UNREAD_TOPIC' => $unread_topic,
);
- if ($row['topic_status'] == ITEM_MOVED)
+ if ($row_ary['topic_status'] == ITEM_MOVED)
{
$topic_row = array_merge($topic_row, array(
- 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row['topic_moved_id']}"),
- 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;topic_id_list[]={$row['topic_id']}&amp;mode=forum_view&amp;action=delete_topic") : '',
+ 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}viewtopic.$phpEx", "t={$row_ary['topic_moved_id']}"),
+ 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;topic_id_list[]={$row_ary['topic_id']}&amp;mode=forum_view&amp;action=delete_topic") : '',
'S_MOVED_TOPIC' => true,
- 'TOPIC_ID' => $row['topic_moved_id'],
+ 'TOPIC_ID' => $row_ary['topic_moved_id'],
));
}
else
{
if ($action == 'merge_topic' || $action == 'merge_topics')
{
- $u_select_topic = $url . "&amp;i=$id&amp;mode=forum_view&amp;action=$action&amp;to_topic_id=" . $row['topic_id'] . $selected_ids;
+ $u_select_topic = $url . "&amp;i=$id&amp;mode=forum_view&amp;action=$action&amp;to_topic_id=" . $row_ary['topic_id'] . $selected_ids;
}
else
{
- $u_select_topic = $url . "&amp;i=$id&amp;mode=topic_view&amp;action=merge&amp;to_topic_id=" . $row['topic_id'] . $selected_ids;
+ $u_select_topic = $url . "&amp;i=$id&amp;mode=topic_view&amp;action=merge&amp;to_topic_id=" . $row_ary['topic_id'] . $selected_ids;
}
$topic_row = array_merge($topic_row, array(
- 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;t={$row['topic_id']}&amp;mode=topic_view"),
+ 'U_VIEW_TOPIC' => append_sid("{$phpbb_root_path}mcp.$phpEx", "i=$id&amp;f=$forum_id&amp;t={$row_ary['topic_id']}&amp;mode=topic_view"),
- 'S_SELECT_TOPIC' => ($merge_select && !in_array($row['topic_id'], $source_topic_ids)) ? true : false,
+ 'S_SELECT_TOPIC' => ($merge_select && !in_array($row_ary['topic_id'], $source_topic_ids)) ? true : false,
'U_SELECT_TOPIC' => $u_select_topic,
'U_MCP_QUEUE' => $u_mcp_queue,
- 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;t=' . $row['topic_id'] . '&amp;action=reports') : '',
- 'TOPIC_ID' => $row['topic_id'],
- 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? true : false,
+ 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=main&amp;mode=topic_view&amp;t=' . $row_ary['topic_id'] . '&amp;action=reports') : '',
+ 'TOPIC_ID' => $row_ary['topic_id'],
+ 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row_ary['topic_id'], $topic_id_list)) ? true : false,
));
}
- $row_ary = $row;
+ $row = $row_ary;
/**
* Modify the topic data before it is assigned to the template in MCP
*
* @event core.mcp_view_forum_modify_topicrow
- * @var array row_ary Array with topic data
+ * @var array row Array with topic data
* @var array topic_row Template array with topic data
* @since 3.1.0-a1
- * @change 3.2.0-a1 Replace row with row_ary
*/
- $vars = array('row_ary', 'topic_row');
+ $vars = array('row', 'topic_row');
extract($phpbb_dispatcher->trigger_event('core.mcp_view_forum_modify_topicrow', compact($vars)));
- $row = $row_ary;
- unset($row_ary);
+ $row_ary = $row;
+ unset($row);
$template->assign_block_vars('topicrow', $topic_row);
}
diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php
index e59f0abb04..33aebccb22 100644
--- a/phpBB/includes/mcp/mcp_post.php
+++ b/phpBB/includes/mcp/mcp_post.php
@@ -549,16 +549,6 @@ function change_poster(&$post_info, $userdata)
$from_username = $post_info['username'];
$to_username = $userdata['username'];
- // Renew post info
- $post_info = phpbb_get_post_data(array($post_id), false, true);
-
- if (!sizeof($post_info))
- {
- trigger_error('POST_NOT_EXIST');
- }
-
- $post_info = $post_info[$post_id];
-
/**
* This event allows you to perform additional tasks after changing a post's poster
*
@@ -566,10 +556,21 @@ function change_poster(&$post_info, $userdata)
* @var array userdata Information on a post's new poster
* @var array post_info Information on the affected post
* @since 3.1.6-RC1
+ * @changed 3.1.7-RC1 Change location to prevent post_info from being set to the new post information
*/
$vars = array('userdata', 'post_info');
extract($phpbb_dispatcher->trigger_event('core.mcp_change_poster_after', compact($vars)));
+ // Renew post info
+ $post_info = phpbb_get_post_data(array($post_id), false, true);
+
+ if (!sizeof($post_info))
+ {
+ trigger_error('POST_NOT_EXIST');
+ }
+
+ $post_info = $post_info[$post_id];
+
// Now add log entry
$phpbb_log->add('mod', $user->data['user_id'], $user->ip, 'LOG_MCP_CHANGE_POSTER', false, array(
'forum_id' => $post_info['forum_id'],
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index cb4b590196..9fdd16e791 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -72,6 +72,7 @@ class mcp_queue
case 'delete':
$post_id_list = $request->variable('post_id_list', array(0));
$topic_id_list = $request->variable('topic_id_list', array(0));
+ $delete_reason = $request->variable('delete_reason', '', true);
if (!empty($post_id_list))
{
@@ -80,7 +81,7 @@ class mcp_queue
global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx);
}
- mcp_delete_post($post_id_list, false, '', $action);
+ mcp_delete_post($post_id_list, false, $delete_reason, $action);
}
else if (!empty($topic_id_list))
{
@@ -89,7 +90,7 @@ class mcp_queue
global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/mcp/mcp_main.' . $phpEx);
}
- mcp_delete_topic($topic_id_list, false, '', $action);
+ mcp_delete_topic($topic_id_list, false, $delete_reason, $action);
}
else
{
diff --git a/phpBB/index.php b/phpBB/index.php
index 73a5989bcb..9939b9ba7f 100644
--- a/phpBB/index.php
+++ b/phpBB/index.php
@@ -123,7 +123,7 @@ $db->sql_freeresult($result);
$legend = implode($user->lang['COMMA_SEPARATOR'], $legend);
// Generate birthday list if required ...
-$birthday_list = array();
+$birthdays = $birthday_list = array();
if ($config['load_birthdays'] && $config['allow_birthdays'] && $auth->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel'))
{
$time = $user->create_datetime();
@@ -136,33 +136,66 @@ if ($config['load_birthdays'] && $config['allow_birthdays'] && $auth->acl_gets('
$leap_year_birthdays = " OR u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', 29, 2)) . "%'";
}
- $sql = 'SELECT u.user_id, u.username, u.user_colour, u.user_birthday
- FROM ' . USERS_TABLE . ' u
- LEFT JOIN ' . BANLIST_TABLE . " b ON (u.user_id = b.ban_userid)
- WHERE (b.ban_id IS NULL
- OR b.ban_exclude = 1)
+ $sql_ary = array(
+ 'SELECT' => 'u.user_id, u.username, u.user_colour, u.user_birthday',
+ 'FROM' => array(
+ USERS_TABLE => 'u',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(BANLIST_TABLE => 'b'),
+ 'ON' => 'u.user_id = b.ban_userid',
+ ),
+ ),
+ 'WHERE' => "(b.ban_id IS NULL OR b.ban_exclude = 1)
AND (u.user_birthday LIKE '" . $db->sql_escape(sprintf('%2d-%2d-', $now['mday'], $now['mon'])) . "%' $leap_year_birthdays)
- AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
+ AND u.user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')',
+ );
+
+ /**
+ * Event to modify the SQL query to get birthdays data
+ *
+ * @event core.index_modify_birthdays_sql
+ * @var array now The assoc array with the 'now' local timestamp data
+ * @var array sql_ary The SQL array to get the birthdays data
+ * @var object time The user related Datetime object
+ * @since 3.1.7-RC1
+ */
+ $vars = array('now', 'sql_ary', 'time');
+ extract($phpbb_dispatcher->trigger_event('core.index_modify_birthdays_sql', compact($vars)));
+
+ $sql = $db->sql_build_query('SELECT', $sql_ary);
$result = $db->sql_query($sql);
+ $rows = $db->sql_fetchrowset($result);
+ $db->sql_freeresult($result);
- while ($row = $db->sql_fetchrow($result))
+ foreach ($rows as $row)
{
$birthday_username = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']);
$birthday_year = (int) substr($row['user_birthday'], -4);
$birthday_age = ($birthday_year) ? max(0, $now['year'] - $birthday_year) : '';
- $template->assign_block_vars('birthdays', array(
+ $birthdays[] = array(
'USERNAME' => $birthday_username,
'AGE' => $birthday_age,
- ));
+ );
// For 3.0 compatibility
- if ($age = (int) substr($row['user_birthday'], -4))
- {
- $birthday_list[] = $birthday_username . (($birthday_year) ? ' (' . $birthday_age . ')' : '');
- }
+ $birthday_list[] = $birthday_username . (($birthday_age) ? " ({$birthday_age})" : '');
}
- $db->sql_freeresult($result);
+
+ /**
+ * Event to modify the birthdays list
+ *
+ * @event core.index_modify_birthdays_list
+ * @var array birthdays Array with the users birhtdays data
+ * @var array rows Array with the birhtdays SQL query result
+ * @since 3.1.7-RC1
+ */
+ $vars = array('birthdays', 'rows');
+ extract($phpbb_dispatcher->trigger_event('core.index_modify_birthdays_list', compact($vars)));
+
+ $template->assign_block_vars_array('birthdays', $birthdays);
}
// Assign index specific vars
diff --git a/phpBB/install_new/app.php b/phpBB/install/app.php
index b2de72dcbc..9664f92cf1 100644
--- a/phpBB/install_new/app.php
+++ b/phpBB/install/app.php
@@ -20,8 +20,8 @@ define('PHPBB_ENVIRONMENT', 'production');
$phpbb_root_path = '../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
-$startup_new_path = $phpbb_root_path . 'install/update/update/new/install_new/startup.' . $phpEx;
-$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install_new/startup.' . $phpEx;
+$startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx;
+$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install/startup.' . $phpEx;
require($startup_path);
/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
@@ -30,7 +30,6 @@ $phpbb_filesystem = $phpbb_installer_container->get('filesystem');
/** @var \phpbb\template\template $template */
$template = $phpbb_installer_container->get('template');
-
// Path to templates
$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
$paths = array_filter($paths, 'is_dir');
@@ -42,17 +41,17 @@ $template->set_custom_style(array(
),
), $paths);
-/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
+/** @var $phpbb_dispatcher \phpbb\event\dispatcher */
$phpbb_dispatcher = $phpbb_installer_container->get('dispatcher');
/** @var \phpbb\language\language $language */
$language = $phpbb_installer_container->get('language');
-$language->add_lang(array('common', 'acp/common', 'acp/board', 'install_new', 'posting'));
+$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
-/* @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */
+/** @var $http_kernel \Symfony\Component\HttpKernel\HttpKernel */
$http_kernel = $phpbb_installer_container->get('http_kernel');
-/* @var $symfony_request \phpbb\symfony_request */
+/** @var $symfony_request \phpbb\symfony_request */
$symfony_request = $phpbb_installer_container->get('symfony_request');
$response = $http_kernel->handle($symfony_request);
$response->send();
diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php
index 30ff5119ab..9949c972d9 100644
--- a/phpBB/install/convertors/convert_phpbb20.php
+++ b/phpBB/install/convertors/convert_phpbb20.php
@@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
$convertor_data = array(
'forum_name' => 'phpBB 2.0.x',
'version' => '1.0.3',
- 'phpbb_version' => '3.1.6',
+ 'phpbb_version' => '3.2.0-a1',
'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>',
'dbms' => $dbms,
'dbhost' => $dbhost,
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
deleted file mode 100644
index a611a33125..0000000000
--- a/phpBB/install/database_update.php
+++ /dev/null
@@ -1,270 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-$update_start_time = time();
-
-/**
-* @ignore
-*/
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-function phpbb_end_update($cache, $config)
-{
- $cache->purge();
-
- $config->increment('assets_version', 1);
-
-?>
- </p>
- </div>
- </div>
- <span class="corners-bottom"><span></span></span>
- </div>
- </div>
- </div>
-
- <div id="page-footer">
- <div class="copyright">
- Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited
- </div>
- </div>
- </div>
-</body>
-</html>
-
-<?php
-
- garbage_collection();
- exit_handler();
-}
-
-require($phpbb_root_path . 'includes/startup.' . $phpEx);
-require($phpbb_root_path . 'phpbb/class_loader.' . $phpEx);
-
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-
-$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
-extract($phpbb_config_php_file->get_all());
-
-if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
-{
- die("Please read: <a href='../docs/INSTALL.html'>INSTALL.html</a> before attempting to update.");
-}
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include files
-require($phpbb_root_path . 'includes/functions.' . $phpEx);
-require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
-
-require($phpbb_root_path . 'includes/constants.' . $phpEx);
-require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-// Set up container (must be done here because extensions table may not exist)
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
-$phpbb_container = $phpbb_container_builder
- ->with_config($phpbb_config_php_file)
- ->without_extensions()
- ->without_cache()
- ->get_container()
-;
-
-// set up caching
-/* @var $cache \phpbb\cache\service */
-$cache = $phpbb_container->get('cache');
-
-// Instantiate some basic classes
-/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
-$phpbb_dispatcher = $phpbb_container->get('dispatcher');
-
-/* @var $request \phpbb\request\request_interface */
-$request = $phpbb_container->get('request');
-
-/* @var $user \phpbb\user */
-$user = $phpbb_container->get('user');
-
-/* @var $auth \phpbb\auth\auth */
-$auth = $phpbb_container->get('auth');
-
-/* @var $db \phpbb\db\driver\driver_interface */
-$db = $phpbb_container->get('dbal.conn');
-
-/* @var $phpbb_log \phpbb\log\log_interface */
-$phpbb_log = $phpbb_container->get('log');
-
-/** @var \phpbb\language\language $language */
-$language = $phpbb_container->get('language');
-
-// Grab global variables, re-cache if necessary
-/* @var $config \phpbb\config\config */
-$config = $phpbb_container->get('config');
-
-if (!isset($config['version_update_from']))
-{
- $config->set('version_update_from', $config['version']);
-}
-
-$orig_version = $config['version_update_from'];
-
-$user->add_lang(array('common', 'acp/common', 'install', 'migrator'));
-
-// Add own hook handler, if present. :o
-if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
-{
- require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
- $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
-
- /* @var $phpbb_hook_finder \phpbb\hook\finder */
- $phpbb_hook_finder = $phpbb_container->get('hook_finder');
- foreach ($phpbb_hook_finder->find() as $hook)
- {
- @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
- }
-}
-else
-{
- $phpbb_hook = false;
-}
-
-header('Content-type: text/html; charset=UTF-8');
-?>
-<!DOCTYPE html>
-<html dir="<?php echo $user->lang['DIRECTION']; ?>" lang="<?php echo $user->lang['USER_LANG']; ?>">
-<head>
-<meta charset="utf-8">
-
-<title><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></title>
-
-<link href="<?php echo htmlspecialchars($phpbb_admin_path); ?>style/admin.css" rel="stylesheet" type="text/css" media="screen" />
-
-</head>
-
-<body>
- <div id="wrap">
- <div id="page-header">&nbsp;</div>
-
- <div id="page-body">
- <div id="acp">
- <div class="panel">
- <span class="corners-top"><span></span></span>
- <div id="content">
- <div id="main" class="install-body">
-
- <h1><?php echo $user->lang['UPDATING_TO_LATEST_STABLE']; ?></h1>
-
- <br />
-
- <p><?php echo $user->lang['DATABASE_TYPE']; ?> :: <strong><?php echo $db->get_sql_layer(); ?></strong><br />
- <?php echo $user->lang['PREVIOUS_VERSION']; ?> :: <strong><?php echo $config['version']; ?></strong><br />
-
-<?php
-
-define('IN_DB_UPDATE', true);
-
-/**
-* @todo mysql update?
-*/
-
-// End startup code
-
-/* @var $migrator \phpbb\db\migrator */
-$migrator = $phpbb_container->get('migrator');
-
-/** @var \phpbb\filesystem\filesystem_interface $phpbb_filesystem */
-$phpbb_filesystem = $phpbb_container->get('filesystem');
-$migrator->set_output_handler(new \phpbb\db\output_handler\log_wrapper_migrator_output_handler($language, new \phpbb\db\output_handler\html_migrator_output_handler($language), $phpbb_root_path . 'store/migrations_' . time() . '.log', $phpbb_filesystem));
-
-$migrator->create_migrations_table();
-
-/* @var $phpbb_extension_manager \phpbb\extension\manager */
-$phpbb_extension_manager = $phpbb_container->get('ext.manager');
-
-$migrations = $phpbb_extension_manager
- ->get_finder()
- ->core_path('phpbb/db/migration/data/')
- ->extension_directory('/migrations')
- ->get_classes();
-
-$migrator->set_migrations($migrations);
-
-// What is a safe limit of execution time? Half the max execution time should be safe.
-// No more than 15 seconds so the user isn't sitting and waiting for a very long time
-$phpbb_ini = new \bantu\IniGetWrapper\IniGetWrapper();
-$safe_time_limit = min(15, ($phpbb_ini->getNumeric('max_execution_time') / 2));
-
-// While we're going to try limit this to half the max execution time,
-// we want to try and take additional measures to prevent hitting the
-// max execution time (if, say, one migration step takes much longer
-// than the max execution time)
-@set_time_limit(0);
-
-while (!$migrator->finished())
-{
- try
- {
- $migrator->update();
- }
- catch (\phpbb\db\migration\exception $e)
- {
- echo $e->getLocalisedMessage($user);
-
- phpbb_end_update($cache, $config);
- }
-
- $state = array_merge(array(
- 'migration_schema_done' => false,
- 'migration_data_done' => false,
- ),
- $migrator->last_run_migration['state']
- );
-
- // Are we approaching the time limit? If so we want to pause the update and continue after refreshing
- if ((time() - $update_start_time) >= $safe_time_limit)
- {
- echo '<br />' . $user->lang['DATABASE_UPDATE_NOT_COMPLETED'] . '<br /><br />';
- echo '<a href="' . append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=' . $request->variable('type', 0) . '&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['DATABASE_UPDATE_CONTINUE'] . '</a>';
-
- phpbb_end_update($cache, $config);
- }
-}
-
-if ($orig_version != $config['version'])
-{
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_DATABASE', false, array($orig_version, $config['version']));
-}
-
-echo $user->lang['DATABASE_UPDATE_COMPLETE'] . '<br />';
-
-if ($request->variable('type', 0))
-{
- echo $user->lang['INLINE_UPDATE_SUCCESSFUL'] . '<br /><br />';
- echo '<a href="' . append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=update&amp;sub=update_db&amp;language=' . $request->variable('language', 'en')) . '" class="button1">' . $user->lang['CONTINUE_UPDATE_NOW'] . '</a>';
-}
-else
-{
- echo '<div class="errorbox">' . $user->lang['UPDATE_FILES_NOTICE'] . '</div>';
- echo $user->lang['COMPLETE_LOGIN_TO_BOARD'];
-}
-
-$config->delete('version_update_from');
-
-phpbb_end_update($cache, $config);
diff --git a/phpBB/install/index.php b/phpBB/install/index.php
deleted file mode 100644
index a578e664cd..0000000000
--- a/phpBB/install/index.php
+++ /dev/null
@@ -1,874 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**#@+
-* @ignore
-*/
-define('IN_PHPBB', true);
-define('IN_INSTALL', true);
-define('PHPBB_ENVIRONMENT', 'production');
-/**#@-*/
-
-$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-
-if (version_compare(PHP_VERSION, '5.4') < 0)
-{
- die('You are running an unsupported PHP version. Please upgrade to PHP 5.4 or higher before trying to install phpBB 3.2');
-}
-
-function phpbb_require_updated($path, $optional = false)
-{
- global $phpbb_root_path, $table_prefix;
-
- $new_path = $phpbb_root_path . 'install/update/new/' . $path;
- $old_path = $phpbb_root_path . $path;
-
- if (file_exists($new_path))
- {
- require($new_path);
- }
- else if (!$optional || file_exists($old_path))
- {
- require($old_path);
- }
-}
-
-function phpbb_include_updated($path, $optional = false)
-{
- global $phpbb_root_path;
-
- $new_path = $phpbb_root_path . 'install/update/new/' . $path;
- $old_path = $phpbb_root_path . $path;
-
- if (file_exists($new_path))
- {
- include($new_path);
- }
- else if (!$optional || file_exists($old_path))
- {
- include($old_path);
- }
-}
-
-phpbb_require_updated('includes/startup.' . $phpEx);
-
-// Try to override some limits - maybe it helps some...
-@set_time_limit(0);
-$mem_limit = @ini_get('memory_limit');
-if (!empty($mem_limit))
-{
- $unit = strtolower(substr($mem_limit, -1, 1));
- $mem_limit = (int) $mem_limit;
-
- if ($unit == 'k')
- {
- $mem_limit = floor($mem_limit / 1024);
- }
- else if ($unit == 'g')
- {
- $mem_limit *= 1024;
- }
- else if (is_numeric($unit))
- {
- $mem_limit = floor((int) ($mem_limit . $unit) / 1048576);
- }
- $mem_limit = max(128, $mem_limit) . 'M';
-}
-else
-{
- $mem_limit = '128M';
-}
-@ini_set('memory_limit', $mem_limit);
-
-// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
-$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
-$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
-
-// Include essential scripts
-phpbb_require_updated('phpbb/class_loader.' . $phpEx);
-
-phpbb_require_updated('includes/functions.' . $phpEx);
-
-phpbb_require_updated('includes/functions_content.' . $phpEx, true);
-
-phpbb_include_updated('includes/functions_admin.' . $phpEx);
-phpbb_include_updated('includes/utf/utf_tools.' . $phpEx);
-phpbb_require_updated('includes/functions_install.' . $phpEx);
-
-// Setup class loader first
-$phpbb_class_loader_new = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}install/update/new/phpbb/", $phpEx);
-$phpbb_class_loader_new->register();
-$phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx);
-$phpbb_class_loader->register();
-$phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx);
-$phpbb_class_loader_ext->register();
-
-// Set up container
-$phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx);
-$phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
-$phpbb_container_builder
- ->without_extensions()
- ->without_cache()
- ->without_compiled_container()
-;
-
-$other_config_path = $phpbb_root_path . 'install/update/new/config/';
-$config_path = file_exists($other_config_path . 'services.yml') ? $other_config_path : $phpbb_root_path . 'config/';
-$phpbb_container_builder->with_config_path($config_path);
-
-$phpbb_container_builder->with_custom_parameters(array(
- 'core.root_path' => $phpbb_root_path,
- 'core.adm_relative_path' => $phpbb_adm_relative_path,
- 'core.php_ext' => $phpEx,
- 'core.table_prefix' => '',
- 'cache.driver.class' => 'phpbb\cache\driver\file',
-));
-
-$phpbb_container = $phpbb_container_builder->get_container();
-$phpbb_container->register('dbal.conn.driver')->setSynthetic(true);
-$phpbb_container->register('template.twig.environment')->setSynthetic(true);
-$phpbb_container->register('language.loader')->setSynthetic(true);
-$phpbb_container->compile();
-
-$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
-$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
-
-/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
-$phpbb_dispatcher = $phpbb_container->get('dispatcher');
-
-/* @var $request \phpbb\request\request_interface */
-$request = $phpbb_container->get('request');
-
-// Try and load an appropriate language if required
-$language = basename($request->variable('language', ''));
-
-if ($request->header('Accept-Language') && !$language)
-{
- $accept_lang_ary = explode(',', strtolower($request->header('Accept-Language')));
- foreach ($accept_lang_ary as $accept_lang)
- {
- // Set correct format ... guess full xx_yy form
- $accept_lang = substr($accept_lang, 0, 2) . '_' . substr($accept_lang, 3, 2);
-
- if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
- {
- $language = $accept_lang;
- break;
- }
- else
- {
- // No match on xx_yy so try xx
- $accept_lang = substr($accept_lang, 0, 2);
- if (file_exists($phpbb_root_path . 'language/' . $accept_lang) && is_dir($phpbb_root_path . 'language/' . $accept_lang))
- {
- $language = $accept_lang;
- break;
- }
- }
- }
-}
-
-// No appropriate language found ... so let's use the first one in the language
-// dir, this may or may not be English
-if (!$language)
-{
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- die('Unable to access the language directory');
- exit;
- }
-
- while (($file = readdir($dir)) !== false)
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if (!is_file($path) && !is_link($path) && file_exists($path . '/iso.txt'))
- {
- $language = $file;
- break;
- }
- }
- closedir($dir);
-}
-
-if (!file_exists($phpbb_root_path . 'language/' . $language) || !is_dir($phpbb_root_path . 'language/' . $language))
-{
- die('No language found!');
-}
-
-// And finally, load the relevant language files
-$load_lang_files = array('common', 'acp/common', 'acp/board', 'install', 'posting');
-$new_path = $phpbb_root_path . 'install/update/new/language/' . $language . '/';
-$old_path = $phpbb_root_path . 'language/' . $language . '/';
-
-// NOTE: we can not use "phpbb_include_updated" as the files uses vars which would be required
-// to be global while loading.
-foreach ($load_lang_files as $lang_file)
-{
- if (file_exists($new_path . $lang_file . '.' . $phpEx))
- {
- include($new_path . $lang_file . '.' . $phpEx);
- }
- else
- {
- include($old_path . $lang_file . '.' . $phpEx);
- }
-}
-
-// usually we would need every single constant here - and it would be consistent. For 3.0.x, use a dirty hack... :(
-
-// Define needed constants
-define('CHMOD_ALL', 7);
-define('CHMOD_READ', 4);
-define('CHMOD_WRITE', 2);
-define('CHMOD_EXECUTE', 1);
-
-$mode = $request->variable('mode', 'overview');
-$sub = $request->variable('sub', '');
-
-// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
-
-$lang_service = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
-$lang_service->add_lang($load_lang_files);
-$lang_service->set_user_language($language);
-$user = new \phpbb\user($lang_service, '\phpbb\datetime');
-$auth = new \phpbb\auth\auth();
-
-// Add own hook handler, if present. :o
-if (file_exists($phpbb_root_path . 'includes/hooks/index.' . $phpEx))
-{
- require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
- $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('template', 'display')));
-
- /* @var $phpbb_hook_finder \phpbb\hook\finder */
- $phpbb_hook_finder = $phpbb_container->get('hook_finder');
- foreach ($phpbb_hook_finder->find() as $hook)
- {
- @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
- }
-}
-else
-{
- $phpbb_hook = false;
-}
-
-// Set some standard variables we want to force
-$config = new \phpbb\config\config(array(
- 'load_tplcompile' => '1'
-));
-
-/* @var $symfony_request \phpbb\symfony_request */
-$symfony_request = $phpbb_container->get('symfony_request');
-
-/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */
-$phpbb_filesystem = $phpbb_container->get('filesystem');
-
-/* @var $phpbb_path_helper \phpbb\path_helper */
-$phpbb_path_helper = $phpbb_container->get('path_helper');
-$cache_path = $phpbb_root_path . 'cache/';
-
-$twig_environment = new \phpbb\template\twig\environment(
- $config,
- $phpbb_filesystem,
- $phpbb_path_helper,
- $phpbb_container,
- $cache_path,
- null,
- $phpbb_container->get('template.twig.loader')
-);
-
-$language_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
-$phpbb_container->set('template.twig.environment', $twig_environment);
-$phpbb_container->set('language.loader', $language_loader);
-$twig_context = new \phpbb\template\context();
-$template = new \phpbb\template\twig\twig(
- $phpbb_path_helper,
- $config,
- $twig_context,
- $twig_environment,
- $cache_path,
- $user,
- array($phpbb_container->get('template.twig.extensions.phpbb'))
-);
-
-/** @var \phpbb\language\language $lang_service */
-$lang_service = $phpbb_container->get('language');
-$lang_service->add_lang($load_lang_files);
-$lang_service->set_user_language($language);
-
-$paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
-$paths = array_filter($paths, 'is_dir');
-$template->set_custom_style(array(
- array(
- 'name' => 'adm',
- 'ext_path' => 'adm/style/',
- ),
-), $paths);
-
-$path = array_shift($paths);
-
-$template->assign_var('T_ASSETS_PATH', $path . '/../../assets');
-$template->assign_var('T_TEMPLATE_PATH', $path);
-
-$install = new module();
-
-$install->create('install', "index.$phpEx", $mode, $sub);
-$install->load();
-
-// Generate the page
-$install->page_header();
-$install->generate_navigation();
-
-$template->set_filenames(array(
- 'body' => $install->get_tpl_name())
-);
-
-$install->page_footer();
-
-class module
-{
- var $id = 0;
- var $type = 'install';
- var $module_ary = array();
- var $filename;
- var $module_url = '';
- var $tpl_name = '';
- var $mode;
- var $sub;
-
- /**
- * Private methods, should not be overwritten
- */
- function create($module_type, $module_url, $selected_mod = false, $selected_submod = false)
- {
- global $db, $config, $phpEx, $phpbb_root_path;
-
- $module = array();
-
- // Grab module information using Bart's "neat-o-module" system (tm)
- $dir = @opendir('.');
-
- if (!$dir)
- {
- $this->error('Unable to access the installation directory', __LINE__, __FILE__);
- }
-
- $setmodules = 1;
- while (($file = readdir($dir)) !== false)
- {
- if (preg_match('#^install_(.*?)\.' . $phpEx . '$#', $file))
- {
- include($file);
- }
- }
- closedir($dir);
-
- unset($setmodules);
-
- if (!sizeof($module))
- {
- $this->error('No installation modules found', __LINE__, __FILE__);
- }
-
- // Order to use and count further if modules get assigned to the same position or not having an order
- $max_module_order = 1000;
-
- foreach ($module as $row)
- {
- // Module order not specified or module already assigned at this position?
- if (!isset($row['module_order']) || isset($this->module_ary[$row['module_order']]))
- {
- $row['module_order'] = $max_module_order;
- $max_module_order++;
- }
-
- $this->module_ary[$row['module_order']]['name'] = $row['module_title'];
- $this->module_ary[$row['module_order']]['filename'] = $row['module_filename'];
- $this->module_ary[$row['module_order']]['subs'] = $row['module_subs'];
- $this->module_ary[$row['module_order']]['stages'] = $row['module_stages'];
-
- if (strtolower($selected_mod) == strtolower($row['module_title']))
- {
- $this->id = (int) $row['module_order'];
- $this->filename = (string) $row['module_filename'];
- $this->module_url = (string) $module_url;
- $this->mode = (string) $selected_mod;
- // Check that the sub-mode specified is valid or set a default if not
- if (is_array($row['module_subs']))
- {
- $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_subs'])) ? $selected_submod : $row['module_subs'][0]);
- }
- else if (is_array($row['module_stages']))
- {
- $this->sub = strtolower((in_array(strtoupper($selected_submod), $row['module_stages'])) ? $selected_submod : $row['module_stages'][0]);
- }
- else
- {
- $this->sub = '';
- }
- }
- } // END foreach
- } // END create
-
- /**
- * Load and run the relevant module if applicable
- */
- function load($mode = false, $run = true)
- {
- global $phpbb_root_path, $phpEx;
-
- if ($run)
- {
- if (!empty($mode))
- {
- $this->mode = $mode;
- }
-
- $module = $this->filename;
- if (!class_exists($module))
- {
- $this->error('Module "' . htmlspecialchars($module) . '" not accessible.', __LINE__, __FILE__);
- }
- $this->module = new $module($this);
-
- if (method_exists($this->module, 'main'))
- {
- $this->module->main($this->mode, $this->sub);
- }
- }
- }
-
- /**
- * Output the standard page header
- */
- function page_header()
- {
- if (defined('HEADER_INC'))
- {
- return;
- }
-
- define('HEADER_INC', true);
- global $template, $lang, $stage, $phpbb_admin_path, $path;
-
- $template->assign_vars(array(
- 'L_CHANGE' => $lang['CHANGE'],
- 'L_COLON' => $lang['COLON'],
- 'L_INSTALL_PANEL' => $lang['INSTALL_PANEL'],
- 'L_SELECT_LANG' => $lang['SELECT_LANG'],
- 'L_SKIP' => $lang['SKIP'],
- 'PAGE_TITLE' => $this->get_page_title(),
- 'T_IMAGE_PATH' => htmlspecialchars($phpbb_admin_path) . 'images/',
- 'T_JQUERY_LINK' => $path . '/../../assets/javascript/jquery.min.js',
-
- 'S_CONTENT_DIRECTION' => $lang['DIRECTION'],
- 'S_CONTENT_FLOW_BEGIN' => ($lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
- 'S_CONTENT_FLOW_END' => ($lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
- 'S_CONTENT_ENCODING' => 'UTF-8',
-
- 'S_USER_LANG' => $lang['USER_LANG'],
- )
- );
-
- header('Content-type: text/html; charset=UTF-8');
- header('Cache-Control: private, no-cache="set-cookie"');
- header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
-
- return;
- }
-
- /**
- * Output the standard page footer
- */
- function page_footer()
- {
- global $db, $template;
-
- $template->display('body');
-
- // Close our DB connection.
- if (!empty($db) && is_object($db))
- {
- $db->sql_close();
- }
-
- if (function_exists('exit_handler'))
- {
- exit_handler();
- }
- }
-
- /**
- * Returns desired template name
- */
- function get_tpl_name()
- {
- return $this->module->tpl_name . '.html';
- }
-
- /**
- * Returns the desired page title
- */
- function get_page_title()
- {
- global $lang;
-
- if (!isset($this->module->page_title))
- {
- return '';
- }
-
- return (isset($lang[$this->module->page_title])) ? $lang[$this->module->page_title] : $this->module->page_title;
- }
-
- /**
- * Generate an HTTP/1.1 header to redirect the user to another page
- * This is used during the installation when we do not have a database available to call the normal redirect function
- * @param string $page The page to redirect to relative to the installer root path
- */
- function redirect($page)
- {
- global $request;
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
- $server_port = $request->server('SERVER_PORT', 0);
- $secure = $request->is_secure() ? 1 : 0;
-
- $script_name = htmlspecialchars_decode($request->server('PHP_SELF'));
- if (!$script_name)
- {
- $script_name = htmlspecialchars_decode($request->server('REQUEST_URI'));
- }
-
- // Replace backslashes and doubled slashes (could happen on some proxy setups)
- $script_name = str_replace(array('\\', '//'), '/', $script_name);
- $script_path = trim(dirname($script_name));
-
- $url = (($secure) ? 'https://' : 'http://') . $server_name;
-
- if ($server_port && (($secure && $server_port <> 443) || (!$secure && $server_port <> 80)))
- {
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') === false)
- {
- $url .= ':' . $server_port;
- }
- }
-
- $url .= $script_path . '/' . $page;
- header('Location: ' . $url);
- exit;
- }
-
- /**
- * Generate the navigation tabs
- */
- function generate_navigation()
- {
- global $lang, $template, $phpEx, $language;
-
- if (is_array($this->module_ary))
- {
- @ksort($this->module_ary);
- foreach ($this->module_ary as $cat_ary)
- {
- $cat = $cat_ary['name'];
- $l_cat = (!empty($lang['CAT_' . $cat])) ? $lang['CAT_' . $cat] : preg_replace('#_#', ' ', $cat);
- $cat = strtolower($cat);
- $url = $this->module_url . "?mode=$cat&amp;language=$language";
-
- if ($this->mode == $cat)
- {
- $template->assign_block_vars('t_block1', array(
- 'L_TITLE' => $l_cat,
- 'S_SELECTED' => true,
- 'U_TITLE' => $url,
- ));
-
- if (is_array($this->module_ary[$this->id]['subs']))
- {
- $subs = $this->module_ary[$this->id]['subs'];
- foreach ($subs as $option)
- {
- $l_option = (!empty($lang['SUB_' . $option])) ? $lang['SUB_' . $option] : preg_replace('#_#', ' ', $option);
- $option = strtolower($option);
- $url = $this->module_url . '?mode=' . $this->mode . "&amp;sub=$option&amp;language=$language";
-
- $template->assign_block_vars('l_block1', array(
- 'L_TITLE' => $l_option,
- 'S_SELECTED' => ($this->sub == $option),
- 'U_TITLE' => $url,
- ));
- }
- }
-
- if (is_array($this->module_ary[$this->id]['stages']))
- {
- $subs = $this->module_ary[$this->id]['stages'];
- $matched = false;
- foreach ($subs as $option)
- {
- $l_option = (!empty($lang['STAGE_' . $option])) ? $lang['STAGE_' . $option] : preg_replace('#_#', ' ', $option);
- $option = strtolower($option);
- $matched = ($this->sub == $option) ? true : $matched;
-
- $template->assign_block_vars('l_block2', array(
- 'L_TITLE' => $l_option,
- 'S_SELECTED' => ($this->sub == $option),
- 'S_COMPLETE' => !$matched,
- ));
- }
- }
- }
- else
- {
- $template->assign_block_vars('t_block1', array(
- 'L_TITLE' => $l_cat,
- 'S_SELECTED' => false,
- 'U_TITLE' => $url,
- ));
- }
- }
- }
- }
-
- /**
- * Output an error message
- * If skip is true, return and continue execution, else exit
- */
- function error($error, $line, $file, $skip = false)
- {
- global $lang, $db, $template, $phpbb_admin_path;
-
- if ($skip)
- {
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['INST_ERR'],
- ));
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
- 'RESULT' => '<b style="color:red">' . $error . '</b>',
- ));
-
- return;
- }
-
- echo '<!DOCTYPE html>';
- echo '<html dir="ltr">';
- echo '<head>';
- echo '<meta charset="utf-8">';
- echo '<title>' . $lang['INST_ERR_FATAL'] . '</title>';
- echo '<link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />';
- echo '</head>';
- echo '<body id="errorpage">';
- echo '<div id="wrap">';
- echo ' <div id="page-header">';
- echo ' </div>';
- echo ' <div id="page-body">';
- echo ' <div id="acp">';
- echo ' <div class="panel">';
- echo ' <span class="corners-top"><span></span></span>';
- echo ' <div id="content">';
- echo ' <h1>' . $lang['INST_ERR_FATAL'] . '</h1>';
- echo ' <p>' . $lang['INST_ERR_FATAL'] . "</p>\n";
- echo ' <p>' . basename($file) . ' [ ' . $line . " ]</p>\n";
- echo ' <p><b>' . $error . "</b></p>\n";
- echo ' </div>';
- echo ' <span class="corners-bottom"><span></span></span>';
- echo ' </div>';
- echo ' </div>';
- echo ' </div>';
- echo ' <div id="page-footer">';
- echo ' Powered by <a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited';
- echo ' </div>';
- echo '</div>';
- echo '</body>';
- echo '</html>';
-
- if (!empty($db) && is_object($db))
- {
- $db->sql_close();
- }
-
- exit_handler();
- }
-
- /**
- * Output an error message for a database related problem
- * If skip is true, return and continue execution, else exit
- */
- function db_error($error, $sql, $line, $file, $skip = false)
- {
- global $lang, $db, $template;
-
- if ($skip)
- {
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['INST_ERR_FATAL'],
- ));
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => basename($file) . ' [ ' . $line . ' ]',
- 'RESULT' => '<b style="color:red">' . $error . '</b><br />&#187; SQL:' . $sql,
- ));
-
- return;
- }
-
- $template->set_filenames(array(
- 'body' => 'install_error.html')
- );
- $this->page_header();
- $this->generate_navigation();
-
- $template->assign_vars(array(
- 'MESSAGE_TITLE' => $lang['INST_ERR_FATAL_DB'],
- 'MESSAGE_TEXT' => '<p>' . basename($file) . ' [ ' . $line . ' ]</p><p>SQL : ' . $sql . '</p><p><b>' . $error . '</b></p>',
- ));
-
- // Rollback if in transaction
- if ($db->get_transaction())
- {
- $db->sql_transaction('rollback');
- }
-
- $this->page_footer();
- }
-
- /**
- * Generate the relevant HTML for an input field and the associated label and explanatory text
- */
- function input_field($name, $type, $value = '', $options = '')
- {
- global $lang;
- $tpl_type = explode(':', $type);
- $tpl = '';
-
- switch ($tpl_type[0])
- {
- case 'text':
- case 'password':
- // HTML5 text-like input types
- case 'color':
- case 'date':
- case 'time':
- case 'datetime':
- case 'datetime-local':
- case 'email':
- case 'month':
- case 'number':
- case 'range':
- case 'search':
- case 'tel':
- case 'url':
- case 'week':
-
- $size = (int) $tpl_type[1];
- $maxlength = (int) $tpl_type[2];
- $autocomplete = (isset($options['autocomplete']) && $options['autocomplete'] == 'off') ? ' autocomplete="off"' : '';
-
- $tpl = '<input id="' . $name . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '"' . $autocomplete . ' value="' . $value . '" />';
- break;
-
- case 'textarea':
- $rows = (int) $tpl_type[1];
- $cols = (int) $tpl_type[2];
-
- $tpl = '<textarea id="' . $name . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $value . '</textarea>';
- break;
-
- case 'radio':
- $key_yes = ($value) ? ' checked="checked" id="' . $name . '"' : '';
- $key_no = (!$value) ? ' checked="checked" id="' . $name . '"' : '';
-
- $tpl_type_cond = explode('_', $tpl_type[1]);
- $type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
-
- $tpl_no = '<label><input type="radio" name="' . $name . '" value="0"' . $key_no . ' class="radio" /> ' . (($type_no) ? $lang['NO'] : $lang['DISABLED']) . '</label>';
- $tpl_yes = '<label><input type="radio" name="' . $name . '" value="1"' . $key_yes . ' class="radio" /> ' . (($type_no) ? $lang['YES'] : $lang['ENABLED']) . '</label>';
-
- $tpl = ($tpl_type_cond[0] == 'yes' || $tpl_type_cond[0] == 'enabled') ? $tpl_yes . '&nbsp;&nbsp;' . $tpl_no : $tpl_no . '&nbsp;&nbsp;' . $tpl_yes;
- break;
-
- case 'select':
- // @codingStandardsIgnoreStart
- eval('$s_options = ' . str_replace('{VALUE}', $value, $options) . ';');
- // @codingStandardsIgnoreEnd
- $tpl = '<select id="' . $name . '" name="' . $name . '">' . $s_options . '</select>';
- break;
-
- case 'custom':
- // @codingStandardsIgnoreStart
- eval('$tpl = ' . str_replace('{VALUE}', $value, $options) . ';');
- // @codingStandardsIgnoreEnd
- break;
-
- default:
- break;
- }
-
- return $tpl;
- }
-
- /**
- * Generate the drop down of available language packs
- */
- function inst_language_select($default = '')
- {
- global $phpbb_root_path, $phpEx;
-
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- $this->error('Unable to access the language directory', __LINE__, __FILE__);
- }
-
- while ($file = readdir($dir))
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
- {
- continue;
- }
-
- if (file_exists($path . '/iso.txt'))
- {
- list($displayname, $localname) = @file($path . '/iso.txt');
- $lang[$localname] = $file;
- }
- }
- closedir($dir);
-
- @asort($lang);
- @reset($lang);
-
- $user_select = '';
- foreach ($lang as $displayname => $filename)
- {
- $selected = (strtolower($default) == strtolower($filename)) ? ' selected="selected"' : '';
- $user_select .= '<option value="' . $filename . '"' . $selected . '>' . ucwords($displayname) . '</option>';
- }
-
- return $user_select;
- }
-}
diff --git a/phpBB/install/install_convert.php b/phpBB/install/install_convert.php
deleted file mode 100644
index d72ee1a633..0000000000
--- a/phpBB/install/install_convert.php
+++ /dev/null
@@ -1,2153 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-*/
-
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'CONVERT',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 20,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'SETTINGS', 'IN_PROGRESS', 'FINAL'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Class holding all convertor-specific details.
-*/
-class convert
-{
- var $options = array();
-
- var $convertor_tag = '';
- var $src_dbms = '';
- var $src_dbhost = '';
- var $src_dbport = '';
- var $src_dbuser = '';
- var $src_dbpasswd = '';
- var $src_dbname = '';
- var $src_table_prefix = '';
-
- var $convertor_data = array();
- var $tables = array();
- var $config_schema = array();
- var $convertor = array();
- var $src_truncate_statement = 'DELETE FROM ';
- var $truncate_statement = 'DELETE FROM ';
-
- var $fulltext_search;
-
- // Batch size, can be adjusted by the conversion file
- // For big boards a value of 6000 seems to be optimal
- var $batch_size = 2000;
- // Number of rows to be inserted at once (extended insert) if supported
- // For installations having enough memory a value of 60 may be good.
- var $num_wait_rows = 20;
-
- // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor.
- var $mysql_convert = false;
-
- var $p_master;
-
- function convert(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-}
-
-/**
-* Convert class for conversions
-*/
-class install_convert extends module
-{
- /** @var array */
- protected $lang;
-
- /** @var string */
- protected $language;
-
- /** @var \phpbb\template\template */
- protected $template;
-
- /** @var string */
- protected $phpbb_root_path;
-
- /** @var string */
- protected $php_ext;
-
- /** @var \phpbb\filesystem\filesystem_interface */
- protected $filesystem;
-
- /**
- * Variables used while converting, they are accessible from the global variable $convert
- */
- function install_convert(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx, $cache, $config, $language, $table_prefix;
- global $convert, $request, $phpbb_container, $phpbb_config_php_file;
-
- $this->tpl_name = 'install_convert';
- $this->mode = $mode;
- $this->lang = $lang;
- $this->language = $language;
- $this->template = $template;
- $this->phpbb_root_path = $phpbb_root_path;
- $this->php_ext = $phpEx;
- $this->filesystem = new \phpbb\filesystem\filesystem();
-
- if (!$this->check_phpbb_installed())
- {
- return;
- }
-
- $convert = new convert($this->p_master);
-
- // Enable super globals to prevent issues with the new \phpbb\request\request object
- $request->enable_super_globals();
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
-
- // Create cache
- /* @var $cache \phpbb\cache\service */
- $cache = $phpbb_container->get('cache');
-
- switch ($sub)
- {
- case 'intro':
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- // Detect if there is already a conversion in progress at this point and offer to resume
- // It's quite possible that the user will get disconnected during a large conversion so they need to be able to resume it
- $new_conversion = $request->variable('new_conv', 0);
-
- if ($new_conversion)
- {
- $config['convert_progress'] = '';
- $config['convert_db_server'] = '';
- $config['convert_db_user'] = '';
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
- WHERE config_name = 'convert_progress'
- OR config_name = 'convert_db_server'
- OR config_name = 'convert_db_user'"
- );
- }
-
- // Let's see if there is a conversion in the works...
- $options = array();
- if (!empty($config['convert_progress']) && !empty($config['convert_db_server']) && !empty($config['convert_db_user']) && !empty($config['convert_options']))
- {
- $options = unserialize($config['convert_progress']);
- $options = array_merge($options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
- }
-
- // This information should have already been checked once, but do it again for safety
- if (!empty($options) && !empty($options['tag']) &&
- isset($options['dbms']) &&
- isset($options['dbhost']) &&
- isset($options['dbport']) &&
- isset($options['dbuser']) &&
- isset($options['dbpasswd']) &&
- isset($options['dbname']) &&
- isset($options['table_prefix']))
- {
- $this->page_title = $lang['CONTINUE_CONVERT'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONTINUE_CONVERT'],
- 'BODY' => $lang['CONTINUE_CONVERT_BODY'],
- 'L_NEW' => $lang['CONVERT_NEW_CONVERSION'],
- 'L_CONTINUE' => $lang['CONTINUE_OLD_CONVERSION'],
- 'S_CONTINUE' => true,
-
- 'U_NEW_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=intro&amp;new_conv=1&amp;language=$language",
- 'U_CONTINUE_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$options['tag']}{$options['step']}&amp;language=$language",
- ));
-
- return;
- }
-
- $this->list_convertors($sub);
-
- break;
-
- case 'settings':
- $this->get_convert_settings($sub);
- break;
-
- case 'in_progress':
- $this->convert_data($sub);
- break;
-
- case 'final':
- $this->page_title = $lang['CONVERT_COMPLETE'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONVERT_COMPLETE'],
- 'BODY' => $lang['CONVERT_COMPLETE_EXPLAIN'],
- ));
-
- // If we reached this step (conversion completed) we want to purge the cache and log the user out.
- // This is for making sure the session get not screwed due to the 3.0.x users table being completely new.
- $cache->purge();
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- $sql = 'SELECT config_value
- FROM ' . CONFIG_TABLE . '
- WHERE config_name = \'search_type\'';
- $result = $db->sql_query($sql);
-
- if ($db->sql_fetchfield('config_value') != 'fulltext_mysql')
- {
- $template->assign_vars(array(
- 'S_ERROR_BOX' => true,
- 'ERROR_TITLE' => $lang['SEARCH_INDEX_UNCONVERTED'],
- 'ERROR_MSG' => $lang['SEARCH_INDEX_UNCONVERTED_EXPLAIN'],
- ));
- }
-
- switch ($db->get_sql_layer())
- {
- case 'sqlite':
- case 'sqlite3':
- $db->sql_query('DELETE FROM ' . SESSIONS_KEYS_TABLE);
- $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
- break;
-
- default:
- $db->sql_query('TRUNCATE TABLE ' . SESSIONS_KEYS_TABLE);
- $db->sql_query('TRUNCATE TABLE ' . SESSIONS_TABLE);
- break;
- }
-
- break;
- }
- }
-
- /**
- * Check whether phpBB is installed.
- * Assigns error template vars if not installed.
- *
- * @return bool Returns true if phpBB is installed.
- */
- public function check_phpbb_installed()
- {
- if (phpbb_check_installation_exists($this->phpbb_root_path, $this->php_ext))
- {
- return true;
- }
-
- $this->page_title = 'BOARD_NOT_INSTALLED';
- $install_url = append_sid($this->phpbb_root_path . 'install/index.' . $this->php_ext, 'mode=install&amp;language=' . $this->language);
-
- $this->template->assign_vars(array(
- 'S_NOT_INSTALLED' => true,
- 'BODY' => sprintf($this->lang['BOARD_NOT_INSTALLED_EXPLAIN'], $install_url),
- ));
-
- return false;
- }
-
- /**
- * Generate a list of all available conversion modules
- */
- function list_convertors($sub)
- {
- global $lang, $language, $template, $phpbb_root_path, $phpEx;
-
- $this->page_title = $lang['SUB_INTRO'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['CONVERT_INTRO'],
- 'BODY' => $lang['CONVERT_INTRO_BODY'],
-
- 'L_AUTHOR' => $lang['AUTHOR'],
- 'L_AVAILABLE_CONVERTORS' => $lang['AVAILABLE_CONVERTORS'],
- 'L_CONVERT' => $lang['CONVERT'],
- 'L_NO_CONVERTORS' => $lang['NO_CONVERTORS'],
- 'L_OPTIONS' => $lang['CONVERT_OPTIONS'],
- 'L_SOFTWARE' => $lang['SOFTWARE'],
- 'L_VERSION' => $lang['VERSION'],
-
- 'S_LIST' => true,
- ));
-
- $convertors = $sort = array();
- $get_info = true;
-
- $handle = @opendir('./convertors/');
-
- if (!$handle)
- {
- $this->error('Unable to access the convertors directory', __LINE__, __FILE__);
- }
-
- while ($entry = readdir($handle))
- {
- if (preg_match('/^convert_([a-z0-9_]+).' . $phpEx . '$/i', $entry, $m))
- {
- include('./convertors/' . $entry);
- if (isset($convertor_data))
- {
- $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors);
-
- $convertors[] = array(
- 'tag' => $m[1],
- 'forum_name' => $convertor_data['forum_name'],
- 'version' => $convertor_data['version'],
- 'dbms' => $convertor_data['dbms'],
- 'dbhost' => $convertor_data['dbhost'],
- 'dbport' => $convertor_data['dbport'],
- 'dbuser' => $convertor_data['dbuser'],
- 'dbpasswd' => $convertor_data['dbpasswd'],
- 'dbname' => $convertor_data['dbname'],
- 'table_prefix' => $convertor_data['table_prefix'],
- 'author' => $convertor_data['author']
- );
- }
- unset($convertor_data);
- }
- }
- closedir($handle);
-
- @ksort($sort);
-
- foreach ($sort as $void => $index)
- {
- $template->assign_block_vars('convertors', array(
- 'AUTHOR' => $convertors[$index]['author'],
- 'SOFTWARE' => $convertors[$index]['forum_name'],
- 'VERSION' => $convertors[$index]['version'],
-
- 'U_CONVERT' => $this->p_master->module_url . "?mode={$this->mode}&amp;language=$language&amp;sub=settings&amp;tag=" . $convertors[$index]['tag'],
- ));
- }
- }
-
- /**
- */
- function get_convert_settings($sub)
- {
- global $lang, $language, $template, $db, $phpbb_root_path, $phpEx, $config, $cache, $phpbb_config_php_file;
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- $this->page_title = $lang['STAGE_SETTINGS'];
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- $convertor_tag = $request->variable('tag', '');
-
- if (empty($convertor_tag))
- {
- $this->p_master->error($lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
- }
- $get_info = true;
-
- // check security implications of direct inclusion
- $convertor_tag = basename($convertor_tag);
- if (!file_exists('./convertors/convert_' . $convertor_tag . '.' . $phpEx))
- {
- $this->p_master->error($lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
- }
-
- include('./convertors/convert_' . $convertor_tag . '.' . $phpEx);
-
- // The test_file is a file that should be present in the location of the old board.
- if (!isset($test_file))
- {
- $this->p_master->error($lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
- }
-
- $submit = (isset($_POST['submit'])) ? true : false;
-
- $src_dbms = $request->variable('src_dbms', $convertor_data['dbms']);
- $src_dbhost = $request->variable('src_dbhost', $convertor_data['dbhost']);
- $src_dbport = $request->variable('src_dbport', $convertor_data['dbport']);
- $src_dbuser = $request->variable('src_dbuser', $convertor_data['dbuser']);
- $src_dbpasswd = $request->variable('src_dbpasswd', $convertor_data['dbpasswd']);
- $src_dbname = $request->variable('src_dbname', $convertor_data['dbname']);
- $src_table_prefix = $request->variable('src_table_prefix', $convertor_data['table_prefix']);
- $forum_path = $request->variable('forum_path', $convertor_data['forum_path']);
- $refresh = $request->variable('refresh', 1);
-
- // Default URL of the old board
- // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it?
- // -> We should convert old urls to the new relative urls format
- // $src_url = $request->variable('src_url', 'Not in use at the moment');
-
- // strip trailing slash from old forum path
- $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path;
-
- $error = array();
- if ($submit)
- {
- if (!@file_exists('./../' . $forum_path . '/' . $test_file))
- {
- $error[] = sprintf($lang['COULD_NOT_FIND_PATH'], $forum_path);
- }
-
- $connect_test = false;
- $available_dbms = get_available_dbms(false, true, true);
-
- if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE'])
- {
- $error[] = $lang['INST_ERR_NO_DB'];
- $connect_test = false;
- }
- else
- {
- $connect_test = connect_check_db(true, $error, $available_dbms[$src_dbms], $src_table_prefix, $src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, true, ($src_dbms == $dbms) ? false : true, false);
- }
-
- // The forum prefix of the old and the new forum can only be the same if two different databases are used.
- if ($src_table_prefix == $table_prefix && $src_dbms == $dbms && $src_dbhost == $dbhost && $src_dbport == $dbport && $src_dbname == $dbname)
- {
- $error[] = sprintf($lang['TABLE_PREFIX_SAME'], $src_table_prefix);
- }
-
- $src_dbms = $phpbb_config_php_file->convert_30_dbms_to_31($src_dbms);
-
- // Check table prefix
- if (!sizeof($error))
- {
- // initiate database connection to old db if old and new db differ
- global $src_db, $same_db;
- $src_db = $same_db = false;
-
- if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser)
- {
- $src_db = new $src_dbms();
- $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true);
- $same_db = false;
- }
- else
- {
- $src_db = $db;
- $same_db = true;
- }
-
- $src_db->sql_return_on_error(true);
- $db->sql_return_on_error(true);
-
- // Try to select one row from the first table to see if the prefix is OK
- $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1);
-
- if (!$result)
- {
- $prefixes = array();
-
- $db_tools_factory = new \phpbb\db\tools\factory();
- $db_tools = $db_tools_factory->get($src_db);
- $tables_existing = $db_tools->sql_list_tables();
- $tables_existing = array_map('strtolower', $tables_existing);
- foreach ($tables_existing as $table_name)
- {
- compare_table($tables, $table_name, $prefixes);
- }
- unset($tables_existing);
-
- foreach ($prefixes as $prefix => $count)
- {
- if ($count >= sizeof($tables))
- {
- $possible_prefix = $prefix;
- break;
- }
- }
-
- $msg = '';
- if (!empty($convertor_data['table_prefix']))
- {
- $msg .= sprintf($lang['DEFAULT_PREFIX_IS'], $convertor_data['forum_name'], $convertor_data['table_prefix']);
- }
-
- if (!empty($possible_prefix))
- {
- $msg .= '<br />';
- $msg .= ($possible_prefix == '*') ? $lang['BLANK_PREFIX_FOUND'] : sprintf($lang['PREFIX_FOUND'], $possible_prefix);
- $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix;
- }
-
- $error[] = $msg;
- }
- $src_db->sql_freeresult($result);
- $src_db->sql_return_on_error(false);
- }
-
- if (!sizeof($error))
- {
- // Save convertor Status
- $config->set('convert_progress', serialize(array(
- 'step' => '',
- 'table_prefix' => $src_table_prefix,
- 'tag' => $convertor_tag,
- )), false);
- $config->set('convert_db_server', serialize(array(
- 'dbms' => $src_dbms,
- 'dbhost' => $src_dbhost,
- 'dbport' => $src_dbport,
- 'dbname' => $src_dbname,
- )), false);
- $config->set('convert_db_user', serialize(array(
- 'dbuser' => $src_dbuser,
- 'dbpasswd' => $src_dbpasswd,
- )), false);
-
- // Save options
- $config->set('convert_options', serialize(array(
- 'forum_path' => './../' . $forum_path,
- 'refresh' => $refresh
- )), false);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['VERIFY_OPTIONS'],
- 'RESULT' => $lang['CONVERT_SETTINGS_VERIFIED'],
- ));
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $lang['BEGIN_CONVERT'],
-// 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag=$convertor_tag&amp;language=$language",
- ));
-
- return;
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['VERIFY_OPTIONS'],
- 'RESULT' => '<b style="color:red">' . implode('<br />', $error) . '</b>',
- ));
- }
- } // end submit
-
- foreach ($this->convert_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], ${$config_key}, $options),
- )
- );
- }
-
- $template->assign_vars(array(
- 'TITLE' => $lang['STAGE_SETTINGS'],
- 'BODY' => $lang['CONV_OPTIONS_BODY'],
- 'L_SUBMIT' => $lang['BEGIN_CONVERT'],
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=settings&amp;tag=$convertor_tag&amp;language=$language",
- ));
- }
-
- /**
- * The function which does the actual work (or dispatches it to the relevant places)
- */
- function convert_data($sub)
- {
- global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
- global $convert, $convert_row, $message_parser, $skip_rows, $language;
- global $request, $phpbb_config_php_file, $phpbb_dispatcher;
-
- extract($phpbb_config_php_file->get_all());
-
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
- require($phpbb_root_path . 'includes/functions_convert.' . $phpEx);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- // Override a couple of config variables for the duration
- $config['max_quote_depth'] = 0;
-
- // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
- $config['max_post_chars'] = $config['min_post_chars'] = 0;
-
- // Set up a user as well. We _should_ have enough of a database here at this point to do this
- // and it helps for any core code we call
- $user->session_begin();
- $user->page = $user->extract_current_page($phpbb_root_path);
-
- // This is a little bit of a fudge, but it allows the language entries to be available to the
- // core code without us loading them again
- $user->lang = &$lang;
-
- $this->page_title = $user->lang['STAGE_IN_PROGRESS'];
-
- $convert->options = array();
- if (isset($config['convert_progress']))
- {
- $convert->options = unserialize($config['convert_progress']);
- $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
- }
-
- // This information should have already been checked once, but do it again for safety
- if (empty($convert->options) || empty($convert->options['tag']) ||
- !isset($convert->options['dbms']) ||
- !isset($convert->options['dbhost']) ||
- !isset($convert->options['dbport']) ||
- !isset($convert->options['dbuser']) ||
- !isset($convert->options['dbpasswd']) ||
- !isset($convert->options['dbname']) ||
- !isset($convert->options['table_prefix']))
- {
- $this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
- }
-
- // Make some short variables accessible, for easier referencing
- $convert->convertor_tag = basename($convert->options['tag']);
- $convert->src_dbms = $convert->options['dbms'];
- $convert->src_dbhost = $convert->options['dbhost'];
- $convert->src_dbport = $convert->options['dbport'];
- $convert->src_dbuser = $convert->options['dbuser'];
- $convert->src_dbpasswd = $convert->options['dbpasswd'];
- $convert->src_dbname = $convert->options['dbname'];
- $convert->src_table_prefix = $convert->options['table_prefix'];
-
- // initiate database connection to old db if old and new db differ
- global $src_db, $same_db;
- $src_db = $same_db = null;
- if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser)
- {
- $dbms = $convert->src_dbms;
- $src_db = new $dbms();
- $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
- $same_db = false;
- }
- else
- {
- $src_db = $db;
- $same_db = true;
- }
-
- $convert->mysql_convert = false;
- switch ($src_db->sql_layer)
- {
- case 'sqlite':
- case 'sqlite3':
- $convert->src_truncate_statement = 'DELETE FROM ';
- break;
-
- // Thanks MySQL, for silently converting...
- case 'mysql':
- case 'mysql4':
- if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>='))
- {
- $convert->mysql_convert = true;
- }
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
-
- case 'mysqli':
- $convert->mysql_convert = true;
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
-
- default:
- $convert->src_truncate_statement = 'TRUNCATE TABLE ';
- break;
- }
-
- if ($convert->mysql_convert && !$same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- switch ($db->get_sql_layer())
- {
- case 'sqlite':
- case 'sqlite3':
- $convert->truncate_statement = 'DELETE FROM ';
- break;
-
- default:
- $convert->truncate_statement = 'TRUNCATE TABLE ';
- break;
- }
-
- $get_info = false;
-
- // check security implications of direct inclusion
- if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx))
- {
- $this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
- }
-
- if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx))
- {
- include('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx);
- }
-
- $get_info = true;
- include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
-
- // Map some variables...
- $convert->convertor_data = $convertor_data;
- $convert->tables = $tables;
- $convert->config_schema = $config_schema;
-
- // Now include the real data
- $get_info = false;
- include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx);
-
- $convert->convertor_data = $convertor_data;
- $convert->tables = $tables;
- $convert->config_schema = $config_schema;
- $convert->convertor = $convertor;
-
- // The test_file is a file that should be present in the location of the old board.
- if (!file_exists($convert->options['forum_path'] . '/' . $test_file))
- {
- $this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__);
- }
-
- $search_type = $config['search_type'];
-
- // For conversions we are a bit less strict and set to a search backend we know exist...
- if (!class_exists($search_type))
- {
- $search_type = '\phpbb\search\fulltext_native';
- $config->set('search_type', $search_type);
- }
-
- if (!class_exists($search_type))
- {
- trigger_error('NO_SUCH_SEARCH_MODULE');
- }
-
- $error = false;
- $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
-
- if ($error)
- {
- trigger_error($error);
- }
-
- include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
- $message_parser = new parse_message();
-
- $jump = $request->variable('jump', 0);
- $final_jump = $request->variable('final_jump', 0);
- $sync_batch = $request->variable('sync_batch', -1);
- $last_statement = $request->variable('last', 0);
-
- // We are running sync...
- if ($sync_batch >= 0)
- {
- $this->sync_forums($sync_batch);
- return;
- }
-
- if ($jump)
- {
- $this->jump($jump, $last_statement);
- return;
- }
-
- if ($final_jump)
- {
- $this->final_jump($final_jump);
- return;
- }
-
- $current_table = $request->variable('current_table', 0);
- $old_current_table = min(-1, $current_table - 1);
- $skip_rows = $request->variable('skip_rows', 0);
-
- if (!$current_table && !$skip_rows)
- {
- if (!$request->variable('confirm', false))
- {
- // If avatars / ranks / smilies folders are specified make sure they are writable
- $bad_folders = array();
-
- $local_paths = array(
- 'avatar_path' => path($config['avatar_path']),
- 'avatar_gallery_path' => path($config['avatar_gallery_path']),
- 'icons_path' => path($config['icons_path']),
- 'ranks_path' => path($config['ranks_path']),
- 'smilies_path' => path($config['smilies_path'])
- );
-
- foreach ($local_paths as $folder => $local_path)
- {
- if (isset($convert->convertor[$folder]))
- {
- if (empty($convert->convertor['test_file']))
- {
- // test_file is mandantory at the moment so this should never be reached, but just in case...
- $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
- }
-
- if (!$local_path || !$this->filesystem->is_writable($phpbb_root_path . $local_path))
- {
- if (!$local_path)
- {
- $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
- }
- else
- {
- $bad_folders[] = $local_path;
- }
- }
- }
- }
-
- if (sizeof($bad_folders))
- {
- $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
- sort($bad_folders);
- $this->p_master->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['INSTALL_TEST'],
- 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}&amp;language=$language",
- ));
- return;
- }
-
- // Grab all the tables used in convertor
- $missing_tables = $tables_list = $aliases = array();
-
- foreach ($convert->convertor['schema'] as $schema)
- {
- // Skip those not used (because of addons/plugins not detected)
- if (!$schema['target'])
- {
- continue;
- }
-
- foreach ($schema as $key => $val)
- {
- // we're dealing with an array like:
- // array('forum_status', 'forums.forum_status', 'is_item_locked')
- if (is_int($key) && !empty($val[1]))
- {
- $temp_data = $val[1];
- if (!is_array($temp_data))
- {
- $temp_data = array($temp_data);
- }
-
- foreach ($temp_data as $val)
- {
- if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $val, $m))
- {
- $table = $convert->src_table_prefix . $m[1];
- $tables_list[$table] = $table;
-
- if (!empty($m[3]))
- {
- $aliases[] = $convert->src_table_prefix . $m[3];
- }
- }
- }
- }
- // 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1'
- else if ($key == 'left_join')
- {
- // Convert the value if it wasn't an array already.
- if (!is_array($val))
- {
- $val = array($val);
- }
-
- for ($j = 0; $j < sizeof($val); ++$j)
- {
- if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m))
- {
- $table = $convert->src_table_prefix . $m[1];
- $tables_list[$table] = $table;
-
- if (!empty($m[2]))
- {
- $aliases[] = $convert->src_table_prefix . $m[2];
- }
- }
- }
- }
- }
- }
-
- // Remove aliased tables from $tables_list
- foreach ($aliases as $alias)
- {
- unset($tables_list[$alias]);
- }
-
- // Check if the tables that we need exist
- $src_db->sql_return_on_error(true);
- foreach ($tables_list as $table => $null)
- {
- $sql = 'SELECT 1 FROM ' . $table;
- $_result = $src_db->sql_query_limit($sql, 1);
-
- if (!$_result)
- {
- $missing_tables[] = $table;
- }
- $src_db->sql_freeresult($_result);
- }
- $src_db->sql_return_on_error(false);
-
- // Throw an error if some tables are missing
- // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again
-
- if (sizeof($missing_tables) == sizeof($tables_list))
- {
- $this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
- }
- else if (sizeof($missing_tables))
- {
- $this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
- }
-
- $url = $this->save_convert_progress('&amp;confirm=1');
- $msg = $user->lang['PRE_CONVERT_COMPLETE'];
-
- if ($convert->convertor_data['author_notes'])
- {
- $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
- }
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'L_MESSAGE' => $msg,
- 'U_ACTION' => $url,
- ));
-
- return;
- } // if (!$request->variable('confirm', false)))
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['STARTING_CONVERT'],
- ));
-
- // Convert the config table and load the settings of the old board
- if (!empty($convert->config_schema))
- {
- restore_config($convert->config_schema);
-
- // Override a couple of config variables for the duration
- $config['max_quote_depth'] = 0;
-
- // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
- $config['max_post_chars'] = $config['min_post_chars'] = 0;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['CONFIG_CONVERT'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- // Now process queries and execute functions that have to be executed prior to the conversion
- if (!empty($convert->convertor['execute_first']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_first']);
- // @codingStandardsIgnoreEnd
- }
-
- if (!empty($convert->convertor['query_first']))
- {
- if (!is_array($convert->convertor['query_first']))
- {
- $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
- }
- else if (!is_array($convert->convertor['query_first'][0]))
- {
- $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
- }
-
- foreach ($convert->convertor['query_first'] as $query_first)
- {
- if ($query_first[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- $src_db->sql_query($query_first[1]);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_first[1]);
- }
- }
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['PREPROCESS_STEP'],
- 'RESULT' => $user->lang['DONE'],
- ));
- } // if (!$current_table && !$skip_rows)
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['FILLING_TABLES'],
- ));
-
- // This loop takes one target table and processes it
- while ($current_table < sizeof($convert->convertor['schema']))
- {
- $schema = $convert->convertor['schema'][$current_table];
-
- // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
- if (empty($schema['target']))
- {
- $current_table++;
- continue;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target']),
- ));
-
- // This is only the case when we first start working on the tables.
- if (!$skip_rows)
- {
- // process execute_first and query_first for this table...
- if (!empty($schema['execute_first']))
- {
- // @codingStandardsIgnoreStart
- eval($schema['execute_first']);
- // @codingStandardsIgnoreEnd
- }
-
- if (!empty($schema['query_first']))
- {
- if (!is_array($schema['query_first']))
- {
- $schema['query_first'] = array('target', array($schema['query_first']));
- }
- else if (!is_array($schema['query_first'][0]))
- {
- $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
- }
-
- foreach ($schema['query_first'] as $query_first)
- {
- if ($query_first[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
- $src_db->sql_query($query_first[1]);
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_first[1]);
- }
- }
- }
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'postgres':
- $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
- break;
-
- case 'oracle':
- $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $largest_id = (int) $row['max_id'];
-
- if ($largest_id)
- {
- $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
- $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
- }
- break;
- }
- }
- }
-
- // Process execute_always for this table
- // This is for code which needs to be executed on every pass of this table if
- // it gets split because of time restrictions
- if (!empty($schema['execute_always']))
- {
- // @codingStandardsIgnoreStart
- eval($schema['execute_always']);
- // @codingStandardsIgnoreEnd
- }
-
- //
- // Set up some variables
- //
- // $waiting_rows holds rows for multirows insertion (MySQL only)
- // $src_tables holds unique tables with aliases to select from
- // $src_fields will quickly refer source fields (or aliases) corresponding to the current index
- // $select_fields holds the names of the fields to retrieve
- //
-
- $sql_data = array(
- 'source_fields' => array(),
- 'target_fields' => array(),
- 'source_tables' => array(),
- 'select_fields' => array(),
- );
-
- // This statement is building the keys for later insertion.
- $insert_query = $this->build_insert_query($schema, $sql_data, $current_table);
-
- // If no source table is affected, we skip the table
- if (empty($sql_data['source_tables']))
- {
- $skip_rows = 0;
- $current_table++;
- continue;
- }
-
- $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : '';
-
- $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']);
-
- // Where
- $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : '';
-
- // Group By
- if (!empty($schema['group_by']))
- {
- $schema['group_by'] = array($schema['group_by']);
- foreach ($sql_data['select_fields'] as $select)
- {
- $alias = strpos(strtolower($select), ' as ');
- $select = ($alias) ? substr($select, 0, $alias) : $select;
- if (!in_array($select, $schema['group_by']))
- {
- $schema['group_by'][] = $select;
- }
- }
- }
- $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : '';
-
- // Having
- $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : '';
-
- // Order By
- if (empty($schema['order_by']) && !empty($schema['primary']))
- {
- $schema['order_by'] = $schema['primary'];
- }
- $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : '';
-
- // Counting basically holds the amount of rows processed.
- $counting = -1;
- $batch_time = 0;
-
- while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time()))
- {
- $old_current_table = $current_table;
-
- $rows = '';
- $waiting_rows = array();
-
- if (!empty($batch_time))
- {
- $mtime = explode(' ', microtime());
- $mtime = $mtime[0] + $mtime[1];
- $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | ";
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => "skip_rows = $skip_rows",
- 'RESULT' => $rows . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''),
- ));
-
- $mtime = explode(' ', microtime());
- $batch_time = $mtime[0] + $mtime[1];
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- // Take skip rows into account and only fetch batch_size amount of rows
- $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
-
- // This loop processes each row
- $counting = 0;
-
- $convert->row = $convert_row = array();
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON');
- break;
- }
- }
-
- // Now handle the rows until time is over or no more rows to process...
- while ($counting === 0 || still_on_time())
- {
- $convert_row = $src_db->sql_fetchrow($___result);
-
- if (!$convert_row)
- {
- // move to the next batch or table
- break;
- }
-
- // With this we are able to always save the last state
- $convert->row = $convert_row;
-
- // Increment the counting variable, it stores the number of rows we have processed
- $counting++;
-
- $insert_values = array();
-
- $sql_flag = $this->process_row($schema, $sql_data, $insert_values);
-
- if ($sql_flag === true)
- {
- switch ($db->get_sql_layer())
- {
- // If MySQL, we'll wait to have num_wait_rows rows to submit at once
- case 'mysql':
- case 'mysql4':
- case 'mysqli':
- $waiting_rows[] = '(' . implode(', ', $insert_values) . ')';
-
- if (sizeof($waiting_rows) >= $convert->num_wait_rows)
- {
- $errored = false;
-
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
- {
- $errored = true;
- }
- $db->sql_return_on_error(false);
-
- if ($errored)
- {
- $db->sql_return_on_error(true);
-
- // Because it errored out we will try to insert the rows one by one... most of the time this
- // is caused by duplicate entries - but we also do not want to miss one...
- foreach ($waiting_rows as $waiting_sql)
- {
- if (!$db->sql_query($insert_query . $waiting_sql))
- {
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
- }
-
- $db->sql_return_on_error(false);
- }
-
- $waiting_rows = array();
- }
-
- break;
-
- default:
- $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')';
-
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_sql))
- {
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
- $db->sql_return_on_error(false);
-
- $waiting_rows = array();
-
- break;
- }
- }
-
- $skip_rows++;
- }
- $src_db->sql_freeresult($___result);
-
- // We might still have some rows waiting
- if (sizeof($waiting_rows))
- {
- $errored = false;
- $db->sql_return_on_error(true);
-
- if (!$db->sql_query($insert_query . implode(', ', $waiting_rows)))
- {
- $errored = true;
- }
- $db->sql_return_on_error(false);
-
- if ($errored)
- {
- $db->sql_return_on_error(true);
-
- // Because it errored out we will try to insert the rows one by one... most of the time this
- // is caused by duplicate entries - but we also do not want to miss one...
- foreach ($waiting_rows as $waiting_sql)
- {
- $db->sql_query($insert_query . $waiting_sql);
- $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
- }
-
- $db->sql_return_on_error(false);
- }
-
- $waiting_rows = array();
- }
-
- if (!empty($schema['autoincrement']))
- {
- switch ($db->get_sql_layer())
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF');
- break;
-
- case 'postgres':
- $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
- break;
-
- case 'oracle':
- $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $largest_id = (int) $row['max_id'];
-
- if ($largest_id)
- {
- $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
- $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
- }
- break;
- }
- }
- }
-
- // When we reach this point, either the current table has been processed or we're running out of time.
- if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG')*/)
- {
- $skip_rows = 0;
- $current_table++;
- }
- else
- {/*
- if (still_on_time() && $counting < $convert->batch_size)
- {
- $skip_rows = 0;
- $current_table++;
- }*/
-
- // Looks like we ran out of time.
- $url = $this->save_convert_progress('&amp;current_table=' . $current_table . '&amp;skip_rows=' . $skip_rows);
-
- $current_table++;
-// $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows));
-
- $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema']));
-
- $template->assign_vars(array(
- 'L_MESSAGE' => $msg,
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
-
- // Process execute_last then we'll be done
- $url = $this->save_convert_progress('&amp;jump=1');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['FINAL_STEP'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * Sync function being executed at the middle, some functions need to be executed after a successful sync.
- */
- function sync_forums($sync_batch)
- {
- global $template, $user, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['SYNC_TOPICS'],
- ));
-
- $batch_size = $convert->batch_size;
-
- $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value
- FROM ' . TOPICS_TABLE;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // Set values of minimum/maximum primary value for this table.
- $primary_min = $row['min_value'];
- $primary_max = $row['max_value'];
-
- if ($sync_batch == 0)
- {
- $sync_batch = (int) $primary_min;
- }
-
- if ($sync_batch == 0)
- {
- $sync_batch = 1;
- }
-
- // Fetch a batch of rows, process and insert them.
- while ($sync_batch <= $primary_max && still_on_time())
- {
- $end = ($sync_batch + $batch_size - 1);
-
- // Sync all topics in batch mode...
- sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''),
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $sync_batch += $batch_size;
- }
-
- if ($sync_batch >= $primary_max)
- {
- $url = $this->save_convert_progress('&amp;final_jump=1');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- else
- {
- $sync_batch--;
- }
-
- $url = $this->save_convert_progress('&amp;sync_batch=' . $sync_batch);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * Save the convertor status
- */
- function save_convert_progress($step)
- {
- global $config, $convert, $language;
-
- // Save convertor Status
- $config->set('convert_progress', serialize(array(
- 'step' => $step,
- 'table_prefix' => $convert->src_table_prefix,
- 'tag' => $convert->convertor_tag,
- )), false);
-
- $config->set('convert_db_server', serialize(array(
- 'dbms' => $convert->src_dbms,
- 'dbhost' => $convert->src_dbhost,
- 'dbport' => $convert->src_dbport,
- 'dbname' => $convert->src_dbname,
- )), false);
-
- $config->set('convert_db_user', serialize(array(
- 'dbuser' => $convert->src_dbuser,
- 'dbpasswd' => $convert->src_dbpasswd,
- )), false);
-
- return $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}$step&amp;language=$language";
- }
-
- /**
- * Finish conversion, the last function to be called.
- */
- function finish_conversion()
- {
- global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user, $template;
- global $cache, $auth, $phpbb_container, $phpbb_log;
-
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . "
- WHERE config_name = 'convert_progress'
- OR config_name = 'convert_options'
- OR config_name = 'convert_db_server'
- OR config_name = 'convert_db_user'");
- $db->sql_query('DELETE FROM ' . SESSIONS_TABLE);
-
- @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx);
- phpbb_cache_moderators($db, $cache, $auth);
-
- // And finally, add a note to the log
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_CONVERTED', false, array($convert->convertor_data['forum_name'], $config['version']));
-
- $url = $this->p_master->module_url . "?mode={$this->mode}&amp;sub=final&amp;language=$language";
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['FINAL_STEP'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- /**
- * This function marks the steps after syncing
- */
- function final_jump($final_jump)
- {
- global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['PROCESS_LAST'],
- ));
-
- if ($final_jump == 1)
- {
- $db->sql_return_on_error(true);
-
- update_topics_posted();
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- if ($db->get_sql_error_triggered())
- {
- $template->assign_vars(array(
- 'S_ERROR_BOX' => true,
- 'ERROR_TITLE' => $user->lang['UPDATE_TOPICS_POSTED'],
- 'ERROR_MSG' => $user->lang['UPDATE_TOPICS_POSTED_ERR'],
- ));
- }
- $db->sql_return_on_error(false);
-
- $this->finish_conversion();
- return;
- }
- }
-
- /**
- * This function marks the steps before syncing (jump=1)
- */
- function jump($jump, $last_statement)
- {
- global $template, $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache;
- global $convert;
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $user->lang['PROCESS_LAST'],
- ));
-
- if ($jump == 1)
- {
- // Execute 'last' statements/queries
- if (!empty($convert->convertor['execute_last']))
- {
- if (!is_array($convert->convertor['execute_last']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_last']);
- // @codingStandardsIgnoreEnd
- }
- else
- {
- while ($last_statement < sizeof($convert->convertor['execute_last']))
- {
- // @codingStandardsIgnoreStart
- eval($convert->convertor['execute_last'][$last_statement]);
- // @codingStandardsIgnoreEnd
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $convert->convertor['execute_last'][$last_statement],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $last_statement++;
- $url = $this->save_convert_progress('&amp;jump=1&amp;last=' . $last_statement);
-
- $percentage = ($last_statement == 0) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement));
- $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($convert->convertor['execute_last']), $percentage);
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_LAST'],
- 'L_MESSAGE' => $msg,
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
- }
-
- if (!empty($convert->convertor['query_last']))
- {
- if (!is_array($convert->convertor['query_last']))
- {
- $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last']));
- }
- else if (!is_array($convert->convertor['query_last'][0]))
- {
- $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1]));
- }
-
- foreach ($convert->convertor['query_last'] as $query_last)
- {
- if ($query_last[0] == 'src')
- {
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'binary'");
- }
-
- $src_db->sql_query($query_last[1]);
-
- if ($convert->mysql_convert && $same_db)
- {
- $src_db->sql_query("SET NAMES 'utf8'");
- }
- }
- else
- {
- $db->sql_query($query_last[1]);
- }
- }
- }
-
- // Sanity check
- $db->sql_return_on_error(false);
- $src_db->sql_return_on_error(false);
-
- fix_empty_primary_groups();
-
- $sql = 'SELECT MIN(user_regdate) AS board_startdate
- FROM ' . USERS_TABLE;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0))
- {
- $config->set('board_startdate', $row['board_startdate']);
- $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS);
- }
-
- update_dynamic_config();
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['CLEAN_VERIFY'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- $url = $this->save_convert_progress('&amp;jump=2');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
-
- if ($jump == 2)
- {
- $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''");
-
- // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics.
- // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing)
- sync('forum', '', '', false, true);
- $cache->destroy('sql', FORUMS_TABLE);
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $user->lang['SYNC_FORUMS'],
- 'RESULT' => $user->lang['DONE'],
- ));
-
- // Continue with synchronizing the forums...
- $url = $this->save_convert_progress('&amp;sync_batch=0');
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'],
- 'U_ACTION' => $url,
- ));
-
- $this->meta_refresh($url);
- return;
- }
- }
-
- function build_insert_query(&$schema, &$sql_data, $current_table)
- {
- global $db, $user;
- global $convert;
-
- // Can we use IGNORE with this DBMS?
- $sql_ignore = (strpos($db->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? 'IGNORE ' : '';
- $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' (';
-
- $aliases = array();
-
- $sql_data = array(
- 'source_fields' => array(),
- 'target_fields' => array(),
- 'source_tables' => array(),
- 'select_fields' => array(),
- );
-
- foreach ($schema as $key => $val)
- {
- // Example: array('group_name', 'extension_groups.group_name', 'htmlspecialchars'),
- if (is_int($key))
- {
- if (!empty($val[0]))
- {
- // Target fields
- $sql_data['target_fields'][$val[0]] = $key;
- $insert_query .= $val[0] . ', ';
- }
-
- if (!is_array($val[1]))
- {
- $val[1] = array($val[1]);
- }
-
- foreach ($val[1] as $valkey => $value_1)
- {
- // This should cover about any case:
- //
- // table.field => SELECT table.field FROM table
- // table.field AS alias => SELECT table.field AS alias FROM table
- // table.field AS table2.alias => SELECT table2.field AS alias FROM table table2
- // table.field AS table2.field => SELECT table2.field FROM table table2
- //
- if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m))
- {
- // There is 'AS ...' in the field names
- if (!empty($m[3]))
- {
- $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6];
-
- // Table alias: store it then replace the source table with it
- if (!empty($m[5]) && $m[5] != $m[1])
- {
- $aliases[$m[5]] = $m[1];
- $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1);
- }
- }
- else
- {
- // No table alias
- $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1];
- }
-
- $sql_data['select_fields'][$value_1] = $value_1;
- $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2];
- }
- }
- }
- else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having')
- {
- if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m))
- {
- foreach ($m[1] as $value)
- {
- $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value;
- }
- }
- }
- }
-
- // Add the aliases to the list of tables
- foreach ($aliases as $alias => $table)
- {
- $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias;
- }
-
- // 'left_join' => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id',
- if (!empty($schema['left_join']))
- {
- if (!is_array($schema['left_join']))
- {
- $schema['left_join'] = array($schema['left_join']);
- }
-
- foreach ($schema['left_join'] as $left_join)
- {
- // This won't handle concatened LEFT JOINs
- if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m))
- {
- $this->p_master->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__);
- }
-
- if (!empty($aliases[$m[2]]))
- {
- if (!empty($m[3]))
- {
- $this->p_master->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__);
- }
-
- $m[2] = $aliases[$m[2]];
- $m[3] = $m[2];
- }
-
- $right_table = $convert->src_table_prefix . $m[2];
- if (!empty($m[3]))
- {
- unset($sql_data['source_tables'][$m[3]]);
- }
- else if ($m[2] != $m[1])
- {
- unset($sql_data['source_tables'][$m[2]]);
- }
-
- if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false)
- {
- $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table";
- }
- else
- {
- $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table";
- }
-
- if (!empty($m[3]))
- {
- unset($sql_data['source_tables'][$m[3]]);
- $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3];
- }
- else if (!empty($convert->src_table_prefix))
- {
- $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2];
- }
- $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5];
- }
- }
-
- // Remove ", " from the end of the insert query
- $insert_query = substr($insert_query, 0, -2) . ') VALUES ';
-
- return $insert_query;
- }
-
- /**
- * Function for processing the currently handled row
- */
- function process_row(&$schema, &$sql_data, &$insert_values)
- {
- global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache;
- global $convert, $convert_row;
-
- $sql_flag = false;
-
- foreach ($schema as $key => $fields)
- {
- // We are only interested in the lines with:
- // array('comment', 'attachments_desc.comment', 'htmlspecialchars'),
- if (is_int($key))
- {
- if (!is_array($fields[1]))
- {
- $fields[1] = array($fields[1]);
- }
-
- $firstkey_set = false;
- $firstkey = 0;
-
- foreach ($fields[1] as $inner_key => $inner_value)
- {
- if (!$firstkey_set)
- {
- $firstkey = $inner_key;
- $firstkey_set = true;
- }
-
- $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : '';
-
- if (!empty($src_field))
- {
- $fields[1][$inner_key] = $convert->row[$src_field];
- }
- }
-
- if (!empty($fields[0]))
- {
- // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE.
- // If a function has already set it to FALSE it won't change it.
- if ($sql_flag === false)
- {
- $sql_flag = true;
- }
-
- // No function assigned?
- if (empty($fields[2]))
- {
- $value = $fields[1][$firstkey];
- }
- else if (is_array($fields[2]) && !is_callable($fields[2]))
- {
- // Execute complex function/eval/typecast
- $value = $fields[1];
-
- foreach ($fields[2] as $type => $execution)
- {
- if (strpos($type, 'typecast') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
- $value = $value[0];
- settype($value, $execution);
- }
- else if (strpos($type, 'function') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $value = call_user_func_array($execution, $value);
- }
- else if (strpos($type, 'execute') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $execution = str_replace('{RESULT}', '$value', $execution);
- $execution = str_replace('{VALUE}', '$value', $execution);
- // @codingStandardsIgnoreStart
- eval($execution);
- // @codingStandardsIgnoreEnd
- }
- }
- }
- else
- {
- $value = call_user_func_array($fields[2], $fields[1]);
- }
-
- if (is_null($value))
- {
- $value = '';
- }
-
- $insert_values[] = $db->_sql_validate_value($value);
- }
- else if (!empty($fields[2]))
- {
- if (is_array($fields[2]))
- {
- // Execute complex function/eval/typecast
- $value = '';
-
- foreach ($fields[2] as $type => $execution)
- {
- if (strpos($type, 'typecast') === 0)
- {
- $value = settype($value, $execution);
- }
- else if (strpos($type, 'function') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $value = call_user_func_array($execution, $value);
- }
- else if (strpos($type, 'execute') === 0)
- {
- if (!is_array($value))
- {
- $value = array($value);
- }
-
- $execution = str_replace('{RESULT}', '$value', $execution);
- $execution = str_replace('{VALUE}', '$value', $execution);
- // @codingStandardsIgnoreStart
- eval($execution);
- // @codingStandardsIgnoreEnd
- }
- }
- }
- else
- {
- call_user_func_array($fields[2], $fields[1]);
- }
- }
- }
- }
-
- return $sql_flag;
- }
-
- /**
- * Own meta refresh function to be able to change the global time used
- */
- function meta_refresh($url)
- {
- global $convert, $template;
-
- if ($convert->options['refresh'])
- {
- // Because we should not rely on correct settings, we simply use the relative path here directly.
- $template->assign_vars(array(
- 'S_REFRESH' => true,
- 'META' => '<meta http-equiv="refresh" content="5; url=' . $url . '" />')
- );
- }
- }
-
- /**
- * The information below will be used to build the input fields presented to the user
- */
- var $convert_options = array(
- 'legend1' => 'SPECIFY_OPTIONS',
- 'src_dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\', true)', 'explain' => false),
- 'src_dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
- 'src_dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
- 'src_dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
- 'src_dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
- 'src_dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
- 'src_table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => false),
- //'src_url' => array('lang' => 'FORUM_ADDRESS', 'type' => 'text:50:100', 'explain' => true),
- 'forum_path' => array('lang' => 'FORUM_PATH', 'type' => 'text:25:100', 'explain' => true),
- 'refresh' => array('lang' => 'REFRESH_PAGE', 'type' => 'radio:yes_no', 'explain' => true),
- );
-}
diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php
deleted file mode 100644
index da6dcb085e..0000000000
--- a/phpBB/install/install_install.php
+++ /dev/null
@@ -1,2368 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-*/
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- // If phpBB is already installed we do not include this module
- if (phpbb_check_installation_exists($phpbb_root_path, $phpEx) && !file_exists($phpbb_root_path . 'cache/install_lock'))
- {
- return;
- }
-
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'INSTALL',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 10,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'REQUIREMENTS', 'DATABASE', 'ADMINISTRATOR', 'CONFIG_FILE', 'ADVANCED', 'CREATE_TABLE', 'FINAL'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Installation
-*/
-class install_install extends module
-{
- /**
- * @var \phpbb\filesystem\filesystem_interface
- */
- protected $filesystem;
-
- function install_install(&$p_master)
- {
- $this->p_master = &$p_master;
- $this->filesystem = new \phpbb\filesystem\filesystem();
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $language, $phpbb_root_path, $phpEx;
- global $phpbb_container, $cache, $phpbb_log, $request, $phpbb_config_php_file;
-
- switch ($sub)
- {
- case 'intro':
- $phpbb_container->get('cache.driver')->purge();
-
- $this->page_title = $lang['SUB_INTRO'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['INSTALL_INTRO'],
- 'BODY' => $lang['INSTALL_INTRO_BODY'],
- 'L_SUBMIT' => $lang['NEXT_STEP'],
- 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language",
- ));
-
- break;
-
- case 'requirements':
- $this->check_server_requirements($mode, $sub);
-
- break;
-
- case 'database':
- $this->obtain_database_settings($mode, $sub);
-
- break;
-
- case 'administrator':
- $this->obtain_admin_settings($mode, $sub);
-
- break;
-
- case 'config_file':
- $this->create_config_file($mode, $sub);
-
- break;
-
- case 'advanced':
- $this->obtain_advanced_settings($mode, $sub);
-
- break;
-
- case 'create_table':
- $this->load_schema($mode, $sub);
- break;
-
- case 'final':
- // Enable super globals to prevent issues with the new \phpbb\request\request object
- $request->enable_super_globals();
-
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder->with_config($phpbb_config_php_file)->get_container();
-
- // Sets the global variables
- /* @var $cache \phpbb\cache\service */
- $cache = $phpbb_container->get('cache');
-
- /* @var $phpbb_log \phpbb\log\log_interface */
- $phpbb_log = $phpbb_container->get('log');
-
- $this->build_search_index($mode, $sub);
- $this->add_modules($mode, $sub);
- $this->add_language($mode, $sub);
- $this->add_bots($mode, $sub);
- $this->email_admin($mode, $sub);
- $this->disable_avatars_if_unwritable();
- $this->populate_migrations($phpbb_container->get('ext.manager'), $phpbb_container->get('migrator'));
-
- // Remove the lock file
- @unlink($phpbb_root_path . 'cache/install_lock');
-
- break;
- }
-
- $this->tpl_name = 'install_install';
- }
-
- /**
- * Checks that the server we are installing on meets the requirements for running phpBB
- */
- function check_server_requirements($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx, $language;
-
- $this->page_title = $lang['STAGE_REQUIREMENTS'];
-
- $template->assign_vars(array(
- 'TITLE' => $lang['REQUIREMENTS_TITLE'],
- 'BODY' => $lang['REQUIREMENTS_EXPLAIN'],
- ));
-
- $passed = array('php' => false, 'db' => false, 'files' => false, 'pcre' => false, 'imagesize' => false, 'json' => false,);
-
- // Test for basic PHP settings
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_SETTINGS'],
- 'LEGEND_EXPLAIN' => $lang['PHP_SETTINGS_EXPLAIN'],
- ));
-
- // Test the minimum PHP version
- $php_version = PHP_VERSION;
-
- if (version_compare($php_version, '5.4') < 0)
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
- else
- {
- $passed['php'] = true;
-
- // We also give feedback on whether we're running in safe mode
- $result = '<strong style="color:green">' . $lang['YES'];
- if (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) == 'on')
- {
- $result .= ', ' . $lang['PHP_SAFE_MODE'];
- }
- $result .= '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_VERSION_REQD'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
-
- // Don't check for register_globals on 5.4+
- if (version_compare($php_version, '5.4.0-dev') < 0)
- {
- // Check for register_globals being enabled
- if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on')
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_REGISTER_GLOBALS'],
- 'TITLE_EXPLAIN' => $lang['PHP_REGISTER_GLOBALS_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
- }
-
- // Check for url_fopen
- if (@ini_get('allow_url_fopen') == '1' || strtolower(@ini_get('allow_url_fopen')) == 'on')
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_URL_FOPEN_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_URL_FOPEN_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for getimagesize
- if (@function_exists('getimagesize'))
- {
- $passed['imagesize'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_GETIMAGESIZE_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for PCRE UTF-8 support
- if (@preg_match('//u', ''))
- {
- $passed['pcre'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PCRE_UTF_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PCRE_UTF_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- // Check for php json support
- if (@extension_loaded('json'))
- {
- $passed['json'] = true;
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- else
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['PHP_JSON_SUPPORT'],
- 'TITLE_EXPLAIN' => $lang['PHP_JSON_SUPPORT_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
-
- $passed['mbstring'] = true;
- if (@extension_loaded('mbstring'))
- {
- // Test for available database modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['MBSTRING_CHECK'],
- 'LEGEND_EXPLAIN' => $lang['MBSTRING_CHECK_EXPLAIN'],
- ));
-
- $checks = array(
- array('func_overload', '&', MB_OVERLOAD_MAIL|MB_OVERLOAD_STRING),
- array('encoding_translation', '!=', 0),
- array('http_input', '!=', array('pass', '')),
- array('http_output', '!=', array('pass', ''))
- );
-
- foreach ($checks as $mb_checks)
- {
- $ini_val = @ini_get('mbstring.' . $mb_checks[0]);
- switch ($mb_checks[1])
- {
- case '&':
- if (intval($ini_val) & $mb_checks[2])
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- $passed['mbstring'] = false;
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- break;
-
- case '!=':
- if (!is_array($mb_checks[2]) && $ini_val != $mb_checks[2] ||
- is_array($mb_checks[2]) && !in_array($ini_val, $mb_checks[2]))
- {
- $result = '<strong style="color:red">' . $lang['NO'] . '</strong>';
- $passed['mbstring'] = false;
- }
- else
- {
- $result = '<strong style="color:green">' . $lang['YES'] . '</strong>';
- }
- break;
- }
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['MBSTRING_' . strtoupper($mb_checks[0])],
- 'TITLE_EXPLAIN' => $lang['MBSTRING_' . strtoupper($mb_checks[0]) . '_EXPLAIN'],
- 'RESULT' => $result,
-
- 'S_EXPLAIN' => true,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- // Test for available database modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_SUPPORTED_DB'],
- 'LEGEND_EXPLAIN' => $lang['PHP_SUPPORTED_DB_EXPLAIN'],
- ));
-
- $available_dbms = get_available_dbms(false, true);
- $passed['db'] = $available_dbms['ANY_DB_SUPPORT'];
- unset($available_dbms['ANY_DB_SUPPORT']);
-
- foreach ($available_dbms as $db_name => $db_ary)
- {
- if (!$db_ary['AVAILABLE'])
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
- 'RESULT' => '<span style="color:red">' . $lang['UNAVAILABLE'] . '</span>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($db_name)],
- 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- // Test for other modules
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['PHP_OPTIONAL_MODULE'],
- 'LEGEND_EXPLAIN' => $lang['PHP_OPTIONAL_MODULE_EXPLAIN'],
- ));
-
- foreach ($this->php_dlls_other as $dll)
- {
- if (!@extension_loaded($dll))
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($dll)],
- 'RESULT' => '<strong style="color:red">' . $lang['UNAVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- continue;
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DLL_' . strtoupper($dll)],
- 'RESULT' => '<strong style="color:green">' . $lang['AVAILABLE'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // Can we find Imagemagick anywhere on the system?
- $exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : '';
-
- $magic_home = getenv('MAGICK_HOME');
- $img_imagick = '';
- if (empty($magic_home))
- {
- $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/');
- $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH'))));
-
- $locations = array_merge($path_locations, $locations);
- foreach ($locations as $location)
- {
- // The path might not end properly, fudge it
- if (substr($location, -1, 1) !== '/')
- {
- $location .= '/';
- }
-
- if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000)
- {
- $img_imagick = str_replace('\\', '/', $location);
- continue;
- }
- }
- }
- else
- {
- $img_imagick = str_replace('\\', '/', $magic_home);
- }
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['APP_MAGICK'],
- 'RESULT' => ($img_imagick) ? '<strong style="color:green">' . $lang['AVAILABLE'] . ', ' . $img_imagick . '</strong>' : '<strong style="color:blue">' . $lang['NO_LOCATION'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
-
- // Check permissions on files/directories we need access to
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['FILES_REQUIRED'],
- 'LEGEND_EXPLAIN' => $lang['FILES_REQUIRED_EXPLAIN'],
- ));
-
- $directories = array('cache/', 'files/', 'store/');
-
- umask(0);
-
- $passed['files'] = true;
- foreach ($directories as $dir)
- {
- $exists = $write = false;
-
- // Try to create the directory if it does not exist
- if (!file_exists($phpbb_root_path . $dir))
- {
- @mkdir($phpbb_root_path . $dir, 0777);
-
- try
- {
- $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
- }
- catch (\phpbb\filesystem\exception\filesystem_exception $e)
- {
- // Do nothing
- }
- }
-
- // Now really check
- if (file_exists($phpbb_root_path . $dir) && is_dir($phpbb_root_path . $dir))
- {
- try
- {
- $this->filesystem->phpbb_chmod($phpbb_root_path . $dir, CHMOD_READ | CHMOD_WRITE);
- }
- catch (\phpbb\filesystem\exception\filesystem_exception $e)
- {
- // Do nothing
- }
-
- $exists = true;
- }
-
- // Now check if it is writable by storing a simple file
- $fp = @fopen($phpbb_root_path . $dir . 'test_lock', 'wb');
- if ($fp !== false)
- {
- $write = true;
- }
- @fclose($fp);
-
- @unlink($phpbb_root_path . $dir . 'test_lock');
-
- $passed['files'] = ($exists && $write && $passed['files']) ? true : false;
-
- $exists = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
- $write = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $dir,
- 'RESULT' => $exists . $write,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // Check permissions on files/directories it would be useful access to
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['FILES_OPTIONAL'],
- 'LEGEND_EXPLAIN' => $lang['FILES_OPTIONAL_EXPLAIN'],
- ));
-
- $directories = array('config.' . $phpEx, 'images/avatars/upload/');
-
- foreach ($directories as $dir)
- {
- $write = $exists = true;
- if (file_exists($phpbb_root_path . $dir))
- {
- if (!$this->filesystem->is_writable($phpbb_root_path . $dir))
- {
- $write = false;
- }
- }
- else
- {
- $write = $exists = false;
- }
-
- $exists_str = ($exists) ? '<strong style="color:green">' . $lang['FOUND'] . '</strong>' : '<strong style="color:red">' . $lang['NOT_FOUND'] . '</strong>';
- $write_str = ($write) ? ', <strong style="color:green">' . $lang['WRITABLE'] . '</strong>' : (($exists) ? ', <strong style="color:red">' . $lang['UNWRITABLE'] . '</strong>' : '');
-
- $template->assign_block_vars('checks', array(
- 'TITLE' => $dir,
- 'RESULT' => $exists_str . $write_str,
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
-
- // And finally where do we want to go next (well today is taken isn't it :P)
- $s_hidden_fields = ($img_imagick) ? '<input type="hidden" name="img_imagick" value="' . addslashes($img_imagick) . '" />' : '';
-
- $url = (!in_array(false, $passed)) ? $this->p_master->module_url . "?mode=$mode&amp;sub=database&amp;language=$language" : $this->p_master->module_url . "?mode=$mode&amp;sub=requirements&amp;language=$language ";
- $submit = (!in_array(false, $passed)) ? $lang['INSTALL_START'] : $lang['INSTALL_TEST'];
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Obtain the information required to connect to the database
- */
- function obtain_database_settings($mode, $sub)
- {
- global $lang, $template, $phpEx;
-
- $this->page_title = $lang['STAGE_DATABASE'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- $connect_test = false;
- $error = array();
- $available_dbms = get_available_dbms(false, true);
-
- // Has the user opted to test the connection?
- if (isset($_POST['testdb']))
- {
- if (!isset($available_dbms[$data['dbms']]) || !$available_dbms[$data['dbms']]['AVAILABLE'])
- {
- $error[] = $lang['INST_ERR_NO_DB'];
- $connect_test = false;
- }
- else if (!preg_match(get_preg_expression('table_prefix'), $data['table_prefix']))
- {
- $error[] = $lang['INST_ERR_DB_INVALID_PREFIX'];
- $connect_test = false;
- }
- else
- {
- $connect_test = connect_check_db(true, $error, $available_dbms[$data['dbms']], $data['table_prefix'], $data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport']);
- }
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['DB_CONNECTION'],
- 'LEGEND_EXPLAIN' => false,
- ));
-
- if ($connect_test)
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DB_TEST'],
- 'RESULT' => '<strong style="color:green">' . $lang['SUCCESSFUL_CONNECT'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['DB_TEST'],
- 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- if (!$connect_test)
- {
- // Update the list of available DBMS modules to only contain those which can be used
- $available_dbms_temp = array();
- foreach ($available_dbms as $type => $dbms_ary)
- {
- if (!$dbms_ary['AVAILABLE'])
- {
- continue;
- }
-
- $available_dbms_temp[$type] = $dbms_ary;
- }
-
- $available_dbms = &$available_dbms_temp;
-
- // And now for the main part of this page
- $data['table_prefix'] = (!empty($data['table_prefix']) ? $data['table_prefix'] : 'phpbb_');
-
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
- }
-
- // And finally where do we want to go next (well today is taken isn't it :P)
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
- if ($connect_test)
- {
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
- }
-
- $url = ($connect_test) ? $this->p_master->module_url . "?mode=$mode&amp;sub=administrator" : $this->p_master->module_url . "?mode=$mode&amp;sub=database";
- $s_hidden_fields .= ($connect_test) ? '' : '<input type="hidden" name="testdb" value="true" />';
-
- $submit = $lang['NEXT_STEP'];
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Obtain the administrator's name, password and email address
- */
- function obtain_admin_settings($mode, $sub)
- {
- global $lang, $template, $phpEx;
-
- $this->page_title = $lang['STAGE_ADMINISTRATOR'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $passed = false;
-
- $data['default_lang'] = ($data['default_lang'] !== '') ? $data['default_lang'] : $data['language'];
-
- if (isset($_POST['check']))
- {
- $error = array();
-
- // Check the entered email address and password
- if ($data['admin_name'] == '' || $data['admin_pass1'] == '' || $data['admin_pass2'] == '' || $data['board_email'] == '')
- {
- $error[] = $lang['INST_ERR_MISSING_DATA'];
- }
-
- if ($data['admin_pass1'] != $data['admin_pass2'] && $data['admin_pass1'] != '')
- {
- $error[] = $lang['INST_ERR_PASSWORD_MISMATCH'];
- }
-
- // Test against the default username rules
- if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) < 3)
- {
- $error[] = $lang['INST_ERR_USER_TOO_SHORT'];
- }
-
- if ($data['admin_name'] != '' && utf8_strlen($data['admin_name']) > 20)
- {
- $error[] = $lang['INST_ERR_USER_TOO_LONG'];
- }
-
- // Test against the default password rules
- if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) < 6)
- {
- $error[] = $lang['INST_ERR_PASSWORD_TOO_SHORT'];
- }
-
- if ($data['admin_pass1'] != '' && utf8_strlen($data['admin_pass1']) > 30)
- {
- $error[] = $lang['INST_ERR_PASSWORD_TOO_LONG'];
- }
-
- if ($data['board_email'] != '' && !preg_match('/^' . get_preg_expression('email') . '$/i', $data['board_email']))
- {
- $error[] = $lang['INST_ERR_EMAIL_INVALID'];
- }
-
- $template->assign_block_vars('checks', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang['STAGE_ADMINISTRATOR'],
- 'LEGEND_EXPLAIN' => false,
- ));
-
- if (!sizeof($error))
- {
- $passed = true;
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['ADMIN_TEST'],
- 'RESULT' => '<strong style="color:green">' . $lang['TESTS_PASSED'] . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- else
- {
- $template->assign_block_vars('checks', array(
- 'TITLE' => $lang['ADMIN_TEST'],
- 'RESULT' => '<strong style="color:red">' . implode('<br />', $error) . '</strong>',
-
- 'S_EXPLAIN' => false,
- 'S_LEGEND' => false,
- ));
- }
- }
-
- if (!$passed)
- {
- foreach ($this->admin_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
- }
- else
- {
- foreach ($this->admin_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
- }
-
- $s_hidden_fields .= ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
-
- foreach ($this->db_config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = ($passed) ? $this->p_master->module_url . "?mode=$mode&amp;sub=config_file" : $this->p_master->module_url . "?mode=$mode&amp;sub=administrator";
- $s_hidden_fields .= ($passed) ? '' : '<input type="hidden" name="check" value="true" />';
-
- $template->assign_vars(array(
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Writes the config file to disk, or if unable to do so offers alternative methods
- */
- function create_config_file($mode, $sub)
- {
- global $lang, $template, $phpbb_root_path, $phpEx;
-
- $this->page_title = $lang['STAGE_CONFIG_FILE'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
- $written = false;
-
- // Create a list of any PHP modules we wish to have loaded
- $available_dbms = get_available_dbms($data['dbms']);
-
- // Create a lock file to indicate that there is an install in progress
- $fp = @fopen($phpbb_root_path . 'cache/install_lock', 'wb');
- if ($fp === false)
- {
- // We were unable to create the lock file - abort
- $this->p_master->error($lang['UNABLE_WRITE_LOCK'], __LINE__, __FILE__);
- }
- @fclose($fp);
-
- @chmod($phpbb_root_path . 'cache/install_lock', 0777);
-
- // Time to convert the data provided into a config file
- $config_data = phpbb_create_config_file_data($data, $available_dbms[$data['dbms']]['DRIVER']);
-
- // Attempt to write out the config file directly. If it works, this is the easiest way to do it ...
- if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && $this->filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) || $this->filesystem->is_writable($phpbb_root_path))
- {
- // Assume it will work ... if nothing goes wrong below
- $written = true;
-
- if (!($fp = @fopen($phpbb_root_path . 'config.' . $phpEx, 'w')))
- {
- // Something went wrong ... so let's try another method
- $written = false;
- }
-
- if (!(@fwrite($fp, $config_data)))
- {
- // Something went wrong ... so let's try another method
- $written = false;
- }
-
- @fclose($fp);
-
- if ($written)
- {
- // We may revert back to chmod() if we see problems with users not able to change their config.php file directly
- try
- {
- $this->filesystem->phpbb_chmod($phpbb_root_path . 'config.' . $phpEx, CHMOD_READ);
- }
- catch (\phpbb\filesystem\exception\filesystem_exception $e)
- {
- // Do nothing
- }
- }
- }
-
- if (isset($_POST['dldone']))
- {
- // Do a basic check to make sure that the file has been uploaded
- // Note that all we check is that the file has _something_ in it
- // We don't compare the contents exactly - if they can't upload
- // a single file correctly, it's likely they will have other problems....
- if (filesize($phpbb_root_path . 'config.' . $phpEx) > 10)
- {
- $written = true;
- }
- }
-
- $config_options = array_merge($this->db_config_options, $this->admin_config_options);
-
- foreach ($config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- if (!$written)
- {
- // OK, so it didn't work let's try the alternatives
-
- if (isset($_POST['dlconfig']))
- {
- // They want a copy of the file to download, so send the relevant headers and dump out the data
- header("Content-Type: text/x-delimtext; name=\"config.$phpEx\"");
- header("Content-disposition: attachment; filename=config.$phpEx");
- echo $config_data;
- exit;
- }
-
- // The option to download the config file is always available, so output it here
- $template->assign_vars(array(
- 'BODY' => $lang['CONFIG_FILE_UNABLE_WRITE'],
- 'L_DL_CONFIG' => $lang['DL_CONFIG'],
- 'L_DL_CONFIG_EXPLAIN' => $lang['DL_CONFIG_EXPLAIN'],
- 'L_DL_DONE' => $lang['DONE'],
- 'L_DL_DOWNLOAD' => $lang['DL_DOWNLOAD'],
- 'S_HIDDEN' => $s_hidden_fields,
- 'S_SHOW_DOWNLOAD' => true,
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=config_file",
- ));
- return;
- }
- else
- {
- $template->assign_vars(array(
- 'BODY' => $lang['CONFIG_FILE_WRITTEN'],
- 'L_SUBMIT' => $lang['NEXT_STEP'],
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $this->p_master->module_url . "?mode=$mode&amp;sub=advanced",
- ));
- return;
- }
- }
-
- /**
- * Provide an opportunity to customise some advanced settings during the install
- * in case it is necessary for them to be set to access later
- */
- function obtain_advanced_settings($mode, $sub)
- {
- global $lang, $template, $phpEx, $request;
-
- $this->page_title = $lang['STAGE_ADVANCED'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $s_hidden_fields = ($data['img_imagick']) ? '<input type="hidden" name="img_imagick" value="' . addslashes($data['img_imagick']) . '" />' : '';
- $s_hidden_fields .= '<input type="hidden" name="language" value="' . $data['language'] . '" />';
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
-
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') !== false)
- {
- $server_name = substr($server_name, 0, strpos($server_name, ':'));
- }
-
- $data['email_enable'] = ($data['email_enable'] !== '') ? $data['email_enable'] : true;
- $data['server_name'] = ($data['server_name'] !== '') ? $data['server_name'] : $server_name;
- $data['server_port'] = ($data['server_port'] !== '') ? $data['server_port'] : $request->server('SERVER_PORT', 0);
- $data['server_protocol'] = ($data['server_protocol'] !== '') ? $data['server_protocol'] : ($request->is_secure() ? 'https://' : 'http://');
- $data['cookie_secure'] = ($data['cookie_secure'] !== '') ? $data['cookie_secure'] : $request->is_secure();
-
- if ($data['script_path'] === '')
- {
- $name = htmlspecialchars_decode($request->server('PHP_SELF'));
- if (!$name)
- {
- $name = htmlspecialchars_decode($request->server('REQUEST_URI'));
- }
-
- // Replace backslashes and doubled slashes (could happen on some proxy setups)
- $name = str_replace(array('\\', '//'), '/', $name);
- $data['script_path'] = trim(dirname(dirname($name)));
- }
-
- foreach ($this->advanced_config_options as $config_key => $vars)
- {
- if (!is_array($vars) && strpos($config_key, 'legend') === false)
- {
- continue;
- }
-
- if (strpos($config_key, 'legend') !== false)
- {
- $template->assign_block_vars('options', array(
- 'S_LEGEND' => true,
- 'LEGEND' => $lang[$vars])
- );
-
- continue;
- }
-
- $options = isset($vars['options']) ? $vars['options'] : '';
-
- $template->assign_block_vars('options', array(
- 'KEY' => $config_key,
- 'TITLE' => $lang[$vars['lang']],
- 'S_EXPLAIN' => $vars['explain'],
- 'S_LEGEND' => false,
- 'TITLE_EXPLAIN' => ($vars['explain']) ? $lang[$vars['lang'] . '_EXPLAIN'] : '',
- 'CONTENT' => $this->p_master->input_field($config_key, $vars['type'], $data[$config_key], $options),
- )
- );
- }
-
- $config_options = array_merge($this->db_config_options, $this->admin_config_options);
- foreach ($config_options as $config_key => $vars)
- {
- if (!is_array($vars))
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="' . $config_key . '" value="' . $data[$config_key] . '" />';
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = $this->p_master->module_url . "?mode=$mode&amp;sub=create_table";
-
- $template->assign_vars(array(
- 'BODY' => $lang['STAGE_ADVANCED_EXPLAIN'],
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => $s_hidden_fields,
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Load the contents of the schema into the database and then alter it based on what has been input during the installation
- */
- function load_schema($mode, $sub)
- {
- global $db, $lang, $template, $phpbb_root_path, $phpEx, $request;
-
- $this->page_title = $lang['STAGE_CREATE_TABLE'];
- $s_hidden_fields = '';
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- if ($data['dbms'] == '')
- {
- // Someone's been silly and tried calling this page direct
- // So we send them back to the start to do it again properly
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- // HTTP_HOST is having the correct browser url in most cases...
- $server_name = strtolower(htmlspecialchars_decode($request->header('Host', $request->server('SERVER_NAME'))));
- $referer = strtolower($request->header('Referer'));
-
- // HTTP HOST can carry a port number...
- if (strpos($server_name, ':') !== false)
- {
- $server_name = substr($server_name, 0, strpos($server_name, ':'));
- }
-
- $cookie_domain = ($data['server_name'] != '') ? $data['server_name'] : $server_name;
-
- // Try to come up with the best solution for cookie domain...
- if (strpos($cookie_domain, 'www.') === 0)
- {
- $cookie_domain = str_replace('www.', '.', $cookie_domain);
- }
-
- // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
- $available_dbms = get_available_dbms($data['dbms']);
-
- if (!isset($available_dbms[$data['dbms']]))
- {
- // Someone's been silly and tried providing a non-existant dbms
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $dbms = $available_dbms[$data['dbms']]['DRIVER'];
-
- // Instantiate the database
- $db = new $dbms();
- $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
-
- // NOTE: trigger_error does not work here.
- $db->sql_return_on_error(true);
-
- // If mysql is chosen, we need to adjust the schema filename slightly to reflect the correct version. ;)
- if ($data['dbms'] == 'mysql')
- {
- if (version_compare($db->sql_server_info(true), '4.1.3', '>='))
- {
- $available_dbms[$data['dbms']]['SCHEMA'] .= '_41';
- }
- else
- {
- $available_dbms[$data['dbms']]['SCHEMA'] .= '_40';
- }
- }
-
- // Ok we have the db info go ahead and read in the relevant schema
- // and work on building the table
- $dbms_schema = 'schemas/' . $available_dbms[$data['dbms']]['SCHEMA'] . '_schema.sql';
-
- // How should we treat this schema?
- $delimiter = $available_dbms[$data['dbms']]['DELIM'];
-
- if (file_exists($dbms_schema))
- {
- $sql_query = @file_get_contents($dbms_schema);
- $sql_query = preg_replace('#phpbb_#i', $data['table_prefix'], $sql_query);
- $sql_query = phpbb_remove_comments($sql_query);
- $sql_query = split_sql_file($sql_query, $delimiter);
-
- foreach ($sql_query as $sql)
- {
- // Ignore errors when the functions or types already exist
- // to allow installing phpBB twice in the same database with
- // a different prefix
- $db->sql_query($sql);
- }
- unset($sql_query);
- }
-
- // Ok we have the db info go ahead and work on building the table
- if (file_exists('schemas/schema.json'))
- {
- $db_table_schema = @file_get_contents('schemas/schema.json');
- $db_table_schema = json_decode($db_table_schema, true);
- }
- else
- {
- global $phpbb_root_path, $phpEx, $table_prefix;
- $table_prefix = 'phpbb_';
-
- if (!defined('CONFIG_TABLE'))
- {
- // We need to include the constants file for the table constants
- // when we generate the schema from the migration files.
- include($phpbb_root_path . 'includes/constants.' . $phpEx);
- }
-
- $finder = new \phpbb\finder(new \phpbb\filesystem\filesystem(), $phpbb_root_path, null, $phpEx);
- $classes = $finder->core_path('phpbb/db/migration/data/')
- ->get_classes();
-
- $sqlite_db = new \phpbb\db\driver\sqlite();
- $factory = new \phpbb\db\tools\factory();
- $db_tools = $factory->get($sqlite_db, true);
- $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $sqlite_db, $db_tools, $phpbb_root_path, $phpEx, $table_prefix);
- $db_table_schema = $schema_generator->get_schema();
- }
-
- if (!defined('CONFIG_TABLE'))
- {
- // CONFIG_TABLE is required by sql_create_index() to check the
- // length of index names. However table_prefix is not defined
- // here yet, so we need to create the constant ourselves.
- define('CONFIG_TABLE', $data['table_prefix'] . 'config');
- }
-
- $factory = new \phpbb\db\tools\factory();
- $db_tools = $factory->get($db);
- foreach ($db_table_schema as $table_name => $table_data)
- {
- $db_tools->sql_create_table(
- $data['table_prefix'] . substr($table_name, 6),
- $table_data
- );
- }
-
- // Ok tables have been built, let's fill in the basic information
- $sql_query = file_get_contents('schemas/schema_data.sql');
-
- // Deal with any special comments and characters
- switch ($data['dbms'])
- {
- case 'mssql':
- case 'mssql_odbc':
- case 'mssqlnative':
- $sql_query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $sql_query);
- break;
-
- case 'postgres':
- $sql_query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $sql_query);
- break;
-
- case 'mysql':
- case 'mysqli':
- $sql_query = str_replace('\\', '\\\\', $sql_query);
- break;
- }
-
- // Change prefix
- $sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $data['table_prefix'] . '\1 ', $sql_query);
-
- // Change language strings...
- $sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', 'adjust_language_keys_callback', $sql_query);
-
- $sql_query = phpbb_remove_comments($sql_query);
- $sql_query = split_sql_file($sql_query, ';');
-
- foreach ($sql_query as $sql)
- {
- //$sql = trim(str_replace('|', ';', $sql));
- if (!$db->sql_query($sql))
- {
- $error = $db->sql_error();
- $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
- }
- }
- unset($sql_query);
-
- $current_time = time();
-
- $user_ip = $request->server('REMOTE_ADDR') ? phpbb_ip_normalise($request->server('REMOTE_ADDR')) : '';
-
- if ($data['script_path'] !== '/')
- {
- // Adjust destination path (no trailing slash)
- if (substr($data['script_path'], -1) == '/')
- {
- $data['script_path'] = substr($data['script_path'], 0, -1);
- }
-
- $data['script_path'] = str_replace(array('../', './'), '', $data['script_path']);
-
- if ($data['script_path'][0] != '/')
- {
- $data['script_path'] = '/' . $data['script_path'];
- }
- }
-
- // Set default config and post data, this applies to all DB's
- $sql_ary = array(
- 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
- VALUES ('board_startdate', '$current_time')",
-
- 'INSERT INTO ' . $data['table_prefix'] . "config (config_name, config_value)
- VALUES ('default_lang', '" . $db->sql_escape($data['default_lang']) . "')",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['img_imagick']) . "'
- WHERE config_name = 'img_imagick'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_name']) . "'
- WHERE config_name = 'server_name'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_port']) . "'
- WHERE config_name = 'server_port'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['board_email']) . "'
- WHERE config_name = 'board_email'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['board_email']) . "'
- WHERE config_name = 'board_contact'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($cookie_domain) . "'
- WHERE config_name = 'cookie_domain'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($lang['default_dateformat']) . "'
- WHERE config_name = 'default_dateformat'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['email_enable']) . "'
- WHERE config_name = 'email_enable'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_delivery']) . "'
- WHERE config_name = 'smtp_delivery'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_host']) . "'
- WHERE config_name = 'smtp_host'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_auth']) . "'
- WHERE config_name = 'smtp_auth_method'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_user']) . "'
- WHERE config_name = 'smtp_username'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['smtp_pass']) . "'
- WHERE config_name = 'smtp_password'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['cookie_secure']) . "'
- WHERE config_name = 'cookie_secure'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['force_server_vars']) . "'
- WHERE config_name = 'force_server_vars'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['script_path']) . "'
- WHERE config_name = 'script_path'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['server_protocol']) . "'
- WHERE config_name = 'server_protocol'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE config_name = 'newest_username'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . md5(mt_rand()) . "'
- WHERE config_name = 'avatar_salt'",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . md5(mt_rand()) . "'
- WHERE config_name = 'plupload_salt'",
-
- 'UPDATE ' . $data['table_prefix'] . "users
- SET username = '" . $db->sql_escape($data['admin_name']) . "', user_password='" . $db->sql_escape(md5($data['admin_pass1'])) . "', user_ip = '" . $db->sql_escape($user_ip) . "', user_lang = '" . $db->sql_escape($data['default_lang']) . "', user_email='" . $db->sql_escape($data['board_email']) . "', user_dateformat='" . $db->sql_escape($lang['default_dateformat']) . "', user_email_hash = " . $db->sql_escape(phpbb_email_hash($data['board_email'])) . ", username_clean = '" . $db->sql_escape(utf8_clean_string($data['admin_name'])) . "'
- WHERE username = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "moderator_cache
- SET username = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE username = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "forums
- SET forum_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE forum_last_poster_name = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "topics
- SET topic_first_poster_name = '" . $db->sql_escape($data['admin_name']) . "', topic_last_poster_name = '" . $db->sql_escape($data['admin_name']) . "'
- WHERE topic_first_poster_name = 'Admin'
- OR topic_last_poster_name = 'Admin'",
-
- 'UPDATE ' . $data['table_prefix'] . "users
- SET user_regdate = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "posts
- SET post_time = $current_time, poster_ip = '" . $db->sql_escape($user_ip) . "'",
-
- 'UPDATE ' . $data['table_prefix'] . "topics
- SET topic_time = $current_time, topic_last_post_time = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "forums
- SET forum_last_post_time = $current_time",
-
- 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($db->sql_server_info(true)) . "'
- WHERE config_name = 'dbms_version'",
- );
-
- if (@extension_loaded('gd'))
- {
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = 'core.captcha.plugins.gd'
- WHERE config_name = 'captcha_plugin'";
-
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '1'
- WHERE config_name = 'captcha_gd'";
- }
-
- $ref = substr($referer, strpos($referer, '://') + 3);
-
- if (!(stripos($ref, $server_name) === 0))
- {
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '0'
- WHERE config_name = 'referer_validation'";
- }
-
- // We set a (semi-)unique cookie name to bypass login issues related to the cookie name.
- $cookie_name = 'phpbb3_';
- $rand_str = md5(mt_rand());
- $rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35));
- $rand_str = substr($rand_str, 0, 5);
- $cookie_name .= strtolower($rand_str);
-
- $sql_ary[] = 'UPDATE ' . $data['table_prefix'] . "config
- SET config_value = '" . $db->sql_escape($cookie_name) . "'
- WHERE config_name = 'cookie_name'";
-
- foreach ($sql_ary as $sql)
- {
- //$sql = trim(str_replace('|', ';', $sql));
-
- if (!$db->sql_query($sql))
- {
- $error = $db->sql_error();
- $this->p_master->db_error($error['message'], $sql, __LINE__, __FILE__);
- }
- }
-
- $submit = $lang['NEXT_STEP'];
-
- $url = $this->p_master->module_url . "?mode=$mode&amp;sub=final";
-
- $template->assign_vars(array(
- 'BODY' => $lang['STAGE_CREATE_TABLE_EXPLAIN'],
- 'L_SUBMIT' => $submit,
- 'S_HIDDEN' => build_hidden_fields($data),
- 'U_ACTION' => $url,
- ));
- }
-
- /**
- * Build the search index...
- */
- function build_search_index($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpbb_dispatcher, $phpEx, $config, $auth, $user;
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
- $table_prefix = $data['table_prefix'];
-
- // If we get here and the extension isn't loaded it should be safe to just go ahead and load it
- $available_dbms = get_available_dbms($data['dbms']);
-
- if (!isset($available_dbms[$data['dbms']]))
- {
- // Someone's been silly and tried providing a non-existant dbms
- $this->p_master->redirect("index.$phpEx?mode=install");
- }
-
- $dbms = $available_dbms[$data['dbms']]['DRIVER'];
-
- // Instantiate the database
- $db = new $dbms();
- $db->sql_connect($data['dbhost'], $data['dbuser'], htmlspecialchars_decode($data['dbpasswd']), $data['dbname'], $data['dbport'], false, false);
-
- // NOTE: trigger_error does not work here.
- $db->sql_return_on_error(true);
-
- include_once($phpbb_root_path . 'includes/constants.' . $phpEx);
- include_once($phpbb_root_path . 'phpbb/search/fulltext_native.' . $phpEx);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- $error = false;
- $search = new \phpbb\search\fulltext_native($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
-
- $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id
- FROM ' . POSTS_TABLE;
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']);
- }
- $db->sql_freeresult($result);
- }
-
- /**
- * Populate the module tables
- */
- function add_modules($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx, $phpbb_extension_manager, $config, $phpbb_container;
-
- // modules require an extension manager
- if (empty($phpbb_extension_manager))
- {
- /* @var $phpbb_extension_manager \phpbb\extension\manager */
- $phpbb_extension_manager = $phpbb_container->get('ext.manager');
- }
-
- $_module = new \phpbb\module\module_manager(
- new \phpbb\cache\driver\dummy(),
- $db,
- $phpbb_extension_manager,
- MODULES_TABLE,
- $phpbb_root_path,
- $phpEx
- );
- $module_classes = array('acp', 'mcp', 'ucp');
-
- // Add categories
- foreach ($module_classes as $module_class)
- {
- $categories = array();
-
- // Set the module class
- $_module->module_class = $module_class;
-
- foreach ($this->module_categories[$module_class] as $cat_name => $subs)
- {
- $basename = '';
- // Check if this sub-category has a basename. If it has, use it.
- if (isset($this->module_categories_basenames[$cat_name]))
- {
- $basename = $this->module_categories_basenames[$cat_name];
- }
- $module_data = array(
- 'module_basename' => $basename,
- 'module_enabled' => 1,
- 'module_display' => 1,
- 'parent_id' => 0,
- 'module_class' => $module_class,
- 'module_langname' => $cat_name,
- 'module_mode' => '',
- 'module_auth' => '',
- );
-
- // Add category
- $_module->update_module_data($module_data);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
-
- $categories[$cat_name]['id'] = (int) $module_data['module_id'];
- $categories[$cat_name]['parent_id'] = 0;
-
- // Create sub-categories...
- if (is_array($subs))
- {
- foreach ($subs as $level2_name)
- {
- $basename = '';
- // Check if this sub-category has a basename. If it has, use it.
- if (isset($this->module_categories_basenames[$level2_name]))
- {
- $basename = $this->module_categories_basenames[$level2_name];
- }
- $module_data = array(
- 'module_basename' => $basename,
- 'module_enabled' => 1,
- 'module_display' => 1,
- 'parent_id' => (int) $categories[$cat_name]['id'],
- 'module_class' => $module_class,
- 'module_langname' => $level2_name,
- 'module_mode' => '',
- 'module_auth' => '',
- );
-
- $_module->update_module_data($module_data);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
-
- $categories[$level2_name]['id'] = (int) $module_data['module_id'];
- $categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id'];
- }
- }
- }
-
- // Get the modules we want to add... returned sorted by name
- $module_info = $_module->get_module_infos($module_class);
-
- foreach ($module_info as $module_basename => $fileinfo)
- {
- foreach ($fileinfo['modes'] as $module_mode => $row)
- {
- foreach ($row['cat'] as $cat_name)
- {
- if (!isset($categories[$cat_name]))
- {
- continue;
- }
-
- $module_data = array(
- 'module_basename' => $module_basename,
- 'module_enabled' => 1,
- 'module_display' => (isset($row['display'])) ? (int) $row['display'] : 1,
- 'parent_id' => (int) $categories[$cat_name]['id'],
- 'module_class' => $module_class,
- 'module_langname' => $row['title'],
- 'module_mode' => $module_mode,
- 'module_auth' => $row['auth'],
- );
-
- $_module->update_module_data($module_data);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- }
-
- // Move some of the modules around since the code above will put them in the wrong place
- if ($module_class == 'acp')
- {
- // Move main module 4 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_main'
- AND module_class = 'acp'
- AND module_mode = 'main'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'acp', 'move_up', 4);
-
- // Move permissions intro screen module 4 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_permissions'
- AND module_class = 'acp'
- AND module_mode = 'intro'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'acp', 'move_up', 4);
-
- // Move manage users screen module 5 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'acp_users'
- AND module_class = 'acp'
- AND module_mode = 'overview'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'acp', 'move_up', 5);
-
- // Move extension management module 1 up...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT'
- AND module_class = 'acp'
- AND module_mode = ''
- AND module_basename = ''";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'acp', 'move_up', 1);
- }
-
- if ($module_class == 'mcp')
- {
- // Move pm report details module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_report_details'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'mcp', 'move_down', 3);
-
- // Move closed pm reports module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_reports_closed'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'mcp', 'move_down', 3);
-
- // Move open pm reports module 3 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'mcp_pm_reports'
- AND module_class = 'mcp'
- AND module_mode = 'pm_reports'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'mcp', 'move_down', 3);
- }
-
- if ($module_class == 'ucp')
- {
- // Move attachment module 4 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_attachments'
- AND module_class = 'ucp'
- AND module_mode = 'attachments'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'ucp', 'move_down', 4);
-
- // Move notification options module 4 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_notifications'
- AND module_class = 'ucp'
- AND module_mode = 'notification_options'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'ucp', 'move_down', 4);
-
- // Move OAuth module 5 down...
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_basename = 'ucp_auth_link'
- AND module_class = 'ucp'
- AND module_mode = 'auth_link'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $_module->move_module_by($row, 'ucp', 'move_down', 5);
- }
-
- // And now for the special ones
- // (these are modules which appear in multiple categories and thus get added manually to some for more control)
- if (isset($this->module_extras[$module_class]))
- {
- foreach ($this->module_extras[$module_class] as $cat_name => $mods)
- {
- $sql = 'SELECT module_id, left_id, right_id
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = '" . $db->sql_escape($cat_name) . "'
- AND module_class = '" . $db->sql_escape($module_class) . "'";
- $result = $db->sql_query_limit($sql, 1);
- $row2 = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- foreach ($mods as $mod_name)
- {
- $sql = 'SELECT *
- FROM ' . MODULES_TABLE . "
- WHERE module_langname = '" . $db->sql_escape($mod_name) . "'
- AND module_class = '" . $db->sql_escape($module_class) . "'
- AND module_basename <> ''";
- $result = $db->sql_query_limit($sql, 1);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $module_data = array(
- 'module_basename' => $row['module_basename'],
- 'module_enabled' => (int) $row['module_enabled'],
- 'module_display' => (int) $row['module_display'],
- 'parent_id' => (int) $row2['module_id'],
- 'module_class' => $row['module_class'],
- 'module_langname' => $row['module_langname'],
- 'module_mode' => $row['module_mode'],
- 'module_auth' => $row['module_auth'],
- );
-
- $_module->update_module_data($module_data);
-
- // Check for last sql error happened
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- }
-
- $_module->remove_cache_file($module_class);
- }
- }
-
- /**
- * Populate the language tables
- */
- function add_language($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx;
-
- $dir = @opendir($phpbb_root_path . 'language');
-
- if (!$dir)
- {
- $this->error('Unable to access the language directory', __LINE__, __FILE__);
- }
-
- $installed_languages = array();
- while (($file = readdir($dir)) !== false)
- {
- $path = $phpbb_root_path . 'language/' . $file;
-
- if ($file == '.' || $file == '..' || is_link($path) || is_file($path) || $file == 'CVS')
- {
- continue;
- }
-
- if (is_dir($path) && file_exists($path . '/iso.txt'))
- {
- $lang_file = file("$path/iso.txt");
-
- $lang_pack = array(
- 'lang_iso' => basename($path),
- 'lang_dir' => basename($path),
- 'lang_english_name' => trim(htmlspecialchars($lang_file[0])),
- 'lang_local_name' => trim(htmlspecialchars($lang_file[1], ENT_COMPAT, 'UTF-8')),
- 'lang_author' => trim(htmlspecialchars($lang_file[2], ENT_COMPAT, 'UTF-8')),
- );
-
- $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $lang_pack));
-
- $installed_languages[] = (int) $db->sql_nextid();
- if ($db->get_sql_error_triggered())
- {
- $error = $db->sql_error($db->get_sql_error_sql());
- $this->p_master->db_error($error['message'], $db->get_sql_error_sql(), __LINE__, __FILE__);
- }
- }
- }
- closedir($dir);
-
- $sql = 'SELECT *
- FROM ' . PROFILE_FIELDS_TABLE;
- $result = $db->sql_query($sql);
-
- $profile_fields = array();
- $insert_buffer = new \phpbb\db\sql_insert_buffer($db, PROFILE_LANG_TABLE);
- while ($row = $db->sql_fetchrow($result))
- {
- foreach ($installed_languages as $lang_id)
- {
- $insert_buffer->insert(array(
- 'field_id' => $row['field_id'],
- 'lang_id' => $lang_id,
- 'lang_name' => strtoupper(substr($row['field_name'], 6)),// Remove phpbb_ from field name
- 'lang_explain' => '',
- 'lang_default_value' => '',
- ));
- }
- }
- $db->sql_freeresult($result);
-
- $insert_buffer->flush();
- }
-
- /**
- * Add search robots to the database
- */
- function add_bots($mode, $sub)
- {
- global $db, $lang, $phpbb_root_path, $phpEx, $config;
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = 'BOTS'";
- $result = $db->sql_query($sql);
- $group_id = (int) $db->sql_fetchfield('group_id');
- $db->sql_freeresult($result);
-
- if (!$group_id)
- {
- // If we reach this point then something has gone very wrong
- $this->p_master->error($lang['NO_GROUP'], __LINE__, __FILE__);
- }
-
- if (!function_exists('user_add'))
- {
- include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
- }
-
- foreach ($this->bot_list as $bot_name => $bot_ary)
- {
- $user_row = array(
- 'user_type' => USER_IGNORE,
- 'group_id' => $group_id,
- 'username' => $bot_name,
- 'user_regdate' => time(),
- 'user_password' => '',
- 'user_colour' => '9E8DA7',
- 'user_email' => '',
- 'user_lang' => $data['default_lang'],
- 'user_style' => 1,
- 'user_timezone' => 'UTC',
- 'user_dateformat' => $lang['default_dateformat'],
- 'user_allow_massemail' => 0,
- 'user_allow_pm' => 0,
- );
-
- $user_id = user_add($user_row);
-
- if (!$user_id)
- {
- // If we can't insert this user then continue to the next one to avoid inconsistent data
- $this->p_master->db_error('Unable to insert bot into users table', $db->get_sql_error_sql(), __LINE__, __FILE__, true);
- continue;
- }
-
- $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array(
- 'bot_active' => 1,
- 'bot_name' => (string) $bot_name,
- 'user_id' => (int) $user_id,
- 'bot_agent' => (string) $bot_ary[0],
- 'bot_ip' => (string) $bot_ary[1],
- ));
-
- $db->sql_query($sql);
- }
- }
-
- /**
- * Sends an email to the board administrator with their password and some useful links
- */
- function email_admin($mode, $sub)
- {
- global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log;
-
- $this->page_title = $lang['STAGE_FINAL'];
-
- // Obtain any submitted data
- $data = $this->get_submitted_data();
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- $user->session_begin();
- $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true);
-
- // OK, Now that we've reached this point we can be confident that everything
- // is installed and working......I hope :)
- // So it's time to send an email to the administrator confirming the details
- // they entered
-
- if ($config['email_enable'])
- {
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
-
- $messenger = new messenger(false);
-
- $messenger->template('installed', $data['language']);
-
- $messenger->to($data['board_email'], $data['admin_name']);
-
- $messenger->anti_abuse_headers($config, $user);
-
- $messenger->assign_vars(array(
- 'USERNAME' => htmlspecialchars_decode($data['admin_name']),
- 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1']))
- );
-
- $messenger->send(NOTIFY_EMAIL);
- }
-
- // And finally, add a note to the log
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_INSTALLED', false, array($config['version']));
-
- $template->assign_vars(array(
- 'TITLE' => $lang['INSTALL_CONGRATS'],
- 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&amp;language=' . $data['language']), '../docs/README.html'),
- 'L_SUBMIT' => $lang['INSTALL_LOGIN'],
- 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&amp;mode=send_statistics'),
- ));
- }
-
- /**
- * Check if the avatar directory is writable and disable avatars
- * if it isn't writable.
- */
- function disable_avatars_if_unwritable()
- {
- global $config, $phpbb_root_path;
-
- if (!$this->filesystem->is_writable($phpbb_root_path . 'images/avatars/upload/'))
- {
- $config->set('allow_avatar', 0);
- $config->set('allow_avatar_upload', 0);
- }
- }
-
- /**
- * Populate migrations for the installation
- *
- * This "installs" all migrations from (root path)/phpbb/db/migrations/data.
- * "installs" means it adds all migrations to the migrations table, but does not
- * perform any of the actions in the migrations.
- *
- * @param \phpbb\extension\manager $extension_manager
- * @param \phpbb\db\migrator $migrator
- */
- function populate_migrations($extension_manager, $migrator)
- {
- $finder = $extension_manager->get_finder();
-
- $migrations = $finder
- ->core_path('phpbb/db/migration/data/')
- ->get_classes();
- $migrator->populate_migrations($migrations);
- }
-
- /**
- * Generate a list of available mail server authentication methods
- */
- function mail_auth_select($selected_method)
- {
- global $lang;
-
- $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP');
- $s_smtp_auth_options = '';
-
- foreach ($auth_methods as $method)
- {
- $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $lang['SMTP_' . str_replace('-', '_', $method)] . '</option>';
- }
-
- return $s_smtp_auth_options;
- }
-
- /**
- * Get submitted data
- */
- function get_submitted_data()
- {
- global $request;
-
- return array(
- 'language' => basename($request->variable('language', '')),
- 'dbms' => $request->variable('dbms', ''),
- 'dbhost' => $request->variable('dbhost', ''),
- 'dbport' => $request->variable('dbport', ''),
- 'dbuser' => $request->variable('dbuser', ''),
- 'dbpasswd' => $request->variable('dbpasswd', '', true),
- 'dbname' => $request->variable('dbname', ''),
- 'table_prefix' => $request->variable('table_prefix', ''),
- 'default_lang' => basename($request->variable('default_lang', '')),
- 'admin_name' => $request->variable('admin_name', '', true),
- 'admin_pass1' => $request->variable('admin_pass1', '', true),
- 'admin_pass2' => $request->variable('admin_pass2', '', true),
- 'board_email' => strtolower($request->variable('board_email', '')),
- 'img_imagick' => $request->variable('img_imagick', ''),
- 'ftp_path' => $request->variable('ftp_path', ''),
- 'ftp_user' => $request->variable('ftp_user', ''),
- 'ftp_pass' => $request->variable('ftp_pass', ''),
- 'email_enable' => $request->variable('email_enable', ''),
- 'smtp_delivery' => $request->variable('smtp_delivery', ''),
- 'smtp_host' => $request->variable('smtp_host', ''),
- 'smtp_auth' => $request->variable('smtp_auth', ''),
- 'smtp_user' => $request->variable('smtp_user', ''),
- 'smtp_pass' => $request->variable('smtp_pass', ''),
- 'cookie_secure' => $request->variable('cookie_secure', ''),
- 'force_server_vars' => $request->variable('force_server_vars', ''),
- 'server_protocol' => $request->variable('server_protocol', ''),
- 'server_name' => $request->variable('server_name', ''),
- 'server_port' => $request->variable('server_port', ''),
- 'script_path' => $request->variable('script_path', ''),
- );
- }
-
- /**
- * The information below will be used to build the input fields presented to the user
- */
- var $db_config_options = array(
- 'legend1' => 'DB_CONFIG',
- 'dbms' => array('lang' => 'DBMS', 'type' => 'select', 'options' => 'dbms_select(\'{VALUE}\')', 'explain' => false),
- 'dbhost' => array('lang' => 'DB_HOST', 'type' => 'text:25:100', 'explain' => true),
- 'dbport' => array('lang' => 'DB_PORT', 'type' => 'text:25:100', 'explain' => true),
- 'dbname' => array('lang' => 'DB_NAME', 'type' => 'text:25:100', 'explain' => false),
- 'dbuser' => array('lang' => 'DB_USERNAME', 'type' => 'text:25:100', 'explain' => false),
- 'dbpasswd' => array('lang' => 'DB_PASSWORD', 'type' => 'password:25:100', 'explain' => false),
- 'table_prefix' => array('lang' => 'TABLE_PREFIX', 'type' => 'text:25:100', 'explain' => true),
- );
- var $admin_config_options = array(
- 'legend1' => 'ADMIN_CONFIG',
- 'default_lang' => array('lang' => 'DEFAULT_LANG', 'type' => 'select', 'options' => '$this->module->inst_language_select(\'{VALUE}\')', 'explain' => false),
- 'admin_name' => array('lang' => 'ADMIN_USERNAME', 'type' => 'text:25:100', 'explain' => true),
- 'admin_pass1' => array('lang' => 'ADMIN_PASSWORD', 'type' => 'password:25:100', 'explain' => true),
- 'admin_pass2' => array('lang' => 'ADMIN_PASSWORD_CONFIRM', 'type' => 'password:25:100', 'explain' => false),
- 'board_email' => array('lang' => 'CONTACT_EMAIL', 'type' => 'email:25:100', 'explain' => false),
- );
- var $advanced_config_options = array(
- 'legend1' => 'ACP_EMAIL_SETTINGS',
- 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'smtp_delivery' => array('lang' => 'USE_SMTP', 'type' => 'radio:yes_no', 'explain' => true),
- 'smtp_host' => array('lang' => 'SMTP_SERVER', 'type' => 'text:25:50', 'explain' => false),
- 'smtp_auth' => array('lang' => 'SMTP_AUTH_METHOD', 'type' => 'select', 'options' => '$this->module->mail_auth_select(\'{VALUE}\')', 'explain' => true),
- 'smtp_user' => array('lang' => 'SMTP_USERNAME', 'type' => 'text:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
- 'smtp_pass' => array('lang' => 'SMTP_PASSWORD', 'type' => 'password:25:255', 'explain' => true, 'options' => array('autocomplete' => 'off')),
-
- 'legend2' => 'SERVER_URL_SETTINGS',
- 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'type' => 'radio:enabled_disabled', 'explain' => true),
- 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'type' => 'radio:yes_no', 'explain' => true),
- 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'type' => 'text:10:10', 'explain' => true),
- 'server_name' => array('lang' => 'SERVER_NAME', 'type' => 'text:40:255', 'explain' => true),
- 'server_port' => array('lang' => 'SERVER_PORT', 'type' => 'text:5:5', 'explain' => true),
- 'script_path' => array('lang' => 'SCRIPT_PATH', 'type' => 'text::255', 'explain' => true),
- );
-
- /**
- * Specific PHP modules we may require for certain optional or extended features
- */
- var $php_dlls_other = array('zlib', 'ftp', 'gd', 'xml');
-
- /**
- * A list of the web-crawlers/bots we recognise by default
- *
- * Candidates but not included:
- * 'Accoona [Bot]' 'Accoona-AI-Agent/'
- * 'ASPseek [Crawler]' 'ASPseek/'
- * 'Boitho [Crawler]' 'boitho.com-dc/'
- * 'Bunnybot [Bot]' 'powered by www.buncat.de'
- * 'Cosmix [Bot]' 'cfetch/'
- * 'Crawler Search [Crawler]' '.Crawler-Search.de'
- * 'Findexa [Crawler]' 'Findexa Crawler ('
- * 'GBSpider [Spider]' 'GBSpider v'
- * 'genie [Bot]' 'genieBot ('
- * 'Hogsearch [Bot]' 'oegp v. 1.3.0'
- * 'Insuranco [Bot]' 'InsurancoBot'
- * 'IRLbot [Bot]' 'http://irl.cs.tamu.edu/crawler'
- * 'ISC Systems [Bot]' 'ISC Systems iRc Search'
- * 'Jyxobot [Bot]' 'Jyxobot/'
- * 'Kraehe [Metasuche]' '-DIE-KRAEHE- META-SEARCH-ENGINE/'
- * 'LinkWalker' 'LinkWalker'
- * 'MMSBot [Bot]' 'http://www.mmsweb.at/bot.html'
- * 'Naver [Bot]' 'nhnbot@naver.com)'
- * 'NetResearchServer' 'NetResearchServer/'
- * 'Nimble [Crawler]' 'NimbleCrawler'
- * 'Ocelli [Bot]' 'Ocelli/'
- * 'Onsearch [Bot]' 'onCHECK-Robot'
- * 'Orange [Spider]' 'OrangeSpider'
- * 'Sproose [Bot]' 'http://www.sproose.com/bot'
- * 'Susie [Sync]' '!Susie (http://www.sync2it.com/susie)'
- * 'Tbot [Bot]' 'Tbot/'
- * 'Thumbshots [Capture]' 'thumbshots-de-Bot'
- * 'Vagabondo [Crawler]' 'http://webagent.wise-guys.nl/'
- * 'Walhello [Bot]' 'appie 1.1 (www.walhello.com)'
- * 'WissenOnline [Bot]' 'WissenOnline-Bot'
- * 'WWWeasel [Bot]' 'WWWeasel Robot v'
- * 'Xaldon [Spider]' 'Xaldon WebSpider'
- */
- var $bot_list = array(
- 'AdsBot [Google]' => array('AdsBot-Google', ''),
- 'Alexa [Bot]' => array('ia_archiver', ''),
- 'Alta Vista [Bot]' => array('Scooter/', ''),
- 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''),
- 'Baidu [Spider]' => array('Baiduspider', ''),
- 'Bing [Bot]' => array('bingbot/', ''),
- 'Exabot [Bot]' => array('Exabot', ''),
- 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''),
- 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''),
- 'Francis [Bot]' => array('http://www.neomo.de/', ''),
- 'Gigabot [Bot]' => array('Gigabot/', ''),
- 'Google Adsense [Bot]' => array('Mediapartners-Google', ''),
- 'Google Desktop' => array('Google Desktop', ''),
- 'Google Feedfetcher' => array('Feedfetcher-Google', ''),
- 'Google [Bot]' => array('Googlebot', ''),
- 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''),
- 'Heritrix [Crawler]' => array('heritrix/1.', ''),
- 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''),
- 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''),
- 'ichiro [Crawler]' => array('ichiro/', ''),
- 'Majestic-12 [Bot]' => array('MJ12bot/', ''),
- 'Metager [Bot]' => array('MetagerBot/', ''),
- 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''),
- 'MSN [Bot]' => array('msnbot/', ''),
- 'MSNbot Media' => array('msnbot-media/', ''),
- 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''),
- 'Online link [Validator]' => array('online link validator', ''),
- 'psbot [Picsearch]' => array('psbot/0', ''),
- 'Sensis [Crawler]' => array('Sensis Web Crawler', ''),
- 'SEO Crawler' => array('SEO search Crawler/', ''),
- 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''),
- 'SEOSearch [Crawler]' => array('SEOsearch/', ''),
- 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''),
- 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''),
- 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''),
- 'TurnitinBot [Bot]' => array('TurnitinBot/', ''),
- 'Voyager [Bot]' => array('voyager/', ''),
- 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''),
- 'W3C [Linkcheck]' => array('W3C-checklink/', ''),
- 'W3C [Validator]' => array('W3C_Validator', ''),
- 'YaCy [Bot]' => array('yacybot', ''),
- 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''),
- 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''),
- 'Yahoo [Bot]' => array('Yahoo! Slurp', ''),
- 'YahooSeeker [Bot]' => array('YahooSeeker/', ''),
- );
-
- /**
- * Define the module structure so that we can populate the database without
- * needing to hard-code module_id values
- */
- var $module_categories = array(
- 'acp' => array(
- 'ACP_CAT_GENERAL' => array(
- 'ACP_QUICK_ACCESS',
- 'ACP_BOARD_CONFIGURATION',
- 'ACP_CLIENT_COMMUNICATION',
- 'ACP_SERVER_CONFIGURATION',
- ),
- 'ACP_CAT_FORUMS' => array(
- 'ACP_MANAGE_FORUMS',
- 'ACP_FORUM_BASED_PERMISSIONS',
- ),
- 'ACP_CAT_POSTING' => array(
- 'ACP_MESSAGES',
- 'ACP_ATTACHMENTS',
- ),
- 'ACP_CAT_USERGROUP' => array(
- 'ACP_CAT_USERS',
- 'ACP_GROUPS',
- 'ACP_USER_SECURITY',
- ),
- 'ACP_CAT_PERMISSIONS' => array(
- 'ACP_GLOBAL_PERMISSIONS',
- 'ACP_FORUM_BASED_PERMISSIONS',
- 'ACP_PERMISSION_ROLES',
- 'ACP_PERMISSION_MASKS',
- ),
- 'ACP_CAT_CUSTOMISE' => array(
- 'ACP_STYLE_MANAGEMENT',
- 'ACP_EXTENSION_MANAGEMENT',
- 'ACP_LANGUAGE',
- ),
- 'ACP_CAT_MAINTENANCE' => array(
- 'ACP_FORUM_LOGS',
- 'ACP_CAT_DATABASE',
- ),
- 'ACP_CAT_SYSTEM' => array(
- 'ACP_AUTOMATION',
- 'ACP_GENERAL_TASKS',
- 'ACP_MODULE_MANAGEMENT',
- ),
- 'ACP_CAT_DOT_MODS' => null,
- ),
- 'mcp' => array(
- 'MCP_MAIN' => null,
- 'MCP_QUEUE' => null,
- 'MCP_REPORTS' => null,
- 'MCP_NOTES' => null,
- 'MCP_WARN' => null,
- 'MCP_LOGS' => null,
- 'MCP_BAN' => null,
- ),
- 'ucp' => array(
- 'UCP_MAIN' => null,
- 'UCP_PROFILE' => null,
- 'UCP_PREFS' => null,
- 'UCP_PM' => null,
- 'UCP_USERGROUPS' => null,
- 'UCP_ZEBRA' => null,
- ),
- );
- var $module_categories_basenames = array(
- 'UCP_PM' => 'ucp_pm',
- );
-
- var $module_extras = array(
- 'acp' => array(
- 'ACP_QUICK_ACCESS' => array(
- 'ACP_MANAGE_USERS',
- 'ACP_GROUPS_MANAGE',
- 'ACP_MANAGE_FORUMS',
- 'ACP_MOD_LOGS',
- 'ACP_BOTS',
- 'ACP_PHP_INFO',
- ),
- 'ACP_FORUM_BASED_PERMISSIONS' => array(
- 'ACP_FORUM_PERMISSIONS',
- 'ACP_FORUM_PERMISSIONS_COPY',
- 'ACP_FORUM_MODERATORS',
- 'ACP_USERS_FORUM_PERMISSIONS',
- 'ACP_GROUPS_FORUM_PERMISSIONS',
- ),
- ),
- );
-}
diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php
deleted file mode 100644
index d5874dac83..0000000000
--- a/phpBB/install/install_main.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-*/
-
-if ( !defined('IN_INSTALL') )
-{
- // Someone has tried to access the file direct. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- $module[] = array(
- 'module_type' => 'install',
- 'module_title' => 'OVERVIEW',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 0,
- 'module_subs' => array('INTRO', 'LICENSE', 'SUPPORT'),
- 'module_stages' => '',
- 'module_reqs' => ''
- );
-}
-
-/**
-* Main Tab - Installation
-*/
-class install_main extends module
-{
- function install_main(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $lang, $template, $language;
-
- switch ($sub)
- {
- case 'intro' :
- $title = $lang['SUB_INTRO'];
- $body = $lang['OVERVIEW_BODY'];
- break;
-
- case 'license' :
- $title = $lang['GPL'];
- $body = implode("<br/>\n", file(__DIR__ . '/../docs/LICENSE.txt'));
- break;
-
- case 'support' :
- $title = $lang['SUB_SUPPORT'];
- $body = $lang['SUPPORT_BODY'];
- break;
- }
-
- $this->tpl_name = 'install_main';
- $this->page_title = $title;
-
- $template->assign_vars(array(
- 'TITLE' => $title,
- 'BODY' => $body,
-
- 'S_LANG_SELECT' => '<select id="language" name="language">' . $this->p_master->inst_language_select($language) . '</select>',
- ));
- }
-}
diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php
deleted file mode 100644
index 2f8fd71c54..0000000000
--- a/phpBB/install/install_update.php
+++ /dev/null
@@ -1,1789 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-* @todo check for writable cache/store/files directory
-*/
-
-if (!defined('IN_INSTALL'))
-{
- // Someone has tried to access the file directly. This is not a good idea, so exit
- exit;
-}
-
-if (!empty($setmodules))
-{
- // If phpBB is not installed we do not include this module
- if (!phpbb_check_installation_exists($phpbb_root_path, $phpEx) || file_exists($phpbb_root_path . 'cache/install_lock'))
- {
- return;
- }
-
- $module[] = array(
- 'module_type' => 'update',
- 'module_title' => 'UPDATE',
- 'module_filename' => substr(basename(__FILE__), 0, -strlen($phpEx)-1),
- 'module_order' => 30,
- 'module_subs' => '',
- 'module_stages' => array('INTRO', 'VERSION_CHECK', 'FILE_CHECK', 'UPDATE_FILES', 'UPDATE_DB'),
- 'module_reqs' => ''
- );
-}
-
-/**
-* Update Installation
-*/
-class install_update extends module
-{
- var $p_master;
- var $update_info;
-
- var $old_location;
- var $new_location;
- var $latest_version;
- var $current_version;
-
- var $update_to_version;
-
- protected $filesystem;
-
- // Set to false
- var $test_update = false;
-
- function install_update(&$p_master)
- {
- $this->p_master = &$p_master;
- }
-
- function main($mode, $sub)
- {
- global $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language;
- global $request, $phpbb_admin_path, $phpbb_adm_relative_path, $phpbb_container, $phpbb_config_php_file;
-
- // We must enable super globals, otherwise creating a new instance of the request class,
- // using the new container with a dbal connection will fail with the following PHP Notice:
- // Object of class phpbb_request_deactivated_super_global could not be converted to int
- $request->enable_super_globals();
-
- // Create a normal container now
- $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
- $phpbb_container = $phpbb_container_builder
- ->with_config($phpbb_config_php_file)
- ->without_cache()
- ->without_extensions()
- ;
-
- if (file_exists($phpbb_root_path . 'install/update/new/config'))
- {
- $phpbb_container_builder->with_config_path($phpbb_root_path . 'install/update/new/config');
- }
- $phpbb_container = $phpbb_container_builder->get_container();
-
- // Writes into global $cache
- /* @var $cache \phpbb\cache\service */
- $cache = $phpbb_container->get('cache');
-
- $this->filesystem = $phpbb_container->get('filesystem');
-
- $this->tpl_name = 'install_update';
- $this->page_title = 'UPDATE_INSTALLATION';
-
- $this->old_location = $phpbb_root_path . 'install/update/old/';
- $this->new_location = $phpbb_root_path . 'install/update/new/';
-
- // Init DB
- extract($phpbb_config_php_file->get_all());
- require($phpbb_root_path . 'includes/constants.' . $phpEx);
-
- // Special options for conflicts/modified files
- define('MERGE_NO_MERGE_NEW', 1);
- define('MERGE_NO_MERGE_MOD', 2);
- define('MERGE_NEW_FILE', 3);
- define('MERGE_MOD_FILE', 4);
-
- $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
-
- $db = new $dbms();
-
- // Connect to DB
- $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
-
- // We do not need this any longer, unset for safety purposes
- unset($dbpasswd);
-
- // We need to fill the config to let internal functions correctly work
- $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE);
-
- // Force template recompile
- $config['load_tplcompile'] = 1;
-
- // First of all, init the user session
- $user->session_begin();
- $auth->acl($user->data);
-
- // Overwrite user's language with the selected one.
- // Config needs to be changed to ensure that guests also get the selected language.
- $config_default_lang = $config['default_lang'];
- $config['default_lang'] = $language;
- $user->data['user_lang'] = $language;
-
- $user->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
-
- // Reset the default_lang
- $config['default_lang'] = $config_default_lang;
- unset($config_default_lang);
-
- // If we are within the intro page we need to make sure we get up-to-date version info
- if ($sub == 'intro')
- {
- $cache->destroy('_version_info');
- }
-
- // Set custom template again. ;)
- $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
- $paths = array_filter($paths, 'is_dir');
- $template->set_custom_style(array(
- array(
- 'name' => 'adm',
- 'ext_path' => 'adm/style/',
- ),
- ), $paths);
-
- $template->assign_vars(array(
- 'S_USER_LANG' => $user->lang['USER_LANG'],
- 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
- 'S_CONTENT_ENCODING' => 'UTF-8',
- 'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
- 'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
- ));
-
- // Get current and latest version
- /* @var $version_helper \phpbb\version_helper */
- $version_helper = $phpbb_container->get('version_helper');
- try
- {
- $this->latest_version = $version_helper->get_latest_on_current_branch(true);
- }
- catch (\RuntimeException $e)
- {
- $this->latest_version = false;
-
- $update_info = array();
- include($phpbb_root_path . 'install/update/index.' . $phpEx);
- $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
-
- if ($info !== false)
- {
- $this->latest_version = (!empty($info['version']['to'])) ? trim($info['version']['to']) : false;
- }
- }
-
- // For the current version we trick a bit. ;)
- $this->current_version = (!empty($config['version_update_from'])) ? $config['version_update_from'] : $config['version'];
-
- $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->latest_version)), '<')) ? false : true;
-
- // Check for a valid update directory, else point the user to the phpbb.com website
- if (!file_exists($phpbb_root_path . 'install/update') || !file_exists($phpbb_root_path . 'install/update/index.' . $phpEx) || !file_exists($this->old_location) || !file_exists($this->new_location))
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => ($up_to_date) ? $user->lang['NO_UPDATE_FILES_UP_TO_DATE'] : sprintf($user->lang['NO_UPDATE_FILES_OUTDATED'], $config['version'], $this->current_version, $this->latest_version))
- );
-
- return;
- }
-
- $this->update_info = $this->get_file('update_info');
-
- // Make sure the update directory holds the correct information
- // Since admins are able to run the update/checks more than once we only check if the current version is lower or equal than the version to which we update to.
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '>'))
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $config['version'], $this->update_info['version']['from'], $this->update_info['version']['to']))
- );
-
- return;
- }
-
- // Check if the update files are actually meant to update from the current version
- if ($this->current_version != $this->update_info['version']['from'])
- {
- $template->assign_vars(array(
- 'S_ERROR' => true,
- 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $this->current_version, $this->update_info['version']['from'], $this->update_info['version']['to']),
- ));
- }
-
- // Check if the update files stored are for the latest version...
- if (version_compare(strtolower($this->latest_version), strtolower($this->update_info['version']['to']), '>'))
- {
- $template->assign_vars(array(
- 'S_WARNING' => true,
- 'WARNING_MSG' => sprintf($user->lang['OLD_UPDATE_FILES'], $this->update_info['version']['from'], $this->update_info['version']['to'], $this->latest_version))
- );
- }
-
- // We store the "update to" version, because it is not always the latest. ;)
- $this->update_to_version = $this->update_info['version']['to'];
-
- // Fill DB version
- if (empty($config['dbms_version']))
- {
- $config->set('dbms_version', $db->sql_server_info(true));
- }
-
- if ($this->test_update === false)
- {
- // What about the language file? Got it updated?
- if (in_array('language/' . $language . '/install.' . $phpEx, $this->update_info['files']))
- {
- $lang = array();
- include($this->new_location . 'language/' . $language . '/install.' . $phpEx);
- // this is the user's language.. just merge it
- $user->lang = array_merge($user->lang, $lang);
- }
- if ($language != 'en' && in_array('language/en/install.' . $phpEx, $this->update_info['files']))
- {
- $lang = array();
- include($this->new_location . 'language/en/install.' . $phpEx);
- // only add new keys to user's language in english
- $new_keys = array_diff(array_keys($lang), array_keys($user->lang));
- foreach ($new_keys as $i => $new_key)
- {
- $user->lang[$new_key] = $lang[$new_key];
- }
- }
- }
-
- // Include renderer and engine
- $this->include_file('includes/diff/diff.' . $phpEx);
- $this->include_file('includes/diff/engine.' . $phpEx);
- $this->include_file('includes/diff/renderer.' . $phpEx);
-
- // Make sure we stay at the file check if checking the files again
- if ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST))
- {
- $sub = $this->p_master->sub = 'file_check';
- }
-
- switch ($sub)
- {
- case 'intro':
- $this->page_title = 'UPDATE_INSTALLATION';
-
- $template->assign_vars(array(
- 'S_INTRO' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=version_check"),
- ));
-
- // Make sure the update list is destroyed.
- $cache->destroy('_update_list');
- $cache->destroy('_diff_files');
- $cache->destroy('_expected_files');
- break;
-
- case 'version_check':
- $this->page_title = 'STAGE_VERSION_CHECK';
-
- $template->assign_vars(array(
- 'S_VERSION_CHECK' => true,
-
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
-
- 'S_UP_TO_DATE' => $up_to_date,
- 'LATEST_VERSION' => $this->latest_version,
- 'CURRENT_VERSION' => $this->current_version,
- ));
-
- // Print out version the update package updates to
- if ($this->latest_version != $this->update_info['version']['to'])
- {
- $template->assign_var('PACKAGE_VERSION', $this->update_info['version']['to']);
- }
-
- // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
- // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
- // We now try to cope with this by triggering the update process
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
- {
- $template->assign_vars(array(
- 'S_UP_TO_DATE' => false,
- ));
- }
-
- break;
-
- case 'update_db':
- // Redirect the user to the database update script with some explanations...
- $template->assign_vars(array(
- 'S_DB_UPDATE' => true,
- 'S_DB_UPDATE_FINISHED' => ($config['version'] == $this->update_info['version']['to']) ? true : false,
- 'U_DB_UPDATE' => append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=1&amp;language=' . $user->data['user_lang']),
- 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
- 'L_EVERYTHING_UP_TO_DATE' => $user->lang('EVERYTHING_UP_TO_DATE', append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login'), append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=login&amp;redirect=' . $phpbb_adm_relative_path . 'index.php%3Fi=send_statistics%26mode=send_statistics')),
- ));
-
- // Do not display incompatible package note after successful update
- if ($config['version'] == $this->update_info['version']['to'])
- {
- $template->assign_var('S_ERROR', false);
- }
- break;
-
- case 'file_check':
-
- // retrieve info on what changes should have already been made to the files.
- $expected_files = $cache->get('_expected_files');
- if (!$expected_files)
- {
- $expected_files = array();
- }
-
- // Now make sure the previous file collection is no longer valid...
- $cache->destroy('_diff_files');
-
- $this->page_title = 'STAGE_FILE_CHECK';
-
- // Now make sure our update list is correct if the admin refreshes
- $action = $request->variable('action', '');
-
- // We are directly within an update. To make sure our update list is correct we check its status.
- $update_list = ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST)) ? false : $cache->get('_update_list');
- $modified = ($update_list !== false) ? @filemtime($cache->get_driver()->cache_dir . 'data_update_list.' . $phpEx) : 0;
-
- // Make sure the list is up-to-date
- if ($update_list !== false)
- {
- $get_new_list = false;
- foreach ($this->update_info['files'] as $file)
- {
- if (file_exists($phpbb_root_path . $file) && filemtime($phpbb_root_path . $file) > $modified)
- {
- $get_new_list = true;
- break;
- }
- }
- }
- else
- {
- $get_new_list = true;
- }
-
- if (!$get_new_list && $update_list['status'] != -1)
- {
- $get_new_list = true;
- }
-
- if ($get_new_list)
- {
- $this->get_update_structure($update_list, $expected_files);
- $cache->put('_update_list', $update_list);
-
- // Refresh the page if we are still not finished...
- if ($update_list['status'] != -1)
- {
- $refresh_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check");
- meta_refresh(2, $refresh_url);
-
- $template->assign_vars(array(
- 'S_IN_PROGRESS' => true,
- 'S_COLLECTED' => (int) $update_list['status'],
- 'S_TO_COLLECT' => sizeof($this->update_info['files']),
- 'L_IN_PROGRESS' => $user->lang['COLLECTING_FILE_DIFFS'],
- 'L_IN_PROGRESS_EXPLAIN' => sprintf($user->lang['NUMBER_OF_FILES_COLLECTED'], (int) $update_list['status'], sizeof($this->update_info['files']) + sizeof($this->update_info['deleted'])),
- ));
-
- return;
- }
- }
-
- if ($action == 'diff')
- {
- $this->show_diff($update_list);
- return;
- }
-
- if (sizeof($update_list['no_update']))
- {
- $template->assign_vars(array(
- 'S_NO_UPDATE_FILES' => true,
- 'NO_UPDATE_FILES' => implode(', ', array_map('htmlspecialchars', $update_list['no_update'])))
- );
- }
-
- $new_expected_files = array();
-
- // Now assign the list to the template
- foreach ($update_list as $status => $filelist)
- {
- if ($status == 'no_update' || !sizeof($filelist) || $status == 'status' || $status == 'status_deleted')
- {
- continue;
- }
-
-/* $template->assign_block_vars('files', array(
- 'S_STATUS' => true,
- 'STATUS' => $status,
- 'L_STATUS' => $user->lang['STATUS_' . strtoupper($status)],
- 'TITLE' => $user->lang['FILES_' . strtoupper($status)],
- 'EXPLAIN' => $user->lang['FILES_' . strtoupper($status) . '_EXPLAIN'],
- )
- );*/
-
- foreach ($filelist as $file_struct)
- {
- $s_binary = (!empty($this->update_info['binary']) && in_array($file_struct['filename'], $this->update_info['binary'])) ? true : false;
-
- $filename = htmlspecialchars($file_struct['filename']);
- if (strrpos($filename, '/') !== false)
- {
- $dir_part = substr($filename, 0, strrpos($filename, '/') + 1);
- $file_part = substr($filename, strrpos($filename, '/') + 1);
- }
- else
- {
- $dir_part = '';
- $file_part = $filename;
- }
-
- $diff_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check&amp;action=diff&amp;status=$status&amp;file=" . urlencode($file_struct['filename']));
-
- if (isset($file_struct['as_expected']) && $file_struct['as_expected'])
- {
- $new_expected_files[$file_struct['filename']] = $expected_files[$file_struct['filename']];
- }
- else
- {
- $template->assign_block_vars($status, array(
- 'STATUS' => $status,
-
- 'FILENAME' => $filename,
- 'DIR_PART' => $dir_part,
- 'FILE_PART' => $file_part,
- 'NUM_CONFLICTS' => (isset($file_struct['conflicts'])) ? $file_struct['conflicts'] : 0,
-
- 'S_CUSTOM' => ($file_struct['custom']) ? true : false,
- 'S_BINARY' => $s_binary,
- 'CUSTOM_ORIGINAL' => ($file_struct['custom']) ? $file_struct['original'] : '',
-
- 'U_SHOW_DIFF' => $diff_url,
- 'L_SHOW_DIFF' => ($status != 'up_to_date') ? $user->lang['SHOW_DIFF_' . strtoupper($status)] : '',
-
- 'U_VIEW_MOD_FILE' => $diff_url . '&amp;op=' . MERGE_MOD_FILE,
- 'U_VIEW_NEW_FILE' => $diff_url . '&amp;op=' . MERGE_NEW_FILE,
- 'U_VIEW_NO_MERGE_MOD' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_MOD,
- 'U_VIEW_NO_MERGE_NEW' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_NEW,
- ));
- }
- }
- }
-
- $cache->put('_expected_files', $new_expected_files);
-
- $all_up_to_date = true;
- foreach ($update_list as $status => $filelist)
- {
- if ($status != 'up_to_date' && $status != 'custom' && $status != 'status' && $status != 'status_deleted' && sizeof($filelist))
- {
- $all_up_to_date = false;
- break;
- }
- }
-
- $template->assign_vars(array(
- 'S_FILE_CHECK' => true,
- 'S_ALL_UP_TO_DATE' => $all_up_to_date,
- 'S_VERSION_UP_TO_DATE' => $up_to_date,
- 'S_UP_TO_DATE' => $up_to_date,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"),
- 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_db"),
- ));
-
- // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
- // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
- // We now try to cope with this by triggering the update process
- if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<'))
- {
- $template->assign_vars(array(
- 'S_UP_TO_DATE' => false,
- ));
- }
-
- if ($all_up_to_date)
- {
- global $phpbb_container;
-
- /* @var $phpbb_log \phpbb\log\log_interface */
- $phpbb_log = $phpbb_container->get('log');
-
- // Add database update to log
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_PHPBB', time(), array($this->current_version, $this->update_to_version));
-
- $db->sql_return_on_error(true);
- $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
- $db->sql_return_on_error(false);
-
- $cache->purge();
- }
-
- break;
-
- case 'update_files':
-
- $this->page_title = 'STAGE_UPDATE_FILES';
-
- $s_hidden_fields = '';
- $params = array();
- $conflicts = $request->variable('conflict', array('' => 0));
- $modified = $request->variable('modified', array('' => 0));
-
- foreach ($conflicts as $filename => $merge_option)
- {
- $s_hidden_fields .= '<input type="hidden" name="conflict[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
- $params[] = 'conflict[' . urlencode($filename) . ']=' . urlencode($merge_option);
- }
-
- foreach ($modified as $filename => $merge_option)
- {
- if (!$merge_option)
- {
- continue;
- }
- $s_hidden_fields .= '<input type="hidden" name="modified[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
- $params[] = 'modified[' . urlencode($filename) . ']=' . urlencode($merge_option);
- }
-
- $no_update = $request->variable('no_update', array(0 => ''));
-
- foreach ($no_update as $index => $filename)
- {
- $s_hidden_fields .= '<input type="hidden" name="no_update[]" value="' . htmlspecialchars($filename) . '" />';
- $params[] = 'no_update[]=' . urlencode($filename);
- }
-
- // Before the user is choosing his preferred method, let's create the content list...
- $update_list = $cache->get('_update_list');
-
- if ($update_list === false)
- {
- trigger_error($user->lang['NO_UPDATE_INFO'], E_USER_ERROR);
- }
-
- // Check if the conflicts data is valid
- if (sizeof($conflicts))
- {
- $conflict_filenames = array();
- foreach ($update_list['conflict'] as $files)
- {
- $conflict_filenames[] = $files['filename'];
- }
-
- $new_conflicts = array();
- foreach ($conflicts as $filename => $diff_method)
- {
- if (in_array($filename, $conflict_filenames))
- {
- $new_conflicts[$filename] = $diff_method;
- }
- }
-
- $conflicts = $new_conflicts;
- }
-
- // Build list for modifications
- if (sizeof($modified))
- {
- $modified_filenames = array();
- foreach ($update_list['modified'] as $files)
- {
- $modified_filenames[] = $files['filename'];
- }
-
- $new_modified = array();
- foreach ($modified as $filename => $diff_method)
- {
- if (in_array($filename, $modified_filenames))
- {
- $new_modified[$filename] = $diff_method;
- }
- }
-
- $modified = $new_modified;
- }
-
- // Check number of conflicting files, they need to be equal. For modified files the number can differ
- if (sizeof($update_list['conflict']) != sizeof($conflicts))
- {
- trigger_error($user->lang['MERGE_SELECT_ERROR'], E_USER_ERROR);
- }
-
- // Before we do anything, let us diff the files and store the raw file information "somewhere"
- $get_files = false;
- $file_list = $cache->get('_diff_files');
- $expected_files = $cache->get('_expected_files');
-
- if ($file_list === false || $file_list['status'] != -1)
- {
- $get_files = true;
- }
-
- if ($get_files)
- {
- if ($file_list === false)
- {
- $file_list = array(
- 'status' => 0,
- );
- }
-
- if (!isset($expected_files) || $expected_files === false)
- {
- $expected_files = array();
- }
-
- $processed = 0;
- foreach ($update_list as $status => $files)
- {
- if (!is_array($files))
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- // Skip this file if the user selected to not update it
- if (in_array($file_struct['filename'], $no_update))
- {
- $expected_files[$file_struct['filename']] = false;
- continue;
- }
-
- // Already handled... then skip of course...
- if (isset($file_list[$file_struct['filename']]))
- {
- continue;
- }
-
- // Refresh if we reach 5 diffs...
- if ($processed >= 5)
- {
- $cache->put('_diff_files', $file_list);
-
- if ($request->variable('download', false))
- {
- $params[] = 'download=1';
- }
-
- $redirect_url = append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;" . implode('&amp;', $params));
- meta_refresh(3, $redirect_url);
-
- $template->assign_vars(array(
- 'S_IN_PROGRESS' => true,
- 'L_IN_PROGRESS' => $user->lang['MERGING_FILES'],
- 'L_IN_PROGRESS_EXPLAIN' => $user->lang['MERGING_FILES_EXPLAIN'],
- ));
-
- return;
- }
-
- if (file_exists($phpbb_root_path . $file_struct['filename']))
- {
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- if (isset($expected_files[$file_struct['filename']]) && md5($contents) == $expected_files[$file_struct['filename']])
- {
- continue;
- }
- }
-
- $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
-
- switch ($status)
- {
- case 'modified':
-
- $option = (isset($modified[$file_struct['filename']])) ? $modified[$file_struct['filename']] : 0;
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- $contents = file_get_contents($this->new_location . $original_filename);
- break;
-
- case MERGE_NO_MERGE_MOD:
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- break;
-
- default:
- $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
-
- $contents = implode("\n", $diff->merged_output());
- unset($diff);
- break;
- }
-
- $expected_files[$file_struct['filename']] = md5($contents);
- $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
- $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
-
- $file_list['status']++;
- $processed++;
-
- break;
-
- case 'conflict':
-
- $option = $conflicts[$file_struct['filename']];
- $contents = '';
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- $contents = file_get_contents($this->new_location . $original_filename);
- break;
-
- case MERGE_NO_MERGE_MOD:
- $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
- break;
-
- default:
-
- $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
-
- if ($option == MERGE_NEW_FILE)
- {
- $contents = implode("\n", $diff->merged_new_output());
- }
- else if ($option == MERGE_MOD_FILE)
- {
- $contents = implode("\n", $diff->merged_orig_output());
- }
- else
- {
- unset($diff);
- break 2;
- }
-
- unset($diff);
- break;
- }
-
- $expected_files[$file_struct['filename']] = md5($contents);
- $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
- $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
-
- $file_list['status']++;
- $processed++;
-
- break;
- }
- }
- }
- $cache->put('_expected_files', $expected_files);
- }
-
- $file_list['status'] = -1;
- $cache->put('_diff_files', $file_list);
-
- if ($request->variable('download', false))
- {
- $this->include_file('includes/functions_compress.' . $phpEx);
-
- $use_method = $request->variable('use_method', '');
- $methods = array('.tar');
-
- $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
- foreach ($available_methods as $type => $module)
- {
- if (!@extension_loaded($module))
- {
- continue;
- }
-
- $methods[] = $type;
- }
-
- // Let the user decide in which format he wants to have the pack
- if (!$use_method)
- {
- $this->page_title = 'SELECT_DOWNLOAD_FORMAT';
-
- $radio_buttons = '';
- foreach ($methods as $method)
- {
- $radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>';
- }
-
- $template->assign_vars(array(
- 'S_DOWNLOAD_FILES' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'RADIO_BUTTONS' => $radio_buttons,
- 'S_HIDDEN_FIELDS' => $s_hidden_fields)
- );
-
- // To ease the update process create a file location map
- $update_list = $cache->get('_update_list');
- $script_path = ($config['force_server_vars']) ? (($config['script_path'] == '/') ? '/' : $config['script_path'] . '/') : $user->page['root_script_path'];
-
- foreach ($update_list as $status => $files)
- {
- if ($status == 'up_to_date' || $status == 'no_update' || $status == 'status' || $status == 'status_deleted')
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- if (in_array($file_struct['filename'], $no_update))
- {
- continue;
- }
-
- $template->assign_block_vars('location', array(
- 'SOURCE' => htmlspecialchars($file_struct['filename']),
- 'DESTINATION' => $script_path . htmlspecialchars($file_struct['filename']),
- ));
- }
- }
- return;
- }
-
- if (!in_array($use_method, $methods))
- {
- $use_method = '.tar';
- }
-
- $update_mode = 'download';
- }
- else
- {
- $this->include_file('includes/functions_transfer.' . $phpEx);
-
- // Choose FTP, if not available use fsock...
- $method = basename($request->variable('method', ''));
- $submit = (isset($_POST['submit'])) ? true : false;
- $test_ftp_connection = $request->variable('test_connection', '');
-
- if (!$method || !class_exists($method))
- {
- $method = 'ftp';
- $methods = transfer::methods();
-
- if (!in_array('ftp', $methods))
- {
- $method = $methods[0];
- }
- }
-
- $test_connection = false;
- if ($test_ftp_connection || $submit)
- {
- $transfer = new $method(
- $request->variable('host', ''),
- $request->variable('username', ''),
- htmlspecialchars_decode($request->untrimmed_variable('password', '')),
- $request->variable('root_path', ''),
- $request->variable('port', ''),
- $request->variable('timeout', '')
- );
- $test_connection = $transfer->open_session();
-
- // Make sure that the directory is correct by checking for the existence of common.php
- if ($test_connection === true)
- {
- // Check for common.php file
- if (!$transfer->file_exists($phpbb_root_path, 'common.' . $phpEx))
- {
- $test_connection = 'ERR_WRONG_PATH_TO_PHPBB';
- }
- }
-
- $transfer->close_session();
-
- // Make sure the login details are correct before continuing
- if ($submit && $test_connection !== true)
- {
- $submit = false;
- $test_ftp_connection = true;
- }
- }
-
- $s_hidden_fields .= build_hidden_fields(array('method' => $method));
-
- if (!$submit)
- {
- $this->page_title = 'SELECT_FTP_SETTINGS';
-
- if (!class_exists($method))
- {
- trigger_error('Method does not exist.', E_USER_ERROR);
- }
-
- $requested_data = call_user_func(array($method, 'data'));
- foreach ($requested_data as $data => $default)
- {
- $template->assign_block_vars('data', array(
- 'DATA' => $data,
- 'NAME' => $user->lang[strtoupper($method . '_' . $data)],
- 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'],
- 'DEFAULT' => $request->variable($data, (string) $default),
- ));
- }
-
- $template->assign_vars(array(
- 'S_CONNECTION_SUCCESS' => ($test_ftp_connection && $test_connection === true) ? true : false,
- 'S_CONNECTION_FAILED' => ($test_ftp_connection && $test_connection !== true) ? true : false,
- 'ERROR_MSG' => ($test_ftp_connection && $test_connection !== true) ? $user->lang[$test_connection] : '',
-
- 'S_FTP_UPLOAD' => true,
- 'UPLOAD_METHOD' => $method,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files"),
- 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=update_files&amp;download=1"),
- 'S_HIDDEN_FIELDS' => $s_hidden_fields,
- ));
-
- return;
- }
-
- $update_mode = 'upload';
- }
-
- // Now update the installation or download the archive...
- $download_filename = 'update_' . $this->update_info['version']['from'] . '_to_' . $this->update_info['version']['to'];
- $archive_filename = $download_filename . '_' . time() . '_' . unique_id();
-
- // Now init the connection
- if ($update_mode == 'download')
- {
- if ($this->filesystem->is_writable($phpbb_root_path . 'store/'))
- {
- trigger_error(sprintf('The directory “%s” is not writable.', $phpbb_root_path . 'store/'), E_USER_ERROR);
- }
-
- if ($use_method == '.zip')
- {
- $compress = new compress_zip('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method);
- }
- else
- {
- $compress = new compress_tar('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method, $use_method);
- }
- }
- else
- {
- $transfer = new $method(
- $request->variable('host', ''),
- $request->variable('username', ''),
- htmlspecialchars_decode($request->untrimmed_variable('password', '')),
- $request->variable('root_path', ''),
- $request->variable('port', ''),
- $request->variable('timeout', '')
- );
- $transfer->open_session();
- }
-
- // Ok, go through the update list and do the operations based on their status
- foreach ($update_list as $status => $files)
- {
- if (!is_array($files))
- {
- continue;
- }
-
- foreach ($files as $file_struct)
- {
- // Skip this file if the user selected to not update it
- if (in_array($file_struct['filename'], $no_update))
- {
- continue;
- }
-
- $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename'];
-
- switch ($status)
- {
- case 'new':
- case 'new_conflict':
- case 'not_modified':
-
- if ($update_mode == 'download')
- {
- $compress->add_custom_file($this->new_location . $original_filename, $file_struct['filename']);
- }
- else
- {
- if ($status != 'new')
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- }
-
- // New directory too?
- $dirname = dirname($file_struct['filename']);
-
- if ($dirname && !file_exists($phpbb_root_path . $dirname))
- {
- $transfer->make_dir($dirname);
- }
-
- $transfer->copy_file($this->new_location . $original_filename, $file_struct['filename']);
- }
- break;
-
- case 'modified':
-
- $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
-
- if ($update_mode == 'download')
- {
- $compress->add_data($contents, $file_struct['filename']);
- }
- else
- {
- // @todo add option to specify if a backup file should be created?
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- $transfer->write_file($file_struct['filename'], $contents);
- }
- break;
-
- case 'conflict':
-
- $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
-
- if ($update_mode == 'download')
- {
- $compress->add_data($contents, $file_struct['filename']);
- }
- else
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- $transfer->write_file($file_struct['filename'], $contents);
- }
- break;
-
- case 'deleted':
-
- if ($update_mode != 'download')
- {
- $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
- }
- break;
- }
- }
- }
-
- if ($update_mode == 'download')
- {
- $compress->close();
-
- $compress->download($archive_filename, $download_filename);
- @unlink($phpbb_root_path . 'store/' . $archive_filename . $use_method);
-
- exit;
- }
- else
- {
- $transfer->close_session();
-
- $template->assign_vars(array(
- 'S_UPLOAD_SUCCESS' => true,
- 'U_ACTION' => append_sid($this->p_master->module_url, "language=$language&amp;mode=$mode&amp;sub=file_check"))
- );
- return;
- }
-
- break;
-
- }
- }
-
- /**
- * Show file diff
- */
- function show_diff(&$update_list)
- {
- global $phpbb_root_path, $template, $user, $request;
-
- $this->tpl_name = 'install_update_diff';
-
- $this->page_title = 'VIEWING_FILE_DIFF';
-
- $status = $request->variable('status', '');
- $file = $request->variable('file', '');
- $diff_mode = $request->variable('diff_mode', 'inline');
-
- // First of all make sure the file is within our file update list with the correct status
- $found_entry = array();
- foreach ($update_list[$status] as $index => $file_struct)
- {
- if ($file_struct['filename'] === $file)
- {
- $found_entry = $update_list[$status][$index];
- }
- }
-
- if (empty($found_entry))
- {
- trigger_error($user->lang['FILE_DIFF_NOT_ALLOWED'], E_USER_ERROR);
- }
-
- // If the status is 'up_to_date' then we do not need to show a diff
- if ($status == 'up_to_date')
- {
- trigger_error($user->lang['FILE_ALREADY_UP_TO_DATE'], E_USER_ERROR);
- }
-
- $original_file = ($found_entry['custom']) ? $found_entry['original'] : $file;
-
- // Get the correct diff
- switch ($status)
- {
- case 'conflict':
- $option = $request->variable('op', 0);
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- case MERGE_NO_MERGE_MOD:
-
- $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- // Merge differences and use new phpBB code for conflicted blocks
- case MERGE_NEW_FILE:
- case MERGE_MOD_FILE:
-
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
-
- $template->assign_vars(array(
- 'S_DIFF_CONFLICT_FILE' => true,
- 'NUM_CONFLICTS' => $diff->get_num_conflicts())
- );
-
- $diff = $this->return_diff($phpbb_root_path . $file, ($option == MERGE_NEW_FILE) ? $diff->merged_new_output() : $diff->merged_orig_output());
- break;
-
- // Download conflict file
- default:
-
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $file, $this->new_location . $original_file);
-
- header('Pragma: no-cache');
- header("Content-Type: application/octetstream; name=\"$file\"");
- header("Content-disposition: attachment; filename=$file");
-
- @set_time_limit(0);
-
- echo implode("\n", $diff->get_conflicts_content());
-
- flush();
- exit;
-
- break;
- }
-
- break;
-
- case 'modified':
- $option = $request->variable('op', 0);
-
- switch ($option)
- {
- case MERGE_NO_MERGE_NEW:
- case MERGE_NO_MERGE_MOD:
-
- $diff = $this->return_diff(array(), ($option == MERGE_NO_MERGE_NEW) ? $this->new_location . $original_file : $phpbb_root_path . $file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- default:
- $diff = $this->return_diff($this->old_location . $original_file, $phpbb_root_path . $original_file, $this->new_location . $file);
- $diff = $this->return_diff($phpbb_root_path . $file, $diff->merged_output());
- break;
- }
- break;
-
- case 'not_modified':
- case 'new_conflict':
- $diff = $this->return_diff($phpbb_root_path . $file, $this->new_location . $original_file);
- break;
-
- case 'new':
-
- $diff = $this->return_diff(array(), $this->new_location . $original_file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
-
- case 'deleted':
-
- $diff = $this->return_diff(array(), $phpbb_root_path . $original_file);
-
- $template->assign_var('S_DIFF_NEW_FILE', true);
- $diff_mode = 'inline';
- $this->page_title = 'VIEWING_FILE_CONTENTS';
-
- break;
- }
-
- $diff_mode_options = '';
- foreach (array('side_by_side', 'inline', 'unified', 'raw') as $option)
- {
- $diff_mode_options .= '<option value="' . $option . '"' . (($diff_mode == $option) ? ' selected="selected"' : '') . '>' . $user->lang['DIFF_' . strtoupper($option)] . '</option>';
- }
-
- // Now the correct renderer
- $render_class = 'diff_renderer_' . $diff_mode;
-
- if (!class_exists($render_class))
- {
- trigger_error('Chosen diff mode is not supported', E_USER_ERROR);
- }
-
- $renderer = new $render_class();
-
- $template->assign_vars(array(
- 'DIFF_CONTENT' => $renderer->get_diff_content($diff),
- 'DIFF_MODE' => $diff_mode,
- 'S_DIFF_MODE_OPTIONS' => $diff_mode_options,
- 'S_SHOW_DIFF' => true,
- ));
-
- unset($diff, $renderer);
- }
-
- /**
- * Collect all file status infos we need for the update by diffing all files
- */
- function get_update_structure(&$update_list, $expected_files)
- {
- global $phpbb_root_path, $phpEx, $user;
-
- if ($update_list === false)
- {
- $update_list = array(
- 'up_to_date' => array(),
- 'new' => array(),
- 'not_modified' => array(),
- 'modified' => array(),
- 'new_conflict' => array(),
- 'conflict' => array(),
- 'no_update' => array(),
- 'deleted' => array(),
- 'status' => 0,
- 'status_deleted'=> 0,
- );
- }
-
- /* if (!empty($this->update_info['custom']))
- {
- foreach ($this->update_info['custom'] as $original_file => $file_ary)
- {
- foreach ($file_ary as $index => $file)
- {
- $this->make_update_diff($update_list, $original_file, $file, true);
- }
- }
- } */
-
- // Get a list of those files which are completely new by checking with file_exists...
- $num_bytes_processed = 0;
-
- foreach ($this->update_info['files'] as $index => $file)
- {
- if (is_int($update_list['status']) && $index < $update_list['status'])
- {
- continue;
- }
-
- if ($num_bytes_processed >= 500 * 1024)
- {
- return;
- }
-
- if (!file_exists($phpbb_root_path . $file))
- {
- // Make sure the update files are consistent by checking if the file is in new_files...
- if (!file_exists($this->new_location . $file))
- {
- trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
- }
-
- // If the file exists within the old directory the file got removed and we will write it back
- // not a biggie, but we might want to state this circumstance separately later.
- // if (file_exists($this->old_location . $file))
- // {
- // $update_list['removed'][] = $file;
- // }
-
- /* Only include a new file as new if the underlying path exist
- // The path normally do not exist if the original style or language has been removed
- if (file_exists($phpbb_root_path . dirname($file)))
- {
- $this->get_custom_info($update_list['new'], $file);
- $update_list['new'][] = array('filename' => $file, 'custom' => false);
- }
- else
- {
- // Do not include style-related or language-related content
- if (strpos($file, 'styles/') !== 0 && strpos($file, 'language/') !== 0)
- {
- $update_list['no_update'][] = $file;
- }
- }*/
-
- if (!phpbb_ignore_new_file_on_update($phpbb_root_path, $file))
- {
- $this->get_custom_info($update_list['new'], $file);
- $update_list['new'][] = array('filename' => $file, 'custom' => false);
- }
-
- // unset($this->update_info['files'][$index]);
- }
- else
- {
- // not modified?
- $this->make_update_diff($update_list, $file, $file, $expected_files);
- }
-
- $num_bytes_processed += (file_exists($this->new_location . $file)) ? filesize($this->new_location . $file) : 100 * 1024;
- $update_list['status']++;
- }
-
- foreach ($this->update_info['deleted'] as $index => $file)
- {
- if (is_int($update_list['status_deleted']) && $index < $update_list['status_deleted'])
- {
- continue;
- }
-
- if ($num_bytes_processed >= 500 * 1024)
- {
- return;
- }
-
- if (file_exists($phpbb_root_path . $file))
- {
- $update_list['deleted'][] = array('filename' => $file, 'custom' => false, 'as_expected' => false);
- $num_bytes_processed += filesize($phpbb_root_path . $file);
- }
-
- $update_list['status_deleted']++;
- $update_list['status']++;
- }
-
- $update_list['status_deleted'] = -1;
- $update_list['status'] = -1;
-
-/* if (!sizeof($this->update_info['files']))
- {
- return $update_list;
- }
-
- // Now diff the remaining files to get information about their status (not modified/modified/up-to-date)
-
- // not modified?
- foreach ($this->update_info['files'] as $index => $file)
- {
- $this->make_update_diff($update_list, $file, $file);
- }
-
- // Now to the styles...
- if (empty($this->update_info['custom']))
- {
- return $update_list;
- }
-
- foreach ($this->update_info['custom'] as $original_file => $file_ary)
- {
- foreach ($file_ary as $index => $file)
- {
- $this->make_update_diff($update_list, $original_file, $file, true);
- }
- }
-
- return $update_list;*/
- }
-
- /**
- * Compare files for storage in update_list
- */
- function make_update_diff(&$update_list, $original_file, $file, $expected_files, $custom = false)
- {
- global $phpbb_root_path, $user;
-
- $update_ary = array('filename' => $file, 'custom' => $custom, 'as_expected' => false);
-
- if ($custom)
- {
- $update_ary['original'] = $original_file;
- }
-
- if (file_exists($phpbb_root_path . $file))
- {
- $content = file_get_contents($phpbb_root_path . $file);
-
- if (isset($expected_files[$file]) && // the user already selected what to do with this file
- ($expected_files[$file] === false || // the user wanted this file to stay the same, so just assume it's alright
- $expected_files[$file] === md5($content)))
- {
- // the file contains what it was supposed to contain after the merge
- $update_ary['as_expected'] = true;
- $update_ary['was_ignored'] = ($expected_files[$file] === false);
- $update_list['up_to_date'][] = $update_ary;
-
- return;
- }
- }
-
- // we only want to know if the files are successfully merged and newlines could result in errors (duplicate addition of lines and such things)
- // Therefore we check for empty diffs with two methods, preserving newlines and not preserving them (which mostly works best, therefore the first option)
-
- // On a successfull update the new location file exists but the old one does not exist.
- // Check for this circumstance, the new file need to be up-to-date with the current file then...
- if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file))
- {
- $tmp = array(
- 'file1' => file_get_contents($this->new_location . $original_file),
- 'file2' => $content,
- );
-
- // We need to diff the contents here to make sure the file is really the one we expect
- $diff = new diff($tmp['file1'], $tmp['file2'], false);
- $empty = $diff->is_empty();
-
- unset($tmp, $diff);
-
- // if there are no differences we have an up-to-date file...
- if ($empty)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- // If no other status matches we have another file in the way...
- $update_list['new_conflict'][] = $update_ary;
- return;
- }
-
- // Old file removed?
- if (file_exists($this->old_location . $original_file) && !file_exists($this->new_location . $original_file))
- {
- return;
- }
-
- // Check for existance, else abort immediately
- if (!file_exists($this->old_location . $original_file) || !file_exists($this->new_location . $original_file))
- {
- trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
- }
-
- $preserve_cr_ary = array(false, true);
-
- foreach ($preserve_cr_ary as $preserve_cr)
- {
- $tmp = array(
- 'file1' => file_get_contents($this->old_location . $original_file),
- 'file2' => $content,
- );
-
- // We need to diff the contents here to make sure the file is really the one we expect
- $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty_1 = $diff->is_empty();
-
- unset($tmp, $diff);
-
- $tmp = array(
- 'file1' => file_get_contents($this->new_location . $original_file),
- 'file2' => $content,
- );
-
- $diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty_2 = $diff->is_empty();
-
- unset($tmp, $diff);
-
- // If the file is not modified we are finished here...
- if ($empty_1)
- {
- // Further check if it is already up to date - it could happen that non-modified files
- // slip through
- if ($empty_2)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- $update_list['not_modified'][] = $update_ary;
- return;
- }
-
- // If the file had been modified then we need to check if it is already up to date
-
- // if there are no differences we have an up-to-date file...
- if ($empty_2)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
- }
-
- $conflicts = false;
-
- foreach ($preserve_cr_ary as $preserve_cr)
- {
- // if the file is modified we try to make sure a merge succeed
- $tmp = array(
- 'orig' => file_get_contents($this->old_location . $original_file),
- 'final1' => file_get_contents($phpbb_root_path . $file),
- 'final2' => file_get_contents($this->new_location . $original_file),
- );
-
- $diff = new diff3($tmp['orig'], $tmp['final1'], $tmp['final2'], $preserve_cr);
- unset($tmp);
-
- if (!$diff->get_num_conflicts())
- {
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_output()),
- );
-
- // now compare the merged output with the original file to see if the modified file is up to date
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
-
- unset($diff, $diff2);
-
- if ($empty)
- {
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
-
- // If we preserve cr tag it as modified because the conflict would not show in this mode anyway
- if ($preserve_cr)
- {
- $update_list['modified'][] = $update_ary;
- return;
- }
- }
- else
- {
- // There is one special case... users having merged with a conflicting file... we need to check this
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_new_output()),
- );
-
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
-
- if (!$empty)
- {
- unset($tmp, $diff2);
-
- // We check if the user merged with his output
- $tmp = array(
- 'file1' => file_get_contents($phpbb_root_path . $file),
- 'file2' => implode("\n", $diff->merged_orig_output()),
- );
-
- $diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
- $empty = $diff2->is_empty();
- }
-
- if (!$empty)
- {
- $conflicts = $diff->get_num_conflicts();
- }
-
- unset($diff, $diff2);
-
- if ($empty)
- {
- // A conflict got resolved...
- $update_list['up_to_date'][] = $update_ary;
- return;
- }
- }
- }
-
- if ($conflicts !== false)
- {
- $update_ary['conflicts'] = $conflicts;
- $update_list['conflict'][] = $update_ary;
- return;
- }
-
- // If no other status matches we have a modified file...
- $update_list['modified'][] = $update_ary;
- }
-
- /**
- * Update update_list with custom new files
- */
- function get_custom_info(&$update_list, $file)
- {
- if (empty($this->update_info['custom']))
- {
- return;
- }
-
- if (isset($this->update_info['custom'][$file]))
- {
- foreach ($this->update_info['custom'][$file] as $_file)
- {
- $update_list[] = array('filename' => $_file, 'custom' => true, 'original' => $file);
- }
- }
- }
-
- /**
- * Get remote file
- */
- function get_file($mode)
- {
- global $user;
-
- $errstr = '';
-
- switch ($mode)
- {
- case 'update_info':
- global $phpbb_root_path, $phpEx;
-
- $update_info = array();
- include($phpbb_root_path . 'install/update/index.' . $phpEx);
-
- $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
- $errstr = ($info === false) ? $user->lang['WRONG_INFO_FILE_FORMAT'] : '';
-
- if ($info !== false)
- {
- // We assume that all file extensions have been renamed to .$phpEx,
- // if someone is using a non .php file extension for php files.
- // However, in $update_info['files'] we use hardcoded .php.
- // We therefore replace .php with .$phpEx.
- $info['files'] = preg_replace('/\.php$/i', ".$phpEx", $info['files']);
-
- // Adjust the update info file to hold some specific style-related information
- $info['custom'] = array();
-/*
- // Get custom installed styles...
- $sql = 'SELECT style_name, style_path
- FROM ' . STYLES_TABLE . "
- WHERE LOWER(style_name) NOT IN ('prosilver')";
- $result = $db->sql_query($sql);
-
- $templates = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $templates[] = $row;
- }
- $db->sql_freeresult($result);
-
- if (sizeof($templates))
- {
- foreach ($info['files'] as $filename)
- {
- // Template update?
- if (strpos(strtolower($filename), 'styles/prosilver/template/') === 0)
- {
- foreach ($templates as $row)
- {
- $info['custom'][$filename][] = str_replace('/prosilver/', '/' . $row['style_path'] . '/', $filename);
- }
- }
- }
- }
-*/
- }
- break;
-
- default:
- trigger_error('Mode for getting remote file not specified', E_USER_ERROR);
- break;
- }
-
- if ($info === false)
- {
- trigger_error($errstr, E_USER_ERROR);
- }
-
- return $info;
- }
-
- /**
- * Function for including files...
- */
- function include_file($filename)
- {
- global $phpbb_root_path, $phpEx;
-
- if (!empty($this->update_info['files']) && in_array($filename, $this->update_info['files']))
- {
- include_once($this->new_location . $filename);
- }
- else
- {
- include_once($phpbb_root_path . $filename);
- }
- }
-
- /**
- * Wrapper for returning a diff object
- */
- function return_diff()
- {
- $args = func_get_args();
- $three_way_diff = (func_num_args() > 2) ? true : false;
-
- $file1 = array_shift($args);
- $file2 = array_shift($args);
-
- $tmp['file1'] = (!empty($file1) && is_string($file1)) ? file_get_contents($file1) : $file1;
- $tmp['file2'] = (!empty($file2) && is_string($file2)) ? file_get_contents($file2) : $file2;
-
- if ($three_way_diff)
- {
- $file3 = array_shift($args);
- $tmp['file3'] = (!empty($file3) && is_string($file3)) ? file_get_contents($file3) : $file3;
-
- $diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3']);
- }
- else
- {
- $diff = new diff($tmp['file1'], $tmp['file2']);
- }
-
- unset($tmp);
-
- return $diff;
- }
-}
diff --git a/phpBB/install_new/phpbbcli.php b/phpBB/install/phpbbcli.php
index 49a2920900..e36922f1a5 100644..100755
--- a/phpBB/install_new/phpbbcli.php
+++ b/phpBB/install/phpbbcli.php
@@ -12,6 +12,8 @@
*
*/
+use Symfony\Component\Console\Input\ArgvInput;
+
if (php_sapi_name() !== 'cli')
{
echo 'This program must be run from the command line.' . PHP_EOL;
@@ -27,16 +29,18 @@ $phpEx = substr(strrchr(__FILE__, '.'), 1);
//
// Let's do the common.php logic
//
-$startup_new_path = $phpbb_root_path . 'install/update/update/new/install_new/startup.' . $phpEx;
-$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install_new/startup.' . $phpEx;
+$startup_new_path = $phpbb_root_path . 'install/update/update/new/install/startup.' . $phpEx;
+$startup_path = (file_exists($startup_new_path)) ? $startup_new_path : $phpbb_root_path . 'install/startup.' . $phpEx;
require($startup_path);
+$input = new ArgvInput();
+
/** @var \phpbb\filesystem\filesystem $phpbb_filesystem */
$phpbb_filesystem = $phpbb_installer_container->get('filesystem');
/** @var \phpbb\language\language $language */
$language = $phpbb_installer_container->get('language');
-$language->add_lang(array('common', 'acp/common', 'acp/board', 'install_new', 'posting', 'cli'));
+$language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting', 'cli'));
$application = new \phpbb\console\application('phpBB Installer', PHPBB_VERSION, $language);
$application->setDispatcher($phpbb_installer_container->get('dispatcher'));
diff --git a/phpBB/install/phpinfo.php b/phpBB/install/phpinfo.php
deleted file mode 100644
index 1512b00563..0000000000
--- a/phpBB/install/phpinfo.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-phpinfo();
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index 680341b855..5cf5af6ddc 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -275,7 +275,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0
INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0');
-INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a1-dev');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a2-dev');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400');
diff --git a/phpBB/install_new/startup.php b/phpBB/install/startup.php
index 766f6be38a..0d3e01efaa 100644
--- a/phpBB/install_new/startup.php
+++ b/phpBB/install/startup.php
@@ -47,6 +47,48 @@ function phpbb_include_updated($path, $phpbb_root_path, $optional = false)
}
}
+function installer_msg_handler($errno, $msg_text, $errfile, $errline)
+{
+ global $phpbb_installer_container;
+
+ switch ($errno)
+ {
+ case E_NOTICE:
+ case E_WARNING:
+ case E_USER_WARNING:
+ case E_USER_NOTICE:
+ $msg = '[phpBB debug] "' . $msg_text . '" in file ' . $errfile . ' on line ' . $errline;
+
+ try
+ {
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $phpbb_installer_container->get('installer.helper.iohandler');
+ $iohandler->add_warning_message($msg);
+ }
+ catch (\phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception $e)
+ {
+ print ($msg);
+ }
+ break;
+ case E_USER_ERROR:
+ $msg = '<b>General Error:</b><br />' . $msg_text . '<br /> in file ' . $errfile . ' on line ' . $errline;
+
+ $backtrace = get_backtrace();
+ if ($backtrace)
+ {
+ $msg .= '<br /><br />BACKTRACE<br />' . $backtrace;
+ }
+
+ throw new \phpbb\exception\runtime_exception($msg);
+ break;
+ case E_DEPRECATED:
+ return true;
+ break;
+ }
+
+ return false;
+}
+
phpbb_require_updated('includes/startup.' . $phpEx, $phpbb_root_path);
phpbb_require_updated('phpbb/class_loader.' . $phpEx, $phpbb_root_path);
@@ -69,7 +111,7 @@ phpbb_require_updated('includes/functions_user.' . $phpEx, $phpbb_root_path);
phpbb_require_updated('includes/utf/utf_tools.' . $phpEx, $phpbb_root_path);
// Set PHP error handler to ours
-set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler');
+set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'installer_msg_handler');
$phpbb_installer_container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
$phpbb_installer_container_builder
@@ -81,4 +123,5 @@ $config_path = (file_exists($other_config_path . '/installer/config.yml')) ? $ot
$phpbb_installer_container = $phpbb_installer_container_builder
->with_config_path($config_path)
+ ->with_custom_parameters(array('cache.driver.class' => 'phpbb\cache\driver\file'))
->get_container();
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 32a3593257..a1e2d1ef40 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -231,6 +231,7 @@ $lang = array_merge($lang, array(
'CRON_NO_SUCH_TASK' => 'Could not find cron task “%s”.',
'CRON_NO_TASK' => 'No cron tasks need to be run right now.',
'CRON_NO_TASKS' => 'No cron tasks could be found.',
+ 'CURRENT_VERSION' => 'Current version',
'DEACTIVATE' => 'Deactivate',
'DIRECTORY_DOES_NOT_EXIST' => 'The entered path “%s” does not exist.',
@@ -256,6 +257,7 @@ $lang = array_merge($lang, array(
'IP' => 'User IP',
'IP_HOSTNAME' => 'IP addresses or hostnames',
+ 'LATEST_VERSION' => 'Latest version',
'LOAD_NOTIFICATIONS' => 'Display Notifications',
'LOAD_NOTIFICATIONS_EXPLAIN' => 'Display the notifications list on every page (typically in the header).',
'LOGGED_IN_AS' => 'You are logged in as:',
@@ -288,6 +290,7 @@ $lang = array_merge($lang, array(
'PERMISSIONS_TRANSFERRED_EXPLAIN' => 'You currently have the permissions from %1$s. You are able to browse the board with this user’s permissions, but not access the administration control panel since admin permissions were not transferred. You can <a href="%2$s"><strong>revert to your permission set</strong></a> at any time.',
'PROCEED_TO_ACP' => '%sProceed to the ACP%s',
+ 'RELEASE_ANNOUNCEMENT' => 'Announcement',
'REMIND' => 'Remind',
'REPARSE_LOCK_ERROR' => 'Reparsing is already in progress by another process.',
'RESYNC' => 'Resynchronise',
@@ -421,6 +424,11 @@ $lang = array_merge($lang, array(
'VALUE' => 'Value',
'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.',
'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version',
+ 'VERSION_CHECK' => 'Version check',
+ 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
+ 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.<br />Below is a link to the release announcement, which contains more information as well as instructions on updating.',
+ 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.',
+ 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
'VIEW_ADMIN_LOG' => 'View administrator log',
'VIEW_INACTIVE_USERS' => 'View inactive users',
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index f6b9bce58b..a473e0d091 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -698,8 +698,10 @@ $lang = array_merge($lang, array(
'SORRY_AUTH_READ_TOPIC' => 'You are not authorised to read this topic.',
'SORRY_AUTH_VIEW_ATTACH' => 'You are not authorised to download this attachment.',
'SORT_BY' => 'Sort by',
+ 'SORT_DIRECTION' => 'Direction',
'SORT_JOINED' => 'Joined date',
'SORT_LOCATION' => 'Location',
+ 'SORT_OPTIONS' => 'Display and sorting options',
'SORT_RANK' => 'Rank',
'SORT_POSTS' => 'Posts',
'SORT_TOPIC_TITLE' => 'Topic title',
diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php
index d3b36d8015..e9f3562646 100644
--- a/phpBB/language/en/help/bbcode.php
+++ b/phpBB/language/en/help/bbcode.php
@@ -35,13 +35,13 @@ $lang = array_merge($lang, array(
'HELP_BBCODE_IMAGES_ATTACHMENT_ANSWER' => 'Attachments can now be placed in any part of a post by using the new <strong>[attachment=][/attachment]</strong> BBCode, if the attachments functionality has been enabled by a board administrator and if you are given the appropriate permissions to create attachments. Within the posting screen is a drop-down box (respectively a button) for placing attachments inline.',
'HELP_BBCODE_IMAGES_ATTACHMENT_QUESTION' => 'Adding attachments into a post',
- 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => 'phpBB BBCode incorporates a tag for including images in your posts. Two very important things to remember when using this tag are: many users do not appreciate lots of images being shown in posts and secondly the image you display must already be available on the internet (it cannot exist only on your computer for example, unless you run a webserver!). To display an image you must surround the URL pointing to the image with <strong>[img][/img]</strong> tags. For example:<br /><br /><strong>[img]</strong>http://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img]</strong><br /><br />As noted in the URL section above you can wrap an image in a <strong>[url][/url]</strong> tag if you wish, e.g.<br /><br /><strong>[url=http://www.phpbb.com/][img]</strong>http://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img][/url]</strong><br /><br />would generate:<br /><br /><a href="http://www.phpbb.com/"><img src="http://www.phpbb.com/theme/images/logos/blue/160x52.png" alt="" /></a>',
+ 'HELP_BBCODE_IMAGES_BASIC_ANSWER' => 'phpBB BBCode incorporates a tag for including images in your posts. Two very important things to remember when using this tag are: many users do not appreciate lots of images being shown in posts and secondly the image you display must already be available on the internet (it cannot exist only on your computer for example, unless you run a webserver!). To display an image you must surround the URL pointing to the image with <strong>[img][/img]</strong> tags. For example:<br /><br /><strong>[img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img]</strong><br /><br />As noted in the URL section above you can wrap an image in a <strong>[url][/url]</strong> tag if you wish, e.g.<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/img][/url]</strong><br /><br />would generate:<br /><br /><a href="https://www.phpbb.com/"><img src="https://www.phpbb.com/theme/images/logos/blue/160x52.png" alt="" /></a>',
'HELP_BBCODE_IMAGES_BASIC_QUESTION' => 'Adding an image to a post',
'HELP_BBCODE_INTRO_BBCODE_ANSWER' => 'BBCode is a special implementation of HTML. Whether you can actually use BBCode in your posts on the forum is determined by the administrator. In addition you can disable BBCode on a per post basis via the posting form. BBCode itself is similar in style to HTML, tags are enclosed in square brackets [ and ] rather than &lt; and &gt; and it offers greater control over what and how something is displayed. Depending on the template you are using you may find adding BBCode to your posts is made much easier through a clickable interface above the message area on the posting form. Even with this you may find the following guide useful.',
'HELP_BBCODE_INTRO_BBCODE_QUESTION' => 'What is BBCode?',
- 'HELP_BBCODE_LINKS_BASIC_ANSWER' => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.<ul><li>The first of these uses the <strong>[url=][/url]</strong> tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:<br /><br /><strong>[url=http://www.phpbb.com/]</strong>Visit phpBB!<strong>[/url]</strong><br /><br />This would generate the following link, <a href="http://www.phpbb.com/">Visit phpBB!</a> Please notice that the link opens in the same window or a new window depending on the users browser preferences.</li><li>If you want the URL itself displayed as the link you can do this by simply using:<br /><br /><strong>[url]</strong>http://www.phpbb.com/<strong>[/url]</strong><br /><br />This would generate the following link, <a href="http://www.phpbb.com/">http://www.phpbb.com/</a></li><li>Additionally, phpBB features something called <i>Magic Links</i>, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to <a href="http://www.phpbb.com/">www.phpbb.com</a> being output when you view the message.</li><li>The same thing applies equally to email addresses, you can either specify an address explicitly for example:<br /><br /><strong>[email]</strong>no.one@domain.adr<strong>[/email]</strong><br /><br />which will output <a href="mailto:no.one@domain.adr">no.one@domain.adr</a> or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.</li></ul>As with all the BBCode tags you can wrap URLs around any of the other tags such as <strong>[img][/img]</strong> (see next entry), <strong>[b][/b]</strong>, etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:<br /><br /><strong>[url=http://www.phpbb.com/][img]</strong>http://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/url][/img]</strong><br /><br />is <span style="text-decoration: underline">not</span> correct which may lead to your post being deleted so take care.',
+ 'HELP_BBCODE_LINKS_BASIC_ANSWER' => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.<ul><li>The first of these uses the <strong>[url=][/url]</strong> tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:<br /><br /><strong>[url=https://www.phpbb.com/]</strong>Visit phpBB!<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">Visit phpBB!</a> Please notice that the link opens in the same window or a new window depending on the users browser preferences.</li><li>If you want the URL itself displayed as the link you can do this by simply using:<br /><br /><strong>[url]</strong>https://www.phpbb.com/<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">https://www.phpbb.com/</a></li><li>Additionally, phpBB features something called <i>Magic Links</i>, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to <a href="http://www.phpbb.com/">www.phpbb.com</a> being output when you view the message.</li><li>The same thing applies equally to email addresses, you can either specify an address explicitly for example:<br /><br /><strong>[email]</strong>no.one@domain.adr<strong>[/email]</strong><br /><br />which will output <a href="mailto:no.one@domain.adr">no.one@domain.adr</a> or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.</li></ul>As with all the BBCode tags you can wrap URLs around any of the other tags such as <strong>[img][/img]</strong> (see next entry), <strong>[b][/b]</strong>, etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/url][/img]</strong><br /><br />is <span style="text-decoration: underline">not</span> correct which may lead to your post being deleted so take care.',
'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'Linking to another site',
'HELP_BBCODE_LISTS_ORDERER_ANSWER' => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use <strong>[list=1][/list]</strong> to create a numbered list or alternatively <strong>[list=a][/list]</strong> for an alphabetical list. As with the unordered list, items are specified using <strong>[*]</strong>. For example:<br /><br /><strong>[list=1]</strong><br /><strong>[*]</strong>Go to the shops<br /><strong>[*]</strong>Buy a new computer<br /><strong>[*]</strong>Swear at computer when it crashes<br /><strong>[/list]</strong><br /><br />will generate the following:<ol style="list-style-type: decimal;"><li>Go to the shops</li><li>Buy a new computer</li><li>Swear at computer when it crashes</li></ol>Whereas for an alphabetical list you would use:<br /><br /><strong>[list=a]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol>',
diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php
index 5d26e22423..6097bd66bb 100644
--- a/phpBB/language/en/install.php
+++ b/phpBB/language/en/install.php
@@ -1,19 +1,19 @@
<?php
/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
/**
-* DO NOT CHANGE
-*/
+ * DO NOT CHANGE
+ */
if (!defined('IN_PHPBB'))
{
exit;
@@ -36,166 +36,27 @@ if (empty($lang) || !is_array($lang))
// equally where a string contains only two placeholders which are used to wrap text
// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
+// Common installer pages
$lang = array_merge($lang, array(
- 'ADMIN_CONFIG' => 'Administrator configuration',
- 'ADMIN_PASSWORD' => 'Administrator password',
- 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password',
- 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.',
- 'ADMIN_TEST' => 'Check administrator settings',
- 'ADMIN_USERNAME' => 'Administrator username',
- 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.',
- 'APP_MAGICK' => 'Imagemagick support [ Attachments ]',
- 'AUTHOR_NOTES' => 'Author notes<br />» %s',
- 'AVAILABLE' => 'Available',
- 'AVAILABLE_CONVERTORS' => 'Available convertors',
-
- 'BEGIN_CONVERT' => 'Begin conversion',
- 'BLANK_PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using no table prefix.',
- 'BOARD_NOT_INSTALLED' => 'No installation found',
- 'BOARD_NOT_INSTALLED_EXPLAIN' => 'The phpBB Unified Convertor Framework requires a default installation of phpBB3 to function, please <a href="%s">proceed by first installing phpBB3</a>.',
- 'BACKUP_NOTICE' => 'Please backup your board before updating in case any problems arise during the update process.',
-
- 'CATEGORY' => 'Category',
- 'CACHE_STORE' => 'Cache type',
- 'CACHE_STORE_EXPLAIN' => 'The physical location where data is cached, filesystem is preferred.',
- 'CAT_CONVERT' => 'Convert',
- 'CAT_INSTALL' => 'Install',
- 'CAT_OVERVIEW' => 'Overview',
- 'CAT_UPDATE' => 'Update',
- 'CHANGE' => 'Change',
- 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.',
- 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure',
- 'CLEANING_USERNAMES' => 'Cleaning usernames',
- 'COLLIDING_CLEAN_USERNAME' => '<strong>%s</strong> is the clean username for:',
- 'COLLIDING_USERNAMES_FOUND' => 'Colliding usernames were found on your old board. In order to complete the conversion please delete or rename these users so that there is only one user on your old board for each clean username.',
- 'COLLIDING_USER' => '» user id: <strong>%d</strong> username: <strong>%s</strong> (%d posts)',
- 'CONFIG_CONVERT' => 'Converting the configuration',
- 'CONFIG_FILE_UNABLE_WRITE' => 'It was not possible to write the configuration file. Alternative methods for this file to be created are presented below.',
- 'CONFIG_FILE_WRITTEN' => 'The configuration file has been written. You may now proceed to the next step of the installation.',
- 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s” is empty.',
- 'CONFIG_RETRY' => 'Retry',
- 'CONTINUE_CONVERT' => 'Continue conversion',
- 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.',
- 'CONTINUE_LAST' => 'Continue last statements',
- 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion',
- 'CONVERT' => 'Convert',
- 'CONVERT_COMPLETE' => 'Conversion completed',
- 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.1. You can now login and <a href="../">access your board</a>. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">Documentation</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">support forums</a>.',
- 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework',
- 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.',
- 'CONVERT_NEW_CONVERSION' => 'New conversion',
- 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.',
- 'CONVERT_OPTIONS' => 'Options',
- 'CONVERT_SETTINGS_VERIFIED' => 'The information you entered has been verified. To start the conversion process, please push the button below.',
- 'CONV_ERR_FATAL' => 'Fatal conversion error',
-
- 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.',
- 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.',
- 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.',
- 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.',
- 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.',
- 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%s”.',
- 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.',
- 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.',
- 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.',
- 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.',
- 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.',
- 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error',
- 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.',
- 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.',
- 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.',
- 'CONV_ERROR_NO_GROUP' => 'Group “%1$s” could not be found in %2$s.',
- 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.',
- 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.',
- 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.',
- 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.',
- 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.',
- 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.',
- 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.',
- 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.',
- 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s” defined in %2$s.',
- 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.',
- 'CONV_SAVED_MESSAGES' => 'Saved messages',
-
- 'COULD_NOT_COPY' => 'Could not copy file <strong>%1$s</strong> to <strong>%2$s</strong><br /><br />Please check that the target directory exists and is writable by the webserver.',
- 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.<br />» %s was specified as the source path.',
-
- 'DBMS' => 'Database type',
- 'DB_CONFIG' => 'Database configuration',
- 'DB_CONNECTION' => 'Database connection',
- 'DB_ERR_INSERT' => 'Error while processing <code>INSERT</code> query.',
- 'DB_ERR_LAST' => 'Error while processing <var>query_last</var>.',
- 'DB_ERR_QUERY_FIRST' => 'Error while executing <var>query_first</var>.',
- 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing <var>query_first</var>, %s (“%s”).',
- 'DB_ERR_SELECT' => 'Error while running <code>SELECT</code> query.',
- 'DB_HOST' => 'Database server hostname or DSN',
- 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.',
- 'DB_NAME' => 'Database name',
- 'DB_PASSWORD' => 'Database password',
- 'DB_PORT' => 'Database server port',
- 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.',
- 'DB_UPDATE_NOT_SUPPORTED' => 'We are sorry, but this script does not support updating from versions of phpBB prior to “%1$s”. The version you currently have installed is “%2$s”. Please update to a previous version before running this script. Assistance with this is available in the Support Forum on phpBB.com.',
- 'DB_USERNAME' => 'Database username',
- 'DB_TEST' => 'Test connection',
- 'DEFAULT_LANG' => 'Default board language',
- 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is <strong>%2$s</strong>.',
- 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.',
- 'DIRECTORIES_AND_FILES' => 'Directory and file setup',
- 'DISABLE_KEYS' => 'Disabling keys',
- 'DLL_FTP' => 'Remote FTP support [ Installation ]',
- 'DLL_GD' => 'GD graphics support [ Visual Confirmation ]',
- 'DLL_MBSTRING' => 'Multi-byte character support',
- 'DLL_MSSQL' => 'MSSQL Server 2000+',
- 'DLL_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
- 'DLL_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
- 'DLL_MYSQL' => 'MySQL',
- 'DLL_MYSQLI' => 'MySQL with MySQLi Extension',
- 'DLL_ORACLE' => 'Oracle',
- 'DLL_POSTGRES' => 'PostgreSQL',
- 'DLL_SQLITE' => 'SQLite 2',
- 'DLL_SQLITE3' => 'SQLite 3',
- 'DLL_XML' => 'XML support [ Jabber ]',
- 'DLL_ZLIB' => 'zlib compression support [ gz, .tar.gz, .zip ]',
- 'DL_CONFIG' => 'Download config',
- 'DL_CONFIG_EXPLAIN' => 'You may download the complete config.php to your own PC. You will then need to upload the file manually, replacing any existing config.php in your phpBB 3.1 root directory. Please remember to upload the file in ASCII format (see your FTP application documentation if you are unsure how to achieve this). When you have uploaded the config.php please click “Done” to move to the next stage.',
- 'DL_DOWNLOAD' => 'Download',
- 'DONE' => 'Done',
-
- 'ENABLE_KEYS' => 'Re-enabling keys. This can take a while.',
-
- 'FILES_OPTIONAL' => 'Optional files and directories',
- 'FILES_OPTIONAL_EXPLAIN' => '<strong>Optional</strong> - These files, directories or permission settings are not required. The installation system will attempt to use various techniques to create them if they do not exist or cannot be written to. However, the presence of these will speed installation.',
- 'FILES_REQUIRED' => 'Files and Directories',
- 'FILES_REQUIRED_EXPLAIN' => '<strong>Required</strong> - In order to function correctly phpBB needs to be able to access or write to certain files or directories. If you see “Not Found” you need to create the relevant file or directory. If you see “Unwritable” you need to change the permissions on the file or directory to allow phpBB to write to it.',
- 'FILLING_TABLE' => 'Filling table <strong>%s</strong>',
- 'FILLING_TABLES' => 'Filling tables',
-
- 'FINAL_STEP' => 'Process final step',
- 'FORUM_ADDRESS' => 'Board address',
- 'FORUM_ADDRESS_EXPLAIN' => 'This is the URL of your former board, for example <samp>http://www.example.com/phpBB2/</samp>. If an address is entered here and not left empty every instance of this address will be replaced by your new board address within messages, private messages and signatures.',
- 'FORUM_PATH' => 'Board path',
- 'FORUM_PATH_EXPLAIN' => 'This is the <strong>relative</strong> path on disk to your former board from the <strong>root of this phpBB3 installation</strong>.',
- 'FOUND' => 'Found',
- 'FTP_CONFIG' => 'Transfer config by FTP',
- 'FTP_CONFIG_EXPLAIN' => 'phpBB has detected the presence of the FTP module on this server. You may attempt to install your config.php via this if you wish. You will need to supply the information listed below. Remember your username and password are those to your server! (ask your hosting provider for details if you are unsure what these are).',
- 'FTP_PATH' => 'FTP path',
- 'FTP_PATH_EXPLAIN' => 'This is the path from your root directory to that of phpBB, e.g. <samp>htdocs/phpBB3/</samp>.',
- 'FTP_UPLOAD' => 'Upload',
-
- 'GPL' => 'General Public License',
-
- 'INITIAL_CONFIG' => 'Basic configuration',
- 'INITIAL_CONFIG_EXPLAIN' => 'Now that install has determined your server can run phpBB you need to supply some specific information. If you do not know how to connect to your database please contact your hosting provider (in the first instance) or use the phpBB support forums. When entering data please ensure you check it thoroughly before continuing.',
- 'INSTALL_CONGRATS' => 'Congratulations!',
- 'INSTALL_CONGRATS_EXPLAIN' => '
- You have successfully installed phpBB %1$s. Please proceed by choosing one of the following options:</p>
- <h2>Convert an existing board to phpBB3</h2>
- <p>The phpBB Unified Convertor Framework supports the conversion of phpBB 2.0.x and other board systems to phpBB3. If you have an existing board that you wish to convert, please <a href="%2$s">proceed to the convertor</a>.</p>
- <h2>Go live with your phpBB3!</h2>
- <p>Clicking the button below will take you to a form for submitting statistical data to phpBB in your Administration Control Panel (ACP). We would appreciate it if you could help us by sending that information. Afterwards you should take some time to examine the options available to you. Remember that help is available online via the <a href="https://www.phpbb.com/support/docs/en/3.1/ug/">Documentation</a>, <a href="%3$s">README</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">Support Forums</a>.</p><p><strong>Please delete, move or rename the install directory before using your board. While this directory exists, only the Administration Control Panel (ACP) will be accessible.</strong>',
- 'INSTALL_INTRO' => 'Welcome to Installation',
-
- 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.</p><p>In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:</p>
+ 'INSTALL_PANEL' => 'Installation Panel',
+ 'SELECT_LANG' => 'Select language',
+
+ 'STAGE_INSTALL' => 'Installing phpBB',
+
+ // Introduction page
+ 'INTRODUCTION_TITLE' => 'Introduction',
+ 'INTRODUCTION_BODY' => 'Welcome to phpBB3!<br /><br />phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.<br /><br />This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read <a href="../docs/INSTALL.html">the installation guide</a>.<br /><br />To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.',
+
+ // Support page
+ 'SUPPORT_TITLE' => 'Support',
+ 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:</p><ul><li>installation</li><li>configuration</li><li>technical questions</li><li>problems relating to potential bugs in the software</li><li>updating from Release Candidate (RC) versions to the latest stable version</li><li>converting from phpBB 2.0.x to phpBB3</li><li>converting from other discussion board software to phpBB3 (please see the <a href="https://www.phpbb.com/community/viewforum.php?f=486">Convertors Forum</a>)</li></ul><p>We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.</p><h2>Extensions / Styles</h2><p>For issues relating to Extensions, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=451">Extensions Forum</a>.<br />For issues relating to styles, templates and themes, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=471">Styles Forum</a>.<br /><br />If your question relates to a specific package, please post directly in the topic dedicated to the package.</p><h2>Obtaining Support</h2><p><a href="https://www.phpbb.com/community/viewtopic.php?f=14&amp;t=571070">The phpBB Welcome Package</a><br /><a href="https://www.phpbb.com/support/">Support Section</a><br /><a href="https://www.phpbb.com/support/docs/en/3.1/ug/quickstart/">Quick Start Guide</a><br /><br />To ensure you stay up to date with the latest news and releases, why not <a href="https://www.phpbb.com/support/">subscribe to our mailing list</a>?<br /><br />',
+
+ // License
+ 'LICENSE_TITLE' => 'General Public License',
+
+ // Install page
+ 'INSTALL_INTRO' => 'Welcome to Installation',
+ 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.</p><p>In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:</p>
<ul>
<li>The Database Type - the database you will be using.</li>
@@ -219,367 +80,136 @@ $lang = array_merge($lang, array(
</ul>
<p>Only those databases supported on your server will be displayed.',
- 'INSTALL_INTRO_NEXT' => 'To commence the installation, please press the button below.',
- 'INSTALL_LOGIN' => 'Login',
- 'INSTALL_NEXT' => 'Next stage',
- 'INSTALL_NEXT_FAIL' => 'Some tests failed and you should correct these problems before proceeding to the next stage. Failure to do so may result in an incomplete installation.',
- 'INSTALL_NEXT_PASS' => 'All the basic tests have been passed and you may proceed to the next stage of installation. If you have changed any permissions, modules, etc. and wish to re-test you can do so if you wish.',
- 'INSTALL_PANEL' => 'Installation Panel',
- 'INSTALL_SEND_CONFIG' => 'Unfortunately phpBB could not write the configuration information directly to your config.php. This may be because the file does not exist or is not writable. A number of options will be listed below enabling you to complete installation of config.php.',
- 'INSTALL_START' => 'Start install',
- 'INSTALL_TEST' => 'Test again',
- 'INST_ERR' => 'Installation error',
- 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.',
- 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.',
- 'INST_ERR_DB_INVALID_PREFIX'=> 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.',
- 'INST_ERR_DB_NO_ERROR' => 'No error message given.',
- 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension” option you have selected. Please try the “MySQL” option instead.',
- 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.',
- 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
- 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
- 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
- 'INST_ERR_DB_NO_NAME' => 'No database name specified.',
- 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.',
- 'INST_ERR_EMAIL_MISMATCH' => 'The emails you entered did not match.',
- 'INST_ERR_FATAL' => 'Fatal installation error',
- 'INST_ERR_FATAL_DB' => 'A fatal and unrecoverable database error has occurred. This may be because the specified user does not have appropriate permissions to <code>CREATE TABLES</code> or <code>INSERT</code> data, etc. Further information may be given below. Please contact your hosting provider in the first instance or the support forums of phpBB for further assistance.',
- 'INST_ERR_FTP_PATH' => 'Could not change to the given directory, please check the path.',
- 'INST_ERR_FTP_LOGIN' => 'Could not login to FTP server, check your username and password.',
+
+ 'ACP_LINK' => 'Take me to <a href="%1$s">the ACP</a>',
+));
+
+// Requirements translation
+$lang = array_merge($lang, array(
+ // Filesystem requirements
+ 'FILE_NOT_EXISTS' => 'File not exists',
+ 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.',
+ 'FILE_NOT_WRITABLE' => 'File not writable',
+ 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.',
+
+ 'DIRECTORY_NOT_EXISTS' => 'Directory not exists',
+ 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.',
+ 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable',
+ 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.',
+
+ // Server requirements
+ 'PHP_VERSION_REQD' => 'PHP version',
+ 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.4.0 or higher.',
+ 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required',
+ 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.',
+ 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support',
+ 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.',
+ 'PHP_JSON_SUPPORT' => 'PHP JSON support',
+ 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.',
+ 'PHP_SUPPORTED_DB' => 'Supported databases',
+ 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.',
+
+ 'RETEST_REQUIREMENTS' => 'Retest requirements',
+
+ 'STAGE_REQUIREMENTS' => 'Check requirements'
+));
+
+// General error messages
+$lang = array_merge($lang, array(
'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.',
- 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.',
- 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.',
- 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.',
- 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.',
- 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
- 'INST_ERR_PREFIX_INVALID' => 'The table prefix you have specified is invalid for your database. Please try another, removing characters such as the hyphen.',
- 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.',
- 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.',
- 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.',
- 'INVALID_PRIMARY_KEY' => 'Invalid primary key : %s',
-
- 'LONG_SCRIPT_EXECUTION' => 'Please note that this can take a while... Please do not stop the script.',
-
- // mbstring
- 'MBSTRING_CHECK' => '<samp>mbstring</samp> extension check',
- 'MBSTRING_CHECK_EXPLAIN' => '<strong>Required</strong> - <samp>mbstring</samp> is a PHP extension that provides multibyte string functions. Certain features of mbstring are not compatible with phpBB and must be disabled.',
- 'MBSTRING_FUNC_OVERLOAD' => 'Function overloading',
- 'MBSTRING_FUNC_OVERLOAD_EXPLAIN' => '<var>mbstring.func_overload</var> must be set to either 0 or 4.',
- 'MBSTRING_ENCODING_TRANSLATION' => 'Transparent character encoding',
- 'MBSTRING_ENCODING_TRANSLATION_EXPLAIN' => '<var>mbstring.encoding_translation</var> must be set to 0.',
- 'MBSTRING_HTTP_INPUT' => 'HTTP input character conversion',
- 'MBSTRING_HTTP_INPUT_EXPLAIN' => '<var>mbstring.http_input</var> must be set to <samp>pass</samp>.',
- 'MBSTRING_HTTP_OUTPUT' => 'HTTP output character conversion',
- 'MBSTRING_HTTP_OUTPUT_EXPLAIN' => '<var>mbstring.http_output</var> must be set to <samp>pass</samp>.',
-
- 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:<br />»<strong>%s</strong>.',
- 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:<br />»<strong>%s</strong>.',
-
- 'MYSQL_SCHEMA_UPDATE_REQUIRED' => 'Your MySQL database schema for phpBB is outdated. phpBB detected a schema for MySQL 3.x/4.x, but the server runs on MySQL %2$s.<br /><strong>Before you proceed the update, you need to upgrade the schema.</strong><br /><br />Please refer to the <a href="https://www.phpbb.com/kb/article/doesnt-have-a-default-value-errors/">Knowledge Base article about upgrading the MySQL schema</a>. If you encounter problems, please use <a href="https://www.phpbb.com/community/viewforum.php?f=466">our support forums</a>.',
-
- 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases<br /><br />%s',
- 'NEXT_STEP' => 'Proceed to next step',
- 'NOT_FOUND' => 'Cannot find',
- 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%s”)',
- 'NO_CONVERTORS' => 'No convertors are available for use.',
- 'NO_CONVERT_SPECIFIED' => 'No convertor specified.',
- 'NO_LOCATION' => 'Cannot determine location. If you know Imagemagick is installed, you may specify the location later within your administration control panel',
- 'NO_TABLES_FOUND' => 'No tables found.',
-
- 'OVERVIEW_BODY' => 'Welcome to phpBB3!<br /><br />phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.<br /><br />This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read <a href="../docs/INSTALL.html">the installation guide</a>.<br /><br />To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.',
-
- 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support',
- 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will <strong>not</strong> run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.',
- 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP function getimagesize() is available',
- 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => '<strong>Required</strong> - In order for phpBB to function correctly, the getimagesize function needs to be available.',
- 'PHP_JSON_SUPPORT' => 'PHP JSON support',
- 'PHP_JSON_SUPPORT_EXPLAIN' => '<strong>Required</strong> - In order for phpBB to function correctly, the PHP JSON extension needs to be available.',
- 'PHP_OPTIONAL_MODULE' => 'Optional modules',
- 'PHP_OPTIONAL_MODULE_EXPLAIN' => '<strong>Optional</strong> - These modules or applications are optional. However, if they are available they will enable extra features.',
- 'PHP_SUPPORTED_DB' => 'Supported databases',
- 'PHP_SUPPORTED_DB_EXPLAIN' => '<strong>Required</strong> - You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.',
- 'PHP_REGISTER_GLOBALS' => 'PHP setting <var>register_globals</var> is disabled',
- 'PHP_REGISTER_GLOBALS_EXPLAIN' => 'phpBB will still run if this setting is enabled, but if possible, it is recommended that register_globals is disabled on your PHP install for security reasons.',
- 'PHP_SAFE_MODE' => 'Safe mode',
- 'PHP_SETTINGS' => 'PHP version and settings',
- 'PHP_SETTINGS_EXPLAIN' => '<strong>Required</strong> - You must be running at least version 5.4.0 of PHP in order to install phpBB. If <var>safe mode</var> is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.',
- 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting <var>allow_url_fopen</var> is enabled',
- 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => '<strong>Optional</strong> - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.',
- 'PHP_VERSION_REQD' => 'PHP version >= 5.4.0',
- 'POST_ID' => 'Post ID',
- 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using <strong>%s</strong> as table prefix.',
- 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries',
- 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.',
- 'PROCESS_LAST' => 'Processing last statements',
-
- 'REFRESH_PAGE' => 'Refresh page to continue conversion',
- 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.',
- 'REQUIREMENTS_TITLE' => 'Installation compatibility',
- 'REQUIREMENTS_EXPLAIN' => 'Before proceeding with the full installation phpBB will carry out some tests on your server configuration and files to ensure that you are able to install and run phpBB. Please ensure you read through the results thoroughly and do not proceed until all the required tests are passed. If you wish to use any of the features depending on the optional tests, you should ensure that these tests are passed also.',
- 'RETRY_WRITE' => 'Retry writing config',
- 'RETRY_WRITE_EXPLAIN' => 'If you wish you can change the permissions on config.php to allow phpBB to write to it. Should you wish to do that you can click Retry below to try again. Remember to return the permissions on config.php after phpBB has finished installation.',
-
- 'SELECT_LANG' => 'Select language',
- 'SEARCH_INDEX_UNCONVERTED' => 'Search index was not converted',
- 'SEARCH_INDEX_UNCONVERTED_EXPLAIN' => 'Your old search index was not converted. Searching will always yield an empty result. To create a new search index go to the Administration Control Panel, select Maintenance and then choose Search index from the submenu.',
- 'SELECT_FORUM_GA' => 'In phpBB 3.1 the global announcements are linked to forums. Select a forum for your current global announcements (can be moved later):',
- 'SOFTWARE' => 'Board software',
- 'SPECIFY_OPTIONS' => 'Specify conversion options',
- 'STAGE_ADMINISTRATOR' => 'Administrator details',
- 'STAGE_ADVANCED' => 'Advanced settings',
- 'STAGE_ADVANCED_EXPLAIN' => 'The settings on this page are only necessary to set if you know that you require something different from the default. If you are unsure, just proceed to the next page, as these settings can be altered from the Administration Control Panel later.',
- 'STAGE_CONFIG_FILE' => 'Configuration file',
- 'STAGE_CREATE_TABLE' => 'Create database tables',
- 'STAGE_CREATE_TABLE_EXPLAIN' => 'The database tables used by phpBB 3.1 have been created and populated with some initial data. Proceed to the next screen to finish installing phpBB.',
- 'STAGE_DATABASE' => 'Database settings',
- 'STAGE_FINAL' => 'Final stage',
- 'STAGE_INTRO' => 'Introduction',
- 'STAGE_IN_PROGRESS' => 'Conversion in progress',
- 'STAGE_REQUIREMENTS' => 'Requirements',
- 'STAGE_SETTINGS' => 'Settings',
- 'STARTING_CONVERT' => 'Starting conversion process',
- 'STEP_PERCENT_COMPLETED' => 'Step <strong>%d</strong> of <strong>%d</strong>',
- 'SUB_INTRO' => 'Introduction',
- 'SUB_LICENSE' => 'License',
- 'SUB_SUPPORT' => 'Support',
- 'SUCCESSFUL_CONNECT' => 'Successful connection',
- 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:</p><ul><li>installation</li><li>configuration</li><li>technical questions</li><li>problems relating to potential bugs in the software</li><li>updating from Release Candidate (RC) versions to the latest stable version</li><li>converting from phpBB 2.0.x to phpBB3</li><li>converting from other discussion board software to phpBB3 (please see the <a href="https://www.phpbb.com/community/viewforum.php?f=486">Convertors Forum</a>)</li></ul><p>We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.</p><h2>Extensions / Styles</h2><p>For issues relating to Extensions, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=451">Extensions Forum</a>.<br />For issues relating to styles, templates and themes, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=471">Styles Forum</a>.<br /><br />If your question relates to a specific package, please post directly in the topic dedicated to the package.</p><h2>Obtaining Support</h2><p><a href="https://www.phpbb.com/community/viewtopic.php?f=14&amp;t=571070">The phpBB Welcome Package</a><br /><a href="https://www.phpbb.com/support/">Support Section</a><br /><a href="https://www.phpbb.com/support/docs/en/3.1/ug/quickstart/">Quick Start Guide</a><br /><br />To ensure you stay up to date with the latest news and releases, why not <a href="https://www.phpbb.com/support/">subscribe to our mailing list</a>?<br /><br />',
- 'SYNC_FORUMS' => 'Starting to synchronise forums',
- 'SYNC_POST_COUNT' => 'Synchronising post_counts',
- 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from <var>entry</var> %1$s to %2$s.',
- 'SYNC_TOPICS' => 'Starting to synchronise topics',
- 'SYNC_TOPIC_ID' => 'Synchronising topics from <var>topic_id</var> %1$s to %2$s.',
-
- 'TABLES_MISSING' => 'Could not find these tables<br />» <strong>%s</strong>.',
- 'TABLE_PREFIX' => 'Prefix for tables in database',
- 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
- 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.<br />» Specified table prefix was %s.',
- 'TESTS_PASSED' => 'Tests passed',
- 'TESTS_FAILED' => 'Tests failed',
-
- 'UNABLE_WRITE_LOCK' => 'Unable to write lock file.',
- 'UNAVAILABLE' => 'Unavailable',
- 'UNWRITABLE' => 'Unwritable',
- 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information',
- 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.',
- 'VERIFY_OPTIONS' => 'Verifying conversion options',
- 'VERSION' => 'Version',
-
- 'WELCOME_INSTALL' => 'Welcome to phpBB3 Installation',
- 'WRITABLE' => 'Writable',
+ 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.'
));
-// Updater
+// Data obtaining translations
$lang = array_merge($lang, array(
- 'ALL_FILES_UP_TO_DATE' => 'All files are up to date with the latest phpBB version.',
- 'ARCHIVE_FILE' => 'Source file within archive',
-
- 'BACK' => 'Back',
- 'BINARY_FILE' => 'Binary file',
- 'BOT' => 'Spider/Robot',
-
- 'CHANGE_CLEAN_NAMES' => 'The method used to make sure a username is not used by multiple users has been changed. There are some users which have the same name when compared with the new method. You have to delete or rename these users to make sure that each name is only used by one user before you can proceed.',
- 'CHECK_FILES' => 'Check files',
- 'CHECK_FILES_AGAIN' => 'Check files again',
- 'CHECK_FILES_EXPLAIN' => 'Within the next step all files will be checked against the update files - this can take a while if this is the first file check.',
- 'CHECK_FILES_UP_TO_DATE' => 'According to your database your version is up to date. You may want to proceed with the file check to make sure all files are really up to date with the latest phpBB version.',
- 'CHECK_UPDATE_DATABASE' => 'Continue update process',
- 'COLLECTED_INFORMATION' => 'File information',
- 'COLLECTED_INFORMATION_EXPLAIN' => 'The list below shows information about the files needing an update. Please read the information in front of every status block to see what they mean and what you may need to do to perform a successful update.',
- 'COLLECTING_FILE_DIFFS' => 'Collecting file differences',
- 'COMPLETE_LOGIN_TO_BOARD' => 'You should now <a href="../ucp.php?mode=login">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory!',
- 'CONTINUE_UPDATE_NOW' => 'Continue the update process now', // Shown within the database update script at the end if called from the updater
- 'CONTINUE_UPDATE' => 'Continue update now', // Shown after file upload to indicate the update process is not yet finished
- 'CURRENT_FILE' => 'Begin of Conflict - Original File code before update',
- 'CURRENT_VERSION' => 'Current version',
-
- 'DATABASE_TYPE' => 'Database type',
- 'DATABASE_UPDATE_COMPLETE' => 'Database updater has completed!',
- 'DATABASE_UPDATE_CONTINUE' => 'Continue database update',
- 'DATABASE_UPDATE_INFO_OLD' => 'The database update file within the install directory is outdated. Please make sure you uploaded the correct version of the file.',
- 'DATABASE_UPDATE_NOT_COMPLETED' => 'The database update has not yet completed.',
- 'DELETE_USER_REMOVE' => 'Delete user and remove posts',
- 'DELETE_USER_RETAIN' => 'Delete user but keep posts',
- 'DESTINATION' => 'Destination file',
- 'DIFF_INLINE' => 'Inline',
- 'DIFF_RAW' => 'Raw unified diff',
- 'DIFF_SEP_EXPLAIN' => 'Code block used within the updated/new file',
- 'DIFF_SIDE_BY_SIDE' => 'Side by Side',
- 'DIFF_UNIFIED' => 'Unified diff',
- 'DO_NOT_UPDATE' => 'Do not update this file',
- 'DONE' => 'Done',
- 'DOWNLOAD' => 'Download',
- 'DOWNLOAD_AS' => 'Download as',
- 'DOWNLOAD_UPDATE_METHOD_BUTTON' => 'Download modified files archive (recommended)',
- 'DOWNLOAD_CONFLICTS' => 'Download conflicts for this file',
- 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for &lt;&lt;&lt; to spot conflicts',
- 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive',
- 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, please check the files again with the other button below.',
+ 'STAGE_OBTAIN_DATA' => 'Set installation data',
- 'EDIT_USERNAME' => 'Edit username',
- 'ERROR' => 'Error',
- 'EVERYTHING_UP_TO_DATE' => 'Everything is up to date with the latest phpBB version. You should now <a href="%1$s">login to your board</a> and check if everything is working fine. Do not forget to delete, rename or move your install directory! Please send us updated information about your server and board configurations from the <a href="%2$s">Send statistics</a> module in your ACP.',
+ //
+ // Admin data
+ //
+ 'STAGE_ADMINISTRATOR' => 'Administrator details',
- 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.',
- 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.',
- 'FILE_USED' => 'Information used from', // Single file
- 'FILES_CONFLICT' => 'Conflict files',
- 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.',
- 'FILES_DELETED' => 'Deleted files',
- 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.',
- 'FILES_MODIFIED' => 'Modified files',
- 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.',
- 'FILES_NEW' => 'New files',
- 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.',
- 'FILES_NEW_CONFLICT' => 'New conflicting files',
- 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.',
- 'FILES_NOT_MODIFIED' => 'Not modified files',
- 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.',
- 'FILES_UP_TO_DATE' => 'Already updated files',
- 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.',
- 'FTP_SETTINGS' => 'FTP settings',
- 'FTP_UPDATE_METHOD' => 'FTP upload',
+ // Form labels
+ 'ADMIN_CONFIG' => 'Administrator configuration',
+ 'ADMIN_PASSWORD' => 'Administrator password',
+ 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password',
+ 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.',
+ 'ADMIN_USERNAME' => 'Administrator username',
+ 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.',
- 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.',
- 'INCOMPLETE_UPDATE_FILES' => 'The update files are incomplete.',
- 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful. Now you need to continue the update process.',
-
- 'KEEP_OLD_NAME' => 'Keep username',
-
- 'LATEST_VERSION' => 'Latest version',
- 'LINE' => 'Line',
- 'LINE_ADDED' => 'Added',
- 'LINE_MODIFIED' => 'Modified',
- 'LINE_REMOVED' => 'Removed',
- 'LINE_UNMODIFIED' => 'Unmodified',
- 'LOGIN_UPDATE_EXPLAIN' => 'In order to update your installation you need to login first.',
-
- 'MAPPING_FILE_STRUCTURE' => 'To ease the upload here are the file locations which map your phpBB installation.',
-
- 'MERGE_MODIFICATIONS_OPTION' => 'Merge modifications',
-
- 'MERGE_NO_MERGE_NEW_OPTION' => 'Do not merge - use new file',
- 'MERGE_NO_MERGE_MOD_OPTION' => 'Do not merge - use currently installed file',
- 'MERGE_MOD_FILE_OPTION' => 'Merge modifications (removes new phpBB code within conflicting block)',
- 'MERGE_NEW_FILE_OPTION' => 'Merge modifications (removes modified code within conflicting block)',
- 'MERGE_SELECT_ERROR' => 'Conflicting file merge modes are not correctly selected.',
- 'MERGING_FILES' => 'Merging differences',
- 'MERGING_FILES_EXPLAIN' => 'Currently collecting final file changes.<br /><br />Please wait until phpBB has completed all operations on changed files.',
-
- 'NEW_FILE' => 'End of Conflict',
- 'NEW_USERNAME' => 'New username',
- 'NO_AUTH_UPDATE' => 'Not authorised to update',
- 'NO_ERRORS' => 'No errors',
- 'NO_UPDATE_FILES' => 'Not updating the following files',
- 'NO_UPDATE_FILES_EXPLAIN' => 'The following files are new or modified but the directory they normally reside in could not be found on your installation. If this list contains files to other directories than language/ or styles/ than you may have modified your directory structure and the update may be incomplete.',
- 'NO_UPDATE_FILES_OUTDATED' => 'No valid update directory was found, please make sure you uploaded the relevant files.<br /><br />Your installation does <strong>not</strong> seem to be up to date. Updates are available for your version of phpBB %1$s, please visit <a href="https://www.phpbb.com/downloads/" rel="external">https://www.phpbb.com/downloads/</a> to obtain the correct package to update from Version %2$s to Version %3$s.',
- 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.',
- 'NO_UPDATE_INFO' => 'Update file information could not be found.',
- 'NO_UPDATES_REQUIRED' => 'No updates required',
- 'NO_VISIBLE_CHANGES' => 'No visible changes',
- 'NOTICE' => 'Notice',
- 'NUM_CONFLICTS' => 'Number of conflicts',
- 'NUMBER_OF_FILES_COLLECTED' => 'Currently differences from %1$d of %2$d files have been checked.<br />Please wait until all files are checked.',
-
- 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.',
-
- 'PACKAGE_UPDATES_TO' => 'Current package updates to version',
- 'PERFORM_DATABASE_UPDATE' => 'Perform database update',
- 'PERFORM_DATABASE_UPDATE_EXPLAIN' => 'Below you will find a button to the database update script. The database update can take a while, so please do not stop the execution if it seems to hang. After the database update has been performed just follow the instructions to continue the update process.',
- 'PREVIOUS_VERSION' => 'Previous version',
- 'PROGRESS' => 'Progress',
-
- 'RELEASE_ANNOUNCEMENT' => 'Announcement',
- 'RESULT' => 'Result',
- 'RUN_DATABASE_SCRIPT' => 'Update my database now',
-
- 'SELECT_DIFF_MODE' => 'Select diff mode',
- 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format',
- 'SELECT_FTP_SETTINGS' => 'Select FTP settings',
- 'SHOW_DIFF_CONFLICT' => 'Show differences/conflicts',
- 'SHOW_DIFF_DELETED' => 'Show file contents',
- 'SHOW_DIFF_FINAL' => 'Show resulting file',
- 'SHOW_DIFF_MODIFIED' => 'Show merged differences',
- 'SHOW_DIFF_NEW' => 'Show file contents',
- 'SHOW_DIFF_NEW_CONFLICT' => 'Show differences',
- 'SHOW_DIFF_NOT_MODIFIED' => 'Show differences',
- 'SOME_QUERIES_FAILED' => 'Some queries failed, the statements and errors are listed below.',
- 'SQL' => 'SQL',
- 'SQL_FAILURE_EXPLAIN' => 'This is probably nothing to worry about, update will continue. Should this fail to complete you may need to seek help at our support forums. See <a href="../docs/README.html">README</a> for details on how to obtain advice.',
- 'STAGE_FILE_CHECK' => 'Check files',
- 'STAGE_UPDATE_DB' => 'Update database',
- 'STAGE_UPDATE_FILES' => 'Update files',
- 'STAGE_VERSION_CHECK' => 'Version check',
- 'STATUS_CONFLICT' => 'Modified file producing conflicts',
- 'STATUS_DELETED' => 'Deleted file',
- 'STATUS_MODIFIED' => 'Modified file',
- 'STATUS_NEW' => 'New file',
- 'STATUS_NEW_CONFLICT' => 'Conflicting new file',
- 'STATUS_NOT_MODIFIED' => 'Not modified file',
- 'STATUS_UP_TO_DATE' => 'Already updated file',
-
- 'TOGGLE_DISPLAY' => 'View/Hide file list',
- 'TRY_DOWNLOAD_METHOD' => 'You may want to try the download modified files method.<br />This method always works and is also the recommended update path.',
- 'TRY_DOWNLOAD_METHOD_BUTTON'=> 'Try this method now',
-
- 'UPDATE_COMPLETED' => 'Update completed',
- 'UPDATE_DATABASE' => 'Update database',
- 'UPDATE_DATABASE_EXPLAIN' => 'Within the next step the database will be updated.',
- 'UPDATE_DATABASE_SCHEMA' => 'Updating database schema',
- 'UPDATE_FILES' => 'Update files',
- 'UPDATE_FILES_NOTICE' => 'Please make sure you have updated your board files too, this file is only updating your database.',
- 'UPDATE_INSTALLATION' => 'Update phpBB installation',
- 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.<br />During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.<br /><br />The file update itself can be done in two different ways.</p><h2>Manual Update</h2><p>With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.</p><h2>Automatic Update with FTP</h2><p>This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.<br /><br />',
- 'UPDATE_INSTRUCTIONS' => '
-
- <h1>Release announcement</h1>
-
- <p>Please read the release announcement for the latest version before you continue your update process, it may contain useful information. It also contains full download links as well as the change log.</p>
-
- <br />
-
- <h1>How to update your installation with the Automatic Update Package</h1>
-
- <p>The recommended way of updating your installation listed here is only valid for the automatic update package. You are also able to update your installation using the methods listed within the INSTALL.html document. The steps for updating phpBB3 automatically are:</p>
-
- <ul style="margin-left: 20px; font-size: 1.1em;">
- <li>Go to the <a href="https://www.phpbb.com/downloads/" title="https://www.phpbb.com/downloads/">phpBB.com downloads page</a> and download the "Automatic Update Package" archive.<br /><br /></li>
- <li>Unpack the archive.<br /><br /></li>
- <li>Upload the complete uncompressed "install" and "vendor" folders to your phpBB root directory (where your config.php file is).<br /><br /></li>
- </ul>
-
- <p>Once uploaded your board will be offline for normal users due to the install directory you uploaded now present.<br /><br />
- <strong><a href="%1$s" title="%1$s">Now start the update process by pointing your browser to the install folder</a>.</strong><br />
- <br />
- You will then be guided through the update process. You will be notified once the update is complete.
- </p>
- ',
- 'UPDATE_METHOD' => 'Update method',
- 'UPDATE_METHOD_EXPLAIN' => 'You are now able to choose your preferred update method. Using the FTP upload will present you with a form you need to enter your FTP account details into. With this method the files will be automatically moved to the new location and backups of the old files being created by appending .bak to the filename. If you choose to download the modified files you are able to unpack and upload them to their correct location manually later.',
- 'UPDATE_REQUIRES_FILE' => 'The updater requires that the following file is present: %s',
- 'UPDATE_SUCCESS' => 'Update was successful',
- 'UPDATE_SUCCESS_EXPLAIN' => 'Successfully updated all files. The next step involves checking all files again to make sure the files got updated correctly.',
- 'UPDATE_VERSION_OPTIMIZE' => 'Updating version and optimising tables',
- 'UPDATING_DATA' => 'Updating data',
- 'UPDATING_TO_LATEST_STABLE' => 'Updating database to latest stable release',
- 'UPDATED_VERSION' => 'Updated version',
- 'UPLOAD_METHOD' => 'Upload method',
-
- 'UPDATE_DB_SUCCESS' => 'Database update was successful.',
- 'UPDATE_FILE_SUCCESS' => 'File update was successful.',
- 'USER_ACTIVE' => 'Active user',
- 'USER_INACTIVE' => 'Inactive user',
-
- 'VERSION_CHECK' => 'Version check',
- 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.',
- 'VERSION_NOT_UP_TO_DATE' => 'Your phpBB installation is not up to date. Please continue the update process.',
- 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.<br />Below is a link to the release announcement, which contains more information as well as instructions on updating.',
- 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.',
- 'VERSION_UP_TO_DATE' => 'Your phpBB installation is up to date. Although there are no updates available at this time, you may continue in order to perform a file validity check.',
- 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.',
- 'VIEWING_FILE_CONTENTS' => 'Viewing file contents',
- 'VIEWING_FILE_DIFF' => 'Viewing file differences',
-
- 'WRONG_INFO_FILE_FORMAT' => 'Wrong info file format',
+ // Errors
+ 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.',
+ 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.',
+ 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.',
+ 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.',
+ 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.',
+ 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.',
+
+ //
+ // Board data
+ //
+ // Form labels
+ 'BOARD_CONFIG' => 'Bulletin board configuration',
+ 'DEFAULT_LANGUAGE' => 'Default language',
+ 'BOARD_NAME' => 'Title of the board',
+ 'BOARD_DESCRIPTION' => 'Short description of the board',
+
+ //
+ // Database data
+ //
+ 'STAGE_DATABASE' => 'Database settings',
+
+ // Form labels
+ 'DB_CONFIG' => 'Database configuration',
+ 'DBMS' => 'Database type',
+ 'DB_HOST' => 'Database server hostname or DSN',
+ 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.',
+ 'DB_PORT' => 'Database server port',
+ 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.',
+ 'DB_PASSWORD' => 'Database password',
+ 'DB_NAME' => 'Database name',
+ 'DB_USERNAME' => 'Database username',
+ 'TABLE_PREFIX' => 'Prefix for tables in database',
+ 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
+
+ // Database options
+ 'DB_OPTION_MSSQL' => 'MSSQL Server 2000+',
+ 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
+ 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
+ 'DB_OPTION_MYSQL' => 'MySQL',
+ 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension',
+ 'DB_OPTION_ORACLE' => 'Oracle',
+ 'DB_OPTION_POSTGRES' => 'PostgreSQL',
+ 'DB_OPTION_SQLITE' => 'SQLite 2',
+ 'DB_OPTION_SQLITE3' => 'SQLite 3',
+
+ // Errors
+ 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.',
+ 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.',
+ 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.',
+ 'INST_ERR_DB_NO_NAME' => 'No database name specified.',
+ 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.',
+ 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.',
+ 'INST_ERR_DB_NO_ERROR' => 'No error message given.',
+ 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
+ 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension” option you have selected. Please try the “MySQL” option instead.',
+ 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.',
+ 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
+ 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
+ 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
+
+ //
+ // Email data
+ //
+ 'EMAIL_CONFIG' => 'E-mail configuration',
+
+ //
+ // Server data
+ //
+ // Form labels
+ 'SERVER_CONFIG' => 'Server configuration',
+ 'SCRIPT_PATH' => 'Script path',
+ 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. <samp>/phpBB3</samp>.',
));
// Default database schema entries...
@@ -627,3 +257,157 @@ $lang = array_merge($lang, array(
'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3',
));
+
+// Common navigation items' translation
+$lang = array_merge($lang, array(
+ 'MENU_OVERVIEW' => 'Overview',
+ 'MENU_INTRO' => 'Introduction',
+ 'MENU_LICENSE' => 'License',
+ 'MENU_SUPPORT' => 'Support',
+));
+
+// Task names
+$lang = array_merge($lang, array(
+ // Install filesystem
+ 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file',
+
+ // Install database
+ 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings',
+ 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database',
+ 'TASK_CREATE_DATABASE_SCHEMA' => 'Creating database schema',
+
+ // Install data
+ 'TASK_ADD_BOTS' => 'Registering bots',
+ 'TASK_ADD_LANGUAGES' => 'Installing available languages',
+ 'TASK_ADD_MODULES' => 'Installing modules',
+
+ // Install finish tasks
+ 'TASK_NOTIFY_USER' => 'Sending notification e-mail',
+ 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations',
+
+ // Installer general progress messages
+ 'INSTALLER_FINISHED' => 'The installer has finished successfully',
+));
+
+// Installer's general messages
+$lang = array_merge($lang, array(
+ 'MODULE_NOT_FOUND' => 'Module not found',
+ 'MODULE_NOT_FOUND_DESCRIPTION' => 'A module could not be found because the service, %s, is undefined.',
+
+ 'TASK_NOT_FOUND' => 'Task not found',
+ 'TASK_NOT_FOUND_DESCRIPTION' => 'A task could not be found because the service, %s, is undefined.',
+
+ 'SKIP_MODULE' => 'Skip “%s” module',
+ 'SKIP_TASK' => 'Skip “%s” task',
+
+ 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installer”',
+ 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s” given, the expected class namespace is “%2$s” for that. For more information please see the documentation of task_interface.',
+
+ 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.',
+));
+
+// CLI messages
+$lang = array_merge($lang, array(
+ 'CLI_INSTALL_BOARD' => 'Install phpBB',
+ 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used',
+ 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file',
+ 'CLI_CONFIG_FILE' => 'Config file to use',
+ 'MISSING_FILE' => 'Unable to access file %1$s',
+ 'INVALID_YAML_FILE' => 'Could not parse YAML file %1$s',
+));
+
+// Common updater messages
+$lang = array_merge($lang, array(
+ 'UPDATE_INSTALLATION' => 'Update phpBB installation',
+ 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.<br />During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.<br /><br />The file update itself can be done in two different ways.</p><h2>Manual Update</h2><p>With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.</p><h2>Automatic Update with FTP</h2><p>This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.<br /><br />',
+));
+
+// Updater forms
+$lang = array_merge($lang, array(
+ // Updater types
+ 'UPDATE_TYPE' => 'Type of update to run',
+
+ 'UPDATE_TYPE_ALL' => 'Update filesystem and database',
+ 'UPDATE_TYPE_DB_ONLY' => 'Update database only',
+
+ // File updater methods
+ 'UPDATE_FILE_METHOD_TITLE' => 'File updater methods',
+
+ 'UPDATE_FILE_METHOD' => 'File updater method',
+ 'UPDATE_FILE_METHOD_DOWNLOAD' => 'Download modified files in an archive',
+ 'UPDATE_FILE_METHOD_FTP' => 'Update files via FTP (Automatic)',
+ 'UPDATE_FILE_METHOD_FILESYSTEM' => 'Update files via direct file access (Automatic)',
+
+ // File updater archives
+ 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format',
+
+ // FTP settings
+ 'FTP_SETTINGS' => 'FTP settings',
+));
+
+// Requirements messages
+$lang = array_merge($lang, array(
+ 'UPDATE_FILES_NOT_FOUND' => 'No valid update directory was found, please make sure you uploaded the relevant files.',
+
+ 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.',
+ 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.',
+ 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.',
+));
+
+// Update files
+$lang = array_merge($lang, array(
+ 'STAGE_UPDATE_FILES' => 'Update files',
+
+ // Check files
+ 'UPDATE_CHECK_FILES' => 'Check files to update',
+
+ // Update file differ
+ 'FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ' => 'The file differ failed to open %s.',
+
+ 'UPDATE_FILE_DIFF' => 'Diffing changed files',
+ 'ALL_FILES_DIFFED' => 'All modified files has been diffed.',
+
+ // File status
+ 'UPDATE_CONTINUE_FILE_UPDATE' => 'Update files',
+
+ 'DOWNLOAD' => 'Download',
+ 'DOWNLOAD_CONFLICTS' => 'Download merge conflicts archive',
+ 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for &lt;&lt;&lt; to spot conflicts',
+ 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive',
+ 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, you may continue with the update process.',
+
+ 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.',
+ 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.',
+ 'FILE_USED' => 'Information used from', // Single file
+ 'FILES_CONFLICT' => 'Conflict files',
+ 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.',
+ 'FILES_DELETED' => 'Deleted files',
+ 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.',
+ 'FILES_MODIFIED' => 'Modified files',
+ 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.',
+ 'FILES_NEW' => 'New files',
+ 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.',
+ 'FILES_NEW_CONFLICT' => 'New conflicting files',
+ 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.',
+ 'FILES_NOT_MODIFIED' => 'Not modified files',
+ 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.',
+ 'FILES_UP_TO_DATE' => 'Already updated files',
+ 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.',
+ 'TOGGLE_DISPLAY' => 'View/Hide file list',
+
+ // File updater
+ 'UPDATE_UPDATING_FILES' => 'Updating files',
+
+ 'UPDATE_FILE_UPDATER_HAS_FAILED' => 'File updater “%1$s“ has failed. The installer will try to fallback to “%2$s“.',
+ 'UPDATE_FILE_UPDATERS_HAVE_FAILED' => 'The file updater failed. No further fallback methods are available.',
+
+ 'UPDATE_CONTINUE_UPDATE_PROCESS' => 'Continue update process',
+ 'UPDATE_RECHECK_UPDATE_FILES' => 'Check files again',
+));
+
+// Update database
+$lang = array_merge($lang, array(
+ 'STAGE_UPDATE_DATABASE' => 'Update database',
+
+ 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful.',
+));
diff --git a/phpBB/language/en/install_new.php b/phpBB/language/en/install_new.php
deleted file mode 100644
index db7e96829d..0000000000
--- a/phpBB/language/en/install_new.php
+++ /dev/null
@@ -1,411 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-/**
-* DO NOT CHANGE
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-if (empty($lang) || !is_array($lang))
-{
- $lang = array();
-}
-
-// DEVELOPERS PLEASE NOTE
-//
-// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
-//
-// Placeholders can now contain order information, e.g. instead of
-// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
-// translators to re-order the output of data while ensuring it remains correct
-//
-// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
-// equally where a string contains only two placeholders which are used to wrap text
-// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
-
-// Common installer pages
-$lang = array_merge($lang, array(
- 'INSTALL_PANEL' => 'Installation Panel',
- 'SELECT_LANG' => 'Select language',
-
- 'STAGE_INSTALL' => 'Installing phpBB',
-
- // Introduction page
- 'INTRODUCTION_TITLE' => 'Introduction',
- 'INTRODUCTION_BODY' => 'Welcome to phpBB3!<br /><br />phpBB® is the most widely used open source bulletin board solution in the world. phpBB3 is the latest installment in a package line started in 2000. Like its predecessors, phpBB3 is feature-rich, user-friendly, and fully supported by the phpBB Team. phpBB3 greatly improves on what made phpBB2 popular, and adds commonly requested features that were not present in previous versions. We hope it exceeds your expectations.<br /><br />This installation system will guide you through installing phpBB3, updating to the latest version of phpBB3 from past releases, as well as converting to phpBB3 from a different discussion board system (including phpBB2). For more information, we encourage you to read <a href="../docs/INSTALL.html">the installation guide</a>.<br /><br />To read the phpBB3 license or learn about obtaining support and our stance on it, please select the respective options from the side menu. To continue, please select the appropriate tab above.',
-
- // Support page
- 'SUPPORT_TITLE' => 'Support',
- 'SUPPORT_BODY' => 'Full support will be provided for the current stable release of phpBB3, free of charge. This includes:</p><ul><li>installation</li><li>configuration</li><li>technical questions</li><li>problems relating to potential bugs in the software</li><li>updating from Release Candidate (RC) versions to the latest stable version</li><li>converting from phpBB 2.0.x to phpBB3</li><li>converting from other discussion board software to phpBB3 (please see the <a href="https://www.phpbb.com/community/viewforum.php?f=486">Convertors Forum</a>)</li></ul><p>We encourage users still running beta versions of phpBB3 to replace their installation with a fresh copy of the latest version.</p><h2>Extensions / Styles</h2><p>For issues relating to Extensions, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=451">Extensions Forum</a>.<br />For issues relating to styles, templates and themes, please post in the appropriate <a href="https://www.phpbb.com/community/viewforum.php?f=471">Styles Forum</a>.<br /><br />If your question relates to a specific package, please post directly in the topic dedicated to the package.</p><h2>Obtaining Support</h2><p><a href="https://www.phpbb.com/community/viewtopic.php?f=14&amp;t=571070">The phpBB Welcome Package</a><br /><a href="https://www.phpbb.com/support/">Support Section</a><br /><a href="https://www.phpbb.com/support/docs/en/3.1/ug/quickstart/">Quick Start Guide</a><br /><br />To ensure you stay up to date with the latest news and releases, why not <a href="https://www.phpbb.com/support/">subscribe to our mailing list</a>?<br /><br />',
-
- // License
- 'LICENSE_TITLE' => 'General Public License',
-
- // Install page
- 'INSTALL_INTRO' => 'Welcome to Installation',
- 'INSTALL_INTRO_BODY' => 'With this option, it is possible to install phpBB3 onto your server.</p><p>In order to proceed, you will need your database settings. If you do not know your database settings, please contact your host and ask for them. You will not be able to continue without them. You need:</p>
-
- <ul>
- <li>The Database Type - the database you will be using.</li>
- <li>The Database server hostname or DSN - the address of the database server.</li>
- <li>The Database server port - the port of the database server (most of the time this is not needed).</li>
- <li>The Database name - the name of the database on the server.</li>
- <li>The Database username and Database password - the login data to access the database.</li>
- </ul>
-
- <p><strong>Note:</strong> if you are installing using SQLite, you should enter the full path to your database file in the DSN field and leave the username and password fields blank. For security reasons, you should make sure that the database file is not stored in a location accessible from the web.</p>
-
- <p>phpBB3 supports the following databases:</p>
- <ul>
- <li>MySQL 3.23 or above (MySQLi supported)</li>
- <li>PostgreSQL 8.3+</li>
- <li>SQLite 2.8.2+</li>
- <li>SQLite 3.6.15+</li>
- <li>MS SQL Server 2000 or above (directly or via ODBC)</li>
- <li>MS SQL Server 2005 or above (native)</li>
- <li>Oracle</li>
- </ul>
-
- <p>Only those databases supported on your server will be displayed.',
-
- 'ACP_LINK' => 'Take me to <a href="%1$s">the ACP</a>',
-));
-
-// Requirements translation
-$lang = array_merge($lang, array(
- // Filesystem requirements
- 'FILE_NOT_EXISTS' => 'File not exists',
- 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.',
- 'FILE_NOT_WRITABLE' => 'File not writable',
- 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.',
-
- 'DIRECTORY_NOT_EXISTS' => 'Directory not exists',
- 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.',
- 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable',
- 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.',
-
- // Server requirements
- 'PHP_VERSION_REQD' => 'PHP version',
- 'PHP_VERSION_REQD_EXPLAIN' => 'phpBB requires PHP version 5.4.0 or higher.',
- 'PHP_GETIMAGESIZE_SUPPORT' => 'PHP getimagesize() function is required',
- 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the getimagesize function needs to be available.',
- 'PCRE_UTF_SUPPORT' => 'PCRE UTF-8 support',
- 'PCRE_UTF_SUPPORT_EXPLAIN' => 'phpBB will not run if your PHP installation is not compiled with UTF-8 support in the PCRE extension.',
- 'PHP_JSON_SUPPORT' => 'PHP JSON support',
- 'PHP_JSON_SUPPORT_EXPLAIN' => 'In order for phpBB to function correctly, the PHP JSON extension needs to be available.',
- 'PHP_SUPPORTED_DB' => 'Supported databases',
- 'PHP_SUPPORTED_DB_EXPLAIN' => 'You must have support for at least one compatible database within PHP. If no database modules are shown as available you should contact your hosting provider or review the relevant PHP installation documentation for advice.',
-
- 'RETEST_REQUIREMENTS' => 'Retest requirements',
-
- 'STAGE_REQUIREMENTS' => 'Check requirements'
-));
-
-// General error messages
-$lang = array_merge($lang, array(
- 'INST_ERR_MISSING_DATA' => 'You must fill out all fields in this block.',
- 'PHPBB_ALREADY_INSTALLED' => 'phpBB is already installed.'
-));
-
-// Data obtaining translations
-$lang = array_merge($lang, array(
- 'STAGE_OBTAIN_DATA' => 'Set installation data',
-
- //
- // Admin data
- //
- 'STAGE_ADMINISTRATOR' => 'Administrator details',
-
- // Form labels
- 'ADMIN_CONFIG' => 'Administrator configuration',
- 'ADMIN_PASSWORD' => 'Administrator password',
- 'ADMIN_PASSWORD_CONFIRM' => 'Confirm administrator password',
- 'ADMIN_PASSWORD_EXPLAIN' => 'Please enter a password between 6 and 30 characters in length.',
- 'ADMIN_USERNAME' => 'Administrator username',
- 'ADMIN_USERNAME_EXPLAIN' => 'Please enter a username between 3 and 20 characters in length.',
-
- // Errors
- 'INST_ERR_EMAIL_INVALID' => 'The email address you entered is invalid.',
- 'INST_ERR_PASSWORD_MISMATCH' => 'The passwords you entered did not match.',
- 'INST_ERR_PASSWORD_TOO_LONG' => 'The password you entered is too long. The maximum length is 30 characters.',
- 'INST_ERR_PASSWORD_TOO_SHORT' => 'The password you entered is too short. The minimum length is 6 characters.',
- 'INST_ERR_USER_TOO_LONG' => 'The username you entered is too long. The maximum length is 20 characters.',
- 'INST_ERR_USER_TOO_SHORT' => 'The username you entered is too short. The minimum length is 3 characters.',
-
- //
- // Board data
- //
- // Form labels
- 'BOARD_CONFIG' => 'Bulletin board configuration',
- 'DEFAULT_LANGUAGE' => 'Default language',
- 'BOARD_NAME' => 'Title of the board',
- 'BOARD_DESCRIPTION' => 'Short description of the board',
-
- //
- // Database data
- //
- 'STAGE_DATABASE' => 'Database settings',
-
- // Form labels
- 'DB_CONFIG' => 'Database configuration',
- 'DBMS' => 'Database type',
- 'DB_HOST' => 'Database server hostname or DSN',
- 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.',
- 'DB_PORT' => 'Database server port',
- 'DB_PORT_EXPLAIN' => 'Leave this blank unless you know the server operates on a non-standard port.',
- 'DB_PASSWORD' => 'Database password',
- 'DB_NAME' => 'Database name',
- 'DB_USERNAME' => 'Database username',
- 'TABLE_PREFIX' => 'Prefix for tables in database',
- 'TABLE_PREFIX_EXPLAIN' => 'The prefix must start with a letter and must only contain letters, numbers and underscores.',
-
- // Database options
- 'DB_OPTION_MSSQL' => 'MSSQL Server 2000+',
- 'DB_OPTION_MSSQL_ODBC' => 'MSSQL Server 2000+ via ODBC',
- 'DB_OPTION_MSSQLNATIVE' => 'MSSQL Server 2005+ [ Native ]',
- 'DB_OPTION_MYSQL' => 'MySQL',
- 'DB_OPTION_MYSQLI' => 'MySQL with MySQLi Extension',
- 'DB_OPTION_ORACLE' => 'Oracle',
- 'DB_OPTION_POSTGRES' => 'PostgreSQL',
- 'DB_OPTION_SQLITE' => 'SQLite 2',
- 'DB_OPTION_SQLITE3' => 'SQLite 3',
-
- // Errors
- 'INST_ERR_NO_DB' => 'Cannot load the PHP module for the selected database type.',
- 'INST_ERR_DB_INVALID_PREFIX' => 'The prefix you entered is invalid. It must start with a letter and must only contain letters, numbers and underscores.',
- 'INST_ERR_PREFIX_TOO_LONG' => 'The table prefix you have specified is too long. The maximum length is %d characters.',
- 'INST_ERR_DB_NO_NAME' => 'No database name specified.',
- 'INST_ERR_DB_FORUM_PATH' => 'The database file specified is within your board directory tree. You should put this file in a non web-accessible location.',
- 'INST_ERR_DB_CONNECT' => 'Could not connect to the database, see error message below.',
- 'INST_ERR_DB_NO_ERROR' => 'No error message given.',
- 'INST_ERR_PREFIX' => 'Tables with the specified prefix already exist, please choose an alternative.',
- 'INST_ERR_DB_NO_MYSQLI' => 'The version of MySQL installed on this machine is incompatible with the “MySQL with MySQLi Extension” option you have selected. Please try the “MySQL” option instead.',
- 'INST_ERR_DB_NO_SQLITE' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 2.8.2.',
- 'INST_ERR_DB_NO_SQLITE3' => 'The version of the SQLite extension you have installed is too old, it must be upgraded to at least 3.6.15.',
- 'INST_ERR_DB_NO_ORACLE' => 'The version of Oracle installed on this machine requires you to set the <var>NLS_CHARACTERSET</var> parameter to <var>UTF8</var>. Either upgrade your installation to 9.2+ or change the parameter.',
- 'INST_ERR_DB_NO_POSTGRES' => 'The database you have selected was not created in <var>UNICODE</var> or <var>UTF8</var> encoding. Try installing with a database in <var>UNICODE</var> or <var>UTF8</var> encoding.',
-
- //
- // Email data
- //
- 'EMAIL_CONFIG' => 'E-mail configuration',
-
- //
- // Server data
- //
- // Form labels
- 'SERVER_CONFIG' => 'Server configuration',
- 'SCRIPT_PATH' => 'Script path',
- 'SCRIPT_PATH_EXPLAIN' => 'The path where phpBB is located relative to the domain name, e.g. <samp>/phpBB3</samp>.',
-));
-
-// Default database schema entries...
-$lang = array_merge($lang, array(
- 'CONFIG_BOARD_EMAIL_SIG' => 'Thanks, The Management',
- 'CONFIG_SITE_DESC' => 'A short text to describe your forum',
- 'CONFIG_SITENAME' => 'yourdomain.com',
-
- 'DEFAULT_INSTALL_POST' => 'This is an example post in your phpBB3 installation. Everything seems to be working. You may delete this post if you like and continue to set up your board. During the installation process your first category and your first forum are assigned an appropriate set of permissions for the predefined usergroups administrators, bots, global moderators, guests, registered users and registered COPPA users. If you also choose to delete your first category and your first forum, do not forget to assign permissions for all these usergroups for all new categories and forums you create. It is recommended to rename your first category and your first forum and copy permissions from these while creating new categories and forums. Have fun!',
-
- 'FORUMS_FIRST_CATEGORY' => 'Your first category',
- 'FORUMS_TEST_FORUM_DESC' => 'Description of your first forum.',
- 'FORUMS_TEST_FORUM_TITLE' => 'Your first forum',
-
- 'RANKS_SITE_ADMIN_TITLE' => 'Site Admin',
- 'REPORT_WAREZ' => 'The post contains links to illegal or pirated software.',
- 'REPORT_SPAM' => 'The reported post has the only purpose to advertise for a website or another product.',
- 'REPORT_OFF_TOPIC' => 'The reported post is off topic.',
- 'REPORT_OTHER' => 'The reported post does not fit into any other category, please use the further information field.',
-
- 'SMILIES_ARROW' => 'Arrow',
- 'SMILIES_CONFUSED' => 'Confused',
- 'SMILIES_COOL' => 'Cool',
- 'SMILIES_CRYING' => 'Crying or Very Sad',
- 'SMILIES_EMARRASSED' => 'Embarrassed',
- 'SMILIES_EVIL' => 'Evil or Very Mad',
- 'SMILIES_EXCLAMATION' => 'Exclamation',
- 'SMILIES_GEEK' => 'Geek',
- 'SMILIES_IDEA' => 'Idea',
- 'SMILIES_LAUGHING' => 'Laughing',
- 'SMILIES_MAD' => 'Mad',
- 'SMILIES_MR_GREEN' => 'Mr. Green',
- 'SMILIES_NEUTRAL' => 'Neutral',
- 'SMILIES_QUESTION' => 'Question',
- 'SMILIES_RAZZ' => 'Razz',
- 'SMILIES_ROLLING_EYES' => 'Rolling Eyes',
- 'SMILIES_SAD' => 'Sad',
- 'SMILIES_SHOCKED' => 'Shocked',
- 'SMILIES_SMILE' => 'Smile',
- 'SMILIES_SURPRISED' => 'Surprised',
- 'SMILIES_TWISTED_EVIL' => 'Twisted Evil',
- 'SMILIES_UBER_GEEK' => 'Uber Geek',
- 'SMILIES_VERY_HAPPY' => 'Very Happy',
- 'SMILIES_WINK' => 'Wink',
-
- 'TOPICS_TOPIC_TITLE' => 'Welcome to phpBB3',
-));
-
-// Common navigation items' translation
-$lang = array_merge($lang, array(
- 'MENU_OVERVIEW' => 'Overview',
- 'MENU_INTRO' => 'Introduction',
- 'MENU_LICENSE' => 'License',
- 'MENU_SUPPORT' => 'Support',
-));
-
-// Task names
-$lang = array_merge($lang, array(
- // Install filesystem
- 'TASK_CREATE_CONFIG_FILE' => 'Creating configuration file',
-
- // Install database
- 'TASK_ADD_CONFIG_SETTINGS' => 'Adding configuration settings',
- 'TASK_ADD_DEFAULT_DATA' => 'Adding default settings to the database',
- 'TASK_CREATE_DATABASE_SCHEMA' => 'Creating database schema',
-
- // Install data
- 'TASK_ADD_BOTS' => 'Registering bots',
- 'TASK_ADD_LANGUAGES' => 'Installing available languages',
- 'TASK_ADD_MODULES' => 'Installing modules',
-
- // Install finish tasks
- 'TASK_NOTIFY_USER' => 'Sending notification e-mail',
- 'TASK_POPULATE_MIGRATIONS' => 'Populating migrations',
-
- // Installer general progress messages
- 'INSTALLER_FINISHED' => 'The installer has finished successfully',
-));
-
-// Installer's general messages
-$lang = array_merge($lang, array(
- 'MODULE_NOT_FOUND' => 'Module not found',
- 'MODULE_NOT_FOUND_DESCRIPTION' => 'A module could not be found because the service, %s, is undefined.',
-
- 'TASK_NOT_FOUND' => 'Task not found',
- 'TASK_NOT_FOUND_DESCRIPTION' => 'A task could not be found because the service, %s, is undefined.',
-
- 'SKIP_MODULE' => 'Skip “%s” module',
- 'SKIP_TASK' => 'Skip “%s” task',
-
- 'TASK_SERVICE_INSTALLER_MISSING' => 'All installer task services should start with “installer”',
- 'TASK_CLASS_NOT_FOUND' => 'Installer task service definition is invalid. Service name “%1$s” given, the expected class namespace is “%2$s” for that. For more information please see the documentation of task_interface.',
-
- 'INSTALLER_CONFIG_NOT_WRITABLE' => 'The installer config file is not writable.',
-));
-
-// CLI messages
-$lang = array_merge($lang, array(
- 'CLI_INSTALL_BOARD' => 'Install phpBB',
- 'CLI_INSTALL_SHOW_CONFIG' => 'Show the configuration which will be used',
- 'CLI_INSTALL_VALIDATE_CONFIG' => 'Validate a configuration file',
- 'CLI_CONFIG_FILE' => 'Config file to use',
-));
-
-// Common updater messages
-$lang = array_merge($lang, array(
- 'UPDATE_INSTALLATION' => 'Update phpBB installation',
- 'UPDATE_INSTALLATION_EXPLAIN' => 'With this option, it is possible to update your phpBB installation to the latest version.<br />During the process all of your files will be checked for their integrity. You are able to review all differences and files before the update.<br /><br />The file update itself can be done in two different ways.</p><h2>Manual Update</h2><p>With this update you only download your personal set of changed files to make sure you do not lose your file modifications you may have done. After you downloaded this package you need to manually upload the files to their correct position under your phpBB root directory. Once done, you are able to do the file check stage again to see if you moved the files to their correct location.</p><h2>Automatic Update with FTP</h2><p>This method is similar to the first one but without the need to download the changed files and uploading them on your own. This will be done for you. In order to use this method you need to know your FTP login details since you will be asked for them. Once finished you will be redirected to the file check again to make sure everything got updated correctly.<br /><br />',
-));
-
-// Updater forms
-$lang = array_merge($lang, array(
- // Updater types
- 'UPDATE_TYPE' => 'Type of update to run',
-
- 'UPDATE_TYPE_ALL' => 'Update filesystem and database',
- 'UPDATE_TYPE_DB_ONLY' => 'Update database only',
-
- // File updater methods
- 'UPDATE_FILE_METHOD_TITLE' => 'File updater methods',
-
- 'UPDATE_FILE_METHOD' => 'File updater method',
- 'UPDATE_FILE_METHOD_DOWNLOAD' => 'Download modified files in an archive',
- 'UPDATE_FILE_METHOD_FTP' => 'Update files via FTP (Automatic)',
- 'UPDATE_FILE_METHOD_FILESYSTEM' => 'Update files via direct file access (Automatic)',
-
- // File updater archives
- 'SELECT_DOWNLOAD_FORMAT' => 'Select download archive format',
-
- // FTP settings
- 'FTP_SETTINGS' => 'FTP settings',
-));
-
-// Requirements messages
-$lang = array_merge($lang, array(
- 'UPDATE_FILES_NOT_FOUND' => 'No valid update directory was found, please make sure you uploaded the relevant files.',
-
- 'NO_UPDATE_FILES_UP_TO_DATE' => 'Your version is up to date. There is no need to run the update tool. If you want to make an integrity check on your files make sure you uploaded the correct update files.',
- 'OLD_UPDATE_FILES' => 'Update files are out of date. The update files found are for updating from phpBB %1$s to phpBB %2$s but the latest version of phpBB is %3$s.',
- 'INCOMPATIBLE_UPDATE_FILES' => 'The update files found are incompatible with your installed version. Your installed version is %1$s and the update file is for updating phpBB %2$s to %3$s.',
-));
-
-// Update files
-$lang = array_merge($lang, array(
- 'STAGE_UPDATE_FILES' => 'Update files',
-
- // Check files
- 'UPDATE_CHECK_FILES' => 'Check files to update',
-
- // Update file differ
- 'FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ' => 'The file differ failed to open %s.',
-
- 'UPDATE_FILE_DIFF' => 'Diffing changed files',
- 'ALL_FILES_DIFFED' => 'All modified files has been diffed.',
-
- // File status
- 'UPDATE_CONTINUE_FILE_UPDATE' => 'Update files',
-
- 'DOWNLOAD' => 'Download',
- 'DOWNLOAD_CONFLICTS' => 'Download merge conflicts archive',
- 'DOWNLOAD_CONFLICTS_EXPLAIN' => 'Search for &lt;&lt;&lt; to spot conflicts',
- 'DOWNLOAD_UPDATE_METHOD' => 'Download modified files archive',
- 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' => 'Once downloaded you should unpack the archive. You will find the modified files you need to upload to your phpBB root directory within it. Please upload the files to their respective locations then. After you have uploaded all files, you may continue with the update process.',
-
- 'FILE_ALREADY_UP_TO_DATE' => 'File is already up to date.',
- 'FILE_DIFF_NOT_ALLOWED' => 'File not allowed to be diffed.',
- 'FILE_USED' => 'Information used from', // Single file
- 'FILES_CONFLICT' => 'Conflict files',
- 'FILES_CONFLICT_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. phpBB determined that these files create conflicts if they are tried to be merged. Please investigate the conflicts and try to manually resolve them or continue the update choosing the preferred merging method. If you resolve the conflicts manually check the files again after you modified them. You are also able to choose between the preferred merge method for every file. The first one will result in a file where the conflicting lines from your old file will be lost, the other one will result in losing the changes from the newer file.',
- 'FILES_DELETED' => 'Deleted files',
- 'FILES_DELETED_EXPLAIN' => 'The following files do not exist in the new version. These files have to be deleted from your installation.',
- 'FILES_MODIFIED' => 'Modified files',
- 'FILES_MODIFIED_EXPLAIN' => 'The following files are modified and do not represent the original files from the old version. The updated file will be a merge between your modifications and the new file.',
- 'FILES_NEW' => 'New files',
- 'FILES_NEW_EXPLAIN' => 'The following files currently do not exist within your installation. These files will be added to your installation.',
- 'FILES_NEW_CONFLICT' => 'New conflicting files',
- 'FILES_NEW_CONFLICT_EXPLAIN' => 'The following files are new within the latest version but it has been determined that there is already a file with the same name within the same position. This file will be overwritten by the new file.',
- 'FILES_NOT_MODIFIED' => 'Not modified files',
- 'FILES_NOT_MODIFIED_EXPLAIN' => 'The following files are not modified and represent the original phpBB files from the version you want to update from.',
- 'FILES_UP_TO_DATE' => 'Already updated files',
- 'FILES_UP_TO_DATE_EXPLAIN' => 'The following files are already up to date and do not need to be updated.',
- 'TOGGLE_DISPLAY' => 'View/Hide file list',
-
- // File updater
- 'UPDATE_UPDATING_FILES' => 'Updating files',
-
- 'UPDATE_FILE_UPDATER_HAS_FAILED' => 'File updater “%1$s“ has failed. The installer will try to fallback to “%2$s“.',
- 'UPDATE_FILE_UPDATERS_HAVE_FAILED' => 'The file updater failed. No further fallback methods are available.',
-
- 'UPDATE_CONTINUE_UPDATE_PROCESS' => 'Continue update process',
- 'UPDATE_RECHECK_UPDATE_FILES' => 'Check files again',
-));
-
-// Update database
-$lang = array_merge($lang, array(
- 'STAGE_UPDATE_DATABASE' => 'Update database',
-
- 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful.',
-));
diff --git a/phpBB/language/en/memberlist.php b/phpBB/language/en/memberlist.php
index 5605f8f4b5..c7b2bf55d1 100644
--- a/phpBB/language/en/memberlist.php
+++ b/phpBB/language/en/memberlist.php
@@ -101,6 +101,7 @@ $lang = array_merge($lang, array(
'LOGIN_EXPLAIN_SEARCHUSER' => 'The board requires you to be registered and logged in to search users.',
'LOGIN_EXPLAIN_VIEWPROFILE' => 'The board requires you to be registered and logged in to view profiles.',
+ 'MANAGE_GROUP' => 'Manage Group',
'MORE_THAN' => 'More than',
'NO_CONTACT_FORM' => 'The board administrator contact form has been disabled.',
diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php
index c4865ab3c2..c23a409ae7 100644
--- a/phpBB/memberlist.php
+++ b/phpBB/memberlist.php
@@ -1090,7 +1090,7 @@ switch ($mode)
if ($mode == 'group')
{
// We JOIN here to save a query for determining membership for hidden groups. ;)
- $sql = 'SELECT g.*, ug.user_id
+ $sql = 'SELECT g.*, ug.user_id, ug.group_leader
FROM ' . GROUPS_TABLE . ' g
LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (ug.user_pending = 0 AND ug.user_id = ' . $user->data['user_id'] . " AND ug.group_id = $group_id)
WHERE g.group_id = $group_id";
@@ -1149,6 +1149,24 @@ switch ($mode)
$user_rank_data['img'] .= '<br />';
}
}
+ // include modules for manage groups link display or not
+ // need to ensure the module is active
+ $can_manage_group = false;
+ if ($user->data['is_registered'] && $group_row['group_leader'])
+ {
+ if (!class_exists('p_master'))
+ {
+ include($phpbb_root_path . 'includes/functions_module.' . $phpEx);
+ }
+ $module = new p_master;
+ $module->list_modules('ucp');
+
+ if ($module->is_active('ucp_groups', 'manage'))
+ {
+ $can_manage_group = true;
+ }
+ unset($module);
+ }
$template->assign_vars(array(
'GROUP_DESC' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']),
@@ -1161,7 +1179,8 @@ switch ($mode)
'RANK_IMG' => $user_rank_data['img'],
'RANK_IMG_SRC' => $user_rank_data['img_src'],
- 'U_PM' => ($auth->acl_get('u_sendpm') && $auth->acl_get('u_masspm_group') && $group_row['group_receive_pm'] && $config['allow_privmsg'] && $config['allow_mass_pm']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=compose&amp;g=' . $group_id) : '',)
+ 'U_PM' => ($auth->acl_get('u_sendpm') && $auth->acl_get('u_masspm_group') && $group_row['group_receive_pm'] && $config['allow_privmsg'] && $config['allow_mass_pm']) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;mode=compose&amp;g=' . $group_id) : '',
+ 'U_MANAGE' => ($can_manage_group) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=ucp_groups&amp;mode=manage') : false,)
);
$sql_select = ', ug.group_leader';
@@ -1574,12 +1593,12 @@ switch ($mode)
'U_HIDE_FIND_MEMBER' => ($mode == 'searchuser' || ($mode == '' && $submit)) ? $u_hide_find_member : '',
'U_LIVE_SEARCH' => ($config['allow_live_searches']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=livesearch') : false,
'U_SORT_USERNAME' => $sort_url . '&amp;sk=a&amp;sd=' . (($sort_key == 'a' && $sort_dir == 'a') ? 'd' : 'a'),
- 'U_SORT_JOINED' => $sort_url . '&amp;sk=c&amp;sd=' . (($sort_key == 'c' && $sort_dir == 'a') ? 'd' : 'a'),
- 'U_SORT_POSTS' => $sort_url . '&amp;sk=d&amp;sd=' . (($sort_key == 'd' && $sort_dir == 'a') ? 'd' : 'a'),
- 'U_SORT_EMAIL' => $sort_url . '&amp;sk=e&amp;sd=' . (($sort_key == 'e' && $sort_dir == 'a') ? 'd' : 'a'),
- 'U_SORT_ACTIVE' => ($auth->acl_get('u_viewonline')) ? $sort_url . '&amp;sk=l&amp;sd=' . (($sort_key == 'l' && $sort_dir == 'a') ? 'd' : 'a') : '',
- 'U_SORT_RANK' => $sort_url . '&amp;sk=m&amp;sd=' . (($sort_key == 'm' && $sort_dir == 'a') ? 'd' : 'a'),
- 'U_LIST_CHAR' => $sort_url . '&amp;sk=a&amp;sd=' . (($sort_key == 'l' && $sort_dir == 'a') ? 'd' : 'a'),
+ 'U_SORT_JOINED' => $sort_url . '&amp;sk=c&amp;sd=' . (($sort_key == 'c' && $sort_dir == 'd') ? 'a' : 'd'),
+ 'U_SORT_POSTS' => $sort_url . '&amp;sk=d&amp;sd=' . (($sort_key == 'd' && $sort_dir == 'd') ? 'a' : 'd'),
+ 'U_SORT_EMAIL' => $sort_url . '&amp;sk=e&amp;sd=' . (($sort_key == 'e' && $sort_dir == 'd') ? 'a' : 'd'),
+ 'U_SORT_ACTIVE' => ($auth->acl_get('u_viewonline')) ? $sort_url . '&amp;sk=l&amp;sd=' . (($sort_key == 'l' && $sort_dir == 'd') ? 'a' : 'd') : '',
+ 'U_SORT_RANK' => $sort_url . '&amp;sk=m&amp;sd=' . (($sort_key == 'm' && $sort_dir == 'd') ? 'a' : 'd'),
+ 'U_LIST_CHAR' => $sort_url . '&amp;sk=a&amp;sd=' . (($sort_key == 'l' && $sort_dir == 'd') ? 'a' : 'd'),
'S_SHOW_GROUP' => ($mode == 'group') ? true : false,
'S_VIEWONLINE' => $auth->acl_get('u_viewonline'),
diff --git a/phpBB/phpbb/db/driver/sqlite3.php b/phpBB/phpbb/db/driver/sqlite3.php
index b7f6e60337..0508500c52 100644
--- a/phpBB/phpbb/db/driver/sqlite3.php
+++ b/phpBB/phpbb/db/driver/sqlite3.php
@@ -102,7 +102,7 @@ class sqlite3 extends \phpbb\db\driver\driver
break;
case 'rollback':
- return $this->dbo->exec('ROLLBACK');
+ return @$this->dbo->exec('ROLLBACK');
break;
}
@@ -134,9 +134,26 @@ class sqlite3 extends \phpbb\db\driver\driver
if ($this->query_result === false)
{
+ if ($this->transaction === true && strpos($query, 'INSERT') === 0)
+ {
+ $query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query);
+ }
+
if (($this->query_result = @$this->dbo->query($query)) === false)
{
- $this->sql_error($query);
+ // Try to recover a lost database connection
+ if ($this->dbo && !@$this->dbo->lastErrorMsg())
+ {
+ if ($this->sql_connect($this->server, $this->user, '', $this->dbname))
+ {
+ $this->query_result = @$this->dbo->query($query);
+ }
+ }
+
+ if ($this->query_result === false)
+ {
+ $this->sql_error($query);
+ }
}
if (defined('DEBUG'))
@@ -213,6 +230,7 @@ class sqlite3 extends \phpbb\db\driver\driver
if ($query_id === false)
{
+ /** @var \SQLite3Result $query_id */
$query_id = $this->query_result;
}
@@ -221,7 +239,7 @@ class sqlite3 extends \phpbb\db\driver\driver
return $cache->sql_fetchrow($query_id);
}
- return is_object($query_id) ? $query_id->fetchArray(SQLITE3_ASSOC) : false;
+ return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false;
}
/**
diff --git a/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php
index de127e3745..726822bc71 100644
--- a/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php
+++ b/phpBB/phpbb/db/migration/data/v320/allowed_schemes_links.php
@@ -15,6 +15,13 @@ namespace phpbb\db\migration\data\v320;
class allowed_schemes_links extends \phpbb\db\migration\migration
{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
public function update_data()
{
return array(
diff --git a/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php
index fe30a1c1b8..7afecb884b 100644
--- a/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php
+++ b/phpBB/phpbb/db/migration/data/v320/announce_global_permission.php
@@ -29,7 +29,9 @@ class announce_global_permission extends \phpbb\db\migration\migration
static public function depends_on()
{
- return array('\phpbb\db\migration\data\v310\rc2');
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
}
public function update_data()
diff --git a/phpBB/phpbb/db/migration/data/v320/dev.php b/phpBB/phpbb/db/migration/data/v320/dev.php
new file mode 100644
index 0000000000..ad2da3c1f4
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/dev.php
@@ -0,0 +1,36 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v320;
+
+class dev extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-dev', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v31x\v316',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-dev')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php b/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php
index 6ffaf18b4a..817b638037 100644
--- a/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php
+++ b/phpBB/phpbb/db/migration/data/v320/font_awesome_update.php
@@ -15,6 +15,13 @@ namespace phpbb\db\migration\data\v320;
class font_awesome_update extends \phpbb\db\migration\migration
{
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
public function effectively_installed()
{
return isset($this->config['load_font_awesome_url']);
diff --git a/phpBB/phpbb/db/migration/data/v320/icons_alt.php b/phpBB/phpbb/db/migration/data/v320/icons_alt.php
index 7071ae78db..80132e579e 100644
--- a/phpBB/phpbb/db/migration/data/v320/icons_alt.php
+++ b/phpBB/phpbb/db/migration/data/v320/icons_alt.php
@@ -17,7 +17,9 @@ class icons_alt extends \phpbb\db\migration\migration
{
static public function depends_on()
{
- return array('\phpbb\db\migration\data\v310\dev');
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
}
public function update_schema()
diff --git a/phpBB/phpbb/db/migration/data/v320/log_post_id.php b/phpBB/phpbb/db/migration/data/v320/log_post_id.php
index 0f155d543c..ead53c8138 100644
--- a/phpBB/phpbb/db/migration/data/v320/log_post_id.php
+++ b/phpBB/phpbb/db/migration/data/v320/log_post_id.php
@@ -17,7 +17,9 @@ class log_post_id extends \phpbb\db\migration\migration
{
static public function depends_on()
{
- return array('\phpbb\db\migration\data\v310\dev');
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
}
public function update_schema()
diff --git a/phpBB/phpbb/db/migration/data/v320/notifications_board.php b/phpBB/phpbb/db/migration/data/v320/notifications_board.php
index fd9f1a2ad6..8a76ebab58 100644
--- a/phpBB/phpbb/db/migration/data/v320/notifications_board.php
+++ b/phpBB/phpbb/db/migration/data/v320/notifications_board.php
@@ -17,7 +17,9 @@ class notifications_board extends \phpbb\db\migration\migration
{
static public function depends_on()
{
- return array('\phpbb\db\migration\data\v310\notifications');
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
}
public function update_data()
diff --git a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php
index 59208be4dc..c14d31f1c0 100644
--- a/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php
+++ b/phpBB/phpbb/db/migration/data/v320/remove_outdated_media.php
@@ -21,6 +21,13 @@ class remove_outdated_media extends \phpbb\db\migration\migration
ATTACHMENT_CATEGORY_QUICKTIME,
);
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
+ }
+
public function update_data()
{
return array(
diff --git a/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php b/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php
index 2898c708f8..1cb9070bf9 100644
--- a/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php
+++ b/phpBB/phpbb/db/migration/data/v320/remove_profilefield_wlm.php
@@ -17,7 +17,9 @@ class remove_profilefield_wlm extends \phpbb\db\migration\migration
{
static public function depends_on()
{
- return array('\phpbb\db\migration\data\v310\profilefield_wlm');
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ );
}
public function update_schema()
diff --git a/phpBB/phpbb/db/migration/data/v320/v320a1.php b/phpBB/phpbb/db/migration/data/v320/v320a1.php
new file mode 100644
index 0000000000..d7ecb36f90
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v320/v320a1.php
@@ -0,0 +1,44 @@
+<?php
+/**
+*
+* This file is part of the phpBB Forum Software package.
+*
+* @copyright (c) phpBB Limited <https://www.phpbb.com>
+* @license GNU General Public License, version 2 (GPL-2.0)
+*
+* For full copyright and license information, please see
+* the docs/CREDITS.txt file.
+*
+*/
+
+namespace phpbb\db\migration\data\v320;
+
+class v320a1 extends \phpbb\db\migration\container_aware_migration
+{
+ public function effectively_installed()
+ {
+ return version_compare($this->config['version'], '3.2.0-a1', '>=');
+ }
+
+ static public function depends_on()
+ {
+ return array(
+ '\phpbb\db\migration\data\v320\dev',
+ '\phpbb\db\migration\data\v320\allowed_schemes_links',
+ '\phpbb\db\migration\data\v320\announce_global_permission',
+ '\phpbb\db\migration\data\v320\remove_profilefield_wlm',
+ '\phpbb\db\migration\data\v320\font_awesome_update',
+ '\phpbb\db\migration\data\v320\icons_alt',
+ '\phpbb\db\migration\data\v320\log_post_id',
+ '\phpbb\db\migration\data\v320\remove_outdated_media',
+ '\phpbb\db\migration\data\v320\notifications_board',
+ );
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.update', array('version', '3.2.0-dev')),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php
index 69ac71abb7..a5ed62fd65 100644
--- a/phpBB/phpbb/db/migration/tool/module.php
+++ b/phpBB/phpbb/db/migration/tool/module.php
@@ -262,7 +262,7 @@ class module implements \phpbb\db\migration\tool\tool_interface
// Success
$module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
- $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name));
+ $phpbb_log->add('admin', (isset($user->data['user_id'])) ? $user->data['user_id'] : ANONYMOUS, $user->ip, 'LOG_MODULE_ADD', false, array($module_log_name));
// Move the module if requested above/below an existing one
if (isset($data['before']) && $data['before'])
diff --git a/phpBB/phpbb/files/upload.php b/phpBB/phpbb/files/upload.php
index e011e714e5..a9bf74094d 100644
--- a/phpBB/phpbb/files/upload.php
+++ b/phpBB/phpbb/files/upload.php
@@ -65,9 +65,6 @@ class upload
/** @var request_interface Request class */
protected $request;
- /** @var string phpBB root path */
- protected $phpbb_root_path;
-
/**
* Init file upload class.
*
@@ -76,16 +73,14 @@ class upload
* @param language $language Language class
* @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper
* @param request_interface $request Request class
- * @param string $phpbb_root_path phpBB root path
*/
- public function __construct(filesystem_interface $filesystem, factory $factory, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path)
+ public function __construct(filesystem_interface $filesystem, factory $factory, language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, request_interface $request)
{
$this->filesystem = $filesystem;
$this->factory = $factory;
$this->language = $language;
$this->php_ini = $php_ini;
$this->request = $request;
- $this->phpbb_root_path = $phpbb_root_path;
}
/**
diff --git a/phpBB/phpbb/install/console/command/install/config/show.php b/phpBB/phpbb/install/console/command/install/config/show.php
index 4155440fc3..5d82d8d1ef 100644
--- a/phpBB/phpbb/install/console/command/install/config/show.php
+++ b/phpBB/phpbb/install/console/command/install/config/show.php
@@ -96,7 +96,7 @@ class show extends \phpbb\console\command\command
if (!is_file($config_file))
{
- $iohandler->add_error_message(array('MISSING_FILE', array($config_file)));
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
return;
}
diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php
index 81ad1039f6..d76182af92 100644
--- a/phpBB/phpbb/install/console/command/install/install.php
+++ b/phpBB/phpbb/install/console/command/install/install.php
@@ -116,7 +116,7 @@ class install extends \phpbb\console\command\command
if (!is_file($config_file))
{
- $iohandler->add_error_message(array('MISSING_FILE', array($config_file)));
+ $iohandler->add_error_message(array('MISSING_FILE', $config_file));
return 1;
}
@@ -127,7 +127,7 @@ class install extends \phpbb\console\command\command
}
catch (ParseException $e)
{
- $iohandler->add_error_message('INVALID_YAML_FILE');
+ $iohandler->add_error_message(array('INVALID_YAML_FILE', $config_file));
return 1;
}
diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php
index bfa9ec6238..ed817f7396 100644
--- a/phpBB/phpbb/install/controller/helper.php
+++ b/phpBB/phpbb/install/controller/helper.php
@@ -197,13 +197,14 @@ class helper
$this->language_cookie = $lang;
}
- $lang = (!empty($lang) && strpos($lang, '/')) ? $lang : null;
+ $lang = (!empty($lang) && strpos($lang, '/') === false) ? $lang : null;
$this->render_language_select($lang);
if ($lang !== null)
{
$this->language->set_user_language($lang, true);
+ $this->installer_config->set('user_language', $lang);
}
}
diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php
index 77e0a896bc..a41b4cd6a6 100644
--- a/phpBB/phpbb/install/installer.php
+++ b/phpBB/phpbb/install/installer.php
@@ -13,6 +13,7 @@
namespace phpbb\install;
+use phpbb\cache\driver\driver_interface;
use phpbb\di\ordered_service_collection;
use phpbb\install\exception\installer_config_not_writable_exception;
use phpbb\install\exception\jump_to_restart_point_exception;
@@ -26,6 +27,11 @@ use phpbb\path_helper;
class installer
{
/**
+ * @var driver_interface
+ */
+ protected $cache;
+
+ /**
* @var config
*/
protected $install_config;
@@ -55,11 +61,13 @@ class installer
/**
* Constructor
*
- * @param config $config Installer config handler
- * @param path_helper $path_helper Path helper
+ * @param driver_interface $cache Cache service
+ * @param config $config Installer config handler
+ * @param path_helper $path_helper Path helper
*/
- public function __construct(config $config, path_helper $path_helper)
+ public function __construct(driver_interface $cache, config $config, path_helper $path_helper)
{
+ $this->cache = $cache;
$this->install_config = $config;
$this->installer_modules = null;
$this->web_root = $path_helper->get_web_root_path();
@@ -235,6 +243,7 @@ class installer
if ($install_finished || $fail_cleanup)
{
$this->install_config->clean_up_config_file();
+ $this->cache->purge();
}
else
{
diff --git a/phpBB/phpbb/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php
index b45d3808db..2ee641ff63 100644
--- a/phpBB/phpbb/install/module/install_data/task/add_bots.php
+++ b/phpBB/phpbb/install/module/install_data/task/add_bots.php
@@ -197,6 +197,11 @@ class add_bots extends \phpbb\install\task_base
'user_allow_pm' => 0,
);
+ if (!function_exists('user_add'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
$user_id = user_add($user_row);
if (!$user_id)
diff --git a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php
index 25da36e01d..6fb03ff73d 100644
--- a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php
+++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php
@@ -233,7 +233,7 @@ class add_config_settings extends \phpbb\install\task_base
SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "',
user_password='" . $this->password_manager->hash($this->install_config->get('admin_passwd')) . "',
user_ip = '" . $this->db->sql_escape($user_ip) . "',
- user_lang = '" . $this->db->sql_escape($this->install_config->get('language')) . "',
+ user_lang = '" . $this->db->sql_escape($this->install_config->get('user_language', 'en')) . "',
user_email='" . $this->db->sql_escape($this->install_config->get('board_email')) . "',
user_dateformat='" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "',
user_email_hash = " . $this->db->sql_escape(phpbb_email_hash($this->install_config->get('board_email'))) . ",
diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php
index 7cc521eee8..cabb78787f 100644
--- a/phpBB/phpbb/install/module/install_database/task/create_schema.php
+++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php
@@ -80,6 +80,16 @@ class create_schema extends \phpbb\install\task_base
$factory = new \phpbb\db\tools\factory();
$this->db = new $dbms();
+ $this->db->sql_connect(
+ $config->get('dbhost'),
+ $config->get('dbuser'),
+ $config->get('dbpasswd'),
+ $config->get('dbname'),
+ $config->get('dbport'),
+ false,
+ false
+ );
+
$this->config = $config;
$this->db_tools = $factory->get($this->db);
$this->database_helper = $db_helper;
@@ -89,9 +99,6 @@ class create_schema extends \phpbb\install\task_base
$this->php_ext = $php_ext;
parent::__construct(true);
-
- // Connect to DB
- $this->db->sql_connect($config->get('dbhost'), $config->get('dbuser'), $config->get('dbpasswd'), $config->get('dbname'), $config->get('dbport'), false, false);
}
/**
diff --git a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php
index 337d401216..e0890a929c 100644
--- a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php
+++ b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php
@@ -51,6 +51,11 @@ class create_config_file extends \phpbb\install\task_base
protected $php_ext;
/**
+ * @var array
+ */
+ protected $options;
+
+ /**
* Constructor
*
* @param \phpbb\filesystem\filesystem_interface $filesystem
@@ -59,13 +64,15 @@ class create_config_file extends \phpbb\install\task_base
* @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
* @param string $phpbb_root_path
* @param string $php_ext
+ * @param array $options
*/
public function __construct(\phpbb\filesystem\filesystem_interface $filesystem,
\phpbb\install\helper\config $install_config,
\phpbb\install\helper\database $db_helper,
\phpbb\install\helper\iohandler\iohandler_interface $iohandler,
$phpbb_root_path,
- $php_ext)
+ $php_ext,
+ $options = array())
{
$this->install_config = $install_config;
$this->db_helper = $db_helper;
@@ -73,6 +80,11 @@ class create_config_file extends \phpbb\install\task_base
$this->iohandler = $iohandler;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
+ $this->options = array_merge(array(
+ 'debug' => false,
+ 'debug_container' => false,
+ 'environment' => null,
+ ), $options);
parent::__construct(true);
}
@@ -93,7 +105,7 @@ class create_config_file extends \phpbb\install\task_base
$config_written = false;
}
- $config_content = $this->get_config_data();
+ $config_content = $this->get_config_data($this->options['debug'], $this->options['debug_container'], $this->options['environment']);
if (!@fwrite($fp, $config_content))
{
@@ -145,15 +157,14 @@ class create_config_file extends \phpbb\install\task_base
/**
* Returns the content which should be dumped to config.php
*
- * @param bool $debug If the debug constants should be enabled by default or not
- * @param bool $debug_container If the container should be compiled on
+ * @param bool $debug If the debug constants should be enabled by default or not
+ * @param bool $debug_container If the container should be compiled on
* every page load or not
- * @param bool $debug_test If the DEBUG_TEST constant should be added
- * NOTE: Only for use within the testing framework
+ * @param string $environment The environment to use
*
* @return string content to be written to the config file
*/
- protected function get_config_data($debug = false, $debug_container = false, $debug_test = false)
+ protected function get_config_data($debug = false, $debug_container = false, $environment = null)
{
$config_content = "<?php\n";
$config_content .= "// phpBB 3.2.x auto-generated configuration file\n// Do not change anything in this file!\n";
@@ -184,7 +195,7 @@ class create_config_file extends \phpbb\install\task_base
$config_content .= "\n@define('PHPBB_INSTALLED', true);\n";
$config_content .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n";
- if ($debug_test)
+ if ($environment)
{
$config_content .= "@define('PHPBB_ENVIRONMENT', 'test');\n";
}
@@ -206,7 +217,7 @@ class create_config_file extends \phpbb\install\task_base
$config_content .= "// @define('DEBUG_CONTAINER', true);\n";
}
- if ($debug_test)
+ if ($environment === 'test')
{
$config_content .= "@define('DEBUG_TEST', true);\n";
diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php
index 0af76f6f60..5268b85a42 100644
--- a/phpBB/phpbb/install/module/install_finish/task/notify_user.php
+++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php
@@ -41,6 +41,11 @@ class notify_user extends \phpbb\install\task_base
protected $config;
/**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
* @var \phpbb\log\log_interface
*/
protected $log;
@@ -75,6 +80,7 @@ class notify_user extends \phpbb\install\task_base
$this->iohandler = $iohandler;
$this->auth = $container->get('auth');
+ $this->language = $container->get('language');
$this->log = $container->get('log');
$this->user = $container->get('user');
$this->phpbb_root_path = $phpbb_root_path;
@@ -86,6 +92,8 @@ class notify_user extends \phpbb\install\task_base
$container->get('cache.driver'),
$container->get_parameter('tables.config')
);
+
+ parent::__construct(true);
}
/**
@@ -100,8 +108,13 @@ class notify_user extends \phpbb\install\task_base
{
include ($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext);
+ // functions_messenger.php uses config to determine language paths
+ // Remove when able
+ global $config;
+ $config = $this->config;
+
$messenger = new \messenger(false);
- $messenger->template('installed', $this->install_config->get('language'));
+ $messenger->template('installed', $this->install_config->get('user_language', 'en'));
$messenger->to($this->config['board_email'], $this->install_config->get('admin_name'));
$messenger->anti_abuse_headers($this->config, $this->user);
$messenger->assign_vars(array(
diff --git a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php
index b2a4800f86..8629d9aea3 100644
--- a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php
+++ b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php
@@ -37,6 +37,8 @@ class populate_migrations extends \phpbb\install\task_base
{
$this->extension_manager = $container->get('ext.manager');
$this->migrator = $container->get('migrator');
+
+ parent::__construct(true);
}
/**
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
index 41616e995a..ac305e8ab5 100644
--- a/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
@@ -70,7 +70,7 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta
$admin_name = $this->io_handler->get_input('admin_name', '', true);
$admin_pass1 = $this->io_handler->get_input('admin_pass1', '', true);
$admin_pass2 = $this->io_handler->get_input('admin_pass2', '', true);
- $board_email = $this->io_handler->get_input('board_email', '');
+ $board_email = $this->io_handler->get_input('board_email', '', true);
$admin_data_valid = $this->check_admin_data($admin_name, $admin_pass1, $admin_pass2, $board_email);
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
index 0726cc449c..6c54561d14 100644
--- a/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
@@ -76,8 +76,8 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta
{
// Board data
$default_lang = $this->io_handler->get_input('default_lang', '');
- $board_name = $this->io_handler->get_input('board_name', '');
- $board_desc = $this->io_handler->get_input('board_description', '');
+ $board_name = $this->io_handler->get_input('board_name', '', true);
+ $board_desc = $this->io_handler->get_input('board_description', '', true);
// Check default lang
$langs = $this->language_helper->get_available_languages();
@@ -116,8 +116,8 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta
{
if ($use_request_data)
{
- $board_name = $this->io_handler->get_input('board_name', '');
- $board_desc = $this->io_handler->get_input('board_description', '');
+ $board_name = $this->io_handler->get_input('board_name', '', true);
+ $board_desc = $this->io_handler->get_input('board_description', '', true);
}
else
{
@@ -126,7 +126,7 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta
}
// Use language because we only check this to be valid
- $default_lang = $this->install_config->get('language', '');
+ $default_lang = $this->install_config->get('user_language', 'en');
$langs = $this->language_helper->get_available_languages();
$lang_options = array();
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php
index ae7526a9e3..b04b8e353f 100644
--- a/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php
@@ -116,12 +116,12 @@ class obtain_email_data extends \phpbb\install\task_base implements \phpbb\insta
),
'smtp_host' => array(
'label' => 'SMTP_SERVER',
- 'description' => 'SMTP_SERVER_EXPLAIN',
'type' => 'text',
'default' => $smtp_host,
),
'smtp_auth' => array(
'label' => 'SMTP_AUTH_METHOD',
+ 'description' => 'SMTP_AUTH_METHOD_EXPLAIN',
'type' => 'select',
'options' => $auth_options,
),
diff --git a/phpBB/phpbb/install/module/update_database/task/update.php b/phpBB/phpbb/install/module/update_database/task/update.php
index 2d640134a3..84ec6f73f5 100644
--- a/phpBB/phpbb/install/module/update_database/task/update.php
+++ b/phpBB/phpbb/install/module/update_database/task/update.php
@@ -172,7 +172,7 @@ class update extends task_base
{
$this->log->add(
'admin',
- $this->user->data['user_id'],
+ (isset($this->user->data['user_id'])) ? $this->user->data['user_id'] : ANONYMOUS,
$this->user->ip,
'LOG_UPDATE_DATABASE',
false,
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
index 1c6b9aa058..e712b8ad6a 100644
--- a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
+++ b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
@@ -100,7 +100,7 @@ class show_file_status extends task_base
{
$this->file_updater->create_new_file(
$filename,
- $this->cache->get('_file_' . md5($filename)),
+ base64_decode($this->cache->get('_file_' . md5($filename))),
true
);
}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/update_files.php b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
index 747a86281b..fbb465cc66 100644
--- a/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
+++ b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
@@ -164,20 +164,20 @@ class update_files extends task_base
{
case 'delete':
$this->file_updater->delete_file($path);
- break;
+ break;
case 'new':
$this->file_updater->create_new_file($path, $new_path . $path);
- break;
+ break;
case 'update_without_diff':
$this->file_updater->update_file($path, $new_path . $path);
- break;
+ break;
case 'update_with_diff':
$this->file_updater->update_file(
$path,
- $this->cache->get('_file_' . md5($path)),
+ base64_decode($this->cache->get('_file_' . md5($path))),
true
);
- break;
+ break;
}
// Save progress
diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php
index 47f055f56a..382d4db89e 100644
--- a/phpBB/phpbb/language/language.php
+++ b/phpBB/phpbb/language/language.php
@@ -549,6 +549,16 @@ class language
}
/**
+ * Returns the ISO code of the used language
+ *
+ * @return string The ISO code of the currently used language
+ */
+ public function get_used_language()
+ {
+ return $this->language_fallback[0];
+ }
+
+ /**
* Returns language fallback data
*
* @param bool $reload Whether or not to reload language files
@@ -559,12 +569,12 @@ class language
{
$fallback_array = array();
- if ($this->user_language !== false)
+ if ($this->user_language)
{
$fallback_array[] = $this->user_language;
}
- if ($this->default_language !== false)
+ if ($this->default_language)
{
$fallback_array[] = $this->default_language;
}
diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php
index 4be678ac91..ea1b800dc5 100644
--- a/phpBB/phpbb/notification/manager.php
+++ b/phpBB/phpbb/notification/manager.php
@@ -44,6 +44,9 @@ class manager
/** @var \phpbb\cache\service */
protected $cache;
+ /** @var \phpbb\language\language */
+ protected $language;
+
/** @var \phpbb\user */
protected $user;
@@ -63,13 +66,14 @@ class manager
* @param \phpbb\event\dispatcher_interface $phpbb_dispatcher
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\cache\service $cache
+ * @param \phpbb\language\language $language
* @param \phpbb\user $user
* @param string $notification_types_table
* @param string $user_notifications_table
*
* @return \phpbb\notification\manager
*/
- public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\user $user, $notification_types_table, $user_notifications_table)
+ public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, \phpbb\language\language $language, \phpbb\user $user, $notification_types_table, $user_notifications_table)
{
$this->notification_types = $notification_types;
$this->notification_methods = $notification_methods;
@@ -79,6 +83,7 @@ class manager
$this->phpbb_dispatcher = $phpbb_dispatcher;
$this->db = $db;
$this->cache = $cache;
+ $this->language = $language;
$this->user = $user;
$this->notification_types_table = $notification_types_table;
@@ -111,7 +116,7 @@ class manager
if (! $method instanceof \phpbb\notification\method\method_interface)
{
- throw new \phpbb\notification\exception($this->user->lang('NOTIFICATION_METHOD_INVALID', $method_name));
+ throw new \phpbb\notification\exception($this->language->lang('NOTIFICATION_METHOD_INVALID', $method_name));
}
else if ($method->is_available())
{
@@ -166,7 +171,7 @@ class manager
$notification_type_id = false;
}
- /** @var method_interface $method */
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->mark_notifications($notification_type_id, $item_id, $user_id, $time, $mark_read);
@@ -208,6 +213,7 @@ class manager
$notification_type_id = $this->get_notification_type_id($notification_type_name);
}
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time, $mark_read);
@@ -263,8 +269,6 @@ class manager
return $notified_users;
}
- $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
-
// find out which users want to receive this type of notification
$notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options);
@@ -317,7 +321,7 @@ class manager
$item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
$user_ids = array();
- $notification_objects = $notification_methods = array();
+ $notification_methods = array();
// Never send notifications to the anonymous user!
unset($notify_users[ANONYMOUS]);
@@ -325,6 +329,7 @@ class manager
// Make sure not to send new notifications to users who've already been notified about this item
// This may happen when an item was added, but now new users are able to see the item
// We remove each user which was already notified by at least one method.
+ /** @var method\method_interface $method */
foreach ($this->get_subscription_methods_instances() as $method)
{
$notified_users = $method->get_notified_users($notification_type_id, array('item_id' => $item_id));
@@ -415,6 +420,7 @@ class manager
$options['item_id'] = $notification->get_item_id($data);
}
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->update_notification($notification, $data, $options);
@@ -443,6 +449,7 @@ class manager
$notification_type_id = $this->get_notification_type_id($notification_type_name);
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->delete_notifications($notification_type_id, $item_id, $parent_id, $user_id);
@@ -462,6 +469,7 @@ class manager
foreach ($this->notification_types as $type_name => $data)
{
+ /** @var type\base $type */
$type = $this->get_item_type_class($type_name);
if ($type instanceof \phpbb\notification\type\type_interface && $type->is_available())
@@ -497,6 +505,7 @@ class manager
{
$subscription_methods = array();
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method_name => $method)
{
$subscription_methods[$method_name] = array(
@@ -539,6 +548,7 @@ class manager
{
$subscription_methods = array();
+ /** @var method\method_interface $method */
foreach ($this->get_subscription_methods_instances() as $method_name => $method)
{
if ($method->is_available())
@@ -768,6 +778,7 @@ class manager
{
$notification_type_id = $this->get_notification_type_id($notification_type_name);
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->purge_notifications($notification_type_id);
@@ -805,6 +816,7 @@ class manager
*/
public function prune_notifications($timestamp, $only_read = true)
{
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$method->prune_notifications($timestamp, $only_read);
@@ -834,6 +846,8 @@ class manager
/**
* Helper to get the notifications item type class and set it up
*
+ * @param string $notification_type_name
+ * @param array $data
* @return type\type_interface
*/
public function get_item_type_class($notification_type_name, $data = array())
@@ -848,6 +862,7 @@ class manager
/**
* Helper to get the notifications method class and set it up
*
+ * @param string $method_name
* @return method\method_interface
*/
public function get_method_class($method_name)
@@ -858,6 +873,7 @@ class manager
/**
* Helper to load objects (notification types/methods)
*
+ * @param string $object_name
* @return method\method_interface|type\type_interface
*/
protected function load_object($object_name)
@@ -950,6 +966,8 @@ class manager
$notification_type_id = $this->get_notification_type_id($notification_type_name);
$notified_users = array();
+
+ /** @var method\method_interface $method */
foreach ($this->get_available_subscription_methods() as $method)
{
$notified_users = $notified_users + $method->get_notified_users($notification_type_id, $options);
diff --git a/phpBB/phpbb/notification/method/board.php b/phpBB/phpbb/notification/method/board.php
index c45f3a8caa..931b252daa 100644
--- a/phpBB/phpbb/notification/method/board.php
+++ b/phpBB/phpbb/notification/method/board.php
@@ -266,6 +266,7 @@ class board extends \phpbb\notification\method\base
{
$insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table);
+ /** @var \phpbb\notification\type\type_interface $notification */
foreach ($this->queue as $notification)
{
$data = $notification->get_insert_array();
diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php
index 61119b9882..8a8e284e13 100644
--- a/phpBB/phpbb/notification/method/messenger_base.php
+++ b/phpBB/phpbb/notification/method/messenger_base.php
@@ -82,6 +82,7 @@ abstract class messenger_base extends \phpbb\notification\method\base
$messenger = new \messenger();
// Time to go through the queue and send emails
+ /** @var \phpbb\notification\type\type_interface $notification */
foreach ($this->queue as $notification)
{
if ($notification->get_email_template() === false)
diff --git a/phpBB/phpbb/notification/type/admin_activate_user.php b/phpBB/phpbb/notification/type/admin_activate_user.php
index b191fa62ae..9f2ae857ef 100644
--- a/phpBB/phpbb/notification/type/admin_activate_user.php
+++ b/phpBB/phpbb/notification/type/admin_activate_user.php
@@ -130,7 +130,7 @@ class admin_activate_user extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->item_id, 'no_profile');
- return $this->user->lang($this->language_key, $username);
+ return $this->language->lang($this->language_key, $username);
}
/**
diff --git a/phpBB/phpbb/notification/type/base.php b/phpBB/phpbb/notification/type/base.php
index 31e853d7d9..4aacb1c99e 100644
--- a/phpBB/phpbb/notification/type/base.php
+++ b/phpBB/phpbb/notification/type/base.php
@@ -24,6 +24,9 @@ abstract class base implements \phpbb\notification\type\type_interface
/** @var \phpbb\db\driver\driver_interface */
protected $db;
+ /** @var \phpbb\language\language */
+ protected $language;
+
/** @var \phpbb\user */
protected $user;
@@ -56,7 +59,7 @@ abstract class base implements \phpbb\notification\type\type_interface
protected $notification_type_id;
/**
- * Indentification data
+ * Identification data
* notification_type_id - ID of the item type (auto generated, from notification types table)
* item_id - ID of the item (e.g. post_id, msg_id)
* item_parent_id - Parent item id (ex: for topic => forum_id, for post => topic_id, etc)
@@ -71,19 +74,20 @@ abstract class base implements \phpbb\notification\type\type_interface
private $data = array();
/**
- * Notification Type Base Constructor
- *
- * @param \phpbb\db\driver\driver_interface $db
- * @param \phpbb\user $user
- * @param \phpbb\auth\auth $auth
- * @param string $phpbb_root_path
- * @param string $php_ext
- * @param string $user_notifications_table
- * @return \phpbb\notification\type\base
- */
- public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\user $user, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext, $user_notifications_table)
+ * Notification Type Base Constructor
+ *
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\language\language $language
+ * @param \phpbb\user $user
+ * @param \phpbb\auth\auth $auth
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ * @param string $user_notifications_table
+ */
+ public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\language\language $language, \phpbb\user $user, \phpbb\auth\auth $auth, $phpbb_root_path, $php_ext, $user_notifications_table)
{
$this->db = $db;
+ $this->language = $language;
$this->user = $user;
$this->auth = $auth;
@@ -192,7 +196,7 @@ abstract class base implements \phpbb\notification\type\type_interface
'notification_time' => time(),
'notification_read' => false,
- 'notification_data' => array(),
+ 'notification_data' => array(),
), $this->data);
}
@@ -304,6 +308,7 @@ abstract class base implements \phpbb\notification\type\type_interface
* URL to unsubscribe to this notification (fall back)
*
* @param string|bool $method Method name to unsubscribe from (email|jabber|etc), False to unsubscribe from all notifications for this item
+ * @return false
*/
public function get_unsubscribe_url($method = false)
{
@@ -371,8 +376,11 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
- * Load the special items (fall back)
- */
+ * Load the special items (fall back)
+ *
+ * @param array $data
+ * @param array $notifications
+ */
public function load_special($data, $notifications)
{
return;
@@ -389,10 +397,12 @@ abstract class base implements \phpbb\notification\type\type_interface
}
/**
- * Pre create insert array function (fall back)
- *
- * @return array
- */
+ * Pre create insert array function (fall back)
+ *
+ * @param array $type_data
+ * @param array $notify_users
+ * @return array
+ */
public function pre_create_insert_array($type_data, $notify_users)
{
return array();
@@ -403,13 +413,13 @@ abstract class base implements \phpbb\notification\type\type_interface
*/
/**
- * Find the users who want to receive notifications (helper)
- *
- * @param array $user_ids User IDs to check if they want to receive notifications
- * (Bool False to check all users besides anonymous and bots (USER_IGNORE))
- *
- * @return array
- */
+ * Find the users who want to receive notifications (helper)
+ *
+ * @param array|bool $user_ids User IDs to check if they want to receive notifications
+ * (Bool False to check all users besides anonymous and bots (USER_IGNORE))
+ * @param array $options
+ * @return array
+ */
protected function check_user_notification_options($user_ids = false, $options = array())
{
$options = array_merge(array(
@@ -505,6 +515,8 @@ abstract class base implements \phpbb\notification\type\type_interface
{
$this->notification_manager->mark_notifications($this->get_type(), (int) $this->item_id, (int) $this->user_id, false, $this->notification_read);
}
+
+ return null;
}
/**
diff --git a/phpBB/phpbb/notification/type/disapprove_post.php b/phpBB/phpbb/notification/type/disapprove_post.php
index 21338bddb7..2d908eb254 100644
--- a/phpBB/phpbb/notification/type/disapprove_post.php
+++ b/phpBB/phpbb/notification/type/disapprove_post.php
@@ -73,7 +73,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_title()
{
- return $this->user->lang($this->language_key);
+ return $this->language->lang($this->language_key);
}
/**
@@ -83,7 +83,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -96,7 +96,7 @@ class disapprove_post extends \phpbb\notification\type\approve_post
*/
public function get_reason()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('disapprove_reason')
);
diff --git a/phpBB/phpbb/notification/type/disapprove_topic.php b/phpBB/phpbb/notification/type/disapprove_topic.php
index 30a23a83fe..c2522fb562 100644
--- a/phpBB/phpbb/notification/type/disapprove_topic.php
+++ b/phpBB/phpbb/notification/type/disapprove_topic.php
@@ -73,7 +73,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_title()
{
- return $this->user->lang($this->language_key);
+ return $this->language->lang($this->language_key);
}
/**
@@ -83,7 +83,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -96,7 +96,7 @@ class disapprove_topic extends \phpbb\notification\type\approve_topic
*/
public function get_reason()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('disapprove_reason')
);
diff --git a/phpBB/phpbb/notification/type/group_request.php b/phpBB/phpbb/notification/type/group_request.php
index 8a0027bfec..28a9e73bf9 100644
--- a/phpBB/phpbb/notification/type/group_request.php
+++ b/phpBB/phpbb/notification/type/group_request.php
@@ -114,7 +114,7 @@ class group_request extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->item_id, 'no_profile');
- return $this->user->lang('NOTIFICATION_GROUP_REQUEST', $username, $this->get_data('group_name'));
+ return $this->language->lang('NOTIFICATION_GROUP_REQUEST', $username, $this->get_data('group_name'));
}
/**
diff --git a/phpBB/phpbb/notification/type/group_request_approved.php b/phpBB/phpbb/notification/type/group_request_approved.php
index dc353f3380..f55d28bafd 100644
--- a/phpBB/phpbb/notification/type/group_request_approved.php
+++ b/phpBB/phpbb/notification/type/group_request_approved.php
@@ -69,7 +69,7 @@ class group_request_approved extends \phpbb\notification\type\base
*/
public function get_title()
{
- return $this->user->lang('NOTIFICATION_GROUP_REQUEST_APPROVED', $this->get_data('group_name'));
+ return $this->language->lang('NOTIFICATION_GROUP_REQUEST_APPROVED', $this->get_data('group_name'));
}
/**
diff --git a/phpBB/phpbb/notification/type/pm.php b/phpBB/phpbb/notification/type/pm.php
index 2de2dcfa0b..8fb9172911 100644
--- a/phpBB/phpbb/notification/type/pm.php
+++ b/phpBB/phpbb/notification/type/pm.php
@@ -128,7 +128,7 @@ class pm extends \phpbb\notification\type\base
{
$username = $this->user_loader->get_username($this->get_data('from_user_id'), 'no_profile');
- return $this->user->lang('NOTIFICATION_PM', $username);
+ return $this->language->lang('NOTIFICATION_PM', $username);
}
/**
@@ -138,7 +138,7 @@ class pm extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
$this->get_data('message_subject')
);
diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php
index b16014ff74..b9afc6d70a 100644
--- a/phpBB/phpbb/notification/type/post.php
+++ b/phpBB/phpbb/notification/type/post.php
@@ -83,6 +83,7 @@ class post extends \phpbb\notification\type\base
* Get the id of the item
*
* @param array $post The data from the post
+ * @return int The post id
*/
static public function get_item_id($post)
{
@@ -93,6 +94,7 @@ class post extends \phpbb\notification\type\base
* Get the id of the parent
*
* @param array $post The data from the post
+ * @return int The topic id
*/
static public function get_item_parent_id($post)
{
@@ -218,14 +220,14 @@ class post extends \phpbb\notification\type\base
if ($trimmed_responders_cnt > 20)
{
- $usernames[] = $this->user->lang('NOTIFICATION_MANY_OTHERS');
+ $usernames[] = $this->language->lang('NOTIFICATION_MANY_OTHERS');
}
else if ($trimmed_responders_cnt)
{
- $usernames[] = $this->user->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt);
+ $usernames[] = $this->language->lang('NOTIFICATION_X_OTHERS', $trimmed_responders_cnt);
}
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
phpbb_generate_string_list($usernames, $this->user),
$responders_cnt
@@ -239,7 +241,7 @@ class post extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -407,6 +409,7 @@ class post extends \phpbb\notification\type\base
* Add responders to the notification
*
* @param mixed $post
+ * @return array Array of responder data
*/
public function add_responders($post)
{
diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php
index 2edf37efc7..684463c8c3 100644
--- a/phpBB/phpbb/notification/type/quote.php
+++ b/phpBB/phpbb/notification/type/quote.php
@@ -106,6 +106,7 @@ class quote extends \phpbb\notification\type\post
* Update a notification
*
* @param array $post Data specific for this type that will be updated
+ * @return true
*/
public function update_notifications($post)
{
diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php
index 4be4705d05..6091919769 100644
--- a/phpBB/phpbb/notification/type/report_pm.php
+++ b/phpBB/phpbb/notification/type/report_pm.php
@@ -70,6 +70,7 @@ class report_pm extends \phpbb\notification\type\pm
* Get the id of the parent
*
* @param array $pm The data from the pm
+ * @return int The report id
*/
static public function get_item_parent_id($pm)
{
@@ -144,10 +145,10 @@ class report_pm extends \phpbb\notification\type\pm
$user_data = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
return array(
- 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
- 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
+ 'AUTHOR_NAME' => htmlspecialchars_decode($user_data['username']),
+ 'SUBJECT' => htmlspecialchars_decode(censor_text($this->get_data('message_subject'))),
- 'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details",
+ 'U_VIEW_REPORT' => generate_board_url() . "mcp.{$this->php_ext}?r={$this->item_parent_id}&amp;i=pm_reports&amp;mode=pm_report_details",
);
}
@@ -168,11 +169,11 @@ class report_pm extends \phpbb\notification\type\pm
*/
public function get_title()
{
- $this->user->add_lang('mcp');
+ $this->language->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -185,7 +186,7 @@ class report_pm extends \phpbb\notification\type\pm
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('message_subject'))
);
@@ -200,21 +201,21 @@ class report_pm extends \phpbb\notification\type\pm
{
if ($this->get_data('report_text'))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('report_text')
);
}
- if (isset($this->user->lang[$this->get_data('reason_title')]))
+ if ($this->language->is_set($this->get_data('reason_title')))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
- $this->user->lang[$this->get_data('reason_title')]
+ $this->language->lang($this->get_data('reason_title'))
);
}
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('reason_description')
);
diff --git a/phpBB/phpbb/notification/type/report_pm_closed.php b/phpBB/phpbb/notification/type/report_pm_closed.php
index f793c7df9a..5e98eb5feb 100644
--- a/phpBB/phpbb/notification/type/report_pm_closed.php
+++ b/phpBB/phpbb/notification/type/report_pm_closed.php
@@ -106,7 +106,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -119,7 +119,7 @@ class report_pm_closed extends \phpbb\notification\type\pm
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('message_subject'))
);
diff --git a/phpBB/phpbb/notification/type/report_post.php b/phpBB/phpbb/notification/type/report_post.php
index 6eefd53832..84a5241417 100644
--- a/phpBB/phpbb/notification/type/report_post.php
+++ b/phpBB/phpbb/notification/type/report_post.php
@@ -139,11 +139,11 @@ class report_post extends \phpbb\notification\type\post_in_queue
*/
public function get_title()
{
- $this->user->add_lang('mcp');
+ $this->language->add_lang('mcp');
$username = $this->user_loader->get_username($this->get_data('reporter_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -156,7 +156,7 @@ class report_post extends \phpbb\notification\type\post_in_queue
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('post_subject'))
);
@@ -171,21 +171,21 @@ class report_post extends \phpbb\notification\type\post_in_queue
{
if ($this->get_data('report_text'))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('report_text')
);
}
- if (isset($this->user->lang[$this->get_data('reason_title')]))
+ if ($this->language->is_set($this->get_data('reason_title')))
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
- $this->user->lang[$this->get_data('reason_title')]
+ $this->language->lang($this->get_data('reason_title'))
);
}
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REASON',
$this->get_data('reason_description')
);
diff --git a/phpBB/phpbb/notification/type/report_post_closed.php b/phpBB/phpbb/notification/type/report_post_closed.php
index 6327011f2d..165034d57e 100644
--- a/phpBB/phpbb/notification/type/report_post_closed.php
+++ b/phpBB/phpbb/notification/type/report_post_closed.php
@@ -113,7 +113,7 @@ class report_post_closed extends \phpbb\notification\type\post
{
$username = $this->user_loader->get_username($this->get_data('closer_id'), 'no_profile');
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -126,7 +126,7 @@ class report_post_closed extends \phpbb\notification\type\post
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('post_subject'))
);
diff --git a/phpBB/phpbb/notification/type/topic.php b/phpBB/phpbb/notification/type/topic.php
index 4812e8b5af..671c34fe96 100644
--- a/phpBB/phpbb/notification/type/topic.php
+++ b/phpBB/phpbb/notification/type/topic.php
@@ -83,6 +83,7 @@ class topic extends \phpbb\notification\type\base
* Get the id of the item
*
* @param array $post The data from the post
+ * @return int The topic id
*/
static public function get_item_id($post)
{
@@ -93,6 +94,7 @@ class topic extends \phpbb\notification\type\base
* Get the id of the parent
*
* @param array $post The data from the post
+ * @return int The forum id
*/
static public function get_item_parent_id($post)
{
@@ -154,7 +156,7 @@ class topic extends \phpbb\notification\type\base
$username = $this->user_loader->get_username($this->get_data('poster_id'), 'no_profile');
}
- return $this->user->lang(
+ return $this->language->lang(
$this->language_key,
$username
);
@@ -167,7 +169,7 @@ class topic extends \phpbb\notification\type\base
*/
public function get_reference()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_REFERENCE',
censor_text($this->get_data('topic_title'))
);
@@ -180,7 +182,7 @@ class topic extends \phpbb\notification\type\base
*/
public function get_forum()
{
- return $this->user->lang(
+ return $this->language->lang(
'NOTIFICATION_FORUM',
$this->get_data('forum_name')
);
diff --git a/phpBB/phpbb/textreparser/plugins/forum_description.php b/phpBB/phpbb/textreparser/plugins/forum_description.php
index 0302dc3082..b0f5a42452 100644
--- a/phpBB/phpbb/textreparser/plugins/forum_description.php
+++ b/phpBB/phpbb/textreparser/plugins/forum_description.php
@@ -27,12 +27,4 @@ class forum_description extends \phpbb\textreparser\row_based_plugin
'options' => 'forum_desc_options',
);
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return FORUMS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/forum_rules.php b/phpBB/phpbb/textreparser/plugins/forum_rules.php
index ce550225f2..d131d00707 100644
--- a/phpBB/phpbb/textreparser/plugins/forum_rules.php
+++ b/phpBB/phpbb/textreparser/plugins/forum_rules.php
@@ -27,12 +27,4 @@ class forum_rules extends \phpbb\textreparser\row_based_plugin
'options' => 'forum_rules_options',
);
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return FORUMS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/group_description.php b/phpBB/phpbb/textreparser/plugins/group_description.php
index 3346ccf25e..2c45c00474 100644
--- a/phpBB/phpbb/textreparser/plugins/group_description.php
+++ b/phpBB/phpbb/textreparser/plugins/group_description.php
@@ -27,12 +27,4 @@ class group_description extends \phpbb\textreparser\row_based_plugin
'options' => 'group_desc_options',
);
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return GROUPS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/pm_text.php b/phpBB/phpbb/textreparser/plugins/pm_text.php
index 4d06a2878b..867da624ee 100644
--- a/phpBB/phpbb/textreparser/plugins/pm_text.php
+++ b/phpBB/phpbb/textreparser/plugins/pm_text.php
@@ -29,12 +29,4 @@ class pm_text extends \phpbb\textreparser\row_based_plugin
'bbcode_uid' => 'bbcode_uid',
);
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return PRIVMSGS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/poll_title.php b/phpBB/phpbb/textreparser/plugins/poll_title.php
index 038ae0c366..76d30655c9 100644
--- a/phpBB/phpbb/textreparser/plugins/poll_title.php
+++ b/phpBB/phpbb/textreparser/plugins/poll_title.php
@@ -39,12 +39,4 @@ class poll_title extends \phpbb\textreparser\row_based_plugin
return $sql;
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return TOPICS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/post_text.php b/phpBB/phpbb/textreparser/plugins/post_text.php
index 4a07c98cea..1c98e86067 100644
--- a/phpBB/phpbb/textreparser/plugins/post_text.php
+++ b/phpBB/phpbb/textreparser/plugins/post_text.php
@@ -29,12 +29,4 @@ class post_text extends \phpbb\textreparser\row_based_plugin
'bbcode_uid' => 'bbcode_uid',
);
}
-
- /**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return POSTS_TABLE;
- }
}
diff --git a/phpBB/phpbb/textreparser/plugins/user_signature.php b/phpBB/phpbb/textreparser/plugins/user_signature.php
index f657a45d38..647d3a7b14 100644
--- a/phpBB/phpbb/textreparser/plugins/user_signature.php
+++ b/phpBB/phpbb/textreparser/plugins/user_signature.php
@@ -55,14 +55,6 @@ class user_signature extends \phpbb\textreparser\row_based_plugin
}
/**
- * {@inheritdoc}
- */
- public function get_table_name()
- {
- return USERS_TABLE;
- }
-
- /**
* Save the keyoptions var from \phpbb\user
*/
protected function save_keyoptions()
diff --git a/phpBB/phpbb/textreparser/row_based_plugin.php b/phpBB/phpbb/textreparser/row_based_plugin.php
index d3ca334591..2d32104493 100644
--- a/phpBB/phpbb/textreparser/row_based_plugin.php
+++ b/phpBB/phpbb/textreparser/row_based_plugin.php
@@ -21,13 +21,20 @@ abstract class row_based_plugin extends base
protected $db;
/**
+ * @var string
+ */
+ protected $table;
+
+ /**
* Constructor
*
* @param \phpbb\db\driver\driver_interface $db Database connection
+ * @param string $table
*/
- public function __construct(\phpbb\db\driver\driver_interface $db)
+ public function __construct(\phpbb\db\driver\driver_interface $db, $table)
{
$this->db = $db;
+ $this->table = $table;
}
/**
@@ -38,20 +45,13 @@ abstract class row_based_plugin extends base
abstract public function get_columns();
/**
- * Return the name of the table used by this plugin
- *
- * @return string
- */
- abstract public function get_table_name();
-
- /**
* {@inheritdoc}
*/
public function get_max_id()
{
$columns = $this->get_columns();
- $sql = 'SELECT MAX(' . $columns['id'] . ') AS max_id FROM ' . $this->get_table_name();
+ $sql = 'SELECT MAX(' . $columns['id'] . ') AS max_id FROM ' . $this->table;
$result = $this->db->sql_query($sql);
$max_id = (int) $this->db->sql_fetchfield('max_id');
$this->db->sql_freeresult($result);
@@ -96,7 +96,7 @@ abstract class row_based_plugin extends base
}
$sql = 'SELECT ' . implode(', ', $fields) . '
- FROM ' . $this->get_table_name() . '
+ FROM ' . $this->table . '
WHERE ' . $columns['id'] . ' BETWEEN ' . $min_id . ' AND ' . $max_id;
return $sql;
@@ -109,7 +109,7 @@ abstract class row_based_plugin extends base
{
$columns = $this->get_columns();
- $sql = 'UPDATE ' . $this->get_table_name() . '
+ $sql = 'UPDATE ' . $this->table . '
SET ' . $columns['text'] . " = '" . $this->db->sql_escape($record['text']) . "'
WHERE " . $columns['id'] . ' = ' . $record['id'];
$this->db->sql_query($sql);
diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg
index 481b80d912..33547c3ce5 100644
--- a/phpBB/styles/prosilver/style.cfg
+++ b/phpBB/styles/prosilver/style.cfg
@@ -21,8 +21,8 @@
# General Information about this style
name = prosilver
copyright = © phpBB Limited, 2007
-style_version = 3.2.0-a1-dev
-phpbb_version = 3.2.0-a1-dev
+style_version = 3.2.0-a1
+phpbb_version = 3.2.0-a1
# Defining a different template bitfield
# template_bitfield = lNg=
diff --git a/phpBB/styles/prosilver/template/ajax.js b/phpBB/styles/prosilver/template/ajax.js
index e3780f024a..aec6b0bbe6 100644
--- a/phpBB/styles/prosilver/template/ajax.js
+++ b/phpBB/styles/prosilver/template/ajax.js
@@ -87,7 +87,7 @@ phpbb.addAjaxCallback('mark_topics_read', function(res, updateTopicLinks) {
});
// Remove link to first unread post
- $('a').has('span.icon_topic_newest').remove();
+ $('a.unread').has('.icon-red').remove();
// Update mark topics read links
if (updateTopicLinks) {
diff --git a/phpBB/styles/prosilver/template/display_options.html b/phpBB/styles/prosilver/template/display_options.html
new file mode 100644
index 0000000000..d1ec3dcef1
--- /dev/null
+++ b/phpBB/styles/prosilver/template/display_options.html
@@ -0,0 +1,27 @@
+<div class="dropdown-container dropdown-container-{S_CONTENT_FLOW_BEGIN} dropdown-button-control sort-tools">
+ <span title="{L_SORT_OPTIONS}" class="button button-secondary dropdown-trigger dropdown-select">
+ <i class="icon fa-sort-amount-asc fa-fw" aria-hidden="true"></i>
+ <span class="caret"><i class="icon fa-sort-down fa-fw" aria-hidden="true"></i></span>
+ </span>
+ <div class="dropdown hidden">
+ <div class="pointer"><div class="pointer-inner"></div></div>
+ <div class="dropdown-contents">
+ <fieldset class="display-options">
+ <!-- IF S_SORT_OPTIONS -->
+ <label>{L_SORT_BY}{L_COLON} <select name="sk" id="sk">{S_SORT_OPTIONS}</select></label>
+ <label>{L_SORT_DIRECTION}{L_COLON} <select name="sd" id="sd">{S_ORDER_SELECT}</select></label>
+ <hr class="dashed" />
+ <input type="submit" class="button2" name="sort" value="{L_SORT}" />
+ <!-- ELSE -->
+ <label>{L_DISPLAY}{L_COLON} {S_SELECT_SORT_DAYS}</label>
+ <!-- IF S_SELECT_SORT_KEY -->
+ <label>{L_SORT_BY}{L_COLON} {S_SELECT_SORT_KEY}</label>
+ <label>{L_SORT_DIRECTION}{L_COLON} {S_SELECT_SORT_DIR}</label>
+ <!-- ENDIF -->
+ <hr class="dashed" />
+ <input type="submit" class="button2" name="sort" value="{L_GO}" />
+ <!-- ENDIF -->
+ </fieldset>
+ </div>
+ </div>
+</div>
diff --git a/phpBB/styles/prosilver/template/mcp_forum.html b/phpBB/styles/prosilver/template/mcp_forum.html
index 1f48b19c18..147afff0f5 100644
--- a/phpBB/styles/prosilver/template/mcp_forum.html
+++ b/phpBB/styles/prosilver/template/mcp_forum.html
@@ -108,16 +108,9 @@
</ul>
<!-- ENDIF -->
- <fieldset class="display-options">
- <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_TOPICS}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_logs.html b/phpBB/styles/prosilver/template/mcp_logs.html
index 9b4c4c786f..a50bd95ccd 100644
--- a/phpBB/styles/prosilver/template/mcp_logs.html
+++ b/phpBB/styles/prosilver/template/mcp_logs.html
@@ -51,16 +51,9 @@
</table>
<!-- IF .log -->
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_notes_user.html b/phpBB/styles/prosilver/template/mcp_notes_user.html
index a9c1e49360..6a9d88389c 100644
--- a/phpBB/styles/prosilver/template/mcp_notes_user.html
+++ b/phpBB/styles/prosilver/template/mcp_notes_user.html
@@ -90,17 +90,9 @@
</tbody>
</table>
- <hr />
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
- <fieldset class="display-options">
- <label>{L_DISPLAY_LOG}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
-
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_REPORTS}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html
index a0b470cbca..c7b52bb3a5 100644
--- a/phpBB/styles/prosilver/template/mcp_post.html
+++ b/phpBB/styles/prosilver/template/mcp_post.html
@@ -14,7 +14,7 @@
<h3>{L_REPORT_REASON}{L_COLON} {REPORT_REASON_TITLE}</h3>
<p class="author">{L_REPORTED} {L_POST_BY_AUTHOR} {REPORTER_FULL} &laquo; {REPORT_DATE}</p>
<!-- IF S_REPORT_CLOSED -->
- <p class="post-notice reported">{L_REPORT_CLOSED}</p>
+ <p class="post-notice reported"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i>{L_REPORT_CLOSED}</p>
<!-- ENDIF -->
<div class="content">
<!-- IF REPORT_TEXT -->
diff --git a/phpBB/styles/prosilver/template/mcp_queue.html b/phpBB/styles/prosilver/template/mcp_queue.html
index 169d201b16..ce58d110e1 100644
--- a/phpBB/styles/prosilver/template/mcp_queue.html
+++ b/phpBB/styles/prosilver/template/mcp_queue.html
@@ -73,16 +73,10 @@
<!-- END postrow -->
</ul>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" onClick="document.getElementById('mcp').submit()" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_reports.html b/phpBB/styles/prosilver/template/mcp_reports.html
index fbdd63ae9c..4131d9f2f3 100644
--- a/phpBB/styles/prosilver/template/mcp_reports.html
+++ b/phpBB/styles/prosilver/template/mcp_reports.html
@@ -79,16 +79,10 @@
<!-- END postrow -->
</ul>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" />&nbsp; <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <!-- IF TOPIC_ID --><label><input type="checkbox" class="radio" name="t" value="{TOPIC_ID}" checked="checked" onClick="document.getElementById('mcp').submit()" /> <strong>{L_ONLY_TOPIC}</strong></label><!-- ENDIF -->
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_REPORTS}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/mcp_topic.html b/phpBB/styles/prosilver/template/mcp_topic.html
index 9ab0b8e4cc..5f11e763e1 100644
--- a/phpBB/styles/prosilver/template/mcp_topic.html
+++ b/phpBB/styles/prosilver/template/mcp_topic.html
@@ -119,7 +119,7 @@
</p>
<!-- IF postrow.S_POST_UNAPPROVED -->
<p class="post-notice unapproved">
- <a href="{postrow.U_MCP_APPROVE}"><strong>{L_POST_UNAPPROVED}</strong></a>
+ <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>
</p>
<!-- ENDIF -->
@@ -131,7 +131,7 @@
<!-- IF postrow.S_POST_REPORTED -->
<p class="post-notice reported">
- <a href="{postrow.U_MCP_REPORT}"><strong>{L_POST_REPORTED}</strong></a>
+ <a href="{postrow.U_MCP_REPORT}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_REPORTED}</strong></a>
</p>
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/mcp_warn_list.html b/phpBB/styles/prosilver/template/mcp_warn_list.html
index 568705e7d0..215e155d5c 100644
--- a/phpBB/styles/prosilver/template/mcp_warn_list.html
+++ b/phpBB/styles/prosilver/template/mcp_warn_list.html
@@ -43,15 +43,9 @@
</tbody>
</table>
- <fieldset class="display-options">
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label><label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- </fieldset>
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_USERS}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/memberlist_body.html b/phpBB/styles/prosilver/template/memberlist_body.html
index c7f9340207..997147f492 100644
--- a/phpBB/styles/prosilver/template/memberlist_body.html
+++ b/phpBB/styles/prosilver/template/memberlist_body.html
@@ -14,7 +14,11 @@
<!-- IF S_SHOW_GROUP -->
<h2 class="group-title"<!-- IF GROUP_COLOR --> style="color:#{GROUP_COLOR};"<!-- ENDIF -->>{GROUP_NAME}</h2>
+ <!-- IF U_MANAGE -->
+ <p class="right responsive-center manage rightside"><a href="{U_MANAGE}">{L_MANAGE_GROUP}</a></p>
+ <!-- ENDIF -->
<p>{GROUP_DESC} {GROUP_TYPE}</p>
+
<p>
<!-- IF AVATAR_IMG -->{AVATAR_IMG}<!-- ENDIF -->
<!-- IF RANK_IMG -->{RANK_IMG}<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/search_body.html b/phpBB/styles/prosilver/template/search_body.html
index 8d56a103d2..618e2680ba 100644
--- a/phpBB/styles/prosilver/template/search_body.html
+++ b/phpBB/styles/prosilver/template/search_body.html
@@ -9,7 +9,9 @@
<div class="inner">
<h3>{L_SEARCH_QUERY}</h3>
+ <!-- EVENT search_body_search_query_before -->
<fieldset>
+ <!-- EVENT search_body_search_query_prepend -->
<dl>
<dt><label for="keywords">{L_SEARCH_KEYWORDS}{L_COLON}</label><br /><span>{L_SEARCH_KEYWORDS_EXPLAIN}</span></dt>
<dd><input type="search" class="inputbox" name="keywords" id="keywords" size="40" title="{L_SEARCH_KEYWORDS}" /></dd>
@@ -20,7 +22,9 @@
<dt><label for="author">{L_SEARCH_AUTHOR}{L_COLON}</label><br /><span>{L_SEARCH_AUTHOR_EXPLAIN}</span></dt>
<dd><input type="search" class="inputbox" name="author" id="author" size="40" title="{L_SEARCH_AUTHOR}" /></dd>
</dl>
+ <!-- EVENT search_body_search_query_append -->
</fieldset>
+ <!-- EVENT search_body_search_query_after -->
</div>
</div>
@@ -30,7 +34,9 @@
<h3>{L_SEARCH_OPTIONS}</h3>
+ <!-- EVENT search_body_search_options_before -->
<fieldset>
+ <!-- EVENT search_body_search_options_prepend -->
<dl>
<dt><label for="search_forum">{L_SEARCH_FORUMS}{L_COLON}</label><br /><span>{L_SEARCH_FORUMS_EXPLAIN}</span></dt>
<dd><select name="fid[]" id="search_forum" multiple="multiple" size="8" title="{L_SEARCH_FORUMS}">{S_FORUM_OPTIONS}</select></dd>
@@ -49,9 +55,11 @@
<dd><label for="sf3"><input type="radio" name="sf" id="sf3" value="titleonly" /> {L_SEARCH_TITLE_ONLY}</label></dd>
<dd><label for="sf4"><input type="radio" name="sf" id="sf4" value="firstpost" /> {L_SEARCH_FIRST_POST}</label></dd>
</dl>
+ <!-- EVENT search_body_search_options_append -->
<hr class="dashed" />
+ <!-- EVENT search_body_search_display_options_prepend -->
<dl>
<dt><label for="show_results1">{L_DISPLAY_RESULTS}{L_COLON}</label></dt>
<dd>
@@ -74,7 +82,9 @@
<dt><label>{L_RETURN_FIRST}{L_COLON}</label></dt>
<dd><select name="ch" title="{L_RETURN_FIRST}">{S_CHARACTER_OPTIONS}</select> {L_POST_CHARACTERS}</dd>
</dl>
+ <!-- EVENT search_body_search_display_options_append -->
</fieldset>
+ <!-- EVENT search_body_search_options_after -->
</div>
</div>
@@ -91,7 +101,9 @@
</div>
</form>
+<!-- EVENT search_body_form_after -->
+<!-- EVENT search_body_recent_search_before -->
<!-- IF .recentsearch -->
<div class="forumbg forumbg-table">
<div class="inner">
@@ -119,5 +131,6 @@
</div>
</div>
<!-- ENDIF -->
+<!-- EVENT search_body_recent_search_after -->
<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/styles/prosilver/template/search_results.html b/phpBB/styles/prosilver/template/search_results.html
index c63415915b..cd8ce66a74 100644
--- a/phpBB/styles/prosilver/template/search_results.html
+++ b/phpBB/styles/prosilver/template/search_results.html
@@ -84,7 +84,7 @@
<!-- EVENT topiclist_row_prepend -->
<!-- IF searchresults.S_UNREAD_TOPIC and not S_IS_BOT -->
- <a href="{searchresults.U_NEWEST_POST}">
+ <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>
</a>
<!-- ENDIF -->
@@ -209,24 +209,13 @@
<!-- END searchresults -->
<!-- ENDIF -->
-<!-- IF .pagination or .searchresults or S_SELECT_SORT_KEY or S_SELECT_SORT_DAYS -->
+<div class="action-bar bottom">
+ <!-- IF .searchresults and (S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY) -->
<form method="post" action="{S_SEARCH_ACTION}">
-
- <fieldset class="display-options">
- <!-- IF S_SELECT_SORT_DAYS or S_SELECT_SORT_KEY -->
- <label><!-- IF S_SHOW_TOPICS -->{L_DISPLAY_POSTS}<!-- ELSE -->{L_SORT_BY}</label><label><!-- ENDIF --> {S_SELECT_SORT_DAYS}<!-- IF S_SELECT_SORT_KEY --></label> <label>{S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}<!-- ENDIF --></label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
-
+ <!-- INCLUDE display_options.html -->
</form>
+ <!-- ENDIF -->
- <hr />
-<!-- ENDIF -->
-
-<!-- IF .pagination or .searchresults or PAGE_NUMBER -->
-<div class="action-bar bar-bottom">
<div class="pagination">
{SEARCH_MATCHES}
<!-- IF .pagination -->
@@ -236,7 +225,6 @@
<!-- ENDIF -->
</div>
</div>
-<!-- ENDIF -->
<!-- INCLUDE jumpbox.html -->
diff --git a/phpBB/styles/prosilver/template/ucp_attachments.html b/phpBB/styles/prosilver/template/ucp_attachments.html
index 0ea0661c37..9de08f17b9 100644
--- a/phpBB/styles/prosilver/template/ucp_attachments.html
+++ b/phpBB/styles/prosilver/template/ucp_attachments.html
@@ -10,7 +10,7 @@
<p>{L_ATTACHMENTS_EXPLAIN}</p>
<!-- IF .attachrow -->
- <div class="action-bar bar-top">
+ <div class="action-bar top">
<div class="pagination">
{NUM_ATTACHMENTS}
<!-- IF .pagination -->
@@ -50,16 +50,10 @@
<!-- END attachrow -->
</ul>
- <fieldset class="display-options">
- <label for="sk">{L_SORT_BY}{L_COLON} <select name="sk" id="sk">{S_SORT_OPTIONS}</select></label>
- <label><select name="sd" id="sd">{S_ORDER_SELECT}</select></label>
- <input class="button2" type="submit" name="sort" value="{L_SORT}" />
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
{S_FORM_TOKEN}
- </fieldset>
- <hr />
-
- <div class="action-bar bar-bottom">
<div class="pagination">
{TOTAL_ATTACHMENTS} {L_TITLE}
<!-- IF .pagination -->
diff --git a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
index 72d23e7da1..71e54c12eb 100644
--- a/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
+++ b/phpBB/styles/prosilver/template/ucp_main_bookmarks.html
@@ -39,7 +39,7 @@
<!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<!-- IF topicrow.S_UNREAD_TOPIC -->
- <a href="{topicrow.U_NEWEST_POST}">
+ <a class="unread" href="{topicrow.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>
</a>
<!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
diff --git a/phpBB/styles/prosilver/template/ucp_main_front.html b/phpBB/styles/prosilver/template/ucp_main_front.html
index 1351af914b..aaeb55729f 100644
--- a/phpBB/styles/prosilver/template/ucp_main_front.html
+++ b/phpBB/styles/prosilver/template/ucp_main_front.html
@@ -18,7 +18,7 @@
<!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<!-- IF topicrow.S_UNREAD -->
- <a href="{topicrow.U_NEWEST_POST}">
+ <a class="unread" href="{topicrow.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>
</a>
<!-- ENDIF -->
diff --git a/phpBB/styles/prosilver/template/ucp_main_subscribed.html b/phpBB/styles/prosilver/template/ucp_main_subscribed.html
index 3405a44f60..6cf23bdf31 100644
--- a/phpBB/styles/prosilver/template/ucp_main_subscribed.html
+++ b/phpBB/styles/prosilver/template/ucp_main_subscribed.html
@@ -82,7 +82,7 @@
<!-- IF topicrow.S_UNREAD_TOPIC --><a href="{topicrow.U_NEWEST_POST}" class="row-item-link"></a><!-- ENDIF -->
<div class="list-inner">
<!-- IF topicrow.S_UNREAD_TOPIC -->
- <a href="{topicrow.U_NEWEST_POST}">
+ <a class="unread" href="{topicrow.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>
</a>
<!-- ENDIF --><a href="{topicrow.U_VIEW_TOPIC}" class="topictitle">{topicrow.TOPIC_TITLE}</a>
diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
index 3914b33091..a3d58c8749 100644
--- a/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
+++ b/phpBB/styles/prosilver/template/ucp_pm_viewfolder.html
@@ -107,7 +107,10 @@
<hr />
- <div class="action-bar bar-bottom">
+ <div class="action-bar bottom">
+ <!-- INCLUDE display_options.html -->
+ <input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
+
<div class="pagination">
{TOTAL_MESSAGES}
<!-- IF .pagination -->
@@ -122,16 +125,6 @@
</div>
</div>
- <!-- IF FOLDER_CUR_MESSAGES neq 0 -->
- <fieldset class="display-options">
- <label>{L_DISPLAY}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <input type="hidden" name="cur_folder_id" value="{CUR_FOLDER_ID}" />
- </fieldset>
- <!-- ENDIF -->
-
<!-- INCLUDE ucp_pm_message_footer.html -->
<!-- ENDIF -->
<!-- INCLUDE ucp_footer.html -->
diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html
index f36e17369e..c17d99be74 100644
--- a/phpBB/styles/prosilver/template/viewforum_body.html
+++ b/phpBB/styles/prosilver/template/viewforum_body.html
@@ -159,7 +159,7 @@
<div class="list-inner">
<!-- EVENT topiclist_row_prepend -->
<!-- IF topicrow.S_UNREAD_TOPIC and not S_IS_BOT -->
- <a href="{topicrow.U_NEWEST_POST}">
+ <a class="unread" href="{topicrow.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>
</a>
<!-- ENDIF -->
@@ -189,6 +189,13 @@
<!-- IF topicrow.REPLIES --><span class="responsive-show left-box" style="display: none;">{L_REPLIES}{L_COLON} <strong>{topicrow.REPLIES}</strong></span><!-- ENDIF -->
<!-- ENDIF -->
+ <div class="responsive-hide">
+ <!-- IF topicrow.S_HAS_POLL --><i class="icon fa-bar-chart fa-fw" aria-hidden="true"></i><!-- ENDIF -->
+ <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i><!-- ENDIF -->
+ {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} &raquo; {topicrow.FIRST_POST_TIME}
+ <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --> &raquo; {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF -->
+ </div>
+
<!-- IF .topicrow.pagination -->
<div class="pagination">
<span><i class="icon fa-clone fa-fw" aria-hidden="true"></i></span>
@@ -205,13 +212,6 @@
</div>
<!-- ENDIF -->
- <div class="responsive-hide">
- <!-- IF topicrow.S_HAS_POLL --><i class="icon fa-bar-chart fa-fw" aria-hidden="true"></i><!-- ENDIF -->
- <!-- IF topicrow.ATTACH_ICON_IMG --><i class="icon fa-paperclip fa-fw" aria-hidden="true"></i><!-- ENDIF -->
- {L_POST_BY_AUTHOR} {topicrow.TOPIC_AUTHOR_FULL} &raquo; {topicrow.FIRST_POST_TIME}
- <!-- IF topicrow.S_POST_GLOBAL and FORUM_ID != topicrow.FORUM_ID --> &raquo; {L_IN} <a href="{topicrow.U_VIEW_FORUM}">{topicrow.FORUM_NAME}</a><!-- ENDIF -->
- </div>
-
<!-- EVENT topiclist_row_append -->
</div>
</dt>
@@ -248,20 +248,6 @@
<!-- ENDIF -->
<!-- END topicrow -->
-<!-- IF S_SELECT_SORT_DAYS and not S_DISPLAY_ACTIVE -->
- <form method="post" action="{S_FORUM_ACTION}">
- <fieldset class="display-options">
- <!-- IF not S_IS_BOT -->
- <label>{L_DISPLAY_TOPICS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label>
- <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
- </form>
- <hr />
-<!-- ENDIF -->
-
<!-- IF .topicrow and not S_DISPLAY_ACTIVE -->
<div class="action-bar bar-bottom">
<!-- IF not S_IS_BOT and S_DISPLAY_POST_INFO -->
@@ -278,6 +264,12 @@
<!-- EVENT viewforum_buttons_bottom_after -->
<!-- ENDIF -->
+ <!-- IF S_SELECT_SORT_DAYS and not S_IS_BOT -->
+ <form method="post" action="{S_FORUM_ACTION}">
+ <!-- INCLUDE display_options.html -->
+ </form>
+ <!-- ENDIF -->
+
<div class="pagination">
<!-- IF not S_IS_BOT and U_MARK_TOPICS and .topicrow --><a href="{U_MARK_TOPICS}" data-ajax="mark_topics_read">{L_MARK_TOPICS_READ}</a> &bull; <!-- ENDIF -->
{TOTAL_TOPICS}
diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html
index 0c64adc305..5067cac418 100644
--- a/phpBB/styles/prosilver/template/viewtopic_body.html
+++ b/phpBB/styles/prosilver/template/viewtopic_body.html
@@ -222,6 +222,7 @@
<!-- ENDIF -->
<div id="post_content{postrow.POST_ID}"<!-- IF postrow.S_POST_HIDDEN --> style="display: none;"<!-- ENDIF -->>
+ <!-- EVENT viewtopic_body_post_subject_before -->
<h3 <!-- IF postrow.S_FIRST_ROW -->class="first"<!-- ENDIF -->><!-- IF postrow.POST_ICON_IMG --><img src="{T_ICONS_PATH}{postrow.POST_ICON_IMG}" width="{postrow.POST_ICON_IMG_WIDTH}" height="{postrow.POST_ICON_IMG_HEIGHT}" alt="{postrow.POST_ICON_IMG_ALT}" title="{postrow.POST_ICON_IMG_ALT}" /> <!-- ENDIF --><a href="#p{postrow.POST_ID}">{postrow.POST_SUBJECT}</a></h3>
<!-- DEFINE $SHOW_POST_BUTTONS = (postrow.U_EDIT or postrow.U_DELETE or postrow.U_REPORT or postrow.U_WARN or postrow.U_INFO or postrow.U_QUOTE) -->
@@ -283,7 +284,7 @@
<!-- IF S_IS_BOT -->
<span><i class="icon fa-file fa-fw <!-- IF postrow.S_UNREAD_POST -->icon-red<!-- ELSE -->icon-lightgray<!-- ENDIF --> icon-md" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span></span>
<!-- ELSE -->
- <a href="{postrow.U_MINI_POST}" title="{postrow.MINI_POST}">
+ <a class="unread" href="{postrow.U_MINI_POST}" title="{postrow.MINI_POST}">
<i class="icon fa-file fa-fw <!-- IF postrow.S_UNREAD_POST -->icon-red<!-- ELSE -->icon-lightgray<!-- ENDIF --> icon-md" aria-hidden="true"></i><span class="sr-only">{postrow.MINI_POST}</span>
</a>
<!-- ENDIF -->
@@ -294,6 +295,7 @@
<!-- IF postrow.S_POST_UNAPPROVED -->
<form method="post" class="mcp_approve" action="{postrow.U_APPROVE_ACTION}">
<p class="post-notice unapproved">
+ <span><i class="icon fa-question icon-red fa-fw" aria-hidden="true"></i></span>
<strong>{L_POST_UNAPPROVED_ACTION}</strong>
<input class="button2" type="submit" value="{L_DISAPPROVE}" name="action[disapprove]" />
<input class="button1" type="submit" value="{L_APPROVE}" name="action[approve]" />
@@ -317,7 +319,7 @@
<!-- IF postrow.S_POST_REPORTED -->
<p class="post-notice reported">
- <a href="{postrow.U_MCP_REPORT}"><strong>{L_POST_REPORTED}</strong></a>
+ <a href="{postrow.U_MCP_REPORT}"><i class="icon fa-exclamation fa-fw icon-red" aria-hidden="true"></i><strong>{L_POST_REPORTED}</strong></a>
</p>
<!-- ENDIF -->
@@ -375,19 +377,6 @@
<!-- INCLUDE quickreply_editor.html -->
<!-- ENDIF -->
-<!-- IF S_NUM_POSTS > 1 or .pagination -->
- <form id="viewtopic" method="post" action="{S_TOPIC_ACTION}">
- <fieldset class="display-options" style="margin-top: 0; ">
- <!-- IF not S_IS_BOT -->
- <label>{L_DISPLAY_POSTS}{L_COLON} {S_SELECT_SORT_DAYS}</label>
- <label>{L_SORT_BY} {S_SELECT_SORT_KEY}</label> <label>{S_SELECT_SORT_DIR}</label>
- <input type="submit" name="sort" value="{L_GO}" class="button2" />
- <!-- ENDIF -->
- </fieldset>
- </form>
- <hr />
-<!-- ENDIF -->
-
<!-- EVENT viewtopic_body_topic_actions_before -->
<div class="action-bar bar-bottom">
<!-- EVENT viewtopic_buttons_bottom_before -->
@@ -405,6 +394,12 @@
<!-- INCLUDE viewtopic_topic_tools.html -->
+ <!-- IF (S_NUM_POSTS > 1 or .pagination) and not S_IS_BOT -->
+ <form method="post" action="{S_TOPIC_ACTION}">
+ <!-- INCLUDE display_options.html -->
+ </form>
+ <!-- ENDIF -->
+
<!-- IF .quickmod -->
<div class="quickmod dropdown-container dropdown-container-left dropdown-up dropdown-{S_CONTENT_FLOW_END} dropdown-button-control" id="quickmod">
<span title="{L_QUICK_MOD}" class="button button-secondary dropdown-trigger dropdown-select">
@@ -435,7 +430,6 @@
<!-- ENDIF -->
</div>
<!-- ENDIF -->
- <div class="clear"></div>
</div>
<!-- EVENT viewtopic_body_footer_before -->
diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css
index ca7982b456..a6d4bef6f4 100644
--- a/phpBB/styles/prosilver/theme/bidi.css
+++ b/phpBB/styles/prosilver/theme/bidi.css
@@ -454,7 +454,6 @@ li.breadcrumbs span:first-child > a {
.rtl p.post-notice {
padding-left: 5px;
- padding-right: 26px;
}
.rtl p.post-notice:before {
@@ -862,6 +861,10 @@ li.breadcrumbs span:first-child > a {
padding-right: 0;
}
+.rtl .dropdown fieldset.display-options label {
+ text-align: left;
+}
+
/* Display actions for ucp and mcp pages */
.rtl fieldset.display-actions {
text-align: left;
diff --git a/phpBB/styles/prosilver/theme/common.css b/phpBB/styles/prosilver/theme/common.css
index e5a147f034..ef6a07cebb 100644
--- a/phpBB/styles/prosilver/theme/common.css
+++ b/phpBB/styles/prosilver/theme/common.css
@@ -807,7 +807,6 @@ fieldset.fields1 dl.pmlist dd.recipients {
---------------------------------------- */
.pagination {
float: right;
- margin-top: 3px;
text-align: right;
width: auto;
}
@@ -876,7 +875,7 @@ fieldset.fields1 dl.pmlist dd.recipients {
/* Pagination in viewforum for multipage topics */
.row .pagination {
display: block;
- margin-top: 0;
+ margin-top: -12px;
}
.row .pagination > ul {
@@ -1005,23 +1004,10 @@ div.rules ul, div.rules ol {
p.post-notice {
position: relative;
padding: 5px;
- padding-left: 26px;
min-height: 14px;
margin-bottom: 1em;
}
-p.post-notice:before {
- content: '';
- display: block;
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- width: 28px;
- background: transparent none 50% 50% no-repeat;
- pointer-events: none;
-}
-
form > p.post-notice strong {
line-height: 20px;
}
diff --git a/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css
index 7eb501c21a..ef18e26ef1 100644
--- a/phpBB/styles/prosilver/theme/content.css
+++ b/phpBB/styles/prosilver/theme/content.css
@@ -149,6 +149,10 @@ dl.row-item dt, dl.row-item dd {
min-height: 35px;
}
+dl.row-item dt a {
+ display: inline;
+}
+
dl a.row-item-link { /* topic row icon links */
display: block;
width: 30px;
@@ -667,7 +671,7 @@ fieldset.polls dd div {
text-align: right;
font-family: Arial, Helvetica, sans-serif;
font-weight: bold;
- padding: 0 2px;
+ padding: 2px 2px 0 2px;
overflow: visible;
min-width: 8px;
}
diff --git a/phpBB/styles/prosilver/theme/forms.css b/phpBB/styles/prosilver/theme/forms.css
index 371a56fca5..e8efbc6045 100644
--- a/phpBB/styles/prosilver/theme/forms.css
+++ b/phpBB/styles/prosilver/theme/forms.css
@@ -183,6 +183,24 @@ fieldset.display-options a {
margin-top: 3px;
}
+.dropdown fieldset.display-options {
+ font-size: 1em;
+ margin: 0;
+ padding: 0;
+}
+
+.dropdown fieldset.display-options label {
+ display: block;
+ margin: 4px;
+ padding: 0;
+ text-align: right;
+ white-space: nowrap;
+}
+
+.dropdown fieldset.display-options select {
+ min-width: 120px;
+}
+
/* Display actions for ucp and mcp pages */
fieldset.display-actions {
text-align: right;
diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css
index 02a4ae73a0..a018bbc792 100644
--- a/phpBB/styles/prosilver/theme/links.css
+++ b/phpBB/styles/prosilver/theme/links.css
@@ -73,6 +73,7 @@ a.topictitle {
font-size: 1.2em;
font-weight: bold;
text-decoration: none;
+ display: inline;
}
a.topictitle:hover {
diff --git a/phpBB/styles/prosilver/theme/responsive.css b/phpBB/styles/prosilver/theme/responsive.css
index 826972fdac..d71fd142e6 100644
--- a/phpBB/styles/prosilver/theme/responsive.css
+++ b/phpBB/styles/prosilver/theme/responsive.css
@@ -280,6 +280,11 @@
margin: 5px 0 0;
}
+ .row .pagination {
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
+
.row .pagination .ellipsis + li {
display: none !important;
}
@@ -552,8 +557,34 @@
}
}
+@media (min-width: 700px) {
+ .postbody { width: 70%; }
+}
+
+@media (min-width: 850px) {
+ .postbody { width: 76%; }
+}
+
@media (max-width: 850px) {
.postprofile { width: 28%; }
- .postbody { width: 70%; }
+}
+
+@media (min-width: 701px) and (max-width: 950px) {
+ .row .pagination {
+ margin-top: 2px;
+ margin-bottom: 2px;
+ }
+
+ ul.topiclist dt {
+ margin-right: -410px;
+ }
+
+ ul.topiclist dt .list-inner {
+ margin-right: 410px;
+ }
+
+ dd.posts, dd.topics, dd.views {
+ width: 80px;
+ }
}
diff --git a/phpBB/viewforum.php b/phpBB/viewforum.php
index 3e9eb019bc..c9a081cc0e 100644
--- a/phpBB/viewforum.php
+++ b/phpBB/viewforum.php
@@ -267,7 +267,7 @@ gen_forum_auth_level('forum', $forum_id, $forum_data['forum_status']);
$limit_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']);
$sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']);
-$sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 't.topic_title', 'v' => 't.topic_views');
+$sort_by_sql = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 'LOWER(t.topic_title)', 'v' => 't.topic_views');
$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $default_sort_days, $default_sort_key, $default_sort_dir);
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 8be23def00..87de7c79a4 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -1824,6 +1824,9 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i)
($user->data['user_id'] == ANONYMOUS || $auth->acl_get('f_reply', $forum_id))
);
+ // Only display the quote button if the post is quotable. Posts not approved are not quotable.
+ $quote_allowed = ($quote_allowed && $row['post_visibility'] == ITEM_APPROVED) ? true : false;
+
$delete_allowed = $force_delete_allowed || ($user->data['is_registered'] && (
($auth->acl_get('m_delete', $forum_id) || ($auth->acl_get('m_softdelete', $forum_id) && $row['post_visibility'] != ITEM_DELETED)) ||
(!$s_cannot_delete && !$s_cannot_delete_lastpost && !$s_cannot_delete_time && !$s_cannot_delete_locked)
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index ace48ea035..86e1e5314b 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -16,6 +16,8 @@ define('PHPBB_ENVIRONMENT', 'test');
$phpbb_root_path = 'phpBB/';
$phpEx = 'php';
+
+global $table_prefix;
require_once $phpbb_root_path . 'includes/startup.php';
$table_prefix = 'phpbb_';
diff --git a/tests/datetime/from_format_test.php b/tests/datetime/from_format_test.php
index 32b88ff588..7ecb546768 100644
--- a/tests/datetime/from_format_test.php
+++ b/tests/datetime/from_format_test.php
@@ -113,10 +113,6 @@ class phpbb_datetime_from_format_test extends phpbb_test_case
{
global $phpbb_root_path, $phpEx;
- // This magically fixes the segmentation fault error on PHP7 tests
- // while date_default_timezone_set('UTC') does not
- date_default_timezone_set('Europe/Paris');
-
$lang_loader = new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx);
$lang = new \phpbb\language\language($lang_loader);
$user = new \phpbb\user($lang, '\phpbb\datetime');
diff --git a/tests/functional/search/base.php b/tests/functional/search/base.php
index 1d37d748df..a3cac381d2 100644
--- a/tests/functional/search/base.php
+++ b/tests/functional/search/base.php
@@ -36,6 +36,8 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->login();
$this->admin_login();
+ $this->create_search_index('\phpbb\search\fulltext_native');
+
$post = $this->create_topic(2, 'Test Topic 1 foosubject', 'This is a test topic posted by the barsearch testing framework.');
$crawler = self::request('GET', 'adm/index.php?i=acp_search&mode=settings&sid=' . $this->sid);
@@ -58,6 +60,7 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($post['topic_id']);
$this->markTestSkipped("Search backend is not supported/running");
}
+
$this->create_search_index();
}
@@ -72,14 +75,14 @@ abstract class phpbb_functional_search_base extends phpbb_functional_test_case
$this->delete_topic($post['topic_id']);
}
- protected function create_search_index()
+ protected function create_search_index($backend = null)
{
$this->add_lang('acp/search');
$crawler = self::request(
'POST',
'adm/index.php?i=acp_search&mode=index&sid=' . $this->sid,
array(
- 'search_type' => $this->search_backend,
+ 'search_type' => ( ($backend === null) ? $this->search_backend : $backend ),
'action' => 'create',
'submit' => true,
)
diff --git a/tests/functions_install/ignore_new_file_on_update_test.php b/tests/functions_install/ignore_new_file_on_update_test.php
deleted file mode 100644
index 822c5e6789..0000000000
--- a/tests/functions_install/ignore_new_file_on_update_test.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
-*
-* This file is part of the phpBB Forum Software package.
-*
-* @copyright (c) phpBB Limited <https://www.phpbb.com>
-* @license GNU General Public License, version 2 (GPL-2.0)
-*
-* For full copyright and license information, please see
-* the docs/CREDITS.txt file.
-*
-*/
-
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php';
-
-class phpbb_functions_install_ignore_new_file_on_update_test extends phpbb_test_case
-{
- static public function ignore_new_file_on_update_data()
- {
- return array(
- array('willneverexist.php', false),
- array('includes/dirwillneverexist/newfile.php', false),
-
- array('language/en/email/short/bookmark.txt', false),
- array('language/languagewillneverexist/email/short/bookmark.txt', true),
-
- array('styles/prosilver/template/bbcode.html', false),
- array('styles/stylewillneverexist/template/bbcode.html', true),
-
- array('styles/prosilver/theme/en/icon_user_online.gif', false),
- array('styles/prosilver/theme/languagewillneverexist/icon_user_online.gif', true),
-
- array('styles/prosilver/theme/imageset.css', false),
- );
- }
-
- /**
- * @dataProvider ignore_new_file_on_update_data
- */
- public function test_ignore_new_file_on_update($file, $expected)
- {
- global $phpbb_root_path;
- $this->assertEquals($expected, phpbb_ignore_new_file_on_update($phpbb_root_path, $file));
- }
-}
diff --git a/tests/mock/notification_type_post.php b/tests/mock/notification_type_post.php
index fd2d1b63cd..4116fecf5e 100644
--- a/tests/mock/notification_type_post.php
+++ b/tests/mock/notification_type_post.php
@@ -21,11 +21,12 @@ if (!defined('IN_PHPBB'))
class phpbb_mock_notification_type_post extends \phpbb\notification\type\post
{
- public function __construct($user_loader, $db, $cache, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table)
+ public function __construct($user_loader, $db, $cache, $language, $user, $auth, $config, $phpbb_root_path, $php_ext, $notification_types_table, $user_notifications_table)
{
$this->user_loader = $user_loader;
$this->db = $db;
$this->cache = $cache;
+ $this->language = $language;
$this->user = $user;
$this->auth = $auth;
$this->config = $config;
diff --git a/tests/notification/base.php b/tests/notification/base.php
index 1295f099f0..b64e25cf8c 100644
--- a/tests/notification/base.php
+++ b/tests/notification/base.php
@@ -90,6 +90,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case
$loader->load('services_notification.yml');
$phpbb_container->set('user_loader', $this->user_loader);
$phpbb_container->set('user', $user);
+ $phpbb_container->set('language', $lang);
$phpbb_container->set('config', $this->config);
$phpbb_container->set('dbal.conn', $this->db);
$phpbb_container->set('auth', $auth);
@@ -111,6 +112,7 @@ abstract class phpbb_tests_notification_base extends phpbb_database_test_case
$this->phpbb_dispatcher,
$this->db,
$this->cache,
+ $lang,
$this->user,
'phpbb_notification_types',
'phpbb_user_notifications'
diff --git a/tests/notification/fixtures/services_notification.yml b/tests/notification/fixtures/services_notification.yml
index e0a404b12b..6e68cccff6 100644
--- a/tests/notification/fixtures/services_notification.yml
+++ b/tests/notification/fixtures/services_notification.yml
@@ -17,6 +17,9 @@ services:
dbal.conn:
synthetic: true
+ language:
+ synthetic: true
+
auth:
synthetic: true
diff --git a/tests/notification/submit_post_base.php b/tests/notification/submit_post_base.php
index 72b25abf0a..14ca4499d2 100644
--- a/tests/notification/submit_post_base.php
+++ b/tests/notification/submit_post_base.php
@@ -54,7 +54,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
{
parent::setUp();
- global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path, $user_loader;
+ global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $lang, $user, $request, $phpEx, $phpbb_root_path, $user_loader;
// Database
$this->db = $this->new_dbal();
@@ -91,9 +91,12 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
// Event dispatcher
$phpbb_dispatcher = new phpbb_mock_event_dispatcher();
+ // Language
+ $lang = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx));
+
// User
$user = $this->getMock('\phpbb\user', array(), array(
- new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)),
+ $lang,
'\phpbb\datetime'
));
$user->ip = '';
@@ -117,6 +120,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
$loader->load('services_notification.yml');
$phpbb_container->set('user_loader', $user_loader);
$phpbb_container->set('user', $user);
+ $phpbb_container->set('language', $lang);
$phpbb_container->set('config', $config);
$phpbb_container->set('dbal.conn', $db);
$phpbb_container->set('auth', $auth);
@@ -146,7 +150,7 @@ abstract class phpbb_notification_submit_post_base extends phpbb_database_test_c
// Notification Manager
$phpbb_notifications = new \phpbb\notification\manager($notification_types_array, $notification_methods_array,
- $phpbb_container, $user_loader, $phpbb_dispatcher, $db, $cache, $user,
+ $phpbb_container, $user_loader, $phpbb_dispatcher, $db, $cache, $lang, $user,
NOTIFICATION_TYPES_TABLE, USER_NOTIFICATIONS_TABLE);
$phpbb_container->set('notification_manager', $phpbb_notifications);
}
diff --git a/tests/notification/user_list_trim_test.php b/tests/notification/user_list_trim_test.php
index d57fbf0485..9f6eb492f6 100644
--- a/tests/notification/user_list_trim_test.php
+++ b/tests/notification/user_list_trim_test.php
@@ -55,13 +55,13 @@ class phpbb_notification_user_list_trim_test extends phpbb_database_test_case
$lang = new \phpbb\language\language($lang_loader);
$user = new \phpbb\user($lang, '\phpbb\datetime');
$user->data = array('user_lang' => 'en');
- $user->add_lang('common');
+ $lang->add_lang('common');
$user_loader = new phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
$user_loader->load_users(array(2, 3, 4, 5, 6));
$this->notification = new phpbb_mock_notification_type_post(
- $user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null
+ $user_loader, null, null, $lang, $user, null, null, $phpbb_root_path, $phpEx, null, null
);
}
diff --git a/tests/test_framework/mock/phpbb_mock_null_installer_task.php b/tests/test_framework/mock/phpbb_mock_null_installer_task.php
new file mode 100644
index 0000000000..c1b880d967
--- /dev/null
+++ b/tests/test_framework/mock/phpbb_mock_null_installer_task.php
@@ -0,0 +1,30 @@
+<?php
+/**
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+class phpbb_mock_null_installer_task extends \phpbb\install\task_base
+{
+ public function run()
+ {
+
+ }
+
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php
index 5136af5ad1..fa50d89a70 100644
--- a/tests/test_framework/phpbb_database_test_connection_manager.php
+++ b/tests/test_framework/phpbb_database_test_connection_manager.php
@@ -11,7 +11,6 @@
*
*/
-require_once dirname(__FILE__) . '/../../phpBB/includes/functions_install.php';
require_once dirname(__FILE__) . '/phpbb_database_connection_odbc_pdo_wrapper.php';
class phpbb_database_test_connection_manager
@@ -344,10 +343,13 @@ class phpbb_database_test_connection_manager
if (file_exists($filename))
{
+ global $phpbb_root_path;
+
$queries = file_get_contents($filename);
- $sql = phpbb_remove_comments($queries);
- $sql = split_sql_file($sql, $this->dbms['DELIM']);
+ $db_helper = new \phpbb\install\helper\database(new \phpbb\filesystem\filesystem(), $phpbb_root_path);
+ $sql = $db_helper->remove_comments($queries);
+ $sql = $db_helper->split_sql_file($sql, $this->dbms['DELIM']);
foreach ($sql as $query)
{
diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php
index bef1208609..323d97ff42 100644
--- a/tests/test_framework/phpbb_functional_test_case.php
+++ b/tests/test_framework/phpbb_functional_test_case.php
@@ -12,7 +12,7 @@
*/
use Symfony\Component\BrowserKit\CookieJar;
-require_once __DIR__ . '/../../phpBB/includes/functions_install.php';
+require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';
class phpbb_functional_test_case extends phpbb_test_case
{
@@ -285,120 +285,98 @@ class phpbb_functional_test_case extends phpbb_test_case
}
}
- self::$cookieJar = new CookieJar;
- self::$client = new Goutte\Client(array(), null, self::$cookieJar);
- // Set client manually so we can increase the cURL timeout
- self::$client->setClient(new Guzzle\Http\Client('', array(
- Guzzle\Http\Client::DISABLE_REDIRECTS => true,
- 'curl.options' => array(
- CURLOPT_TIMEOUT => 120,
- ),
- )));
-
- // Reset the curl handle because it is 0 at this point and not a valid
- // resource
- self::$client->getClient()->getCurlMulti()->reset(true);
+ $container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $container = $container_builder
+ ->with_environment('installer')
+ ->without_extensions()
+ ->without_cache()
+ ->with_custom_parameters([
+ 'core.disable_super_globals' => false,
+ 'installer.create_config_file.options' => [
+ 'debug' => true,
+ 'environment' => 'test',
+ ],
+ 'cache.driver.class' => 'phpbb\cache\driver\file'
+ ])
+ ->without_compiled_container()
+ ->get_container();
+
+ $container->register('installer.install_finish.notify_user')->setSynthetic(true);
+ $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task());
+ $container->compile();
+
+ $language = $container->get('language');
+ $language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+ $iohandler_factory = $container->get('installer.helper.iohandler_factory');
+ $iohandler_factory->set_environment('cli');
+ $iohandler = $iohandler_factory->get();
$parseURL = parse_url(self::$config['phpbb_functional_url']);
- $crawler = self::request('GET', 'install/index.php?mode=install&language=en');
- self::assertContains('Welcome to Installation', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // install/index.php?mode=install&sub=requirements
- $crawler = self::submit($form);
- self::assertContains('Installation compatibility', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // install/index.php?mode=install&sub=database
- $crawler = self::submit($form);
- self::assertContains('Database configuration', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- // Installer uses 3.0-style dbms name
- 'dbms' => str_replace('phpbb\db\driver\\', '', self::$config['dbms']),
- 'dbhost' => self::$config['dbhost'],
- 'dbport' => self::$config['dbport'],
- 'dbname' => self::$config['dbname'],
- 'dbuser' => self::$config['dbuser'],
- 'dbpasswd' => self::$config['dbpasswd'],
- 'table_prefix' => self::$config['table_prefix'],
- ));
-
- // install/index.php?mode=install&sub=database
- $crawler = self::submit($form);
- self::assertContains('Successful connection', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // install/index.php?mode=install&sub=administrator
- $crawler = self::submit($form);
- self::assertContains('Administrator configuration', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- 'default_lang' => 'en',
- 'admin_name' => 'admin',
- 'admin_pass1' => 'adminadmin',
- 'admin_pass2' => 'adminadmin',
- 'board_email' => 'nobody@example.com',
- ));
-
- // install/index.php?mode=install&sub=administrator
- $crawler = self::submit($form);
- self::assertContains('Tests passed', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
-
- // We have to skip install/index.php?mode=install&sub=config_file
- // because that step will create a config.php file if phpBB has the
- // permission to do so. We have to create the config file on our own
- // in order to get the DEBUG constants defined.
- $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true);
- $config_created = file_put_contents($config_file, $config_php_data) !== false;
- if (!$config_created)
+ $output = new \Symfony\Component\Console\Output\NullOutput();
+ $style = new \Symfony\Component\Console\Style\SymfonyStyle(
+ new \Symfony\Component\Console\Input\ArrayInput(array()),
+ $output
+ );
+ $iohandler->set_style($style, $output);
+
+ $installer = $container->get('installer.installer.install');
+ $installer->set_iohandler($iohandler);
+
+ // Set data
+ $iohandler->set_input('admin_name', 'admin');
+ $iohandler->set_input('admin_pass1', 'adminadmin');
+ $iohandler->set_input('admin_pass2', 'adminadmin');
+ $iohandler->set_input('board_email', 'nobody@example.com');
+ $iohandler->set_input('submit_admin', 'submit');
+
+ $iohandler->set_input('default_lang', 'en');
+ $iohandler->set_input('board_name', 'yourdomain.com');
+ $iohandler->set_input('board_description', 'A short text to describe your forum');
+ $iohandler->set_input('submit_board', 'submit');
+
+ $iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
+ $iohandler->set_input('dbhost', self::$config['dbhost']);
+ $iohandler->set_input('dbport', self::$config['dbport']);
+ $iohandler->set_input('dbuser', self::$config['dbuser']);
+ $iohandler->set_input('dbpasswd', self::$config['dbpasswd']);
+ $iohandler->set_input('dbname', self::$config['dbname']);
+ $iohandler->set_input('table_prefix', self::$config['table_prefix']);
+ $iohandler->set_input('submit_database', 'submit');
+
+ $iohandler->set_input('email_enable', true);
+ $iohandler->set_input('smtp_delivery', '1');
+ $iohandler->set_input('smtp_host', 'nxdomain.phpbb.com');
+ $iohandler->set_input('smtp_auth', 'PLAIN');
+ $iohandler->set_input('smtp_user', 'nxuser');
+ $iohandler->set_input('smtp_pass', 'nxpass');
+ $iohandler->set_input('submit_email', 'submit');
+
+ $iohandler->set_input('cookie_secure', '0');
+ $iohandler->set_input('server_protocol', '0');
+ $iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://');
+ $iohandler->set_input('server_name', $parseURL['host']);
+ $iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80);
+ $iohandler->set_input('script_path', $parseURL['path']);
+ $iohandler->set_input('submit_server', 'submit');
+
+ do
{
- self::markTestSkipped("Could not write $config_file file.");
+ $installer->run();
}
+ while (file_exists($phpbb_root_path . 'store/install_config.php'));
+
+ copy($config_file, $config_file_test);
- // We also have to create a install lock that is normally created by
- // the installer. The file will be removed by the final step of the
- // installer.
- $install_lock_file = $phpbb_root_path . 'cache/install_lock';
- $lock_created = file_put_contents($install_lock_file, '') !== false;
- if (!$lock_created)
+ if (file_exists($phpbb_root_path . 'cache/install_lock'))
{
- self::markTestSkipped("Could not create $lock_created file.");
+ unlink($phpbb_root_path . 'cache/install_lock');
}
- @chmod($install_lock_file, 0666);
-
- // install/index.php?mode=install&sub=advanced
- $form_data = $form->getValues();
- unset($form_data['submit']);
-
- $crawler = self::request('POST', 'install/index.php?mode=install&sub=advanced', $form_data);
- self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form(array(
- 'email_enable' => true,
- 'smtp_delivery' => true,
- 'smtp_host' => 'nxdomain.phpbb.com',
- 'smtp_auth' => 'PLAIN',
- 'smtp_user' => 'nxuser',
- 'smtp_pass' => 'nxpass',
- 'cookie_secure' => false,
- 'force_server_vars' => false,
- 'server_protocol' => $parseURL['scheme'] . '://',
- 'server_name' => 'localhost',
- 'server_port' => isset($parseURL['port']) ? (int) $parseURL['port'] : 80,
- 'script_path' => $parseURL['path'],
- ));
-
- // install/index.php?mode=install&sub=create_table
- $crawler = self::submit($form);
- self::assertContains('The database tables used by phpBB', $crawler->filter('#main')->text());
- self::assertContains('have been created and populated with some initial data.', $crawler->filter('#main')->text());
- $form = $crawler->selectButton('submit')->form();
- // install/index.php?mode=install&sub=final
- $crawler = self::submit($form);
- self::assertContains('You have successfully installed', $crawler->text());
-
- copy($config_file, $config_file_test);
+ global $phpbb_container, $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log, $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;
+ $phpbb_container->reset();
+ unset($phpbb_container, $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log, $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template);
}
public function install_ext($extension)
diff --git a/tests/test_framework/phpbb_ui_test_case.php b/tests/test_framework/phpbb_ui_test_case.php
index c8ac492e25..e118801972 100644
--- a/tests/test_framework/phpbb_ui_test_case.php
+++ b/tests/test_framework/phpbb_ui_test_case.php
@@ -11,7 +11,7 @@
*
*/
-require_once __DIR__ . '/../../phpBB/includes/functions_install.php';
+require_once __DIR__ . '/mock/phpbb_mock_null_installer_task.php';
class phpbb_ui_test_case extends phpbb_test_case
{
@@ -118,87 +118,97 @@ class phpbb_ui_test_case extends phpbb_test_case
}
}
+ $container_builder = new \phpbb\di\container_builder($phpbb_root_path, $phpEx);
+ $container = $container_builder
+ ->with_environment('installer')
+ ->without_extensions()
+ ->without_cache()
+ ->with_custom_parameters([
+ 'core.disable_super_globals' => false,
+ 'installer.create_config_file.options' => [
+ 'debug' => true,
+ 'environment' => 'test',
+ ],
+ 'cache.driver.class' => 'phpbb\cache\driver\file'
+ ])
+ ->without_compiled_container()
+ ->get_container();
+
+ $container->register('installer.install_finish.notify_user')->setSynthetic(true);
+ $container->set('installer.install_finish.notify_user', new phpbb_mock_null_installer_task());
+ $container->compile();
+
+ $language = $container->get('language');
+ $language->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
+
+ $iohandler_factory = $container->get('installer.helper.iohandler_factory');
+ $iohandler_factory->set_environment('cli');
+ $iohandler = $iohandler_factory->get();
+
$parseURL = parse_url(self::$config['phpbb_functional_url']);
- self::visit('install/index.php?mode=install&language=en');
- self::assertContains('Welcome to Installation', self::find_element('id', 'main')->getText());
-
- // install/index.php?mode=install&sub=requirements
- self::submit();
- self::assertContains('Installation compatibility', self::find_element('id', 'main')->getText());
-
- // install/index.php?mode=install&sub=database
- self::submit();
- self::assertContains('Database configuration', self::find_element('id', 'main')->getText());
-
- self::find_element('id','dbms')->sendKeys(str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
- self::find_element('id','dbhost')->sendKeys(self::$config['dbhost']);
- self::find_element('id','dbport')->sendKeys(self::$config['dbport']);
- self::find_element('id','dbname')->sendKeys(self::$config['dbname']);
- self::find_element('id','dbuser')->sendKeys(self::$config['dbuser']);
- self::find_element('id','dbpasswd')->sendKeys(self::$config['dbpasswd']);
-
- // Need to clear default phpbb_ prefix
- self::find_element('id','table_prefix')->clear();
- self::find_element('id','table_prefix')->sendKeys(self::$config['table_prefix']);
-
- // install/index.php?mode=install&sub=database
- self::submit();
- self::assertContains('Successful connection', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=administrator
- self::submit();
- self::assertContains('Administrator configuration', self::find_element('id','main')->getText());
-
- self::find_element('id','admin_name')->sendKeys('admin');
- self::find_element('id','admin_pass1')->sendKeys('adminadmin');
- self::find_element('id','admin_pass2')->sendKeys('adminadmin');
- self::find_element('id','board_email')->sendKeys('nobody@example.com');
-
- // install/index.php?mode=install&sub=administrator
- self::submit();
- self::assertContains('Tests passed', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=config_file
- self::submit();
-
- // Installer has created a config.php file, we will overwrite it with a
- // config file of our own in order to get the DEBUG constants defined
- $config_php_data = phpbb_create_config_file_data(self::$config, self::$config['dbms'], true, false, true);
- $config_created = file_put_contents($config_file, $config_php_data) !== false;
- if (!$config_created)
+ $output = new \Symfony\Component\Console\Output\NullOutput();
+ $style = new \Symfony\Component\Console\Style\SymfonyStyle(
+ new \Symfony\Component\Console\Input\ArrayInput(array()),
+ $output
+ );
+ $iohandler->set_style($style, $output);
+
+ $installer = $container->get('installer.installer.install');
+ $installer->set_iohandler($iohandler);
+
+ // Set data
+ $iohandler->set_input('admin_name', 'admin');
+ $iohandler->set_input('admin_pass1', 'adminadmin');
+ $iohandler->set_input('admin_pass2', 'adminadmin');
+ $iohandler->set_input('board_email', 'nobody@example.com');
+ $iohandler->set_input('submit_admin', 'submit');
+
+ $iohandler->set_input('default_lang', 'en');
+ $iohandler->set_input('board_name', 'yourdomain.com');
+ $iohandler->set_input('board_description', 'A short text to describe your forum');
+ $iohandler->set_input('submit_board', 'submit');
+
+ $iohandler->set_input('dbms', str_replace('phpbb\db\driver\\', '', self::$config['dbms']));
+ $iohandler->set_input('dbhost', self::$config['dbhost']);
+ $iohandler->set_input('dbport', self::$config['dbport']);
+ $iohandler->set_input('dbuser', self::$config['dbuser']);
+ $iohandler->set_input('dbpasswd', self::$config['dbpasswd']);
+ $iohandler->set_input('dbname', self::$config['dbname']);
+ $iohandler->set_input('table_prefix', self::$config['table_prefix']);
+ $iohandler->set_input('submit_database', 'submit');
+
+ $iohandler->set_input('email_enable', true);
+ $iohandler->set_input('smtp_delivery', '1');
+ $iohandler->set_input('smtp_host', 'nxdomain.phpbb.com');
+ $iohandler->set_input('smtp_auth', 'PLAIN');
+ $iohandler->set_input('smtp_user', 'nxuser');
+ $iohandler->set_input('smtp_pass', 'nxpass');
+ $iohandler->set_input('submit_email', 'submit');
+
+ $iohandler->set_input('cookie_secure', '0');
+ $iohandler->set_input('server_protocol', '0');
+ $iohandler->set_input('force_server_vars', $parseURL['scheme'] . '://');
+ $iohandler->set_input('server_name', $parseURL['host']);
+ $iohandler->set_input('server_port', isset($parseURL['port']) ? (int) $parseURL['port'] : 80);
+ $iohandler->set_input('script_path', $parseURL['path']);
+ $iohandler->set_input('submit_server', 'submit');
+
+ do
{
- self::markTestSkipped("Could not write $config_file file.");
+ $installer->run();
}
+ while (file_exists($phpbb_root_path . 'store/install_config.php'));
+
+ copy($config_file, $config_file_test);
- if (strpos(self::find_element('id','main')->getText(), 'The configuration file has been written') === false)
+ if (file_exists($phpbb_root_path . 'cache/install_lock'))
{
- self::submit('id', 'dldone');
+ unlink($phpbb_root_path . 'cache/install_lock');
}
- self::assertContains('The configuration file has been written', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=advanced
- self::submit();
- self::assertContains('The settings on this page are only necessary to set if you know that you require something different from the default.', self::find_element('id','main')->getText());
-
- self::find_element('id','smtp_delivery')->sendKeys('1');
- self::find_element('id','smtp_host')->sendKeys('nxdomain.phpbb.com');
- self::find_element('id','smtp_user')->sendKeys('nxuser');
- self::find_element('id','smtp_pass')->sendKeys('nxpass');
- self::find_element('id','server_protocol')->sendKeys($parseURL['scheme'] . '://');
- self::find_element('id','server_name')->sendKeys('localhost');
- self::find_element('id','server_port')->sendKeys(isset($parseURL['port']) ? $parseURL['port'] : 80);
- self::find_element('id','script_path')->sendKeys($parseURL['path']);
-
- // install/index.php?mode=install&sub=create_table
- self::submit();
- self::assertContains('The database tables used by phpBB', self::find_element('id','main')->getText());
- self::assertContains('have been created and populated with some initial data.', self::find_element('id','main')->getText());
-
- // install/index.php?mode=install&sub=final
- self::submit();
- self::assertContains('You have successfully installed', self::find_element('id', 'main')->getText());
- copy($config_file, $config_file_test);
+ global $phpbb_container, $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log, $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;
+ $phpbb_container->reset();
+ unset($phpbb_container, $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log, $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template);
}
}
diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.html b/tests/text_processing/tickets_data/PHPBB3-13451.html
new file mode 100644
index 0000000000..e0892c18a9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13451.html
@@ -0,0 +1 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-13451.txt b/tests/text_processing/tickets_data/PHPBB3-13451.txt
new file mode 100644
index 0000000000..e0892c18a9
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-13451.txt
@@ -0,0 +1 @@
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@example.org \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.html b/tests/text_processing/tickets_data/PHPBB3-9791.html
new file mode 100644
index 0000000000..cabed5b12f
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9791.html
@@ -0,0 +1 @@
+<a href="http://www.phpbb.com/community/search.php?keywords=bogus&amp;terms=all&amp;author=&amp;fid%5B%5D=46&amp;sc=1&amp;sf=all&amp;sr=posts&amp;sk=t&amp;sd=d&amp;st=0&amp;ch=300&amp;t=0&amp;submit=Search" class="postlink">http://www.phpbb.com/community/search.php?keywords=bogus&amp;terms=all&amp;author=&amp;fid[]=46&amp;sc=1&amp;sf=all&amp;sr=posts&amp;sk=t&amp;sd=d&amp;st=0&amp;ch=300&amp;t=0&amp;submit=Search</a> \ No newline at end of file
diff --git a/tests/text_processing/tickets_data/PHPBB3-9791.txt b/tests/text_processing/tickets_data/PHPBB3-9791.txt
new file mode 100644
index 0000000000..e29b20086d
--- /dev/null
+++ b/tests/text_processing/tickets_data/PHPBB3-9791.txt
@@ -0,0 +1 @@
+http://www.phpbb.com/community/search.php?keywords=bogus&terms=all&author=&fid[]=46&sc=1&sf=all&sr=posts&sk=t&sd=d&st=0&ch=300&t=0&submit=Search \ No newline at end of file
diff --git a/tests/text_reparser/plugins/forum_description_test.php b/tests/text_reparser/plugins/forum_description_test.php
index 3b739353cd..57166e6a3c 100644
--- a/tests/text_reparser/plugins/forum_description_test.php
+++ b/tests/text_reparser/plugins/forum_description_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_forum_description_test extends phpbb_textreparser_test_
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\forum_description($this->db);
+ return new \phpbb\textreparser\plugins\forum_description($this->db, FORUMS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/forum_rules_test.php b/tests/text_reparser/plugins/forum_rules_test.php
index 4c267c9014..72e4e98876 100644
--- a/tests/text_reparser/plugins/forum_rules_test.php
+++ b/tests/text_reparser/plugins/forum_rules_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_forum_rules_test extends phpbb_textreparser_test_row_ba
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\forum_rules($this->db);
+ return new \phpbb\textreparser\plugins\forum_rules($this->db, FORUMS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/group_description_test.php b/tests/text_reparser/plugins/group_description_test.php
index 51035903e1..babfc7e02f 100644
--- a/tests/text_reparser/plugins/group_description_test.php
+++ b/tests/text_reparser/plugins/group_description_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_group_description_test extends phpbb_textreparser_test_
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\group_description($this->db);
+ return new \phpbb\textreparser\plugins\group_description($this->db, GROUPS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/pm_text_test.php b/tests/text_reparser/plugins/pm_text_test.php
index 3896a57e98..6dc1a9cb4c 100644
--- a/tests/text_reparser/plugins/pm_text_test.php
+++ b/tests/text_reparser/plugins/pm_text_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_pm_text_test extends phpbb_textreparser_test_row_based_
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\pm_text($this->db);
+ return new \phpbb\textreparser\plugins\pm_text($this->db, PRIVMSGS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/poll_title_test.php b/tests/text_reparser/plugins/poll_title_test.php
index 76ca2ee228..046b6019c8 100644
--- a/tests/text_reparser/plugins/poll_title_test.php
+++ b/tests/text_reparser/plugins/poll_title_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_poll_title_test extends phpbb_textreparser_test_row_bas
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\poll_title($this->db);
+ return new \phpbb\textreparser\plugins\poll_title($this->db, TOPICS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/post_text_test.php b/tests/text_reparser/plugins/post_text_test.php
index 0f934a06ee..8ea71e65f5 100644
--- a/tests/text_reparser/plugins/post_text_test.php
+++ b/tests/text_reparser/plugins/post_text_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_post_text_test extends phpbb_textreparser_test_row_base
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\post_text($this->db);
+ return new \phpbb\textreparser\plugins\post_text($this->db, POSTS_TABLE);
}
}
diff --git a/tests/text_reparser/plugins/test_row_based_plugin.php b/tests/text_reparser/plugins/test_row_based_plugin.php
index bbae44c8e0..e8218dfdd6 100644
--- a/tests/text_reparser/plugins/test_row_based_plugin.php
+++ b/tests/text_reparser/plugins/test_row_based_plugin.php
@@ -24,8 +24,13 @@ abstract class phpbb_textreparser_test_row_based_plugin extends phpbb_database_t
{
$reparser = $this->get_reparser();
$columns = $reparser->get_columns();
+
+ $reflection_reparser = new ReflectionClass(get_class($reparser));
+ $table_property = $reflection_reparser->getProperty('table');
+ $table_property->setAccessible(true);
+
$sql = 'SELECT ' . $columns['id'] . ' AS id, ' . $columns['text'] . ' AS text
- FROM ' . $reparser->get_table_name() . '
+ FROM ' . $table_property->getValue($reparser) . '
WHERE ' . $this->db->sql_in_set($columns['id'], $ids) . '
ORDER BY id';
$result = $this->db->sql_query($sql);
diff --git a/tests/text_reparser/plugins/user_signature_test.php b/tests/text_reparser/plugins/user_signature_test.php
index ab830a303d..5b66f2788a 100644
--- a/tests/text_reparser/plugins/user_signature_test.php
+++ b/tests/text_reparser/plugins/user_signature_test.php
@@ -21,6 +21,6 @@ class phpbb_textreparser_user_signature_test extends phpbb_textreparser_test_row
protected function get_reparser()
{
- return new \phpbb\textreparser\plugins\user_signature($this->db);
+ return new \phpbb\textreparser\plugins\user_signature($this->db, USERS_TABLE);
}
}
diff --git a/travis/check-executable-files.sh b/travis/check-executable-files.sh
index 4ec037e6ce..1aa8dca073 100755
--- a/travis/check-executable-files.sh
+++ b/travis/check-executable-files.sh
@@ -28,7 +28,7 @@ then
files_skipped="-false"
# Files which have to be executable
- executable_files="-path ${path}bin/*"
+ executable_files="-path ${path}bin/* -o -path ${path}install/phpbbcli.php"
incorrect_files=$( \
find ${path} \