diff options
Diffstat (limited to 'phpBB/phpbb')
35 files changed, 918 insertions, 107 deletions
diff --git a/phpBB/phpbb/config/db.php b/phpBB/phpbb/config/db.php index ef20ebf62a..26489bdd34 100644 --- a/phpBB/phpbb/config/db.php +++ b/phpBB/phpbb/config/db.php @@ -145,9 +145,9 @@ class db extends \phpbb\config\config $sql .= " AND config_value = '" . $this->db->sql_escape($old_value) . "'"; } - $result = $this->db->sql_query($sql); + $this->db->sql_query($sql); - if (!$this->db->sql_affectedrows($result) && isset($this->config[$key])) + if (!$this->db->sql_affectedrows() && isset($this->config[$key])) { return false; } diff --git a/phpBB/phpbb/content_visibility.php b/phpBB/phpbb/content_visibility.php index 8bd537586e..c8516d6c85 100644 --- a/phpBB/phpbb/content_visibility.php +++ b/phpBB/phpbb/content_visibility.php @@ -44,6 +44,12 @@ class content_visibility protected $config; /** + * Event dispatcher object + * @var \phpbb\event\dispatcher + */ + protected $phpbb_dispatcher; + + /** * phpBB root path * @var string */ @@ -60,6 +66,7 @@ class content_visibility * * @param \phpbb\auth\auth $auth Auth object * @param \phpbb\config\config $config Config object + * @param \phpbb\event\dispatcher $phpbb_dispatcher Event dispatcher object * @param \phpbb\db\driver\driver_interface $db Database object * @param \phpbb\user $user User object * @param string $phpbb_root_path Root path @@ -69,10 +76,11 @@ class content_visibility * @param string $topics_table Topics table name * @param string $users_table Users table name */ - public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table) + public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\user $user, $phpbb_root_path, $php_ext, $forums_table, $posts_table, $topics_table, $users_table) { $this->auth = $auth; $this->config = $config; + $this->phpbb_dispatcher = $phpbb_dispatcher; $this->db = $db; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; @@ -160,6 +168,36 @@ class content_visibility $approve_forums = array_intersect($forum_ids, array_keys($this->auth->acl_getf('m_approve', true))); + $get_forums_visibility_sql_overwrite = false; + /** + * Allow changing the result of calling get_forums_visibility_sql + * + * @event core.phpbb_content_visibility_get_forums_visibility_before + * @var string where_sql The action the user tried to execute + * @var string mode Either "topic" or "post" depending on the query this is being used in + * @var array forum_ids Array of forum ids which the posts/topics are limited to + * @var string table_alias Table alias to prefix in SQL queries + * @var array approve_forums Array of forums where the user has m_approve permissions + * @var mixed get_forums_visibility_sql_overwrite If a string, forces the function to return get_forums_visibility_sql_overwrite after executing the event + * If false, get_forums_visibility_sql continues normally + * It must be either boolean or string + * @since 3.1.3-RC1 + */ + $vars = array( + 'where_sql', + 'mode', + 'forum_ids', + 'table_alias', + 'approve_forums', + 'get_forums_visibility_sql_overwrite', + ); + extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_forums_visibility_before', compact($vars))); + + if ($get_forums_visibility_sql_overwrite !== false) + { + return $get_forums_visibility_sql_overwrite; + } + if (sizeof($approve_forums)) { // Remove moderator forums from the rest @@ -206,6 +244,35 @@ class content_visibility $approve_forums = array_diff(array_keys($this->auth->acl_getf('m_approve', true)), $exclude_forum_ids); + $visibility_sql_overwrite = null; + + /** + * Allow changing the result of calling get_global_visibility_sql + * + * @event core.phpbb_content_visibility_get_global_visibility_before + * @var array where_sqls The action the user tried to execute + * @var string mode Either "topic" or "post" depending on the query this is being used in + * @var array forum_ids Array of forum ids which the posts/topics are limited to + * @var string table_alias Table alias to prefix in SQL queries + * @var array approve_forums Array of forums where the user has m_approve permissions + * @var string visibility_sql_overwrite Forces the function to return an implosion of where_sqls (joined by "OR") + * @since 3.1.3-RC1 + */ + $vars = array( + 'where_sqls', + 'mode', + 'forum_ids', + 'table_alias', + 'approve_forums', + 'visibility_sql_overwrite', + ); + extract($this->phpbb_dispatcher->trigger_event('core.phpbb_content_visibility_get_global_visibility_before', compact($vars))); + + if ($visibility_sql_overwrite) + { + return $visibility_sql_overwrite; + } + if (sizeof($exclude_forum_ids)) { $where_sqls[] = '(' . $this->db->sql_in_set($table_alias . 'forum_id', $exclude_forum_ids, true) . ' diff --git a/phpBB/phpbb/db/migration/container_aware_migration.php b/phpBB/phpbb/db/migration/container_aware_migration.php new file mode 100644 index 0000000000..3b4b49b04b --- /dev/null +++ b/phpBB/phpbb/db/migration/container_aware_migration.php @@ -0,0 +1,36 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration; + +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* Abstract base class for container aware database migrations. +*/ +abstract class container_aware_migration extends migration implements ContainerAwareInterface +{ + /** + * @var ContainerInterface + */ + protected $container; + + /** + * {@inheritdoc} + */ + public function setContainer(ContainerInterface $container = null) + { + $this->container = $container; + } +} diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php new file mode 100644 index 0000000000..9ea68fa862 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_13_rc1.php @@ -0,0 +1,37 @@ +<?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\v30x; + +class release_3_0_13_rc1 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.0.13-RC1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v30x\release_3_0_12'); + } + + public function update_data() + { + return array( + array('if', array( + phpbb_version_compare($this->config['version'], '3.0.13-RC1', '<'), + array('config.update', array('version', '3.0.13-RC1')), + )), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php index 2cc7786046..003ccf8f18 100644 --- a/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php +++ b/phpBB/phpbb/db/migration/data/v30x/release_3_0_5_rc1.php @@ -13,7 +13,9 @@ namespace phpbb\db\migration\data\v30x; -class release_3_0_5_rc1 extends \phpbb\db\migration\migration +use phpbb\db\migration\container_aware_migration; + +class release_3_0_5_rc1 extends container_aware_migration { public function effectively_installed() { @@ -55,9 +57,7 @@ class release_3_0_5_rc1 extends \phpbb\db\migration\migration public function hash_old_passwords() { - global $phpbb_container; - - $passwords_manager = $phpbb_container->get('passwords.manager'); + $passwords_manager = $this->container->get('passwords.manager'); $sql = 'SELECT user_id, user_password FROM ' . $this->table_prefix . 'users WHERE user_pass_convert = 1'; @@ -110,7 +110,7 @@ class release_3_0_5_rc1 extends \phpbb\db\migration\migration // Select auth_option_ids... the largest id will be preserved $sql = 'SELECT auth_option_id FROM ' . ACL_OPTIONS_TABLE . " - WHERE auth_option = '" . $db->sql_escape($option) . "' + WHERE auth_option = '" . $this->db->sql_escape($option) . "' ORDER BY auth_option_id DESC"; // sql_query_limit not possible here, due to bug in postgresql layer $result = $this->db->sql_query($sql); diff --git a/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php index 4530ebe285..e04a705c91 100644 --- a/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php +++ b/phpBB/phpbb/db/migration/data/v310/mysql_fulltext_drop.php @@ -15,10 +15,18 @@ namespace phpbb\db\migration\data\v310; class mysql_fulltext_drop extends \phpbb\db\migration\migration { + protected $indexes; + public function effectively_installed() { // This migration is irrelevant for all non-MySQL DBMSes. - return strpos($this->db->get_sql_layer(), 'mysql') === false; + if (strpos($this->db->get_sql_layer(), 'mysql') === false) + { + return true; + } + + $this->find_indexes_to_drop(); + return empty($this->indexes); } static public function depends_on() @@ -30,6 +38,11 @@ class mysql_fulltext_drop extends \phpbb\db\migration\migration public function update_schema() { + if (empty($this->indexes)) + { + return array(); + } + /* * Drop FULLTEXT indexes related to MySQL fulltext search. * Doing so is equivalent to dropping the search index from the ACP. @@ -40,12 +53,28 @@ class mysql_fulltext_drop extends \phpbb\db\migration\migration */ return array( 'drop_keys' => array( - $this->table_prefix . 'posts' => array( - 'post_subject', - 'post_text', - 'post_content', - ), + $this->table_prefix . 'posts' => $this->indexes, ), ); } + + public function find_indexes_to_drop() + { + if ($this->indexes !== null) + { + return $this->indexes; + } + + $this->indexes = array(); + $potential_keys = array('post_subject', 'post_text', 'post_content'); + foreach ($potential_keys as $key) + { + if ($this->db_tools->sql_index_exists($this->table_prefix . 'posts', $key)) + { + $this->indexes[] = $key; + } + } + + return $this->indexes; + } } diff --git a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php index ea442dfb1b..3457c19478 100644 --- a/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php +++ b/phpBB/phpbb/db/migration/data/v310/postgres_fulltext_drop.php @@ -15,10 +15,18 @@ namespace phpbb\db\migration\data\v310; class postgres_fulltext_drop extends \phpbb\db\migration\migration { + protected $indexes; + public function effectively_installed() { // This migration is irrelevant for all non-PostgreSQL DBMSes. - return strpos($this->db->get_sql_layer(), 'postgres') === false; + if (strpos($this->db->get_sql_layer(), 'postgres') === false) + { + return true; + } + + $this->find_indexes_to_drop(); + return empty($this->indexes); } static public function depends_on() @@ -30,6 +38,11 @@ class postgres_fulltext_drop extends \phpbb\db\migration\migration public function update_schema() { + if (empty($this->indexes)) + { + return array(); + } + /* * Drop FULLTEXT indexes related to PostgreSQL fulltext search. * Doing so is equivalent to dropping the search index from the ACP. @@ -40,12 +53,28 @@ class postgres_fulltext_drop extends \phpbb\db\migration\migration */ return array( 'drop_keys' => array( - $this->table_prefix . 'posts' => array( - 'post_subject', - 'post_text', - 'post_content', - ), + $this->table_prefix . 'posts' => $this->indexes, ), ); } + + public function find_indexes_to_drop() + { + if ($this->indexes !== null) + { + return $this->indexes; + } + + $this->indexes = array(); + $potential_keys = array('post_subject', 'post_text', 'post_content'); + foreach ($potential_keys as $key) + { + if ($this->db_tools->sql_index_exists($this->table_prefix . 'posts', $key)) + { + $this->indexes[] = $key; + } + } + + return $this->indexes; + } } diff --git a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php index 58845b88ec..85b90da5fa 100644 --- a/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php +++ b/phpBB/phpbb/db/migration/data/v310/soft_delete_mod_convert.php @@ -13,12 +13,14 @@ namespace phpbb\db\migration\data\v310; +use phpbb\db\migration\container_aware_migration; + /** * Migration to convert the Soft Delete MOD for 3.0 * * https://www.phpbb.com/customise/db/mod/soft_delete/ */ -class soft_delete_mod_convert extends \phpbb\db\migration\migration +class soft_delete_mod_convert extends container_aware_migration { static public function depends_on() { @@ -115,19 +117,11 @@ class soft_delete_mod_convert extends \phpbb\db\migration\migration } } + /** + * @return \phpbb\content_visibility + */ protected function get_content_visibility() { - return new \phpbb\content_visibility( - new \phpbb\auth\auth(), - $this->config, - $this->db, - new \phpbb\user('\phpbb\datetime'), - $this->phpbb_root_path, - $this->php_ext, - $this->table_prefix . 'forums', - $this->table_prefix . 'posts', - $this->table_prefix . 'topics', - $this->table_prefix . 'users' - ); + return $this->container->get('content.visibility'); } } diff --git a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php index 5a3a1d5de7..e8d3a3af64 100644 --- a/phpBB/phpbb/db/migration/data/v310/style_update_p1.php +++ b/phpBB/phpbb/db/migration/data/v310/style_update_p1.php @@ -92,7 +92,7 @@ class style_update_p1 extends \phpbb\db\migration\migration else { $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_id - FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . "stles_theme c + FROM ' . STYLES_TABLE . ' s, ' . $this->table_prefix . 'styles_template t, ' . $this->table_prefix . "styles_theme c WHERE t.template_id = s.template_id AND c.theme_id = s.theme_id"; } diff --git a/phpBB/phpbb/db/migration/data/v31x/plupload_last_gc_dynamic.php b/phpBB/phpbb/db/migration/data/v31x/plupload_last_gc_dynamic.php new file mode 100644 index 0000000000..0783d707c5 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/plupload_last_gc_dynamic.php @@ -0,0 +1,31 @@ +<?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\v31x; + +class plupload_last_gc_dynamic extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v31x\v312'); + } + + public function update_data() + { + return array( + // Make plupload_last_gc dynamic. + array('config.remove', array('plupload_last_gc')), + array('config.add', array('plupload_last_gc', 0, 1)), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/profilefield_remove_underscore_from_alpha.php b/phpBB/phpbb/db/migration/data/v31x/profilefield_remove_underscore_from_alpha.php new file mode 100644 index 0000000000..60491f8de8 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/profilefield_remove_underscore_from_alpha.php @@ -0,0 +1,47 @@ +<?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\v31x; + +class profilefield_remove_underscore_from_alpha extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v31x\v311'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'remove_underscore_from_alpha_validations'))), + ); + } + + public function remove_underscore_from_alpha_validations() + { + $this->update_validation_rule('[\w]+', '[a-zA-Z0-9]+'); + $this->update_validation_rule('[\w_]+', '[\w]+'); + $this->update_validation_rule('[\w.]+', '[a-zA-Z0-9.]+'); + $this->update_validation_rule('[\w\x20_+\-\[\]]+', '[\w\x20+\-\[\]]+'); + $this->update_validation_rule('[a-zA-Z][\w\.,\-_]+', '[a-zA-Z][\w\.,\-]+'); + } + + public function update_validation_rule($old_validation, $new_validation) + { + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_validation = '" . $this->db->sql_escape($new_validation) . "' + WHERE field_validation = '" . $this->db->sql_escape($old_validation) . "'"; + $this->db->sql_query($sql); + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/profilefield_yahoo_update_url.php b/phpBB/phpbb/db/migration/data/v31x/profilefield_yahoo_update_url.php new file mode 100644 index 0000000000..4df9083bdf --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/profilefield_yahoo_update_url.php @@ -0,0 +1,38 @@ +<?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\v31x; + +class profilefield_yahoo_update_url extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v31x\v312'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_contact_url'))), + ); + } + + public function update_contact_url() + { + $sql = 'UPDATE ' . $this->table_prefix . "profile_fields + SET field_contact_url = 'ymsgr:sendim?%s' + WHERE field_name = 'phpbb_yahoo' + AND field_contact_url = 'http://edit.yahoo.com/config/send_webmesg?.target=%s&.src=pg'"; + $this->sql_query($sql); + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php new file mode 100644 index 0000000000..854ed1f568 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/update_custom_bbcodes_with_idn.php @@ -0,0 +1,70 @@ +<?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\v31x; + +class update_custom_bbcodes_with_idn extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v312', + ); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_bbcodes_table'))), + ); + } + + public function update_bbcodes_table() + { + if (!class_exists('acp_bbcodes')) + { + include($this->phpbb_root_path . 'includes/acp/acp_bbcodes.' . $this->php_ext); + } + + $bbcodes = new \acp_bbcodes(); + + $sql = 'SELECT bbcode_id, bbcode_match, bbcode_tpl + FROM ' . BBCODES_TABLE; + $result = $this->sql_query($sql); + + $sql_ary = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $data = array(); + if (preg_match('/(URL|LOCAL_URL|RELATIVE_URL)/', $row['bbcode_match'])) + { + $data = $bbcodes->build_regexp($row['bbcode_match'], $row['bbcode_tpl']); + $sql_ary[$row['bbcode_id']] = array( + 'first_pass_match' => $data['first_pass_match'], + 'first_pass_replace' => $data['first_pass_replace'], + 'second_pass_match' => $data['second_pass_match'], + 'second_pass_replace' => $data['second_pass_replace'] + ); + } + } + $this->db->sql_freeresult($result); + + foreach ($sql_ary as $bbcode_id => $bbcode_data) + { + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $this->db->sql_build_array('UPDATE', $bbcode_data) . ' + WHERE bbcode_id = ' . (int) $bbcode_id; + $this->sql_query($sql); + } + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v312.php b/phpBB/phpbb/db/migration/data/v31x/v312.php new file mode 100644 index 0000000000..bf49935f4d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v312.php @@ -0,0 +1,31 @@ +<?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\v31x; + +class v312 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v312rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.2')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v31x/v312rc1.php b/phpBB/phpbb/db/migration/data/v31x/v312rc1.php new file mode 100644 index 0000000000..d4b133fc01 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v312rc1.php @@ -0,0 +1,32 @@ +<?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\v31x; + +class v312rc1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v311', + '\phpbb\db\migration\data\v31x\m_softdelete_global', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.2-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/profilefield_base_migration.php b/phpBB/phpbb/db/migration/profilefield_base_migration.php index 9000949a7d..da1a38e2fa 100644 --- a/phpBB/phpbb/db/migration/profilefield_base_migration.php +++ b/phpBB/phpbb/db/migration/profilefield_base_migration.php @@ -13,7 +13,7 @@ namespace phpbb\db\migration; -abstract class profilefield_base_migration extends \phpbb\db\migration\migration +abstract class profilefield_base_migration extends container_aware_migration { protected $profilefield_name; @@ -237,8 +237,7 @@ abstract class profilefield_base_migration extends \phpbb\db\migration\migration if ($profile_row === null) { - global $phpbb_container; - $manager = $phpbb_container->get('profilefields.manager'); + $manager = $this->container->get('profilefields.manager'); $profile_row = $manager->build_insert_sql_array(array()); } diff --git a/phpBB/phpbb/db/migration/tool/module.php b/phpBB/phpbb/db/migration/tool/module.php index db43046a95..035625b095 100644 --- a/phpBB/phpbb/db/migration/tool/module.php +++ b/phpBB/phpbb/db/migration/tool/module.php @@ -475,6 +475,7 @@ class module implements \phpbb\db\migration\tool\tool_interface if (!class_exists('acp_modules')) { include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext); + $this->user->add_lang('acp/modules'); } $acp_modules = new \acp_modules(); $module = $acp_modules->get_module_infos($basename, $class, true); diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php index d03496eae3..7fc3e787e2 100644 --- a/phpBB/phpbb/db/migrator.php +++ b/phpBB/phpbb/db/migrator.php @@ -13,11 +13,19 @@ namespace phpbb\db; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + /** * The migrator is responsible for applying new migrations in the correct order. */ class migrator { + /** + * @var ContainerInterface + */ + protected $container; + /** @var \phpbb\config\config */ protected $config; @@ -77,15 +85,16 @@ class migrator /** * The output handler. A null handler is configured by default. * - * @var migrator_output_handler + * @var migrator_output_handler_interface */ public $output_handler; /** * Constructor of the database migrator */ - public function __construct(\phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) + public function __construct(ContainerInterface $container, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\db\tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools, \phpbb\db\migration\helper $helper) { + $this->container = $container; $this->config = $config; $this->db = $db; $this->db_tools = $db_tools; @@ -172,6 +181,18 @@ class migrator */ public function update() { + $this->container->get('dispatcher')->disable(); + $this->update_do(); + $this->container->get('dispatcher')->enable(); + } + + /** + * Effectively runs a single update step from the next migration to be applied. + * + * @return null + */ + protected function update_do() + { foreach ($this->migrations as $name) { if (!isset($this->migration_state[$name]) || @@ -317,7 +338,7 @@ class migrator catch (\phpbb\db\migration\exception $e) { // Revert the schema changes - $this->revert($name); + $this->revert_do($name); // Rethrow exception throw $e; @@ -337,10 +358,22 @@ class migrator * check if revert() needs to be called again use the migration_state() method. * * @param string $migration String migration name to revert (including any that depend on this migration) - * @return null */ public function revert($migration) { + $this->container->get('dispatcher')->disable(); + $this->revert_do($migration); + $this->container->get('dispatcher')->enable(); + } + + /** + * Effectively runs a single revert step from the last migration installed + * + * @param string $migration String migration name to revert (including any that depend on this migration) + * @return null + */ + protected function revert_do($migration) + { if (!isset($this->migration_state[$migration])) { // Not installed @@ -351,7 +384,7 @@ class migrator { if (!empty($state['migration_depends_on']) && in_array($migration, $state['migration_depends_on'])) { - $this->revert($name); + $this->revert_do($name); } } @@ -742,7 +775,14 @@ class migrator */ protected function get_migration($name) { - return new $name($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix); + $migration = new $name($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix); + + if ($migration instanceof ContainerAwareInterface) + { + $migration->setContainer($this->container); + } + + return $migration; } /** diff --git a/phpBB/phpbb/db/tools.php b/phpBB/phpbb/db/tools.php index c8d25f23a2..f523b39fb3 100644 --- a/phpBB/phpbb/db/tools.php +++ b/phpBB/phpbb/db/tools.php @@ -2175,7 +2175,7 @@ class tools } // no break case 'mysql_41': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . '(' . implode(', ', $column) . ')'; + $statements[] = 'ALTER TABLE ' . $table_name . ' ADD INDEX ' . $index_name . ' (' . implode(', ', $column) . ')'; break; case 'mssql': diff --git a/phpBB/phpbb/error_collector.php b/phpBB/phpbb/error_collector.php index 7141f83174..bf8efd1065 100644 --- a/phpBB/phpbb/error_collector.php +++ b/phpBB/phpbb/error_collector.php @@ -16,15 +16,28 @@ namespace phpbb; class error_collector { var $errors; + var $error_types; - function __construct() + /** + * Constructor. + * + * The variable $error_types may be set to a mask of PHP error types that + * the collector should keep, e.g. `E_ALL`. If unset, the current value of + * the error_reporting() function will be used to determine which errors + * the collector will keep. + * + * @see PHPBB3-13306 + * @param int|null $error_types + */ + function __construct($error_types = null) { $this->errors = array(); + $this->error_types = $error_types; } function install() { - set_error_handler(array(&$this, 'error_handler')); + set_error_handler(array(&$this, 'error_handler'), ($this->error_types !== null) ? $this->error_types : error_reporting()); } function uninstall() diff --git a/phpBB/phpbb/event/dispatcher.php b/phpBB/phpbb/event/dispatcher.php index 9a786022c2..1c4abeb108 100644 --- a/phpBB/phpbb/event/dispatcher.php +++ b/phpBB/phpbb/event/dispatcher.php @@ -14,6 +14,7 @@ namespace phpbb\event; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\Event; /** * Extension of the Symfony2 EventDispatcher @@ -32,6 +33,11 @@ use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_interface { /** + * @var bool + */ + protected $disabled = false; + + /** * {@inheritdoc} */ public function trigger_event($eventName, $data = array()) @@ -40,4 +46,33 @@ class dispatcher extends ContainerAwareEventDispatcher implements dispatcher_int $this->dispatch($eventName, $event); return $event->get_data_filtered(array_keys($data)); } + + /** + * {@inheritdoc} + */ + public function dispatch($eventName, Event $event = null) + { + if ($this->disabled) + { + return $event; + } + + return parent::dispatch($eventName, $event); + } + + /** + * {@inheritdoc} + */ + public function disable() + { + $this->disabled = true; + } + + /** + * {@inheritdoc} + */ + public function enable() + { + $this->disabled = false; + } } diff --git a/phpBB/phpbb/event/dispatcher_interface.php b/phpBB/phpbb/event/dispatcher_interface.php index 50a3ef9101..c66aa98260 100644 --- a/phpBB/phpbb/event/dispatcher_interface.php +++ b/phpBB/phpbb/event/dispatcher_interface.php @@ -37,4 +37,14 @@ interface dispatcher_interface extends \Symfony\Component\EventDispatcher\EventD * @return mixed */ public function trigger_event($eventName, $data = array()); + + /** + * Disable the event dispatcher. + */ + public function disable(); + + /** + * Enable the event dispatcher. + */ + public function enable(); } diff --git a/phpBB/phpbb/extension/metadata_manager.php b/phpBB/phpbb/extension/metadata_manager.php index edca8ee1af..a64d88fe39 100644 --- a/phpBB/phpbb/extension/metadata_manager.php +++ b/phpBB/phpbb/extension/metadata_manager.php @@ -177,6 +177,7 @@ class metadata_manager throw new \phpbb\extension\exception($this->user->lang('FILE_JSON_DECODE_ERR', $this->metadata_file)); } + array_walk_recursive($metadata, array($this, 'sanitize_json')); $this->metadata = $metadata; return true; @@ -184,6 +185,17 @@ class metadata_manager } /** + * Sanitize input from JSON array using htmlspecialchars() + * + * @param mixed $value Value of array row + * @param string $key Key of array row + */ + public function sanitize_json(&$value, $key) + { + $value = htmlspecialchars($value); + } + + /** * This array handles the cleaning of the array * * @return array Contains the cleaned metadata array @@ -337,30 +349,30 @@ class metadata_manager public function output_template_data() { $this->template->assign_vars(array( - 'META_NAME' => htmlspecialchars($this->metadata['name']), - 'META_TYPE' => htmlspecialchars($this->metadata['type']), - 'META_DESCRIPTION' => (isset($this->metadata['description'])) ? htmlspecialchars($this->metadata['description']) : '', + 'META_NAME' => $this->metadata['name'], + 'META_TYPE' => $this->metadata['type'], + 'META_DESCRIPTION' => (isset($this->metadata['description'])) ? $this->metadata['description'] : '', 'META_HOMEPAGE' => (isset($this->metadata['homepage'])) ? $this->metadata['homepage'] : '', - 'META_VERSION' => (isset($this->metadata['version'])) ? htmlspecialchars($this->metadata['version']) : '', - 'META_TIME' => (isset($this->metadata['time'])) ? htmlspecialchars($this->metadata['time']) : '', - 'META_LICENSE' => htmlspecialchars($this->metadata['license']), + 'META_VERSION' => (isset($this->metadata['version'])) ? $this->metadata['version'] : '', + 'META_TIME' => (isset($this->metadata['time'])) ? $this->metadata['time'] : '', + 'META_LICENSE' => $this->metadata['license'], - 'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? htmlspecialchars($this->metadata['require']['php']) : '', + 'META_REQUIRE_PHP' => (isset($this->metadata['require']['php'])) ? $this->metadata['require']['php'] : '', 'META_REQUIRE_PHP_FAIL' => !$this->validate_require_php(), - 'META_REQUIRE_PHPBB' => (isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) ? htmlspecialchars($this->metadata['extra']['soft-require']['phpbb/phpbb']) : '', + 'META_REQUIRE_PHPBB' => (isset($this->metadata['extra']['soft-require']['phpbb/phpbb'])) ? $this->metadata['extra']['soft-require']['phpbb/phpbb'] : '', 'META_REQUIRE_PHPBB_FAIL' => !$this->validate_require_phpbb(), - 'META_DISPLAY_NAME' => (isset($this->metadata['extra']['display-name'])) ? htmlspecialchars($this->metadata['extra']['display-name']) : '', + 'META_DISPLAY_NAME' => (isset($this->metadata['extra']['display-name'])) ? $this->metadata['extra']['display-name'] : '', )); foreach ($this->metadata['authors'] as $author) { $this->template->assign_block_vars('meta_authors', array( - 'AUTHOR_NAME' => htmlspecialchars($author['name']), + 'AUTHOR_NAME' => $author['name'], 'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '', 'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '', - 'AUTHOR_ROLE' => (isset($author['role'])) ? htmlspecialchars($author['role']) : '', + 'AUTHOR_ROLE' => (isset($author['role'])) ? $author['role'] : '', )); } } diff --git a/phpBB/phpbb/file_downloader.php b/phpBB/phpbb/file_downloader.php new file mode 100644 index 0000000000..d717b394d5 --- /dev/null +++ b/phpBB/phpbb/file_downloader.php @@ -0,0 +1,120 @@ +<?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; + +class file_downloader +{ + /** @var string Error string */ + protected $error_string = ''; + + /** @var int Error number */ + protected $error_number = 0; + + /** + * Retrieve contents from remotely stored file + * + * @param string $host File host + * @param string $directory Directory file is in + * @param string $filename Filename of file to retrieve + * @param int $port Port to connect to; default: 80 + * @param int $timeout Connection timeout in seconds; default: 6 + * + * @return mixed File data as string if file can be read and there is no + * timeout, false if there were errors or the connection timed out + * + * @throws \RuntimeException If data can't be retrieved and no error + * message is returned + */ + public function get($host, $directory, $filename, $port = 80, $timeout = 6) + { + // Set default values for error variables + $this->error_number = 0; + $this->error_string = ''; + + if ($socket = @fsockopen($host, $port, $this->error_number, $this->error_string, $timeout)) + { + @fputs($socket, "GET $directory/$filename HTTP/1.0\r\n"); + @fputs($socket, "HOST: $host\r\n"); + @fputs($socket, "Connection: close\r\n\r\n"); + + $timer_stop = time() + $timeout; + stream_set_timeout($socket, $timeout); + + $file_info = ''; + $get_info = false; + + while (!@feof($socket)) + { + if ($get_info) + { + $file_info .= @fread($socket, 1024); + } + else + { + $line = @fgets($socket, 1024); + if ($line == "\r\n") + { + $get_info = true; + } + else if (stripos($line, '404 not found') !== false) + { + throw new \RuntimeException(array('FILE_NOT_FOUND', $filename)); + } + } + + $stream_meta_data = stream_get_meta_data($socket); + + if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) + { + throw new \RuntimeException('FSOCK_TIMEOUT'); + } + } + @fclose($socket); + } + else + { + if ($this->error_string) + { + $this->error_string = utf8_convert_message($this->error_string); + return false; + } + else + { + throw new \RuntimeException('FSOCK_DISABLED'); + } + } + + return $file_info; + } + + /** + * Get error string + * + * @return string Error string + */ + public function get_error_string() + { + return $this->error_string; + } + + /** + * Get error number + * + * @return int Error number + */ + public function get_error_number() + { + return $this->error_number; + } +} diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index 2af8b50b54..0c5205530b 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -708,6 +708,50 @@ class log implements \phpbb\log\log_interface } } + /** + * Allow modifying or execute extra final filter on log entries + * + * @event core.get_logs_after + * @var array log Array with all our log entries + * @var array topic_id_list Array of topic ids, for which we + * get the permission data + * @var array reportee_id_list Array of additional user IDs we + * get the username strings for + * @var string mode Mode of the entries we display + * @var bool count_logs Do we count all matching entries? + * @var int limit Limit the number of entries + * @var int offset Offset when fetching the entries + * @var mixed forum_id Limit entries to the forum_id, + * can also be an array of forum_ids + * @var int topic_id Limit entries to the topic_id + * @var int user_id Limit entries to the user_id + * @var int log_time Limit maximum age of log entries + * @var string sort_by SQL order option + * @var string keywords Will only return entries that have the + * keywords in log_operation or log_data + * @var string profile_url URL to the users profile + * @var int log_type The type of logs it was filtered + * @since 3.1.3-RC1 + */ + $vars = array( + 'log', + 'topic_id_list', + 'reportee_id_list', + 'mode', + 'count_logs', + 'limit', + 'offset', + 'forum_id', + 'topic_id', + 'user_id', + 'log_time', + 'sort_by', + 'keywords', + 'profile_url', + 'log_type', + ); + extract($this->dispatcher->trigger_event('core.get_logs_after', compact($vars))); + return $log; } diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index dd611e1dd1..aa52eb61d0 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -38,6 +38,9 @@ class manager /** @var \phpbb\config\config */ protected $config; + /** @var \phpbb\event\dispatcher */ + protected $phpbb_dispatcher; + /** @var \phpbb\db\driver\driver_interface */ protected $db; @@ -70,6 +73,7 @@ class manager * @param ContainerInterface $phpbb_container * @param \phpbb\user_loader $user_loader * @param \phpbb\config\config $config + * @param \phpbb\event\dispatcher $phpbb_dispatcher * @param \phpbb\db\driver\driver_interface $db * @param \phpbb\cache\service $cache * @param \phpbb\user $user @@ -81,7 +85,7 @@ class manager * * @return \phpbb\notification\manager */ - public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) + public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table) { $this->notification_types = $notification_types; $this->notification_methods = $notification_methods; @@ -89,6 +93,7 @@ class manager $this->user_loader = $user_loader; $this->config = $config; + $this->phpbb_dispatcher = $phpbb_dispatcher; $this->db = $db; $this->cache = $cache; $this->user = $user; @@ -350,6 +355,26 @@ class manager // find out which users want to receive this type of notification $notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options); + /** + * Allow filtering the notify_users array for a notification that is about to be sent. + * Here, $notify_users is already filtered by f_read and the ignored list included in the options variable + * + * @event core.notification_manager_add_notifications + * @var string notification_type_name The forum id from where the topic belongs + * @var array data Data specific for the notification_type_name used will be inserted + * @var array notify_users The array of userid that are going to be notified for this notification. Set to array() to cancel. + * @var array options The options that were used when this method was called (read only) + * + * @since 3.1.3-RC1 + */ + $vars = array( + 'notification_type_name', + 'data', + 'notify_users', + 'options', + ); + extract($this->phpbb_dispatcher->trigger_event('core.notification_manager_add_notifications', compact($vars))); + $this->add_notifications_for_users($notification_type_name, $data, $notify_users); return $notify_users; diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index 4a446a5d9d..5400c1c5a6 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -282,10 +282,16 @@ class path_helper $referer_dir = dirname($referer_dir); } - while (strpos($absolute_board_url, $referer_dir) !== 0) + while (($dir_position = strpos($absolute_board_url, $referer_dir)) !== 0) { $fixed_root_path .= '../'; $referer_dir = dirname($referer_dir); + + // Just return phpbb_root_path if we reach the top directory + if ($referer_dir === '.') + { + return $this->phpbb_root_path; + } } $fixed_root_path .= substr($absolute_board_url, strlen($referer_dir) + 1); @@ -449,4 +455,38 @@ class path_helper return $url_parts['base'] . (($params) ? '?' . $this->glue_url_params($params) : ''); } + + /** + * Get a valid page + * + * @param string $page The page to verify + * @param bool $mod_rewrite Whether mod_rewrite is enabled, default: false + * + * @return string A valid page based on given page and mod_rewrite + */ + public function get_valid_page($page, $mod_rewrite = false) + { + // We need to be cautious here. + // On some situations, the redirect path is an absolute URL, sometimes a relative path + // For a relative path, let's prefix it with $phpbb_root_path to point to the correct location, + // else we use the URL directly. + $url_parts = parse_url($page); + + // URL + if ($url_parts === false || empty($url_parts['scheme']) || empty($url_parts['host'])) + { + // Remove 'app.php/' from the page, when rewrite is enabled. + // Treat app.php as a reserved file name and remove on mod rewrite + // even if it might not be in the phpBB root. + if ($mod_rewrite && ($app_position = strpos($page, 'app.' . $this->php_ext . '/')) !== false) + { + $page = substr($page, 0, $app_position) . substr($page, $app_position + strlen('app.' . $this->php_ext . '/')); + } + + // Remove preceding slashes from page name and prepend root path + $page = $this->get_phpbb_root_path() . ltrim($page, '/\\'); + } + + return $page; + } } diff --git a/phpBB/phpbb/profilefields/type/type_bool.php b/phpBB/phpbb/profilefields/type/type_bool.php index 75934e3be7..f6f3f17a6c 100644 --- a/phpBB/phpbb/profilefields/type/type_bool.php +++ b/phpBB/phpbb/profilefields/type/type_bool.php @@ -173,7 +173,7 @@ class type_bool extends type_base } else { - return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1); + return $this->lang_helper->is_set($field_id, $lang_id, $field_value + 1) ? $this->lang_helper->get($field_id, $lang_id, $field_value + 1) : null; } } @@ -367,29 +367,29 @@ class type_bool extends type_base */ public function prepare_hidden_fields($step, $key, $action, &$field_data) { - if ($key == 'l_lang_options' && $this->request->is_set('l_lang_options')) + if ($key == 'field_default_value') { - return $this->request->variable($key, array(array('')), true); - } - else if ($key == 'field_default_value') - { - return $this->request->variable($key, $field_data[$key]); - } - else - { - if (!$this->request->is_set($key)) - { - return false; - } - else if ($key == 'field_ident' && isset($field_data[$key])) - { - return $field_data[$key]; - } - else + $field_length = $this->request->variable('field_length', 0); + + // Do a simple is set check if using checkbox. + if ($field_length == 2) { - return ($key == 'lang_options') ? $this->request->variable($key, array(''), true) : $this->request->variable($key, '', true); + return $this->request->is_set($key); } + return $this->request->variable($key, $field_data[$key], true); + } + + $default_lang_options = array( + 'l_lang_options' => array(0 => array('')), + 'lang_options' => array(0 => ''), + ); + + if (isset($default_lang_options[$key]) && $this->request->is_set($key)) + { + return $this->request->variable($key, $default_lang_options[$key], true); } + + return parent::prepare_hidden_fields($step, $key, $action, $field_data); } /** diff --git a/phpBB/phpbb/profilefields/type/type_string_common.php b/phpBB/phpbb/profilefields/type/type_string_common.php index ff33a7b49c..f5e1992044 100644 --- a/phpBB/phpbb/profilefields/type/type_string_common.php +++ b/phpBB/phpbb/profilefields/type/type_string_common.php @@ -18,11 +18,11 @@ abstract class type_string_common extends type_base protected $validation_options = array( 'CHARS_ANY' => '.*', 'NUMBERS_ONLY' => '[0-9]+', - 'ALPHA_ONLY' => '[\w]+', - 'ALPHA_UNDERSCORE' => '[\w_]+', - 'ALPHA_DOTS' => '[\w.]+', - 'ALPHA_SPACERS' => '[\w\x20_+\-\[\]]+', - 'ALPHA_PUNCTUATION' => '[a-zA-Z][\w\.,\-_]+', + 'ALPHA_ONLY' => '[a-zA-Z0-9]+', + 'ALPHA_UNDERSCORE' => '[\w]+', + 'ALPHA_DOTS' => '[a-zA-Z0-9.]+', + 'ALPHA_SPACERS' => '[\w\x20+\-\[\]]+', + 'ALPHA_PUNCTUATION' => '[a-zA-Z][\w\.,\-]+', 'LETTER_NUM_ONLY' => '[\p{Lu}\p{Ll}0-9]+', 'LETTER_NUM_UNDERSCORE' => '[\p{Lu}\p{Ll}0-9_]+', 'LETTER_NUM_DOTS' => '[\p{Lu}\p{Ll}0-9.]+', diff --git a/phpBB/phpbb/profilefields/type/type_url.php b/phpBB/phpbb/profilefields/type/type_url.php index bc8ac869d0..fe0bffd582 100644 --- a/phpBB/phpbb/profilefields/type/type_url.php +++ b/phpBB/phpbb/profilefields/type/type_url.php @@ -64,7 +64,7 @@ class type_url extends type_string return false; } - if (!preg_match('#^' . get_preg_expression('url') . '$#i', $field_value)) + if (!preg_match('#^' . get_preg_expression('url') . '$#iu', $field_value)) { return $this->user->lang('FIELD_INVALID_URL', $this->get_field_name($field_data['lang_name'])); } diff --git a/phpBB/phpbb/request/request.php b/phpBB/phpbb/request/request.php index f0f2f7e2a2..56ce3999ed 100644 --- a/phpBB/phpbb/request/request.php +++ b/phpBB/phpbb/request/request.php @@ -275,7 +275,7 @@ class request implements \phpbb\request\request_interface */ public function file($form_name) { - return $this->variable($form_name, array('name' => 'none'), false, \phpbb\request\request_interface::FILES); + return $this->variable($form_name, array('name' => 'none'), true, \phpbb\request\request_interface::FILES); } /** diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php index 48b0f077c7..8865d37712 100644 --- a/phpBB/phpbb/search/fulltext_native.php +++ b/phpBB/phpbb/search/fulltext_native.php @@ -434,7 +434,7 @@ class fulltext_native extends \phpbb\search\base // throw an error if we shall not ignore unexistant words else if (!$ignore_no_id && sizeof($non_common_words)) { - trigger_error(sprintf($user->lang['WORDS_IN_NO_POST'], implode($user->lang['COMMA_SEPARATOR'], $non_common_words))); + trigger_error(sprintf($this->user->lang['WORDS_IN_NO_POST'], implode($this->user->lang['COMMA_SEPARATOR'], $non_common_words))); } unset($non_common_words); } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index dc90d942c3..0a6a18ffbe 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1063,7 +1063,7 @@ class session $name_data = rawurlencode($config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata); $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime); - $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']; + $domain = (!$config['cookie_domain'] || $config['cookie_domain'] == '127.0.0.1' || strpos($config['cookie_domain'], '.') === false) ? '' : '; domain=' . $config['cookie_domain']; header('Set-Cookie: ' . $name_data . (($cookietime) ? '; expires=' . $expire : '') . '; path=' . $config['cookie_path'] . $domain . ((!$config['cookie_secure']) ? '' : '; secure') . ';' . (($httponly) ? ' HttpOnly' : ''), false); } @@ -1082,7 +1082,7 @@ class session */ function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false) { - global $config, $db; + global $config, $db, $phpbb_dispatcher; if (defined('IN_CHECK_BAN') || defined('SKIP_CHECK_BAN')) { @@ -1196,6 +1196,20 @@ class session } $db->sql_freeresult($result); + /** + * Event to set custom ban type + * + * @event core.session_set_custom_ban + * @var bool return If $return is false this routine does not return on finding a banned user, it outputs a relevant message and stops execution + * @var bool banned Check if user already banned + * @var array|false ban_row Ban data + * @var string ban_triggered_by Method that caused ban, can be your custom method + * @since 3.1.3-RC1 + */ + $ban_row = isset($ban_row) ? $ban_row : false; + $vars = array('return', 'banned', 'ban_row', 'ban_triggered_by'); + extract($phpbb_dispatcher->trigger_event('core.session_set_custom_ban', compact($vars))); + if ($banned && !$return) { global $template, $phpbb_root_path, $phpEx; diff --git a/phpBB/phpbb/template/twig/twig.php b/phpBB/phpbb/template/twig/twig.php index 5b71bb5e8a..bd754d9bbd 100644 --- a/phpBB/phpbb/template/twig/twig.php +++ b/phpBB/phpbb/template/twig/twig.php @@ -115,6 +115,11 @@ class twig extends \phpbb\template\base ) ); + if (defined('DEBUG')) + { + $this->twig->addExtension(new \Twig_Extension_Debug()); + } + $lexer = new \phpbb\template\twig\lexer($this->twig); $this->twig->setLexer($lexer); @@ -280,19 +285,19 @@ class twig extends \phpbb\template\base $ext_style_theme_path = $ext_style_path . 'theme/'; } - $ok = false; + $is_valid_dir = false; if (is_dir($ext_style_template_path)) { - $ok = true; + $is_valid_dir = true; $paths[] = $ext_style_template_path; } if (is_dir($ext_style_theme_path)) { - $ok = true; + $is_valid_dir = true; $paths[] = $ext_style_theme_path; } - if ($ok) + if ($is_valid_dir) { // Add the base style directory as a safe directory $this->twig->getLoader()->addSafeDirectory($ext_style_path); diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php index c3c3602944..dc62f06fb2 100644 --- a/phpBB/phpbb/version_helper.php +++ b/phpBB/phpbb/version_helper.php @@ -50,6 +50,9 @@ class version_helper /** @var \phpbb\config\config */ protected $config; + /** @var \phpbb\file_downloader */ + protected $file_downloader; + /** @var \phpbb\user */ protected $user; @@ -58,12 +61,14 @@ class version_helper * * @param \phpbb\cache\service $cache * @param \phpbb\config\config $config + * @param \phpbb\file_downloader $file_downloader * @param \phpbb\user $user */ - public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\user $user) + public function __construct(\phpbb\cache\service $cache, \phpbb\config\config $config, \phpbb\file_downloader $file_downloader, \phpbb\user $user) { $this->cache = $cache; $this->config = $config; + $this->file_downloader = $file_downloader; $this->user = $user; if (defined('PHPBB_QA')) @@ -249,16 +254,32 @@ class version_helper } else if ($info === false || $force_update) { - $errstr = $errno = ''; - $info = get_remote_file($this->host, $this->path, $this->file, $errstr, $errno); + try { + $info = $this->file_downloader->get($this->host, $this->path, $this->file); + } + catch (\RuntimeException $exception) + { + throw new \RuntimeException($this->user->lang($exception->getMessage())); + } + $error_string = $this->file_downloader->get_error_string(); - if (!empty($errstr)) + if (!empty($error_string)) { - throw new \RuntimeException($errstr); + throw new \RuntimeException($error_string); } $info = json_decode($info, true); + // Sanitize any data we retrieve from a server + if (!empty($info)) + { + $json_sanitizer = function (&$value, $key) { + $type_cast_helper = new \phpbb\request\type_cast_helper(); + $type_cast_helper->set_var($value, $value, gettype($value), true); + }; + array_walk_recursive($info, $json_sanitizer); + } + if (empty($info['stable']) && empty($info['unstable'])) { $this->user->add_lang('acp/common'); @@ -266,15 +287,6 @@ class version_helper throw new \RuntimeException($this->user->lang('VERSIONCHECK_FAIL')); } - // Replace & with & on announcement links - foreach ($info as $stability => $branches) - { - foreach ($branches as $branch => $branch_data) - { - $info[$stability][$branch]['announcement'] = (!empty($branch_data['announcement'])) ? str_replace('&', '&', $branch_data['announcement']) : ''; - } - } - $info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; $info['unstable'] = (empty($info['unstable'])) ? $info['stable'] : $info['unstable']; |