aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/phpbb
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/phpbb')
-rw-r--r--phpBB/phpbb/attachment/delete.php432
-rw-r--r--phpBB/phpbb/attachment/manager.php99
-rw-r--r--phpBB/phpbb/attachment/resync.php124
-rw-r--r--phpBB/phpbb/attachment/upload.php334
-rw-r--r--phpBB/phpbb/auth/auth.php19
-rw-r--r--phpBB/phpbb/avatar/driver/gravatar.php13
-rw-r--r--phpBB/phpbb/avatar/driver/local.php6
-rw-r--r--phpBB/phpbb/captcha/plugins/recaptcha.php127
-rw-r--r--phpBB/phpbb/console/command/db/console_migrator_output_handler.php2
-rw-r--r--phpBB/phpbb/console/command/db/migrate.php9
-rw-r--r--phpBB/phpbb/console/command/db/revert.php9
-rw-r--r--phpBB/phpbb/db/driver/driver.php137
-rw-r--r--phpBB/phpbb/db/migrator.php4
-rw-r--r--phpBB/phpbb/db/output_handler/html_migrator_output_handler.php (renamed from phpBB/phpbb/db/html_migrator_output_handler.php)18
-rw-r--r--phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php46
-rw-r--r--phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php (renamed from phpBB/phpbb/db/log_wrapper_migrator_output_handler.php)25
-rw-r--r--phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php (renamed from phpBB/phpbb/db/migrator_output_handler_interface.php)2
-rw-r--r--phpBB/phpbb/db/output_handler/null_migrator_output_handler.php (renamed from phpBB/phpbb/db/null_migrator_output_handler.php)2
-rw-r--r--phpBB/phpbb/di/container_builder.php1
-rw-r--r--phpBB/phpbb/event/kernel_exception_subscriber.php22
-rw-r--r--phpBB/phpbb/hook/finder.php13
-rw-r--r--phpBB/phpbb/install/controller/archive_download.php93
-rw-r--r--phpBB/phpbb/install/controller/helper.php96
-rw-r--r--phpBB/phpbb/install/controller/install.php43
-rw-r--r--phpBB/phpbb/install/controller/update.php162
-rw-r--r--phpBB/phpbb/install/exception/file_updater_failure_exception.php22
-rw-r--r--phpBB/phpbb/install/exception/jump_to_restart_point_exception.php44
-rw-r--r--phpBB/phpbb/install/helper/config.php52
-rw-r--r--phpBB/phpbb/install/helper/container_factory.php54
-rw-r--r--phpBB/phpbb/install/helper/database.php2
-rw-r--r--phpBB/phpbb/install/helper/file_updater/compression_file_updater.php133
-rw-r--r--phpBB/phpbb/install/helper/file_updater/factory.php69
-rw-r--r--phpBB/phpbb/install/helper/file_updater/file_updater.php202
-rw-r--r--phpBB/phpbb/install/helper/file_updater/file_updater_interface.php49
-rw-r--r--phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php136
-rw-r--r--phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php119
-rw-r--r--phpBB/phpbb/install/helper/iohandler/cli_iohandler.php24
-rw-r--r--phpBB/phpbb/install/helper/iohandler/iohandler_base.php4
-rw-r--r--phpBB/phpbb/install/helper/iohandler/iohandler_interface.php19
-rw-r--r--phpBB/phpbb/install/helper/navigation/update_navigation.php80
-rw-r--r--phpBB/phpbb/install/helper/update_helper.php113
-rw-r--r--phpBB/phpbb/install/installer.php42
-rw-r--r--phpBB/phpbb/install/module/obtain_data/install_module.php (renamed from phpBB/phpbb/install/module/obtain_data/module.php)2
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php2
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php2
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php168
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php113
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php164
-rw-r--r--phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php103
-rw-r--r--phpBB/phpbb/install/module/obtain_data/update_module.php33
-rw-r--r--phpBB/phpbb/install/module/requirements/abstract_requirements_module.php (renamed from phpBB/phpbb/install/module/requirements/module.php)16
-rw-r--r--phpBB/phpbb/install/module/requirements/install_module.php25
-rw-r--r--phpBB/phpbb/install/module/requirements/task/check_filesystem.php16
-rw-r--r--phpBB/phpbb/install/module/requirements/task/check_update.php185
-rw-r--r--phpBB/phpbb/install/module/requirements/update_module.php25
-rw-r--r--phpBB/phpbb/install/module/update_database/module.php33
-rw-r--r--phpBB/phpbb/install/module/update_database/task/update.php212
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/module.php33
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/diff_files.php205
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php124
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/file_check.php186
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php168
-rw-r--r--phpBB/phpbb/install/module/update_filesystem/task/update_files.php294
-rw-r--r--phpBB/phpbb/install/module_base.php2
-rw-r--r--phpBB/phpbb/install/task_base.php2
-rw-r--r--phpBB/phpbb/notification/type/approve_post.php2
-rw-r--r--phpBB/phpbb/notification/type/approve_topic.php2
-rw-r--r--phpBB/phpbb/notification/type/bookmark.php2
-rw-r--r--phpBB/phpbb/notification/type/post.php2
-rw-r--r--phpBB/phpbb/notification/type/post_in_queue.php2
-rw-r--r--phpBB/phpbb/notification/type/quote.php4
-rw-r--r--phpBB/phpbb/notification/type/report_pm.php2
-rw-r--r--phpBB/phpbb/notification/type/topic_in_queue.php2
-rw-r--r--phpBB/phpbb/passwords/driver/salted_md5.php2
-rw-r--r--phpBB/phpbb/plupload/plupload.php2
-rw-r--r--phpBB/phpbb/routing/resources_locator/installer_resources_locator.php78
-rw-r--r--phpBB/phpbb/search/fulltext_mysql.php72
-rw-r--r--phpBB/phpbb/search/fulltext_native.php80
-rw-r--r--phpBB/phpbb/search/fulltext_postgres.php72
-rw-r--r--phpBB/phpbb/search/fulltext_sphinx.php52
80 files changed, 5178 insertions, 313 deletions
diff --git a/phpBB/phpbb/attachment/delete.php b/phpBB/phpbb/attachment/delete.php
new file mode 100644
index 0000000000..e093da8865
--- /dev/null
+++ b/phpBB/phpbb/attachment/delete.php
@@ -0,0 +1,432 @@
+<?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\attachment;
+
+use \phpbb\config\config;
+use \phpbb\db\driver\driver_interface;
+use \phpbb\event\dispatcher;
+use \phpbb\filesystem\filesystem;
+
+/**
+ * Attachment delete class
+ */
+class delete
+{
+ /** @var config */
+ protected $config;
+
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var \phpbb\event\dispatcher */
+ protected $dispatcher;
+
+ /** @var filesystem */
+ protected $filesystem;
+
+ /** @var resync */
+ protected $resync;
+
+ /** @var string phpBB root path */
+ protected $phpbb_root_path;
+
+ /** @var array Attachement IDs */
+ protected $ids;
+
+ /** @var string SQL ID string */
+ private $sql_id;
+
+ /** @var string SQL where string */
+ private $sql_where = '';
+
+ /** @var int Number of deleted items */
+ private $num_deleted;
+
+ /** @var array Post IDs */
+ private $post_ids = array();
+
+ /** @var array Message IDs */
+ private $message_ids = array();
+
+ /** @var array Topic IDs */
+ private $topic_ids = array();
+
+ /** @var array Info of physical file */
+ private $physical = array();
+
+ /**
+ * Attachment delete class constructor
+ *
+ * @param config $config
+ * @param driver_interface $db
+ * @param dispatcher $dispatcher
+ * @param filesystem $filesystem
+ * @param resync $resync
+ * @param string $phpbb_root_path
+ */
+ public function __construct(config $config, driver_interface $db, dispatcher $dispatcher, filesystem $filesystem, resync $resync, $phpbb_root_path)
+ {
+ $this->config = $config;
+ $this->db = $db;
+ $this->dispatcher = $dispatcher;
+ $this->filesystem = $filesystem;
+ $this->resync = $resync;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Delete Attachments
+ *
+ * @param string $mode can be: post|message|topic|attach|user
+ * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
+ * @param bool $resync set this to false if you are deleting posts or topics
+ *
+ * @return int|bool Number of deleted attachments or false if something
+ * went wrong during attachment deletion
+ */
+ public function delete($mode, $ids, $resync = true)
+ {
+ if (!$this->set_attachment_ids($ids))
+ {
+ return false;
+ }
+
+ $this->set_sql_constraints($mode);
+
+ /**
+ * Perform additional actions before collecting data for attachment(s) deletion
+ *
+ * @event core.delete_attachments_collect_data_before
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars)));
+
+ // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
+ $this->collect_attachment_info($resync);
+
+ // Delete attachments from database
+ $this->delete_attachments_from_db();
+
+ /**
+ * Perform additional actions after attachment(s) deletion from the database
+ *
+ * @event core.delete_attachments_from_database_after
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @var int num_deleted The number of deleted attachment(s) from the database
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ 'num_deleted',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars)));
+
+ if (!$this->num_deleted)
+ {
+ return 0;
+ }
+
+ // Delete attachments from filesystem
+ $this->remove_from_filesystem();
+
+ // If we do not resync, we do not need to adjust any message, post, topic or user entries
+ if (!$resync)
+ {
+ return $this->num_deleted;
+ }
+
+ // No more use for the original ids
+ unset($ids);
+
+ // Update post indicators for posts now no longer having attachments
+ $this->resync->resync('post', $this->post_ids);
+
+ // Update message table if messages are affected
+ $this->resync->resync('message', $this->message_ids);
+
+ // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
+ $this->resync->resync('topic', $this->topic_ids);
+
+ return $this->num_deleted;
+ }
+
+ /**
+ * Set attachment IDs
+ *
+ * @param mixed $ids ID or array of IDs
+ *
+ * @return bool True if attachment IDs were set, false if not
+ */
+ protected function set_attachment_ids($ids)
+ {
+ // 0 is as bad as an empty array
+ if (empty($ids))
+ {
+ return false;
+ }
+
+ if (is_array($ids))
+ {
+ $ids = array_unique($ids);
+ $this->ids = array_map('intval', $ids);
+ }
+ else
+ {
+ $this->ids = array((int) $ids);
+ }
+
+ return true;
+ }
+
+ /**
+ * Set SQL constraints based on mode
+ *
+ * @param string $mode Delete mode; can be: post|message|topic|attach|user
+ */
+ private function set_sql_constraints($mode)
+ {
+ switch ($mode)
+ {
+ case 'post':
+ case 'message':
+ $this->sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
+ break;
+
+ case 'topic':
+ $this->sql_id = 'topic_id';
+ break;
+
+ case 'user':
+ $this->sql_id = 'poster_id';
+ break;
+
+ case 'attach':
+ default:
+ $this->sql_id = 'attach_id';
+ break;
+ }
+ }
+
+ /**
+ * Collect info about attachment IDs
+ *
+ * @param bool $resync Whether topics/posts should be resynced after delete
+ */
+ protected function collect_attachment_info($resync)
+ {
+ // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
+ $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids);
+
+ $sql .= $this->sql_where;
+
+ $result = $this->db->sql_query($sql);
+
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
+ if ($resync && !$row['is_orphan'])
+ {
+ if (!$row['in_message'])
+ {
+ $this->post_ids[] = $row['post_msg_id'];
+ $this->topic_ids[] = $row['topic_id'];
+ }
+ else
+ {
+ $this->message_ids[] = $row['post_msg_id'];
+ }
+ }
+
+ $this->physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
+ }
+ $this->db->sql_freeresult($result);
+
+ // IDs should be unique
+ $this->post_ids = array_unique($this->post_ids);
+ $this->message_ids = array_unique($this->message_ids);
+ $this->topic_ids = array_unique($this->topic_ids);
+ }
+
+ /**
+ * Delete attachments from database table
+ */
+ protected function delete_attachments_from_db()
+ {
+ /**
+ * Perform additional actions before attachment(s) deletion
+ *
+ * @event core.delete_attachments_before
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_before', compact($vars)));
+
+ // Delete attachments
+ $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->sql_id, $this->ids);
+
+ $sql .= $this->sql_where;
+
+ $this->db->sql_query($sql);
+ $this->num_deleted = $this->db->sql_affectedrows();
+ }
+
+ /**
+ * Delete attachments from filesystem
+ */
+ protected function remove_from_filesystem()
+ {
+ $space_removed = $files_removed = 0;
+
+ foreach ($this->physical as $file_ary)
+ {
+ if ($this->unlink_attachment($file_ary['filename'], 'file', true) && !$file_ary['is_orphan'])
+ {
+ // Only non-orphaned files count to the file size
+ $space_removed += $file_ary['filesize'];
+ $files_removed++;
+ }
+
+ if ($file_ary['thumbnail'])
+ {
+ $this->unlink_attachment($file_ary['filename'], 'thumbnail', true);
+ }
+ }
+
+ /**
+ * Perform additional actions after attachment(s) deletion from the filesystem
+ *
+ * @event core.delete_attachments_from_filesystem_after
+ * @var string mode Variable containing attachments deletion mode, can be: post|message|topic|attach|user
+ * @var mixed ids Array or comma separated list of ids corresponding to the mode
+ * @var bool resync Flag indicating if posts/messages/topics should be synchronized
+ * @var string sql_id The field name to collect/delete data for depending on the mode
+ * @var array post_ids Array with post ids for deleted attachment(s)
+ * @var array topic_ids Array with topic ids for deleted attachment(s)
+ * @var array message_ids Array with private message ids for deleted attachment(s)
+ * @var array physical Array with deleted attachment(s) physical file(s) data
+ * @var int num_deleted The number of deleted attachment(s) from the database
+ * @var int space_removed The size of deleted files(s) from the filesystem
+ * @var int files_removed The number of deleted file(s) from the filesystem
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'mode',
+ 'ids',
+ 'resync',
+ 'sql_id',
+ 'post_ids',
+ 'topic_ids',
+ 'message_ids',
+ 'physical',
+ 'num_deleted',
+ 'space_removed',
+ 'files_removed',
+ );
+ extract($this->dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars)));
+
+ if ($space_removed || $files_removed)
+ {
+ $this->config->increment('upload_dir_size', $space_removed * (-1), false);
+ $this->config->increment('num_files', $files_removed * (-1), false);
+ }
+ }
+
+ /**
+ * Delete attachment from filesystem
+ *
+ * @param string $filename Filename of attachment
+ * @param string $mode Delete mode
+ * @param bool $entry_removed Whether entry was removed. Defaults to false
+ * @return bool True if file was removed, false if not
+ */
+ public function unlink_attachment($filename, $mode = 'file', $entry_removed = false)
+ {
+ // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
+ $sql = 'SELECT COUNT(attach_id) AS num_entries
+ FROM ' . ATTACHMENTS_TABLE . "
+ WHERE physical_filename = '" . $this->db->sql_escape(utf8_basename($filename)) . "'";
+ $result = $this->db->sql_query($sql);
+ $num_entries = (int) $this->db->sql_fetchfield('num_entries');
+ $this->db->sql_freeresult($result);
+
+ // Do not remove file if at least one additional entry with the same name exist.
+ if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1))
+ {
+ return false;
+ }
+
+ $filename = ($mode == 'thumbnail') ? 'thumb_' . utf8_basename($filename) : utf8_basename($filename);
+ $filepath = $this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename;
+
+ try
+ {
+ if ($this->filesystem->exists($filepath))
+ {
+ $this->filesystem->remove($this->phpbb_root_path . $this->config['upload_path'] . '/' . $filename);
+ return true;
+ }
+ }
+ catch (\phpbb\filesystem\exception\filesystem_exception $exception)
+ {
+ // Fail is covered by return statement below
+ }
+
+ return false;
+ }
+}
diff --git a/phpBB/phpbb/attachment/manager.php b/phpBB/phpbb/attachment/manager.php
new file mode 100644
index 0000000000..3c47171b2f
--- /dev/null
+++ b/phpBB/phpbb/attachment/manager.php
@@ -0,0 +1,99 @@
+<?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\attachment;
+
+/**
+ * Attachment manager
+ */
+class manager
+{
+ /** @var delete Attachment delete class */
+ protected $delete;
+
+ /** @var resync Attachment resync class */
+ protected $resync;
+
+ /** @var upload Attachment upload class */
+ protected $upload;
+
+ /**
+ * Constructor for attachment manager
+ *
+ * @param delete $delete Attachment delete class
+ * @param resync $resync Attachment resync class
+ * @param upload $upload Attachment upload class
+ */
+ public function __construct(delete $delete, resync $resync, upload $upload)
+ {
+ $this->delete = $delete;
+ $this->resync = $resync;
+ $this->upload = $upload;
+ }
+
+ /**
+ * Wrapper method for deleting attachments
+ *
+ * @param string $mode can be: post|message|topic|attach|user
+ * @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
+ * @param bool $resync set this to false if you are deleting posts or topics
+ *
+ * @return int|bool Number of deleted attachments or false if something
+ * went wrong during attachment deletion
+ */
+ public function delete($mode, $ids, $resync = true)
+ {
+ return $this->delete->delete($mode, $ids, $resync);
+ }
+
+ /**
+ * Wrapper method for deleting attachments from filesystem
+ *
+ * @param string $filename Filename of attachment
+ * @param string $mode Delete mode
+ * @param bool $entry_removed Whether entry was removed. Defaults to false
+ * @return bool True if file was removed, false if not
+ */
+ public function unlink($filename, $mode = 'file', $entry_removed = false)
+ {
+ return $this->delete->unlink_attachment($filename, $mode, $entry_removed);
+ }
+
+ /**
+ * Wrapper method for resyncing specified type
+ *
+ * @param string $type Type of resync
+ * @param array $ids IDs to resync
+ */
+ public function resync($type, $ids)
+ {
+ $this->resync->resync($type, $ids);
+ }
+
+ /**
+ * Wrapper method for uploading attachment
+ *
+ * @param string $form_name The form name of the file upload input
+ * @param int $forum_id The id of the forum
+ * @param bool $local Whether the file is local or not
+ * @param string $local_storage The path to the local file
+ * @param bool $is_message Whether it is a PM or not
+ * @param array $local_filedata An file data object created for the local file
+ *
+ * @return array File data array
+ */
+ public function upload($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = [])
+ {
+ return $this->upload->upload($form_name, $forum_id, $local, $local_storage, $is_message, $local_filedata);
+ }
+}
diff --git a/phpBB/phpbb/attachment/resync.php b/phpBB/phpbb/attachment/resync.php
new file mode 100644
index 0000000000..6c2e0a8b0d
--- /dev/null
+++ b/phpBB/phpbb/attachment/resync.php
@@ -0,0 +1,124 @@
+<?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\attachment;
+
+use \phpbb\db\driver\driver_interface;
+
+/**
+ * Attachment resync class
+ */
+class resync
+{
+ /** @var driver_interface */
+ protected $db;
+
+ /** @var string Attachment table SQL ID */
+ private $attach_sql_id;
+
+ /** @var string Resync table SQL ID */
+ private $resync_sql_id;
+
+ /** @var string Resync SQL table */
+ private $resync_table;
+
+ /** @var string SQL where statement */
+ private $sql_where;
+
+ /**
+ * Constructor for attachment resync class
+ *
+ * @param driver_interface $db Database driver
+ */
+ public function __construct(driver_interface $db)
+ {
+ $this->db = $db;
+ }
+
+ /**
+ * Set type constraints for attachment resync
+ *
+ * @param string $type Type of resync; can be: message|post|topic
+ */
+ protected function set_type_constraints($type)
+ {
+ switch ($type)
+ {
+ case 'message':
+ $this->attach_sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = 1
+ AND is_orphan = 0';
+ $this->resync_table = PRIVMSGS_TABLE;
+ $this->resync_sql_id = 'msg_id';
+ break;
+
+ case 'post':
+ $this->attach_sql_id = 'post_msg_id';
+ $this->sql_where = ' AND in_message = 0
+ AND is_orphan = 0';
+ $this->resync_table = POSTS_TABLE;
+ $this->resync_sql_id = 'post_id';
+ break;
+
+ case 'topic':
+ $this->attach_sql_id = 'topic_id';
+ $this->sql_where = ' AND is_orphan = 0';
+ $this->resync_table = TOPICS_TABLE;
+ $this->resync_sql_id = 'topic_id';
+ break;
+ }
+ }
+
+ /**
+ * Resync specified type
+ *
+ * @param string $type Type of resync
+ * @param array $ids IDs to resync
+ */
+ public function resync($type, $ids)
+ {
+ if (empty($type) || !is_array($ids) || !sizeof($ids) || !in_array($type, array('post', 'topic', 'message')))
+ {
+ return;
+ }
+
+ $this->set_type_constraints($type);
+
+ // Just check which elements are still having an assigned attachment
+ // not orphaned by querying the attachments table
+ $sql = 'SELECT ' . $this->attach_sql_id . '
+ FROM ' . ATTACHMENTS_TABLE . '
+ WHERE ' . $this->db->sql_in_set($this->attach_sql_id, $ids)
+ . $this->sql_where;
+ $result = $this->db->sql_query($sql);
+
+ $remaining_ids = array();
+ while ($row = $this->db->sql_fetchrow($result))
+ {
+ $remaining_ids[] = $row[$this->attach_sql_id];
+ }
+ $this->db->sql_freeresult($result);
+
+ // Now only unset those ids remaining
+ $ids = array_diff($ids, $remaining_ids);
+
+ if (sizeof($ids))
+ {
+ $sql = 'UPDATE ' . $this->resync_table . '
+ SET ' . $type . '_attachment = 0
+ WHERE ' . $this->db->sql_in_set($this->resync_sql_id, $ids);
+ $this->db->sql_query($sql);
+ }
+ }
+
+}
diff --git a/phpBB/phpbb/attachment/upload.php b/phpBB/phpbb/attachment/upload.php
new file mode 100644
index 0000000000..957558768b
--- /dev/null
+++ b/phpBB/phpbb/attachment/upload.php
@@ -0,0 +1,334 @@
+<?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\attachment;
+
+use phpbb\auth\auth;
+use \phpbb\cache\service;
+use \phpbb\config\config;
+use \phpbb\event\dispatcher;
+use \phpbb\language\language;
+use \phpbb\mimetype\guesser;
+use \phpbb\plupload\plupload;
+use \phpbb\user;
+
+/**
+ * Attachment upload class
+ */
+class upload
+{
+ /** @var auth */
+ protected $auth;
+
+ /** @var service */
+ protected $cache;
+
+ /** @var config */
+ protected $config;
+
+ /** @var \phpbb\files\upload Upload class */
+ protected $files_upload;
+
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ /** @var guesser Mimetype guesser */
+ protected $mimetype_guesser;
+
+ /** @var dispatcher */
+ protected $phpbb_dispatcher;
+
+ /** @var plupload Plupload */
+ protected $plupload;
+
+ /** @var user */
+ protected $user;
+
+ /** @var \phpbb\files\filespec Current filespec instance */
+ private $file;
+
+ /** @var array File data */
+ private $file_data = array(
+ 'error' => array()
+ );
+
+ /** @var array Extensions array */
+ private $extensions;
+
+ /**
+ * Constructor for attachments upload class
+ *
+ * @param auth $auth
+ * @param service $cache
+ * @param config $config
+ * @param \phpbb\files\upload $files_upload
+ * @param language $language
+ * @param guesser $mimetype_guesser
+ * @param dispatcher $phpbb_dispatcher
+ * @param plupload $plupload
+ * @param user $user
+ * @param $phpbb_root_path
+ */
+ public function __construct(auth $auth, service $cache, config $config, \phpbb\files\upload $files_upload, language $language, guesser $mimetype_guesser, dispatcher $phpbb_dispatcher, plupload $plupload, user $user, $phpbb_root_path)
+ {
+ $this->auth = $auth;
+ $this->cache = $cache;
+ $this->config = $config;
+ $this->files_upload = $files_upload;
+ $this->language = $language;
+ $this->mimetype_guesser = $mimetype_guesser;
+ $this->phpbb_dispatcher = $phpbb_dispatcher;
+ $this->plupload = $plupload;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * Upload Attachment - filedata is generated here
+ * Uses upload class
+ *
+ * @param string $form_name The form name of the file upload input
+ * @param int $forum_id The id of the forum
+ * @param bool $local Whether the file is local or not
+ * @param string $local_storage The path to the local file
+ * @param bool $is_message Whether it is a PM or not
+ * @param array $local_filedata An file data object created for the local file
+ *
+ * @return array File data array
+ */
+ public function upload($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = array())
+ {
+ $this->init_files_upload($forum_id, $is_message);
+
+ $this->file_data['post_attach'] = $local || $this->files_upload->is_valid($form_name);
+
+ if (!$this->file_data['post_attach'])
+ {
+ $this->file_data['error'][] = $this->language->lang('NO_UPLOAD_FORM_FOUND');
+ return $this->file_data;
+ }
+
+ $this->file = ($local) ? $this->files_upload->handle_upload('files.types.local', $local_storage, $local_filedata) : $this->files_upload->handle_upload('files.types.form', $form_name);
+
+ if ($this->file->init_error())
+ {
+ $this->file_data['post_attach'] = false;
+ return $this->file_data;
+ }
+
+ // Whether the uploaded file is in the image category
+ $is_image = (isset($this->extensions[$this->file->get('extension')]['display_cat'])) ? $this->extensions[$this->file->get('extension')]['display_cat'] == ATTACHMENT_CATEGORY_IMAGE : false;
+
+ if (!$this->auth->acl_get('a_') && !$this->auth->acl_get('m_', $forum_id))
+ {
+ // Check Image Size, if it is an image
+ if ($is_image)
+ {
+ $this->file->upload->set_allowed_dimensions(0, 0, $this->config['img_max_width'], $this->config['img_max_height']);
+ }
+
+ // Admins and mods are allowed to exceed the allowed filesize
+ if (!empty($this->extensions[$this->file->get('extension')]['max_filesize']))
+ {
+ $allowed_filesize = $this->extensions[$this->file->get('extension')]['max_filesize'];
+ }
+ else
+ {
+ $allowed_filesize = ($is_message) ? $this->config['max_filesize_pm'] : $this->config['max_filesize'];
+ }
+
+ $this->file->upload->set_max_filesize($allowed_filesize);
+ }
+
+ $this->file->clean_filename('unique', $this->user->data['user_id'] . '_');
+
+ // Are we uploading an image *and* this image being within the image category?
+ // Only then perform additional image checks.
+ $this->file->move_file($this->config['upload_path'], false, !$is_image);
+
+ // Do we have to create a thumbnail?
+ $this->file_data['thumbnail'] = ($is_image && $this->config['img_create_thumbnail']) ? 1 : 0;
+
+ // Make sure the image category only holds valid images...
+ $this->check_image($is_image);
+
+ if (sizeof($this->file->error))
+ {
+ $this->file->remove();
+ $this->file_data['error'] = array_merge($this->file_data['error'], $this->file->error);
+ $this->file_data['post_attach'] = false;
+
+ return $this->file_data;
+ }
+
+ $this->fill_file_data();
+
+ $filedata = $this->file_data;
+
+ /**
+ * Event to modify uploaded file before submit to the post
+ *
+ * @event core.modify_uploaded_file
+ * @var array filedata Array containing uploaded file data
+ * @var bool is_image Flag indicating if the file is an image
+ * @since 3.1.0-RC3
+ */
+ $vars = array(
+ 'filedata',
+ 'is_image',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.modify_uploaded_file', compact($vars)));
+ $this->file_data = $filedata;
+ unset($filedata);
+
+ // Check for attachment quota and free space
+ if (!$this->check_attach_quota() || !$this->check_disk_space())
+ {
+ return $this->file_data;
+ }
+
+ // Create Thumbnail
+ $this->create_thumbnail();
+
+ return $this->file_data;
+ }
+
+ /**
+ * Create thumbnail for file if necessary
+ *
+ * @return array Updated $filedata
+ */
+ protected function create_thumbnail()
+ {
+ if ($this->file_data['thumbnail'])
+ {
+ $source = $this->file->get('destination_file');
+ $destination = $this->file->get('destination_path') . '/thumb_' . $this->file->get('realname');
+
+ if (!create_thumbnail($source, $destination, $this->file->get('mimetype')))
+ {
+ $this->file_data['thumbnail'] = 0;
+ }
+ }
+ }
+
+ /**
+ * Init files upload class
+ *
+ * @param int $forum_id Forum ID
+ * @param bool $is_message Whether attachment is inside PM or not
+ */
+ protected function init_files_upload($forum_id, $is_message)
+ {
+ if ($this->config['check_attachment_content'] && isset($this->config['mime_triggers']))
+ {
+ $this->files_upload->set_disallowed_content(explode('|', $this->config['mime_triggers']));
+ }
+ else if (!$this->config['check_attachment_content'])
+ {
+ $this->files_upload->set_disallowed_content(array());
+ }
+
+ $this->extensions = $this->cache->obtain_attach_extensions((($is_message) ? false : (int) $forum_id));
+ $this->files_upload->set_allowed_extensions(array_keys($this->extensions['_allowed_']));
+ }
+
+ /**
+ * Check if uploaded file is really an image
+ *
+ * @param bool $is_image Whether file is image
+ */
+ protected function check_image($is_image)
+ {
+ // Make sure the image category only holds valid images...
+ if ($is_image && !$this->file->is_image())
+ {
+ $this->file->remove();
+
+ if ($this->plupload && $this->plupload->is_active())
+ {
+ $this->plupload->emit_error(104, 'ATTACHED_IMAGE_NOT_IMAGE');
+ }
+
+ // If this error occurs a user tried to exploit an IE Bug by renaming extensions
+ // Since the image category is displaying content inline we need to catch this.
+ $this->file->set_error($this->language->lang('ATTACHED_IMAGE_NOT_IMAGE'));
+ }
+ }
+
+ /**
+ * Check if attachment quota was reached
+ *
+ * @return bool False if attachment quota was reached, true if not
+ */
+ protected function check_attach_quota()
+ {
+ if ($this->config['attachment_quota'])
+ {
+ if (intval($this->config['upload_dir_size']) + $this->file->get('filesize') > $this->config['attachment_quota'])
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_QUOTA_REACHED');
+ $this->file_data['post_attach'] = false;
+
+ $this->file->remove();
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if there is enough free space available on disk
+ *
+ * @return bool True if disk space is available, false if not
+ */
+ protected function check_disk_space()
+ {
+ if ($free_space = @disk_free_space($this->phpbb_root_path . $this->config['upload_path']))
+ {
+ if ($free_space <= $this->file->get('filesize'))
+ {
+ if ($this->auth->acl_get('a_'))
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_DISK_FULL');
+ }
+ else
+ {
+ $this->file_data['error'][] = $this->language->lang('ATTACH_QUOTA_REACHED');
+ }
+ $this->file_data['post_attach'] = false;
+
+ $this->file->remove();
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Fills file data with file information and current time as filetime
+ */
+ protected function fill_file_data()
+ {
+ $this->file_data['filesize'] = $this->file->get('filesize');
+ $this->file_data['mimetype'] = $this->file->get('mimetype');
+ $this->file_data['extension'] = $this->file->get('extension');
+ $this->file_data['physical_filename'] = $this->file->get('realname');
+ $this->file_data['real_filename'] = $this->file->get('uploadname');
+ $this->file_data['filetime'] = time();
+ }
+}
diff --git a/phpBB/phpbb/auth/auth.php b/phpBB/phpbb/auth/auth.php
index 92c19fd5f7..fc7cc1a0b1 100644
--- a/phpBB/phpbb/auth/auth.php
+++ b/phpBB/phpbb/auth/auth.php
@@ -928,6 +928,7 @@ class auth
function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
{
global $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
+ global $phpbb_dispatcher;
/* @var $provider_collection \phpbb\auth\provider_collection */
$provider_collection = $phpbb_container->get('auth.provider_collection');
@@ -983,6 +984,24 @@ class auth
redirect($url);
}
+ /**
+ * Event is triggered after checking for valid username and password, and before the actual session creation.
+ *
+ * @event core.auth_login_session_create_before
+ * @var array login Variable containing login array
+ * @var bool admin Boolean variable whether user is logging into the ACP
+ * @var string username Username of user to log in
+ * @var bool autologin Boolean variable signaling whether login is triggered via auto login
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'login',
+ 'admin',
+ 'username',
+ 'autologin',
+ );
+ extract($phpbb_dispatcher->trigger_event('core.auth_login_session_create_before', compact($vars)));
+
// If login succeeded, we will log the user in... else we pass the login array through...
if ($login['status'] == LOGIN_SUCCESS)
{
diff --git a/phpBB/phpbb/avatar/driver/gravatar.php b/phpBB/phpbb/avatar/driver/gravatar.php
index badbd9421d..b8cf84424a 100644
--- a/phpBB/phpbb/avatar/driver/gravatar.php
+++ b/phpBB/phpbb/avatar/driver/gravatar.php
@@ -172,6 +172,8 @@ class gravatar extends \phpbb\avatar\driver\driver
*/
protected function get_gravatar_url($row)
{
+ global $phpbb_dispatcher;
+
$url = self::GRAVATAR_URL;
$url .= md5(strtolower(trim($row['avatar'])));
@@ -180,6 +182,17 @@ class gravatar extends \phpbb\avatar\driver\driver
$url .= '?s=' . max($row['avatar_width'], $row['avatar_height']);
}
+ /**
+ * Modify gravatar url
+ *
+ * @event core.get_gravatar_url_after
+ * @var string row User data or group data
+ * @var string url Gravatar URL
+ * @since 3.1.7-RC1
+ */
+ $vars = array('row', 'url');
+ extract($phpbb_dispatcher->trigger_event('core.get_gravatar_url_after', compact($vars)));
+
return $url;
}
}
diff --git a/phpBB/phpbb/avatar/driver/local.php b/phpBB/phpbb/avatar/driver/local.php
index 88a139f81e..f5547c4bc6 100644
--- a/phpBB/phpbb/avatar/driver/local.php
+++ b/phpBB/phpbb/avatar/driver/local.php
@@ -84,11 +84,13 @@ class local extends \phpbb\avatar\driver\driver
'AVATAR_IMAGE' => $this->phpbb_root_path . $this->config['avatar_gallery_path'] . '/' . $img['file'],
'AVATAR_NAME' => $img['name'],
'AVATAR_FILE' => $img['filename'],
+ 'CHECKED' => $img['file'] === $row['avatar'],
));
$template->assign_block_vars('avatar_local_row.avatar_local_option', array(
'AVATAR_FILE' => $img['filename'],
- 'S_OPTIONS_AVATAR' => $img['filename']
+ 'S_OPTIONS_AVATAR' => $img['filename'],
+ 'CHECKED' => $img['file'] === $row['avatar'],
));
$col_count = ($col_count + 1) % $table_cols;
@@ -184,7 +186,7 @@ class local extends \phpbb\avatar\driver\driver
}
$cat = ($path == $file_path) ? $user->lang['NO_AVATAR_CATEGORY'] : str_replace("$path/", '', $file_path);
$avatar_list[$cat][$image] = array(
- 'file' => ($cat != $user->lang['NO_AVATAR_CATEGORY']) ? rawurlencode($cat) . '/' . rawurlencode($image) : rawurlencode($image),
+ 'file' => ($cat != $user->lang['NO_AVATAR_CATEGORY']) ? str_replace('%2F', '/', 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/captcha/plugins/recaptcha.php b/phpBB/phpbb/captcha/plugins/recaptcha.php
index 98132ab47d..152709a9ea 100644
--- a/phpBB/phpbb/captcha/plugins/recaptcha.php
+++ b/phpBB/phpbb/captcha/plugins/recaptcha.php
@@ -18,12 +18,6 @@ class recaptcha extends captcha_abstract
var $recaptcha_server = 'http://www.google.com/recaptcha/api';
var $recaptcha_server_secure = 'https://www.google.com/recaptcha/api'; // class constants :(
- // We are opening a socket to port 80 of this host and send
- // the POST request asking for verification to the path specified here.
- var $recaptcha_verify_server = 'www.google.com';
- var $recaptcha_verify_path = '/recaptcha/api/verify';
-
- var $challenge;
var $response;
/**
@@ -37,12 +31,11 @@ class recaptcha extends captcha_abstract
function init($type)
{
- global $config, $db, $user, $request;
+ global $user, $request;
$user->add_lang('captcha_recaptcha');
parent::init($type);
- $this->challenge = $request->variable('recaptcha_challenge_field', '');
- $this->response = $request->variable('recaptcha_response_field', '');
+ $this->response = $request->variable('g-recaptcha-response', '');
}
public function is_available()
@@ -75,7 +68,7 @@ class recaptcha extends captcha_abstract
function acp_page($id, &$module)
{
- global $config, $db, $template, $user, $phpbb_log, $request;
+ global $config, $template, $user, $phpbb_log, $request;
$captcha_vars = array(
'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY',
@@ -151,7 +144,6 @@ class recaptcha extends captcha_abstract
$template->assign_vars(array(
'RECAPTCHA_SERVER' => $this->recaptcha_server,
'RECAPTCHA_PUBKEY' => isset($config['recaptcha_pubkey']) ? $config['recaptcha_pubkey'] : '',
- 'RECAPTCHA_ERRORGET' => '',
'S_RECAPTCHA_AVAILABLE' => self::is_available(),
'S_CONFIRM_CODE' => true,
'S_TYPE' => $this->type,
@@ -202,106 +194,25 @@ class recaptcha extends captcha_abstract
}
}
-// Code from here on is based on recaptchalib.php
-/*
- * This is a PHP library that handles calling reCAPTCHA.
- * - Documentation and latest version
- * http://recaptcha.net/plugins/php/
- * - Get a reCAPTCHA API Key
- * http://recaptcha.net/api/getkey
- * - Discussion group
- * http://groups.google.com/group/recaptcha
- *
- * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
- * AUTHORS:
- * Mike Crawford
- * Ben Maurer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
- /**
- * Submits an HTTP POST to a reCAPTCHA server
- * @param string $host
- * @param string $path
- * @param array $data
- * @param int port
- * @return array response
- */
- function _recaptcha_http_post($host, $path, $data, $port = 80)
- {
- $req = $this->_recaptcha_qsencode ($data);
-
- $http_request = "POST $path HTTP/1.0\r\n";
- $http_request .= "Host: $host\r\n";
- $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
- $http_request .= "Content-Length: " . strlen($req) . "\r\n";
- $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n";
- $http_request .= "\r\n";
- $http_request .= $req;
-
- $response = '';
- if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10)))
- {
- trigger_error('RECAPTCHA_SOCKET_ERROR', E_USER_ERROR);
- }
-
- fwrite($fs, $http_request);
-
- while (!feof($fs))
- {
- // One TCP-IP packet
- $response .= fgets($fs, 1160);
- }
- fclose($fs);
- $response = explode("\r\n\r\n", $response, 2);
-
- return $response;
- }
-
/**
* Calls an HTTP POST function to verify if the user's guess was correct
- * @param array $extra_params an array of extra variables to post to the server
- * @return ReCaptchaResponse
+ *
+ * @return bool|string Returns false on success or error string on failure.
*/
- function recaptcha_check_answer($extra_params = array())
+ function recaptcha_check_answer()
{
global $config, $user;
//discard spam submissions
- if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0)
+ if ($this->response == null || strlen($this->response) == 0)
{
return $user->lang['RECAPTCHA_INCORRECT'];
}
- $response = $this->_recaptcha_http_post($this->recaptcha_verify_server, $this->recaptcha_verify_path,
- array(
- 'privatekey' => $config['recaptcha_privkey'],
- 'remoteip' => $user->ip,
- 'challenge' => $this->challenge,
- 'response' => $this->response
- ) + $extra_params
- );
-
- $answers = explode("\n", $response[1]);
+ $recaptcha = new \ReCaptcha\ReCaptcha($config['recaptcha_privkey']);
+ $result = $recaptcha->verify($this->response, $user->ip);
- if (trim($answers[0]) === 'true')
+ if ($result->isSuccess())
{
$this->solved = true;
return false;
@@ -311,22 +222,4 @@ class recaptcha extends captcha_abstract
return $user->lang['RECAPTCHA_INCORRECT'];
}
}
-
- /**
- * Encodes the given data into a query string format
- * @param $data - array of string elements to be encoded
- * @return string - encoded request
- */
- function _recaptcha_qsencode($data)
- {
- $req = '';
- foreach ($data as $key => $value)
- {
- $req .= $key . '=' . urlencode(stripslashes($value)) . '&';
- }
-
- // Cut the last '&'
- $req = substr($req, 0, strlen($req) - 1);
- return $req;
- }
}
diff --git a/phpBB/phpbb/console/command/db/console_migrator_output_handler.php b/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
index b9741a3838..568b2646d4 100644
--- a/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
+++ b/phpBB/phpbb/console/command/db/console_migrator_output_handler.php
@@ -13,8 +13,8 @@
namespace phpbb\console\command\db;
+use phpbb\db\output_handler\migrator_output_handler_interface;
use phpbb\user;
-use phpbb\db\migrator_output_handler_interface;
use Symfony\Component\Console\Output\OutputInterface;
class console_migrator_output_handler implements migrator_output_handler_interface
diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php
index 43029b7458..ae4211f7be 100644
--- a/phpBB/phpbb/console/command/db/migrate.php
+++ b/phpBB/phpbb/console/command/db/migrate.php
@@ -12,6 +12,7 @@
*/
namespace phpbb\console\command\db;
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -26,8 +27,12 @@ class migrate extends \phpbb\console\command\db\migration_command
/** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
- function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
{
+ $this->language = $language;
$this->log = $log;
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
@@ -45,7 +50,7 @@ class migrate extends \phpbb\console\command\db\migration_command
protected function execute(InputInterface $input, OutputInterface $output)
{
- $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
+ $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
$this->migrator->create_migrations_table();
diff --git a/phpBB/phpbb/console/command/db/revert.php b/phpBB/phpbb/console/command/db/revert.php
index 838640968e..3fa2e17515 100644
--- a/phpBB/phpbb/console/command/db/revert.php
+++ b/phpBB/phpbb/console/command/db/revert.php
@@ -12,6 +12,7 @@
*/
namespace phpbb\console\command\db;
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -24,9 +25,13 @@ class revert extends \phpbb\console\command\db\migration_command
/** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
- function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
+ /** @var \phpbb\language\language */
+ protected $language;
+
+ function __construct(\phpbb\user $user, \phpbb\language\language $language, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
{
$this->filesystem = $filesystem;
+ $this->language = $language;
$this->phpbb_root_path = $phpbb_root_path;
parent::__construct($user, $migrator, $extension_manager, $config, $cache);
$this->user->add_lang(array('common', 'migrator'));
@@ -49,7 +54,7 @@ class revert extends \phpbb\console\command\db\migration_command
{
$name = str_replace('/', '\\', $input->getArgument('name'));
- $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
+ $this->migrator->set_output_handler(new log_wrapper_migrator_output_handler($this->language, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
$this->cache->purge();
diff --git a/phpBB/phpbb/db/driver/driver.php b/phpBB/phpbb/db/driver/driver.php
index 2925765e94..7e2d7a5ea6 100644
--- a/phpBB/phpbb/db/driver/driver.php
+++ b/phpBB/phpbb/db/driver/driver.php
@@ -774,7 +774,18 @@ abstract class driver implements driver_interface
if (!empty($array['WHERE']))
{
- $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']);
+ $sql .= ' WHERE ';
+
+ if (is_array($array['WHERE']))
+ {
+ $sql_where = $this->_process_boolean_tree_first($array['WHERE']);
+ }
+ else
+ {
+ $sql_where = $array['WHERE'];
+ }
+
+ $sql .= $this->_sql_custom_build('WHERE', $sql_where);
}
if (!empty($array['GROUP_BY']))
@@ -793,6 +804,130 @@ abstract class driver implements driver_interface
return $sql;
}
+
+ protected function _process_boolean_tree_first($operations_ary)
+ {
+ // In cases where an array exists but there is no head condition,
+ // it should be because there's only 1 WHERE clause. This seems the best way to deal with it.
+ if ($operations_ary[0] !== 'AND' &&
+ $operations_ary[0] !== 'OR')
+ {
+ $operations_ary = array('AND', $operations_ary);
+ }
+ return $this->_process_boolean_tree($operations_ary) . "\n";
+ }
+
+ protected function _process_boolean_tree($operations_ary)
+ {
+ $operation = array_shift($operations_ary);
+
+ foreach ($operations_ary as &$condition)
+ {
+ switch ($condition[0])
+ {
+ case 'AND':
+ case 'OR':
+
+ $condition = ' ( ' . $this->_process_boolean_tree($condition) . ') ';
+
+ break;
+ case 'NOT':
+
+ $condition = ' NOT (' . $this->_process_boolean_tree($condition) . ') ';
+
+ break;
+
+ default:
+
+ switch (sizeof($condition))
+ {
+ case 3:
+
+ // Typical 3 element clause with {left hand} {operator} {right hand}
+ switch ($condition[1])
+ {
+ case 'IN':
+ case 'NOT_IN':
+
+ // As this is used with an IN, assume it is a set of elements for sql_in_set()
+ $condition = $this->sql_in_set($condition[0], $condition[2], $condition[1] === 'NOT_IN', true);
+
+ break;
+
+ case 'LIKE':
+
+ $condition = $condition[0] . ' ' . $this->sql_like_expression($condition[2]) . ' ';
+
+ break;
+
+ case 'NOT_LIKE':
+
+ $condition = $condition[0] . ' ' . $this->sql_not_like_expression($condition[2]) . ' ';
+
+ break;
+
+ case 'IS_NOT':
+
+ $condition[1] = 'IS NOT';
+
+ // no break
+ case 'IS':
+
+ // If the value is NULL, the string of it is the empty string ('') which is not the intended result.
+ // this should solve that
+ if ($condition[2] === null)
+ {
+ $condition[2] = 'NULL';
+ }
+
+ $condition = implode(' ', $condition);
+
+ break;
+
+ default:
+
+ $condition = implode(' ', $condition);
+
+ break;
+ }
+
+ break;
+
+ case 5:
+
+ // Subquery with {left hand} {operator} {compare kind} {SELECT Kind } {Sub Query}
+
+ $condition = $condition[0] . ' ' . $condition[1] . ' ' . $condition[2] . ' ( ';
+ $condition .= $this->sql_build_query($condition[3], $condition[4]);
+ $condition .= ' )';
+
+ break;
+
+ default:
+ // This is an unpredicted clause setup. Just join all elements.
+ $condition = implode(' ', $condition);
+
+ break;
+ }
+
+ break;
+ }
+
+ }
+
+ if ($operation === 'NOT')
+ {
+ $operations_ary = implode("", $operations_ary);
+ }
+ else
+ {
+ $operations_ary = implode(" \n $operation ", $operations_ary);
+ }
+
+ return $operations_ary;
+ }
+
+
/**
* {@inheritDoc}
*/
diff --git a/phpBB/phpbb/db/migrator.php b/phpBB/phpbb/db/migrator.php
index 18c6403c07..a809bc14f9 100644
--- a/phpBB/phpbb/db/migrator.php
+++ b/phpBB/phpbb/db/migrator.php
@@ -13,6 +13,8 @@
namespace phpbb\db;
+use phpbb\db\output_handler\migrator_output_handler_interface;
+use phpbb\db\output_handler\null_migrator_output_handler;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -122,7 +124,7 @@ class migrator
/**
* Set the output handler.
*
- * @param migrator_output_handler $handler The output handler
+ * @param migrator_output_handler_interface $handler The output handler
*/
public function set_output_handler(migrator_output_handler_interface $handler)
{
diff --git a/phpBB/phpbb/db/html_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/html_migrator_output_handler.php
index e37c667463..67309649c9 100644
--- a/phpBB/phpbb/db/html_migrator_output_handler.php
+++ b/phpBB/phpbb/db/output_handler/html_migrator_output_handler.php
@@ -11,27 +11,25 @@
*
*/
-namespace phpbb\db;
-
-use phpbb\user;
+namespace phpbb\db\output_handler;
class html_migrator_output_handler implements migrator_output_handler_interface
{
/**
- * User object.
+ * Language object.
*
- * @var user
+ * @var \phpbb\language\language
*/
- private $user;
+ private $language;
/**
* Constructor
*
- * @param user $user User object
+ * @param \phpbb\language\language $language Language object
*/
- public function __construct(user $user)
+ public function __construct(\phpbb\language\language $language)
{
- $this->user = $user;
+ $this->language = $language;
}
/**
@@ -41,7 +39,7 @@ class html_migrator_output_handler implements migrator_output_handler_interface
{
if ($verbosity <= migrator_output_handler_interface::VERBOSITY_VERBOSE)
{
- $final_message = call_user_func_array(array($this->user, 'lang'), $message);
+ $final_message = $this->language->lang_array(array_shift($message), $message);
echo $final_message . "<br />\n";
}
}
diff --git a/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php
new file mode 100644
index 0000000000..56d5cf49a1
--- /dev/null
+++ b/phpBB/phpbb/db/output_handler/installer_migrator_output_handler.php
@@ -0,0 +1,46 @@
+<?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\output_handler;
+
+use phpbb\install\helper\iohandler\iohandler_interface;
+
+class installer_migrator_output_handler implements migrator_output_handler_interface
+{
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param iohandler_interface $iohandler Installer's IO-handler
+ */
+ public function __construct(iohandler_interface $iohandler)
+ {
+ $this->iohandler = $iohandler;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function write($message, $verbosity)
+ {
+ if ($verbosity <= migrator_output_handler_interface::VERBOSITY_VERBOSE)
+ {
+ $this->iohandler->add_log_message($message);
+ $this->iohandler->send_response();
+ }
+ }
+}
diff --git a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php
index 4c85bf4d67..20991746ac 100644
--- a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php
+++ b/phpBB/phpbb/db/output_handler/log_wrapper_migrator_output_handler.php
@@ -11,18 +11,16 @@
*
*/
-namespace phpbb\db;
-
-use phpbb\user;
+namespace phpbb\db\output_handler;
class log_wrapper_migrator_output_handler implements migrator_output_handler_interface
{
/**
- * User object.
+ * Language object.
*
- * @var user
+ * @var \phpbb\language\language
*/
- protected $user;
+ protected $language;
/**
* A migrator output handler
@@ -45,14 +43,14 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int
/**
* Constructor
*
- * @param user $user User object
- * @param migrator_output_handler_interface $migrator Migrator output handler
- * @param string $log_file File to log to
- * @param \phpbb\filesystem\filesystem_interface phpBB filesystem object
+ * @param \phpbb\language\language $language Language object
+ * @param migrator_output_handler_interface $migrator Migrator output handler
+ * @param string $log_file File to log to
+ * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB filesystem object
*/
- public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file, \phpbb\filesystem\filesystem_interface $filesystem)
+ public function __construct(\phpbb\language\language $language, migrator_output_handler_interface $migrator, $log_file, \phpbb\filesystem\filesystem_interface $filesystem)
{
- $this->user = $user;
+ $this->language = $language;
$this->migrator = $migrator;
$this->filesystem = $filesystem;
$this->file_open($log_file);
@@ -84,7 +82,8 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int
if ($this->file_handle !== false)
{
- $translated_message = call_user_func_array(array($this->user, 'lang'), $message) . "\n";
+
+ $translated_message = $this->language->lang_array(array_shift($message), $message);
if ($verbosity <= migrator_output_handler_interface::VERBOSITY_NORMAL)
{
diff --git a/phpBB/phpbb/db/migrator_output_handler_interface.php b/phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php
index a923af99f6..7bb5c73fec 100644
--- a/phpBB/phpbb/db/migrator_output_handler_interface.php
+++ b/phpBB/phpbb/db/output_handler/migrator_output_handler_interface.php
@@ -11,7 +11,7 @@
*
*/
-namespace phpbb\db;
+namespace phpbb\db\output_handler;
interface migrator_output_handler_interface
{
diff --git a/phpBB/phpbb/db/null_migrator_output_handler.php b/phpBB/phpbb/db/output_handler/null_migrator_output_handler.php
index 0e8cfbb049..5fc2a52577 100644
--- a/phpBB/phpbb/db/null_migrator_output_handler.php
+++ b/phpBB/phpbb/db/output_handler/null_migrator_output_handler.php
@@ -11,7 +11,7 @@
*
*/
-namespace phpbb\db;
+namespace phpbb\db\output_handler;
class null_migrator_output_handler implements migrator_output_handler_interface
{
diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php
index fb391760ce..0a94aac98d 100644
--- a/phpBB/phpbb/di/container_builder.php
+++ b/phpBB/phpbb/di/container_builder.php
@@ -355,6 +355,7 @@ class container_builder
->without_cache()
->without_extensions()
->with_config($this->config_php_file)
+ ->with_config_path($this->get_config_path())
->with_environment('production')
->without_compiled_container()
->get_container()
diff --git a/phpBB/phpbb/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php
index 0a8a0183dc..e427abf5e3 100644
--- a/phpBB/phpbb/event/kernel_exception_subscriber.php
+++ b/phpBB/phpbb/event/kernel_exception_subscriber.php
@@ -24,26 +24,28 @@ class kernel_exception_subscriber implements EventSubscriberInterface
{
/**
* Template object
+ *
* @var \phpbb\template\template
*/
protected $template;
/**
- * User object
- * @var \phpbb\user
+ * Language object
+ *
+ * @var \phpbb\language\language
*/
- protected $user;
+ protected $language;
/**
* Construct method
*
- * @param \phpbb\template\template $template Template object
- * @param \phpbb\user $user User object
+ * @param \phpbb\template\template $template Template object
+ * @param \phpbb\language\language $language Language object
*/
- public function __construct(\phpbb\template\template $template, \phpbb\user $user)
+ public function __construct(\phpbb\template\template $template, \phpbb\language\language $language)
{
$this->template = $template;
- $this->user = $user;
+ $this->language = $language;
}
/**
@@ -60,15 +62,15 @@ class kernel_exception_subscriber implements EventSubscriberInterface
if ($exception instanceof \phpbb\exception\exception_interface)
{
- $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($message), $exception->get_parameters()));
+ $message = $this->language->lang_array($message, $exception->get_parameters());
}
if (!$event->getRequest()->isXmlHttpRequest())
{
- page_header($this->user->lang('INFORMATION'));
+ page_header($this->language->lang('INFORMATION'));
$this->template->assign_vars(array(
- 'MESSAGE_TITLE' => $this->user->lang('INFORMATION'),
+ 'MESSAGE_TITLE' => $this->language->lang('INFORMATION'),
'MESSAGE_TEXT' => $message,
));
diff --git a/phpBB/phpbb/hook/finder.php b/phpBB/phpbb/hook/finder.php
index a3d02d3aa0..f5a68a1370 100644
--- a/phpBB/phpbb/hook/finder.php
+++ b/phpBB/phpbb/hook/finder.php
@@ -18,8 +18,19 @@ namespace phpbb\hook;
*/
class finder
{
- protected $phpbb_root_path;
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
protected $cache;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
protected $php_ext;
/**
diff --git a/phpBB/phpbb/install/controller/archive_download.php b/phpBB/phpbb/install/controller/archive_download.php
new file mode 100644
index 0000000000..a0f0ba181d
--- /dev/null
+++ b/phpBB/phpbb/install/controller/archive_download.php
@@ -0,0 +1,93 @@
+<?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\install\controller;
+
+use phpbb\exception\http_exception;
+use phpbb\install\helper\config;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\ResponseHeaderBag;
+
+class archive_download
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ */
+ public function __construct(config $config)
+ {
+ $this->installer_config = $config;
+ $this->installer_config->load_config();
+ }
+
+ /**
+ * Sends response with the merge conflict archive
+ *
+ * Merge conflicts always have to be resolved manually,
+ * so we use a different archive for that.
+ *
+ * @return BinaryFileResponse
+ */
+ public function conflict_archive()
+ {
+ $filename = $this->installer_config->get('update_file_conflict_archive', false);
+
+ if (!$filename)
+ {
+ throw new http_exception(404, 'URL_NOT_FOUND');
+ }
+
+ return $this->send_response($filename);
+ }
+
+ /**
+ * Sends response with the updated files' archive
+ *
+ * @return BinaryFileResponse
+ */
+ public function update_archive()
+ {
+ $filename = $this->installer_config->get('update_file_archive', '');
+
+ if (!$filename)
+ {
+ throw new http_exception(404, 'URL_NOT_FOUND');
+ }
+
+ return $this->send_response($filename);
+ }
+
+ /**
+ * Generates a download response
+ *
+ * @param string $filename Path to the file to download
+ *
+ * @return BinaryFileResponse Response object
+ */
+ private function send_response($filename)
+ {
+ $response = new BinaryFileResponse($filename);
+ $response->setContentDisposition(
+ ResponseHeaderBag::DISPOSITION_ATTACHMENT,
+ basename($filename)
+ );
+
+ return $response;
+ }
+}
diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php
index fdfa6821ed..bfa9ec6238 100644
--- a/phpBB/phpbb/install/controller/helper.php
+++ b/phpBB/phpbb/install/controller/helper.php
@@ -13,6 +13,7 @@
namespace phpbb\install\controller;
+use phpbb\install\helper\config;
use phpbb\install\helper\navigation\navigation_provider;
use phpbb\language\language;
use phpbb\language\language_file_helper;
@@ -34,6 +35,11 @@ use Symfony\Component\HttpFoundation\Cookie;
class helper
{
/**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
* @var \phpbb\language\language
*/
protected $language;
@@ -91,6 +97,7 @@ class helper
/**
* Constructor
*
+ * @param config $config
* @param language $language
* @param language_file_helper $lang_helper
* @param navigation_provider $nav
@@ -101,8 +108,9 @@ class helper
* @param router $router
* @param string $phpbb_root_path
*/
- public function __construct(language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, request $phpbb_request, symfony_request $request, router $router, $phpbb_root_path)
+ public function __construct(config $config, language $language, language_file_helper $lang_helper, navigation_provider $nav, template $template, path_helper $path_helper, request $phpbb_request, symfony_request $request, router $router, $phpbb_root_path)
{
+ $this->installer_config = $config;
$this->language = $language;
$this->language_cookie = false;
$this->lang_helper = $lang_helper;
@@ -200,6 +208,47 @@ class helper
}
/**
+ * Process navigation data to reflect active/completed stages
+ *
+ * @param \phpbb\install\helper\iohandler\iohandler_interface|null $iohandler
+ */
+ public function handle_navigation($iohandler = null)
+ {
+ $nav_data = $this->installer_config->get_navigation_data();
+
+ // Set active navigation stage
+ if (isset($nav_data['active']) && is_array($nav_data['active']))
+ {
+ if ($iohandler !== null)
+ {
+ $iohandler->set_active_stage_menu($nav_data['active']);
+ }
+
+ $this->navigation_provider->set_nav_property($nav_data['active'], array(
+ 'selected' => true,
+ 'completed' => false,
+ ));
+ }
+
+ // Set finished navigation stages
+ if (isset($nav_data['finished']) && is_array($nav_data['finished']))
+ {
+ foreach ($nav_data['finished'] as $finished_stage)
+ {
+ if ($iohandler !== null)
+ {
+ $iohandler->set_finished_stage_menu($finished_stage);
+ }
+
+ $this->navigation_provider->set_nav_property($finished_stage, array(
+ 'selected' => false,
+ 'completed' => true,
+ ));
+ }
+ }
+ }
+
+ /**
* Set default template variables
*
* @param string $page_title Title of the page
@@ -207,27 +256,32 @@ class helper
*/
protected function page_header($page_title, $selected_language = false)
{
+ // Path to templates
+ $paths = array($this->phpbb_root_path . 'install/update/new/adm/', $this->phpbb_admin_path);
+ $paths = array_filter($paths, 'is_dir');
+ $path = array_shift($paths);
+ $path = substr($path, strlen($this->phpbb_root_path));
+
$this->template->assign_vars(array(
- 'L_CHANGE' => $this->language->lang('CHANGE'),
- 'L_COLON' => $this->language->lang('COLON'),
- 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'),
- 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'),
- 'L_SKIP' => $this->language->lang('SKIP'),
- 'PAGE_TITLE' => $this->language->lang($page_title),
- 'T_IMAGE_PATH' => htmlspecialchars($this->phpbb_admin_path) . 'images/',
- 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . 'assets/javascript/jquery.min.js',
- 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . 'adm/style',
- 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . 'assets/',
-
- 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'),
- 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right',
- 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left',
- 'S_CONTENT_ENCODING' => 'UTF-8',
- 'S_LANG_SELECT' => $selected_language,
-
- 'S_USER_LANG' => $this->language->lang('USER_LANG'),
- )
- );
+ 'L_CHANGE' => $this->language->lang('CHANGE'),
+ 'L_COLON' => $this->language->lang('COLON'),
+ 'L_INSTALL_PANEL' => $this->language->lang('INSTALL_PANEL'),
+ 'L_SELECT_LANG' => $this->language->lang('SELECT_LANG'),
+ 'L_SKIP' => $this->language->lang('SKIP'),
+ 'PAGE_TITLE' => $this->language->lang($page_title),
+ 'T_IMAGE_PATH' => $this->path_helper->get_web_root_path() . $path . 'images/',
+ 'T_JQUERY_LINK' => $this->path_helper->get_web_root_path() . $path . '../assets/javascript/jquery.min.js',
+ 'T_TEMPLATE_PATH' => $this->path_helper->get_web_root_path() . $path . 'style/',
+ 'T_ASSETS_PATH' => $this->path_helper->get_web_root_path() . $path . '../assets/',
+
+ 'S_CONTENT_DIRECTION' => $this->language->lang('DIRECTION'),
+ 'S_CONTENT_FLOW_BEGIN' => ($this->language->lang('DIRECTION') === 'ltr') ? 'left' : 'right',
+ 'S_CONTENT_FLOW_END' => ($this->language->lang('DIRECTION') === 'ltr') ? 'right' : 'left',
+ 'S_CONTENT_ENCODING' => 'UTF-8',
+ 'S_LANG_SELECT' => $selected_language,
+
+ 'S_USER_LANG' => $this->language->lang('USER_LANG'),
+ ));
$this->render_navigation();
}
diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php
index 80f6651a39..8d5ff95958 100644
--- a/phpBB/phpbb/install/controller/install.php
+++ b/phpBB/phpbb/install/controller/install.php
@@ -13,7 +13,6 @@
namespace phpbb\install\controller;
-use phpbb\install\helper\config;
use phpbb\install\helper\install_helper;
use phpbb\install\helper\navigation\navigation_provider;
use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -36,11 +35,6 @@ class install
protected $controller_helper;
/**
- * @var config
- */
- protected $installer_config;
-
- /**
* @var factory
*/
protected $iohandler_factory;
@@ -79,7 +73,6 @@ class install
* Constructor
*
* @param helper $helper
- * @param config $install_config
* @param factory $factory
* @param navigation_provider $nav_provider
* @param language $language
@@ -88,10 +81,9 @@ class install
* @param installer $installer
* @param install_helper $install_helper
*/
- public function __construct(helper $helper, config $install_config, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer, install_helper $install_helper)
+ public function __construct(helper $helper, factory $factory, navigation_provider $nav_provider, language $language, template $template, request_interface $request, installer $installer, install_helper $install_helper)
{
$this->controller_helper = $helper;
- $this->installer_config = $install_config;
$this->iohandler_factory = $factory;
$this->menu_provider = $nav_provider;
$this->language = $language;
@@ -130,34 +122,6 @@ class install
// Set the appropriate input-output handler
$this->installer->set_iohandler($this->iohandler_factory->get());
- // Set up navigation
- $nav_data = $this->installer_config->get_navigation_data();
- /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
- $iohandler = $this->iohandler_factory->get();
-
- // Set active navigation stage
- if (isset($nav_data['active']) && is_array($nav_data['active']))
- {
- $iohandler->set_active_stage_menu($nav_data['active']);
- $this->menu_provider->set_nav_property($nav_data['active'], array(
- 'selected' => true,
- 'completed' => false,
- ));
- }
-
- // Set finished navigation stages
- if (isset($nav_data['finished']) && is_array($nav_data['finished']))
- {
- foreach ($nav_data['finished'] as $finished_stage)
- {
- $iohandler->set_finished_stage_menu($finished_stage);
- $this->menu_provider->set_nav_property($finished_stage, array(
- 'selected' => false,
- 'completed' => true,
- ));
- }
- }
-
if ($this->request->is_ajax())
{
$installer = $this->installer;
@@ -193,6 +157,11 @@ class install
'TITLE' => $this->language->lang('INSTALL_INTRO'),
'CONTENT' => $this->language->lang('INSTALL_INTRO_BODY'),
));
+
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $this->controller_helper->handle_navigation($iohandler);
+
return $this->controller_helper->render('installer_install.html', 'INSTALL', true);
}
diff --git a/phpBB/phpbb/install/controller/update.php b/phpBB/phpbb/install/controller/update.php
new file mode 100644
index 0000000000..5212ba7f26
--- /dev/null
+++ b/phpBB/phpbb/install/controller/update.php
@@ -0,0 +1,162 @@
+<?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\install\controller;
+
+use phpbb\install\helper\install_helper;
+use phpbb\install\helper\iohandler\factory;
+use phpbb\install\helper\navigation\navigation_provider;
+use phpbb\install\installer;
+use phpbb\language\language;
+use phpbb\request\request_interface;
+use phpbb\template\template;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+
+/**
+ * Updater controller
+ */
+class update
+{
+ /**
+ * @var helper
+ */
+ protected $controller_helper;
+
+ /**
+ * @var installer
+ */
+ protected $installer;
+
+ /**
+ * @var install_helper
+ */
+ protected $install_helper;
+
+ /**
+ * @var factory
+ */
+ protected $iohandler_factory;
+
+ /**
+ * @var language
+ */
+ protected $language;
+
+ /**
+ * @var navigation_provider
+ */
+ protected $menu_provider;
+
+ /**
+ * @var request_interface
+ */
+ protected $request;
+
+ /**
+ * @var template
+ */
+ protected $template;
+
+ /**
+ * Constructor
+ *
+ * @param helper $controller_helper
+ * @param installer $installer
+ * @param install_helper $install_helper
+ * @param factory $iohandler
+ * @param language $language
+ * @param navigation_provider $menu_provider
+ * @param request_interface $request
+ * @param template $template
+ */
+ public function __construct(helper $controller_helper, installer $installer, install_helper $install_helper, factory $iohandler, language $language, navigation_provider $menu_provider, request_interface $request, template $template)
+ {
+ $this->controller_helper = $controller_helper;
+ $this->installer = $installer;
+ $this->install_helper = $install_helper;
+ $this->iohandler_factory = $iohandler;
+ $this->language = $language;
+ $this->menu_provider = $menu_provider;
+ $this->request = $request;
+ $this->template = $template;
+ }
+
+ /**
+ * Controller entry point
+ */
+ public function handle()
+ {
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ die ('phpBB is not installed');
+ }
+
+ $this->template->assign_vars(array(
+ 'U_ACTION' => $this->controller_helper->route('phpbb_installer_update'),
+ ));
+
+ // Set up input-output handler
+ if ($this->request->is_ajax())
+ {
+ $this->iohandler_factory->set_environment('ajax');
+ }
+ else
+ {
+ $this->iohandler_factory->set_environment('nojs');
+ }
+
+ // Set the appropriate input-output handler
+ $this->installer->set_iohandler($this->iohandler_factory->get());
+
+ // Render the intro page
+ if ($this->request->is_ajax())
+ {
+ $installer = $this->installer;
+ $response = new StreamedResponse();
+ $response->setCallback(function() use ($installer) {
+ $installer->run();
+ });
+
+ // Try to bypass any server output buffers
+ $response->headers->set('X-Accel-Buffering', 'no');
+ $response->headers->set('Content-type', 'application/json');
+
+ return $response;
+ }
+ else
+ {
+ $this->controller_helper->handle_language_select();
+
+ // Set active stage
+ $this->menu_provider->set_nav_property(
+ array('update', 0, 'introduction'),
+ array(
+ 'selected' => true,
+ 'completed' => false,
+ )
+ );
+
+ $this->template->assign_vars(array(
+ 'SHOW_INSTALL_START_FORM' => true,
+ 'TITLE' => $this->language->lang('UPDATE_INSTALLATION'),
+ 'CONTENT' => $this->language->lang('UPDATE_INSTALLATION_EXPLAIN'),
+ ));
+
+ /** @var \phpbb\install\helper\iohandler\iohandler_interface $iohandler */
+ $iohandler = $this->iohandler_factory->get();
+ $this->controller_helper->handle_navigation($iohandler);
+
+ return $this->controller_helper->render('installer_update.html', 'UPDATE_INSTALLATION', true);
+ }
+ }
+}
diff --git a/phpBB/phpbb/install/exception/file_updater_failure_exception.php b/phpBB/phpbb/install/exception/file_updater_failure_exception.php
new file mode 100644
index 0000000000..46ba2ed32d
--- /dev/null
+++ b/phpBB/phpbb/install/exception/file_updater_failure_exception.php
@@ -0,0 +1,22 @@
+<?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\install\exception;
+
+/**
+ * Thrown when the file updater fails
+ */
+class file_updater_failure_exception extends installer_exception
+{
+
+}
diff --git a/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php b/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php
new file mode 100644
index 0000000000..b628c4fbe3
--- /dev/null
+++ b/phpBB/phpbb/install/exception/jump_to_restart_point_exception.php
@@ -0,0 +1,44 @@
+<?php
+/**
+ *
+ * This file is part of the phpBB Forum Software package.
+ *
+ * @copyright (c) phpBB Limited <https://www.phpbb.com>
+ * @license GNU General Public License, version 2 (GPL-2.0)
+ *
+ * For full copyright and license information, please see
+ * the docs/CREDITS.txt file.
+ *
+ */
+
+namespace phpbb\install\exception;
+
+class jump_to_restart_point_exception extends installer_exception
+{
+ /**
+ * @var string
+ */
+ protected $restart_point_name;
+
+ /**
+ * Constructor
+ *
+ * @param string $restart_point_name
+ */
+ public function __construct($restart_point_name)
+ {
+ $this->restart_point_name = $restart_point_name;
+
+ parent::__construct();
+ }
+
+ /**
+ * Returns the restart point's name
+ *
+ * @return string
+ */
+ public function get_restart_point_name()
+ {
+ return $this->restart_point_name;
+ }
+}
diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php
index d5653f1924..0f0840f470 100644
--- a/phpBB/phpbb/install/helper/config.php
+++ b/phpBB/phpbb/install/helper/config.php
@@ -99,6 +99,8 @@ class config
'last_task_name' => '', // Stores the service name of the latest finished task
'max_task_progress' => 0,
'current_task_progress' => 0,
+ '_restart_points' => array(),
+ 'use_restart_point' => false,
);
$this->install_config_file = $this->phpbb_root_path . 'store/install_config.php';
@@ -240,6 +242,56 @@ class config
}
/**
+ * Creates a progress restart point
+ *
+ * Restart points can be used to repeat certain tasks periodically.
+ * You need to call this method from the first task you want to repeat.
+ *
+ * @param string $name Name of the restart point
+ */
+ public function create_progress_restart_point($name)
+ {
+ $tmp_progress_data = $this->progress_data;
+ unset($tmp_progress_data['_restart_points']);
+
+ $this->progress_data['_restart_points'][$name] = $tmp_progress_data;
+ }
+
+ /**
+ * Set restart point to continue from
+ *
+ * @param string $name Name of the restart point
+ *
+ * @return bool Returns false if the restart point name does not exist, otherwise true
+ */
+ public function jump_to_restart_point($name)
+ {
+ if (!isset($this->progress_data['_restart_points'][$name]) || empty($this->progress_data['_restart_points'][$name]))
+ {
+ return false;
+ }
+
+ foreach ($this->progress_data['_restart_points'][$name] as $key => $value)
+ {
+ $this->progress_data[$key] = $value;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns whether a restart point with a given name exists or not
+ *
+ * @param string $name Name of the restart point
+ *
+ * @return bool
+ */
+ public function has_restart_point($name)
+ {
+ return isset($this->progress_data['_restart_points'][$name]);
+ }
+
+ /**
* Dumps install configuration to disk
*/
public function save_config()
diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php
index dc0eef6485..6c1ecd2d02 100644
--- a/phpBB/phpbb/install/helper/container_factory.php
+++ b/phpBB/phpbb/install/helper/container_factory.php
@@ -15,10 +15,17 @@ namespace phpbb\install\helper;
use phpbb\cache\driver\dummy;
use phpbb\install\exception\cannot_build_container_exception;
+use phpbb\language\language;
+use phpbb\request\request;
class container_factory
{
/**
+ * @var language
+ */
+ protected $language;
+
+ /**
* @var string
*/
protected $phpbb_root_path;
@@ -34,6 +41,11 @@ class container_factory
protected $request;
/**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
* The full phpBB container
*
* @var \Symfony\Component\DependencyInjection\ContainerInterface
@@ -43,13 +55,17 @@ class container_factory
/**
* Constructor
*
- * @param \phpbb\request\request $request Request interface
- * @param string $phpbb_root_path Path to phpBB's root
- * @param string $php_ext Extension of PHP files
+ * @param language $language Language service
+ * @param request $request Request interface
+ * @param update_helper $update_helper Update helper
+ * @param string $phpbb_root_path Path to phpBB's root
+ * @param string $php_ext Extension of PHP files
*/
- public function __construct(\phpbb\request\request $request, $phpbb_root_path, $php_ext)
+ public function __construct(language $language, request $request, update_helper $update_helper, $phpbb_root_path, $php_ext)
{
+ $this->language = $language;
$this->request = $request;
+ $this->update_helper = $update_helper;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->container = null;
@@ -124,7 +140,7 @@ class container_factory
$phpbb_container_builder = new \phpbb\di\container_builder($this->phpbb_root_path, $this->php_ext);
// For BC with functions that we need during install
- global $phpbb_container;
+ global $phpbb_container, $table_prefix;
$disable_super_globals = $this->request->super_globals_disabled();
@@ -134,8 +150,13 @@ class container_factory
$this->request->enable_super_globals();
}
- $this->container = $phpbb_container = $phpbb_container_builder
+ $other_config_path = $this->phpbb_root_path . 'install/update/new/config';
+ $config_path = (is_dir($other_config_path)) ? $other_config_path : $this->phpbb_root_path . 'config';
+
+ $this->container = $phpbb_container_builder
+ ->with_environment('production')
->with_config($phpbb_config_php_file)
+ ->with_config_path($config_path)
->without_cache()
->without_compiled_container()
->get_container();
@@ -145,18 +166,29 @@ class container_factory
$this->container->register('request')->setSynthetic(true);
$this->container->set('request', $this->request);
- // Replace cache service, as config gets cached, and we don't want that
- $this->container->register('cache.driver')->setSynthetic(true);
- $this->container->set('cache.driver', new dummy());
+ $this->container->register('language')->setSynthetic(true);
+ $this->container->set('language', $this->language);
+
+ // Replace cache service, as config gets cached, and we don't want that when we are installing
+ if (!is_dir($other_config_path))
+ {
+ $this->container->register('cache.driver')->setSynthetic(true);
+ $this->container->set('cache.driver', new dummy());
+ }
+
$this->container->compile();
+ $phpbb_container = $this->container;
+ $table_prefix = $phpbb_config_php_file->get('table_prefix');
+
// Restore super globals to previous state
if ($disable_super_globals)
{
$this->request->disable_super_globals();
}
- // Get compatibilty globals
- require ($this->phpbb_root_path . 'includes/compatibility_globals.' . $this->php_ext);
+ // Get compatibilty globals and constants
+ $this->update_helper->include_file('includes/compatibility_globals.' . $this->php_ext);
+ $this->update_helper->include_file('includes/constants.' . $this->php_ext);
}
}
diff --git a/phpBB/phpbb/install/helper/database.php b/phpBB/phpbb/install/helper/database.php
index 627e9ea9b0..c4c90a01a4 100644
--- a/phpBB/phpbb/install/helper/database.php
+++ b/phpBB/phpbb/install/helper/database.php
@@ -338,7 +338,7 @@ class database
$db->sql_return_on_error(true);
// Check that we actually have a database name before going any further
- if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle')) && $dbname === '')
+ if (!in_array($dbms_info['SCHEMA'], array('sqlite', 'oracle'), true) && $dbname === '')
{
$errors[] = array(
'title' => 'INST_ERR_DB_NO_NAME',
diff --git a/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php b/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php
new file mode 100644
index 0000000000..ede992fb6e
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/compression_file_updater.php
@@ -0,0 +1,133 @@
+<?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\install\helper\file_updater;
+
+use phpbb\install\helper\update_helper;
+
+/**
+ * File updater for generating archive with updated files
+ */
+class compression_file_updater implements file_updater_interface
+{
+ /**
+ * @var \compress
+ */
+ protected $compress;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->compress = null;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Set the compression method
+ *
+ * @param string $method Compression method's file extension
+ *
+ * @return string Archive's filename
+ */
+ public function init($method)
+ {
+ $this->update_helper->include_file('includes/functions_compress.' . $this->php_ext);
+
+ $archive_filename = 'update_archive_' . time() . '_' . uniqid();
+ $path = $this->phpbb_root_path . 'store/' . $archive_filename . '' . $method;
+
+ if ($method === '.zip')
+ {
+ $this->compress = new \compress_zip('w', $path);
+ }
+ else
+ {
+ $this->compress = new \compress_tar('w', $path, $method);
+ }
+
+ return $path;
+ }
+
+ /**
+ * Close archive writing process
+ */
+ public function close()
+ {
+ $this->compress->close();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_file($path_to_file)
+ {
+ // We do absolutely nothing here, as this function is called when a file should be
+ // removed from the filesystem, but since this is an archive generator, it clearly
+ // cannot do that.
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ if ($create_from_content)
+ {
+ $this->compress->add_data($source, $path_to_file_to_create);
+ }
+ else
+ {
+ $this->compress->add_custom_file($source, $path_to_file_to_create);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ // Both functions are identical here
+ $this->create_new_file($path_to_file_to_update, $source, $create_from_content);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'compression';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/factory.php b/phpBB/phpbb/install/helper/file_updater/factory.php
new file mode 100644
index 0000000000..d3a2f22782
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/factory.php
@@ -0,0 +1,69 @@
+<?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\install\helper\file_updater;
+
+use phpbb\di\service_collection;
+use phpbb\install\exception\file_updater_failure_exception;
+
+/**
+ * File updater factory
+ */
+class factory
+{
+ /**
+ * @var array
+ */
+ protected $file_updaters;
+
+ /**
+ * Constructor
+ *
+ * @param service_collection $collection File updater service collection
+ */
+ public function __construct(service_collection $collection)
+ {
+ foreach ($collection as $service)
+ {
+ $this->register($service);
+ }
+ }
+
+ /**
+ * Register updater object
+ *
+ * @param file_updater_interface $updater Updater object
+ */
+ public function register(file_updater_interface $updater)
+ {
+ $name = $updater->get_method_name();
+ $this->file_updaters[$name] = $updater;
+ }
+
+ /**
+ * Returns file updater object
+ *
+ * @param string $name Name of the updater method
+ *
+ * @throws file_updater_failure_exception When the specified file updater does not exist
+ */
+ public function get($name)
+ {
+ if (!isset($this->file_updaters[$name]))
+ {
+ throw new file_updater_failure_exception();
+ }
+
+ return $this->file_updaters[$name];
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/file_updater.php b/phpBB/phpbb/install/helper/file_updater/file_updater.php
new file mode 100644
index 0000000000..cc0f5c6b5f
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/file_updater.php
@@ -0,0 +1,202 @@
+<?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\install\helper\file_updater;
+
+use phpbb\filesystem\exception\filesystem_exception;
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\file_updater_failure_exception;
+
+/**
+ * File updater for direct filesystem access
+ */
+class file_updater implements file_updater_interface
+{
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param filesystem $filesystem
+ * @param string $phpbb_root_path
+ */
+ public function __construct(filesystem $filesystem, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function delete_file($path_to_file)
+ {
+ $this->filesystem->remove($this->phpbb_root_path . $path_to_file);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ $path_to_file_to_create = $this->phpbb_root_path . $path_to_file_to_create;
+
+ $dir = dirname($path_to_file_to_create);
+ if (!$this->filesystem->exists($dir))
+ {
+ $this->make_dir($dir);
+ }
+
+ $original_dir_perms = false;
+
+ if (!$this->filesystem->is_writable($dir))
+ {
+ // Extract last 9 bits we actually need
+ $original_dir_perms = @fileperms($dir) & 511;
+ $this->filesystem->phpbb_chmod($dir, filesystem::CHMOD_ALL);
+ }
+
+ if (!$create_from_content)
+ {
+ try
+ {
+ $this->filesystem->copy($source, $path_to_file_to_create);
+ }
+ catch (filesystem_exception $e)
+ {
+ $this->write_file($path_to_file_to_create, $source, $create_from_content);
+ }
+ }
+ else
+ {
+ $this->write_file($path_to_file_to_create, $source, $create_from_content);
+ }
+
+ if ($original_dir_perms !== false)
+ {
+ $this->filesystem->phpbb_chmod($dir, $original_dir_perms);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ * @throws filesystem_exception When the filesystem class fails
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ $path_to_file_to_update = $this->phpbb_root_path . $path_to_file_to_update;
+ $original_file_perms = false;
+
+ // Maybe necessary for binary files
+ $dir = dirname($path_to_file_to_update);
+ if (!$this->filesystem->exists($dir))
+ {
+ $this->make_dir($dir);
+ }
+
+ if (!$this->filesystem->is_writable($path_to_file_to_update))
+ {
+ // Extract last 9 bits we actually need
+ $original_file_perms = @fileperms($path_to_file_to_update) & 511;
+ $this->filesystem->phpbb_chmod($path_to_file_to_update, filesystem::CHMOD_WRITE);
+ }
+
+ if (!$create_from_content)
+ {
+ try
+ {
+ $this->filesystem->copy($source, $path_to_file_to_update, true);
+ }
+ catch (filesystem_exception $e)
+ {
+ $this->write_file($path_to_file_to_update, $source, $create_from_content);
+ }
+ }
+ else
+ {
+ $this->write_file($path_to_file_to_update, $source, $create_from_content);
+ }
+
+ if ($original_file_perms !== false)
+ {
+ $this->filesystem->phpbb_chmod($path_to_file_to_update, $original_file_perms);
+ }
+ }
+
+ /**
+ * Creates directory structure
+ *
+ * @param string $path Path to the directory where the file should be placed (and non-existent)
+ */
+ private function make_dir($path)
+ {
+ if (is_dir($path))
+ {
+ return;
+ }
+
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ $this->filesystem->mkdir($path, 493); // 493 === 0755
+ }
+
+ /**
+ * Fallback function for file writing
+ *
+ * @param string $path_to_file Path to the file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool|false $create_from_content Whether or not to use $source as the content, false by default
+ *
+ * @throws file_updater_failure_exception When the file is not writable
+ */
+ private function write_file($path_to_file, $source, $create_from_content = false)
+ {
+ if (!$create_from_content)
+ {
+ $source = @file_get_contents($source);
+ }
+
+ $file_pointer = @fopen($path_to_file, 'w');
+
+ if (!is_resource($file_pointer))
+ {
+ throw new file_updater_failure_exception();
+ }
+
+ @fwrite($file_pointer, $source);
+ @fclose($file_pointer);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'direct_file';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/file_updater_interface.php b/phpBB/phpbb/install/helper/file_updater/file_updater_interface.php
new file mode 100644
index 0000000000..b13d7c9fe1
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/file_updater_interface.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\install\helper\file_updater;
+
+interface file_updater_interface
+{
+ /**
+ * Deletes a file
+ *
+ * @param string $path_to_file Path to the file to delete
+ */
+ public function delete_file($path_to_file);
+
+ /**
+ * Creates a new file
+ *
+ * @param string $path_to_file_to_create Path to the new file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool $create_from_content Whether or not to use $source as the content, false by default
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false);
+
+ /**
+ * Update file
+ *
+ * @param string $path_to_file_to_update Path to the file's location
+ * @param string $source Path to file to copy or string with the new file's content
+ * @param bool $create_from_content Whether or not to use $source as the content, false by default
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false);
+
+ /**
+ * Returns the name of the file updater method
+ *
+ * @return string
+ */
+ public function get_method_name();
+}
diff --git a/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php
new file mode 100644
index 0000000000..258a035768
--- /dev/null
+++ b/phpBB/phpbb/install/helper/file_updater/ftp_file_updater.php
@@ -0,0 +1,136 @@
+<?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\install\helper\file_updater;
+
+use phpbb\install\helper\update_helper;
+
+/**
+ * File updater for FTP updates
+ */
+class ftp_file_updater implements file_updater_interface
+{
+ /**
+ * @var \transfer
+ */
+ protected $transfer;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __constructor(update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->transfer = null;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * Initialize FTP connection
+ *
+ * @param string $method
+ * @param string $host
+ * @param string $user
+ * @param string $pass
+ * @param string $path
+ * @param int $port
+ * @param int $timeout
+ */
+ public function init($method, $host, $user, $pass, $path, $port, $timeout)
+ {
+ $this->update_helper->include_file('includes/functions_transfer.' . $this->php_ext);
+ $this->transfer = new $method($host, $user, $pass, $path, $port, $timeout);
+ $this->transfer->open_session();
+ }
+
+ /**
+ * Close FTP session
+ */
+ public function close()
+ {
+ $this->transfer->close_session();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete_file($path_to_file)
+ {
+ $this->transfer->delete_file($path_to_file);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function create_new_file($path_to_file_to_create, $source, $create_from_content = false)
+ {
+ $dirname = dirname($path_to_file_to_create);
+
+ if ($dirname && !file_exists($this->phpbb_root_path . $dirname))
+ {
+ $this->transfer->make_dir($dirname);
+ }
+
+ if ($create_from_content)
+ {
+ $this->transfer->write_file($path_to_file_to_create, $source);
+ }
+ else
+ {
+ $this->transfer->copy_file($path_to_file_to_create, $source);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update_file($path_to_file_to_update, $source, $create_from_content = false)
+ {
+ if ($create_from_content)
+ {
+ $this->transfer->write_file($path_to_file_to_update, $source);
+ }
+ else
+ {
+ $this->transfer->copy_file($path_to_file_to_update, $source);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_method_name()
+ {
+ return 'ftp';
+ }
+}
diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php
index fa628f3365..1342ffa30f 100644
--- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php
+++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php
@@ -13,12 +13,20 @@
namespace phpbb\install\helper\iohandler;
+use phpbb\path_helper;
+use phpbb\routing\router;
+
/**
* Input-Output handler for the AJAX frontend
*/
class ajax_iohandler extends iohandler_base
{
/**
+ * @var path_helper
+ */
+ protected $path_helper;
+
+ /**
* @var \phpbb\request\request_interface
*/
protected $request;
@@ -29,6 +37,16 @@ class ajax_iohandler extends iohandler_base
protected $template;
/**
+ * @var router
+ */
+ protected $router;
+
+ /**
+ * @var string
+ */
+ protected $file_status;
+
+ /**
* @var string
*/
protected $form;
@@ -49,18 +67,29 @@ class ajax_iohandler extends iohandler_base
protected $cookies;
/**
+ * @var array
+ */
+ protected $download;
+
+ /**
* Constructor
*
+ * @param path_helper $path_helper
* @param \phpbb\request\request_interface $request HTTP request interface
* @param \phpbb\template\template $template Template engine
+ * @param router $router Router
*/
- public function __construct(\phpbb\request\request_interface $request, \phpbb\template\template $template)
+ public function __construct(path_helper $path_helper, \phpbb\request\request_interface $request, \phpbb\template\template $template, router $router)
{
+ $this->path_helper = $path_helper;
$this->request = $request;
+ $this->router = $router;
$this->template = $template;
$this->form = '';
$this->nav_data = array();
$this->cookies = array();
+ $this->download = array();
+ $this->file_status = '';
parent::__construct();
}
@@ -102,13 +131,13 @@ class ajax_iohandler extends iohandler_base
*/
public function add_user_form_group($title, $form)
{
- $this->template->assign_var('S_FORM_ELEM_COUNT', sizeof($form));
-
$this->template->assign_block_vars('options', array(
'LEGEND' => $this->language->lang($title),
'S_LEGEND' => true,
));
+ $not_button_form = false;
+
foreach ($form as $input_name => $input_options)
{
if (!isset($input_options['type']))
@@ -117,6 +146,7 @@ class ajax_iohandler extends iohandler_base
}
$tpl_ary = array();
+ $not_button_form = ($input_options['type'] !== 'submit' || $not_button_form);
$tpl_ary['TYPE'] = $input_options['type'];
$tpl_ary['TITLE'] = $this->language->lang($input_options['label']);
@@ -136,7 +166,7 @@ class ajax_iohandler extends iohandler_base
$tpl_ary['S_EXPLAIN'] = true;
}
- if (in_array($input_options['type'], array('select', 'radio')))
+ if (in_array($input_options['type'], array('select', 'radio'), true))
{
for ($i = 0, $total = sizeof($input_options['options']); $i < $total; $i++)
{
@@ -149,9 +179,12 @@ class ajax_iohandler extends iohandler_base
$tpl_ary['OPTIONS'] = $input_options['options'];
}
- $this->template->assign_block_vars('options', $tpl_ary);
+ $block_name = ($input_options['type'] === 'submit') ? 'submit_buttons' : 'options';
+ $this->template->assign_block_vars($block_name, $tpl_ary);
}
+ $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form);
+
$this->template->set_filenames(array(
'form_install' => 'installer_form.html',
));
@@ -185,14 +218,27 @@ class ajax_iohandler extends iohandler_base
'warnings' => $this->warnings,
'logs' => $this->logs,
'success' => $this->success,
+ 'download' => $this->download,
);
+ $this->errors = array();
+ $this->warnings = array();
+ $this->logs = array();
+ $this->success = array();
+ $this->download = array();
+
if (!empty($this->form))
{
$json_array['form'] = $this->form;
$this->form = '';
}
+ if (!empty($this->file_status))
+ {
+ $json_array['file_status'] = $this->file_status;
+ $this->file_status = '';
+ }
+
// If current task name is set, we push progress message to the client side
if (!empty($this->current_task_name))
{
@@ -201,19 +247,20 @@ class ajax_iohandler extends iohandler_base
'task_num' => $this->current_task_progress,
'task_count' => $this->task_progress_count,
);
+
+ if ($this->restart_progress_bar)
+ {
+ $json_array['progress']['restart'] = 1;
+ $this->restart_progress_bar = false;
+ }
}
if (!empty($this->nav_data))
{
$json_array['nav'] = $this->nav_data;
+ $this->nav_data = array();
}
- $this->errors = array();
- $this->warnings = array();
- $this->logs = array();
- $this->success = array();
- $this->nav_data = array();
-
if ($this->request_client_refresh)
{
$json_array['refresh'] = true;
@@ -276,6 +323,56 @@ class ajax_iohandler extends iohandler_base
}
/**
+ * {@inheritdoc}
+ */
+ public function add_download_link($route, $title, $msg = null)
+ {
+ $link_properties = array(
+ 'href' => $this->router->generate($route),
+ 'title' => $this->language->lang($title),
+ 'download' => $this->language->lang('DOWNLOAD'),
+ );
+
+ if ($msg !== null)
+ {
+ $link_properties['msg'] = htmlspecialchars_decode($this->language->lang($msg));
+ }
+
+ $this->download[] = $link_properties;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render_update_file_status($status_array)
+ {
+ $this->template->assign_vars(array(
+ 'T_IMAGE_PATH' => $this->path_helper->get_web_root_path() . 'adm/images/',
+ ));
+
+ foreach ($status_array as $block => $list)
+ {
+ foreach ($list as $filename)
+ {
+ $dirname = dirname($filename);
+
+ $this->template->assign_block_vars($block, array(
+ 'STATUS' => $block,
+ 'FILENAME' => $filename,
+ 'DIR_PART' => (!empty($dirname) && $dirname !== '.') ? dirname($filename) . '/' : false,
+ 'FILE_PART' => basename($filename),
+ ));
+ }
+ }
+
+ $this->template->set_filenames(array(
+ 'file_status' => 'installer_update_file_status.html',
+ ));
+
+ $this->file_status = $this->template->assign_display('file_status');
+ }
+
+ /**
* Callback function for language replacing
*
* @param array $matches
diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php
index c5b2bb06bc..abdd730d2e 100644
--- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php
+++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php
@@ -181,9 +181,12 @@ class cli_iohandler extends iohandler_base
}
}
- public function set_task_count($task_count)
+ /**
+ * {@inheritdoc}
+ */
+ public function set_task_count($task_count, $restart = false)
{
- parent::set_task_count($task_count);
+ parent::set_task_count($task_count, $restart);
if ($this->output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL)
{
@@ -206,6 +209,9 @@ class cli_iohandler extends iohandler_base
}
}
+ /**
+ * {@inheritdoc}
+ */
public function set_progress($task_lang_key, $task_number)
{
parent::set_progress($task_lang_key, $task_number);
@@ -262,4 +268,18 @@ class cli_iohandler extends iohandler_base
public function set_cookie($cookie_name, $cookie_value)
{
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add_download_link($route, $title, $msg = null)
+ {
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render_update_file_status($status_array)
+ {
+ }
}
diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php
index 006411f1e3..530cb4766b 100644
--- a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php
+++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php
@@ -80,6 +80,7 @@ abstract class iohandler_base implements iohandler_interface
$this->logs = array();
$this->success = array();
+ $this->restart_progress_bar = false;
$this->task_progress_count = 0;
$this->current_task_progress = 0;
$this->current_task_name = '';
@@ -130,9 +131,10 @@ abstract class iohandler_base implements iohandler_interface
/**
* {@inheritdoc}
*/
- public function set_task_count($task_count)
+ public function set_task_count($task_count, $restart = false)
{
$this->task_progress_count = $task_count;
+ $this->restart_progress_bar = $restart;
}
/**
diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php
index 5f5f8499d6..00aab3283e 100644
--- a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php
+++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php
@@ -127,8 +127,9 @@ interface iohandler_interface
* Sets the number of tasks belonging to the installer in the current mode.
*
* @param int $task_count Number of tasks
+ * @param bool $restart Whether or not to restart the progress bar, false by default
*/
- public function set_task_count($task_count);
+ public function set_task_count($task_count, $restart = false);
/**
* Sets the progress information
@@ -165,6 +166,22 @@ interface iohandler_interface
public function finish_progress($message_lang_key);
/**
+ * Adds a download link
+ *
+ * @param string $route Route for the link
+ * @param string $title Language key for the title
+ * @param string|null|array $msg Language key for the message
+ */
+ public function add_download_link($route, $title, $msg = null);
+
+ /**
+ * Renders the status of update files
+ *
+ * @param array $status_array Array containing files in groups to render
+ */
+ public function render_update_file_status($status_array);
+
+ /**
* Sends and sets cookies
*
* @param string $cookie_name Name of the cookie to set
diff --git a/phpBB/phpbb/install/helper/navigation/update_navigation.php b/phpBB/phpbb/install/helper/navigation/update_navigation.php
new file mode 100644
index 0000000000..3d239c3451
--- /dev/null
+++ b/phpBB/phpbb/install/helper/navigation/update_navigation.php
@@ -0,0 +1,80 @@
+<?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\install\helper\navigation;
+
+use phpbb\install\helper\install_helper;
+
+class update_navigation implements navigation_interface
+{
+ /**
+ * @var install_helper
+ */
+ private $install_helper;
+
+ /**
+ * Constructor
+ *
+ * @param install_helper $install_helper
+ */
+ public function __construct(install_helper $install_helper)
+ {
+ $this->install_helper = $install_helper;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get()
+ {
+ if (!$this->install_helper->is_phpbb_installed())
+ {
+ return array();
+ }
+
+ return array(
+ 'update' => array(
+ 'label' => 'UPDATE',
+ 'route' => 'phpbb_installer_update',
+ 'order' => 1,
+ array(
+ 'introduction' => array(
+ 'label' => 'INTRODUCTION_TITLE',
+ 'stage' => true,
+ 'order' => 0,
+ ),
+ 'requirements' => array(
+ 'label' => 'STAGE_REQUIREMENTS',
+ 'stage' => true,
+ 'order' => 1,
+ ),
+ 'obtain_data' => array(
+ 'label' => 'STAGE_OBTAIN_DATA',
+ 'stage' => true,
+ 'order' => 2,
+ ),
+ 'update_files' => array(
+ 'label' => 'STAGE_UPDATE_FILES',
+ 'stage' => true,
+ 'order' => 3,
+ ),
+ 'update_database' => array(
+ 'label' => 'STAGE_UPDATE_DATABASE',
+ 'stage' => true,
+ 'order' => 4,
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/phpBB/phpbb/install/helper/update_helper.php b/phpBB/phpbb/install/helper/update_helper.php
new file mode 100644
index 0000000000..a00731d317
--- /dev/null
+++ b/phpBB/phpbb/install/helper/update_helper.php
@@ -0,0 +1,113 @@
+<?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\install\helper;
+
+/**
+ * General helper functionality for the updater
+ */
+class update_helper
+{
+ /**
+ * @var string
+ */
+ protected $path_to_new_files;
+
+ /**
+ * @var string
+ */
+ protected $path_to_old_files;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param string $phpbb_root_path
+ */
+ public function __construct($phpbb_root_path)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->path_to_new_files = $phpbb_root_path . 'install/update/new/';
+ $this->path_to_old_files = $phpbb_root_path . 'install/update/old/';
+ }
+
+ /**
+ * Returns path to new update files
+ *
+ * @return string
+ */
+ public function get_path_to_new_update_files()
+ {
+ return $this->path_to_new_files;
+ }
+
+ /**
+ * Returns path to new update files
+ *
+ * @return string
+ */
+ public function get_path_to_old_update_files()
+ {
+ return $this->path_to_old_files;
+ }
+
+ /**
+ * Includes the updated file if available
+ *
+ * @param string $filename Path to the file relative to phpBB root path
+ */
+ public function include_file($filename)
+ {
+ if (is_file($this->path_to_new_files . $filename))
+ {
+ include_once($this->path_to_new_files . $filename);
+ }
+ else if (is_file($this->phpbb_root_path . $filename))
+ {
+ include_once($this->phpbb_root_path . $filename);
+ }
+ }
+
+ /**
+ * Customized version_compare()
+ *
+ * @param string $version_number1
+ * @param string $version_number2
+ * @param string|null $operator
+ * @return int|bool The returned value is identical to the PHP build-in function version_compare()
+ */
+ public function phpbb_version_compare($version_number1, $version_number2, $operator = null)
+ {
+ if ($operator === null)
+ {
+ $result = version_compare(
+ str_replace('rc', 'RC', strtolower($version_number1)),
+ str_replace('rc', 'RC', strtolower($version_number2))
+ );
+ }
+ else
+ {
+ $result = version_compare(
+ str_replace('rc', 'RC', strtolower($version_number1)),
+ str_replace('rc', 'RC', strtolower($version_number2)),
+ $operator
+ );
+ }
+
+ return $result;
+ }
+}
diff --git a/phpBB/phpbb/install/installer.php b/phpBB/phpbb/install/installer.php
index 755edb5297..77e0a896bc 100644
--- a/phpBB/phpbb/install/installer.php
+++ b/phpBB/phpbb/install/installer.php
@@ -15,11 +15,13 @@ namespace phpbb\install;
use phpbb\di\ordered_service_collection;
use phpbb\install\exception\installer_config_not_writable_exception;
+use phpbb\install\exception\jump_to_restart_point_exception;
use phpbb\install\exception\resource_limit_reached_exception;
use phpbb\install\exception\user_interaction_required_exception;
use phpbb\install\helper\config;
use phpbb\install\helper\iohandler\cli_iohandler;
use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\path_helper;
class installer
{
@@ -39,6 +41,11 @@ class installer
protected $iohandler;
/**
+ * @var string
+ */
+ protected $web_root;
+
+ /**
* Stores the number of steps that a given module has
*
* @var array
@@ -48,12 +55,14 @@ class installer
/**
* Constructor
*
- * @param config $config Installer config handler
+ * @param config $config Installer config handler
+ * @param path_helper $path_helper Path helper
*/
- public function __construct(config $config)
+ public function __construct(config $config, path_helper $path_helper)
{
$this->install_config = $config;
$this->installer_modules = null;
+ $this->web_root = $path_helper->get_web_root_path();
}
/**
@@ -94,6 +103,7 @@ class installer
// Variable used to check if the install process have been finished
$install_finished = false;
$fail_cleanup = false;
+ $send_refresh = false;
// We are installing something, so the introduction stage can go now...
$this->install_config->set_finished_navigation_stage(array('install', 0, 'introduction'));
@@ -142,7 +152,7 @@ class installer
$this->install_config->set_active_module($name);
// Run until there are available resources
- if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0)
+ if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
{
throw new resource_limit_reached_exception();
}
@@ -181,21 +191,7 @@ class installer
else
{
global $SID;
-
- // Construct ACP url
- $acp_url = $protocol = $this->install_config->get('server_protocol');
- $acp_url .= $this->install_config->get('server_name');
- $port = $this->install_config->get('server_port');
-
- if (!((strpos($protocol, 'https:') === 0 && $port === 443)
- || (strpos($protocol, 'http:') === 0 && $port === 80)))
- {
- $acp_url .= ':' . $port;
- }
-
- $acp_url .= $this->install_config->get('script_path');
- $acp_url .= '/adm/index.php' . $SID;
-
+ $acp_url = $this->web_root . 'adm/index.php' . $SID;
$this->iohandler->add_success_message('INSTALLER_FINISHED', array(
'ACP_LINK',
$acp_url,
@@ -208,7 +204,12 @@ class installer
}
catch (resource_limit_reached_exception $e)
{
- // Do nothing
+ $send_refresh = true;
+ }
+ catch (jump_to_restart_point_exception $e)
+ {
+ $this->install_config->jump_to_restart_point($e->get_restart_point_name());
+ $send_refresh = true;
}
catch (\Exception $e)
{
@@ -222,9 +223,10 @@ class installer
// Send install finished message
$this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count());
}
- else if (!$fail_cleanup)
+ else if ($send_refresh)
{
$this->iohandler->request_refresh();
+ $this->iohandler->send_response();
}
// Save install progress
diff --git a/phpBB/phpbb/install/module/obtain_data/module.php b/phpBB/phpbb/install/module/obtain_data/install_module.php
index 0e008796c5..deb4be90d8 100644
--- a/phpBB/phpbb/install/module/obtain_data/module.php
+++ b/phpBB/phpbb/install/module/obtain_data/install_module.php
@@ -13,7 +13,7 @@
namespace phpbb\install\module\obtain_data;
-class module extends \phpbb\install\module_base
+class install_module extends \phpbb\install\module_base
{
/**
* {@inheritdoc}
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
index b2250e524b..41616e995a 100644
--- a/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php
@@ -155,7 +155,7 @@ class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\insta
$data_valid = true;
// Check if none of admin data is empty
- if (in_array('', array($username, $pass1, $pass2, $email)))
+ if (in_array('', array($username, $pass1, $pass2, $email), true))
{
$this->io_handler->add_error_message('INST_ERR_MISSING_DATA');
$data_valid = false;
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
index 821c221123..0726cc449c 100644
--- a/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php
@@ -165,7 +165,7 @@ class obtain_board_data extends \phpbb\install\task_base implements \phpbb\insta
$this->io_handler->add_user_form_group('BOARD_CONFIG', $board_form);
$this->io_handler->send_response();
- throw new user_interaction_required_exception;
+ throw new user_interaction_required_exception();
}
/**
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php
new file mode 100644
index 0000000000..9bcb73a6a9
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_file_updater_method.php
@@ -0,0 +1,168 @@
+<?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\install\module\obtain_data\task;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_file_updater_method extends task_base
+{
+ /**
+ * @var array Supported compression methods
+ *
+ * Note: .tar is assumed to be supported, but not in the list
+ */
+ protected $available_methods;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+
+ $this->available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->iohandler->get_input('submit_update_file', false))
+ {
+ $supported_methods = array('compression', 'ftp', 'direct_file');
+ $method = $this->iohandler->get_input('method', 'compression');
+ $update_method = (in_array($method, $supported_methods, true)) ? $method : 'compression';
+ $this->installer_config->set('file_update_method', $update_method);
+
+ $compression = $this->iohandler->get_input('compression_method', '.zip');
+ $supported_methods = array_keys($this->available_methods);
+ $supported_methods[] = '.tar';
+ $compression = (in_array($compression, $supported_methods, true)) ? $compression : '.zip';
+ $this->installer_config->set('file_update_compression', $compression);
+ }
+ else
+ {
+ $this->iohandler->add_user_form_group('UPDATE_FILE_METHOD_TITLE', array(
+ 'method' => array(
+ 'label' => 'UPDATE_FILE_METHOD',
+ 'type' => 'select',
+ 'options' => array(
+ array(
+ 'value' => 'compression',
+ 'label' => 'UPDATE_FILE_METHOD_DOWNLOAD',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 'ftp',
+ 'label' => 'UPDATE_FILE_METHOD_FTP',
+ 'selected' => false,
+ ),
+ array(
+ 'value' => 'direct_file',
+ 'label' => 'UPDATE_FILE_METHOD_FILESYSTEM',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'compression_method' => array(
+ 'label' => 'SELECT_DOWNLOAD_FORMAT',
+ 'type' => 'select',
+ 'options' => $this->get_available_compression_methods(),
+ ),
+ 'submit_update_file' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ $this->iohandler->send_response();
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * Returns form elements in an array of available compression methods
+ *
+ * @return array
+ */
+ protected function get_available_compression_methods()
+ {
+ $methods[] = array(
+ 'value' => '.tar',
+ 'label' => '.tar',
+ 'selected' => true,
+ );
+
+ foreach ($this->available_methods as $type => $module)
+ {
+ if (!@extension_loaded($module))
+ {
+ continue;
+ }
+
+ $methods[] = array(
+ 'value' => $type,
+ 'label' => $type,
+ 'selected' => false,
+ );
+ }
+
+ return $methods;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php
new file mode 100644
index 0000000000..0cb809154e
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_files.php
@@ -0,0 +1,113 @@
+<?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\install\module\obtain_data\task;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_update_files extends task_base
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(config $config, iohandler_interface $iohandler, $phpbb_root_path, $php_ext)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Load update info file
+ // The file should be checked in the requirements, so we assume that it exists
+ $update_info_file = $this->phpbb_root_path . 'install/update/index.' . $this->php_ext;
+ include($update_info_file);
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+
+ // If the file is invalid, abort mission
+ if (!$info)
+ {
+ $this->iohandler->add_error_message('WRONG_INFO_FILE_FORMAT');
+ throw new user_interaction_required_exception();
+ }
+
+ // Replace .php with $this->php_ext if needed
+ if ($this->php_ext !== 'php')
+ {
+ $custom_extension = '.' . $this->php_ext;
+ $info['files'] = preg_replace('#\.php$#i', $custom_extension, $info['files']);
+ }
+
+ // Save update info
+ $this->installer_config->set('update_info_unprocessed', $info);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php
new file mode 100644
index 0000000000..a4d362a0f1
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_ftp_data.php
@@ -0,0 +1,164 @@
+<?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\install\module\obtain_data\task;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+class obtain_update_ftp_data extends task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $php_ext
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler, update_helper $update_helper, $php_ext)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->php_ext = $php_ext;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return ($this->installer_config->get('do_update_files', false) &&
+ ($this->installer_config->get('file_update_method', '') === 'ftp')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if ($this->iohandler->get_input('submit_ftp', false))
+ {
+ $this->update_helper->include_file('includes/functions_transfer.' . $this->php_ext);
+
+ $method = 'ftp';
+ $methods = \transfer::methods();
+ if (!in_array($method, $methods, true))
+ {
+ $method = $methods[0];
+ }
+
+ $ftp_host = $this->iohandler->get_input('ftp_host', '');
+ $ftp_user = $this->iohandler->get_input('ftp_user', '');
+ $ftp_pass = htmlspecialchars_decode($this->iohandler->get_input('ftp_pass', ''));
+ $ftp_path = $this->iohandler->get_input('ftp_path', '');
+ $ftp_port = $this->iohandler->get_input('ftp_port', 21);
+ $ftp_time = $this->iohandler->get_input('ftp_timeout', 10);
+
+ $this->installer_config->set('ftp_host', $ftp_host);
+ $this->installer_config->set('ftp_user', $ftp_user);
+ $this->installer_config->set('ftp_pass', $ftp_pass);
+ $this->installer_config->set('ftp_path', $ftp_path);
+ $this->installer_config->set('ftp_port', (int) $ftp_port);
+ $this->installer_config->set('ftp_timeout', (int) $ftp_time);
+ $this->installer_config->set('ftp_method', $method);
+ }
+ else
+ {
+ $this->iohandler->add_user_form_group('FTP_SETTINGS', array(
+ 'ftp_host' => array(
+ 'label' => 'FTP_HOST',
+ 'description' => 'FTP_HOST_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_user' => array(
+ 'label' => 'FTP_USERNAME',
+ 'description' => 'FTP_USERNAME_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_pass' => array(
+ 'label' => 'FTP_PASSWORD',
+ 'description' => 'FTP_PASSWORD_EXPLAIN',
+ 'type' => 'password',
+ ),
+ 'ftp_path' => array(
+ 'label' => 'FTP_ROOT_PATH',
+ 'description' => 'FTP_ROOT_PATH_EXPLAIN',
+ 'type' => 'text',
+ ),
+ 'ftp_port' => array(
+ 'label' => 'FTP_PORT',
+ 'description' => 'FTP_PORT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => 21,
+ ),
+ 'ftp_timeout' => array(
+ 'label' => 'FTP_TIMEOUT',
+ 'description' => 'FTP_TIMEOUT_EXPLAIN',
+ 'type' => 'text',
+ 'default' => 10,
+ ),
+ 'submit_ftp' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ $this->iohandler->send_response();
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php
new file mode 100644
index 0000000000..6a98721e77
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.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.
+ *
+ */
+
+namespace phpbb\install\module\obtain_data\task;
+
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class obtain_update_settings extends task_base
+{
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $installer_config
+ * @param iohandler_interface $iohandler
+ */
+ public function __construct(config $installer_config, iohandler_interface $iohandler)
+ {
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Check if data is sent
+ if ($this->iohandler->get_input('submit_update', false))
+ {
+ $update_files = $this->iohandler->get_input('update_type', 'all') === 'all';
+ $this->installer_config->set('do_update_files', $update_files);
+ }
+ else
+ {
+ $this->iohandler->add_user_form_group('UPDATE_TYPE', array(
+ 'update_type' => array(
+ 'label' => 'UPDATE_TYPE',
+ 'type' => 'radio',
+ 'options' => array(
+ array(
+ 'value' => 'all',
+ 'label' => 'UPDATE_TYPE_ALL',
+ 'selected' => true,
+ ),
+ array(
+ 'value' => 'db_only',
+ 'label' => 'UPDATE_TYPE_DB_ONLY',
+ 'selected' => false,
+ ),
+ ),
+ ),
+ 'submit_update' => array(
+ 'label' => 'SUBMIT',
+ 'type' => 'submit',
+ ),
+ ));
+
+ $this->iohandler->send_response();
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/obtain_data/update_module.php b/phpBB/phpbb/install/module/obtain_data/update_module.php
new file mode 100644
index 0000000000..c2f9019d34
--- /dev/null
+++ b/phpBB/phpbb/install/module/obtain_data/update_module.php
@@ -0,0 +1,33 @@
+<?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\install\module\obtain_data;
+
+class update_module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'obtain_data');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/module.php b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php
index 79a031bad9..26593e6777 100644
--- a/phpBB/phpbb/install/module/requirements/module.php
+++ b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php
@@ -15,8 +15,12 @@ namespace phpbb\install\module\requirements;
use phpbb\install\exception\resource_limit_reached_exception;
use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\module_base;
-class module extends \phpbb\install\module_base
+/**
+ * Base class for requirements installer module
+ */
+abstract class abstract_requirements_module extends module_base
{
public function run()
{
@@ -33,7 +37,7 @@ class module extends \phpbb\install\module_base
foreach ($this->task_collection as $name => $task)
{
// Run until there are available resources
- if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0)
+ if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
{
throw new resource_limit_reached_exception();
}
@@ -99,12 +103,4 @@ class module extends \phpbb\install\module_base
{
return 0;
}
-
- /**
- * {@inheritdoc}
- */
- public function get_navigation_stage_path()
- {
- return array('install', 0, 'requirements');
- }
}
diff --git a/phpBB/phpbb/install/module/requirements/install_module.php b/phpBB/phpbb/install/module/requirements/install_module.php
new file mode 100644
index 0000000000..ed0c5fbd94
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/install_module.php
@@ -0,0 +1,25 @@
+<?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\install\module\requirements;
+
+class install_module extends abstract_requirements_module
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('install', 0, 'requirements');
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/task/check_filesystem.php b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php
index ab6b1091e2..2aec3915e0 100644
--- a/phpBB/phpbb/install/module/requirements/task/check_filesystem.php
+++ b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php
@@ -50,11 +50,9 @@ class check_filesystem extends \phpbb\install\task_base
* @param \phpbb\install\helper\iohandler\iohandler_interface $response response helper
* @param string $phpbb_root_path relative path to phpBB's root
* @param string $php_ext extension of php files
+ * @param bool $check_config_php Whether or not to check if config.php is writable
*/
- public function __construct(\phpbb\filesystem\filesystem_interface $filesystem,
- \phpbb\install\helper\iohandler\iohandler_interface $response,
- $phpbb_root_path,
- $php_ext)
+ public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \phpbb\install\helper\iohandler\iohandler_interface $response, $phpbb_root_path, $php_ext, $check_config_php = true)
{
parent::__construct(true);
@@ -87,12 +85,16 @@ class check_filesystem extends \phpbb\install\task_base
'failable' => true,
'is_file' => false,
),
- array(
+ );
+
+ if ($check_config_php)
+ {
+ $this->files_to_check[] = array(
'path' => "config.$php_ext",
'failable' => false,
'is_file' => true,
- ),
- );
+ );
+ }
}
/**
diff --git a/phpBB/phpbb/install/module/requirements/task/check_update.php b/phpBB/phpbb/install/module/requirements/task/check_update.php
new file mode 100644
index 0000000000..c986c76810
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/task/check_update.php
@@ -0,0 +1,185 @@
+<?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\install\module\requirements\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Check the availability of updater files and update version
+ */
+class check_update extends task_base
+{
+ /**
+ * @var \phpbb\config\db
+ */
+ protected $config;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var \phpbb\version_helper
+ */
+ protected $version_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var bool
+ */
+ protected $tests_passed;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param filesystem $filesystem
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(container_factory $container, filesystem $filesystem, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->filesystem = $filesystem;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ $this->tests_passed = true;
+
+ $this->config = $container->get('config');
+ $this->version_helper = $container->get('version_helper');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * Sets $this->tests_passed
+ *
+ * @param bool $is_passed
+ */
+ protected function set_test_passed($is_passed)
+ {
+ // If one test failed, tests_passed should be false
+ $this->tests_passed = $this->tests_passed && $is_passed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Array of update files
+ $update_files = array(
+ $this->phpbb_root_path . 'install/update',
+ $this->phpbb_root_path . 'install/update/index.' . $this->php_ext,
+ );
+
+ // Check for a valid update directory
+ if (!$this->filesystem->exists($update_files) || !$this->filesystem->is_readable($update_files))
+ {
+ $this->iohandler->add_error_message('UPDATE_FILES_NOT_FOUND');
+ $this->set_test_passed(false);
+
+ // If there are no update files, we can't check the version
+ return false;
+ }
+
+ // Recover version numbers
+ $update_info = array();
+ @include($this->phpbb_root_path . 'install/update/index.' . $this->php_ext);
+ $info = (empty($update_info) || !is_array($update_info)) ? false : $update_info;
+ $update_version = false;
+
+ if ($info !== false)
+ {
+ $update_version = (!empty($info['version']['to'])) ? trim($info['version']['to']) : false;
+ }
+
+ // Get current and latest version
+ try
+ {
+ $latest_version = $this->version_helper->get_latest_on_current_branch(true);
+ }
+ catch (\RuntimeException $e)
+ {
+ $latest_version = $update_version;
+ }
+
+ $current_version = (!empty($this->config['version_update_from'])) ? $this->config['version_update_from'] : $this->config['version'];
+
+ // Check if the update package
+ if (!$this->update_helper->phpbb_version_compare($current_version, $update_version, '<'))
+ {
+ $this->iohandler->add_error_message('NO_UPDATE_FILES_UP_TO_DATE');
+ $this->tests_passed = false;
+ }
+
+ // Check if the update package works with the installed version
+ if (empty($info['version']['from']) || $info['version']['from'] !== $current_version)
+ {
+ $this->iohandler->add_error_message(array('INCOMPATIBLE_UPDATE_FILES', $current_version, $info['version']['from'], $update_version));
+ $this->tests_passed = false;
+ }
+
+ // check if this is the latest update package
+ if ($this->update_helper->phpbb_version_compare($update_version, $latest_version, '<'))
+ {
+ $this->iohandler->add_warning_message(array('OLD_UPDATE_FILES', $info['version']['from'], $update_version, $latest_version));
+ }
+
+ return $this->tests_passed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/requirements/update_module.php b/phpBB/phpbb/install/module/requirements/update_module.php
new file mode 100644
index 0000000000..223d12faf3
--- /dev/null
+++ b/phpBB/phpbb/install/module/requirements/update_module.php
@@ -0,0 +1,25 @@
+<?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\install\module\requirements;
+
+class update_module extends abstract_requirements_module
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'requirements');
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_database/module.php b/phpBB/phpbb/install/module/update_database/module.php
new file mode 100644
index 0000000000..ee38afe17d
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_database/module.php
@@ -0,0 +1,33 @@
+<?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\install\module\update_database;
+
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'update_database');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_database/task/update.php b/phpBB/phpbb/install/module/update_database/task/update.php
new file mode 100644
index 0000000000..2d640134a3
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_database/task/update.php
@@ -0,0 +1,212 @@
+<?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\install\module\update_database\task;
+
+use phpbb\db\migration\exception;
+use phpbb\db\output_handler\installer_migrator_output_handler;
+use phpbb\db\output_handler\log_wrapper_migrator_output_handler;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\task_base;
+
+/**
+ * Database updater task
+ */
+class update extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var \phpbb\config\config
+ */
+ protected $config;
+
+ /**
+ * @var \phpbb\extension\manager
+ */
+ protected $extension_manager;
+
+ /**
+ * @var \phpbb\filesystem\filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var \phpbb\install\helper\config
+ */
+ protected $installer_config;
+
+ /**
+ * @var \phpbb\install\helper\iohandler\iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\language\language
+ */
+ protected $language;
+
+ /**
+ * @var \phpbb\log\log
+ */
+ protected $log;
+
+ /**
+ * @var \phpbb\db\migrator
+ */
+ protected $migrator;
+
+ /**
+ * @var \phpbb\user
+ */
+ protected $user;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param \phpbb\install\helper\container_factory $container
+ * @param \phpbb\filesystem\filesystem $filesystem
+ * @param \phpbb\install\helper\config $installer_config
+ * @param \phpbb\install\helper\iohandler\iohandler_interface $iohandler
+ * @param \phpbb\language\language $language
+ * @param string $phpbb_root_path
+ */
+ public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\filesystem\filesystem $filesystem, \phpbb\install\helper\config $installer_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, \phpbb\language\language $language, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->installer_config = $installer_config;
+ $this->iohandler = $iohandler;
+ $this->language = $language;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ $this->cache = $container->get('cache.driver');
+ $this->config = $container->get('config');
+ $this->extension_manager = $container->get('ext.manager');
+ $this->log = $container->get('log');
+ $this->migrator = $container->get('migrator');
+ $this->user = $container->get('user');
+
+ parent::__construct(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $this->language->add_lang('migrator');
+
+ if (!isset($this->config['version_update_from']))
+ {
+ $this->config->set('version_update_from', $this->config['version']);
+ }
+
+ $original_version = $this->config['version_update_from'];
+
+ $this->migrator->set_output_handler(
+ new log_wrapper_migrator_output_handler(
+ $this->language,
+ new installer_migrator_output_handler($this->iohandler),
+ $this->phpbb_root_path . 'store/migrations_' . time() . '.log',
+ $this->filesystem
+ )
+ );
+
+ $this->migrator->create_migrations_table();
+
+ $migrations = $this->extension_manager
+ ->get_finder()
+ ->core_path('phpbb/db/migration/data/')
+ ->extension_directory('/migrations')
+ ->get_classes();
+
+ $this->migrator->set_migrations($migrations);
+ $migration_count = count($migrations);
+ $this->iohandler->set_task_count($migration_count, true);
+ $progress_count = $this->installer_config->get('database_update_count', 0);
+
+ while (!$this->migrator->finished())
+ {
+ try
+ {
+ $this->migrator->update();
+ $progress_count++;
+ $this->iohandler->set_progress('STAGE_UPDATE_DATABASE', $progress_count);
+ }
+ catch (exception $e)
+ {
+ $msg = $e->getParameters();
+ array_unshift($msg, $e->getMessage());
+
+ $this->iohandler->add_error_message($msg);
+ throw new user_interaction_required_exception();
+ }
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ $this->installer_config->set('database_update_count', $progress_count);
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ if ($original_version !== $this->config['version'])
+ {
+ $this->log->add(
+ 'admin',
+ $this->user->data['user_id'],
+ $this->user->ip,
+ 'LOG_UPDATE_DATABASE',
+ false,
+ array(
+ $original_version,
+ $this->config['version']
+ )
+ );
+ }
+
+ $this->iohandler->finish_progress('INLINE_UPDATE_SUCCESSFUL');
+
+ $this->iohandler->add_success_message('INLINE_UPDATE_SUCCESSFUL');
+
+ $this->config->delete('version_update_from');
+
+ $this->cache->purge();
+
+ $this->config->increment('assets_version', 1);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/module.php b/phpBB/phpbb/install/module/update_filesystem/module.php
new file mode 100644
index 0000000000..157c78a1ac
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/module.php
@@ -0,0 +1,33 @@
+<?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\install\module\update_filesystem;
+
+class module extends \phpbb\install\module_base
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function get_navigation_stage_path()
+ {
+ return array('update', 0, 'update_files');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_step_count()
+ {
+ return 0;
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php
new file mode 100644
index 0000000000..e3e6db6263
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/diff_files.php
@@ -0,0 +1,205 @@
+<?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\install\module\update_filesystem\task;
+
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Merges user made changes into the files
+ */
+class diff_files extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * @var string
+ */
+ protected $php_ext;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ * @param string $php_ext
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+
+ $this->cache = $container->get('cache.driver');
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ $files_to_diff = $this->installer_config->get('update_files', array());
+ $files_to_diff = (isset($files_to_diff['update_with_diff'])) ? $files_to_diff['update_with_diff'] : array();
+
+ return $this->installer_config->get('do_update_files', false) && count($files_to_diff) > 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ // Include diff engine
+ $this->update_helper->include_file('includes/diff/diff.' . $this->php_ext);
+ $this->update_helper->include_file('includes/diff/engine.' . $this->php_ext);
+
+ // Set up basic vars
+ $old_path = $this->update_helper->get_path_to_old_update_files();
+ $new_path = $this->update_helper->get_path_to_new_update_files();
+
+ $files_to_diff = $this->installer_config->get('update_files', array());
+ $files_to_diff = $files_to_diff['update_with_diff'];
+
+ // Set progress bar
+ $this->iohandler->set_task_count(count($files_to_diff), true);
+ $this->iohandler->set_progress('UPDATE_FILE_DIFF', 0);
+ $progress_count = $this->installer_config->get('file_diff_update_count', 0);
+
+ // Recover progress
+ $progress_key = $this->installer_config->get('differ_progress_key', -1);
+ $progress_recovered = ($progress_key === -1);
+ $merge_conflicts = $this->installer_config->get('merge_conflict_list', array());
+
+ foreach ($files_to_diff as $key => $filename)
+ {
+ if ($progress_recovered === false)
+ {
+ if ($progress_key === $key)
+ {
+ $progress_recovered = true;
+ }
+
+ continue;
+ }
+
+ // Read in files' content
+ $file_contents = array();
+
+ // Handle the special case when user created a file with the filename that is now new in the core
+ $file_contents[0] = (file_exists($old_path . $filename)) ? file_get_contents($old_path . $filename) : '';
+
+ $filenames = array(
+ $this->phpbb_root_path . $filename,
+ $new_path . $filename
+ );
+
+ foreach ($filenames as $file_to_diff)
+ {
+ $file_contents[] = file_get_contents($file_to_diff);
+
+ if ($file_contents[sizeof($file_contents) - 1] === false)
+ {
+ $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff));
+ unset($file_contents);
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]);
+ unset($file_contents);
+
+ // Handle conflicts
+ if ($diff->get_num_conflicts() !== 0)
+ {
+ $merge_conflicts[] = $filename;
+ }
+
+ // Save merged output
+ $this->cache->put(
+ '_file_' . md5($filename),
+ base64_encode(implode("\n", $diff->merged_output()))
+ );
+
+ unset($diff);
+
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_FILE_DIFF', $progress_count);
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Save differ progress
+ $this->installer_config->set('differ_progress_key', $key);
+ $this->installer_config->set('merge_conflict_list', $merge_conflicts);
+ $this->installer_config->set('file_diff_update_count', $progress_count);
+
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+ }
+
+ $this->iohandler->finish_progress('ALL_FILES_DIFFED');
+ $this->installer_config->set('merge_conflict_list', $merge_conflicts);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php
new file mode 100644
index 0000000000..9271e8fd50
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php
@@ -0,0 +1,124 @@
+<?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\install\module\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\jump_to_restart_point_exception;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class download_updated_files extends task_base
+{
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * Constructor
+ *
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param filesystem $filesystem
+ */
+ public function __construct(config $config, iohandler_interface $iohandler, filesystem $filesystem)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->filesystem = $filesystem;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false)
+ && $this->installer_config->get('file_update_method', '') === 'compression';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if ($this->iohandler->get_input('database_update_submit', false))
+ {
+ // Remove archive
+ $this->filesystem->remove(
+ $this->installer_config->get('update_file_archive', null)
+ );
+
+ $this->installer_config->set('update_file_archive', null);
+ }
+ else if ($this->iohandler->get_input('update_recheck_files_submit', false))
+ {
+ throw new jump_to_restart_point_exception('check_update_files');
+ }
+ else
+ {
+ // Render download box
+ $this->iohandler->add_download_link(
+ 'phpbb_installer_update_file_download',
+ 'DOWNLOAD_UPDATE_METHOD',
+ 'DOWNLOAD_UPDATE_METHOD_EXPLAIN'
+ );
+
+ // Add form to continue update
+ $this->iohandler->add_user_form_group('UPDATE_CONTINUE_UPDATE_PROCESS', array(
+ 'update_recheck_files_submit' => array(
+ 'label' => 'UPDATE_RECHECK_UPDATE_FILES',
+ 'type' => 'submit',
+ ),
+ 'database_update_submit' => array(
+ 'label' => 'UPDATE_CONTINUE_UPDATE_PROCESS',
+ 'type' => 'submit',
+ ),
+ ));
+
+ $this->iohandler->send_response();
+ throw new user_interaction_required_exception();
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php
new file mode 100644
index 0000000000..5dbee6c259
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php
@@ -0,0 +1,186 @@
+<?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\install\module\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * Updater task performing file checking
+ */
+class file_check extends task_base
+{
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Construct
+ *
+ * @param filesystem $filesystem
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ */
+ public function __construct(filesystem $filesystem, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path)
+ {
+ $this->filesystem = $filesystem;
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if (!$this->installer_config->has_restart_point('check_update_files'))
+ {
+ $this->installer_config->create_progress_restart_point('check_update_files');
+ }
+
+ $old_path = $this->update_helper->get_path_to_old_update_files();
+ $new_path = $this->update_helper->get_path_to_new_update_files();
+
+ $update_info = $this->installer_config->get('update_info', array());
+ $file_update_info = $this->installer_config->get('update_files', array());
+
+ if (empty($update_info))
+ {
+ $root_path = $this->phpbb_root_path;
+
+ $update_info = $this->installer_config->get('update_info_unprocessed', array());
+
+ $file_update_info = array();
+ $file_update_info['update_without_diff'] = array_diff($update_info['binary'], $update_info['deleted']);
+
+ // Filter out files that are already deleted
+ $file_update_info['delete'] = array_filter(
+ $update_info['deleted'],
+ function ($filename) use ($root_path)
+ {
+ return file_exists($root_path . $filename);
+ }
+ );
+ }
+
+ $progress_count = $this->installer_config->get('file_check_progress_count', 0);
+ $task_count = count($update_info['files']);
+ $this->iohandler->set_task_count($task_count);
+ $this->iohandler->set_progress('UPDATE_CHECK_FILES', 0);
+
+ foreach ($update_info['files'] as $key => $filename)
+ {
+ $old_file = $old_path . $filename;
+ $new_file = $new_path . $filename;
+ $file = $this->phpbb_root_path . $filename;
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Save progress
+ $this->installer_config->set('update_info', $update_info);
+ $this->installer_config->set('file_check_progress_count', $progress_count);
+ $this->installer_config->set('update_files', $file_update_info);
+
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_CHECK_FILES', $progress_count);
+
+ if (!$this->filesystem->exists($file))
+ {
+ $file_update_info['new'][] = $filename;
+ }
+ else
+ {
+ $file_checksum = md5_file($file);
+
+ if ($file_checksum === md5_file($new_file))
+ {
+ // File already up to date
+ continue;
+ }
+ else if ($this->filesystem->exists($old_file) && $file_checksum === md5_file($old_file))
+ {
+ // No need to diff the file
+ $file_update_info['update_without_diff'][] = $filename;
+ }
+ else
+ {
+ $file_update_info['update_with_diff'][] = $filename;
+ }
+ }
+
+ unset($update_info['files'][$key]);
+ }
+
+ $this->installer_config->set('update_files', $file_update_info);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
new file mode 100644
index 0000000000..1c6b9aa058
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php
@@ -0,0 +1,168 @@
+<?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\install\module\update_filesystem\task;
+
+use phpbb\filesystem\filesystem;
+use phpbb\install\exception\user_interaction_required_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\file_updater\factory;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\task_base;
+
+class show_file_status extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var filesystem
+ */
+ protected $filesystem;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var \phpbb\install\helper\file_updater\compression_file_updater
+ */
+ protected $file_updater;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param filesystem $filesystem
+ * @param factory $file_updater_factory
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, filesystem $filesystem, factory $file_updater_factory)
+ {
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->filesystem = $filesystem;
+
+ $this->cache = $container->get('cache.driver');
+
+ // Initialize compression file updater
+ $compression_method = $this->installer_config->get('compression_method', '');
+ $this->file_updater = $file_updater_factory->get('compression');
+ $conflict_archive = $this->file_updater->init($compression_method);
+
+ $this->installer_config->set('update_file_conflict_archive', $conflict_archive);
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ if (!$this->iohandler->get_input('submit_continue_file_update', false))
+ {
+ // Handle merge conflicts
+ $merge_conflicts = $this->installer_config->get('merge_conflict_list', array());
+
+ // Create archive for merge conflicts
+ if (!empty($merge_conflicts))
+ {
+ foreach ($merge_conflicts as $filename)
+ {
+ $this->file_updater->create_new_file(
+ $filename,
+ $this->cache->get('_file_' . md5($filename)),
+ true
+ );
+ }
+
+ // Render download box
+ $this->iohandler->add_download_link(
+ 'phpbb_installer_update_conflict_download',
+ 'DOWNLOAD_CONFLICTS',
+ 'DOWNLOAD_CONFLICTS_EXPLAIN'
+ );
+ }
+
+ $this->file_updater->close();
+
+ // Render update file statuses
+ $file_update_info = $this->installer_config->get('update_files', array());
+ $file_status = array(
+ 'deleted' => (!isset($file_update_info['delete'])) ? array() : $file_update_info['delete'],
+ 'new' => (!isset($file_update_info['new'])) ? array() : $file_update_info['new'],
+ 'conflict' => $this->installer_config->get('merge_conflict_list', array()),
+ 'modified' => (!isset($file_update_info['update_with_diff'])) ? array() : $file_update_info['update_with_diff'],
+ 'not_modified' => (!isset($file_update_info['update_without_diff'])) ? array() : $file_update_info['update_without_diff'],
+ );
+
+ $this->iohandler->render_update_file_status($file_status);
+
+ // Add form to continue update
+ $this->iohandler->add_user_form_group('UPDATE_CONTINUE_FILE_UPDATE', array(
+ 'submit_continue_file_update' => array(
+ 'label' => 'UPDATE_CONTINUE_FILE_UPDATE',
+ 'type' => 'submit',
+ ),
+ ));
+
+ // Show results to the user
+ $this->iohandler->send_response();
+ throw new user_interaction_required_exception();
+ }
+ else
+ {
+ // Remove archive
+ $this->filesystem->remove(
+ $this->installer_config->get('update_file_conflict_archive', null)
+ );
+
+ $this->installer_config->set('update_file_conflict_archive', null);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module/update_filesystem/task/update_files.php b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
new file mode 100644
index 0000000000..747a86281b
--- /dev/null
+++ b/phpBB/phpbb/install/module/update_filesystem/task/update_files.php
@@ -0,0 +1,294 @@
+<?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\install\module\update_filesystem\task;
+
+use phpbb\exception\runtime_exception;
+use phpbb\install\exception\resource_limit_reached_exception;
+use phpbb\install\helper\config;
+use phpbb\install\helper\container_factory;
+use phpbb\install\helper\file_updater\factory;
+use phpbb\install\helper\file_updater\file_updater_interface;
+use phpbb\install\helper\iohandler\iohandler_interface;
+use phpbb\install\helper\update_helper;
+use phpbb\install\task_base;
+
+/**
+ * File updater task
+ */
+class update_files extends task_base
+{
+ /**
+ * @var \phpbb\cache\driver\driver_interface
+ */
+ protected $cache;
+
+ /**
+ * @var config
+ */
+ protected $installer_config;
+
+ /**
+ * @var iohandler_interface
+ */
+ protected $iohandler;
+
+ /**
+ * @var factory
+ */
+ protected $factory;
+
+ /**
+ * @var file_updater_interface
+ */
+ protected $file_updater;
+
+ /**
+ * @var update_helper
+ */
+ protected $update_helper;
+
+ /**
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor
+ *
+ * @param container_factory $container
+ * @param config $config
+ * @param iohandler_interface $iohandler
+ * @param factory $file_updater_factory
+ * @param update_helper $update_helper
+ * @param string $phpbb_root_path
+ */
+ public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, factory $file_updater_factory, update_helper $update_helper, $phpbb_root_path)
+ {
+ $this->factory = $file_updater_factory;
+ $this->installer_config = $config;
+ $this->iohandler = $iohandler;
+ $this->update_helper = $update_helper;
+ $this->phpbb_root_path = $phpbb_root_path;
+
+ $this->cache = $container->get('cache.driver');
+ $this->file_updater = null;
+
+ parent::__construct(false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function check_requirements()
+ {
+ return $this->installer_config->get('do_update_files', false);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function run()
+ {
+ $new_path = $this->update_helper->get_path_to_new_update_files();
+
+ $file_update_info = $this->installer_config->get('update_files', array());
+
+ $update_type_progress = $this->installer_config->get('file_updater_type_progress', '');
+ $update_elem_progress = $this->installer_config->get('file_updater_elem_progress', '');
+ $type_progress_found = false;
+ $elem_progress_found = false;
+
+ // Progress bar
+ $task_count = 0;
+ foreach ($file_update_info as $sub_array)
+ {
+ $task_count += count($sub_array);
+ }
+
+ // Everything is up to date, so just continue
+ if ($task_count === 0)
+ {
+ return;
+ }
+
+ $progress_count = $this->installer_config->get('file_update_progress_count', 0);
+ $this->iohandler->set_task_count($task_count, true);
+ $this->iohandler->set_progress('UPDATE_UPDATING_FILES', 0);
+
+ $this->file_updater = $this->get_file_updater();
+
+ // File updater fallback logic
+ try
+ {
+ // Update files
+ foreach ($file_update_info as $type => $file_update_vector)
+ {
+ if (!$type_progress_found)
+ {
+ if ($type === $update_type_progress || empty($update_elem_progress))
+ {
+ $type_progress_found = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ foreach ($file_update_vector as $path)
+ {
+ if (!$elem_progress_found)
+ {
+ if ($path === $update_elem_progress || empty($update_elem_progress))
+ {
+ $elem_progress_found = true;
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ switch ($type)
+ {
+ case 'delete':
+ $this->file_updater->delete_file($path);
+ break;
+ case 'new':
+ $this->file_updater->create_new_file($path, $new_path . $path);
+ break;
+ case 'update_without_diff':
+ $this->file_updater->update_file($path, $new_path . $path);
+ break;
+ case 'update_with_diff':
+ $this->file_updater->update_file(
+ $path,
+ $this->cache->get('_file_' . md5($path)),
+ true
+ );
+ break;
+ }
+
+ // Save progress
+ $this->installer_config->set('file_updater_type_progress', $type);
+ $this->installer_config->set('file_updater_elem_progress', $path);
+ $progress_count++;
+ $this->iohandler->set_progress('UPDATE_UPDATING_FILES', $progress_count);
+
+ if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0)
+ {
+ // Request refresh
+ throw new resource_limit_reached_exception();
+ }
+ }
+ }
+
+ $this->iohandler->finish_progress('UPDATE_UPDATING_FILES');
+ }
+ catch (runtime_exception $e)
+ {
+ if ($e instanceof resource_limit_reached_exception)
+ {
+ throw new resource_limit_reached_exception();
+ }
+
+ $current_method = $this->installer_config->get('file_update_method', '');
+
+ // File updater failed, try to fallback to download file update mode
+ if ($current_method !== 'compression')
+ {
+ $this->iohandler->add_warning_message(array(
+ 'UPDATE_FILE_UPDATER_HAS_FAILED',
+ $current_method,
+ 'compression'
+ ));
+ $this->installer_config->set('file_update_method', 'compression');
+
+ // We only want a simple refresh here
+ throw new resource_limit_reached_exception();
+ }
+ else
+ {
+ // Nowhere to fallback to :(
+ // Due to the way the installer handles fatal errors, we need to throw a low level exception
+ throw new runtime_exception('UPDATE_FILE_UPDATERS_HAVE_FAILED');
+ }
+ }
+
+ $file_updater_method = $this->installer_config->get('file_update_method', '');
+ if ($file_updater_method === 'compression' || $file_updater_method === 'ftp')
+ {
+ $this->file_updater->close();
+ }
+ }
+
+ /**
+ * Get file updater
+ *
+ * @param null|string $file_updater_method Name of the file updater to use
+ *
+ * @return file_updater_interface File updater
+ */
+ protected function get_file_updater($file_updater_method = null)
+ {
+ $file_updater_method = ($file_updater_method === null) ? $this->installer_config->get('file_update_method', '') : $file_updater_method;
+
+ if ($file_updater_method === 'compression')
+ {
+ $compression_method = $this->installer_config->get('file_update_compression', '');
+
+ /** @var \phpbb\install\helper\file_updater\compression_file_updater $file_updater */
+ $file_updater = $this->factory->get('compression');
+ $archive_path = $file_updater->init($compression_method);
+ $this->installer_config->set('update_file_archive', $archive_path);
+ }
+ else if ($file_updater_method === 'ftp')
+ {
+ /** @var \phpbb\install\helper\file_updater\ftp_file_updater $file_updater */
+ $file_updater = $this->factory->get('ftp');
+ $file_updater->init(
+ $this->installer_config->get('ftp_method', ''),
+ $this->installer_config->get('ftp_host', ''),
+ $this->installer_config->get('ftp_user', ''),
+ $this->installer_config->get('ftp_pass', ''),
+ $this->installer_config->get('ftp_path', ''),
+ $this->installer_config->get('ftp_port', 0),
+ $this->installer_config->get('ftp_timeout', 10)
+ );
+ }
+ else
+ {
+ /** @var file_updater_interface $file_updater */
+ $file_updater = $this->factory->get('direct_file');
+ }
+
+ return $file_updater;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ static public function get_step_count()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get_task_lang_name()
+ {
+ return '';
+ }
+}
diff --git a/phpBB/phpbb/install/module_base.php b/phpBB/phpbb/install/module_base.php
index a933d4987c..fb68c3aca2 100644
--- a/phpBB/phpbb/install/module_base.php
+++ b/phpBB/phpbb/install/module_base.php
@@ -115,7 +115,7 @@ abstract class module_base implements module_interface
foreach ($this->task_collection as $name => $task)
{
// Run until there are available resources
- if ($this->install_config->get_time_remaining() <= 0 && $this->install_config->get_memory_remaining() <= 0)
+ if ($this->install_config->get_time_remaining() <= 0 || $this->install_config->get_memory_remaining() <= 0)
{
throw new resource_limit_reached_exception();
}
diff --git a/phpBB/phpbb/install/task_base.php b/phpBB/phpbb/install/task_base.php
index 5946be8c52..b5199be4af 100644
--- a/phpBB/phpbb/install/task_base.php
+++ b/phpBB/phpbb/install/task_base.php
@@ -44,7 +44,7 @@ abstract class task_base implements task_interface
/**
* {@inheritdoc}
*
- * Overwrite this method if your task is non-essential!
+ * Note: Overwrite this method if your task is non-essential!
*/
public function check_requirements()
{
diff --git a/phpBB/phpbb/notification/type/approve_post.php b/phpBB/phpbb/notification/type/approve_post.php
index 9666647bd8..e4b111e4da 100644
--- a/phpBB/phpbb/notification/type/approve_post.php
+++ b/phpBB/phpbb/notification/type/approve_post.php
@@ -82,7 +82,7 @@ class approve_post extends \phpbb\notification\type\post
$users[$post['poster_id']] = $this->notification_manager->get_default_methods();
return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array(
- 'item_type' => self::$notification_option['id'],
+ 'item_type' => static::$notification_option['id'],
)));
}
diff --git a/phpBB/phpbb/notification/type/approve_topic.php b/phpBB/phpbb/notification/type/approve_topic.php
index e9f4c32852..f8a3fdec6f 100644
--- a/phpBB/phpbb/notification/type/approve_topic.php
+++ b/phpBB/phpbb/notification/type/approve_topic.php
@@ -82,7 +82,7 @@ class approve_topic extends \phpbb\notification\type\topic
$users[$post['poster_id']] = $this->notification_manager->get_default_methods();
return $this->get_authorised_recipients(array_keys($users), $post['forum_id'], array_merge($options, array(
- 'item_type' => self::$notification_option['id'],
+ 'item_type' => static::$notification_option['id'],
)));
}
diff --git a/phpBB/phpbb/notification/type/bookmark.php b/phpBB/phpbb/notification/type/bookmark.php
index 5b3fc3a1f2..ebbb961c57 100644
--- a/phpBB/phpbb/notification/type/bookmark.php
+++ b/phpBB/phpbb/notification/type/bookmark.php
@@ -92,7 +92,7 @@ class bookmark extends \phpbb\notification\type\post
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
$notified_users = $this->notification_manager->get_notified_users($this->get_type(), array(
- 'item_parent_id' => self::get_item_parent_id($post),
+ 'item_parent_id' => static::get_item_parent_id($post),
'read' => 0,
));
diff --git a/phpBB/phpbb/notification/type/post.php b/phpBB/phpbb/notification/type/post.php
index b54a6610b2..b9afc6d70a 100644
--- a/phpBB/phpbb/notification/type/post.php
+++ b/phpBB/phpbb/notification/type/post.php
@@ -150,7 +150,7 @@ class post extends \phpbb\notification\type\base
// Try to find the users who already have been notified about replies and have not read the topic since and just update their notifications
$notified_users = $this->notification_manager->get_notified_users($this->get_type(), array(
- 'item_parent_id' => self::get_item_parent_id($post),
+ 'item_parent_id' => static::get_item_parent_id($post),
'read' => 0,
));
diff --git a/phpBB/phpbb/notification/type/post_in_queue.php b/phpBB/phpbb/notification/type/post_in_queue.php
index 8b21d77cdd..2d556fc9c8 100644
--- a/phpBB/phpbb/notification/type/post_in_queue.php
+++ b/phpBB/phpbb/notification/type/post_in_queue.php
@@ -108,7 +108,7 @@ class post_in_queue extends \phpbb\notification\type\post
}
return $this->check_user_notification_options($auth_read[$post['forum_id']]['f_read'], array_merge($options, array(
- 'item_type' => self::$notification_option['id'],
+ 'item_type' => static::$notification_option['id'],
)));
}
diff --git a/phpBB/phpbb/notification/type/quote.php b/phpBB/phpbb/notification/type/quote.php
index 9e759ef137..684463c8c3 100644
--- a/phpBB/phpbb/notification/type/quote.php
+++ b/phpBB/phpbb/notification/type/quote.php
@@ -111,7 +111,7 @@ class quote extends \phpbb\notification\type\post
public function update_notifications($post)
{
$old_notifications = $this->notification_manager->get_notified_users($this->get_type(), array(
- 'item_id' => self::get_item_id($post),
+ 'item_id' => static::get_item_id($post),
));
// Find the new users to notify
@@ -133,7 +133,7 @@ class quote extends \phpbb\notification\type\post
// Remove the necessary notifications
if (!empty($remove_notifications))
{
- $this->notification_manager->delete_notifications($this->get_type(), self::get_item_id($post), false, $remove_notifications);
+ $this->notification_manager->delete_notifications($this->get_type(), static::get_item_id($post), false, $remove_notifications);
}
// return true to continue with the update code in the notifications service (this will update the rest of the notifications)
diff --git a/phpBB/phpbb/notification/type/report_pm.php b/phpBB/phpbb/notification/type/report_pm.php
index b80afc1039..6091919769 100644
--- a/phpBB/phpbb/notification/type/report_pm.php
+++ b/phpBB/phpbb/notification/type/report_pm.php
@@ -121,7 +121,7 @@ class report_pm extends \phpbb\notification\type\pm
}
return $this->check_user_notification_options($auth_approve[$post['forum_id']][$this->permission], array_merge($options, array(
- 'item_type' => self::$notification_option['id'],
+ 'item_type' => static::$notification_option['id'],
)));
}
diff --git a/phpBB/phpbb/notification/type/topic_in_queue.php b/phpBB/phpbb/notification/type/topic_in_queue.php
index ad2961525e..2d732b9cd7 100644
--- a/phpBB/phpbb/notification/type/topic_in_queue.php
+++ b/phpBB/phpbb/notification/type/topic_in_queue.php
@@ -108,7 +108,7 @@ class topic_in_queue extends \phpbb\notification\type\topic
}
return $this->check_user_notification_options($auth_read[$topic['forum_id']]['f_read'], array_merge($options, array(
- 'item_type' => self::$notification_option['id'],
+ 'item_type' => static::$notification_option['id'],
)));
}
diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php
index 81ac010785..38d6d9cd2c 100644
--- a/phpBB/phpbb/passwords/driver/salted_md5.php
+++ b/phpBB/phpbb/passwords/driver/salted_md5.php
@@ -75,7 +75,7 @@ class salted_md5 extends base
// happen if pre-determined settings are
// directly passed to the driver. The manager
// will not do this. Same as the old hashing
- // implementatio in phpBB 3.0
+ // implementation in phpBB 3.0
return md5($password);
}
}
diff --git a/phpBB/phpbb/plupload/plupload.php b/phpBB/phpbb/plupload/plupload.php
index 0e67ee209b..a47fc87adf 100644
--- a/phpBB/phpbb/plupload/plupload.php
+++ b/phpBB/phpbb/plupload/plupload.php
@@ -125,7 +125,7 @@ class plupload
// Need to modify some of the $_FILES values to reflect the new file
return array(
'tmp_name' => $file_path,
- 'name' => $this->request->variable('real_filename', ''),
+ 'name' => $this->request->variable('real_filename', '', true),
'size' => filesize($file_path),
'type' => $this->mimetype_guesser->guess($file_path, $file_name),
);
diff --git a/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php
new file mode 100644
index 0000000000..42cd0f11af
--- /dev/null
+++ b/phpBB/phpbb/routing/resources_locator/installer_resources_locator.php
@@ -0,0 +1,78 @@
+<?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\routing\resources_locator;
+
+use phpbb\filesystem\filesystem_interface;
+
+/**
+ * Locates the yaml routing resources taking update directories into consideration
+ */
+class installer_resources_locator implements resources_locator_interface
+{
+ /**
+ * phpBB's filesystem handler
+ *
+ * @var filesystem_interface
+ */
+ protected $filesystem;
+
+ /**
+ * phpBB root path
+ *
+ * @var string
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Name of the current environment
+ *
+ * @var string
+ */
+ protected $environment;
+
+ /**
+ * Construct method
+ *
+ * @param filesystem_interface $filesystem phpBB's filesystem handler
+ * @param string $phpbb_root_path phpBB root path
+ * @param string $environment Name of the current environment
+ */
+ public function __construct(filesystem_interface $filesystem, $phpbb_root_path, $environment)
+ {
+ $this->filesystem = $filesystem;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->environment = $environment;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locate_resources()
+ {
+ if ($this->filesystem->exists($this->phpbb_root_path . 'install/update/new/config'))
+ {
+ $resources = array(
+ array('install/update/new/config/' . $this->environment . '/routing/environment.yml', 'yaml')
+ );
+ }
+ else
+ {
+ $resources = array(
+ array('config/' . $this->environment . '/routing/environment.yml', 'yaml')
+ );
+ }
+
+ return $resources;
+ }
+}
diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php
index ba9f5f3a77..d1962bc8cc 100644
--- a/phpBB/phpbb/search/fulltext_mysql.php
+++ b/phpBB/phpbb/search/fulltext_mysql.php
@@ -379,7 +379,7 @@ class fulltext_mysql extends \phpbb\search\base
}
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
implode(', ', $this->split_words),
$type,
$fields,
@@ -390,7 +390,39 @@ class fulltext_mysql extends \phpbb\search\base
implode(',', $ex_fid_ary),
$post_visibility,
implode(',', $author_ary)
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_mysql_by_keyword_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var string type Searching type ('posts', 'topics')
+ * @var string fields Searching fields ('titleonly', 'msgonly', 'firstpost', 'all')
+ * @var string terms Searching terms ('all', 'any')
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'type',
+ 'fields',
+ 'terms',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_by_keyword_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
if ($start < 0)
{
@@ -610,7 +642,7 @@ class fulltext_mysql extends \phpbb\search\base
}
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
'',
$type,
($firstpost_only) ? 'firstpost' : '',
@@ -623,7 +655,39 @@ class fulltext_mysql extends \phpbb\search\base
$post_visibility,
implode(',', $author_ary),
$author_name,
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_mysql_by_author_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var string type Searching type ('posts', 'topics')
+ * @var boolean firstpost_only Flag indicating if only topic starting posts are considered
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @var string author_name The username to search on
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'type',
+ 'firstpost_only',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ 'author_name',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_mysql_by_author_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
if ($start < 0)
{
diff --git a/phpBB/phpbb/search/fulltext_native.php b/phpBB/phpbb/search/fulltext_native.php
index 41d3434c7d..3a74955a18 100644
--- a/phpBB/phpbb/search/fulltext_native.php
+++ b/phpBB/phpbb/search/fulltext_native.php
@@ -64,7 +64,7 @@ class fulltext_native extends \phpbb\search\base
protected $must_not_contain_ids = array();
/**
- * Post ids of posts containing atleast one word that needs to be excluded
+ * Post ids of posts containing at least one word that needs to be excluded
* @var array
*/
protected $must_exclude_one_ids = array();
@@ -533,7 +533,7 @@ class fulltext_native extends \phpbb\search\base
sort($must_exclude_one_ids);
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
serialize($must_contain_ids),
serialize($must_not_contain_ids),
serialize($must_exclude_one_ids),
@@ -547,7 +547,45 @@ class fulltext_native extends \phpbb\search\base
$post_visibility,
implode(',', $author_ary),
$author_name,
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_native_by_keyword_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var array must_contain_ids Array with post ids of posts containing words that are to be included
+ * @var array must_not_contain_ids Array with post ids of posts containing words that should not be included
+ * @var array must_exclude_one_ids Array with post ids of posts containing at least one word that needs to be excluded
+ * @var string type Searching type ('posts', 'topics')
+ * @var string fields Searching fields ('titleonly', 'msgonly', 'firstpost', 'all')
+ * @var string terms Searching terms ('all', 'any')
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'must_contain_ids',
+ 'must_not_contain_ids',
+ 'must_exclude_one_ids',
+ 'type',
+ 'fields',
+ 'terms',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_native_by_keyword_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
// try reading the results from cache
$total_results = 0;
@@ -983,7 +1021,7 @@ class fulltext_native extends \phpbb\search\base
}
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
'',
$type,
($firstpost_only) ? 'firstpost' : '',
@@ -996,7 +1034,39 @@ class fulltext_native extends \phpbb\search\base
$post_visibility,
implode(',', $author_ary),
$author_name,
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_native_by_author_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var string type Searching type ('posts', 'topics')
+ * @var boolean firstpost_only Flag indicating if only topic starting posts are considered
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @var string author_name The username to search on
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'type',
+ 'firstpost_only',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ 'author_name',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_native_by_author_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
// try reading the results from cache
$total_results = 0;
diff --git a/phpBB/phpbb/search/fulltext_postgres.php b/phpBB/phpbb/search/fulltext_postgres.php
index 8fe80a39a3..ab28fd2957 100644
--- a/phpBB/phpbb/search/fulltext_postgres.php
+++ b/phpBB/phpbb/search/fulltext_postgres.php
@@ -341,7 +341,7 @@ class fulltext_postgres extends \phpbb\search\base
}
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
implode(', ', $this->split_words),
$type,
$fields,
@@ -352,7 +352,39 @@ class fulltext_postgres extends \phpbb\search\base
implode(',', $ex_fid_ary),
$post_visibility,
implode(',', $author_ary)
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_postgres_by_keyword_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var string type Searching type ('posts', 'topics')
+ * @var string fields Searching fields ('titleonly', 'msgonly', 'firstpost', 'all')
+ * @var string terms Searching terms ('all', 'any')
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'type',
+ 'fields',
+ 'terms',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_by_keyword_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
if ($start < 0)
{
@@ -585,7 +617,7 @@ class fulltext_postgres extends \phpbb\search\base
}
// generate a search_key from all the options to identify the results
- $search_key = md5(implode('#', array(
+ $search_key_array = array(
'',
$type,
($firstpost_only) ? 'firstpost' : '',
@@ -598,7 +630,39 @@ class fulltext_postgres extends \phpbb\search\base
$post_visibility,
implode(',', $author_ary),
$author_name,
- )));
+ );
+
+ /**
+ * Allow changing the search_key for cached results
+ *
+ * @event core.search_postgres_by_author_modify_search_key
+ * @var array search_key_array Array with search parameters to generate the search_key
+ * @var string type Searching type ('posts', 'topics')
+ * @var boolean firstpost_only Flag indicating if only topic starting posts are considered
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @var string author_name The username to search on
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'search_key_array',
+ 'type',
+ 'firstpost_only',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ 'author_name',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_postgres_by_author_modify_search_key', compact($vars)));
+
+ $search_key = md5(implode('#', $search_key_array));
if ($start < 0)
{
diff --git a/phpBB/phpbb/search/fulltext_sphinx.php b/phpBB/phpbb/search/fulltext_sphinx.php
index 937292fd38..372a2792cf 100644
--- a/phpBB/phpbb/search/fulltext_sphinx.php
+++ b/phpBB/phpbb/search/fulltext_sphinx.php
@@ -359,6 +359,23 @@ class fulltext_sphinx
$non_unique = array('sql_query_pre' => true, 'sql_attr_uint' => true, 'sql_attr_timestamp' => true, 'sql_attr_str2ordinal' => true, 'sql_attr_bool' => true);
$delete = array('sql_group_column' => true, 'sql_date_column' => true, 'sql_str2ordinal_column' => true);
+
+ /**
+ * Allow adding/changing the Sphinx configuration data
+ *
+ * @event core.search_sphinx_modify_config_data
+ * @var array config_data Array with the Sphinx configuration data
+ * @var array non_unique Array with the Sphinx non-unique variables to delete
+ * @var array delete Array with the Sphinx variables to delete
+ * @since 3.1.7-RC1
+ */
+ $vars = array(
+ 'config_data',
+ 'non_unique',
+ 'delete',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_modify_config_data', compact($vars)));
+
foreach ($config_data as $section_name => $section_data)
{
$section = $config_object->get_section_by_name($section_name);
@@ -534,6 +551,41 @@ class fulltext_sphinx
$this->sphinx->SetFilter('topic_id', array($topic_id));
}
+ /**
+ * Allow modifying the Sphinx search options
+ *
+ * @event core.search_sphinx_keywords_modify_options
+ * @var string type Searching type ('posts', 'topics')
+ * @var string fields Searching fields ('titleonly', 'msgonly', 'firstpost', 'all')
+ * @var string terms Searching terms ('all', 'any')
+ * @var int sort_days Time, in days, of the oldest possible post to list
+ * @var string sort_key The sort type used from the possible sort types
+ * @var int topic_id Limit the search to this topic_id only
+ * @var array ex_fid_ary Which forums not to search on
+ * @var string post_visibility Post visibility data
+ * @var array author_ary Array of user_id containing the users to filter the results to
+ * @var string author_name The username to search on
+ * @var object sphinx The Sphinx searchd client object
+ * @since 3.1.7-RC1
+ */
+ $sphinx = $this->sphinx;
+ $vars = array(
+ 'type',
+ 'fields',
+ 'terms',
+ 'sort_days',
+ 'sort_key',
+ 'topic_id',
+ 'ex_fid_ary',
+ 'post_visibility',
+ 'author_ary',
+ 'author_name',
+ 'sphinx',
+ );
+ extract($this->phpbb_dispatcher->trigger_event('core.search_sphinx_keywords_modify_options', compact($vars)));
+ $this->sphinx = $sphinx;
+ unset($sphinx);
+
$search_query_prefix = '';
switch ($fields)