aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--build/build.xml20
-rw-r--r--phpBB/adm/style/acp_avatar_options_local.html1
-rw-r--r--phpBB/adm/style/acp_contact.html76
-rw-r--r--phpBB/adm/style/acp_posting_buttons.html70
-rw-r--r--phpBB/adm/style/acp_users_signature.html64
-rw-r--r--phpBB/assets/javascript/core.js6
-rw-r--r--phpBB/assets/plupload/plupload.full.min.js2
-rwxr-xr-xphpBB/bin/phpbbcli.php5
-rw-r--r--phpBB/config/auth_providers.yml3
-rw-r--r--phpBB/config/console.yml15
-rw-r--r--phpBB/config/passwords.yml66
-rw-r--r--phpBB/config/services.yml32
-rw-r--r--phpBB/develop/create_schema_files.php12
-rw-r--r--phpBB/develop/migration_tips.php46
-rw-r--r--phpBB/docs/events.md28
-rw-r--r--phpBB/includes/acp/acp_contact.php129
-rw-r--r--phpBB/includes/acp/acp_email.php2
-rw-r--r--phpBB/includes/acp/acp_groups.php107
-rw-r--r--phpBB/includes/acp/acp_modules.php4
-rw-r--r--phpBB/includes/acp/acp_php_info.php2
-rw-r--r--phpBB/includes/acp/acp_users.php3
-rw-r--r--phpBB/includes/acp/info/acp_contact.php26
-rw-r--r--phpBB/includes/captcha/plugins/captcha_abstract.php3
-rw-r--r--phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php5
-rw-r--r--phpBB/includes/constants.php1
-rw-r--r--phpBB/includes/functions.php148
-rw-r--r--phpBB/includes/functions_acp.php31
-rw-r--r--phpBB/includes/functions_content.php2
-rw-r--r--phpBB/includes/functions_display.php56
-rw-r--r--phpBB/includes/functions_upload.php10
-rw-r--r--phpBB/includes/functions_user.php46
-rw-r--r--phpBB/includes/mcp/mcp_forum.php20
-rw-r--r--phpBB/includes/mcp/mcp_queue.php2
-rw-r--r--phpBB/includes/mcp/mcp_topic.php22
-rw-r--r--phpBB/includes/ucp/ucp_activate.php1
-rw-r--r--phpBB/includes/ucp/ucp_profile.php2
-rw-r--r--phpBB/includes/ucp/ucp_register.php2
-rw-r--r--phpBB/install/install_main.php2
-rw-r--r--phpBB/install/schemas/schema.json4
-rw-r--r--phpBB/install/schemas/schema_data.sql7
-rw-r--r--phpBB/language/en/acp/board.php19
-rw-r--r--phpBB/language/en/acp/common.php8
-rw-r--r--phpBB/language/en/common.php7
-rw-r--r--phpBB/language/en/email/contact_admin.txt23
-rw-r--r--phpBB/language/en/memberlist.php8
-rw-r--r--phpBB/memberlist.php274
-rw-r--r--phpBB/phpbb/auth/provider/db.php71
-rw-r--r--phpBB/phpbb/auth/provider/oauth/oauth.php2
-rw-r--r--phpBB/phpbb/auth/provider_collection.php65
-rw-r--r--phpBB/phpbb/avatar/driver/gravatar.php3
-rw-r--r--phpBB/phpbb/avatar/driver/local.php6
-rw-r--r--phpBB/phpbb/config/config.php2
-rw-r--r--phpBB/phpbb/console/application.php80
-rw-r--r--phpBB/phpbb/console/command/cache/purge.php1
-rw-r--r--phpBB/phpbb/console/command/cron/cron_list.php90
-rw-r--r--phpBB/phpbb/console/command/db/migrate.php2
-rw-r--r--phpBB/phpbb/console/command/dev/migration_tips.php64
-rw-r--r--phpBB/phpbb/controller/provider.php4
-rw-r--r--phpBB/phpbb/cron/manager.php10
-rw-r--r--phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php27
-rw-r--r--phpBB/phpbb/db/migration/data/v310/contact_admin_form.php37
-rw-r--r--phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php85
-rw-r--r--phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php49
-rw-r--r--phpBB/phpbb/db/migrator.php4
-rw-r--r--phpBB/phpbb/di/service_collection.php47
-rw-r--r--phpBB/phpbb/di/service_collection_iterator.php87
-rw-r--r--phpBB/phpbb/extension/base.php6
-rw-r--r--phpBB/phpbb/extension/manager.php18
-rw-r--r--phpBB/phpbb/finder.php (renamed from phpBB/phpbb/extension/finder.php)94
-rw-r--r--phpBB/phpbb/message/admin_form.php189
-rw-r--r--phpBB/phpbb/message/form.php173
-rw-r--r--phpBB/phpbb/message/message.php280
-rw-r--r--phpBB/phpbb/message/topic_form.php156
-rw-r--r--phpBB/phpbb/message/user_form.php134
-rw-r--r--phpBB/phpbb/notification/manager.php52
-rw-r--r--phpBB/phpbb/passwords/driver/base.php16
-rw-r--r--phpBB/phpbb/passwords/driver/bcrypt.php2
-rw-r--r--phpBB/phpbb/passwords/driver/bcrypt_wcf2.php84
-rw-r--r--phpBB/phpbb/passwords/driver/convert_password.php43
-rw-r--r--phpBB/phpbb/passwords/driver/driver_interface.php10
-rw-r--r--phpBB/phpbb/passwords/driver/md5_mybb.php60
-rw-r--r--phpBB/phpbb/passwords/driver/md5_phpbb2.php118
-rw-r--r--phpBB/phpbb/passwords/driver/md5_vb.php60
-rw-r--r--phpBB/phpbb/passwords/driver/salted_md5.php10
-rw-r--r--phpBB/phpbb/passwords/driver/sha1.php52
-rw-r--r--phpBB/phpbb/passwords/driver/sha1_smf.php51
-rw-r--r--phpBB/phpbb/passwords/driver/sha1_wcf1.php60
-rw-r--r--phpBB/phpbb/passwords/driver/sha_xf1.php68
-rw-r--r--phpBB/phpbb/passwords/manager.php30
-rw-r--r--phpBB/phpbb/session.php24
-rw-r--r--phpBB/phpbb/user.php2
-rw-r--r--phpBB/styles/prosilver/template/memberlist_email.html44
-rw-r--r--phpBB/styles/prosilver/template/navbar_footer.html1
-rw-r--r--phpBB/styles/prosilver/template/ucp_avatar_options_local.html1
-rw-r--r--phpBB/styles/prosilver/template/viewtopic_body.html4
-rw-r--r--phpBB/styles/subsilver2/template/index_body.html6
-rw-r--r--phpBB/styles/subsilver2/template/memberlist_email.html26
-rw-r--r--phpBB/styles/subsilver2/template/ucp_avatar_options_local.html1
-rw-r--r--phpBB/styles/subsilver2/template/viewtopic_body.html5
-rw-r--r--phpBB/viewtopic.php1
-rw-r--r--tests/auth/fixtures/user.xml3
-rw-r--r--tests/auth/fixtures/user_533.xml3
-rw-r--r--tests/auth/provider_apache_test.php1
-rw-r--r--tests/auth/provider_db_test.php1
-rw-r--r--tests/console/cron/cron_list_test.php103
-rw-r--r--tests/console/cron/tasks/simple_not_ready.php13
-rw-r--r--tests/console/cron/tasks/simple_ready.php8
-rw-r--r--tests/controller/helper_route_test.php4
-rw-r--r--tests/extension/finder_test.php50
-rw-r--r--tests/functional/visibility_softdelete_test.php8
-rw-r--r--tests/functions/validate_email_test.php80
-rw-r--r--tests/functions/validate_user_email_test.php106
-rw-r--r--tests/mock/request.php19
-rw-r--r--tests/notification/notification_test.php21
-rw-r--r--tests/pagination/pagination_test.php6
-rw-r--r--tests/passwords/drivers_test.php335
-rw-r--r--tests/passwords/manager_test.php50
-rw-r--r--tests/session/testable_factory.php6
-rw-r--r--tests/test_framework/phpbb_database_test_case.php64
-rw-r--r--tests/test_framework/phpbb_functional_test_case.php78
-rwxr-xr-xtravis/prepare-extension.sh22
122 files changed, 4255 insertions, 771 deletions
diff --git a/.gitignore b/.gitignore
index 18f598cf67..de503c10ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,7 +10,13 @@
/phpBB/files/*
/phpBB/images/avatars/gallery/*
/phpBB/images/avatars/upload/*
+/phpBB/images/ranks/*
+/phpBB/language/*
+!/phpBB/language/en
/phpBB/store/*
+/phpBB/styles/*
+!/phpBB/styles/prosilver
+!/phpBB/styles/subsilver2
/phpBB/vendor
/tests/phpbb_unit_tests.sqlite*
/tests/test_config*.php
diff --git a/build/build.xml b/build/build.xml
index ec94cf3ea6..510e7d0955 100644
--- a/build/build.xml
+++ b/build/build.xml
@@ -78,22 +78,22 @@
-s
--extensions=php
--standard=build/code_sniffer/ruleset-php-strict.xml
- --ignore=phpBB/phpbb/db/migration/data/v30x/*
+ --ignore=${project.basedir}/phpBB/phpbb/db/migration/data/v30x/*
phpBB/phpbb"
dir="." returnProperty="retval-php-strict" passthru="true" />
<exec command="phpBB/vendor/bin/phpcs
-s
--extensions=php
--standard=build/code_sniffer/ruleset-php-legacy.xml
- --ignore=phpBB/cache/*
- --ignore=phpBB/develop/*
- --ignore=phpBB/includes/diff/*.php
- --ignore=phpBB/includes/sphinxapi.php
- --ignore=phpBB/includes/utf/data/*
- --ignore=phpBB/install/data/*
- --ignore=phpBB/install/database_update.php
- --ignore=phpBB/phpbb/*
- --ignore=phpBB/vendor/*
+ --ignore=${project.basedir}/phpBB/cache/*
+ --ignore=${project.basedir}/phpBB/develop/*
+ --ignore=${project.basedir}/phpBB/includes/diff/*.php
+ --ignore=${project.basedir}/phpBB/includes/sphinxapi.php
+ --ignore=${project.basedir}/phpBB/includes/utf/data/*
+ --ignore=${project.basedir}/phpBB/install/data/*
+ --ignore=${project.basedir}/phpBB/install/database_update.php
+ --ignore=${project.basedir}/phpBB/phpbb/*
+ --ignore=${project.basedir}/phpBB/vendor/*
phpBB"
dir="." returnProperty="retval-php-legacy" passthru="true" />
<if>
diff --git a/phpBB/adm/style/acp_avatar_options_local.html b/phpBB/adm/style/acp_avatar_options_local.html
index 0cdb3644d7..8adafa1d99 100644
--- a/phpBB/adm/style/acp_avatar_options_local.html
+++ b/phpBB/adm/style/acp_avatar_options_local.html
@@ -1,7 +1,6 @@
<dl>
<dt><label for="category">{L_AVATAR_CATEGORY}{L_COLON}</label></dt>
<dd><select name="avatar_local_cat" id="category">
- <option value="">{L_NO_AVATAR_CATEGORY}</option>
<!-- BEGIN avatar_local_cats -->
<option value="{avatar_local_cats.NAME}"<!-- IF avatar_local_cats.SELECTED --> selected="selected"<!-- ENDIF -->>{avatar_local_cats.NAME}</option>
<!-- END avatar_local_cats -->
diff --git a/phpBB/adm/style/acp_contact.html b/phpBB/adm/style/acp_contact.html
new file mode 100644
index 0000000000..828fd4b659
--- /dev/null
+++ b/phpBB/adm/style/acp_contact.html
@@ -0,0 +1,76 @@
+<!-- INCLUDE overall_header.html -->
+
+<script type="text/javascript">
+// <![CDATA[
+
+ var form_name = 'acp_contact';
+ var text_name = 'contact_admin_info';
+ var load_draft = false;
+ var upload = false;
+ var imageTag = false;
+
+// ]]>
+</script>
+
+<a id="maincontent"></a>
+
+<h1>{L_ACP_CONTACT_SETTINGS}</h1>
+
+<p>{L_ACP_CONTACT_SETTINGS_EXPLAIN}</p>
+
+<form id="acp_contact" method="post" action="{U_ACTION}">
+ <fieldset>
+ <legend>{L_GENERAL_OPTIONS}</legend>
+ <dl>
+ <dt><label for="contact_admin_form_enable">{L_CONTACT_US_ENABLE}{L_COLON}</label><br /><span>{L_CONTACT_US_ENABLE_EXPLAIN}</span></dt>
+ <dd>
+ <label><input type="radio" class="radio" id="contact_admin_form_enable" name="contact_admin_form_enable" value="1"<!-- IF CONTACT_ENABLED --> checked="checked"<!-- ENDIF --> /> {L_ENABLED}</label>
+ <label><input type="radio" class="radio" name="contact_admin_form_enable" value="0"<!-- IF not CONTACT_ENABLED --> checked="checked"<!-- ENDIF --> /> {L_DISABLED}</label>
+ </dd>
+ </dl>
+ </fieldset>
+
+ <!-- IF CONTACT_US_INFO_PREVIEW -->
+ <fieldset>
+ <legend>{L_CONTACT_US_INFO_PREVIEW}</legend>
+ <p>{CONTACT_US_INFO_PREVIEW}</p>
+ </fieldset>
+ <!-- ENDIF -->
+
+ <fieldset>
+ <legend>{L_CONTACT_US_INFO}</legend>
+ <p>{L_CONTACT_US_INFO_EXPLAIN}</p>
+
+ <!-- INCLUDE acp_posting_buttons.html -->
+
+ <dl class="responsive-columns">
+ <dt style="width: 90px;" id="color_palette_placeholder" data-orientation="v" data-height="12" data-width="15" data-bbcode="true">
+ </dt>
+
+ <dd style="margin-{S_CONTENT_FLOW_BEGIN}: 90px;">
+ <textarea name="contact_admin_info" rows="10" cols="60" style="width: 95%;" onselect="storeCaret(this);" onclick="storeCaret(this);" onkeyup="storeCaret(this);" onfocus="initInsertions();" data-bbcode="true">{CONTACT_US_INFO}</textarea>
+ </dd>
+
+ <dd style="margin-{S_CONTENT_FLOW_BEGIN}: 90px; margin-top: 5px;">
+ <!-- IF S_BBCODE_ALLOWED -->
+ <label><input type="checkbox" class="radio" name="disable_bbcode"<!-- IF S_BBCODE_DISABLE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_DISABLE_BBCODE}</label>
+ <!-- ENDIF -->
+ <!-- IF S_SMILIES_ALLOWED -->
+ <label><input type="checkbox" class="radio" name="disable_smilies"<!-- IF S_SMILIES_DISABLE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_DISABLE_SMILIES}</label>
+ <!-- ENDIF -->
+ <!-- IF S_LINKS_ALLOWED -->
+ <label><input type="checkbox" class="radio" name="disable_magic_url"<!-- IF S_MAGIC_URL_DISABLE_CHECKED --> checked="checked"<!-- ENDIF --> /> {L_DISABLE_MAGIC_URL}</label>
+ <!-- ENDIF -->
+ </dd>
+ <dd style="margin-{S_CONTENT_FLOW_BEGIN}: 90px; margin-top: 10px;"><strong>{L_OPTIONS}{L_COLON} </strong>{BBCODE_STATUS} :: {IMG_STATUS} :: {FLASH_STATUS} :: {URL_STATUS} :: {SMILIES_STATUS}</dd>
+ </dl>
+ </fieldset>
+
+ <fieldset class="submit-buttons">
+ <input class="button1" type="submit" id="submit" name="submit" value="{L_SUBMIT}" />&nbsp;
+ <input class="button2" type="submit" name="preview" value="{L_PREVIEW}" />
+ {S_FORM_TOKEN}
+ </fieldset>
+</form>
+
+<!-- INCLUDE overall_footer.html -->
diff --git a/phpBB/adm/style/acp_posting_buttons.html b/phpBB/adm/style/acp_posting_buttons.html
new file mode 100644
index 0000000000..70b6259689
--- /dev/null
+++ b/phpBB/adm/style/acp_posting_buttons.html
@@ -0,0 +1,70 @@
+<script type="text/javascript">
+// <![CDATA[
+
+ // Define the bbCode tags
+ var bbcode = new Array();
+ var bbtags = new Array('[b]','[/b]','[i]','[/i]','[u]','[/u]','[quote]','[/quote]','[code]','[/code]','[list]','[/list]','[list=]','[/list]','[img]','[/img]','[url]','[/url]','[flash=]', '[/flash]','[size=]','[/size]'<!-- BEGIN custom_tags -->, {custom_tags.BBCODE_NAME}<!-- END custom_tags -->);
+
+ // Helpline messages
+ var help_line = {
+ b: '{LA_BBCODE_B_HELP}',
+ i: '{LA_BBCODE_I_HELP}',
+ u: '{LA_BBCODE_U_HELP}',
+ q: '{LA_BBCODE_Q_HELP}',
+ c: '{LA_BBCODE_C_HELP}',
+ l: '{LA_BBCODE_L_HELP}',
+ o: '{LA_BBCODE_O_HELP}',
+ p: '{LA_BBCODE_P_HELP}',
+ w: '{LA_BBCODE_W_HELP}',
+ a: '{LA_BBCODE_A_HELP}',
+ s: '{LA_BBCODE_S_HELP}',
+ f: '{LA_BBCODE_F_HELP}',
+ y: '{LA_BBCODE_Y_HELP}',
+ d: '{LA_BBCODE_D_HELP}'
+ <!-- BEGIN custom_tags -->
+ ,cb_{custom_tags.BBCODE_ID}{L_COLON} '{custom_tags.A_BBCODE_HELPLINE}'
+ <!-- END custom_tags -->
+ }
+
+// ]]>
+</script>
+
+<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js -->
+
+<!-- EVENT acp_posting_buttons_before -->
+<div id="format-buttons">
+ <input type="button" class="button2" accesskey="b" name="addbbcode0" value=" B " style="font-weight:bold; width: 30px" onclick="bbstyle(0)" title="{L_BBCODE_B_HELP}" />
+ <input type="button" class="button2" accesskey="i" name="addbbcode2" value=" i " style="font-style:italic; width: 30px" onclick="bbstyle(2)" title="{L_BBCODE_I_HELP}" />
+ <input type="button" class="button2" accesskey="u" name="addbbcode4" value=" u " style="text-decoration: underline; width: 30px" onclick="bbstyle(4)" title="{L_BBCODE_U_HELP}" />
+ <!-- IF S_BBCODE_QUOTE -->
+ <input type="button" class="button2" accesskey="q" name="addbbcode6" value="Quote" style="width: 50px" onclick="bbstyle(6)" title="{L_BBCODE_Q_HELP}" />
+ <!-- ENDIF -->
+ <input type="button" class="button2" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" title="{L_BBCODE_C_HELP}" />
+ <input type="button" class="button2" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" title="{L_BBCODE_L_HELP}" />
+ <input type="button" class="button2" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" title="{L_BBCODE_O_HELP}" />
+ <input type="button" class="button2" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
+ <!-- IF S_BBCODE_IMG -->
+ <input type="button" class="button2" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" title="{L_BBCODE_P_HELP}" />
+ <!-- ENDIF -->
+ <!-- IF S_LINKS_ALLOWED -->
+ <input type="button" class="button2" accesskey="w" name="addbbcode16" value="URL" style="text-decoration: underline; width: 40px" onclick="bbstyle(16)" title="{L_BBCODE_W_HELP}" />
+ <!-- ENDIF -->
+ <!-- IF S_BBCODE_FLASH -->
+ <input type="button" class="button2" accesskey="d" name="addbbcode18" value="Flash" onclick="bbstyle(18)" title="{L_BBCODE_D_HELP}" />
+ <!-- ENDIF -->
+ <select name="addbbcode20" onchange="bbfontstyle('[size=' + this.form.addbbcode20.options[this.form.addbbcode20.selectedIndex].value + ']', '[/size]');this.form.addbbcode20.selectedIndex = 2;" title="{L_BBCODE_F_HELP}">
+ <option value="50">{L_FONT_TINY}</option>
+ <option value="85">{L_FONT_SMALL}</option>
+ <option value="100" selected="selected">{L_FONT_NORMAL}</option>
+ <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 150 -->
+ <option value="150">{L_FONT_LARGE}</option>
+ <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 200 -->
+ <option value="200">{L_FONT_HUGE}</option>
+ <!-- ENDIF -->
+ <!-- ENDIF -->
+ </select>
+ <!-- BEGIN custom_tags -->
+ <input type="button" class="button2" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}" />
+ <!-- END custom_tags -->
+</div>
+<!-- EVENT acp_posting_buttons_after -->
diff --git a/phpBB/adm/style/acp_users_signature.html b/phpBB/adm/style/acp_users_signature.html
index 5b5c3ecf7f..c7ec5cc0eb 100644
--- a/phpBB/adm/style/acp_users_signature.html
+++ b/phpBB/adm/style/acp_users_signature.html
@@ -5,36 +5,10 @@
var text_name = 'signature';
var load_draft = false;
var upload = false;
-
- // Define the bbCode tags
- var bbcode = new Array();
- var bbtags = new Array('[b]','[/b]','[i]','[/i]','[u]','[/u]','[quote]','[/quote]','[code]','[/code]','[list]','[/list]','[list=]','[/list]','[img]','[/img]','[url]','[/url]','[flash=]', '[/flash]','[size=]','[/size]'<!-- BEGIN custom_tags -->, {custom_tags.BBCODE_NAME}<!-- END custom_tags -->);
var imageTag = false;
- // Helpline messages
- var help_line = {
- b: '{LA_BBCODE_B_HELP}',
- i: '{LA_BBCODE_I_HELP}',
- u: '{LA_BBCODE_U_HELP}',
- q: '{LA_BBCODE_Q_HELP}',
- c: '{LA_BBCODE_C_HELP}',
- l: '{LA_BBCODE_L_HELP}',
- o: '{LA_BBCODE_O_HELP}',
- p: '{LA_BBCODE_P_HELP}',
- w: '{LA_BBCODE_W_HELP}',
- a: '{LA_BBCODE_A_HELP}',
- s: '{LA_BBCODE_S_HELP}',
- f: '{LA_BBCODE_F_HELP}',
- y: '{LA_BBCODE_Y_HELP}',
- d: '{LA_BBCODE_D_HELP}'
- <!-- BEGIN custom_tags -->
- ,cb_{custom_tags.BBCODE_ID}{L_COLON} '{custom_tags.A_BBCODE_HELPLINE}'
- <!-- END custom_tags -->
- }
-
// ]]>
</script>
-<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/editor.js -->
<form id="user_signature" method="post" action="{U_ACTION}">
@@ -49,43 +23,7 @@
<legend>{L_SIGNATURE}</legend>
<p>{L_SIGNATURE_EXPLAIN}</p>
- <!-- EVENT acp_users_signature_editor_buttons_before -->
- <div id="format-buttons">
- <input type="button" class="button2" accesskey="b" name="addbbcode0" value=" B " style="font-weight:bold; width: 30px" onclick="bbstyle(0)" title="{L_BBCODE_B_HELP}" />
- <input type="button" class="button2" accesskey="i" name="addbbcode2" value=" i " style="font-style:italic; width: 30px" onclick="bbstyle(2)" title="{L_BBCODE_I_HELP}" />
- <input type="button" class="button2" accesskey="u" name="addbbcode4" value=" u " style="text-decoration: underline; width: 30px" onclick="bbstyle(4)" title="{L_BBCODE_U_HELP}" />
- <!-- IF S_BBCODE_QUOTE -->
- <input type="button" class="button2" accesskey="q" name="addbbcode6" value="Quote" style="width: 50px" onclick="bbstyle(6)" title="{L_BBCODE_Q_HELP}" />
- <!-- ENDIF -->
- <input type="button" class="button2" accesskey="c" name="addbbcode8" value="Code" style="width: 40px" onclick="bbstyle(8)" title="{L_BBCODE_C_HELP}" />
- <input type="button" class="button2" accesskey="l" name="addbbcode10" value="List" style="width: 40px" onclick="bbstyle(10)" title="{L_BBCODE_L_HELP}" />
- <input type="button" class="button2" accesskey="o" name="addbbcode12" value="List=" style="width: 40px" onclick="bbstyle(12)" title="{L_BBCODE_O_HELP}" />
- <input type="button" class="button2" accesskey="y" name="addlistitem" value="[*]" style="width: 40px" onclick="bbstyle(-1)" title="{L_BBCODE_LISTITEM_HELP}" />
- <!-- IF S_BBCODE_IMG -->
- <input type="button" class="button2" accesskey="p" name="addbbcode14" value="Img" style="width: 40px" onclick="bbstyle(14)" title="{L_BBCODE_P_HELP}" />
- <!-- ENDIF -->
- <!-- IF S_LINKS_ALLOWED -->
- <input type="button" class="button2" accesskey="w" name="addbbcode16" value="URL" style="text-decoration: underline; width: 40px" onclick="bbstyle(16)" title="{L_BBCODE_W_HELP}" />
- <!-- ENDIF -->
- <!-- IF S_BBCODE_FLASH -->
- <input type="button" class="button2" accesskey="d" name="addbbcode18" value="Flash" onclick="bbstyle(18)" title="{L_BBCODE_D_HELP}" />
- <!-- ENDIF -->
- <select name="addbbcode20" onchange="bbfontstyle('[size=' + this.form.addbbcode20.options[this.form.addbbcode20.selectedIndex].value + ']', '[/size]');this.form.addbbcode20.selectedIndex = 2;" title="{L_BBCODE_F_HELP}">
- <option value="50">{L_FONT_TINY}</option>
- <option value="85">{L_FONT_SMALL}</option>
- <option value="100" selected="selected">{L_FONT_NORMAL}</option>
- <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 150 -->
- <option value="150">{L_FONT_LARGE}</option>
- <!-- IF not MAX_FONT_SIZE or MAX_FONT_SIZE >= 200 -->
- <option value="200">{L_FONT_HUGE}</option>
- <!-- ENDIF -->
- <!-- ENDIF -->
- </select>
- <!-- BEGIN custom_tags -->
- <input type="button" class="button2" name="addbbcode{custom_tags.BBCODE_ID}" value="{custom_tags.BBCODE_TAG}" onclick="bbstyle({custom_tags.BBCODE_ID})" title="{custom_tags.BBCODE_HELPLINE}" />
- <!-- END custom_tags -->
- </div>
- <!-- EVENT acp_users_signature_editor_buttons_after -->
+ <!-- INCLUDE acp_posting_buttons.html -->
<dl class="responsive-columns">
<dt style="width: 90px;" id="color_palette_placeholder" data-orientation="v" data-height="12" data-width="15" data-bbcode="true">
diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js
index 296c5b0ef9..37728864c4 100644
--- a/phpBB/assets/javascript/core.js
+++ b/phpBB/assets/javascript/core.js
@@ -1201,7 +1201,11 @@ phpbb.applyCodeEditor = function(textarea) {
var key = event.keyCode || event.which;
// intercept tabs
- if (key == 9) {
+ if (key == 9 &&
+ !event.ctrlKey &&
+ !event.shiftKey &&
+ !event.altKey &&
+ !event.metaKey) {
if (inTag()) {
appendText("\t");
event.preventDefault();
diff --git a/phpBB/assets/plupload/plupload.full.min.js b/phpBB/assets/plupload/plupload.full.min.js
index caa9728156..ca6cdf82de 100644
--- a/phpBB/assets/plupload/plupload.full.min.js
+++ b/phpBB/assets/plupload/plupload.full.min.js
@@ -25,4 +25,4 @@
*
* Date: 2014-05-14
*/
-;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function l(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function c(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!a)return!1;e.ruid=a,e.connectRuntime(a)}c(new o.File(e))}else e instanceof t.Blob?(c(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){l(e,function(n){n||(f.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?c(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,c):i==="array"&&(n=null,t.each(e,c))}var s=this,u=[],a;a=w(),c(e),u.length&&t.inSeries(u,function(){f.length&&s.trigger("FilesAdded",f)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie); \ No newline at end of file
+;(function(e,t,n){function s(e){function r(e,t,r){var i={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};i[e]?n[i[e]]=t:r||(n[e]=t)}var t=e.required_features,n={};if(typeof t=="string")o.each(t.split(/\s*,\s*/),function(e){r(e,!0)});else if(typeof t=="object")o.each(t,function(e,t){r(t,e)});else if(t===!0){e.chunk_size>0&&(n.slice_blob=!0);if(e.resize.enabled||!e.multipart)n.send_binary_string=!0;o.each(e,function(e,t){r(t,!!e,!0)})}return n}var r=e.setTimeout,i={},o={VERSION:"2.1.2",STOPPED:1,STARTED:2,QUEUED:1,UPLOADING:2,FAILED:4,DONE:5,GENERIC_ERROR:-100,HTTP_ERROR:-200,IO_ERROR:-300,SECURITY_ERROR:-400,INIT_ERROR:-500,FILE_SIZE_ERROR:-600,FILE_EXTENSION_ERROR:-601,FILE_DUPLICATE_ERROR:-602,IMAGE_FORMAT_ERROR:-700,MEMORY_ERROR:-701,IMAGE_DIMENSIONS_ERROR:-702,mimeTypes:t.mimes,ua:t.ua,typeOf:t.typeOf,extend:t.extend,guid:t.guid,get:function(n){var r=[],i;t.typeOf(n)!=="array"&&(n=[n]);var s=n.length;while(s--)i=t.get(n[s]),i&&r.push(i);return r.length?r:null},each:t.each,getPos:t.getPos,getSize:t.getSize,xmlEncode:function(e){var t={"<":"lt",">":"gt","&":"amp",'"':"quot","'":"#39"},n=/[<>&\"\']/g;return e?(""+e).replace(n,function(e){return t[e]?"&"+t[e]+";":e}):e},toArray:t.toArray,inArray:t.inArray,addI18n:t.addI18n,translate:t.translate,isEmptyObj:t.isEmptyObj,hasClass:t.hasClass,addClass:t.addClass,removeClass:t.removeClass,getStyle:t.getStyle,addEvent:t.addEvent,removeEvent:t.removeEvent,removeAllEvents:t.removeAllEvents,cleanName:function(e){var t,n;n=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"];for(t=0;t<n.length;t+=2)e=e.replace(n[t],n[t+1]);return e=e.replace(/\s+/g,"_"),e=e.replace(/[^a-z0-9_\-\.]+/gi,""),e},buildUrl:function(e,t){var n="";return o.each(t,function(e,t){n+=(n?"&":"")+encodeURIComponent(t)+"="+encodeURIComponent(e)}),n&&(e+=(e.indexOf("?")>0?"&":"?")+n),e},formatSize:function(e){function t(e,t){return Math.round(e*Math.pow(10,t))/Math.pow(10,t)}if(e===n||/\D/.test(e))return o.translate("N/A");var r=Math.pow(1024,4);return e>r?t(e/r,1)+" "+o.translate("tb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("gb"):e>(r/=1024)?t(e/r,1)+" "+o.translate("mb"):e>1024?Math.round(e/1024)+" "+o.translate("kb"):e+" "+o.translate("b")},parseSize:t.parseSizeStr,predictRuntime:function(e,n){var r,i;return r=new o.Uploader(e),i=t.Runtime.thatCan(r.getOption().required_features,n||e.runtimes),r.destroy(),i},addFileFilter:function(e,t){i[e]=t}};o.addFileFilter("mime_types",function(e,t,n){e.length&&!e.regexp.test(t.name)?(this.trigger("Error",{code:o.FILE_EXTENSION_ERROR,message:o.translate("File extension error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("max_file_size",function(e,t,n){var r;e=o.parseSize(e),t.size!==r&&e&&t.size>e?(this.trigger("Error",{code:o.FILE_SIZE_ERROR,message:o.translate("File size error."),file:t}),n(!1)):n(!0)}),o.addFileFilter("prevent_duplicates",function(e,t,n){if(e){var r=this.files.length;while(r--)if(t.name===this.files[r].name&&t.size===this.files[r].size){this.trigger("Error",{code:o.FILE_DUPLICATE_ERROR,message:o.translate("Duplicate file error."),file:t}),n(!1);return}}n(!0)}),o.Uploader=function(e){function g(){var e,t=0,n;if(this.state==o.STARTED){for(n=0;n<f.length;n++)!e&&f[n].status==o.QUEUED?(e=f[n],this.trigger("BeforeUpload",e)&&(e.status=o.UPLOADING,this.trigger("UploadFile",e))):t++;t==f.length&&(this.state!==o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged")),this.trigger("UploadComplete",f))}}function y(e){e.percent=e.size>0?Math.ceil(e.loaded/e.size*100):100,b()}function b(){var e,t;d.reset();for(e=0;e<f.length;e++)t=f[e],t.size!==n?(d.size+=t.origSize,d.loaded+=t.loaded*t.origSize/t.size):d.size=n,t.status==o.DONE?d.uploaded++:t.status==o.FAILED?d.failed++:d.queued++;d.size===n?d.percent=f.length>0?Math.ceil(d.uploaded/f.length*100):0:(d.bytesPerSec=Math.ceil(d.loaded/((+(new Date)-p||1)/1e3)),d.percent=d.size>0?Math.ceil(d.loaded/d.size*100):0)}function w(){var e=c[0]||h[0];return e?e.getRuntime().uid:!1}function E(e,n){if(e.ruid){var r=t.Runtime.getInfo(e.ruid);if(r)return r.can(n)}return!1}function S(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",O),this.bind("BeforeUpload",C),this.bind("UploadFile",k),this.bind("UploadProgress",L),this.bind("StateChanged",A),this.bind("QueueChanged",b),this.bind("Error",_),this.bind("FileUploaded",M),this.bind("Destroy",D)}function x(e,n){var r=this,i=0,s=[],u={runtime_order:e.runtimes,required_caps:e.required_features,preferred_caps:l,swf_url:e.flash_swf_url,xap_url:e.silverlight_xap_url};o.each(e.runtimes.split(/\s*,\s*/),function(t){e[t]&&(u[t]=e[t])}),e.browse_button&&o.each(e.browse_button,function(n){s.push(function(s){var a=new t.FileInput(o.extend({},u,{accept:e.filters.mime_types,name:e.file_data_name,multiple:e.multi_selection,container:e.container,browse_button:n}));a.onready=function(){var e=t.Runtime.getInfo(this.ruid);t.extend(r.features,{chunks:e.can("slice_blob"),multipart:e.can("send_multipart"),multi_selection:e.can("select_multiple")}),i++,c.push(this),s()},a.onchange=function(){r.addFile(this.files)},a.bind("mouseenter mouseleave mousedown mouseup",function(r){v||(e.browse_button_hover&&("mouseenter"===r.type?t.addClass(n,e.browse_button_hover):"mouseleave"===r.type&&t.removeClass(n,e.browse_button_hover)),e.browse_button_active&&("mousedown"===r.type?t.addClass(n,e.browse_button_active):"mouseup"===r.type&&t.removeClass(n,e.browse_button_active)))}),a.bind("mousedown",function(){r.trigger("Browse")}),a.bind("error runtimeerror",function(){a=null,s()}),a.init()})}),e.drop_element&&o.each(e.drop_element,function(e){s.push(function(n){var s=new t.FileDrop(o.extend({},u,{drop_zone:e}));s.onready=function(){var e=t.Runtime.getInfo(this.ruid);r.features.dragdrop=e.can("drag_and_drop"),i++,h.push(this),n()},s.ondrop=function(){r.addFile(this.files)},s.bind("error runtimeerror",function(){s=null,n()}),s.init()})}),t.inSeries(s,function(){typeof n=="function"&&n(i)})}function T(e,r,i){var s=new t.Image;try{s.onload=function(){if(r.width>this.width&&r.height>this.height&&r.quality===n&&r.preserve_headers&&!r.crop)return this.destroy(),i(e);s.downsize(r.width,r.height,r.crop,r.preserve_headers)},s.onresize=function(){i(this.getAsBlob(e.type,r.quality)),this.destroy()},s.onerror=function(){i(e)},s.load(e)}catch(o){i(e)}}function N(e,n,r){function f(e,t,n){var r=a[e];switch(e){case"max_file_size":e==="max_file_size"&&(a.max_file_size=a.filters.max_file_size=t);break;case"chunk_size":if(t=o.parseSize(t))a[e]=t,a.send_file_name=!0;break;case"multipart":a[e]=t,t||(a.send_file_name=!0);break;case"unique_names":a[e]=t,t&&(a.send_file_name=!0);break;case"filters":o.typeOf(t)==="array"&&(t={mime_types:t}),n?o.extend(a.filters,t):a.filters=t,t.mime_types&&(a.filters.mime_types.regexp=function(e){var t=[];return o.each(e,function(e){o.each(e.extensions.split(/,/),function(e){/^\s*\*\s*$/.test(e)?t.push("\\.*"):t.push("\\."+e.replace(new RegExp("["+"/^$.*+?|()[]{}\\".replace(/./g,"\\$&")+"]","g"),"\\$&"))})}),new RegExp("("+t.join("|")+")$","i")}(a.filters.mime_types));break;case"resize":n?o.extend(a.resize,t,{enabled:!0}):a.resize=t;break;case"prevent_duplicates":a.prevent_duplicates=a.filters.prevent_duplicates=!!t;break;case"browse_button":case"drop_element":t=o.get(t);case"container":case"runtimes":case"multi_selection":case"flash_swf_url":case"silverlight_xap_url":a[e]=t,n||(u=!0);break;default:a[e]=t}n||i.trigger("OptionChanged",e,t,r)}var i=this,u=!1;typeof e=="object"?o.each(e,function(e,t){f(t,e,r)}):f(e,n,r),r?(a.required_features=s(o.extend({},a)),l=s(o.extend({},a,{required_features:!0}))):u&&(i.trigger("Destroy"),x.call(i,a,function(e){e?(i.runtime=t.Runtime.getInfo(w()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})}))}function C(e,t){if(e.settings.unique_names){var n=t.name.match(/\.([^.]+)$/),r="part";n&&(r=n[1]),t.target_name=t.id+"."+r}}function k(e,n){function h(){u-->0?r(p,1e3):(n.loaded=f,e.trigger("Error",{code:o.HTTP_ERROR,message:o.translate("HTTP Error."),file:n,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}))}function p(){var d,v,g={},y;if(n.status!==o.UPLOADING||e.state===o.STOPPED)return;e.settings.send_file_name&&(g.name=n.target_name||n.name),s&&a.chunks&&c.size>s?(y=Math.min(s,c.size-f),d=c.slice(f,f+y)):(y=c.size,d=c),s&&a.chunks&&(e.settings.send_chunk_number?(g.chunk=Math.ceil(f/s),g.chunks=Math.ceil(c.size/s)):(g.offset=f,g.total=c.size)),m=new t.XMLHttpRequest,m.upload&&(m.upload.onprogress=function(t){n.loaded=Math.min(n.size,f+t.loaded),e.trigger("UploadProgress",n)}),m.onload=function(){if(m.status>=400){h();return}u=e.settings.max_retries,y<c.size?(d.destroy(),f+=y,n.loaded=Math.min(f,c.size),e.trigger("ChunkUploaded",n,{offset:n.loaded,total:c.size,response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()}),t.Env.browser==="Android Browser"&&e.trigger("UploadProgress",n)):n.loaded=n.size,d=v=null,!f||f>=c.size?(n.size!=n.origSize&&(c.destroy(),c=null),e.trigger("UploadProgress",n),n.status=o.DONE,e.trigger("FileUploaded",n,{response:m.responseText,status:m.status,responseHeaders:m.getAllResponseHeaders()})):r(p,1)},m.onerror=function(){h()},m.onloadend=function(){this.destroy(),m=null},e.settings.multipart&&a.multipart?(m.open("post",i,!0),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),v=new t.FormData,o.each(o.extend(g,e.settings.multipart_params),function(e,t){v.append(t,e)}),v.append(e.settings.file_data_name,d),m.send(v,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url})):(i=o.buildUrl(e.settings.url,o.extend(g,e.settings.multipart_params)),m.open("post",i,!0),m.setRequestHeader("Content-Type","application/octet-stream"),o.each(e.settings.headers,function(e,t){m.setRequestHeader(t,e)}),m.send(d,{runtime_order:e.settings.runtimes,required_caps:e.settings.required_features,preferred_caps:l,swf_url:e.settings.flash_swf_url,xap_url:e.settings.silverlight_xap_url}))}var i=e.settings.url,s=e.settings.chunk_size,u=e.settings.max_retries,a=e.features,f=0,c;n.loaded&&(f=n.loaded=s?s*Math.floor(n.loaded/s):0),c=n.getSource(),e.settings.resize.enabled&&E(c,"send_binary_string")&&!!~t.inArray(c.type,["image/jpeg","image/png"])?T.call(this,c,e.settings.resize,function(e){c=e,n.size=e.size,p()}):p()}function L(e,t){y(t)}function A(e){if(e.state==o.STARTED)p=+(new Date);else if(e.state==o.STOPPED)for(var t=e.files.length-1;t>=0;t--)e.files[t].status==o.UPLOADING&&(e.files[t].status=o.QUEUED,b())}function O(){m&&m.abort()}function M(e){b(),r(function(){g.call(e)},1)}function _(e,t){t.code===o.INIT_ERROR?e.destroy():t.file&&(t.file.status=o.FAILED,y(t.file),e.state==o.STARTED&&(e.trigger("CancelUpload"),r(function(){g.call(e)},1)))}function D(e){e.stop(),o.each(f,function(e){e.destroy()}),f=[],c.length&&(o.each(c,function(e){e.destroy()}),c=[]),h.length&&(o.each(h,function(e){e.destroy()}),h=[]),l={},v=!1,p=m=null,d.reset()}var u=o.guid(),a,f=[],l={},c=[],h=[],p,d,v=!1,m;a={runtimes:t.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",flash_swf_url:"js/Moxie.swf",silverlight_xap_url:"js/Moxie.xap",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},N.call(this,e,null,!0),d=new o.QueueProgress,o.extend(this,{id:u,uid:u,state:o.STOPPED,features:{},runtime:null,files:f,settings:a,total:d,init:function(){var e=this;typeof a.preinit=="function"?a.preinit(e):o.each(a.preinit,function(t,n){e.bind(n,t)}),S.call(this);if(!a.browse_button||!a.url){this.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")});return}x.call(this,a,function(n){typeof a.init=="function"?a.init(e):o.each(a.init,function(t,n){e.bind(n,t)}),n?(e.runtime=t.Runtime.getInfo(w()).type,e.trigger("Init",{runtime:e.runtime}),e.trigger("PostInit")):e.trigger("Error",{code:o.INIT_ERROR,message:o.translate("Init error.")})})},setOption:function(e,t){N.call(this,e,t,!this.runtime)},getOption:function(e){return e?a[e]:a},refresh:function(){c.length&&o.each(c,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=o.STARTED&&(this.state=o.STARTED,this.trigger("StateChanged"),g.call(this))},stop:function(){this.state!=o.STOPPED&&(this.state=o.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){v=arguments[0]!==n?arguments[0]:!0,c.length&&o.each(c,function(e){e.disable(v)}),this.trigger("DisableBrowse",v)},getFile:function(e){var t;for(t=f.length-1;t>=0;t--)if(f[t].id===e)return f[t]},addFile:function(e,n){function c(e,n){var r=[];t.each(s.settings.filters,function(t,n){i[n]&&r.push(function(r){i[n].call(s,t,e,function(e){r(!e)})})}),t.inSeries(r,n)}function h(e){var i=t.typeOf(e);if(e instanceof t.File){if(!e.ruid&&!e.isDetached()){if(!l)return!1;e.ruid=l,e.connectRuntime(l)}h(new o.File(e))}else e instanceof t.Blob?(h(e.getSource()),e.destroy()):e instanceof o.File?(n&&(e.name=n),u.push(function(t){c(e,function(n){n||(f.push(e),a.push(e),s.trigger("FileFiltered",e)),r(t,1)})})):t.inArray(i,["file","blob"])!==-1?h(new t.File(null,e)):i==="node"&&t.typeOf(e.files)==="filelist"?t.each(e.files,h):i==="array"&&(n=null,t.each(e,h))}var s=this,u=[],a=[],l;l=w(),h(e),u.length&&t.inSeries(u,function(){a.length&&s.trigger("FilesAdded",a)})},removeFile:function(e){var t=typeof e=="string"?e:e.id;for(var n=f.length-1;n>=0;n--)if(f[n].id===t)return this.splice(n,1)[0]},splice:function(e,t){var r=f.splice(e===n?0:e,t===n?f.length:t),i=!1;return this.state==o.STARTED&&(o.each(r,function(e){if(e.status===o.UPLOADING)return i=!0,!1}),i&&this.stop()),this.trigger("FilesRemoved",r),o.each(r,function(e){e.destroy()}),i&&this.start(),r},bind:function(e,t,n){var r=this;o.Uploader.prototype.bind.call(this,e,function(){var e=[].slice.call(arguments);return e.splice(0,1,r),t.apply(this,e)},0,n)},destroy:function(){this.trigger("Destroy"),a=d=null,this.unbindAll()}})},o.Uploader.prototype=t.EventTarget.instance,o.File=function(){function n(n){o.extend(this,{id:o.guid(),name:n.name||n.fileName,type:n.type||"",size:n.size||n.fileSize,origSize:n.size||n.fileSize,loaded:0,percent:0,status:o.QUEUED,lastModifiedDate:n.lastModifiedDate||(new Date).toLocaleString(),getNative:function(){var e=this.getSource().getSource();return t.inArray(t.typeOf(e),["blob","file"])!==-1?e:null},getSource:function(){return e[this.id]?e[this.id]:null},destroy:function(){var t=this.getSource();t&&(t.destroy(),delete e[this.id])}}),e[this.id]=n}var e={};return n}(),o.QueueProgress=function(){var e=this;e.size=0,e.loaded=0,e.uploaded=0,e.failed=0,e.queued=0,e.percent=0,e.bytesPerSec=0,e.reset=function(){e.size=e.loaded=e.uploaded=e.failed=e.queued=e.percent=e.bytesPerSec=0}},e.plupload=o})(window,mOxie); \ No newline at end of file
diff --git a/phpBB/bin/phpbbcli.php b/phpBB/bin/phpbbcli.php
index 63c8f2230b..8b8d8e43fd 100755
--- a/phpBB/bin/phpbbcli.php
+++ b/phpBB/bin/phpbbcli.php
@@ -39,6 +39,9 @@ $phpbb_container = phpbb_create_update_container($phpbb_root_path, $phpEx, "$php
$phpbb_container->get('request')->enable_super_globals();
require($phpbb_root_path . 'includes/compatibility_globals.' . $phpEx);
-$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION);
+$user = $phpbb_container->get('user');
+$user->add_lang('acp/common');
+
+$application = new \phpbb\console\application('phpBB Console', PHPBB_VERSION, $user);
$application->register_container_commands($phpbb_container);
$application->run();
diff --git a/phpBB/config/auth_providers.yml b/phpBB/config/auth_providers.yml
index dac8b9d252..d2f22ec477 100644
--- a/phpBB/config/auth_providers.yml
+++ b/phpBB/config/auth_providers.yml
@@ -1,8 +1,9 @@
services:
auth.provider_collection:
- class: phpbb\di\service_collection
+ class: phpbb\auth\provider_collection
arguments:
- @service_container
+ - @config
tags:
- { name: service_collection, tag: auth.provider }
auth.provider.db:
diff --git a/phpBB/config/console.yml b/phpBB/config/console.yml
index a102a8c609..00b8f9cec0 100644
--- a/phpBB/config/console.yml
+++ b/phpBB/config/console.yml
@@ -46,6 +46,14 @@ services:
tags:
- { name: console.command }
+ console.command.cron.list:
+ class: phpbb\console\command\cron\cron_list
+ arguments:
+ - @cron.manager
+ - @user
+ tags:
+ - { name: console.command }
+
console.command.cron.run:
class: phpbb\console\command\cron\run
arguments:
@@ -67,6 +75,13 @@ services:
tags:
- { name: console.command }
+ console.command.dev.migration_tips:
+ class: phpbb\console\command\dev\migration_tips
+ arguments:
+ - @ext.manager
+ tags:
+ - { name: console.command }
+
console.command.extension.disable:
class: phpbb\console\command\extension\disable
arguments:
diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml
index 9e249a2c12..3dc217286f 100644
--- a/phpBB/config/passwords.yml
+++ b/phpBB/config/passwords.yml
@@ -22,6 +22,14 @@ services:
tags:
- { name: passwords.driver }
+ passwords.driver.bcrypt_wcf2:
+ class: phpbb\passwords\driver\bcrypt_wcf2
+ arguments:
+ - @passwords.driver.bcrypt
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
passwords.driver.salted_md5:
class: phpbb\passwords\driver\salted_md5
arguments:
@@ -38,6 +46,64 @@ services:
tags:
- { name: passwords.driver }
+ passwords.driver.convert_password:
+ class: phpbb\passwords\driver\convert_password
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1_smf:
+ class: phpbb\passwords\driver\sha1_smf
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1_wcf1:
+ class: phpbb\passwords\driver\sha1_wcf1
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.sha1:
+ class: phpbb\passwords\driver\sha1
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_phpbb2:
+ class: phpbb\passwords\driver\md5_phpbb2
+ arguments:
+ - @request
+ - @passwords.driver.salted_md5
+ - %core.root_path%
+ - %core.php_ext%
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_mybb:
+ class: phpbb\passwords\driver\md5_mybb
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
+ passwords.driver.md5_vb:
+ class: phpbb\passwords\driver\md5_vb
+ arguments:
+ - @config
+ - @passwords.driver_helper
+ tags:
+ - { name: passwords.driver }
+
passwords.driver_collection:
class: phpbb\di\service_collection
arguments:
diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml
index 3bd9182924..3743daa075 100644
--- a/phpBB/config/services.yml
+++ b/phpBB/config/services.yml
@@ -239,6 +239,38 @@ services:
- %core.php_ext%
- %tables.log%
+ message.form.admin:
+ class: phpbb\message\admin_form
+ arguments:
+ - @auth
+ - @config
+ - @config_text
+ - @dbal.conn
+ - @user
+ - %core.root_path%
+ - %core.php_ext%
+
+ message.form.topic:
+ class: phpbb\message\topic_form
+ arguments:
+ - @auth
+ - @config
+ - @config_text
+ - @dbal.conn
+ - @user
+ - %core.root_path%
+ - %core.php_ext%
+
+ message.form.user:
+ class: phpbb\message\user_form
+ arguments:
+ - @auth
+ - @config
+ - @dbal.conn
+ - @user
+ - %core.root_path%
+ - %core.php_ext%
+
notification_manager:
class: phpbb\notification\manager
arguments:
diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php
index 5490e45afa..05085d39ab 100644
--- a/phpBB/develop/create_schema_files.php
+++ b/phpBB/develop/create_schema_files.php
@@ -44,17 +44,9 @@ 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();
-class phpbb_extension_empty_manager extends \phpbb\extension\manager
-{
- public function __construct()
- {
- $this->extensions = array();
- }
-}
-
-$finder = new \phpbb\extension\finder(new \phpbb_extension_empty_manager(), new \phpbb\filesystem(), $phpbb_root_path);
+$finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path);
$classes = $finder->core_path('phpbb/')
- ->directory('db/migration/data')
+ ->directory('/db/migration/data')
->get_classes();
$db = new \phpbb\db\driver\sqlite();
diff --git a/phpBB/develop/migration_tips.php b/phpBB/develop/migration_tips.php
deleted file mode 100644
index fdb1e4544d..0000000000
--- a/phpBB/develop/migration_tips.php
+++ /dev/null
@@ -1,46 +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.
-*
-*/
-
-// This is to help with creating migration files for new versions
-// Use this to find what migrations are not depended on by any other migration
-// (the current migration tree tips)
-
-define('IN_PHPBB', true);
-$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
-$phpEx = substr(strrchr(__FILE__, '.'), 1);
-include($phpbb_root_path . 'common.' . $phpEx);
-
-$phpbb_extension_manager = $phpbb_container->get('ext.manager');
-$finder = $phpbb_extension_manager->get_finder();
-
-$migrations = $finder
- ->core_path('phpbb/db/migration/data/')
- ->get_classes();
-$tips = $migrations;
-
-foreach ($migrations as $migration_class)
-{
- foreach ($migration_class::depends_on() as $dependency)
- {
- if (($tips_key = array_search($dependency, $tips)) !== false)
- {
- unset($tips[$tips_key]);
- }
- }
-}
-
-foreach ($tips as $migration)
-{
- echo "\t\t\t'{$migration}',\n";
-}
-
diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md
index 4dc55540f3..44a7824901 100644
--- a/phpBB/docs/events.md
+++ b/phpBB/docs/events.md
@@ -64,6 +64,20 @@ acp_overall_header_head_append
* Since: 3.1.0-a1
* Purpose: Add assets within the `<head>` tags in the ACP
+acp_posting_buttons_after
+===
+* Locations:
+ + adm/style/acp_posting_buttons.html
+* Since: 3.1.0-b4
+* Purpose: Add content after BBCode posting buttons in the ACP
+
+acp_posting_buttons_before
+===
+* Locations:
+ + adm/style/acp_posting_buttons.html
+* Since: 3.1.0-b4
+* Purpose: Add content before BBCode posting buttons in the ACP
+
acp_simple_footer_after
===
* Location: adm/style/simple_footer.html
@@ -136,20 +150,6 @@ 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_signature_editor_buttons_after
-===
-* Locations:
- + adm/style/acp_users_signature.html
-* Since: 3.1.0-a3
-* Purpose: Add content after BBCode posting buttons in the ACP user signature
-
-acp_users_signature_editor_buttons_before
-===
-* Locations:
- + adm/style/acp_users_signature.html
-* Since: 3.1.0-a3
-* Purpose: Add content before BBCode posting buttons in the ACP user signature
-
forumlist_body_category_header_after
===
* Locations:
diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php
new file mode 100644
index 0000000000..13d38d9f29
--- /dev/null
+++ b/phpBB/includes/acp/acp_contact.php
@@ -0,0 +1,129 @@
+<?php
+/**
+*
+* @package acp
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* @package acp
+*/
+class acp_contact
+{
+ public $u_action;
+
+ public function main($id, $mode)
+ {
+ global $user, $request, $template;
+ global $config, $phpbb_root_path, $phpEx, $phpbb_container;
+
+ $user->add_lang(array('acp/board', 'posting'));
+
+ $this->tpl_name = 'acp_contact';
+ $this->page_title = 'ACP_CONTACT_SETTINGS';
+ $form_name = 'acp_contact';
+ add_form_key($form_name);
+ $error = '';
+
+ if (!function_exists('display_custom_bbcodes'))
+ {
+ include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
+ }
+ if (!class_exists('parse_message'))
+ {
+ include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
+ }
+
+ $config_text = $phpbb_container->get('config_text');
+
+ $contact_admin_data = $config_text->get_array(array(
+ 'contact_admin_info',
+ 'contact_admin_info_uid',
+ 'contact_admin_info_bitfield',
+ 'contact_admin_info_flags',
+ ));
+
+ $contact_admin_info = $contact_admin_data['contact_admin_info'];
+ $contact_admin_info_uid = $contact_admin_data['contact_admin_info_uid'];
+ $contact_admin_info_bitfield= $contact_admin_data['contact_admin_info_bitfield'];
+ $contact_admin_info_flags = $contact_admin_data['contact_admin_info_flags'];
+
+ if ($request->is_set_post('submit') || $request->is_set_post('preview'))
+ {
+ if (!check_form_key($form_name))
+ {
+ $error = $user->lang('FORM_INVALID');
+ }
+
+ $contact_admin_info = $request->variable('contact_admin_info', '', true);
+
+ generate_text_for_storage(
+ $contact_admin_info,
+ $contact_admin_info_uid,
+ $contact_admin_info_bitfield,
+ $contact_admin_info_flags,
+ !$request->variable('disable_bbcode', false),
+ !$request->variable('disable_magic_url', false),
+ !$request->variable('disable_smilies', false)
+ );
+
+ if (empty($error) && $request->is_set_post('submit'))
+ {
+ $config->set('contact_admin_form_enable', $request->variable('contact_admin_form_enable', false));
+
+ $config_text->set_array(array(
+ 'contact_admin_info' => $contact_admin_info,
+ 'contact_admin_info_uid' => $contact_admin_info_uid,
+ 'contact_admin_info_bitfield' => $contact_admin_info_bitfield,
+ 'contact_admin_info_flags' => $contact_admin_info_flags,
+ ));
+
+ trigger_error($user->lang['CONTACT_US_INFO_UPDATED'] . adm_back_link($this->u_action));
+ }
+ }
+
+ $contact_admin_info_preview = '';
+ if ($request->is_set_post('preview'))
+ {
+ $contact_admin_info_preview = generate_text_for_display($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_bitfield, $contact_admin_info_flags);
+ }
+
+ $contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags);
+
+ $template->assign_vars(array(
+ 'ERRORS' => $error,
+ 'CONTACT_ENABLED' => $config['contact_admin_form_enable'],
+
+ 'CONTACT_US_INFO' => $contact_admin_edit['text'],
+ 'CONTACT_US_INFO_PREVIEW' => $contact_admin_info_preview,
+
+ 'S_BBCODE_DISABLE_CHECKED' => !$contact_admin_edit['allow_bbcode'],
+ 'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'],
+ 'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'],
+
+ 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'),
+ 'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'],
+ 'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'],
+ 'FLASH_STATUS' => $user->lang['FLASH_IS_ON'],
+ 'URL_STATUS' => $user->lang['URL_IS_ON'],
+
+ 'S_BBCODE_ALLOWED' => true,
+ 'S_SMILIES_ALLOWED' => true,
+ 'S_BBCODE_IMG' => true,
+ 'S_BBCODE_FLASH' => true,
+ 'S_LINKS_ALLOWED' => true,
+ ));
+
+ // Assigning custom bbcodes
+ display_custom_bbcodes();
+ }
+}
diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php
index 63bfa3ac53..fe55b36e67 100644
--- a/phpBB/includes/acp/acp_email.php
+++ b/phpBB/includes/acp/acp_email.php
@@ -201,7 +201,7 @@ class acp_email
$messenger->set_mail_priority($priority);
$messenger->assign_vars(array(
- 'CONTACT_EMAIL' => $config['board_contact'],
+ 'CONTACT_EMAIL' => phpbb_get_board_contact($config, $phpEx),
'MESSAGE' => htmlspecialchars_decode($message))
);
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index f4013a9bf2..f10f0b1015 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -27,7 +27,7 @@ class acp_groups
{
global $config, $db, $user, $auth, $template, $cache;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix, $file_uploads;
- global $request, $phpbb_container;
+ global $request, $phpbb_container, $phpbb_dispatcher;
$user->add_lang('acp/groups');
$this->tpl_name = 'acp_groups';
@@ -410,6 +410,42 @@ class acp_groups
'colour' => array('hex_colour', true),
);
+ /**
+ * Request group data and operate on it
+ *
+ * @event core.acp_manage_group_request_data
+ * @var string action Type of the action: add|edit
+ * @var int group_id The group id
+ * @var array group_row Array with new group data
+ * @var array error Array of errors, if you add errors
+ * ensure to update the template variables
+ * S_ERROR and ERROR_MSG to display it
+ * @var string group_name The group name
+ * @var string group_desc The group description
+ * @var int group_type The group type
+ * @var bool allow_desc_bbcode Allow bbcode in group description: true|false
+ * @var bool allow_desc_urls Allow urls in group description: true|false
+ * @var bool allow_desc_smilies Allow smiles in group description: true|false
+ * @var array submit_ary Array with new group data
+ * @var array validation_checks Array with validation data
+ * @since 3.1.0-b5
+ */
+ $vars = array(
+ 'action',
+ 'group_id',
+ 'group_row',
+ 'error',
+ 'group_name',
+ 'group_desc',
+ 'group_type',
+ 'allow_desc_bbcode',
+ 'allow_desc_urls',
+ 'allow_desc_smilies',
+ 'submit_ary',
+ 'validation_checks',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_request_data', compact($vars)));
+
if ($validation_error = validate_data($submit_ary, $validation_checks))
{
// Replace "error" string with its real, localised form
@@ -442,6 +478,42 @@ class acp_groups
'skip_auth' => 'int',
);
+ /**
+ * Initialise data before we display the add/edit form
+ *
+ * @event core.acp_manage_group_initialise_data
+ * @var string action Type of the action: add|edit
+ * @var int group_id The group id
+ * @var array group_row Array with new group data
+ * @var array error Array of errors, if you add errors
+ * ensure to update the template variables
+ * S_ERROR and ERROR_MSG to display it
+ * @var string group_name The group name
+ * @var string group_desc The group description
+ * @var int group_type The group type
+ * @var bool allow_desc_bbcode Allow bbcode in group description: true|false
+ * @var bool allow_desc_urls Allow urls in group description: true|false
+ * @var bool allow_desc_smilies Allow smiles in group description: true|false
+ * @var array submit_ary Array with new group data
+ * @var array test_variables Array with variables for test
+ * @since 3.1.0-b5
+ */
+ $vars = array(
+ 'action',
+ 'group_id',
+ 'group_row',
+ 'error',
+ 'group_name',
+ 'group_desc',
+ 'group_type',
+ 'allow_desc_bbcode',
+ 'allow_desc_urls',
+ 'allow_desc_smilies',
+ 'submit_ary',
+ 'test_variables',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_initialise_data', compact($vars)));
+
foreach ($test_variables as $test => $type)
{
if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes)))
@@ -664,6 +736,39 @@ class acp_groups
'L_AVATAR_EXPLAIN' => phpbb_avatar_explanation_string(),
));
+ /**
+ * Modify group template data before we display the form
+ *
+ * @event core.acp_manage_group_display_form
+ * @var string action Type of the action: add|edit
+ * @var bool update Do we display the form only
+ * or did the user press submit
+ * @var int group_id The group id
+ * @var array group_row Array with new group data
+ * @var string group_name The group name
+ * @var int group_type The group type
+ * @var array group_desc_data The group description data
+ * @var string group_rank The group rank
+ * @var string rank_options The rank options
+ * @var array error Array of errors, if you add errors
+ * ensure to update the template variables
+ * S_ERROR and ERROR_MSG to display it
+ * @since 3.1.0-b5
+ */
+ $vars = array(
+ 'action',
+ 'update',
+ 'group_id',
+ 'group_row',
+ 'group_desc_data',
+ 'group_name',
+ 'group_type',
+ 'group_rank',
+ 'rank_options',
+ 'error',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.acp_manage_group_display_form', compact($vars)));
+
return;
break;
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 61bae18557..5932f4cddd 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -561,14 +561,14 @@ class acp_modules
$directory = $phpbb_root_path . 'includes/' . $module_class . '/info/';
$fileinfo = array();
- $finder = $phpbb_extension_manager->get_finder();
+ $finder = $phpbb_extension_manager->get_finder($use_all_available);
$modules = $finder
->extension_suffix('_module')
->extension_directory("/$module_class")
->core_path("includes/$module_class/info/")
->core_prefix($module_class . '_')
- ->get_classes(true, $use_all_available);
+ ->get_classes(true);
foreach ($modules as $cur_module)
{
diff --git a/phpBB/includes/acp/acp_php_info.php b/phpBB/includes/acp/acp_php_info.php
index 0e06c94869..810a111edb 100644
--- a/phpBB/includes/acp/acp_php_info.php
+++ b/phpBB/includes/acp/acp_php_info.php
@@ -47,7 +47,7 @@ class acp_php_info
// for this was nabbed from the PHP annotated manual
preg_match_all('#<body[^>]*>(.*)</body>#si', $phpinfo, $output);
- if (empty($phpinfo) || empty($output))
+ if (empty($phpinfo) || empty($output[1][0]))
{
trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING);
}
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index b653ddd13b..d07120a65f 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -814,7 +814,7 @@ class acp_users
$check_ary += array(
'email' => array(
array('string', false, 6, 60),
- array('email', $user_row['user_email'])
+ array('user_email', $user_row['user_email']),
),
);
}
@@ -922,7 +922,6 @@ class acp_users
$sql_ary += array(
'user_password' => $passwords_manager->hash($data['new_password']),
'user_passchg' => time(),
- 'user_pass_convert' => 0,
);
$user->reset_login_keys($user_id);
diff --git a/phpBB/includes/acp/info/acp_contact.php b/phpBB/includes/acp/info/acp_contact.php
new file mode 100644
index 0000000000..b8326f34ea
--- /dev/null
+++ b/phpBB/includes/acp/info/acp_contact.php
@@ -0,0 +1,26 @@
+<?php
+/**
+*
+* @package acp
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @package module_install
+*/
+class acp_contact_info
+{
+ public function module()
+ {
+ return array(
+ 'filename' => 'acp_contact',
+ 'title' => 'ACP_CONTACT',
+ 'version' => '1.0.0',
+ 'modes' => array(
+ 'contact' => array('title' => 'ACP_CONTACT_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
+ ),
+ );
+ }
+}
diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php
index dde3f9d4c9..8e1e61bdb7 100644
--- a/phpBB/includes/captcha/plugins/captcha_abstract.php
+++ b/phpBB/includes/captcha/plugins/captcha_abstract.php
@@ -96,7 +96,8 @@ class phpbb_captcha_plugins_captcha_abstract
else
{
$link = append_sid($phpbb_root_path . 'ucp.' . $phpEx, 'mode=confirm&amp;confirm_id=' . $this->confirm_id . '&amp;type=' . $this->type);
- $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
+ $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="' . $contact_link . '">', '</a>');
$template->assign_vars(array(
'CONFIRM_IMAGE_LINK' => $link,
diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
index 0568cb7c51..12cc49ef9b 100644
--- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
+++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php
@@ -150,7 +150,7 @@ class phpbb_recaptcha extends phpbb_default_captcha
function get_template()
{
- global $config, $user, $template;
+ global $config, $user, $template, $phpbb_root_path, $phpEx;
if ($this->is_solved())
{
@@ -158,7 +158,8 @@ class phpbb_recaptcha extends phpbb_default_captcha
}
else
{
- $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
+ $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
+ $explain = $user->lang(($this->type != CONFIRM_POST) ? 'CONFIRM_EXPLAIN' : 'POST_CONFIRM_EXPLAIN', '<a href="' . $contact_link . '">', '</a>');
$template->assign_vars(array(
'RECAPTCHA_SERVER' => $this->recaptcha_server,
diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php
index cf18cafe90..723956de0c 100644
--- a/phpBB/includes/constants.php
+++ b/phpBB/includes/constants.php
@@ -233,6 +233,7 @@ define('BBCODES_TABLE', $table_prefix . 'bbcodes');
define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks');
define('BOTS_TABLE', $table_prefix . 'bots');
define('CONFIG_TABLE', $table_prefix . 'config');
+define('CONFIG_TEXT_TABLE', $table_prefix . 'config_text');
define('CONFIRM_TABLE', $table_prefix . 'confirm');
define('DISALLOW_TABLE', $table_prefix . 'disallow');
define('DRAFTS_TABLE', $table_prefix . 'drafts');
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index c423e29d9d..3d0a4761f3 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -2818,8 +2818,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
$user->lang[$result['error_msg']],
($config['email_enable']) ? '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=sendpassword') . '">' : '',
($config['email_enable']) ? '</a>' : '',
- ($config['board_contact']) ? '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">' : '',
- ($config['board_contact']) ? '</a>' : ''
+ '<a href="' . phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx) . '">',
+ '</a>'
);
break;
@@ -2830,7 +2830,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
// Assign admin contact to some error messages
if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD')
{
- $err = (!$config['board_contact']) ? sprintf($user->lang[$result['error_msg']], '', '') : sprintf($user->lang[$result['error_msg']], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>');
+ $err = sprintf($user->lang[$result['error_msg']], '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin') . '">', '</a>');
}
break;
@@ -2854,7 +2854,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa
$s_hidden_fields['credential'] = $credential;
}
- $auth_provider = $phpbb_container->get('auth.provider.' . $config['auth_method']);
+ $provider_collection = $phpbb_container->get('auth.provider_collection');
+ $auth_provider = $provider_collection->get_provider();
$auth_provider_data = $auth_provider->get_login_data();
if ($auth_provider_data)
@@ -4922,6 +4923,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
'U_SEARCH_UNREAD' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unreadposts'),
'U_SEARCH_ACTIVE_TOPICS'=> append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=active_topics'),
'U_DELETE_COOKIES' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=delete_cookies'),
+ 'U_CONTACT_US' => ($config['contact_admin_form_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin') : '',
'U_TEAM' => ($user->data['user_id'] != ANONYMOUS && !$auth->acl_get('u_viewprofile')) ? '' : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=team'),
'U_TERMS_USE' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=terms'),
'U_PRIVACY' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=privacy'),
@@ -5029,6 +5031,72 @@ function page_header($page_title = '', $display_online_list = false, $item_id =
}
/**
+* Check and display the SQL report if requested.
+*
+* @param \phpbb\request\request_interface $request Request object
+* @param \phpbb\auth\auth $auth Auth object
+* @param \phpbb\db\driver\driver_interface $db Database connection
+*/
+function phpbb_check_and_display_sql_report(\phpbb\request\request_interface $request, \phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db)
+{
+ if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG'))
+ {
+ $db->sql_report('display');
+ }
+}
+
+/**
+* Generate the debug output string
+*
+* @param \phpbb\db\driver\driver_interface $db Database connection
+* @param \phpbb\config\config $config Config object
+* @param \phpbb\auth\auth $auth Auth object
+* @param \phpbb\user $user User object
+* @return string
+*/
+function phpbb_generate_debug_output(phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\auth\auth $auth, \phpbb\user $user)
+{
+ $debug_info = array();
+
+ // Output page creation time
+ if (defined('PHPBB_DISPLAY_LOAD_TIME'))
+ {
+ if (isset($GLOBALS['starttime']))
+ {
+ $totaltime = microtime(true) - $GLOBALS['starttime'];
+ $debug_info[] = sprintf('Time: %.3fs', $totaltime);
+ }
+
+ $debug_info[] = $db->sql_num_queries() . ' Queries (' . $db->sql_num_queries(true) . ' cached)';
+
+ $memory_usage = memory_get_peak_usage();
+ if ($memory_usage)
+ {
+ $memory_usage = get_formatted_filesize($memory_usage);
+
+ $debug_info[] = 'Peak Memory Usage: ' . $memory_usage;
+ }
+ }
+
+ if (defined('DEBUG'))
+ {
+ $debug_info[] = 'GZIP: ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off');
+
+ if ($user->load)
+ {
+ $debug_info[] = 'Load: ' . $user->load;
+ }
+
+ if ($auth->acl_get('a_'))
+ {
+ $debug_info[] = '<a href="' . build_url() . '&amp;explain=1">SQL Explain</a>';
+ }
+ }
+
+ return implode(' | ', $debug_info);
+}
+
+/**
* Generate page footer
*
* @param bool $run_cron Whether or not to run the cron
@@ -5060,37 +5128,10 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler =
return;
}
- // Output page creation time
- if (defined('DEBUG'))
- {
- $mtime = explode(' ', microtime());
- $totaltime = $mtime[0] + $mtime[1] - $starttime;
-
- if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG') && method_exists($db, 'sql_report'))
- {
- $db->sql_report('display');
- }
-
- $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress'] && @extension_loaded('zlib')) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
-
- if ($auth->acl_get('a_') && defined('DEBUG'))
- {
- if (function_exists('memory_get_peak_usage'))
- {
- if ($memory_usage = memory_get_peak_usage())
- {
- $memory_usage = get_formatted_filesize($memory_usage);
-
- $debug_output .= ' | Peak Memory Usage: ' . $memory_usage;
- }
- }
-
- $debug_output .= ' | <a href="' . build_url() . '&amp;explain=1">Explain</a>';
- }
- }
+ phpbb_check_and_display_sql_report($request, $auth, $db);
$template->assign_vars(array(
- 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '',
+ 'DEBUG_OUTPUT' => phpbb_generate_debug_output($db, $config, $auth, $user),
'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited'),
@@ -5270,7 +5311,7 @@ function phpbb_convert_30_dbms_to_31($dbms)
// true for mysqli class.
// However, per the docblock any valid 3.1 driver name should be
// recognized by this function, and have priority over 3.0 dbms.
- if (class_exists('phpbb\db\driver\\' . $dbms))
+ if (strpos($dbms, 'phpbb\db\driver') === false && class_exists('phpbb\db\driver\\' . $dbms))
{
return 'phpbb\db\driver\\' . $dbms;
}
@@ -5298,3 +5339,42 @@ function phpbb_convert_30_dbms_to_31($dbms)
throw new \RuntimeException("You have specified an invalid dbms driver: $dbms");
}
+
+/**
+* Get the board contact details (e.g. for emails)
+*
+* @param \phpbb\config\config $config
+* @param string $phpEx
+* @return string
+*/
+function phpbb_get_board_contact(\phpbb\config\config $config, $phpEx)
+{
+ if ($config['contact_admin_form_enable'])
+ {
+ return generate_board_url() . '/memberlist.' . $phpEx . '?mode=contactadmin';
+ }
+ else
+ {
+ return $config['board_contact'];
+ }
+}
+
+/**
+* Get a clickable board contact details link
+*
+* @param \phpbb\config\config $config
+* @param string $phpbb_root_path
+* @param string $phpEx
+* @return string
+*/
+function phpbb_get_board_contact_link(\phpbb\config\config $config, $phpbb_root_path, $phpEx)
+{
+ if ($config['contact_admin_form_enable'])
+ {
+ return append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contactadmin');
+ }
+ else
+ {
+ return 'mailto:' . htmlspecialchars($config['board_contact']);
+ }
+}
diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php
index 373eb57934..8453da6e6e 100644
--- a/phpBB/includes/functions_acp.php
+++ b/phpBB/includes/functions_acp.php
@@ -146,37 +146,10 @@ function adm_page_footer($copyright_html = true)
return;
}
- // Output page creation time
- if (defined('DEBUG'))
- {
- $mtime = explode(' ', microtime());
- $totaltime = $mtime[0] + $mtime[1] - $starttime;
-
- if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG') && method_exists($db, 'sql_report'))
- {
- $db->sql_report('display');
- }
-
- $debug_output = sprintf('Time : %.3fs | ' . $db->sql_num_queries() . ' Queries | GZIP : ' . (($config['gzip_compress']) ? 'On' : 'Off') . (($user->load) ? ' | Load : ' . $user->load : ''), $totaltime);
-
- if ($auth->acl_get('a_') && defined('DEBUG'))
- {
- if (function_exists('memory_get_peak_usage'))
- {
- if ($memory_usage = memory_get_peak_usage())
- {
- $memory_usage = get_formatted_filesize($memory_usage);
-
- $debug_output .= ' | Peak Memory Usage: ' . $memory_usage;
- }
- }
-
- $debug_output .= ' | <a href="' . build_url() . '&amp;explain=1">Explain</a>';
- }
- }
+ phpbb_check_and_display_sql_report($request, $auth, $db);
$template->assign_vars(array(
- 'DEBUG_OUTPUT' => (defined('DEBUG')) ? $debug_output : '',
+ 'DEBUG_OUTPUT' => phpbb_generate_debug_output($db, $config, $auth, $user),
'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
'S_COPYRIGHT_HTML' => $copyright_html,
'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Limited'),
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index f988d009ad..72fca905e0 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -1401,7 +1401,7 @@ function get_username_string($mode, $user_id, $username, $username_colour = '',
// no break;
}
-
+
if (!isset($username_string))
{
if (($mode == 'full' && !$profile_url) || $mode == 'no_profile')
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index ea5ff08c01..4606a9f7ca 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -497,10 +497,15 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$l_post_click_count = ($row['forum_type'] == FORUM_LINK) ? 'CLICKS' : 'POSTS';
$post_click_count = ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? $row['forum_posts'] : '';
- $s_subforums_list = array();
+ $s_subforums_list = $subforums_row = array();
foreach ($subforums_list as $subforum)
{
$s_subforums_list[] = '<a href="' . $subforum['link'] . '" class="subforum ' . (($subforum['unread']) ? 'unread' : 'read') . '" title="' . (($subforum['unread']) ? $user->lang['UNREAD_POSTS'] : $user->lang['NO_UNREAD_POSTS']) . '">' . $subforum['name'] . '</a>';
+ $subforums_row[] = array(
+ 'U_SUBFORUM' => $subforum['link'],
+ 'SUBFORUM_NAME' => $subforum['name'],
+ 'S_UNREAD' => $subforum['unread'],
+ );
}
$s_subforums_list = (string) implode($user->lang['COMMA_SEPARATOR'], $s_subforums_list);
$catless = ($row['parent_id'] == $root_data['forum_id']) ? true : false;
@@ -572,22 +577,41 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
* @event core.display_forums_modify_template_vars
* @var array forum_row Template data of the forum
* @var array row The data of the forum
+ * @var array subforums_row Template data of subforums
* @since 3.1.0-a1
+ * @change 3.1.0-b5 Added var subforums_row
*/
- $vars = array('forum_row', 'row');
+ $vars = array('forum_row', 'row', 'subforums_row');
extract($phpbb_dispatcher->trigger_event('core.display_forums_modify_template_vars', compact($vars)));
$template->assign_block_vars('forumrow', $forum_row);
// Assign subforums loop for style authors
- foreach ($subforums_list as $subforum)
- {
- $template->assign_block_vars('forumrow.subforum', array(
- 'U_SUBFORUM' => $subforum['link'],
- 'SUBFORUM_NAME' => $subforum['name'],
- 'S_UNREAD' => $subforum['unread'])
- );
- }
+ $template->assign_block_vars_array('forumrow.subforum', $subforums_row);
+
+ /**
+ * Modify and/or assign additional template data for the forum
+ * after forumrow loop has been assigned. This can be used
+ * to create additional forumrow subloops in extensions.
+ *
+ * This event is triggered once per forum
+ *
+ * @event core.display_forums_add_template_data
+ * @var array forum_row Template data of the forum
+ * @var array row The data of the forum
+ * @var array subforums_list The data of subforums
+ * @var array subforums_row Template data of subforums
+ * @var bool catless The flag indicating whether a forum has a parent category
+ * @since 3.1.0-b5
+ */
+ $vars = array(
+ 'forum_row',
+ 'row',
+ 'subforums_list',
+ 'subforums_row',
+ 'catless',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.display_forums_add_template_data', compact($vars)));
$last_catless = $catless;
}
@@ -1157,7 +1181,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
$u_url .= ($mode == 'forum') ? '&amp;f' : '&amp;f=' . $forum_id . '&amp;t';
$is_watching = 0;
- // Is user watching this thread?
+ // Is user watching this topic?
if ($user_id != ANONYMOUS)
{
$can_watch = true;
@@ -1347,7 +1371,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id,
*/
function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src)
{
- global $ranks, $config, $phpbb_root_path;
+ global $ranks, $config, $phpbb_root_path, $phpbb_path_helper;
if (empty($ranks))
{
@@ -1358,8 +1382,8 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank
if (!empty($user_rank))
{
$rank_title = (isset($ranks['special'][$user_rank]['rank_title'])) ? $ranks['special'][$user_rank]['rank_title'] : '';
- $rank_img = (!empty($ranks['special'][$user_rank]['rank_image'])) ? '<img src="' . $phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] . '" alt="' . $ranks['special'][$user_rank]['rank_title'] . '" title="' . $ranks['special'][$user_rank]['rank_title'] . '" />' : '';
- $rank_img_src = (!empty($ranks['special'][$user_rank]['rank_image'])) ? $phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] : '';
+ $rank_img_src = (!empty($ranks['special'][$user_rank]['rank_image'])) ? $phpbb_path_helper->update_web_root_path($phpbb_root_path . $config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image']) : '';
+ $rank_img = (!empty($ranks['special'][$user_rank]['rank_image'])) ? '<img src="' . $rank_img_src . '" alt="' . $ranks['special'][$user_rank]['rank_title'] . '" title="' . $ranks['special'][$user_rank]['rank_title'] . '" />' : '';
}
else if ($user_posts !== false)
{
@@ -1370,8 +1394,8 @@ function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank
if ($user_posts >= $rank['rank_min'])
{
$rank_title = $rank['rank_title'];
- $rank_img = (!empty($rank['rank_image'])) ? '<img src="' . $phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : '';
- $rank_img_src = (!empty($rank['rank_image'])) ? $phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image'] : '';
+ $rank_img_src = (!empty($rank['rank_image'])) ? $phpbb_path_helper->update_web_root_path($phpbb_root_path . $config['ranks_path'] . '/' . $rank['rank_image']) : '';
+ $rank_img = (!empty($rank['rank_image'])) ? '<img src="' . $rank_img_src . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : '';
break;
}
}
diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php
index 94eef89c05..c640865212 100644
--- a/phpBB/includes/functions_upload.php
+++ b/phpBB/includes/functions_upload.php
@@ -1051,7 +1051,7 @@ class fileupload
*/
static public function image_types()
{
- return array(
+ $result = array(
IMAGETYPE_GIF => array('gif'),
IMAGETYPE_JPEG => array('jpg', 'jpeg'),
IMAGETYPE_PNG => array('png'),
@@ -1064,10 +1064,16 @@ class fileupload
IMAGETYPE_JP2 => array('jpg', 'jpeg'),
IMAGETYPE_JPX => array('jpg', 'jpeg'),
IMAGETYPE_JB2 => array('jpg', 'jpeg'),
- IMAGETYPE_SWC => array('swc'),
IMAGETYPE_IFF => array('iff'),
IMAGETYPE_WBMP => array('wbmp'),
IMAGETYPE_XBM => array('xbm'),
);
+
+ if (defined('IMAGETYPE_SWC'))
+ {
+ $result[IMAGETYPE_SWC] = array('swc');
+ }
+
+ return $result;
}
}
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 3dcb32350e..d728ed7d78 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -184,7 +184,6 @@ function user_add($user_row, $cp_data = false)
'username' => $user_row['username'],
'username_clean' => $username_clean,
'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '',
- 'user_pass_convert' => 0,
'user_email' => strtolower($user_row['user_email']),
'user_email_hash' => phpbb_email_hash($user_row['user_email']),
'group_id' => $user_row['group_id'],
@@ -1746,25 +1745,21 @@ function validate_password($password)
}
/**
-* Check to see if email address is banned or already present in the DB
+* Check to see if email address is a valid address and contains a MX record
*
* @param string $email The email to check
-* @param string $allowed_email An allowed email, default being $user->data['user_email']
*
* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
*/
-function validate_email($email, $allowed_email = false)
+function phpbb_validate_email($email, $config = null)
{
- global $config, $db, $user;
-
- $email = strtolower($email);
- $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email);
-
- if ($allowed_email == $email)
+ if ($config === null)
{
- return false;
+ global $config;
}
+ $email = strtolower($email);
+
if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email))
{
return 'EMAIL_INVALID';
@@ -1782,6 +1777,35 @@ function validate_email($email, $allowed_email = false)
}
}
+ return false;
+}
+
+/**
+* Check to see if email address is banned or already present in the DB
+*
+* @param string $email The email to check
+* @param string $allowed_email An allowed email, default being $user->data['user_email']
+*
+* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended)
+*/
+function validate_user_email($email, $allowed_email = false)
+{
+ global $config, $db, $user;
+
+ $email = strtolower($email);
+ $allowed_email = ($allowed_email === false) ? strtolower($user->data['user_email']) : strtolower($allowed_email);
+
+ if ($allowed_email == $email)
+ {
+ return false;
+ }
+
+ $validate_email = phpbb_validate_email($email, $config);
+ if ($validate_email)
+ {
+ return $validate_email;
+ }
+
if (($ban_reason = $user->check_ban(false, false, $email, true)) !== false)
{
return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason;
diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php
index 8d2d70bd3b..e63888e70e 100644
--- a/phpBB/includes/mcp/mcp_forum.php
+++ b/phpBB/includes/mcp/mcp_forum.php
@@ -378,14 +378,22 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
return;
}
- $topic_data = get_topic_data(array($to_topic_id), 'm_merge');
+ $sync_topics = array_merge($topic_ids, array($to_topic_id));
- if (!sizeof($topic_data))
+ $topic_data = get_topic_data($sync_topics, 'm_merge');
+
+ if (!sizeof($topic_data) || empty($topic_data[$to_topic_id]))
{
$template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']);
return;
}
+ $sync_forums = array();
+ foreach ($topic_data as $data)
+ {
+ $sync_forums[$data['forum_id']] = $data['forum_id'];
+ }
+
$topic_data = $topic_data[$to_topic_id];
$post_id_list = request_var('post_id_list', array(0));
@@ -436,7 +444,7 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
{
$to_forum_id = $topic_data['forum_id'];
- move_posts($post_id_list, $to_topic_id);
+ move_posts($post_id_list, $to_topic_id, false);
add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']);
// Message and return links
@@ -453,6 +461,12 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
// Update the bookmarks table.
phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_ids, $to_topic_id);
+ // Re-sync the topics and forums because the auto-sync was deactivated in the call of move_posts()
+ sync('topic_reported', 'topic_id', $sync_topics);
+ sync('topic_attachment', 'topic_id', $sync_topics);
+ sync('topic', 'topic_id', $sync_topics, true);
+ sync('forum', 'forum_id', $sync_forums, true, true);
+
// Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
$redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index 5dd39dbf0f..e2ca3a8752 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -655,7 +655,7 @@ class mcp_queue
if (!$post_data['topic_posts_approved'])
{
$phpbb_notifications->delete_notifications('topic_in_queue', $post_data['topic_id']);
-
+
if ($post_data['post_visibility'] == ITEM_UNAPPROVED)
{
$phpbb_notifications->add_notifications(array('topic'), $post_data);
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 51802f1e4d..f8ce8aae7b 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -592,14 +592,22 @@ function merge_posts($topic_id, $to_topic_id)
return;
}
- $topic_data = get_topic_data(array($to_topic_id), 'm_merge');
+ $sync_topics = array($topic_id, $to_topic_id);
- if (!sizeof($topic_data))
+ $topic_data = get_topic_data($sync_topics, 'm_merge');
+
+ if (!sizeof($topic_data) || empty($topic_data[$to_topic_id]))
{
$template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']);
return;
}
+ $sync_forums = array();
+ foreach ($topic_data as $data)
+ {
+ $sync_forums[$data['forum_id']] = $data['forum_id'];
+ }
+
$topic_data = $topic_data[$to_topic_id];
$post_id_list = request_var('post_id_list', array(0));
@@ -634,7 +642,7 @@ function merge_posts($topic_id, $to_topic_id)
{
$to_forum_id = $topic_data['forum_id'];
- move_posts($post_id_list, $to_topic_id);
+ move_posts($post_id_list, $to_topic_id, false);
add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']);
// Message and return links
@@ -642,7 +650,7 @@ function merge_posts($topic_id, $to_topic_id)
// Does the original topic still exist? If yes, link back to it
$sql = 'SELECT forum_id
- FROM ' . TOPICS_TABLE . '
+ FROM ' . POSTS_TABLE . '
WHERE topic_id = ' . $topic_id;
$result = $db->sql_query_limit($sql, 1);
$row = $db->sql_fetchrow($result);
@@ -666,6 +674,12 @@ function merge_posts($topic_id, $to_topic_id)
phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', array($topic_id), $to_topic_id);
}
+ // Re-sync the topics and forums because the auto-sync was deactivated in the call of move_posts()
+ sync('topic_reported', 'topic_id', $sync_topics);
+ sync('topic_attachment', 'topic_id', $sync_topics);
+ sync('topic', 'topic_id', $sync_topics, true);
+ sync('forum', 'forum_id', $sync_forums, true, true);
+
// Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
$redirect = request_var('redirect', "{$phpbb_root_path}viewtopic.$phpEx?f=$to_forum_id&amp;t=$to_topic_id");
diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php
index 06326e57e6..53dec89aad 100644
--- a/phpBB/includes/ucp/ucp_activate.php
+++ b/phpBB/includes/ucp/ucp_activate.php
@@ -78,7 +78,6 @@ class ucp_activate
'user_actkey' => '',
'user_password' => $user_row['user_newpasswd'],
'user_newpasswd' => '',
- 'user_pass_convert' => 0,
'user_login_attempts' => 0,
);
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index c7ed12f4ee..5ba5f1e830 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -66,7 +66,7 @@ class ucp_profile
'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']),
'email' => array(
array('string', false, 6, 60),
- array('email')),
+ array('user_email')),
);
if ($auth->acl_get('u_chgname') && $config['allow_namechange'])
diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php
index cdd5532429..97934fc32d 100644
--- a/phpBB/includes/ucp/ucp_register.php
+++ b/phpBB/includes/ucp/ucp_register.php
@@ -211,7 +211,7 @@ class ucp_register
'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']),
'email' => array(
array('string', false, 6, 60),
- array('email')),
+ array('user_email')),
'tz' => array('timezone'),
'lang' => array('language_iso_name'),
));
diff --git a/phpBB/install/install_main.php b/phpBB/install/install_main.php
index 2f37fc3237..d5874dac83 100644
--- a/phpBB/install/install_main.php
+++ b/phpBB/install/install_main.php
@@ -56,7 +56,7 @@ class install_main extends module
case 'license' :
$title = $lang['GPL'];
- $body = implode("<br/>\n", file('../docs/COPYING'));
+ $body = implode("<br/>\n", file(__DIR__ . '/../docs/LICENSE.txt'));
break;
case 'support' :
diff --git a/phpBB/install/schemas/schema.json b/phpBB/install/schemas/schema.json
index f684fddc25..79f06693a6 100644
--- a/phpBB/install/schemas/schema.json
+++ b/phpBB/install/schemas/schema.json
@@ -3023,10 +3023,6 @@
"TIMESTAMP",
0
],
- "user_pass_convert": [
- "BOOL",
- 0
- ],
"user_email": [
"VCHAR_UNI:100",
""
diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql
index e335c1f9ba..15cd9595c6 100644
--- a/phpBB/install/schemas/schema_data.sql
+++ b/phpBB/install/schemas/schema_data.sql
@@ -82,6 +82,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('confirm_refresh',
INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_attachment_content', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('check_dnsbl', '0');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('chg_passforce', '0');
+INSERT INTO phpbb_config (config_name, config_value) VALUES ('contact_admin_form_enable', '1');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_domain', '');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_name', 'phpbb3');
INSERT INTO phpbb_config (config_name, config_value) VALUES ('cookie_path', '/');
@@ -299,6 +300,12 @@ INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('sessio
INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('upload_dir_size', '0', 1);
INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('warnings_last_gc', '0', 1);
+# Config text
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_uid', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_bitfield', '');
+INSERT INTO phpbb_config_text (config_name, config_value) VALUES ('contact_admin_info_flags', '7');
+
# -- Forum related auth options
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_', 1);
INSERT INTO phpbb_acl_options (auth_option, is_local) VALUES ('f_announce', 1);
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 5e4961c435..638e9907ac 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -111,9 +111,9 @@ $lang = array_merge($lang, array(
'ALLOW_REMOTE_UPLOAD_EXPLAIN' => 'Allow uploading of avatars from another website.',
'ALLOW_UPLOAD' => 'Enable avatar uploading',
'AVATAR_GALLERY_PATH' => 'Avatar gallery path',
- 'AVATAR_GALLERY_PATH_EXPLAIN' => 'Path under your phpBB root directory for pre-loaded images, e.g. <samp>images/avatars/gallery</samp>.',
+ 'AVATAR_GALLERY_PATH_EXPLAIN' => 'Path under your phpBB root directory for pre-loaded images, e.g. <samp>images/avatars/gallery</samp>.<br />Double dots like <samp>../</samp> will be stripped from the path for security reasons.',
'AVATAR_STORAGE_PATH' => 'Avatar storage path',
- 'AVATAR_STORAGE_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/avatars/upload</samp>.<br />Avatar uploading <strong>will not be available</strong> if this path is not writable.',
+ 'AVATAR_STORAGE_PATH_EXPLAIN' => 'Path under your phpBB root directory, e.g. <samp>images/avatars/upload</samp>.<br />Avatar uploading <strong>will not be available</strong> if this path is not writable.<br />Double dots like <samp>../</samp> will be stripped from the path for security reasons.',
'MAX_AVATAR_SIZE' => 'Maximum avatar dimensions',
'MAX_AVATAR_SIZE_EXPLAIN' => 'Width x Height in pixels.',
'MAX_FILESIZE' => 'Maximum avatar file size',
@@ -352,6 +352,19 @@ $lang = array_merge($lang, array(
'SESSION_LENGTH_EXPLAIN' => 'Sessions will expire after this time, in seconds.',
));
+// Contact Settings
+$lang = array_merge($lang, array(
+ 'ACP_CONTACT_SETTINGS_EXPLAIN' => 'Here you can enable and disable the contact page and also add a text that is displayed on the page.',
+
+ 'CONTACT_US_ENABLE' => 'Enable contact page',
+ 'CONTACT_US_ENABLE_EXPLAIN' => 'This page allows users to send emails to board administrators',
+
+ 'CONTACT_US_INFO' => 'Contact information',
+ 'CONTACT_US_INFO_EXPLAIN' => 'The message is displayed on the contact page',
+ 'CONTACT_US_INFO_PREVIEW' => 'Contact page information - Preview',
+ 'CONTACT_US_INFO_UPDATED' => 'Contact page information has been updated.',
+));
+
// Load Settings
$lang = array_merge($lang, array(
'ACP_LOAD_SETTINGS_EXPLAIN' => 'Here you can enable and disable certain board functions to reduce the amount of processing required. On most servers there is no need to disable any functions. However on certain systems or in shared hosting environments it may be beneficial to disable capabilities you do not really need. You can also specify limits for system load and active sessions beyond which the board will go offline.',
@@ -401,7 +414,7 @@ $lang = array_merge($lang, array(
'AUTH_METHOD' => 'Select an authentication method',
'AUTH_PROVIDER_OAUTH_ERROR_ELEMENT_MISSING' => 'Both the key and secret of each enabled OAuth service provider must be provided. Only one was provided for an OAuth service provider.',
- 'AUTH_PROVIDER_OAUTH_EXPLAIN' => 'Each OAuth provider requires a unique secret and key in order to authenticate with the external server.<br />These should be supplied by the OAuth service when you register your website with them and should be entered exactly as provided to you.<br />Any service that does not have both a key and a secret entered here will not be available for use by the forum users.',
+ 'AUTH_PROVIDER_OAUTH_EXPLAIN' => 'Each OAuth provider requires a unique secret and key in order to authenticate with the external server. These should be supplied by the OAuth service when you register your website with them and should be entered exactly as provided to you.<br />Any service that does not have both a key and a secret entered here will not be available for use by the forum users. Also note, that user can still register and login using the DB authentication plug-in.',
'AUTH_PROVIDER_OAUTH_KEY' => 'Key',
'AUTH_PROVIDER_OAUTH_TITLE' => 'OAuth',
'AUTH_PROVIDER_OAUTH_SECRET' => 'Secret',
diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php
index 838a73caed..8470014161 100644
--- a/phpBB/language/en/acp/common.php
+++ b/phpBB/language/en/acp/common.php
@@ -75,6 +75,8 @@ $lang = array_merge($lang, array(
'ACP_CAT_USERS' => 'Users',
'ACP_CLIENT_COMMUNICATION' => 'Client communication',
'ACP_COOKIE_SETTINGS' => 'Cookie settings',
+ 'ACP_CONTACT' => 'Contact page',
+ 'ACP_CONTACT_SETTINGS' => 'Contact page settings',
'ACP_CRITICAL_LOGS' => 'Error log',
'ACP_CUSTOM_PROFILE_FIELDS' => 'Custom profile fields',
@@ -223,14 +225,18 @@ $lang = array_merge($lang, array(
'BACK' => 'Back',
+ 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.',
'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.',
'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run',
+ 'CLI_DESCRIPTION_OPTION_SHELL' => 'Launch the shell.',
+
'COLOUR_SWATCH' => 'Web-safe colour swatch',
'CONFIG_UPDATED' => 'Configuration updated successfully.',
'CRON_LOCK_ERROR' => 'Could not obtain cron lock.',
'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.',
'DEACTIVATE' => 'Deactivate',
'DIRECTORY_DOES_NOT_EXIST' => 'The entered path “%s” does not exist.',
@@ -302,6 +308,8 @@ $lang = array_merge($lang, array(
'SHOW_ALL_OPERATIONS' => 'Show all operations',
+ 'TASKS_NOT_READY' => 'Not ready tasks:',
+ 'TASKS_READY' => 'Ready tasks:',
'TOTAL_SIZE' => 'Total size',
'UCP' => 'User Control Panel',
diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php
index d301086327..9a44337294 100644
--- a/phpBB/language/en/common.php
+++ b/phpBB/language/en/common.php
@@ -171,6 +171,7 @@ $lang = array_merge($lang, array(
'CONNECTION_SUCCESS' => 'Connection was successful!',
'CONTACT' => 'Contact',
'CONTACT_USER' => 'Contact %s',
+ 'CONTACT_US' => 'Contact us',
'COOKIES_DELETED' => 'All board cookies successfully deleted.',
'CURRENT_TIME' => 'It is currently %s',
@@ -669,8 +670,8 @@ $lang = array_merge($lang, array(
'SELECT_ALL_CODE' => 'Select all',
'SELECT_DESTINATION_FORUM' => 'Please select a destination forum',
'SELECT_FORUM' => 'Select a forum',
- 'SEND_EMAIL' => 'Email', // Used for submit buttons
- 'SEND_EMAIL_USER' => 'Email %s',
+ 'SEND_EMAIL' => 'Send email', // Used for submit buttons
+ 'SEND_EMAIL_USER' => 'Send email to %s',
'SEND_PRIVATE_MESSAGE' => 'Send private message',
'SETTINGS' => 'Settings',
'SIGNATURE' => 'Signature',
@@ -733,7 +734,7 @@ $lang = array_merge($lang, array(
'TOO_SHORT_USER_PASSWORD' => 'The password you entered is too short.',
'TOO_SHORT_USERNAME' => 'The username you entered is too short.',
'TOO_SHORT_EMAIL' => 'The email address you entered is too short.',
-
+ 'TOO_SHORT_EMAIL_CONFIRM' => 'The email address confirmation you entered is too short.',
'TOO_SMALL' => 'The value you entered is too small.',
'TOO_SMALL_MAX_RECIPIENTS' => 'The value of <strong>Maximum number of allowed recipients per private message</strong> setting you entered is too small.',
diff --git a/phpBB/language/en/email/contact_admin.txt b/phpBB/language/en/email/contact_admin.txt
new file mode 100644
index 0000000000..c895c4d687
--- /dev/null
+++ b/phpBB/language/en/email/contact_admin.txt
@@ -0,0 +1,23 @@
+
+Hello {TO_USERNAME},
+
+The following is an e-mail sent to you through the administration contact page on "{SITENAME}".
+
+<!-- IF S_IS_REGISTERED -->
+The message has been sent from an account on the site.
+Username: {FROM_USERNAME}
+E-mail address: {FROM_EMAIL_ADDRESS}
+IP Address: {FROM_IP_ADDRESS}
+Profile: {U_FROM_PROFILE}
+<!-- ELSE -->
+The message was sent from a guest who specified the following contact information:
+Name: {FROM_USERNAME}
+E-mail address: {FROM_EMAIL_ADDRESS}
+IP Address: {FROM_IP_ADDRESS}
+<!-- ENDIF -->
+
+
+Message sent to you follows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+{MESSAGE}
diff --git a/phpBB/language/en/memberlist.php b/phpBB/language/en/memberlist.php
index 7b6838e6d9..d900ababd1 100644
--- a/phpBB/language/en/memberlist.php
+++ b/phpBB/language/en/memberlist.php
@@ -49,6 +49,8 @@ $lang = array_merge($lang, array(
'BEFORE' => 'Before',
'CC_EMAIL' => 'Send a copy of this email to yourself.',
+ 'CONTACT_USER' => 'Contact',
+ 'CONTACT_ADMIN' => 'Contact a Board Administrator',
'DEST_LANG' => 'Language',
'DEST_LANG_EXPLAIN' => 'Select an appropriate language (if available) for the recipient of this message.',
@@ -61,6 +63,8 @@ $lang = array_merge($lang, array(
'EMPTY_MESSAGE_EMAIL' => 'You must enter a message to be emailed.',
'EMPTY_MESSAGE_IM' => 'You must enter a message to be send.',
'EMPTY_NAME_EMAIL' => 'You must enter the real name of the recipient.',
+ 'EMPTY_SENDER_EMAIL' => 'You must provide a valid email address.',
+ 'EMPTY_SENDER_NAME' => 'You must provide a name.',
'EMPTY_SUBJECT_EMAIL' => 'You must specify a subject for the email.',
'EQUAL_TO' => 'Equal to',
@@ -98,6 +102,8 @@ $lang = array_merge($lang, array(
'MORE_THAN' => 'More than',
+ 'NO_CONTACT_FORM' => 'The board administrator contact form has been disabled.',
+ 'NO_CONTACT_PAGE' => 'The board administrator contact page has been disabled.',
'NO_EMAIL' => 'You are not permitted to send email to this user.',
'NO_VIEW_USERS' => 'You are not authorised to view the member list or profiles.',
@@ -113,6 +119,8 @@ $lang = array_merge($lang, array(
'SELECT_MARKED' => 'Select marked',
'SELECT_SORT_METHOD' => 'Select sort method',
+ 'SENDER_EMAIL_ADDRESS' => 'Your email address',
+ 'SENDER_NAME' => 'Your name',
'SEND_ICQ_MESSAGE' => 'Send ICQ message',
'SEND_IM' => 'Instant messaging',
'SEND_JABBER_MESSAGE' => 'Send Jabber message',
diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php
index 187b4b1cd9..4eb6d79272 100644
--- a/phpBB/memberlist.php
+++ b/phpBB/memberlist.php
@@ -20,6 +20,14 @@ $phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
+$mode = request_var('mode', '');
+
+if ($mode === 'contactadmin')
+{
+ define('SKIP_CHECK_BAN', true);
+ define('SKIP_CHECK_DISABLED', true);
+}
+
// Start session management
$user->session_begin();
$auth->acl($user->data);
@@ -29,7 +37,6 @@ $user->setup(array('memberlist', 'groups'));
$template->assign_var('S_IN_MEMBERLIST', true);
// Grab data
-$mode = request_var('mode', '');
$action = request_var('action', '');
$user_id = request_var('u', ANONYMOUS);
$username = request_var('un', '', true);
@@ -44,7 +51,7 @@ if ($mode == 'leaders')
}
// Check our mode...
-if (!in_array($mode, array('', 'group', 'viewprofile', 'email', 'contact', 'searchuser', 'team', 'livesearch')))
+if (!in_array($mode, array('', 'group', 'viewprofile', 'email', 'contact', 'contactadmin', 'searchuser', 'team', 'livesearch')))
{
trigger_error('NO_MODE');
}
@@ -52,6 +59,7 @@ if (!in_array($mode, array('', 'group', 'viewprofile', 'email', 'contact', 'sear
switch ($mode)
{
case 'email':
+ case 'contactadmin':
break;
case 'livesearch':
@@ -386,7 +394,7 @@ switch ($mode)
$messenger->set_addresses($row);
$messenger->assign_vars(array(
- 'BOARD_CONTACT' => $config['board_contact'],
+ 'BOARD_CONTACT' => phpbb_get_board_contact($config, $phpEx),
'FROM_USERNAME' => htmlspecialchars_decode($user->data['username']),
'TO_USERNAME' => htmlspecialchars_decode($row['username']),
'MESSAGE' => htmlspecialchars_decode($message))
@@ -660,6 +668,7 @@ switch ($mode)
'POSTS_IN_QUEUE'=> $member['posts_in_queue'],
'PM_IMG' => $user->img('icon_contact_pm', $user->lang['SEND_PRIVATE_MESSAGE']),
+ 'L_SEND_EMAIL_USER' => $user->lang('SEND_EMAIL_USER', $member['username']),
'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['EMAIL']),
'JABBER_IMG' => $user->img('icon_contact_jabber', $user->lang['JABBER']),
'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']),
@@ -736,265 +745,50 @@ switch ($mode)
break;
+ case 'contactadmin':
case 'email':
-
- // Send an email
- $page_title = $user->lang['SEND_EMAIL'];
- $template_html = 'memberlist_email.html';
-
- add_form_key('memberlist_email');
-
- if (!$config['email_enable'])
- {
- trigger_error('EMAIL_DISABLED');
- }
-
- if (!$auth->acl_get('u_sendemail'))
- {
- trigger_error('NO_EMAIL');
- }
-
- // Are we trying to abuse the facility?
- if (time() - $user->data['user_emailtime'] < $config['flood_interval'])
+ if (!class_exists('messenger'))
{
- trigger_error('FLOOD_EMAIL_LIMIT');
+ include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
}
- // Determine action...
- $user_id = request_var('u', 0);
- $topic_id = request_var('t', 0);
+ $user_id = request_var('u', 0);
+ $topic_id = request_var('t', 0);
- // Send email to user...
if ($user_id)
{
- if ($user_id == ANONYMOUS || !$config['board_email_form'])
- {
- trigger_error('NO_EMAIL');
- }
-
- // Get the appropriate username, etc.
- $sql = 'SELECT username, user_email, user_allow_viewemail, user_lang, user_jabber, user_notify_type
- FROM ' . USERS_TABLE . "
- WHERE user_id = $user_id
- AND user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_USER');
- }
-
- // Can we send email to this user?
- if (!$row['user_allow_viewemail'] && !$auth->acl_get('a_user'))
- {
- trigger_error('NO_EMAIL');
- }
+ $form_name = 'user';
}
else if ($topic_id)
{
- // Send topic heads-up to email address
- $sql = 'SELECT forum_id, topic_title
- FROM ' . TOPICS_TABLE . "
- WHERE topic_id = $topic_id";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_TOPIC');
- }
-
- if ($row['forum_id'])
- {
- if (!$auth->acl_get('f_read', $row['forum_id']))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- if (!$auth->acl_get('f_email', $row['forum_id']))
- {
- trigger_error('NO_EMAIL');
- }
- }
- else
- {
- // If global announcement, we need to check if the user is able to at least read and email in one forum...
- if (!$auth->acl_getf_global('f_read'))
- {
- trigger_error('SORRY_AUTH_READ');
- }
-
- if (!$auth->acl_getf_global('f_email'))
- {
- trigger_error('NO_EMAIL');
- }
- }
+ $form_name = 'topic';
+ }
+ else if ($mode === 'contactadmin')
+ {
+ $form_name = 'admin';
}
else
{
trigger_error('NO_EMAIL');
}
+ $form = $phpbb_container->get('message.form.' . $form_name);
- $error = array();
-
- $name = utf8_normalize_nfc(request_var('name', '', true));
- $email = request_var('email', '');
- $email_lang = request_var('lang', $config['default_lang']);
- $subject = utf8_normalize_nfc(request_var('subject', '', true));
- $message = utf8_normalize_nfc(request_var('message', '', true));
- $cc = (isset($_POST['cc_email'])) ? true : false;
- $submit = (isset($_POST['submit'])) ? true : false;
-
- if ($submit)
+ $form->bind($request);
+ $error = $form->check_allow();
+ if ($error)
{
- if (!check_form_key('memberlist_email'))
- {
- $error[] = 'FORM_INVALID';
- }
- if ($user_id)
- {
- if (!$subject)
- {
- $error[] = $user->lang['EMPTY_SUBJECT_EMAIL'];
- }
-
- if (!$message)
- {
- $error[] = $user->lang['EMPTY_MESSAGE_EMAIL'];
- }
-
- $name = $row['username'];
- $email_lang = $row['user_lang'];
- $email = $row['user_email'];
- }
- else
- {
- if (!$email || !preg_match('/^' . get_preg_expression('email') . '$/i', $email))
- {
- $error[] = $user->lang['EMPTY_ADDRESS_EMAIL'];
- }
-
- if (!$name)
- {
- $error[] = $user->lang['EMPTY_NAME_EMAIL'];
- }
- }
-
- if (!sizeof($error))
- {
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_emailtime = ' . time() . '
- WHERE user_id = ' . $user->data['user_id'];
- $result = $db->sql_query($sql);
-
- include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
- $messenger = new messenger(false);
- $email_tpl = ($user_id) ? 'profile_send_email' : 'email_notify';
-
- $mail_to_users = array();
-
- $mail_to_users[] = array(
- 'email_lang' => $email_lang,
- 'email' => $email,
- 'name' => $name,
- 'username' => ($user_id) ? $row['username'] : '',
- 'to_name' => $name,
- 'user_jabber' => ($user_id) ? $row['user_jabber'] : '',
- 'user_notify_type' => ($user_id) ? $row['user_notify_type'] : NOTIFY_EMAIL,
- 'topic_title' => (!$user_id) ? $row['topic_title'] : '',
- 'forum_id' => (!$user_id) ? $row['forum_id'] : 0,
- );
-
- // Ok, now the same email if CC specified, but without exposing the users email address
- if ($cc)
- {
- $mail_to_users[] = array(
- 'email_lang' => $user->data['user_lang'],
- 'email' => $user->data['user_email'],
- 'name' => $user->data['username'],
- 'username' => $user->data['username'],
- 'to_name' => $name,
- 'user_jabber' => $user->data['user_jabber'],
- 'user_notify_type' => ($user_id) ? $user->data['user_notify_type'] : NOTIFY_EMAIL,
- 'topic_title' => (!$user_id) ? $row['topic_title'] : '',
- 'forum_id' => (!$user_id) ? $row['forum_id'] : 0,
- );
- }
-
- foreach ($mail_to_users as $row)
- {
- $messenger->template($email_tpl, $row['email_lang']);
- $messenger->replyto($user->data['user_email']);
- $messenger->to($row['email'], $row['name']);
-
- if ($user_id)
- {
- $messenger->subject(htmlspecialchars_decode($subject));
- $messenger->im($row['user_jabber'], $row['username']);
- $notify_type = $row['user_notify_type'];
- }
- else
- {
- $notify_type = NOTIFY_EMAIL;
- }
-
- $messenger->anti_abuse_headers($config, $user);
-
- $messenger->assign_vars(array(
- 'BOARD_CONTACT' => $config['board_contact'],
- 'TO_USERNAME' => htmlspecialchars_decode($row['to_name']),
- 'FROM_USERNAME' => htmlspecialchars_decode($user->data['username']),
- 'MESSAGE' => htmlspecialchars_decode($message))
- );
-
- if ($topic_id)
- {
- $messenger->assign_vars(array(
- 'TOPIC_NAME' => htmlspecialchars_decode($row['topic_title']),
- 'U_TOPIC' => generate_board_url() . "/viewtopic.$phpEx?f=" . $row['forum_id'] . "&t=$topic_id")
- );
- }
-
- $messenger->send($notify_type);
- }
-
- meta_refresh(3, append_sid("{$phpbb_root_path}index.$phpEx"));
- $message = ($user_id) ? sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.$phpEx") . '">', '</a>') : sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", "f={$row['forum_id']}&amp;t=$topic_id") . '">', '</a>');
- trigger_error($user->lang['EMAIL_SENT'] . '<br /><br />' . $message);
- }
+ trigger_error($error);
}
- if ($user_id)
+ if ($request->is_set_post('submit'))
{
- $template->assign_vars(array(
- 'S_SEND_USER' => true,
- 'L_SEND_EMAIL_USER' => $user->lang('SEND_EMAIL_USER', $row['username']),
-
- 'L_EMAIL_BODY_EXPLAIN' => $user->lang['EMAIL_BODY_EXPLAIN'],
- 'S_POST_ACTION' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=email&amp;u=' . $user_id))
- );
- }
- else
- {
- $template->assign_vars(array(
- 'EMAIL' => $email,
- 'NAME' => $name,
- 'S_LANG_OPTIONS' => language_select($email_lang),
-
- 'L_EMAIL_BODY_EXPLAIN' => $user->lang['EMAIL_TOPIC_EXPLAIN'],
- 'S_POST_ACTION' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=email&amp;t=' . $topic_id))
- );
+ $messenger = new messenger(false);
+ $form->submit($messenger);
}
- $template->assign_vars(array(
- 'ERROR_MESSAGE' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'SUBJECT' => $subject,
- 'MESSAGE' => $message,
- )
- );
+ $page_title = $form->get_page_title();
+ $template_html = $form->get_template_file();
+ $form->render($template);
break;
diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php
index 3be1d3873f..142a47247f 100644
--- a/phpBB/phpbb/auth/provider/db.php
+++ b/phpBB/phpbb/auth/provider/db.php
@@ -78,7 +78,7 @@ class db extends \phpbb\auth\provider\base
$username_clean = utf8_clean_string($username);
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts
FROM ' . USERS_TABLE . "
WHERE username_clean = '" . $this->db->sql_escape($username_clean) . "'";
$result = $this->db->sql_query($sql);
@@ -170,72 +170,8 @@ class db extends \phpbb\auth\provider\base
}
- // If the password convert flag is set we need to convert it
- if ($row['user_pass_convert'])
- {
- // enable super globals to get literal value
- // this is needed to prevent unicode normalization
- $super_globals_disabled = $this->request->super_globals_disabled();
- if ($super_globals_disabled)
- {
- $this->request->enable_super_globals();
- }
-
- // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
- $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
- $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
- $password_new_format = $this->request->variable('password', '', true);
-
- if ($super_globals_disabled)
- {
- $this->request->disable_super_globals();
- }
-
- if ($password == $password_new_format)
- {
- if (!function_exists('utf8_to_cp1252'))
- {
- include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext);
- }
-
- // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
- // plain md5 support left in for conversions from other systems.
- if ((strlen($row['user_password']) == 34 && ($this->passwords_manager->check(md5($password_old_format), $row['user_password']) || $this->passwords_manager->check(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
- || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
- {
- $hash = $this->passwords_manager->hash($password_new_format);
-
- // Update the password in the users table to the new format and remove user_pass_convert flag
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_password = \'' . $this->db->sql_escape($hash) . '\',
- user_pass_convert = 0
- WHERE user_id = ' . $row['user_id'];
- $this->db->sql_query($sql);
-
- $row['user_pass_convert'] = 0;
- $row['user_password'] = $hash;
- }
- else
- {
- // Although we weren't able to convert this password we have to
- // increase login attempt count to make sure this cannot be exploited
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . (int) $row['user_id'] . '
- AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
- $this->db->sql_query($sql);
-
- return array(
- 'status' => LOGIN_ERROR_PASSWORD_CONVERT,
- 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT',
- 'user_row' => $row,
- );
- }
- }
- }
-
// Check password ...
- if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password']))
+ if ($this->passwords_manager->check($password, $row['user_password']))
{
// Check for old password hash...
if ($this->passwords_manager->convert_flag || strlen($row['user_password']) == 32)
@@ -244,8 +180,7 @@ class db extends \phpbb\auth\provider\base
// Update the password in the users table to the new format
$sql = 'UPDATE ' . USERS_TABLE . "
- SET user_password = '" . $this->db->sql_escape($hash) . "',
- user_pass_convert = 0
+ SET user_password = '" . $this->db->sql_escape($hash) . "'
WHERE user_id = {$row['user_id']}";
$this->db->sql_query($sql);
diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php
index 2230ce15d1..07430bb42a 100644
--- a/phpBB/phpbb/auth/provider/oauth/oauth.php
+++ b/phpBB/phpbb/auth/provider/oauth/oauth.php
@@ -215,7 +215,7 @@ class oauth extends \phpbb\auth\provider\base
}
// Retrieve the user's account
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts
FROM ' . $this->users_table . '
WHERE user_id = ' . (int) $row['user_id'];
$result = $this->db->sql_query($sql);
diff --git a/phpBB/phpbb/auth/provider_collection.php b/phpBB/phpbb/auth/provider_collection.php
new file mode 100644
index 0000000000..27a3f24564
--- /dev/null
+++ b/phpBB/phpbb/auth/provider_collection.php
@@ -0,0 +1,65 @@
+<?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\auth;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+* Collection of auth providers to be configured at container compile time.
+*/
+class provider_collection extends \phpbb\di\service_collection
+{
+ /** @var \phpbb\config\config phpBB Config */
+ protected $config;
+
+ /**
+ * Constructor
+ *
+ * @param ContainerInterface $container Container object
+ * @param \phpbb\config\config $config phpBB config
+ */
+ public function __construct($container, \phpbb\config\config $config)
+ {
+ $this->container = $container;
+ $this->config = $config;
+ }
+
+ /**
+ * Get an auth provider.
+ *
+ * @return object Default auth provider selected in config if it
+ * does exist. Otherwise the standard db auth
+ * provider.
+ * @throws \RuntimeException If neither the auth provider that
+ * is specified by the phpBB config nor the db
+ * auth provider exist. The db auth provider
+ * should always exist in a phpBB installation.
+ */
+ public function get_provider()
+ {
+ if ($this->offsetExists('auth.provider.' . basename(trim($this->config['auth_method']))))
+ {
+ return $this->offsetGet('auth.provider.' . basename(trim($this->config['auth_method'])));
+ }
+ // Revert to db auth provider if selected method does not exist
+ elseif ($this->offsetExists('auth.provider.db'))
+ {
+ return $this->offsetGet('auth.provider.db');
+ }
+ else
+ {
+ throw new \RuntimeException(sprintf('The authentication provider for the authentication method "%1$s" does not exist. It was not possible to recover from this by reverting to the database authentication provider.', $this->config['auth_method']));
+ }
+ }
+}
diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php
index 34b894c2a7..c4344ee6e8 100644
--- a/phpBB/phpbb/avatar/driver/gravatar.php
+++ b/phpBB/phpbb/avatar/driver/gravatar.php
@@ -81,7 +81,8 @@ class gravatar extends \phpbb\avatar\driver\driver
array(
'email' => array(
array('string', false, 6, 60),
- array('email'))
+ array('email'),
+ ),
)
);
diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php
index c9e6781205..f3acf7cb2c 100644
--- a/phpBB/phpbb/avatar/driver/local.php
+++ b/phpBB/phpbb/avatar/driver/local.php
@@ -131,7 +131,7 @@ class local extends \phpbb\avatar\driver\driver
}
return array(
- 'avatar' => ($category != $user->lang['MAIN']) ? $category . '/' . $file : $file,
+ 'avatar' => ($category != $user->lang['NO_AVATAR_CATEGORY']) ? $category . '/' . $file : $file,
'avatar_width' => $avatar_list[$category][urldecode($file)]['width'],
'avatar_height' => $avatar_list[$category][urldecode($file)]['height'],
);
@@ -179,9 +179,9 @@ class local extends \phpbb\avatar\driver\driver
{
$dims = array(0, 0);
}
- $cat = ($path == $file_path) ? $user->lang['MAIN'] : str_replace("$path/", '', $file_path);
+ $cat = ($path == $file_path) ? $user->lang['NO_AVATAR_CATEGORY'] : str_replace("$path/", '', $file_path);
$avatar_list[$cat][$image] = array(
- 'file' => ($cat != $user->lang['MAIN']) ? rawurlencode($cat) . '/' . rawurlencode($image) : rawurlencode($image),
+ 'file' => ($cat != $user->lang['NO_AVATAR_CATEGORY']) ? rawurlencode($cat) . '/' . rawurlencode($image) : rawurlencode($image),
'filename' => rawurlencode($image),
'name' => ucfirst(str_replace('_', ' ', preg_replace('#^(.*)\..*$#', '\1', $image))),
'width' => $dims[0],
diff --git a/phpBB/phpbb/config/config.php b/phpBB/phpbb/config/config.php
index 8cbe1e1e2d..aaad333006 100644
--- a/phpBB/phpbb/config/config.php
+++ b/phpBB/phpbb/config/config.php
@@ -37,7 +37,7 @@ class config implements \ArrayAccess, \IteratorAggregate, \Countable
/**
* Retrieves an ArrayIterator over the configuration values.
*
- * @return ArrayIterator An iterator over all config data
+ * @return \ArrayIterator An iterator over all config data
*/
public function getIterator()
{
diff --git a/phpBB/phpbb/console/application.php b/phpBB/phpbb/console/application.php
index da2bfbb49a..b1f0635913 100644
--- a/phpBB/phpbb/console/application.php
+++ b/phpBB/phpbb/console/application.php
@@ -13,15 +13,93 @@
namespace phpbb\console;
+use Symfony\Component\Console\Shell;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\TaggedContainerInterface;
class application extends \Symfony\Component\Console\Application
{
- function register_container_commands(TaggedContainerInterface $container, $tag = 'console.command')
+ /**
+ * @var bool Indicates whether or not we are in a shell
+ */
+ protected $in_shell = false;
+
+ /**
+ * @var \phpbb\user User object
+ */
+ protected $user;
+
+ /**
+ * @param string $name The name of the application
+ * @param string $version The version of the application
+ * @param \phpbb\user $user The user which runs the application (used for translation)
+ */
+ public function __construct($name, $version, \phpbb\user $user)
+ {
+ parent::__construct($name, $version);
+
+ $this->user = $user;
+ }
+
+ /**
+ * Gets the help message.
+ *
+ * It's a hack of the default help message to display the --shell
+ * option only for the application and not for all the commands.
+ *
+ * @return string A help message.
+ */
+ public function getHelp()
+ {
+ // If we are already in a shell
+ // we do not want to have the --shell option available
+ if ($this->in_shell)
+ {
+ return parent::getHelp();
+ }
+
+ $this->getDefinition()->addOption(new InputOption(
+ '--shell',
+ '-s',
+ InputOption::VALUE_NONE,
+ $this->user->lang('CLI_DESCRIPTION_OPTION_SHELL')
+ ));
+
+ return parent::getHelp();
+ }
+
+ /**
+ * Register a set of commands from the container
+ *
+ * @param TaggedContainerInterface $container The container
+ * @param string $tag The tag used to register the commands
+ */
+ public function register_container_commands(TaggedContainerInterface $container, $tag = 'console.command')
{
foreach($container->findTaggedServiceIds($tag) as $id => $void)
{
$this->add($container->get($id));
}
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function doRun(InputInterface $input, OutputInterface $output)
+ {
+ // Run a shell if the --shell (or -s) option is set and if no command name is specified
+ // Also, we do not want to have the --shell option available if we are already in a shell
+ if (!$this->in_shell && $this->getCommandName($input) === null && $input->hasParameterOption(array('--shell', '-s')))
+ {
+ $shell = new Shell($this);
+ $this->in_shell = true;
+ $shell->run();
+
+ return 0;
+ }
+
+ return parent::doRun($input, $output);
+ }
}
diff --git a/phpBB/phpbb/console/command/cache/purge.php b/phpBB/phpbb/console/command/cache/purge.php
index 1e2adaeb4d..50953185a4 100644
--- a/phpBB/phpbb/console/command/cache/purge.php
+++ b/phpBB/phpbb/console/command/cache/purge.php
@@ -43,7 +43,6 @@ class purge extends \phpbb\console\command\command
$this->log = $log;
$this->user = $user;
$this->config = $config;
- $this->user->add_lang(array('acp/common'));
parent::__construct();
}
diff --git a/phpBB/phpbb/console/command/cron/cron_list.php b/phpBB/phpbb/console/command/cron/cron_list.php
new file mode 100644
index 0000000000..9db6a23947
--- /dev/null
+++ b/phpBB/phpbb/console/command/cron/cron_list.php
@@ -0,0 +1,90 @@
+<?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\console\command\cron;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class cron_list extends \phpbb\console\command\command
+{
+ /** @var \phpbb\cron\manager */
+ protected $cron_manager;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ public function __construct(\phpbb\cron\manager $cron_manager, \phpbb\user $user)
+ {
+ $this->cron_manager = $cron_manager;
+ $this->user = $user;
+ parent::__construct();
+ }
+
+ protected function configure()
+ {
+ $this
+ ->setName('cron:list')
+ ->setDescription($this->user->lang('CLI_DESCRIPTION_CRON_LIST'))
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $tasks = $this->cron_manager->get_tasks();
+
+ if (empty($tasks))
+ {
+ $output->writeln($this->user->lang('CRON_NO_TASKS'));
+ return;
+ }
+
+ $ready_tasks = array();
+ $not_ready_tasks = array();
+ foreach ($tasks as $task)
+ {
+ if ($task->is_ready())
+ {
+ $ready_tasks[] = $task;
+ }
+ else
+ {
+ $not_ready_tasks[] = $task;
+ }
+ }
+
+ if (!empty($ready_tasks))
+ {
+ $output->writeln('<info>' . $this->user->lang('TASKS_READY') . '</info>');
+ $this->print_tasks_names($ready_tasks, $output);
+ }
+
+ if (!empty($ready_tasks) && !empty($not_ready_tasks))
+ {
+ $output->writeln('');
+ }
+
+ if (!empty($not_ready_tasks))
+ {
+ $output->writeln('<info>' . $this->user->lang('TASKS_NOT_READY') . '</info>');
+ $this->print_tasks_names($not_ready_tasks, $output);
+ }
+ }
+
+ protected function print_tasks_names(array $tasks, OutputInterface $output)
+ {
+ foreach ($tasks as $task)
+ {
+ $output->writeln($task->get_name());
+ }
+ }
+}
diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php
index 0f74664095..2abeaf5268 100644
--- a/phpBB/phpbb/console/command/db/migrate.php
+++ b/phpBB/phpbb/console/command/db/migrate.php
@@ -43,7 +43,7 @@ class migrate extends \phpbb\console\command\command
$this->cache = $cache;
$this->log = $log;
$this->user = $user;
- $this->user->add_lang(array('common', 'acp/common', 'install', 'migrator'));
+ $this->user->add_lang(array('common', 'install', 'migrator'));
parent::__construct();
}
diff --git a/phpBB/phpbb/console/command/dev/migration_tips.php b/phpBB/phpbb/console/command/dev/migration_tips.php
new file mode 100644
index 0000000000..c2f61568ea
--- /dev/null
+++ b/phpBB/phpbb/console/command/dev/migration_tips.php
@@ -0,0 +1,64 @@
+<?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\console\command\dev;
+
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class migration_tips extends \phpbb\console\command\command
+{
+ /** @var \phpbb\extension\manager */
+ protected $extension_manager;
+
+ function __construct(\phpbb\extension\manager $extension_manager)
+ {
+ $this->extension_manager = $extension_manager;
+ parent::__construct();
+ }
+
+ protected function configure()
+ {
+ $this
+ ->setName('dev:migration-tips')
+ ->setDescription('Finds migrations that are not depended on.')
+ ;
+ }
+
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $migrations = $this->extension_manager->get_finder()
+ ->set_extensions(array())
+ ->core_path('phpbb/db/migration/data/')
+ ->get_classes();
+ $tips = $migrations;
+
+ foreach ($migrations as $migration_class)
+ {
+ foreach ($migration_class::depends_on() as $dependency)
+ {
+ $tips_key = array_search($dependency, $tips);
+ if ($tips_key !== false)
+ {
+ unset($tips[$tips_key]);
+ }
+ }
+ }
+
+ $output->writeln("\t\tarray(");
+ foreach ($tips as $migration)
+ {
+ $output->writeln("\t\t\t'{$migration}',");
+ }
+ $output->writeln("\t\t);");
+ }
+}
diff --git a/phpBB/phpbb/controller/provider.php b/phpBB/phpbb/controller/provider.php
index 91f3a07fb1..bd85385a41 100644
--- a/phpBB/phpbb/controller/provider.php
+++ b/phpBB/phpbb/controller/provider.php
@@ -46,10 +46,10 @@ class provider
}
/**
- * @param \phpbb\extension\finder $finder
+ * @param \phpbb\finder $finder
* @return null
*/
- public function find_routing_files(\phpbb\extension\finder $finder)
+ public function find_routing_files(\phpbb\finder $finder)
{
// We hardcode the path to the core config directory
// because the finder cannot find it
diff --git a/phpBB/phpbb/cron/manager.php b/phpBB/phpbb/cron/manager.php
index 1eb8edf033..f04f063228 100644
--- a/phpBB/phpbb/cron/manager.php
+++ b/phpBB/phpbb/cron/manager.php
@@ -122,6 +122,16 @@ class manager
}
/**
+ * Find all tasks and return them.
+ *
+ * @return array List of all tasks.
+ */
+ public function get_tasks()
+ {
+ return $this->tasks;
+ }
+
+ /**
* Wraps a task inside an instance of \phpbb\cron\task\wrapper.
*
* @param \phpbb\cron\task\task $task The task.
diff --git a/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php b/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php
new file mode 100644
index 0000000000..bd682e2f7c
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/contact_admin_acp_module.php
@@ -0,0 +1,27 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class contact_admin_acp_module extends \phpbb\db\migration\migration
+{
+ public function update_data()
+ {
+ return array(
+ array('module.add', array(
+ 'acp',
+ 'ACP_BOARD_CONFIGURATION',
+ array(
+ 'module_basename' => 'acp_contact',
+ 'modes' => array('contact'),
+ ),
+ )),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/contact_admin_form.php b/phpBB/phpbb/db/migration/data/v310/contact_admin_form.php
new file mode 100644
index 0000000000..e255efb99d
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/contact_admin_form.php
@@ -0,0 +1,37 @@
+<?php
+/**
+*
+* @package migration
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\db\migration\data\v310;
+
+class contact_admin_form extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return isset($this->config['contact_admin_form_enable']);
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('config.add', array('contact_admin_form_enable', 1)),
+ array('custom', array(array($this, 'contact_admin_info'))),
+ );
+ }
+
+ public function contact_admin_info()
+ {
+ $text_config = new \phpbb\config\db_text($this->db, $this->table_prefix . 'config_text');
+ $text_config->set_array(array(
+ 'contact_admin_info' => '',
+ 'contact_admin_info_uid' => '',
+ 'contact_admin_info_bitfield' => '',
+ 'contact_admin_info_flags' => OPTION_FLAG_BBCODE + OPTION_FLAG_SMILIES + OPTION_FLAG_LINKS,
+ ));
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php
new file mode 100644
index 0000000000..004d94d8bd
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php
@@ -0,0 +1,85 @@
+<?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\v310;
+
+class passwords_convert_p1 extends \phpbb\db\migration\migration
+{
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\passwords_p2');
+ }
+
+ public function update_data()
+ {
+ return array(
+ array('custom', array(array($this, 'update_passwords'))),
+ );
+ }
+
+ public function update_passwords($start)
+ {
+ // Nothing to do if user_pass_convert column doesn't exist
+ if (!$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_pass_convert'))
+ {
+ return;
+ }
+
+ $start = (int) $start;
+ $limit = 1000;
+ $converted_users = 0;
+
+ $sql = 'SELECT user_password, user_id
+ FROM ' . $this->table_prefix . 'users
+ WHERE user_pass_convert = 1
+ GROUP BY user_id
+ ORDER BY user_id';
+ $result = $this->db->sql_query_limit($sql, $limit, $start);
+
+ $update_users = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $converted_users++;
+
+ $user_id = (int) $row['user_id'];
+ // Only prefix passwords without proper prefix
+ if (!isset($update_users[$user_id]) && !preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $row['user_password']))
+ {
+ // Use $CP$ prefix for passwords that need to
+ // be converted and set pass convert to false.
+ $update_users[$user_id] = array(
+ 'user_password' => '$CP$' . $row['user_password'],
+ 'user_pass_convert' => 0,
+ );
+ }
+ }
+ $this->db->sql_freeresult($result);
+
+ foreach ($update_users as $user_id => $user_data)
+ {
+ $sql = 'UPDATE ' . $this->table_prefix . 'users
+ SET ' . $this->db->sql_build_array('UPDATE', $user_data) . '
+ WHERE user_id = ' . $user_id;
+ $this->sql_query($sql);
+ }
+
+ if ($converted_users < $limit)
+ {
+ // There are no more users to be converted
+ return;
+ }
+
+ // There are still more users to query, return the next start value
+ return $start + $limit;
+ }
+}
diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php
new file mode 100644
index 0000000000..26a99184a6
--- /dev/null
+++ b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php
@@ -0,0 +1,49 @@
+<?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\v310;
+
+class passwords_convert_p2 extends \phpbb\db\migration\migration
+{
+ public function effectively_installed()
+ {
+ return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_pass_convert');
+ }
+
+ static public function depends_on()
+ {
+ return array('\phpbb\db\migration\data\v310\passwords_convert_p1');
+ }
+
+ public function update_schema()
+ {
+ return array(
+ 'drop_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_pass_convert',
+ ),
+ ),
+ );
+ }
+
+ public function revert_schema()
+ {
+ return array(
+ 'add_columns' => array(
+ $this->table_prefix . 'users' => array(
+ 'user_pass_convert' => array('BOOL', 0, 'after' => 'user_passchg'),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 9b9532a7ad..5255c73c1c 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -714,7 +714,7 @@ class migrator
/**
* Load migration data files from a directory
*
- * @param \phpbb\extension\finder $finder
+ * @param \phpbb\finder $finder
* @param string $path Path to migration data files
* @param bool $check_fulfillable If TRUE (default), we will check
* if all of the migrations are fulfillable after loading them.
@@ -723,7 +723,7 @@ class migrator
* with the last call to prevent throwing errors unnecessarily).
* @return array Array of migration names
*/
- public function load_migrations(\phpbb\extension\finder $finder, $path, $check_fulfillable = true)
+ public function load_migrations(\phpbb\finder $finder, $path, $check_fulfillable = true)
{
if (!is_dir($path))
{
diff --git a/phpBB/phpbb/di/service_collection.php b/phpBB/phpbb/di/service_collection.php
index 3a18644891..a8eeeab8bb 100644
--- a/phpBB/phpbb/di/service_collection.php
+++ b/phpBB/phpbb/di/service_collection.php
@@ -21,6 +21,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class service_collection extends \ArrayObject
{
/**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
* Constructor
*
* @param ContainerInterface $container Container object
@@ -31,6 +36,44 @@ class service_collection extends \ArrayObject
}
/**
+ * {@inheritdoc}
+ */
+ public function getIterator()
+ {
+ return new service_collection_iterator($this->container, $this);
+ }
+
+ // Because of a PHP issue we have to redefine offsetExists
+ // (even with a call to the parent):
+ // https://bugs.php.net/bug.php?id=66834
+ // https://bugs.php.net/bug.php?id=67067
+ // But it triggers a sniffer issue that we have to skip
+ // @codingStandardsIgnoreStart
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($index)
+ {
+ return parent::offsetExists($index);
+ }
+ // @codingStandardsIgnoreEnd
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($index)
+ {
+ $task = parent::offsetGet($index);
+ if ($task === null)
+ {
+ $task = $this->container->get($index);
+ $this->offsetSet($index, $task);
+ }
+
+ return $task;
+ }
+
+ /**
* Add a service to the collection
*
* @param string $name The service name
@@ -38,8 +81,6 @@ class service_collection extends \ArrayObject
*/
public function add($name)
{
- $task = $this->container->get($name);
-
- $this->offsetSet($name, $task);
+ $this->offsetSet($name, null);
}
}
diff --git a/phpBB/phpbb/di/service_collection_iterator.php b/phpBB/phpbb/di/service_collection_iterator.php
new file mode 100644
index 0000000000..54aefca1f7
--- /dev/null
+++ b/phpBB/phpbb/di/service_collection_iterator.php
@@ -0,0 +1,87 @@
+<?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\di;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+* Iterator which loads the services when they are requested
+*/
+class service_collection_iterator extends \ArrayIterator
+{
+ /**
+ * @var \Symfony\Component\DependencyInjection\ContainerInterface
+ */
+ protected $container;
+
+ /**
+ * Construct an ArrayIterator for service_collection
+ *
+ * @param ContainerInterface $container Container object
+ * @param array $array The array or object to be iterated on.
+ * @param int $flags Flags to control the behaviour of the ArrayObject object.
+ * @see ArrayObject::setFlags()
+ */
+ public function __construct(ContainerInterface $container, $array = array(), $flags = 0)
+ {
+ parent::__construct($array, $flags);
+ $this->container = $container;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($index)
+ {
+ $task = parent::offsetGet($index);
+ if ($task === null)
+ {
+ $task = $this->container->get($index);
+ $this->offsetSet($index, $task);
+ }
+
+ return $task;
+ }
+
+ // Because of a PHP issue we have to redefine offsetExists
+ // (even with a call to the parent):
+ // https://bugs.php.net/bug.php?id=66834
+ // https://bugs.php.net/bug.php?id=67067
+ // But it triggers a sniffer issue that we have to skip
+ // @codingStandardsIgnoreStart
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($index)
+ {
+ parent::offsetExists($index);
+ }
+ // @codingStandardsIgnoreEnd
+
+ /**
+ * {@inheritdoc}
+ */
+ public function current()
+ {
+ $task = parent::current();
+ if ($task === null)
+ {
+ $name = $this->key();
+ $task = $this->container->get($name);
+ $this->offsetSet($name, $task);
+ }
+
+ return $task;
+ }
+}
diff --git a/phpBB/phpbb/extension/base.php b/phpBB/phpbb/extension/base.php
index eb306aeb72..cbbd7bc622 100644
--- a/phpBB/phpbb/extension/base.php
+++ b/phpBB/phpbb/extension/base.php
@@ -23,7 +23,7 @@ class base implements \phpbb\extension\extension_interface
/** @var ContainerInterface */
protected $container;
- /** @var \phpbb\extension\finder */
+ /** @var \phpbb\finder */
protected $finder;
/** @var \phpbb\db\migrator */
@@ -39,11 +39,11 @@ class base implements \phpbb\extension\extension_interface
* Constructor
*
* @param ContainerInterface $container Container object
- * @param \phpbb\extension\finder $extension_finder
+ * @param \phpbb\finder $extension_finder
* @param string $extension_name Name of this extension (from ext.manager)
* @param string $extension_path Relative path to this extension
*/
- public function __construct(ContainerInterface $container, \phpbb\extension\finder $extension_finder, \phpbb\db\migrator $migrator, $extension_name, $extension_path)
+ public function __construct(ContainerInterface $container, \phpbb\finder $extension_finder, \phpbb\db\migrator $migrator, $extension_name, $extension_path)
{
$this->container = $container;
$this->extension_finder = $extension_finder;
diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php
index cd7289e085..b83bb1b189 100644
--- a/phpBB/phpbb/extension/manager.php
+++ b/phpBB/phpbb/extension/manager.php
@@ -532,12 +532,22 @@ class manager
}
/**
- * Instantiates a \phpbb\extension\finder.
+ * Instantiates a \phpbb\finder.
*
- * @return \phpbb\extension\finder An extension finder instance
+ * @param bool $use_all_available Should we load all extensions, or just enabled ones
+ * @return \phpbb\finder An extension finder instance
*/
- public function get_finder()
+ public function get_finder($use_all_available = false)
{
- return new \phpbb\extension\finder($this, $this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
+ $finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
+ if ($use_all_available)
+ {
+ $finder->set_extensions(array_keys($this->all_available()));
+ }
+ else
+ {
+ $finder->set_extensions(array_keys($this->all_enabled()));
+ }
+ return $finder;
}
}
diff --git a/phpBB/phpbb/extension/finder.php b/phpBB/phpbb/finder.php
index 6f2408094e..28f28825ba 100644
--- a/phpBB/phpbb/extension/finder.php
+++ b/phpBB/phpbb/finder.php
@@ -11,14 +11,14 @@
*
*/
-namespace phpbb\extension;
+namespace phpbb;
/**
-* The extension finder provides a simple way to locate files in active extensions
+* The finder provides a simple way to locate files in the core and a set of extensions
*/
class finder
{
- protected $extension_manager;
+ protected $extensions;
protected $filesystem;
protected $phpbb_root_path;
protected $cache;
@@ -48,9 +48,6 @@ class finder
/**
* Creates a new finder instance with its dependencies
*
- * @param \phpbb\extension\manager $extension_manager An extension manager
- * instance that provides the finder with a list of active
- * extensions and their locations
* @param \phpbb\filesystem $filesystem Filesystem instance
* @param string $phpbb_root_path Path to the phpbb root directory
* @param \phpbb\cache\driver\driver_interface $cache A cache instance or null
@@ -58,9 +55,8 @@ class finder
* @param string $cache_name The name of the cache variable, defaults to
* _ext_finder
*/
- public function __construct(\phpbb\extension\manager $extension_manager, \phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder')
+ public function __construct(\phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder')
{
- $this->extension_manager = $extension_manager;
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
$this->cache = $cache;
@@ -76,15 +72,37 @@ class finder
'extension_prefix' => false,
'extension_directory' => false,
);
+ $this->extensions = array();
$this->cached_queries = ($this->cache) ? $this->cache->get($this->cache_name) : false;
}
/**
+ * Set the array of extensions
+ *
+ * @param array $extensions A list of extensions that should be searched aswell
+ * @param bool $replace_list Should the list be emptied before adding the extensions
+ * @return \phpbb\finder This object for chaining calls
+ */
+ public function set_extensions(array $extensions, $replace_list = true)
+ {
+ if ($replace_list)
+ {
+ $this->extensions = array();
+ }
+
+ foreach ($extensions as $ext_name)
+ {
+ $this->extensions[$ext_name] = $this->phpbb_root_path . 'ext/' . $ext_name . '/';
+ }
+ return $this;
+ }
+
+ /**
* Sets a core path to be searched in addition to extensions
*
* @param string $core_path The path relative to phpbb_root_path
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function core_path($core_path)
{
@@ -100,7 +118,7 @@ class finder
* file extension is automatically added to suffixes.
*
* @param string $suffix A filename suffix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function suffix($suffix)
{
@@ -117,7 +135,7 @@ class finder
* file extension is automatically added to suffixes.
*
* @param string $extension_suffix A filename suffix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function extension_suffix($extension_suffix)
{
@@ -133,7 +151,7 @@ class finder
* file extension is automatically added to suffixes.
*
* @param string $core_suffix A filename suffix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function core_suffix($core_suffix)
{
@@ -145,7 +163,7 @@ class finder
* Sets the prefix all files found in extensions and core must match
*
* @param string $prefix A filename prefix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function prefix($prefix)
{
@@ -158,7 +176,7 @@ class finder
* Sets a prefix all files found in extensions must match
*
* @param string $extension_prefix A filename prefix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function extension_prefix($extension_prefix)
{
@@ -170,7 +188,7 @@ class finder
* Sets a prefix all files found in the core path must match
*
* @param string $core_prefix A filename prefix
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function core_prefix($core_prefix)
{
@@ -185,7 +203,7 @@ class finder
* the current directory.
*
* @param string $directory
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function directory($directory)
{
@@ -198,7 +216,7 @@ class finder
* Sets a directory all files found in extensions must be contained in
*
* @param string $extension_directory
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function extension_directory($extension_directory)
{
@@ -210,7 +228,7 @@ class finder
* Sets a directory all files found in the core path must be contained in
*
* @param string $core_directory
- * @return \phpbb\extension\finder This object for chaining calls
+ * @return \phpbb\finder This object for chaining calls
*/
public function core_directory($core_directory)
{
@@ -246,16 +264,14 @@ class finder
* phpBB naming rules an incorrect class name will be returned.
*
* @param bool $cache Whether the result should be cached
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
* @return array An array of found class names
*/
- public function get_classes($cache = true, $use_all_available = false)
+ public function get_classes($cache = true)
{
$this->query['extension_suffix'] .= '.' . $this->php_ext;
$this->query['core_suffix'] .= '.' . $this->php_ext;
- $files = $this->find($cache, false, $use_all_available);
+ $files = $this->find($cache, false);
return $this->get_classes_from_files($files);
}
@@ -290,27 +306,23 @@ class finder
* Finds all directories matching the configured options
*
* @param bool $cache Whether the result should be cached
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
* @param bool $extension_keys Whether the result should have extension name as array key
* @return array An array of paths to found directories
*/
- public function get_directories($cache = true, $use_all_available = false, $extension_keys = false)
+ public function get_directories($cache = true, $extension_keys = false)
{
- return $this->find_with_root_path($cache, true, $use_all_available, $extension_keys);
+ return $this->find_with_root_path($cache, true, $extension_keys);
}
/**
* Finds all files matching the configured options.
*
* @param bool $cache Whether the result should be cached
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
* @return array An array of paths to found files
*/
- public function get_files($cache = true, $use_all_available = false)
+ public function get_files($cache = true)
{
- return $this->find_with_root_path($cache, false, $use_all_available);
+ return $this->find_with_root_path($cache, false);
}
/**
@@ -318,16 +330,14 @@ class finder
*
* @param bool $cache Whether the result should be cached
* @param bool $is_dir Directories will be returned when true, only files
- * otherwise
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
+ * otherwise
* @param bool $extension_keys If true, result will be associative array
* with extension name as key
* @return array An array of paths to found items
*/
- protected function find_with_root_path($cache = true, $is_dir = false, $use_all_available = false, $extension_keys = false)
+ protected function find_with_root_path($cache = true, $is_dir = false, $extension_keys = false)
{
- $items = $this->find($cache, $is_dir, $use_all_available);
+ $items = $this->find($cache, $is_dir);
$result = array();
foreach ($items as $item => $ext_name)
@@ -351,21 +361,11 @@ class finder
* @param bool $cache Whether the result should be cached
* @param bool $is_dir Directories will be returned when true, only files
* otherwise
- * @param bool $use_all_available Use all available instead of just all
- * enabled extensions
* @return array An array of paths to found items
*/
- public function find($cache = true, $is_dir = false, $use_all_available = false)
+ public function find($cache = true, $is_dir = false)
{
- if ($use_all_available)
- {
- $extensions = $this->extension_manager->all_available();
- }
- else
- {
- $extensions = $this->extension_manager->all_enabled();
- }
-
+ $extensions = $this->extensions;
if ($this->query['core_path'])
{
$extensions['/'] = $this->phpbb_root_path . $this->query['core_path'];
diff --git a/phpBB/phpbb/message/admin_form.php b/phpBB/phpbb/message/admin_form.php
new file mode 100644
index 0000000000..b71b3fc535
--- /dev/null
+++ b/phpBB/phpbb/message/admin_form.php
@@ -0,0 +1,189 @@
+<?php
+/**
+*
+* @package message
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\message;
+
+/**
+* Class admin_form
+* Displays a message to the user and allows him to send an email
+*
+* @package phpbb\message
+*/
+class admin_form extends form
+{
+ /** @var \phpbb\config\db_text */
+ protected $config_text;
+
+ /** @var string */
+ protected $subject;
+ /** @var string */
+ protected $sender_name;
+ /** @var string */
+ protected $sender_address;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\auth\auth $auth
+ * @param \phpbb\config\config $config
+ * @param \phpbb\config\db_text $config_text
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\user $user
+ * @param string $phpbb_root_path
+ * @param string $phpEx
+ */
+ public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\config\db_text $config_text, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $phpEx)
+ {
+ parent::__construct($auth, $config, $db, $user, $phpbb_root_path, $phpEx);
+ $this->config_text = $config_text;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function check_allow()
+ {
+ $error = parent::check_allow();
+ if ($error)
+ {
+ return $error;
+ }
+
+ if (!$this->config['contact_admin_form_enable'])
+ {
+ return 'NO_CONTACT_PAGE';
+ }
+
+ return false;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function bind(\phpbb\request\request_interface $request)
+ {
+ parent::bind($request);
+
+ $this->subject = $request->variable('subject', '', true);
+ $this->sender_address = $request->variable('email', '');
+ $this->sender_name = $request->variable('name', '', true);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function submit(\messenger $messenger)
+ {
+ if (!$this->subject)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_SUBJECT_EMAIL'];
+ }
+ if (!$this->body)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_MESSAGE_EMAIL'];
+ }
+
+ if ($this->user->data['is_registered'])
+ {
+ $this->message->set_sender_from_user($this->user);
+ $this->sender_name = $this->user->data['username'];
+ $this->sender_address = $this->user->data['user_email'];
+ }
+ else
+ {
+ if (!$this->sender_name)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_SENDER_NAME'];
+ }
+
+ if (!function_exists('validate_data'))
+ {
+ require($this->phpbb_root_path . 'includes/functions_user.' . $this->phpEx);
+ }
+
+ $validate_array = validate_data(
+ array(
+ 'email' => $this->sender_address,
+ ),
+ array(
+ 'email' => array(
+ array('string', false, 6, 60),
+ array('email'),
+ ),
+ )
+ );
+
+ foreach ($validate_array as $error)
+ {
+ $this->errors[] = $this->user->lang[$error];
+ }
+
+ $this->message->set_sender($this->user->ip, $this->sender_name, $this->sender_address, $this->user->lang_name);
+ $this->message->set_sender_notify_type(NOTIFY_EMAIL);
+ }
+
+ $this->message->set_template('contact_admin');
+ $this->message->set_subject($this->subject);
+ $this->message->set_body($this->body);
+ $this->message->add_recipient(
+ $this->user->lang['ADMINISTRATOR'],
+ $this->config['board_contact'],
+ $this->config['default_lang'],
+ NOTIFY_EMAIL
+ );
+
+ $this->message->set_template_vars(array(
+ 'FROM_EMAIL_ADDRESS' => $this->sender_address,
+ 'FROM_IP_ADDRESS' => $this->user->ip,
+ 'S_IS_REGISTERED' => $this->user->data['is_registered'],
+
+ 'U_FROM_PROFILE' => generate_board_url() . '/memberlist.' . $this->phpEx . '?mode=viewprofile&u=' . $this->user->data['user_id'],
+ ));
+
+ parent::submit($messenger);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function render(\phpbb\template\template $template)
+ {
+ $l_admin_info = $this->config_text->get('contact_admin_info');
+ if ($l_admin_info)
+ {
+ $contact_admin_data = $this->config_text->get_array(array(
+ 'contact_admin_info',
+ 'contact_admin_info_uid',
+ 'contact_admin_info_bitfield',
+ 'contact_admin_info_flags',
+ ));
+
+ $l_admin_info = generate_text_for_display(
+ $contact_admin_data['contact_admin_info'],
+ $contact_admin_data['contact_admin_info_uid'],
+ $contact_admin_data['contact_admin_info_bitfield'],
+ $contact_admin_data['contact_admin_info_flags']
+ );
+ }
+
+ $template->assign_vars(array(
+ 'S_CONTACT_ADMIN' => true,
+ 'S_CONTACT_FORM' => $this->config['contact_admin_form_enable'],
+ 'S_IS_REGISTERED' => $this->user->data['is_registered'],
+
+ 'CONTACT_INFO' => $l_admin_info,
+ 'MESSAGE' => $this->body,
+ 'SUBJECT' => $this->subject,
+ 'NAME' => $this->sender_name,
+ 'EMAIL' => $this->sender_address,
+ ));
+
+ parent::render($template);
+ }
+}
diff --git a/phpBB/phpbb/message/form.php b/phpBB/phpbb/message/form.php
new file mode 100644
index 0000000000..d7a42c4080
--- /dev/null
+++ b/phpBB/phpbb/message/form.php
@@ -0,0 +1,173 @@
+<?php
+/**
+*
+* @package message
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\message;
+
+/**
+* Abstract class form
+*
+* @package phpbb\message
+*/
+abstract class form
+{
+ /** @var \phpbb\auth\auth */
+ protected $auth;
+ /** @var \phpbb\config\config */
+ protected $config;
+ /** @var \phpbb\db\driver\driver_interface */
+ protected $db;
+ /** @var \phpbb\message\message */
+ protected $message;
+ /** @var \phpbb\user */
+ protected $user;
+
+ /** @var string */
+ protected $phpbb_root_path;
+ /** @var string */
+ protected $phpEx;
+
+ /** @var array */
+ protected $errors = array();
+ /** @var bool */
+ protected $cc_sender;
+ /** @var string */
+ protected $body;
+
+ /**
+ * Construct
+ *
+ * @param \phpbb\auth\auth $auth
+ * @param \phpbb\config\config $config
+ * @param \phpbb\db\driver\driver_interface $db
+ * @param \phpbb\user $user
+ * @param string $phpbb_root_path
+ * @param string $phpEx
+ */
+ public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $phpEx)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->phpEx = $phpEx;
+ $this->user = $user;
+ $this->auth = $auth;
+ $this->config = $config;
+ $this->db = $db;
+
+ $this->message = new message($config['server_name']);
+ $this->message->set_sender_from_user($this->user);
+ }
+
+ /**
+ * Returns the title for the email form page
+ *
+ * @return string
+ */
+ public function get_page_title()
+ {
+ return $this->user->lang['SEND_EMAIL'];
+ }
+
+ /**
+ * Returns the file name of the form template
+ *
+ * @return string
+ */
+ public function get_template_file()
+ {
+ return 'memberlist_email.html';
+ }
+
+ /**
+ * Checks whether the user is allowed to use the form
+ *
+ * @return false|string Error string if not allowed, false otherwise
+ */
+ public function check_allow()
+ {
+ if (!$this->config['email_enable'])
+ {
+ return 'EMAIL_DISABLED';
+ }
+
+ if (time() - $this->user->data['user_emailtime'] < $this->config['flood_interval'])
+ {
+ return 'FLOOD_EMAIL_LIMIT';
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the return link after the message has been sent
+ *
+ * @return string
+ */
+ public function get_return_message()
+ {
+ return sprintf($this->user->lang['RETURN_INDEX'], '<a href="' . append_sid($this->phpbb_root_path . 'index.' . $this->phpEx) . '">', '</a>');
+ }
+
+ /**
+ * Bind the values of the request to the form
+ *
+ * @param \phpbb\request\request_interface $request
+ * @return null
+ */
+ public function bind(\phpbb\request\request_interface $request)
+ {
+ $this->cc_sender = $request->is_set_post('cc_sender');
+ $this->body = $request->variable('message', '', true);
+ }
+
+ /**
+ * Submit form, generate the email and send it
+ *
+ * @param \messenger $messenger
+ * @return null
+ */
+ public function submit(\messenger $messenger)
+ {
+ if (!check_form_key('memberlist_email'))
+ {
+ $this->errors[] = 'FORM_INVALID';
+ }
+
+ if (!sizeof($this->errors))
+ {
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_emailtime = ' . time() . '
+ WHERE user_id = ' . $this->user->data['user_id'];
+ $this->db->sql_query($sql);
+
+ if ($this->cc_sender)
+ {
+ $this->message->cc_sender();
+ }
+
+ $this->message->send($messenger, phpbb_get_board_contact($this->config, $this->phpEx));
+
+ meta_refresh(3, append_sid($this->phpbb_root_path . 'index.' . $this->phpEx));
+ trigger_error($this->user->lang['EMAIL_SENT'] . '<br /><br />' . $this->get_return_message());
+ }
+ }
+
+ /**
+ * Render the template of the form
+ *
+ * @param \phpbb\template\template $template
+ * @return null
+ */
+ public function render(\phpbb\template\template $template)
+ {
+ add_form_key('memberlist_email');
+
+ $template->assign_vars(array(
+ 'ERROR_MESSAGE' => (sizeof($this->errors)) ? implode('<br />', $this->errors) : '',
+ ));
+ }
+}
diff --git a/phpBB/phpbb/message/message.php b/phpBB/phpbb/message/message.php
new file mode 100644
index 0000000000..182995ba21
--- /dev/null
+++ b/phpBB/phpbb/message/message.php
@@ -0,0 +1,280 @@
+<?php
+/**
+*
+* @package message
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\message;
+
+/**
+* Class message
+* Holds all information for an email and sends it in the end
+*
+* @package phpbb\message
+*/
+class message
+{
+ /** @var string */
+ protected $server_name;
+
+ /** @var string */
+ protected $subject = '';
+ /** @var string */
+ protected $body = '';
+ /** @var string */
+ protected $template = '';
+ /** @var array */
+ protected $template_vars = array();
+
+ /** @var string */
+ protected $sender_ip = '';
+ /** @var string */
+ protected $sender_name = '';
+ /** @var string */
+ protected $sender_address = '';
+ /** @var string */
+ protected $sender_lang = '';
+ /** @var string */
+ protected $sender_id = '';
+ /** @var string */
+ protected $sender_username = '';
+ /** @var string */
+ protected $sender_jabber = '';
+ /** @var int */
+ protected $sender_notify_type = NOTIFY_EMAIL;
+
+ /** @var array */
+ protected $recipients;
+
+ /**
+ * Construct
+ *
+ * @param string $server_name Used for AntiAbuse header
+ */
+ public function __construct($server_name)
+ {
+ $this->server_name = $server_name;
+ }
+
+ /**
+ * Set the subject of the email
+ *
+ * @param string $subject
+ * @return null
+ */
+ public function set_subject($subject)
+ {
+ $this->subject = $subject;
+ }
+
+ /**
+ * Set the body of the email text
+ *
+ * @param string $body
+ * @return null
+ */
+ public function set_body($body)
+ {
+ $this->body = $body;
+ }
+
+ /**
+ * Set the name of the email template to use
+ *
+ * @param string $template
+ * @return null
+ */
+ public function set_template($template)
+ {
+ $this->template = $template;
+ }
+
+ /**
+ * Set the array with the "template" data for the email
+ *
+ * @param array $template_vars
+ * @return null
+ */
+ public function set_template_vars($template_vars)
+ {
+ $this->template_vars = $template_vars;
+ }
+
+ /**
+ * Add a recipient from \phpbb\user
+ *
+ * @param \phpbb\user $user
+ * @return null
+ */
+ public function add_recipient_from_user_row(array $user)
+ {
+ $this->add_recipient(
+ $user['username'],
+ $user['user_email'],
+ $user['user_lang'],
+ $user['user_notify_type'],
+ $user['username'],
+ $user['user_jabber']
+ );
+ }
+
+ /**
+ * Add a recipient
+ *
+ * @param string $recipient_name Displayed sender name
+ * @param string $recipient_address Email address
+ * @param string $recipient_lang
+ * @param int $recipient_notify_type Used notification methods (Jabber, Email, ...)
+ * @param string $recipient_username User Name (used for AntiAbuse header)
+ * @param string $recipient_jabber
+ * @return null
+ */
+ public function add_recipient($recipient_name, $recipient_address, $recipient_lang, $recipient_notify_type = NOTIFY_EMAIL, $recipient_username = '', $recipient_jabber = '')
+ {
+ $this->recipients[] = array(
+ 'name' => $recipient_name,
+ 'address' => $recipient_address,
+ 'lang' => $recipient_lang,
+ 'username' => $recipient_username,
+ 'jabber' => $recipient_jabber,
+ 'notify_type' => $recipient_notify_type,
+ 'to_name' => $recipient_name,
+ );
+ }
+
+ /**
+ * Set the senders data from \phpbb\user object
+ *
+ * @param \phpbb\user $user
+ * @return null
+ */
+ public function set_sender_from_user($user)
+ {
+ $this->set_sender(
+ $user->ip,
+ $user->data['username'],
+ $user->data['user_email'],
+ $user->lang_name,
+ $user->data['user_id'],
+ $user->data['username'],
+ $user->data['user_jabber']
+ );
+
+ $this->set_sender_notify_type($user->data['user_notify_type']);
+ }
+
+ /**
+ * Set the senders data
+ *
+ * @param string $sender_ip
+ * @param string $sender_name Displayed sender name
+ * @param string $sender_address Email address
+ * @param string $sender_lang
+ * @param int $sender_id User ID
+ * @param string $sender_username User Name (used for AntiAbuse header)
+ * @param string $sender_jabber
+ * @return null
+ */
+ public function set_sender($sender_ip, $sender_name, $sender_address, $sender_lang = '', $sender_id = 0, $sender_username = '', $sender_jabber = '')
+ {
+ $this->sender_ip = $sender_ip;
+ $this->sender_name = $sender_name;
+ $this->sender_address = $sender_address;
+ $this->sender_lang = $sender_lang;
+ $this->sender_id = $sender_id;
+ $this->sender_username = $sender_username;
+ $this->sender_jabber = $sender_jabber;
+ }
+
+ /**
+ * Which notification type should be used? Jabber, Email, ...?
+ *
+ * @param int $sender_notify_type
+ * @return null
+ */
+ public function set_sender_notify_type($sender_notify_type)
+ {
+ $this->sender_notify_type = $sender_notify_type;
+ }
+
+ /**
+ * Ok, now the same email if CC specified, but without exposing the user's email address
+ *
+ * @return null
+ */
+ public function cc_sender()
+ {
+ if (!sizeof($this->recipients))
+ {
+ trigger_error('No email recipients specified');
+ }
+ if (!$this->sender_address)
+ {
+ trigger_error('No email sender specified');
+ }
+
+ $this->recipients[] = array(
+ 'lang' => $this->sender_lang,
+ 'address' => $this->sender_address,
+ 'name' => $this->sender_name,
+ 'username' => $this->sender_username,
+ 'jabber' => $this->sender_jabber,
+ 'notify_type' => $this->sender_notify_type,
+ 'to_name' => $this->recipients[0]['to_name'],
+ );
+ }
+
+ /**
+ * Send the email
+ *
+ * @param \messenger $messenger
+ * @param string $phpEx
+ * @return null
+ */
+ public function send(\messenger $messenger, $contact)
+ {
+ if (!sizeof($this->recipients))
+ {
+ return;
+ }
+
+ foreach ($this->recipients as $recipient)
+ {
+ $messenger->template($this->template, $recipient['lang']);
+ $messenger->replyto($this->sender_address);
+ $messenger->to($recipient['address'], $recipient['name']);
+ $messenger->im($recipient['jabber'], $recipient['username']);
+
+ $messenger->headers('X-AntiAbuse: Board servername - ' . $this->server_name);
+ $messenger->headers('X-AntiAbuse: User IP - ' . $this->sender_ip);
+
+ if ($this->sender_id)
+ {
+ $messenger->headers('X-AntiAbuse: User_id - ' . $this->sender_id);
+ }
+ if ($this->sender_username)
+ {
+ $messenger->headers('X-AntiAbuse: Username - ' . $this->sender_username);
+ }
+
+ $messenger->subject(htmlspecialchars_decode($this->subject));
+
+ $messenger->assign_vars(array(
+ 'BOARD_CONTACT' => $contact,
+ 'TO_USERNAME' => htmlspecialchars_decode($recipient['to_name']),
+ 'FROM_USERNAME' => htmlspecialchars_decode($this->sender_name),
+ 'MESSAGE' => htmlspecialchars_decode($this->body))
+ );
+
+ if (sizeof($this->template_vars))
+ {
+ $messenger->assign_vars($this->template_vars);
+ }
+
+ $messenger->send($recipient['notify_type']);
+ }
+ }
+}
diff --git a/phpBB/phpbb/message/topic_form.php b/phpBB/phpbb/message/topic_form.php
new file mode 100644
index 0000000000..3a35c35d21
--- /dev/null
+++ b/phpBB/phpbb/message/topic_form.php
@@ -0,0 +1,156 @@
+<?php
+/**
+*
+* @package message
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\message;
+
+/**
+* Class topic_form
+* Form used to send topics as notification emails
+*
+* @package phpbb\message
+*/
+class topic_form extends form
+{
+ /** @var int */
+ protected $topic_id;
+ /** @var array */
+ protected $topic_row;
+ /** @var string */
+ protected $recipient_address;
+ /** @var string */
+ protected $recipient_name;
+ /** @var string */
+ protected $recipient_lang;
+
+ /**
+ * Get the data of the topic
+ *
+ * @param int $topic_id
+ * @return false|array false if the topic does not exist, array otherwise
+ */
+ protected function get_topic_row($topic_id)
+ {
+ $sql = 'SELECT forum_id, topic_title
+ FROM ' . TOPICS_TABLE . '
+ WHERE topic_id = ' . (int) $topic_id;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ return $row;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function check_allow()
+ {
+ $error = parent::check_allow();
+ if ($error)
+ {
+ return $error;
+ }
+
+ if (!$this->auth->acl_get('u_sendemail'))
+ {
+ return 'NO_EMAIL';
+ }
+
+ if (!$this->topic_row)
+ {
+ return 'NO_TOPIC';
+ }
+
+ if (!$this->auth->acl_get('f_read', $this->topic_row['forum_id']))
+ {
+ return 'SORRY_AUTH_READ';
+ }
+
+ if (!$this->auth->acl_get('f_email', $this->topic_row['forum_id']))
+ {
+ return 'NO_EMAIL';
+ }
+
+ return false;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function bind(\phpbb\request\request_interface $request)
+ {
+ parent::bind($request);
+
+ $this->topic_id = $request->variable('t', 0);
+ $this->recipient_address = $request->variable('email', '');
+ $this->recipient_name = $request->variable('name', '', true);
+ $this->recipient_lang = $request->variable('lang', $this->config['default_lang']);
+
+ $this->topic_row = $this->get_topic_row($this->topic_id);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function submit(\messenger $messenger)
+ {
+ if (!$this->recipient_address || !preg_match('/^' . get_preg_expression('email') . '$/i', $this->recipient_address))
+ {
+ $this->errors[] = $this->user->lang['EMPTY_ADDRESS_EMAIL'];
+ }
+
+ if (!$this->recipient_name)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_NAME_EMAIL'];
+ }
+
+ $this->message->set_template('email_notify');
+ $this->message->set_template_vars(array(
+ 'TOPIC_NAME' => htmlspecialchars_decode($this->topic_row['topic_title']),
+ 'U_TOPIC' => generate_board_url() . '/viewtopic.' . $this->phpEx . '?f=' . $this->topic_row['forum_id'] . '&t=' . $this->topic_id,
+ ));
+
+ $this->message->add_recipient(
+ $this->recipient_name,
+ $this->recipient_address,
+ $this->recipient_lang,
+ NOTIFY_EMAIL
+ );
+ $this->message->set_sender_notify_type(NOTIFY_EMAIL);
+
+ parent::submit($messenger);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function get_return_message()
+ {
+ return sprintf($this->user->lang['RETURN_TOPIC'], '<a href="' . append_sid($this->phpbb_root_path . 'viewtopic.' . $this->phpEx, 'f=' . $this->topic_row['forum_id'] . '&amp;t=' . $this->topic_id) . '">', '</a>');
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function render(\phpbb\template\template $template)
+ {
+ parent::render($template);
+
+ $this->user->add_lang('viewtopic');
+ $template->assign_vars(array(
+ 'EMAIL' => $this->recipient_address,
+ 'NAME' => $this->recipient_name,
+ 'S_LANG_OPTIONS' => language_select($this->recipient_lang),
+ 'MESSAGE' => $this->body,
+
+ 'L_EMAIL_BODY_EXPLAIN' => $this->user->lang['EMAIL_TOPIC_EXPLAIN'],
+ 'S_POST_ACTION' => append_sid($this->phpbb_root_path . 'memberlist.' . $this->phpEx, 'mode=email&amp;t=' . $this->topic_id))
+ );
+ }
+}
diff --git a/phpBB/phpbb/message/user_form.php b/phpBB/phpbb/message/user_form.php
new file mode 100644
index 0000000000..7aa4b94def
--- /dev/null
+++ b/phpBB/phpbb/message/user_form.php
@@ -0,0 +1,134 @@
+<?php
+/**
+*
+* @package message
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+namespace phpbb\message;
+
+/**
+* Class user_form
+* Allows users to send emails to other users
+*
+* @package phpbb\message
+*/
+class user_form extends form
+{
+ /** @var int */
+ protected $recipient_id;
+ /** @var array */
+ protected $recipient_row;
+ /** @var string */
+ protected $subject;
+
+ /**
+ * Get the data of the recipient
+ *
+ * @param int $user_id
+ * @return false|array false if the user does not exist, array otherwise
+ */
+ protected function get_user_row($user_id)
+ {
+ $sql = 'SELECT user_id, username, user_colour, user_email, user_allow_viewemail, user_lang, user_jabber, user_notify_type
+ FROM ' . USERS_TABLE . '
+ WHERE user_id = ' . (int) $user_id . '
+ AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ return $row;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function check_allow()
+ {
+ $error = parent::check_allow();
+ if ($error)
+ {
+ return $error;
+ }
+
+ if (!$this->auth->acl_get('u_sendemail'))
+ {
+ return 'NO_EMAIL';
+ }
+
+ if ($this->recipient_id == ANONYMOUS || !$this->config['board_email_form'])
+ {
+ return 'NO_EMAIL';
+ }
+
+ if (!$this->recipient_row)
+ {
+ return 'NO_USER';
+ }
+
+ // Can we send email to this user?
+ if (!$this->recipient_row['user_allow_viewemail'] && !$this->auth->acl_get('a_user'))
+ {
+ return 'NO_EMAIL';
+ }
+
+ return false;
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function bind(\phpbb\request\request_interface $request)
+ {
+ parent::bind($request);
+
+ $this->recipient_id = $request->variable('u', 0);
+ $this->subject = $request->variable('subject', '', true);
+
+ $this->recipient_row = $this->get_user_row($this->recipient_id);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function submit(\messenger $messenger)
+ {
+ if (!$this->subject)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_SUBJECT_EMAIL'];
+ }
+
+ if (!$this->body)
+ {
+ $this->errors[] = $this->user->lang['EMPTY_MESSAGE_EMAIL'];
+ }
+
+ $this->message->set_template('profile_send_email');
+ $this->message->set_subject($this->subject);
+ $this->message->set_body($this->body);
+ $this->message->add_recipient_from_user_row($this->recipient_row);
+
+ parent::submit($messenger);
+ }
+
+ /**
+ * {inheritDoc}
+ */
+ public function render(\phpbb\template\template $template)
+ {
+ parent::render($template);
+
+ $template->assign_vars(array(
+ 'S_SEND_USER' => true,
+ 'S_POST_ACTION' => append_sid($this->phpbb_root_path . 'memberlist.' . $this->phpEx, 'mode=email&amp;u=' . $this->recipient_id),
+
+ 'L_SEND_EMAIL_USER' => $this->user->lang('SEND_EMAIL_USER', $this->recipient_row['username']),
+ 'USERNAME_FULL' => get_username_string('full', $this->recipient_row['user_id'], $this->recipient_row['username'], $this->recipient_row['user_colour']),
+ 'SUBJECT' => $this->subject,
+ 'MESSAGE' => $this->body,
+ ));
+ }
+}
diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php
index c3539e76df..b787b624f6 100644
--- a/phpBB/phpbb/notification/manager.php
+++ b/phpBB/phpbb/notification/manager.php
@@ -574,6 +574,34 @@ class manager
return $subscription_methods;
}
+
+ /**
+ * Get user's notification data
+ *
+ * @param int $user_id The user_id of the user to get the notifications for
+ *
+ * @return array User's notification
+ */
+ protected function get_user_notifications($user_id)
+ {
+ $sql = 'SELECT method, notify, item_type
+ FROM ' . $this->user_notifications_table . '
+ WHERE user_id = ' . (int) $user_id . '
+ AND item_id = 0';
+
+ $result = $this->db->sql_query($sql);
+ $user_notifications = array();
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $user_notifications[$row['item_type']][] = $row;
+ }
+
+ $this->db->sql_freeresult($result);
+
+ return $user_notifications;
+ }
+
/**
* Get global subscriptions (item_id = 0)
*
@@ -587,28 +615,23 @@ class manager
$subscriptions = array();
- foreach ($this->get_subscription_types() as $group_name => $types)
+ $user_notifications = $this->get_user_notifications($user_id);
+
+ foreach ($this->get_subscription_types() as $types)
{
foreach ($types as $id => $type)
{
- $sql = 'SELECT method, notify
- FROM ' . $this->user_notifications_table . '
- WHERE user_id = ' . (int) $user_id . "
- AND item_type = '" . $this->db->sql_escape($id) . "'
- AND item_id = 0";
- $result = $this->db->sql_query($sql);
-
- $row = $this->db->sql_fetchrow($result);
- if (!$row)
+
+ if (empty($user_notifications[$id]))
{
// No rows at all, default to ''
$subscriptions[$id] = array('');
}
else
{
- do
+ foreach ($user_notifications[$id] as $user_notification)
{
- if (!$row['notify'])
+ if (!$user_notification['notify'])
{
continue;
}
@@ -618,12 +641,9 @@ class manager
$subscriptions[$id] = array();
}
- $subscriptions[$id][] = $row['method'];
+ $subscriptions[$id][] = $user_notification['method'];
}
- while ($row = $this->db->sql_fetchrow($result));
}
-
- $this->db->sql_freeresult($result);
}
}
diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php
index fffc9d1461..1d47180e55 100644
--- a/phpBB/phpbb/passwords/driver/base.php
+++ b/phpBB/phpbb/passwords/driver/base.php
@@ -43,4 +43,20 @@ abstract class base implements driver_interface
{
return true;
}
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function get_settings_only($hash, $full = false)
+ {
+ return false;
+ }
}
diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php
index 3edf7255c0..de5840c7cf 100644
--- a/phpBB/phpbb/passwords/driver/bcrypt.php
+++ b/phpBB/phpbb/passwords/driver/bcrypt.php
@@ -60,7 +60,7 @@ class bcrypt extends base
/**
* @inheritdoc
*/
- public function check($password, $hash)
+ public function check($password, $hash, $user_row = array())
{
$salt = substr($hash, 0, 29);
if (strlen($salt) != 29)
diff --git a/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php b/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php
new file mode 100644
index 0000000000..f706c7af69
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php
@@ -0,0 +1,84 @@
+<?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\passwords\driver;
+
+class bcrypt_wcf2 extends base
+{
+ const PREFIX = '$wcf2$';
+
+ /** @var \phpbb\passwords\driver\bcrypt */
+ protected $bcrypt;
+
+ /** @var phpbb\passwords\driver\helper */
+ protected $helper;
+
+ /**
+ * Constructor of passwords driver object
+ *
+ * @param \phpbb\passwords\driver\bcrypt $bcrypt Salted md5 driver
+ * @param \phpbb\passwords\driver\helper $helper Password driver helper
+ */
+ public function __construct(\phpbb\passwords\driver\bcrypt $bcrypt, helper $helper)
+ {
+ $this->bcrypt = $bcrypt;
+ $this->helper = $helper;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (empty($hash) || strlen($hash) != 60)
+ {
+ return false;
+ }
+ else
+ {
+ $salt = substr($hash, 0, 29);
+
+ if (strlen($salt) != 29)
+ {
+ return false;
+ }
+ // Works for standard WCF 2.x, i.e. WBB4 and similar
+ return $hash === $this->bcrypt->hash($this->bcrypt->hash($password, $salt), $salt);
+ }
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/convert_password.php b/phpBB/phpbb/passwords/driver/convert_password.php
new file mode 100644
index 0000000000..45d84f45c0
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/convert_password.php
@@ -0,0 +1,43 @@
+<?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\passwords\driver;
+
+class convert_password extends base
+{
+ const PREFIX = '$CP$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php
index 54c9d6500e..a257e71f23 100644
--- a/phpBB/phpbb/passwords/driver/driver_interface.php
+++ b/phpBB/phpbb/passwords/driver/driver_interface.php
@@ -23,6 +23,13 @@ interface driver_interface
public function is_supported();
/**
+ * Check if hash type is a legacy hash type
+ *
+ * @return bool True if it's a legacy hash type, false if not
+ */
+ public function is_legacy();
+
+ /**
* Returns the hash prefix
*
* @return string Hash prefix
@@ -44,10 +51,11 @@ interface driver_interface
*
* @param string $password The password to check
* @param string $hash The password hash to check against
+ * @param string $user_row User's row in users table
*
* @return bool True if password is correct, else false
*/
- public function check($password, $hash);
+ public function check($password, $hash, $user_row = array());
/**
* Get only the settings of the specified hash
diff --git a/phpBB/phpbb/passwords/driver/md5_mybb.php b/phpBB/phpbb/passwords/driver/md5_mybb.php
new file mode 100644
index 0000000000..0745bceb5e
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/md5_mybb.php
@@ -0,0 +1,60 @@
+<?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\passwords\driver;
+
+class md5_mybb extends base
+{
+ const PREFIX = '$md5_mybb$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (empty($hash) || strlen($hash) != 32 || !isset($user_row['user_passwd_salt']))
+ {
+ return false;
+ }
+ else
+ {
+ // Works for myBB 1.1.x, 1.2.x, 1.4.x, 1.6.x
+ return $hash === md5(md5($user_row['user_passwd_salt']) . md5($password));
+ }
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/md5_phpbb2.php b/phpBB/phpbb/passwords/driver/md5_phpbb2.php
new file mode 100644
index 0000000000..de1993e8a1
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/md5_phpbb2.php
@@ -0,0 +1,118 @@
+<?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\passwords\driver;
+
+class md5_phpbb2 extends base
+{
+ const PREFIX = '$md5_phpbb2$';
+
+ /** @var \phpbb\request\request phpBB request object */
+ protected $request;
+
+ /** @var \phpbb\passwords\driver\salted_md5 */
+ protected $salted_md5;
+
+ /** @var phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var php file extension */
+ protected $php_ext;
+
+ /**
+ * Constructor of passwords driver object
+ *
+ * @param \phpbb\request\request $request phpBB request object
+ * @param \phpbb\passwords\driver\salted_md5 $salted_md5 Salted md5 driver
+ * @param string $phpbb_root_path phpBB root path
+ * @param string $php_ext PHP file extension
+ */
+ public function __construct($request, \phpbb\passwords\driver\salted_md5 $salted_md5, $phpbb_root_path, $php_ext)
+ {
+ $this->request = $request;
+ $this->salted_md5 = $salted_md5;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (strlen($hash) != 32 && strlen($hash) != 34)
+ {
+ return false;
+ }
+
+ // enable super globals to get literal value
+ // this is needed to prevent unicode normalization
+ $super_globals_disabled = $this->request->super_globals_disabled();
+ if ($super_globals_disabled)
+ {
+ $this->request->enable_super_globals();
+ }
+
+ // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
+ $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
+ $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
+ $password_new_format = $this->request->variable('password', '', true);
+
+ if ($super_globals_disabled)
+ {
+ $this->request->disable_super_globals();
+ }
+
+ if ($password == $password_new_format)
+ {
+ if (!function_exists('utf8_to_cp1252'))
+ {
+ include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext);
+ }
+
+ if (md5($password_old_format) === $hash || md5(\utf8_to_cp1252($password_old_format)) === $hash
+ || $this->salted_md5->check(md5($password_old_format), $hash) === true
+ || $this->salted_md5->check(md5(\utf8_to_cp1252($password_old_format)), $hash) === true)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/md5_vb.php b/phpBB/phpbb/passwords/driver/md5_vb.php
new file mode 100644
index 0000000000..440b9e39e9
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/md5_vb.php
@@ -0,0 +1,60 @@
+<?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\passwords\driver;
+
+class md5_vb extends base
+{
+ const PREFIX = '$md5_vb$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (empty($hash) || strlen($hash) != 32 || !isset($user_row['user_passwd_salt']))
+ {
+ return false;
+ }
+ else
+ {
+ // Works for vB 3.8.x, 4.x.x, 5.0.x
+ return $hash === md5(md5($password) . $user_row['user_passwd_salt']);
+ }
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php
index a9f6712751..b5f59754e1 100644
--- a/phpBB/phpbb/passwords/driver/salted_md5.php
+++ b/phpBB/phpbb/passwords/driver/salted_md5.php
@@ -56,6 +56,14 @@ class salted_md5 extends base
/**
* @inheritdoc
*/
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
public function hash($password, $setting = '')
{
if ($setting)
@@ -92,7 +100,7 @@ class salted_md5 extends base
/**
* @inheritdoc
*/
- public function check($password, $hash)
+ public function check($password, $hash, $user_row = array())
{
if (strlen($hash) !== 34)
{
diff --git a/phpBB/phpbb/passwords/driver/sha1.php b/phpBB/phpbb/passwords/driver/sha1.php
new file mode 100644
index 0000000000..5d6c93f6a8
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/sha1.php
@@ -0,0 +1,52 @@
+<?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\passwords\driver;
+
+class sha1 extends base
+{
+ const PREFIX = '$sha1$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ return (strlen($hash) == 40) ? $hash === sha1($password) : false;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/sha1_smf.php b/phpBB/phpbb/passwords/driver/sha1_smf.php
new file mode 100644
index 0000000000..3e3322d77f
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/sha1_smf.php
@@ -0,0 +1,51 @@
+<?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\passwords\driver;
+
+class sha1_smf extends base
+{
+ const PREFIX = '$smf$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ return (isset($user_row['login_name'])) ? sha1(strtolower($user_row['login_name']) . $password) : false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ return (strlen($hash) == 40) ? $hash === $this->hash($password, $user_row) : false;
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/sha1_wcf1.php b/phpBB/phpbb/passwords/driver/sha1_wcf1.php
new file mode 100644
index 0000000000..04a69705e9
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/sha1_wcf1.php
@@ -0,0 +1,60 @@
+<?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\passwords\driver;
+
+class sha1_wcf1 extends base
+{
+ const PREFIX = '$wcf1$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (empty($hash) || strlen($hash) != 40 || !isset($user_row['user_passwd_salt']))
+ {
+ return false;
+ }
+ else
+ {
+ // Works for standard WCF 1.x, i.e. WBB3 and similar
+ return $hash === sha1($user_row['user_passwd_salt'] . sha1($user_row['user_passwd_salt'] . sha1($password)));
+ }
+ }
+}
diff --git a/phpBB/phpbb/passwords/driver/sha_xf1.php b/phpBB/phpbb/passwords/driver/sha_xf1.php
new file mode 100644
index 0000000000..7ae0b90f51
--- /dev/null
+++ b/phpBB/phpbb/passwords/driver/sha_xf1.php
@@ -0,0 +1,68 @@
+<?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\passwords\driver;
+
+class sha_xf1 extends base
+{
+ const PREFIX = '$xf1$';
+
+ /**
+ * @inheritdoc
+ */
+ public function get_prefix()
+ {
+ return self::PREFIX;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function is_legacy()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function hash($password, $user_row = '')
+ {
+ // Do not support hashing
+ return false;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function check($password, $hash, $user_row = array())
+ {
+ if (empty($hash) || (strlen($hash) != 40 && strlen($hash) != 64) || !isset($user_row['user_passwd_salt']))
+ {
+ return false;
+ }
+ else
+ {
+ // Works for xenforo 1.0, 1.1
+ if ($hash === sha1(sha1($password) . $user_row['user_passwd_salt'])
+ || $hash === hash('sha256', hash('sha256', $password) . $user_row['user_passwd_salt']))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php
index 8b16cf55dd..0a349c4a14 100644
--- a/phpBB/phpbb/passwords/manager.php
+++ b/phpBB/phpbb/passwords/manager.php
@@ -141,7 +141,7 @@ class manager
*/
if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match))
{
- return $this->get_algorithm('$H$');
+ return false;
}
// Be on the lookout for multiple hashing algorithms
@@ -224,9 +224,10 @@ class manager
*
* @param string $password Password that should be checked
* @param string $hash Stored hash
+ * @param array $user_row User's row in users table
* @return string|bool True if password is correct, false if not
*/
- public function check($password, $hash)
+ public function check($password, $hash, $user_row = array())
{
if (strlen($password) > 4096)
{
@@ -235,11 +236,19 @@ class manager
return false;
}
+ // Empty hashes can't be checked
+ if (empty($hash))
+ {
+ return false;
+ }
+
// First find out what kind of hash we're dealing with
$stored_hash_type = $this->detect_algorithm($hash);
if ($stored_hash_type == false)
{
- return false;
+ // Still check MD5 hashes as that is what the installer
+ // will default to for the admin user
+ return $this->get_algorithm('$H$')->check($password, $hash);
}
// Multiple hash passes needed
@@ -259,6 +268,21 @@ class manager
$this->convert_flag = false;
}
+ // Check all legacy hash types if prefix is $CP$
+ if ($stored_hash_type->get_prefix() === '$CP$')
+ {
+ // Remove $CP$ prefix for proper checking
+ $hash = substr($hash, 4);
+
+ foreach ($this->type_map as $algorithm)
+ {
+ if ($algorithm->is_legacy() && $algorithm->check($password, $hash, $user_row) === true)
+ {
+ return true;
+ }
+ }
+ }
+
return $stored_hash_type->check($password, $hash);
}
diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php
index d286dc9cfc..59b7ec2029 100644
--- a/phpBB/phpbb/session.php
+++ b/phpBB/phpbb/session.php
@@ -408,9 +408,8 @@ class session
$session_expired = false;
// Check whether the session is still valid if we have one
- $method = basename(trim($config['auth_method']));
-
- $provider = $phpbb_container->get('auth.provider.' . $method);
+ $provider_collection = $phpbb_container->get('auth.provider_collection');
+ $provider = $provider_collection->get_provider();
if (!($provider instanceof \phpbb\auth\provider\provider_interface))
{
@@ -577,9 +576,8 @@ class session
}
}
- $method = basename(trim($config['auth_method']));
-
- $provider = $phpbb_container->get('auth.provider.' . $method);
+ $provider_collection = $phpbb_container->get('auth.provider_collection');
+ $provider = $provider_collection->get_provider();
$this->data = $provider->autologin();
if (sizeof($this->data))
@@ -898,9 +896,8 @@ class session
$db->sql_query($sql);
// Allow connecting logout with external auth method logout
- $method = basename(trim($config['auth_method']));
-
- $provider = $phpbb_container->get('auth.provider.' . $method);
+ $provider_collection = $phpbb_container->get('auth.provider_collection');
+ $provider = $provider_collection->get_provider();
$provider->logout($this->data, $new_session);
if ($this->data['user_id'] != ANONYMOUS)
@@ -1075,7 +1072,7 @@ class session
{
global $config, $db;
- if (defined('IN_CHECK_BAN'))
+ if (defined('IN_CHECK_BAN') || defined('SKIP_CHECK_BAN'))
{
return;
}
@@ -1189,7 +1186,7 @@ class session
if ($banned && !$return)
{
- global $template;
+ global $template, $phpbb_root_path, $phpEx;
// If the session is empty we need to create a valid one...
if (empty($this->session_id))
@@ -1210,8 +1207,6 @@ class session
// We show a login box here to allow founders accessing the board if banned by IP
if (defined('IN_LOGIN') && $this->data['user_id'] == ANONYMOUS)
{
- global $phpEx;
-
$this->setup('ucp');
$this->data['is_registered'] = $this->data['is_bot'] = false;
@@ -1235,7 +1230,8 @@ class session
$till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : '';
$message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM';
- $message = sprintf($this->lang[$message], $till_date, '<a href="mailto:' . $config['board_contact'] . '">', '</a>');
+ $contact_link = phpbb_get_board_contact_link($config, $phpbb_root_path, $phpEx);
+ $message = sprintf($this->lang[$message], $till_date, '<a href="' . $contact_link . '">', '</a>');
$message .= ($ban_row['ban_give_reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : '';
$message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>';
diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php
index f4cc26cc9a..4e90044395 100644
--- a/phpBB/phpbb/user.php
+++ b/phpBB/phpbb/user.php
@@ -317,7 +317,7 @@ class user extends \phpbb\session
}
// Is board disabled and user not an admin or moderator?
- if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
+ if ($config['board_disable'] && !defined('IN_LOGIN') && !defined('SKIP_CHECK_DISABLED') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
{
if ($this->data['is_bot'])
{
diff --git a/phpBB/styles/prosilver/template/memberlist_email.html b/phpBB/styles/prosilver/template/memberlist_email.html
index 78d0eba5a8..865f0b883c 100644
--- a/phpBB/styles/prosilver/template/memberlist_email.html
+++ b/phpBB/styles/prosilver/template/memberlist_email.html
@@ -1,24 +1,62 @@
<!-- INCLUDE overall_header.html -->
+<!-- IF S_CONTACT_ADMIN-->
+<h2 class="titlespace">{L_CONTACT_ADMIN}</h2>
+<!-- ELSEIF S_SEND_USER -->
<h2 class="titlespace">{L_SEND_EMAIL_USER}</h2>
+<!-- ELSE -->
+<h2 class="titlespace">{L_EMAIL_TOPIC}</h2>
+<!-- ENDIF -->
<form method="post" action="{S_POST_ACTION}" id="post">
-<div class="panel">
- <div class="inner">
+ <!-- IF CONTACT_INFO -->
+ <div class="panel">
+ <div class="inner">
+ <div class="postbody">
+ <div class="content">
+ {CONTACT_INFO}
+ </div>
+ </div>
+ </div>
+ </div>
+ <br class="clear" />
+ <!-- ENDIF -->
+ <div class="panel">
+ <div class="inner">
<div class="content">
+
<!-- IF ERROR_MESSAGE --><p class="error">{ERROR_MESSAGE}</p><!-- ENDIF -->
<fieldset class="fields2">
<!-- IF S_SEND_USER -->
<dl>
<dt><label>{L_RECIPIENT}{L_COLON}</label></dt>
- <dd><strong>{USERNAME}</strong></dd>
+ <dd><strong>{USERNAME_FULL}</strong></dd>
</dl>
<dl>
<dt><label for="subject">{L_SUBJECT}{L_COLON}</label></dt>
<dd><input class="inputbox autowidth" type="text" name="subject" id="subject" size="50" tabindex="1" value="{SUBJECT}" /></dd>
</dl>
+ <!-- ELSEIF S_CONTACT_ADMIN-->
+ <dl>
+ <dt><label>{L_RECIPIENT}:</label></dt>
+ <dd><strong>{L_ADMINISTRATOR}</strong></dd>
+ </dl>
+ <!-- IF not S_IS_REGISTERED -->
+ <dl>
+ <dt><label for="email">{L_SENDER_EMAIL_ADDRESS}:</label></dt>
+ <dd><input class="inputbox autowidth" type="text" name="email" id="email" size="50" maxlength="100" tabindex="1" value="{EMAIL}" /></dd>
+ </dl>
+ <dl>
+ <dt><label for="name">{L_SENDER_NAME}:</label></dt>
+ <dd><input class="inputbox autowidth" type="text" name="name" id="name" size="50" tabindex="2" value="{NAME}" /></dd>
+ </dl>
+ <!-- ENDIF -->
+ <dl>
+ <dt><label for="subject">{L_SUBJECT}:</label></dt>
+ <dd><input class="inputbox autowidth" type="text" name="subject" id="subject" size="50" tabindex="3" value="{SUBJECT}" /></dd>
+ </dl>
<!-- ELSE -->
<dl>
<dt><label for="email">{L_EMAIL_ADDRESS}{L_COLON}</label></dt>
diff --git a/phpBB/styles/prosilver/template/navbar_footer.html b/phpBB/styles/prosilver/template/navbar_footer.html
index 13e50dae19..6912ee242e 100644
--- a/phpBB/styles/prosilver/template/navbar_footer.html
+++ b/phpBB/styles/prosilver/template/navbar_footer.html
@@ -16,6 +16,7 @@
<!-- IF not S_IS_BOT --><li class="rightside"><a href="{U_DELETE_COOKIES}" data-ajax="true" data-refresh="true">{L_DELETE_COOKIES}</a></li><!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_before -->
<!-- IF U_TEAM --><li class="rightside"><a href="{U_TEAM}">{L_THE_TEAM}</a></li><!-- ENDIF -->
+ <!-- IF U_CONTACT_US --><li class="rightside"><a href="{U_CONTACT_US}">{L_CONTACT_US}</a></li><!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_after -->
</ul>
diff --git a/phpBB/styles/prosilver/template/ucp_avatar_options_local.html b/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
index 3946b9d269..2a0f403782 100644
--- a/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
+++ b/phpBB/styles/prosilver/template/ucp_avatar_options_local.html
@@ -1,6 +1,5 @@
<!-- IF .avatar_local_cats -->
<label for="category">{L_AVATAR_CATEGORY}{L_COLON} <select name="avatar_local_cat" id="category">
-<option value="">{L_NO_AVATAR_CATEGORY}</option>
<!-- BEGIN avatar_local_cats -->
<option value="{avatar_local_cats.NAME}"<!-- IF avatar_local_cats.SELECTED --> selected="selected"<!-- ENDIF -->>{avatar_local_cats.NAME}</option>
<!-- END avatar_local_cats -->
diff --git a/phpBB/styles/prosilver/template/viewtopic_body.html b/phpBB/styles/prosilver/template/viewtopic_body.html
index b9cdf03599..38836f3ee4 100644
--- a/phpBB/styles/prosilver/template/viewtopic_body.html
+++ b/phpBB/styles/prosilver/template/viewtopic_body.html
@@ -117,7 +117,9 @@
<!-- BEGIN postrow -->
<!-- EVENT viewtopic_body_postrow_post_before -->
- <!-- IF postrow.S_FIRST_UNREAD --><a id="unread" class="anchor" data-url="{postrow.U_MINI_POST}"></a><!-- ENDIF -->
+ <!-- IF postrow.S_FIRST_UNREAD -->
+ <a id="unread" class="anchor"<!-- IF S_UNREAD_VIEW --> data-url="{postrow.U_MINI_POST}"<!-- ENDIF -->></a>
+ <!-- ENDIF -->
<div id="p{postrow.POST_ID}" class="post <!-- IF postrow.S_ROW_COUNT is odd -->bg1<!-- ELSE -->bg2<!-- ENDIF --><!-- IF postrow.S_UNREAD_POST --> unreadpost<!-- ENDIF --><!-- IF postrow.S_POST_REPORTED --> reported<!-- ENDIF --><!-- IF postrow.S_POST_DELETED --> deleted<!-- ENDIF --><!-- IF postrow.S_ONLINE and not postrow.S_POST_HIDDEN --> online<!-- ENDIF --><!-- IF postrow.POSTER_WARNINGS --> warned<!-- ENDIF -->">
<div class="inner">
diff --git a/phpBB/styles/subsilver2/template/index_body.html b/phpBB/styles/subsilver2/template/index_body.html
index cb67768b15..2fdd0c77c1 100644
--- a/phpBB/styles/subsilver2/template/index_body.html
+++ b/phpBB/styles/subsilver2/template/index_body.html
@@ -20,10 +20,14 @@
<!-- IF not S_IS_BOT and U_TEAM --> | <!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_before -->
<!-- IF U_TEAM --><a href="{U_TEAM}">{L_THE_TEAM}</a><!-- ENDIF -->
+ <!-- IF U_CONTACT_US -->
+ <!-- IF U_TEAM --> | <!-- ENDIF -->
+ <a href="{U_CONTACT_US}">{L_CONTACT_US}</a>
+ <!-- ENDIF -->
<!-- EVENT overall_footer_teamlink_after -->
</span>
-<br />
<!-- ENDIF -->
+<br />
<br clear="all" />
diff --git a/phpBB/styles/subsilver2/template/memberlist_email.html b/phpBB/styles/subsilver2/template/memberlist_email.html
index 7693a4167f..13ff4baace 100644
--- a/phpBB/styles/subsilver2/template/memberlist_email.html
+++ b/phpBB/styles/subsilver2/template/memberlist_email.html
@@ -6,13 +6,24 @@
<table class="tablebg" width="100%" cellspacing="1">
<tr>
+ <!-- IF S_CONTACT_ADMIN-->
+ <th colspan="2">{L_CONTACT_ADMIN}</th>
+ <!-- ELSEIF S_SEND_USER -->
<th colspan="2">{L_SEND_EMAIL_USER}</th>
+ <!-- ELSE -->
+ <th colspan="2">{L_EMAIL_TOPIC}</th>
+ <!-- ENDIF -->
</tr>
<!-- IF ERROR_MESSAGE -->
<tr>
<td class="row3" colspan="2" align="center"><span class="error">{ERROR_MESSAGE}</span></td>
</tr>
<!-- ENDIF -->
+ <!-- IF CONTACT_INFO -->
+ <tr>
+ <td class="row1" colspan="2">{CONTACT_INFO}</td>
+ </tr>
+ <!-- ENDIF -->
<!-- IF S_SEND_USER -->
<tr>
<td class="row1" width="35%"><b class="genmed">{L_RECIPIENT}</b></td>
@@ -22,6 +33,21 @@
<td class="row1" width="35%"><b class="genmed">{L_SUBJECT}</b></td>
<td class="row2"><input class="post" type="text" name="subject" size="50" tabindex="2" value="{SUBJECT}" /></td>
</tr>
+ <!-- ELSEIF S_CONTACT_ADMIN-->
+ <tr>
+ <td class="row1" width="35%"><b class="genmed">{L_RECIPIENT}</b></td>
+ <td class="row2" width="65%"><b class="genmed">{L_ADMINISTRATOR}</b></td>
+ </tr>
+ <!-- IF not S_IS_REGISTERED -->
+ <tr>
+ <td class="row1" width="35%"><b class="genmed">{L_SENDER_EMAIL_ADDRESS}</b></td>
+ <td class="row2"><input class="post" type="text" name="email" size="50" maxlength="100" value="{EMAIL}" /></td>
+ </tr>
+ <tr>
+ <td class="row1" width="35%"><b class="genmed">{L_SENDER_NAME}</b></td>
+ <td class="row2"><input class="post" type="text" name="name" size="50" value="{NAME}" /></td>
+ </tr>
+ <!-- ENDIF -->
<!-- ELSE -->
<tr>
<td class="row1" width="35%"><b class="genmed">{L_EMAIL_ADDRESS}</b></td>
diff --git a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html b/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html
index 87e5608fec..7beddfc109 100644
--- a/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html
+++ b/phpBB/styles/subsilver2/template/ucp_avatar_options_local.html
@@ -2,7 +2,6 @@
<!-- IF .avatar_local_cats -->
<tr>
<td class="cat" colspan="2" align="center" valign="middle"><span class="genmed">{L_AVATAR_CATEGORY}{L_COLON} </span><select name="avatar_local_cat" id="category">
- <option value="">{L_NO_AVATAR_CATEGORY}</option>
<!-- BEGIN avatar_local_cats -->
<option value="{avatar_local_cats.NAME}"<!-- IF avatar_local_cats.SELECTED --> selected="selected"<!-- ENDIF -->>{avatar_local_cats.NAME}</option>
<!-- END avatar_local_cats -->
diff --git a/phpBB/styles/subsilver2/template/viewtopic_body.html b/phpBB/styles/subsilver2/template/viewtopic_body.html
index 8f83bfbea6..c69be83a1e 100644
--- a/phpBB/styles/subsilver2/template/viewtopic_body.html
+++ b/phpBB/styles/subsilver2/template/viewtopic_body.html
@@ -155,7 +155,10 @@
<!-- ELSE -->
<td align="center" valign="middle">
- <!-- IF postrow.S_FIRST_UNREAD --><a id="unread" class="anchor" data-url="{postrow.U_MINI_POST}"></a><!-- ENDIF --><a name="p{postrow.POST_ID}" class="anchor"></a>
+ <!-- IF postrow.S_FIRST_UNREAD -->
+ <a id="unread" class="anchor"<!-- IF S_UNREAD_VIEW --> data-url="{postrow.U_MINI_POST}"<!-- ENDIF -->></a>
+ <!-- ENDIF -->
+ <a name="p{postrow.POST_ID}" class="anchor"></a>
<b class="postauthor"<!-- IF postrow.POST_AUTHOR_COLOUR --> style="color: {postrow.POST_AUTHOR_COLOUR}"<!-- ENDIF -->>{postrow.POST_AUTHOR}</b>
</td>
<td width="100%" height="25">
diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php
index 789d53c676..d13d4b444f 100644
--- a/phpBB/viewtopic.php
+++ b/phpBB/viewtopic.php
@@ -635,6 +635,7 @@ $template->assign_vars(array(
'L_RETURN_TO_FORUM' => $user->lang('RETURN_TO', $topic_data['forum_name']),
'S_VIEWTOPIC' => true,
+ 'S_UNREAD_VIEW' => $view == 'unread',
'S_DISPLAY_SEARCHBOX' => ($auth->acl_get('u_search') && $auth->acl_get('f_search', $forum_id) && $config['load_search']) ? true : false,
'S_SEARCHBOX_ACTION' => append_sid("{$phpbb_root_path}search.$phpEx"),
'S_SEARCH_LOCAL_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields),
diff --git a/tests/auth/fixtures/user.xml b/tests/auth/fixtures/user.xml
index 77f707bab3..1e0eb6ee49 100644
--- a/tests/auth/fixtures/user.xml
+++ b/tests/auth/fixtures/user.xml
@@ -6,7 +6,6 @@
<column>username_clean</column>
<column>user_password</column>
<column>user_passchg</column>
- <column>user_pass_convert</column>
<column>user_email</column>
<column>user_type</column>
<column>user_login_attempts</column>
@@ -18,7 +17,6 @@
<value>foobar</value>
<value>$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i</value>
<value>0</value>
- <value>0</value>
<value>example@example.com</value>
<value>0</value>
<value>0</value>
@@ -31,7 +29,6 @@
<value>foobar2</value>
<value>$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/</value>
<value>0</value>
- <value>0</value>
<value>example@example.com</value>
<value>0</value>
<value>0</value>
diff --git a/tests/auth/fixtures/user_533.xml b/tests/auth/fixtures/user_533.xml
index b64f376e5b..9731e4db4a 100644
--- a/tests/auth/fixtures/user_533.xml
+++ b/tests/auth/fixtures/user_533.xml
@@ -6,7 +6,6 @@
<column>username_clean</column>
<column>user_password</column>
<column>user_passchg</column>
- <column>user_pass_convert</column>
<column>user_email</column>
<column>user_type</column>
<column>user_login_attempts</column>
@@ -18,7 +17,6 @@
<value>foobar</value>
<value>$2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi</value>
<value>0</value>
- <value>0</value>
<value>example@example.com</value>
<value>0</value>
<value>0</value>
@@ -31,7 +29,6 @@
<value>foobar2</value>
<value>$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/</value>
<value>0</value>
- <value>0</value>
<value>example@example.com</value>
<value>0</value>
<value>0</value>
diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php
index e17040902f..2decf0f18c 100644
--- a/tests/auth/provider_apache_test.php
+++ b/tests/auth/provider_apache_test.php
@@ -148,7 +148,6 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case
'username_clean' => 'foobar',
'user_password' => $this->password_hash,
'user_passchg' => '0',
- 'user_pass_convert' => '0',
'user_email' => 'example@example.com',
'user_email_hash' => '0',
'user_birthday' => '',
diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php
index f071709a4b..23324f87f2 100644
--- a/tests/auth/provider_db_test.php
+++ b/tests/auth/provider_db_test.php
@@ -70,7 +70,6 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case
'username' => 'foobar',
'user_password' => $password_hash,
'user_passchg' => '0',
- 'user_pass_convert' => '0',
'user_email' => 'example@example.com',
'user_type' => '0',
'user_login_attempts' => '0',
diff --git a/tests/console/cron/cron_list_test.php b/tests/console/cron/cron_list_test.php
new file mode 100644
index 0000000000..46705a585f
--- /dev/null
+++ b/tests/console/cron/cron_list_test.php
@@ -0,0 +1,103 @@
+<?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__) . '/tasks/simple_ready.php';
+require_once dirname(__FILE__) . '/tasks/simple_not_ready.php';
+
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Tester\CommandTester;
+use phpbb\console\command\cron\cron_list;
+
+class phpbb_console_command_cron_list_test extends phpbb_test_case
+{
+ /** @var \phpbb\cron\manager */
+ protected $cron_manager;
+
+ /** @var \phpbb\user */
+ protected $user;
+
+ protected $command_name;
+
+ protected $command_tester;
+
+ protected function setUp()
+ {
+ $this->user = $this->getMock('\phpbb\user');
+ $this->user->method('lang')->will($this->returnArgument(0));
+ }
+
+ public function test_no_task()
+ {
+ $this->initiate_test(0, 0);
+ $this->assertContains('CRON_NO_TASKS', $this->command_tester->getDisplay());
+ }
+
+ public function test_only_ready()
+ {
+ $this->initiate_test(2, 0);
+ $this->assertContains('TASKS_READY command1 command2', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay())));
+ }
+
+ public function test_only_not_ready()
+ {
+ $this->initiate_test(0, 2);
+ $this->assertContains('TASKS_NOT_READY command1 command2', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay())));
+ }
+
+ public function test_both_ready()
+ {
+ $this->initiate_test(2, 2);
+ $this->assertSame('TASKS_READY command1 command2 TASKS_NOT_READY command3 command4', preg_replace('/\s+/', ' ', trim($this->command_tester->getDisplay())));
+ }
+
+ public function get_cron_manager(array $tasks)
+ {
+ global $pathEx, $phpbb_root_path;
+ $i = 1;
+ foreach ($tasks as $task)
+ {
+ $task->set_name('command' . $i);
+ $i++;
+ }
+ $this->cron_manager = new \phpbb\cron\manager($tasks, $phpbb_root_path, $pathEx);
+ }
+
+ public function get_command_tester()
+ {
+ $application = new Application();
+ $application->add(new cron_list($this->cron_manager, $this->user));
+
+ $command = $application->find('cron:list');
+ $this->command_name = $command->getName();
+ return new CommandTester($command);
+ }
+
+ public function initiate_test($number_ready, $number_not_ready)
+ {
+ $tasks = array();
+
+ for ($i = 0; $i < $number_ready; $i++)
+ {
+ $tasks[] = new phpbb_cron_task_simple_ready();
+ }
+
+ for ($i = 0; $i < $number_not_ready; $i++)
+ {
+ $tasks[] = new phpbb_cron_task_simple_not_ready();
+ }
+
+ $this->get_cron_manager($tasks);
+ $this->command_tester = $this->get_command_tester();
+ $this->command_tester->execute(array('command' => $this->command_name, '--no-ansi' => true));
+ }
+}
diff --git a/tests/console/cron/tasks/simple_not_ready.php b/tests/console/cron/tasks/simple_not_ready.php
new file mode 100644
index 0000000000..887768e5fe
--- /dev/null
+++ b/tests/console/cron/tasks/simple_not_ready.php
@@ -0,0 +1,13 @@
+<?php
+
+class phpbb_cron_task_simple_not_ready extends \phpbb\cron\task\base
+{
+ public function run()
+ {
+ }
+
+ public function should_run()
+ {
+ return false;
+ }
+}
diff --git a/tests/console/cron/tasks/simple_ready.php b/tests/console/cron/tasks/simple_ready.php
new file mode 100644
index 0000000000..47970e104f
--- /dev/null
+++ b/tests/console/cron/tasks/simple_ready.php
@@ -0,0 +1,8 @@
+<?php
+
+class phpbb_cron_task_simple_ready extends \phpbb\cron\task\base
+{
+ public function run()
+ {
+ }
+}
diff --git a/tests/controller/helper_route_test.php b/tests/controller/helper_route_test.php
index df0794a047..621efaa830 100644
--- a/tests/controller/helper_route_test.php
+++ b/tests/controller/helper_route_test.php
@@ -42,12 +42,12 @@ class phpbb_controller_helper_route_test extends phpbb_test_case
)
);
- $finder = new \phpbb\extension\finder(
- $this->extension_manager,
+ $finder = new \phpbb\finder(
new \phpbb\filesystem(),
dirname(__FILE__) . '/',
new phpbb_mock_cache()
);
+ $finder->set_extensions(array_keys($this->extension_manager->all_enabled()));
$this->provider = new \phpbb\controller\provider();
$this->provider->find_routing_files($finder);
$this->provider->find(dirname(__FILE__) . '/');
diff --git a/tests/extension/finder_test.php b/tests/extension/finder_test.php
index 8cc5146b33..2116cc057b 100644
--- a/tests/extension/finder_test.php
+++ b/tests/extension/finder_test.php
@@ -14,7 +14,9 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_extension_finder_test extends phpbb_test_case
{
+ /** @var \phpbb\extension\manager */
protected $extension_manager;
+ /** @var \phpbb\finder */
protected $finder;
public function setUp()
@@ -56,6 +58,47 @@ class phpbb_extension_finder_test extends phpbb_test_case
);
}
+ public function set_extensions_data()
+ {
+ return array(
+ array(
+ array(),
+ array('\phpbb\default\implementation'),
+ ),
+ array(
+ array('vendor3/bar'),
+ array(
+ '\phpbb\default\implementation',
+ '\vendor3\bar\my\hidden_class',
+ ),
+ ),
+ array(
+ array('vendor2/foo', 'vendor3/bar'),
+ array(
+ '\phpbb\default\implementation',
+ '\vendor2\foo\a_class',
+ '\vendor2\foo\b_class',
+ '\vendor3\bar\my\hidden_class',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * @dataProvider set_extensions_data
+ */
+ public function test_set_extensions($extensions, $expected)
+ {
+ $classes = $this->finder
+ ->set_extensions($extensions)
+ ->core_path('phpbb/default/')
+ ->extension_suffix('_class')
+ ->get_classes();
+
+ sort($classes);
+ $this->assertEquals($expected, $classes);
+ }
+
public function test_get_directories()
{
$dirs = $this->finder
@@ -201,7 +244,8 @@ class phpbb_extension_finder_test extends phpbb_test_case
public function test_get_classes_create_cache()
{
$cache = new phpbb_mock_cache;
- $finder = new \phpbb\extension\finder($this->extension_manager, new \phpbb\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name');
+ $finder = new \phpbb\finder(new \phpbb\filesystem(), dirname(__FILE__) . '/', $cache, 'php', '_custom_cache_name');
+ $finder->set_extensions(array_keys($this->extension_manager->all_enabled()));
$files = $finder->suffix('_class.php')->get_files();
$expected_files = array(
@@ -239,8 +283,7 @@ class phpbb_extension_finder_test extends phpbb_test_case
'is_dir' => false,
);
- $finder = new \phpbb\extension\finder(
- $this->extension_manager,
+ $finder = new \phpbb\finder(
new \phpbb\filesystem(),
dirname(__FILE__) . '/',
new phpbb_mock_cache(array(
@@ -249,6 +292,7 @@ class phpbb_extension_finder_test extends phpbb_test_case
),
))
);
+ $finder->set_extensions(array_keys($this->extension_manager->all_enabled()));
$classes = $finder
->core_path($query['core_path'])
diff --git a/tests/functional/visibility_softdelete_test.php b/tests/functional/visibility_softdelete_test.php
index bc722ea043..5b5f09905c 100644
--- a/tests/functional/visibility_softdelete_test.php
+++ b/tests/functional/visibility_softdelete_test.php
@@ -595,8 +595,15 @@ class phpbb_functional_visibility_softdelete_test extends phpbb_functional_test_
'forum_last_post_id' => $this->data['posts']['Soft Delete Topic #1'],
), 'before merging #1');
+ $this->add_lang('viewtopic');
$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Soft Delete Topic #2']}&sid={$this->sid}");
+ $bookmark_tag = $crawler->filter('a.bookmark-link');
+ $this->assertContainsLang('BOOKMARK_TOPIC', $bookmark_tag->text());
+ $bookmark_link = $bookmark_tag->attr('href');
+ $crawler_bookmark = self::request('GET', $bookmark_link);
+ $this->assertContainsLang('BOOKMARK_ADDED', $crawler_bookmark->text());
+
$this->add_lang('mcp');
$form = $crawler->selectButton('Go')->eq(1)->form();
$form['action']->select('merge_topic');
@@ -613,6 +620,7 @@ class phpbb_functional_visibility_softdelete_test extends phpbb_functional_test_
$crawler = self::request('GET', "viewtopic.php?t={$this->data['topics']['Soft Delete Topic #1']}&sid={$this->sid}");
$this->assertContains('Soft Delete Topic #1', $crawler->filter('h2')->text());
$this->assertContainsLang('POST_DELETED_ACTION', $crawler->filter('body')->text());
+ $this->assertContainsLang('BOOKMARK_TOPIC_REMOVE', $crawler->filter('body')->text());
$this->assert_forum_details($this->data['forums']['Soft Delete #1'], array(
'forum_posts_approved' => 1,
diff --git a/tests/functions/validate_email_test.php b/tests/functions/validate_email_test.php
index dbd4b05520..b46509fda7 100644
--- a/tests/functions/validate_email_test.php
+++ b/tests/functions/validate_email_test.php
@@ -1,13 +1,9 @@
<?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.
+* @package testing
+* @copyright (c) 2014 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
@@ -51,60 +47,54 @@ class phpbb_functions_validate_email_test extends phpbb_database_test_case
$user->optionset('banned_users', array('banned@example.com'));
}
- public function test_validate_email()
+ public static function validate_email_data()
+ {
+ return array(
+ array('empty', array('EMAIL_INVALID'), ''), // email does not allow empty
+ array('allowed', array(), 'foobar@example.com'),
+ array('valid_complex', array(), "'%$~test@example.com"),
+ array('invalid', array('EMAIL_INVALID'), 'fööbar@example.com'),
+ array('taken', array(), 'admin@example.com'), // email does not check taken, should use user_email instead
+ array('banned', array(), 'banned@example.com'), // email does not check ban, should use user_email instead
+ );
+ }
+
+ /**
+ * @dataProvider validate_email_data
+ */
+ public function test_validate_email($case, $errors, $email)
{
$this->set_validation_prerequisites(false);
$this->helper->assert_valid_data(array(
- 'empty' => array(
- array(),
- '',
- array('email'),
- ),
- 'allowed' => array(
- array(),
- 'foobar@example.com',
- array('email', 'foobar@example.com'),
- ),
- 'invalid' => array(
- array('EMAIL_INVALID'),
- 'fööbar@example.com',
- array('email'),
- ),
- 'valid_complex' => array(
- array(),
- "'%$~test@example.com",
- array('email'),
- ),
- 'taken' => array(
- array('EMAIL_TAKEN'),
- 'admin@example.com',
- array('email'),
- ),
- 'banned' => array(
- array('EMAIL_BANNED'),
- 'banned@example.com',
+ $case => array(
+ $errors,
+ $email,
array('email'),
),
));
}
+ public static function validate_email_mx_data()
+ {
+ return array(
+ array('valid', array(), 'foobar@phpbb.com'),
+ array('no_mx', array('DOMAIN_NO_MX_RECORD'), 'test@does-not-exist.phpbb.com'),
+ );
+ }
+
/**
+ * @dataProvider validate_email_mx_data
* @group slow
*/
- public function test_validate_email_mx()
+ public function test_validate_email_mx($case, $errors, $email)
{
$this->set_validation_prerequisites(true);
$this->helper->assert_valid_data(array(
- 'valid' => array(
- array(),
- 'foobar@phpbb.com',
- array('email'),
- ),
- 'no_mx' => array(
- array('DOMAIN_NO_MX_RECORD'),
- 'test@does-not-exist.phpbb.com',
+ $case => array(
+ $errors,
+ $email,
array('email'),
),
));
diff --git a/tests/functions/validate_user_email_test.php b/tests/functions/validate_user_email_test.php
new file mode 100644
index 0000000000..951d5794e6
--- /dev/null
+++ b/tests/functions/validate_user_email_test.php
@@ -0,0 +1,106 @@
+<?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.php';
+require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php';
+require_once dirname(__FILE__) . '/../mock/user.php';
+require_once dirname(__FILE__) . '/validate_data_helper.php';
+
+class phpbb_functions_validate_user_email_test extends phpbb_database_test_case
+{
+ protected $db;
+ protected $user;
+ protected $helper;
+
+ public function getDataSet()
+ {
+ return $this->createXMLDataSet(dirname(__FILE__) . '/fixtures/validate_email.xml');
+ }
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->db = $this->new_dbal();
+ $this->user = new phpbb_mock_user;
+ $this->helper = new phpbb_functions_validate_data_helper($this);
+ }
+
+ /**
+ * Get validation prerequesites
+ *
+ * @param bool $check_mx Whether mx records should be checked
+ */
+ protected function set_validation_prerequisites($check_mx)
+ {
+ global $config, $db, $user;
+
+ $config['email_check_mx'] = $check_mx;
+ $db = $this->db;
+ $user = $this->user;
+ $user->optionset('banned_users', array('banned@example.com'));
+ }
+
+ public static function validate_user_email_data()
+ {
+ return array(
+ array('empty', array(), ''),
+ array('allowed', array(), 'foobar@example.com'),
+ array('valid_complex', array(), "'%$~test@example.com"),
+ array('invalid', array('EMAIL_INVALID'), 'fööbar@example.com'),
+ array('taken', array('EMAIL_TAKEN'), 'admin@example.com'),
+ array('banned', array('EMAIL_BANNED'), 'banned@example.com'),
+ );
+ }
+
+ /**
+ * @dataProvider validate_user_email_data
+ */
+ public function test_validate_user_email($case, $errors, $email)
+ {
+ $this->set_validation_prerequisites(false);
+
+ $this->helper->assert_valid_data(array(
+ $case => array(
+ $errors,
+ $email,
+ array('user_email'),
+ ),
+ ));
+ }
+
+ public static function validate_user_email_mx_data()
+ {
+ return array(
+ array('valid', array(), 'foobar@phpbb.com'),
+ array('no_mx', array('DOMAIN_NO_MX_RECORD'), 'test@does-not-exist.phpbb.com'),
+ );
+ }
+
+ /**
+ * @dataProvider validate_user_email_mx_data
+ * @group slow
+ */
+ public function test_validate_user_email_mx($case, $errors, $email)
+ {
+ $this->set_validation_prerequisites(true);
+
+ $this->helper->assert_valid_data(array(
+ $case => array(
+ $errors,
+ $email,
+ array('user_email'),
+ ),
+ ));
+ }
+}
diff --git a/tests/mock/request.php b/tests/mock/request.php
index 89d5321a25..304fcf0eaf 100644
--- a/tests/mock/request.php
+++ b/tests/mock/request.php
@@ -15,6 +15,8 @@ class phpbb_mock_request implements \phpbb\request\request_interface
{
protected $data;
+ protected $super_globals_disabled = false;
+
public function __construct($get = array(), $post = array(), $cookie = array(), $server = array(), $request = false, $files = array())
{
$this->data[\phpbb\request\request_interface::GET] = $get;
@@ -23,6 +25,8 @@ class phpbb_mock_request implements \phpbb\request\request_interface
$this->data[\phpbb\request\request_interface::REQUEST] = ($request === false) ? $post + $get : $request;
$this->data[\phpbb\request\request_interface::SERVER] = $server;
$this->data[\phpbb\request\request_interface::FILES] = $files;
+
+ $this->disable_super_globals();
}
public function overwrite($var_name, $value, $super_global = \phpbb\request\request_interface::REQUEST)
@@ -83,6 +87,21 @@ class phpbb_mock_request implements \phpbb\request\request_interface
return $this->data[$super_global];
}
+ public function super_globals_disabled()
+ {
+ return $this->super_globals_disabled;
+ }
+
+ public function disable_super_globals()
+ {
+ $this->super_globals_disabled = true;
+ }
+
+ public function enable_super_globals()
+ {
+ $this->super_globals_disabled = false;
+ }
+
/* custom methods */
public function set_header($header_name, $value)
diff --git a/tests/notification/notification_test.php b/tests/notification/notification_test.php
index 799dcc5e22..27ea8ddb44 100644
--- a/tests/notification/notification_test.php
+++ b/tests/notification/notification_test.php
@@ -71,6 +71,27 @@ class phpbb_notification_test extends phpbb_tests_notification_base
public function test_subscriptions()
{
+ $expected_subscriptions = array(
+ 'post' => array(''),
+ 'topic' => array(''),
+ 'quote' => array(''),
+ 'bookmark' => array(''),
+ 'test' => array(''),
+ 'pm' => array(''),
+ );
+
+ $subscriptions = $this->notifications->get_global_subscriptions(2);
+
+ foreach ($expected_subscriptions as $item_type => $methods)
+ {
+ $this->assert_array_content_equals($methods, $subscriptions[$item_type]);
+ }
+
+ foreach ($subscriptions as $item_type => $methods)
+ {
+ $this->assert_array_content_equals($methods, $expected_subscriptions[$item_type]);
+ }
+
$this->notifications->delete_subscription('post', 0, '', 2);
$this->assertArrayNotHasKey('post', $this->notifications->get_global_subscriptions(2));
diff --git a/tests/pagination/pagination_test.php b/tests/pagination/pagination_test.php
index 4846dd83f7..ace8c1eed0 100644
--- a/tests/pagination/pagination_test.php
+++ b/tests/pagination/pagination_test.php
@@ -35,16 +35,16 @@ class phpbb_pagination_pagination_test extends phpbb_template_template_test_case
->will($this->returnCallback(array($this, 'return_callback_implode')));
$manager = new phpbb_mock_extension_manager(dirname(__FILE__) . '/', array());
- $this->finder = new \phpbb\extension\finder(
- $manager,
+ $finder = new \phpbb\finder(
new \phpbb\filesystem(),
dirname(__FILE__) . '/',
new phpbb_mock_cache()
);
+ $finder->set_extensions(array_keys($manager->all_enabled()));
$this->config = new \phpbb\config\config(array('enable_mod_rewrite' => '1'));
$provider = new \phpbb\controller\provider();
- $provider->find_routing_files($this->finder);
+ $provider->find_routing_files($finder);
$provider->find(dirname(__FILE__) . '/');
$this->helper = new phpbb_mock_controller_helper($this->template, $this->user, $this->config, $provider, $manager, '', 'php', dirname(__FILE__) . '/');
$this->pagination = new \phpbb\pagination($this->template, $this->user, $this->helper);
diff --git a/tests/passwords/drivers_test.php b/tests/passwords/drivers_test.php
index c2104b0858..ccfb05c40f 100644
--- a/tests/passwords/drivers_test.php
+++ b/tests/passwords/drivers_test.php
@@ -17,14 +17,26 @@ class phpbb_passwords_helper_test extends \phpbb_test_case
{
// Prepare dependencies for drivers
$config = new \phpbb\config\config(array());
+ $request = new phpbb_mock_request(array(), array(), array(), array(), array('password' => 'fööbar'));
$this->driver_helper = new \phpbb\passwords\driver\helper($config);
+ $phpbb_root_path = dirname(__FILE__) . '/../../phpBB/';
+ $php_ext = 'php';
$this->passwords_drivers = array(
'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper),
- 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper),
+ 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper),
'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper),
- 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper),
+ 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper),
+ 'passwords.driver.sha1_smf' => new \phpbb\passwords\driver\sha1_smf($config, $this->driver_helper),
+ 'passwords.driver.sha1_wcf1' => new \phpbb\passwords\driver\sha1_wcf1($config, $this->driver_helper),
+ 'passwords.driver.convert_password'=> new \phpbb\passwords\driver\convert_password($config, $this->driver_helper),
+ 'passwords.driver.sha1' => new \phpbb\passwords\driver\sha1($config, $this->driver_helper),
+ 'passwords.driver.md5_mybb' => new \phpbb\passwords\driver\md5_mybb($config, $this->driver_helper),
+ 'passwords.driver.md5_vb' => new \phpbb\passwords\driver\md5_vb($config, $this->driver_helper),
+ 'passwords.driver.sha_xf1' => new \phpbb\passwords\driver\sha_xf1($config, $this->driver_helper),
);
+ $this->passwords_drivers['passwords.driver.md5_phpbb2'] = new \phpbb\passwords\driver\md5_phpbb2($request, $this->passwords_drivers['passwords.driver.salted_md5'], $phpbb_root_path, $php_ext);
+ $this->passwords_drivers['passwords.driver.bcrypt_wcf2'] = new \phpbb\passwords\driver\bcrypt_wcf2($this->passwords_drivers['passwords.driver.bcrypt'], $this->driver_helper);
}
public function data_helper_encode64()
@@ -82,4 +94,323 @@ class phpbb_passwords_helper_test extends \phpbb_test_case
);
$this->assertEquals(false, $this->passwords_drivers['passwords.driver.salted_md5']->get_hash_settings(false));
}
+
+ public function data_hash_sha1_smf()
+ {
+ return array(
+ array(false, 'test', array()),
+ array(false, 'test', ''),
+ array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', 'foobar', array('login_name' => 'test')),
+ );
+ }
+
+ /**
+ * @dataProvider data_hash_sha1_smf
+ */
+ public function test_hash_sha1_smf($expected, $password, $user_row)
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha1_smf']->hash($password, $user_row));
+ }
+
+ public function data_get_settings()
+ {
+ return array(
+ array(false, '6f9e2a1899e1f15708fd2e554103480eb53e8b57', 'passwords.driver.sha1_smf'),
+ );
+ }
+
+ /**
+ * @dataProvider data_get_settings
+ */
+ public function test_get_settings_only($expected, $hash, $driver)
+ {
+ $this->assertSame($expected, $this->passwords_drivers[$driver]->get_settings_only($hash));
+ }
+
+ public function data_md5_phpbb2_check()
+ {
+ return array(
+ array(false, 'foobar', 'ae2fc75e20ee25d4520766788fbc96ae'),
+ array(false, 'foobar', 'ae2fc75e20ee25d4520766788fbc96aeddsf'),
+ array(false, 'fööbar', 'ae2fc75e20ee25d4520766788fbc96ae'),
+ array(true, 'fööbar', 'ae2fc75e20ee25d4520766788fbc96ae', utf8_decode('fööbar')),
+ array(true, 'fööbar', '$H$966CepJh9RC3hFIm7aKywR6jEn0kpA0', utf8_decode('fööbar')),
+ array(true, 'fööbar', '$H$9rNjgwETtmc8befO8JL1xFMrrMw8MC.', $this->utf8_to_cp1252(utf8_decode('fööbar'))),
+ array(true, 'fööbar', '$H$9rNjgwETtmc8befO8JL1xFMrrMw8MC.', $this->utf8_to_cp1252('fööbar')),
+ );
+ }
+
+ /**
+ * @dataProvider data_md5_phpbb2_check
+ */
+ public function test_md5_phpbb2_check($expected, $password, $hash, $request_password = false)
+ {
+ if (!$request_password)
+ {
+ unset($_REQUEST['password']);
+ }
+ else
+ {
+ $_REQUEST['password'] = $request_password;
+ }
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_phpbb2']->check($password, $hash));
+ }
+
+ public function test_md5_phpbb2_hash()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_phpbb2']->hash('foobar'));
+ }
+
+ public function test_convert_password_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.convert_password']->hash('foobar'));
+ }
+
+ public function test_sha1_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha1']->hash('foobar'));
+ }
+
+ public function data_md5_mybb_check()
+ {
+ return array(
+ array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd'),
+ array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd', array('user_passwd_salt' => 'ae2fc75e')),
+ array(true, 'foobar', 'b86ee7e24008bfd2890dcfab1ed31333', array('user_passwd_salt' => 'yeOtfFO6')),
+ );
+ }
+
+ /**
+ * @dataProvider data_md5_mybb_check
+ */
+ public function test_md5_mybb_check($expected, $password, $hash, $user_row = array())
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_mybb']->check($password, $hash, $user_row));
+ }
+
+ public function test_md5_mybb_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_mybb']->hash('foobar'));
+ }
+
+ public function data_md5_vb_check()
+ {
+ return array(
+ array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd'),
+ array(false, 'foobar', 'b86ee7e24008bfd2890dcfab1ed31333', array('user_passwd_salt' => 'yeOtfFO6')),
+ array(true, 'foobar', 'b452c54c44c588fc095d2d000935c470', array('user_passwd_salt' => '9^F')),
+ array(true, 'foobar', 'f23a8241bd115d270c703213e3ef7f52', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')),
+ array(false, 'nope', 'f23a8241bd115d270c703213e3ef7f52', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')),
+ );
+ }
+
+ /**
+ * @dataProvider data_md5_vb_check
+ */
+ public function test_md5_vb_check($expected, $password, $hash, $user_row = array())
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_vb']->check($password, $hash, $user_row));
+ }
+
+ public function test_md5_vb_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_vb']->hash('foobar'));
+ }
+
+ public function data_sha1_wcf1_check()
+ {
+ return array(
+ array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'),
+ array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => 'yeOtfFO6')),
+ array(true, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => '1a783e478d63f6422783a868db667aed3a857840')),
+ );
+ }
+
+ /**
+ * @dataProvider data_sha1_wcf1_check
+ */
+ public function test_sha1_wcf1_check($expected, $password, $hash, $user_row = array())
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha1_wcf1']->check($password, $hash, $user_row));
+ }
+
+ public function test_sha1_wcf1_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha1_wcf1']->hash('foobar'));
+ }
+
+ public function data_bcrypt_wcf2_check()
+ {
+ return array(
+ array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'),
+ array(true, 'foobar', '$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi'),
+ array(false, 'foobar', ''),
+ );
+ }
+
+ /**
+ * @dataProvider data_bcrypt_wcf2_check
+ */
+ public function test_bcrypt_wcf2_check($expected, $password, $hash)
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.bcrypt_wcf2']->check($password, $hash));
+ }
+
+ public function test_bcrypt_wcf2_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.bcrypt_wcf2']->hash('foobar'));
+ }
+
+ public function data_sha_xf1_check()
+ {
+ return array(
+ array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'),
+ array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => 'yeOtfFO6')),
+ array(true, 'foobar', '7f65d2fa8a826d232f8134772252f8b1aaef8594b1edcabd9ab65e5b0f236ff0', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')),
+ array(true, 'foobar', '69962ae2079420573a3948cc4dedbabd35680051', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')),
+ );
+ }
+
+ /**
+ * @dataProvider data_sha_xf1_check
+ */
+ public function test_sha_xf1_check($expected, $password, $hash, $user_row = array())
+ {
+ $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha_xf1']->check($password, $hash, $user_row));
+ }
+
+ public function test_sha_xf1_driver()
+ {
+ $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha_xf1']->hash('foobar'));
+ }
+
+ protected function utf8_to_cp1252($string)
+ {
+ static $transform = array(
+ "\xE2\x82\xAC" => "\x80",
+ "\xE2\x80\x9A" => "\x82",
+ "\xC6\x92" => "\x83",
+ "\xE2\x80\x9E" => "\x84",
+ "\xE2\x80\xA6" => "\x85",
+ "\xE2\x80\xA0" => "\x86",
+ "\xE2\x80\xA1" => "\x87",
+ "\xCB\x86" => "\x88",
+ "\xE2\x80\xB0" => "\x89",
+ "\xC5\xA0" => "\x8A",
+ "\xE2\x80\xB9" => "\x8B",
+ "\xC5\x92" => "\x8C",
+ "\xC5\xBD" => "\x8E",
+ "\xE2\x80\x98" => "\x91",
+ "\xE2\x80\x99" => "\x92",
+ "\xE2\x80\x9C" => "\x93",
+ "\xE2\x80\x9D" => "\x94",
+ "\xE2\x80\xA2" => "\x95",
+ "\xE2\x80\x93" => "\x96",
+ "\xE2\x80\x94" => "\x97",
+ "\xCB\x9C" => "\x98",
+ "\xE2\x84\xA2" => "\x99",
+ "\xC5\xA1" => "\x9A",
+ "\xE2\x80\xBA" => "\x9B",
+ "\xC5\x93" => "\x9C",
+ "\xC5\xBE" => "\x9E",
+ "\xC5\xB8" => "\x9F",
+ "\xC2\xA0" => "\xA0",
+ "\xC2\xA1" => "\xA1",
+ "\xC2\xA2" => "\xA2",
+ "\xC2\xA3" => "\xA3",
+ "\xC2\xA4" => "\xA4",
+ "\xC2\xA5" => "\xA5",
+ "\xC2\xA6" => "\xA6",
+ "\xC2\xA7" => "\xA7",
+ "\xC2\xA8" => "\xA8",
+ "\xC2\xA9" => "\xA9",
+ "\xC2\xAA" => "\xAA",
+ "\xC2\xAB" => "\xAB",
+ "\xC2\xAC" => "\xAC",
+ "\xC2\xAD" => "\xAD",
+ "\xC2\xAE" => "\xAE",
+ "\xC2\xAF" => "\xAF",
+ "\xC2\xB0" => "\xB0",
+ "\xC2\xB1" => "\xB1",
+ "\xC2\xB2" => "\xB2",
+ "\xC2\xB3" => "\xB3",
+ "\xC2\xB4" => "\xB4",
+ "\xC2\xB5" => "\xB5",
+ "\xC2\xB6" => "\xB6",
+ "\xC2\xB7" => "\xB7",
+ "\xC2\xB8" => "\xB8",
+ "\xC2\xB9" => "\xB9",
+ "\xC2\xBA" => "\xBA",
+ "\xC2\xBB" => "\xBB",
+ "\xC2\xBC" => "\xBC",
+ "\xC2\xBD" => "\xBD",
+ "\xC2\xBE" => "\xBE",
+ "\xC2\xBF" => "\xBF",
+ "\xC3\x80" => "\xC0",
+ "\xC3\x81" => "\xC1",
+ "\xC3\x82" => "\xC2",
+ "\xC3\x83" => "\xC3",
+ "\xC3\x84" => "\xC4",
+ "\xC3\x85" => "\xC5",
+ "\xC3\x86" => "\xC6",
+ "\xC3\x87" => "\xC7",
+ "\xC3\x88" => "\xC8",
+ "\xC3\x89" => "\xC9",
+ "\xC3\x8A" => "\xCA",
+ "\xC3\x8B" => "\xCB",
+ "\xC3\x8C" => "\xCC",
+ "\xC3\x8D" => "\xCD",
+ "\xC3\x8E" => "\xCE",
+ "\xC3\x8F" => "\xCF",
+ "\xC3\x90" => "\xD0",
+ "\xC3\x91" => "\xD1",
+ "\xC3\x92" => "\xD2",
+ "\xC3\x93" => "\xD3",
+ "\xC3\x94" => "\xD4",
+ "\xC3\x95" => "\xD5",
+ "\xC3\x96" => "\xD6",
+ "\xC3\x97" => "\xD7",
+ "\xC3\x98" => "\xD8",
+ "\xC3\x99" => "\xD9",
+ "\xC3\x9A" => "\xDA",
+ "\xC3\x9B" => "\xDB",
+ "\xC3\x9C" => "\xDC",
+ "\xC3\x9D" => "\xDD",
+ "\xC3\x9E" => "\xDE",
+ "\xC3\x9F" => "\xDF",
+ "\xC3\xA0" => "\xE0",
+ "\xC3\xA1" => "\xE1",
+ "\xC3\xA2" => "\xE2",
+ "\xC3\xA3" => "\xE3",
+ "\xC3\xA4" => "\xE4",
+ "\xC3\xA5" => "\xE5",
+ "\xC3\xA6" => "\xE6",
+ "\xC3\xA7" => "\xE7",
+ "\xC3\xA8" => "\xE8",
+ "\xC3\xA9" => "\xE9",
+ "\xC3\xAA" => "\xEA",
+ "\xC3\xAB" => "\xEB",
+ "\xC3\xAC" => "\xEC",
+ "\xC3\xAD" => "\xED",
+ "\xC3\xAE" => "\xEE",
+ "\xC3\xAF" => "\xEF",
+ "\xC3\xB0" => "\xF0",
+ "\xC3\xB1" => "\xF1",
+ "\xC3\xB2" => "\xF2",
+ "\xC3\xB3" => "\xF3",
+ "\xC3\xB4" => "\xF4",
+ "\xC3\xB5" => "\xF5",
+ "\xC3\xB6" => "\xF6",
+ "\xC3\xB7" => "\xF7",
+ "\xC3\xB8" => "\xF8",
+ "\xC3\xB9" => "\xF9",
+ "\xC3\xBA" => "\xFA",
+ "\xC3\xBB" => "\xFB",
+ "\xC3\xBC" => "\xFC",
+ "\xC3\xBD" => "\xFD",
+ "\xC3\xBE" => "\xFE",
+ "\xC3\xBF" => "\xFF"
+ );
+ return strtr($string, $transform);
+ }
}
diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php
index f9244d59f2..e46cf820f2 100644
--- a/tests/passwords/manager_test.php
+++ b/tests/passwords/manager_test.php
@@ -24,13 +24,25 @@ class phpbb_passwords_manager_test extends \phpbb_test_case
// Prepare dependencies for manager and driver
$config = new \phpbb\config\config(array());
$this->driver_helper = new \phpbb\passwords\driver\helper($config);
+ $request = new phpbb_mock_request(array(), array(), array(), array(), array('password' => 'töst'));
+ $phpbb_root_path = dirname(__FILE__) . '/../../phpBB/';
+ $php_ext = 'php';
$this->passwords_drivers = array(
- 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper),
+ 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper),
'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper),
- 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper),
+ 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper),
'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper),
+ 'passwords.driver.convert_password' => new \phpbb\passwords\driver\convert_password($config, $this->driver_helper),
+ 'passwords.driver.sha1_smf' => new \phpbb\passwords\driver\sha1_smf($config, $this->driver_helper),
+ 'passwords.driver.sha1' => new \phpbb\passwords\driver\sha1($config, $this->driver_helper),
+ 'passwords.driver.sha1_wcf1' => new \phpbb\passwords\driver\sha1_wcf1($config, $this->driver_helper),
+ 'passwords.driver.md5_mybb' => new \phpbb\passwords\driver\md5_mybb($config, $this->driver_helper),
+ 'passwords.driver.md5_vb' => new \phpbb\passwords\driver\md5_vb($config, $this->driver_helper),
+ 'passwords.driver.sha_xf1' => new \phpbb\passwords\driver\sha_xf1($config, $this->driver_helper),
);
+ $this->passwords_drivers['passwords.driver.md5_phpbb2'] = new \phpbb\passwords\driver\md5_phpbb2($request, $this->passwords_drivers['passwords.driver.salted_md5'], $phpbb_root_path, $php_ext);
+ $this->passwords_drivers['passwords.driver.bcrypt_wcf2'] = new \phpbb\passwords\driver\bcrypt_wcf2($this->passwords_drivers['passwords.driver.bcrypt'], $this->driver_helper);
$this->helper = new \phpbb\passwords\helper;
// Set up passwords manager
@@ -132,21 +144,39 @@ class phpbb_passwords_manager_test extends \phpbb_test_case
public function check_hash_exceptions_data()
{
return array(
- array('foobar', '3858f62230ac3c915f300c664312c63f', true),
- array('foobar', '$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false),
- array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false),
- array('foobar', '$H$kklk938d023k//k3023', false),
- array('foobar', '$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false),
- array('foobar', '$2a$kwiweorurlaeirw', false),
+ array('3858f62230ac3c915f300c664312c63f', true),
+ array('$CP$3858f62230ac3c915f300c664312c63f', true), // md5_phpbb2
+ array('$CP$3858f62230ac3c915f300c', false),
+ array('$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false),
+ array('$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false),
+ array('$H$kklk938d023k//k3023', false),
+ array('$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false),
+ array('$2a$kwiweorurlaeirw', false),
+ array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', false),
+ array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', false, 'foobar', array('login_name' => 'test')),
+ array('$CP$6f9e2a1899e1f15708fd2e554103480eb53e8b57', true, 'foobar', array('login_name' => 'test')), // sha1_smf
+ array('6f9e2a1899', false, 'foobar', array('login_name' => 'test')),
+ array('ae2fc75e20ee25d4520766788fbc96ae', false, 'fööbar'),
+ array('$CP$ae2fc75e20ee25d4520766788fbc96ae', false, 'fööbar'),
+ array('$CP$ae2fc75e20ee25d4520766788fbc96ae', true, utf8_decode('fööbar')), // md5_phpbb2
+ array('b86ee7e24008bfd2890dcfab1ed31333', false, 'foobar', array('user_passwd_salt' => 'yeOtfFO6')),
+ array('$CP$b86ee7e24008bfd2890dcfab1ed31333', true, 'foobar', array('user_passwd_salt' => 'yeOtfFO6')), // md5_mybb
+ array('$CP$b452c54c44c588fc095d2d000935c470', true, 'foobar', array('user_passwd_salt' => '9^F')), // md5_vb
+ array('$CP$f23a8241bd115d270c703213e3ef7f52', true, 'foobar', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')), // md5_vb
+ array('$CP$fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', true, 'foobar', array('user_passwd_salt' => '1a783e478d63f6422783a868db667aed3a857840')), // sha_wcf1
+ array('$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi', false),
+ array('$CP$$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi', true), // bcrypt_wcf2
+ array('$CP$7f65d2fa8a826d232f8134772252f8b1aaef8594b1edcabd9ab65e5b0f236ff0', true, 'foobar', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), // sha_xf1
+ array('$CP$69962ae2079420573a3948cc4dedbabd35680051', true, 'foobar', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), // sha_xf1
);
}
/**
* @dataProvider check_hash_exceptions_data
*/
- public function test_check_hash_exceptions($password, $hash, $expected)
+ public function test_check_hash_exceptions($hash, $expected, $password = 'foobar', $user_row = array())
{
- $this->assertEquals($expected, $this->manager->check($password, $hash));
+ $this->assertEquals($expected, $this->manager->check($password, $hash, $user_row));
}
public function data_hash_password_length()
diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php
index 81724cf661..3e25286480 100644
--- a/tests/session/testable_factory.php
+++ b/tests/session/testable_factory.php
@@ -96,6 +96,12 @@ class phpbb_session_testable_factory
'auth.provider.db',
new phpbb_mock_auth_provider()
);
+ $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config);
+ $provider_collection->add('auth.provider.db');
+ $phpbb_container->set(
+ 'auth.provider_collection',
+ $provider_collection
+ );
$session = new phpbb_mock_session_testable;
return $session;
diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php
index 60ac68e7b8..1f3a564205 100644
--- a/tests/test_framework/phpbb_database_test_case.php
+++ b/tests/test_framework/phpbb_database_test_case.php
@@ -21,6 +21,12 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
protected $fixture_xml_data;
+ static protected $schema_file;
+
+ static protected $phpbb_schema_copy;
+
+ static protected $install_schema_file;
+
public function __construct($name = NULL, array $data = array(), $dataName = '')
{
parent::__construct($name, $data, $dataName);
@@ -38,6 +44,62 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
$this->db_connections = array();
}
+ /**
+ * @return array List of extensions that should be set up
+ */
+ static protected function setup_extensions()
+ {
+ return array();
+ }
+
+ static public function setUpBeforeClass()
+ {
+ $setup_extensions = static::setup_extensions();
+ self::$schema_file = '';
+ if (!empty($setup_extensions))
+ {
+ $schema_md5 = md5(serialize($setup_extensions));
+
+ self::$schema_file = __DIR__ . '/../tmp/' . $schema_md5 . '.json';
+ self::$phpbb_schema_copy = __DIR__ . '/../tmp/schema_phpbb_copy.json';
+ self::$install_schema_file = __DIR__ . '/../../phpBB/install/schemas/schema.json';
+
+ if (!file_exists(self::$schema_file))
+ {
+ global $phpbb_root_path, $phpEx, $table_prefix;
+
+ $finder = new \phpbb\finder(new \phpbb\filesystem(), $phpbb_root_path, null, $phpEx);
+ $classes = $finder->core_path('phpbb/')
+ ->core_directory('/db/migration/data')
+ ->set_extensions($setup_extensions)
+ ->extension_directory('migrations')
+ ->get_classes();
+
+ $db = new \phpbb\db\driver\sqlite();
+ $schema_generator = new \phpbb\db\migration\schema_generator($classes, new \phpbb\config\config(array()), $db, new \phpbb\db\tools($db, true), $phpbb_root_path, $phpEx, $table_prefix);
+ $schema_data = $schema_generator->get_schema();
+
+ file_put_contents(self::$schema_file, json_encode($schema_data));
+ }
+
+ copy(self::$install_schema_file, self::$phpbb_schema_copy);
+ copy(self::$schema_file, self::$install_schema_file);
+ }
+
+ parent::setUpBeforeClass();
+ }
+
+ static public function tearDownAfterClass()
+ {
+ if (self::$schema_file !== '')
+ {
+ copy(self::$phpbb_schema_copy, self::$install_schema_file);
+ unlink(self::$schema_file);
+ }
+
+ parent::tearDownAfterClass();
+ }
+
protected function tearDown()
{
parent::tearDown();
@@ -151,8 +213,6 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test
public function new_dbal()
{
- global $phpbb_root_path, $phpEx;
-
$config = $this->get_database_config();
$db = new $config['dbms']();
diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php
index 182ffaaaf7..e4504a5f8d 100644
--- a/tests/test_framework/phpbb_functional_test_case.php
+++ b/tests/test_framework/phpbb_functional_test_case.php
@@ -64,6 +64,14 @@ class phpbb_functional_test_case extends phpbb_test_case
}
}
+ /**
+ * @return array List of extensions that should be set up
+ */
+ static protected function setup_extensions()
+ {
+ return array();
+ }
+
public function setUp()
{
parent::setUp();
@@ -81,6 +89,34 @@ class phpbb_functional_test_case extends phpbb_test_case
$this->lang = array();
$this->add_lang('common');
$this->purge_cache();
+
+ $db = $this->get_db();
+
+ foreach (static::setup_extensions() as $extension)
+ {
+ $sql = 'SELECT ext_active
+ FROM ' . EXT_TABLE . "
+ WHERE ext_name = '" . $db->sql_escape($extension). "'";
+ $result = $db->sql_query($sql);
+ $status = (bool) $db->sql_fetchfield('ext_active');
+ $db->sql_freeresult($result);
+
+ if (!$status)
+ {
+ $this->install_ext($extension);
+ }
+ }
+ }
+
+ protected function tearDown()
+ {
+ parent::tearDown();
+
+ if ($this->db instanceof \phpbb\db\driver\driver_interface)
+ {
+ // Close the database connections again this test
+ $this->db->sql_close();
+ }
}
/**
@@ -358,6 +394,24 @@ class phpbb_functional_test_case extends phpbb_test_case
copy($config_file, $config_file_test);
}
+ public function install_ext($extension)
+ {
+ $this->login();
+ $this->admin_login();
+
+ $ext_path = str_replace('/', '%2F', $extension);
+
+ $crawler = self::request('GET', 'adm/index.php?i=acp_extensions&mode=main&action=enable_pre&ext_name=' . $ext_path . '&sid=' . $this->sid);
+ $this->assertGreaterThan(0, $crawler->filter('.submit-buttons')->count());
+
+ $form = $crawler->selectButton('Enable')->form();
+ $crawler = self::submit($form);
+ $this->add_lang('acp/extensions');
+ $this->assertContainsLang('EXTENSION_ENABLE_SUCCESS', $crawler->filter('div.successbox')->text());
+
+ $this->logout();
+ }
+
static private function recreate_database($config)
{
$db_conn_mgr = new phpbb_database_test_connection_manager($config);
@@ -714,6 +768,30 @@ class phpbb_functional_test_case extends phpbb_test_case
$this->lang = array_merge($this->lang, $lang);
}
+ protected function add_lang_ext($ext_name, $lang_file)
+ {
+ if (is_array($lang_file))
+ {
+ foreach ($lang_file as $file)
+ {
+ $this->add_lang_ext($ext_name, $file);
+ }
+
+ return;
+ }
+
+ $lang_path = __DIR__ . "/../../phpBB/ext/{$ext_name}/language/en/$lang_file.php";
+
+ $lang = array();
+
+ if (file_exists($lang_path))
+ {
+ include($lang_path);
+ }
+
+ $this->lang = array_merge($this->lang, $lang);
+ }
+
protected function lang()
{
$args = func_get_args();
diff --git a/travis/prepare-extension.sh b/travis/prepare-extension.sh
new file mode 100755
index 0000000000..4518f935f8
--- /dev/null
+++ b/travis/prepare-extension.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# 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.
+#
+set -e
+set -x
+
+EXTNAME=$1
+BRANCH=$2
+
+# Move the extension in place
+mkdir --parents phpBB/ext/$EXTNAME
+cp -R ../tmp/* phpBB/ext/$EXTNAME
+
+# Move the extensions travis/phpunit-*-travis.xml files in place
+cp -R travis/* phpBB/ext/$EXTNAME/travis