diff options
Diffstat (limited to 'phpBB/phpbb/install')
83 files changed, 11885 insertions, 0 deletions
| diff --git a/phpBB/phpbb/install/console/command/install/config/show.php b/phpBB/phpbb/install/console/command/install/config/show.php new file mode 100644 index 0000000000..5d82d8d1ef --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/config/show.php @@ -0,0 +1,131 @@ +<?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\console\command\install\config; + +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class show extends \phpbb\console\command\command +{ +	/** +	 * @var factory +	 */ +	protected $iohandler_factory; + +	/** +	 * @var installer +	 */ +	protected $installer; + +	/** +	 * @var language +	 */ +	protected $language; + +	/** +	 * Constructor +	 * +	 * @param language $language +	 * @param factory $factory +	 * @param installer $installer +	 */ +	public function __construct(language $language, factory $factory, installer $installer) +	{ +		$this->iohandler_factory = $factory; +		$this->installer = $installer; +		$this->language = $language; + +		parent::__construct(new \phpbb\user($language, 'datetime')); +	} + +	/** +	 * +	 * {@inheritdoc} +	 */ +	protected function configure() +	{ +		$this +			->setName('install:config:show') +			->addArgument( +				'config-file', +				InputArgument::REQUIRED, +				$this->language->lang('CLI_CONFIG_FILE')) +			->setDescription($this->language->lang('CLI_INSTALL_SHOW_CONFIG')) +		; +	} + +	/** +	 * Show the validated configuration +	 * +	 * @param InputInterface  $input  An InputInterface instance +	 * @param OutputInterface $output An OutputInterface instance +	 * +	 * @return null +	 */ +	protected function execute(InputInterface $input, OutputInterface $output) +	{ +		$this->iohandler_factory->set_environment('cli'); + +		/** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ +		$iohandler = $this->iohandler_factory->get(); +		$style = new SymfonyStyle($input, $output); +		$iohandler->set_style($style, $output); + +		$config_file = $input->getArgument('config-file'); + +		if (!is_file($config_file)) +		{ +			$iohandler->add_error_message(array('MISSING_FILE', $config_file)); + +			return; +		} + +		try +		{ +			$config = Yaml::parse(file_get_contents($config_file), true, false); +		} +		catch (ParseException $e) +		{ +			$iohandler->add_error_message('INVALID_YAML_FILE'); + +			return; +		} + +		$processor = new Processor(); +		$configuration = new installer_configuration(); + +		try +		{ +			$config = $processor->processConfiguration($configuration, $config); +		} +		catch (Exception $e) +		{ +			$iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + +			return; +		} + +		$iohandler->add_log_message(Yaml::dump(array('installer' => $config), 10, 4, true, false)); +	} +} diff --git a/phpBB/phpbb/install/console/command/install/config/validate.php b/phpBB/phpbb/install/console/command/install/config/validate.php new file mode 100644 index 0000000000..19b6f99a8b --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/config/validate.php @@ -0,0 +1,132 @@ +<?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\console\command\install\config; + +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class validate extends \phpbb\console\command\command +{ +	/** +	 * @var factory +	 */ +	protected $iohandler_factory; + +	/** +	 * @var installer +	 */ +	protected $installer; + +	/** +	 * @var language +	 */ +	protected $language; + +	/** +	 * Constructor +	 * +	 * @param language $language +	 * @param factory $factory +	 * @param installer $installer +	 */ +	public function __construct(language $language, factory $factory, installer $installer) +	{ +		$this->iohandler_factory = $factory; +		$this->installer = $installer; +		$this->language = $language; + +		parent::__construct(new \phpbb\user($language, 'datetime')); +	} + +	/** +	 * +	 * {@inheritdoc} +	 */ +	protected function configure() +	{ +		$this +			->setName('install:config:validate') +			->addArgument( +				'config-file', +				InputArgument::REQUIRED, +				$this->language->lang('CLI_CONFIG_FILE')) +			->setDescription($this->language->lang('CLI_INSTALL_VALIDATE_CONFIG')) +		; +	} + +	/** +	 * Validate the configuration file +	 * +	 * @param InputInterface  $input  An InputInterface instance +	 * @param OutputInterface $output An OutputInterface instance +	 * +	 * @return null +	 */ +	protected function execute(InputInterface $input, OutputInterface $output) +	{ +		$this->iohandler_factory->set_environment('cli'); + +		/** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ +		$iohandler = $this->iohandler_factory->get(); +		$style = new SymfonyStyle($input, $output); +		$iohandler->set_style($style, $output); + +		$config_file = $input->getArgument('config-file'); + +		if (!is_file($config_file)) +		{ +			$iohandler->add_error_message(array('MISSING_FILE', array($config_file))); + +			return 1; +		} + +		try +		{ +			$config = Yaml::parse(file_get_contents($config_file), true, false); +		} +		catch (ParseException $e) +		{ +			$iohandler->add_error_message('INVALID_YAML_FILE'); + +			return 1; +		} + +		$processor = new Processor(); +		$configuration = new installer_configuration(); + +		try +		{ +			$config = $processor->processConfiguration($configuration, $config); +		} +		catch (Exception $e) +		{ +			$iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + +			return 1; +		} + +		$iohandler->add_success_message('CONFIGURATION_VALID'); +		return 0; +	} +} diff --git a/phpBB/phpbb/install/console/command/install/install.php b/phpBB/phpbb/install/console/command/install/install.php new file mode 100644 index 0000000000..d76182af92 --- /dev/null +++ b/phpBB/phpbb/install/console/command/install/install.php @@ -0,0 +1,206 @@ +<?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\console\command\install; + +use phpbb\install\exception\installer_exception; +use phpbb\install\helper\install_helper; +use phpbb\install\helper\iohandler\cli_iohandler; +use phpbb\install\helper\iohandler\factory; +use phpbb\install\installer; +use phpbb\install\installer_configuration; +use phpbb\language\language; +use Symfony\Component\Config\Definition\Exception\Exception; +use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Yaml\Exception\ParseException; +use Symfony\Component\Yaml\Yaml; + +class install extends \phpbb\console\command\command +{ +	/** +	 * @var factory +	 */ +	protected $iohandler_factory; + +	/** +	 * @var installer +	 */ +	protected $installer; + +	/** +	 * @var install_helper +	 */ +	protected $install_helper; + +	/** +	 * @var language +	 */ +	protected $language; + +	/** +	 * Constructor +	 * +	 * @param language			$language +	 * @param factory			$factory +	 * @param installer			$installer +	 * @param install_helper	$install_helper +	 */ +	public function __construct(language $language, factory $factory, installer $installer, install_helper $install_helper) +	{ +		$this->iohandler_factory = $factory; +		$this->installer = $installer; +		$this->language = $language; +		$this->install_helper = $install_helper; + +		parent::__construct(new \phpbb\user($language, 'datetime')); +	} + +	/** +	 * {@inheritdoc} +	 */ +	protected function configure() +	{ +		$this +			->setName('install') +			->addArgument( +				'config-file', +				InputArgument::REQUIRED, +				$this->language->lang('CLI_CONFIG_FILE')) +			->setDescription($this->language->lang('CLI_INSTALL_BOARD')) +		; +	} + +	/** +	 * Executes the command install. +	 * +	 * Install the board +	 * +	 * @param InputInterface  $input  An InputInterface instance +	 * @param OutputInterface $output An OutputInterface instance +	 * +	 * @return null +	 */ +	protected function execute(InputInterface $input, OutputInterface $output) +	{ +		$this->iohandler_factory->set_environment('cli'); + +		/** @var \phpbb\install\helper\iohandler\cli_iohandler $iohandler */ +		$iohandler = $this->iohandler_factory->get(); +		$style = new SymfonyStyle($input, $output); +		$iohandler->set_style($style, $output); + +		$this->installer->set_iohandler($iohandler); + +		$config_file = $input->getArgument('config-file'); + +		if ($this->install_helper->is_phpbb_installed()) +		{ +			$iohandler->add_error_message('PHPBB_ALREADY_INSTALLED'); + +			return 1; +		} + +		if (!is_file($config_file)) +		{ +			$iohandler->add_error_message(array('MISSING_FILE', $config_file)); + +			return 1; +		} + +		try +		{ +			$config = Yaml::parse(file_get_contents($config_file), true, false); +		} +		catch (ParseException $e) +		{ +			$iohandler->add_error_message(array('INVALID_YAML_FILE', $config_file)); + +			return 1; +		} + +		$processor = new Processor(); +		$configuration = new installer_configuration(); + +		try +		{ +			$config = $processor->processConfiguration($configuration, $config); +		} +		catch (Exception $e) +		{ +			$iohandler->add_error_message('INVALID_CONFIGURATION', $e->getMessage()); + +			return 1; +		} + +		$this->register_configuration($iohandler, $config); + +		try +		{ +			$this->installer->run(); +		} +		catch (installer_exception $e) +		{ +			$iohandler->add_error_message($e->getMessage()); +			return 1; +		} +	} + +	/** +	 * Register the configuration to simulate the forms. +	 * +	 * @param cli_iohandler $iohandler +	 * @param array $config +	 */ +	private function register_configuration(cli_iohandler $iohandler, $config) +	{ +		$iohandler->set_input('admin_name', $config['admin']['name']); +		$iohandler->set_input('admin_pass1', $config['admin']['password']); +		$iohandler->set_input('admin_pass2', $config['admin']['password']); +		$iohandler->set_input('board_email', $config['admin']['email']); +		$iohandler->set_input('submit_admin', 'submit'); + +		$iohandler->set_input('default_lang', $config['board']['lang']); +		$iohandler->set_input('board_name', $config['board']['name']); +		$iohandler->set_input('board_description', $config['board']['description']); +		$iohandler->set_input('submit_board', 'submit'); + +		$iohandler->set_input('dbms', $config['database']['dbms']); +		$iohandler->set_input('dbhost', $config['database']['dbhost']); +		$iohandler->set_input('dbport', $config['database']['dbport']); +		$iohandler->set_input('dbuser', $config['database']['dbuser']); +		$iohandler->set_input('dbpasswd', $config['database']['dbpasswd']); +		$iohandler->set_input('dbname', $config['database']['dbname']); +		$iohandler->set_input('table_prefix', $config['database']['table_prefix']); +		$iohandler->set_input('submit_database', 'submit'); + +		$iohandler->set_input('email_enable', $config['email']['enabled']); +		$iohandler->set_input('smtp_delivery', $config['email']['smtp_delivery']); +		$iohandler->set_input('smtp_host', $config['email']['smtp_host']); +		$iohandler->set_input('smtp_auth', $config['email']['smtp_auth']); +		$iohandler->set_input('smtp_user', $config['email']['smtp_user']); +		$iohandler->set_input('smtp_pass', $config['email']['smtp_pass']); +		$iohandler->set_input('submit_email', 'submit'); + +		$iohandler->set_input('cookie_secure', $config['server']['cookie_secure']); +		$iohandler->set_input('server_protocol', $config['server']['server_protocol']); +		$iohandler->set_input('force_server_vars', $config['server']['force_server_vars']); +		$iohandler->set_input('server_name', $config['server']['server_name']); +		$iohandler->set_input('server_port', $config['server']['server_port']); +		$iohandler->set_input('script_path', $config['server']['script_path']); +		$iohandler->set_input('submit_server', 'submit'); +	} +} 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 new file mode 100644 index 0000000000..ed817f7396 --- /dev/null +++ b/phpBB/phpbb/install/controller/helper.php @@ -0,0 +1,417 @@ +<?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\config; +use phpbb\install\helper\navigation\navigation_provider; +use phpbb\language\language; +use phpbb\language\language_file_helper; +use phpbb\path_helper; +use phpbb\request\request; +use phpbb\request\request_interface; +use phpbb\routing\router; +use phpbb\symfony_request; +use phpbb\template\template; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Cookie; + +/** + * A duplicate of \phpbb\controller\helper + * + * This class is necessary because of controller\helper's legacy function calls + * to page_header() page_footer() functions which has unavailable dependencies. + */ +class helper +{ +	/** +	 * @var config +	 */ +	protected $installer_config; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var bool|string +	 */ +	protected $language_cookie; + +	/** +	 * @var \phpbb\language\language_file_helper +	 */ +	protected $lang_helper; + +	/** +	 * @var \phpbb\install\helper\navigation\navigation_provider +	 */ +	protected $navigation_provider; + +	/** +	 * @var \phpbb\template\template +	 */ +	protected $template; + +	/** +	 * @var \phpbb\path_helper +	 */ +	protected $path_helper; + +	/** +	 * @var \phpbb\request\request +	 */ +	protected $phpbb_request; + +	/** +	 * @var \phpbb\symfony_request +	 */ +	protected $request; + +	/** +	 * @var \phpbb\routing\router +	 */ +	protected $router; + +	/** +	 * @var string +	 */ +	protected $phpbb_admin_path; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Constructor +	 * +	 * @param config				$config +	 * @param language				$language +	 * @param language_file_helper	$lang_helper +	 * @param navigation_provider	$nav +	 * @param template				$template +	 * @param path_helper			$path_helper +	 * @param request				$phpbb_request +	 * @param symfony_request		$request +	 * @param router				$router +	 * @param string				$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; +		$this->navigation_provider = $nav; +		$this->template = $template; +		$this->path_helper = $path_helper; +		$this->phpbb_request = $phpbb_request; +		$this->request = $request; +		$this->router = $router; +		$this->phpbb_root_path = $phpbb_root_path; +		$this->phpbb_admin_path = $phpbb_root_path . 'adm/'; +	} + +	/** +	 * Automate setting up the page and creating the response object. +	 * +	 * @param string	$template_file		The template handle to render +	 * @param string	$page_title			The title of the page to output +	 * @param bool		$selected_language	True to enable language selector it, false otherwise +	 * @param int		$status_code		The status code to be sent to the page header +	 * +	 * @return Response object containing rendered page +	 */ +	public function render($template_file, $page_title = '', $selected_language = false, $status_code = 200) +	{ +		$this->page_header($page_title, $selected_language); + +		$this->template->set_filenames(array( +			'body'	=> $template_file, +		)); + +		$response = new Response($this->template->assign_display('body'), $status_code); + +		// Set language cookie +		if ($this->language_cookie !== false) +		{ +			$cookie = new Cookie('lang', $this->language_cookie, time() + 3600); +			$response->headers->setCookie($cookie); + +			$this->language_cookie = false; +		} + +		return $response; +	} + +	/** +	 * Returns path from route name +	 * +	 * @param string	$route_name +	 * +	 * @return string +	 */ +	public function route($route_name) +	{ +		$url = $this->router->generate($route_name); + +		return $url; +	} + +	/** +	 * Handles language selector form +	 */ +	public function handle_language_select() +	{ +		$lang = null; + +		// Check if language form has been submited +		$submit = $this->phpbb_request->variable('change_lang', ''); +		if (!empty($submit)) +		{ +			$lang = $this->phpbb_request->variable('language', ''); + +			if (!empty($lang)) +			{ +				$this->language_cookie = $lang; +			} +		} + +		// Retrieve language from cookie +		$lang_cookie = $this->phpbb_request->variable('lang', '', false, request_interface::COOKIE); +		if (empty($lang) && !empty($lang_cookie)) +		{ +			$lang = $lang_cookie; +			$this->language_cookie = $lang; +		} + +		$lang = (!empty($lang) && strpos($lang, '/') === false) ? $lang : null; + +		$this->render_language_select($lang); + +		if ($lang !== null) +		{ +			$this->language->set_user_language($lang, true); +			$this->installer_config->set('user_language', $lang); +		} +	} + +	/** +	 * 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 +	 * @param bool		$selected_language	True to enable language selector it, false otherwise +	 */ +	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'			=> $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(); +	} + +	/** +	 * Render navigation +	 */ +	protected function render_navigation() +	{ +		// Get navigation items +		$nav_array = $this->navigation_provider->get(); +		$nav_array = $this->sort_navigation_level($nav_array); + +		$active_main_menu = $this->get_active_main_menu($nav_array); + +		// Pass navigation to template +		foreach ($nav_array as $key => $entry) +		{ +			$this->template->assign_block_vars('t_block1', array( +				'L_TITLE' => $this->language->lang($entry['label']), +				'S_SELECTED' => ($active_main_menu === $key), +				'U_TITLE' => $this->route($entry['route']), +			)); + +			if (is_array($entry[0]) && $active_main_menu === $key) +			{ +				$entry[0] = $this->sort_navigation_level($entry[0]); + +				foreach ($entry[0] as $name => $sub_entry) +				{ +					if (isset($sub_entry['stage']) && $sub_entry['stage'] === true) +					{ +						$this->template->assign_block_vars('l_block2', array( +							'L_TITLE' => $this->language->lang($sub_entry['label']), +							'S_SELECTED' => (isset($sub_entry['selected']) && $sub_entry['selected'] === true), +							'S_COMPLETE' => (isset($sub_entry['completed']) && $sub_entry['completed'] === true), +							'STAGE_NAME' => $name, +						)); +					} +					else +					{ +						$this->template->assign_block_vars('l_block1', array( +							'L_TITLE' => $this->language->lang($sub_entry['label']), +							'S_SELECTED' => (isset($sub_entry['route']) && $sub_entry['route'] === $this->request->get('_route')), +							'U_TITLE' => $this->route($sub_entry['route']), +						)); +					} +				} +			} +		} +	} + +	/** +	 * Render language select form +	 * +	 * @param string	$selected_language +	 */ +	protected function render_language_select($selected_language = null) +	{ +		$langs = $this->lang_helper->get_available_languages(); +		foreach ($langs as $lang) +		{ +			$this->template->assign_block_vars('language_select_item', array( +				'VALUE' => $lang['iso'], +				'NAME' => $lang['local_name'], +				'SELECTED' => ($lang['iso'] === $selected_language), +			)); +		} +	} + +	/** +	 * Returns the name of the active main menu item +	 * +	 * @param array	$nav_array +	 * +	 * @return string|bool	Returns the name of the active main menu element, if the element not found, returns false +	 */ +	protected function get_active_main_menu($nav_array) +	{ +		$active_route = $this->request->get('_route'); + +		foreach ($nav_array as $nav_name => $nav_options) +		{ +			$current_menu = $nav_name; + +			if (isset($nav_options['route']) && $nav_options['route'] === $active_route) +			{ +				return $nav_name; +			} + +			if (is_array($nav_options[0])) +			{ +				foreach ($nav_options[0] as $sub_menus) +				{ +					if (isset($sub_menus['route']) && $sub_menus['route'] === $active_route) +					{ +						return $current_menu; +					} +				} +			} +		} + +		return false; +	} + +	/** +	 * Sorts the top level of navigation array +	 * +	 * @param array	$nav_array	Navigation array +	 * +	 * @return array +	 */ +	protected function sort_navigation_level($nav_array) +	{ +		$sorted = array(); +		foreach ($nav_array as $key => $nav) +		{ +			$order = (isset($nav['order'])) ? $nav['order'] : 0; +			$sorted[$order][$key] = $nav; +		} + +		// Linearization of navigation array +		$nav_array = array(); +		ksort($sorted); +		foreach ($sorted as $nav) +		{ +			$nav_array = array_merge($nav_array, $nav); +		} + +		return $nav_array; +	} +} diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php new file mode 100644 index 0000000000..8bf9062b08 --- /dev/null +++ b/phpBB/phpbb/install/controller/install.php @@ -0,0 +1,174 @@ +<?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\install_helper; +use phpbb\install\helper\navigation\navigation_provider; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpFoundation\Response; +use phpbb\install\helper\iohandler\factory; +use phpbb\install\controller\helper; +use phpbb\template\template; +use phpbb\request\request_interface; +use phpbb\install\installer; +use phpbb\language\language; + +/** + * Controller for installing phpBB + */ +class install +{ +	/** +	 * @var helper +	 */ +	protected $controller_helper; + +	/** +	 * @var factory +	 */ +	protected $iohandler_factory; + +	/** +	 * @var navigation_provider +	 */ +	protected $menu_provider; + +	/** +	 * @var language +	 */ +	protected $language; + +	/** +	 * @var template +	 */ +	protected $template; + +	/** +	 * @var request_interface +	 */ +	protected $request; + +	/** +	 * @var installer +	 */ +	protected $installer; + +	/** +	 * @var install_helper +	 */ +	protected $install_helper; + +	/** +	 * Constructor +	 * +	 * @param helper 				$helper +	 * @param factory 				$factory +	 * @param navigation_provider	$nav_provider +	 * @param language				$language +	 * @param template				$template +	 * @param request_interface		$request +	 * @param installer				$installer +	 * @param 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->iohandler_factory	= $factory; +		$this->menu_provider		= $nav_provider; +		$this->language				= $language; +		$this->template				= $template; +		$this->request				= $request; +		$this->installer			= $installer; +		$this->install_helper		= $install_helper; +	} + +	/** +	 * Controller logic +	 * +	 * @return Response|StreamedResponse +	 * +	 * @throws http_exception When phpBB is already installed +	 */ +	public function handle() +	{ +		if ($this->install_helper->is_phpbb_installed()) +		{ +			throw new http_exception(403, 'INSTALL_PHPBB_INSTALLED'); +		} + +		$this->template->assign_vars(array( +			'U_ACTION' => $this->controller_helper->route('phpbb_installer_install'), +		)); + +		// 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()); + +		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'); + +			return $response; +		} +		else +		{ +			// Determine whether the installation was started or not +			if (true) +			{ +				$this->controller_helper->handle_language_select(); + +				// Set active stage +				$this->menu_provider->set_nav_property( +					array('install', 0, 'introduction'), +					array( +						'selected'	=> true, +						'completed'	=> false, +					) +				); + +				// If not, let's render the welcome page +				$this->template->assign_vars(array( +					'SHOW_INSTALL_START_FORM'	=> true, +					'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); +			} + +			// @todo: implement no js controller logic +		} +	} +} diff --git a/phpBB/phpbb/install/controller/installer_index.php b/phpBB/phpbb/install/controller/installer_index.php new file mode 100644 index 0000000000..c2d9572284 --- /dev/null +++ b/phpBB/phpbb/install/controller/installer_index.php @@ -0,0 +1,81 @@ +<?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; + +class installer_index +{ +	/** +	 * @var helper +	 */ +	protected $helper; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var \phpbb\template\template +	 */ +	protected $template; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Constructor +	 * +	 * @param helper 					$helper +	 * @param \phpbb\language\language	$language +	 * @param \phpbb\template\template	$template +	 * @param string					$phpbb_root_path +	 */ +	public function __construct(helper $helper, \phpbb\language\language $language, \phpbb\template\template $template, $phpbb_root_path) +	{ +		$this->helper = $helper; +		$this->language = $language; +		$this->template = $template; +		$this->phpbb_root_path = $phpbb_root_path; +	} + +	public function handle($mode) +	{ +		$this->helper->handle_language_select(); + +		switch ($mode) +		{ +			case "intro": +				$title = $this->language->lang('INTRODUCTION_TITLE'); +				$body = $this->language->lang('INTRODUCTION_BODY'); +			break; +			case "support": +				$title = $this->language->lang('SUPPORT_TITLE'); +				$body = $this->language->lang('SUPPORT_BODY'); +			break; +			case "license": +				$title = $this->language->lang('LICENSE_TITLE'); +				$body = implode("<br/>\n", file($this->phpbb_root_path . 'docs/LICENSE.txt')); +			break; +		} + +		$this->template->assign_vars(array( +			'TITLE'	=> $title, +			'BODY'	=> $body, +		)); + +		return $this->helper->render('installer_main.html', $title, true); +	} +} diff --git a/phpBB/phpbb/install/controller/update.php b/phpBB/phpbb/install/controller/update.php new file mode 100644 index 0000000000..9fff11cae8 --- /dev/null +++ b/phpBB/phpbb/install/controller/update.php @@ -0,0 +1,167 @@ +<?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\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 +	 * +	 * @return Response|StreamedResponse +	 * +	 * @throws http_exception When phpBB is not installed +	 */ +	public function handle() +	{ +		if (!$this->install_helper->is_phpbb_installed()) +		{ +			throw new http_exception(403, 'INSTALL_PHPBB_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/event/kernel_exception_subscriber.php b/phpBB/phpbb/install/event/kernel_exception_subscriber.php new file mode 100644 index 0000000000..c2960cb13c --- /dev/null +++ b/phpBB/phpbb/install/event/kernel_exception_subscriber.php @@ -0,0 +1,125 @@ +<?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\event; + +use phpbb\exception\exception_interface; +use phpbb\install\controller\helper; +use phpbb\language\language; +use phpbb\template\template; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; + +/** + * Exception handler for the installer + */ +class kernel_exception_subscriber implements EventSubscriberInterface +{ +	/** +	 * @var helper +	 */ +	protected $controller_helper; + +	/** +	 * @var language +	 */ +	protected $language; + +	/** +	 * @var template +	 */ +	protected $template; + +	/** +	 * Constructor +	 * +	 * @param helper	$controller_helper +	 * @param language	$language +	 * @param template	$template +	 */ +	public function __construct(helper $controller_helper, language $language, template $template) +	{ +		$this->controller_helper	= $controller_helper; +		$this->language				= $language; +		$this->template				= $template; +	} + +	/** +	 * This listener is run when the KernelEvents::EXCEPTION event is triggered +	 * +	 * @param GetResponseForExceptionEvent	$event +	 */ +	public function on_kernel_exception(GetResponseForExceptionEvent $event) +	{ +		$exception = $event->getException(); +		$message = $exception->getMessage(); + +		if ($exception instanceof exception_interface) +		{ +			$message = $this->language->lang_array($message, $exception->get_parameters()); +		} + +		if (!$event->getRequest()->isXmlHttpRequest()) +		{ +			$this->template->assign_vars(array( +				'TITLE'	=> $this->language->lang('INFORMATION'), +				'BODY'	=> $message, +			)); + +			$response = $this->controller_helper->render( +				'installer_main.html', +				$this->language->lang('INFORMATION'), +				false, +				500 +			); +		} +		else +		{ +			$data = array(); + +			if (!empty($message)) +			{ +				$data['message'] = $message; +			} + +			if (defined('DEBUG')) +			{ +				$data['trace'] = $exception->getTrace(); +			} + +			$response = new JsonResponse($data, 500); +		} + +		if ($exception instanceof HttpExceptionInterface) +		{ +			$response->setStatusCode($exception->getStatusCode()); +			$response->headers->add($exception->getHeaders()); +		} + +		$event->setResponse($response); +	} + +	/** +	 * Returns an array of events the object is subscribed to +	 * +	 * @return array	Array of events the object is subscribed to +	 */ +	static public function getSubscribedEvents() +	{ +		return array( +			KernelEvents::EXCEPTION		=> 'on_kernel_exception', +		); +	} +} diff --git a/phpBB/phpbb/install/exception/cannot_build_container_exception.php b/phpBB/phpbb/install/exception/cannot_build_container_exception.php new file mode 100644 index 0000000000..6cf12b008b --- /dev/null +++ b/phpBB/phpbb/install/exception/cannot_build_container_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 container cannot be built + */ +class cannot_build_container_exception extends installer_exception +{ + +} 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/installer_config_not_writable_exception.php b/phpBB/phpbb/install/exception/installer_config_not_writable_exception.php new file mode 100644 index 0000000000..51864c5dca --- /dev/null +++ b/phpBB/phpbb/install/exception/installer_config_not_writable_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 installer config is not writable to disk + */ +class installer_config_not_writable_exception extends installer_exception +{ + +} diff --git a/phpBB/phpbb/install/exception/installer_exception.php b/phpBB/phpbb/install/exception/installer_exception.php new file mode 100644 index 0000000000..f17dca8f17 --- /dev/null +++ b/phpBB/phpbb/install/exception/installer_exception.php @@ -0,0 +1,24 @@ +<?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; + +use phpbb\exception\runtime_exception; + +/** + * Installer's base exception + */ +class installer_exception extends runtime_exception +{ + +} diff --git a/phpBB/phpbb/install/exception/invalid_dbms_exception.php b/phpBB/phpbb/install/exception/invalid_dbms_exception.php new file mode 100644 index 0000000000..38de5f613a --- /dev/null +++ b/phpBB/phpbb/install/exception/invalid_dbms_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 an unavailable DBMS has been selected + */ +class invalid_dbms_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/exception/resource_limit_reached_exception.php b/phpBB/phpbb/install/exception/resource_limit_reached_exception.php new file mode 100644 index 0000000000..025e09fbd3 --- /dev/null +++ b/phpBB/phpbb/install/exception/resource_limit_reached_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 installer is out of memory or time + */ +class resource_limit_reached_exception extends installer_exception +{ + +} diff --git a/phpBB/phpbb/install/exception/user_interaction_required_exception.php b/phpBB/phpbb/install/exception/user_interaction_required_exception.php new file mode 100644 index 0000000000..d65a448841 --- /dev/null +++ b/phpBB/phpbb/install/exception/user_interaction_required_exception.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\exception; + +/** + * This exception should be thrown when user interaction is inevitable + * + * Note: Please note that the output should already be setup for the user + * 		 when you use throw this exception + */ +class user_interaction_required_exception extends installer_exception +{ + +} diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php new file mode 100644 index 0000000000..0f0840f470 --- /dev/null +++ b/phpBB/phpbb/install/helper/config.php @@ -0,0 +1,438 @@ +<?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; + +use phpbb\install\exception\installer_config_not_writable_exception; + +/** + * Stores common settings and installation status + */ +class config +{ +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * Array which contains config settings for the installer +	 * +	 * The array will also store all the user input, as well as any +	 * data that is passed to other tasks by a task. +	 * +	 * @var array +	 */ +	protected $installer_config; + +	/** +	 * @var string +	 */ +	protected $install_config_file; + +	/** +	 * @var \bantu\IniGetWrapper\IniGetWrapper +	 */ +	protected $php_ini; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Array containing progress information +	 * +	 * @var array +	 */ +	protected $progress_data; + +	/** +	 * Array containing system information +	 * +	 * The array contains run time and memory limitations. +	 * +	 * @var array +	 */ +	protected $system_data; + +	/** +	 * Array containing navigation bar information +	 * +	 * @var array +	 */ +	protected $navigation_data; + +	/** +	 * Flag indicating that config file should be cleaned up +	 * +	 * @var bool +	 */ +	protected $do_clean_up; + +	/** +	 * Constructor +	 */ +	public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, \bantu\IniGetWrapper\IniGetWrapper $php_ini, $phpbb_root_path) +	{ +		$this->filesystem		= $filesystem; +		$this->php_ini			= $php_ini; +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->do_clean_up		= false; + +		// Set up data arrays +		$this->navigation_data	= array(); +		$this->installer_config	= array(); +		$this->system_data		= array(); +		$this->progress_data	= array( +			'last_task_module_name'		=> '', // Stores the service name of the latest finished module +			'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'; + +		$this->setup_system_data(); +	} + +	/** +	 * Returns data for a specified parameter +	 * +	 * @param	string	$param_name	Name of the parameter to return +	 * @param	mixed	$default	Default value to return when the specified data +	 * 								does not exist. +	 * +	 * @return 	mixed	value of the specified parameter or the default value if the data +	 * 					cannot be recovered. +	 */ +	public function get($param_name, $default = false) +	{ +		return (isset($this->installer_config[$param_name])) ? $this->installer_config[$param_name] : $default; +	} + +	/** +	 * Sets a parameter in installer_config +	 * +	 * @param	string	$param_name	Name of the parameter +	 * @param	mixed	$value		Values to set the parameter +	 */ +	public function set($param_name, $value) +	{ +		$this->installer_config = array_merge($this->installer_config, array( +			$param_name => $value, +		)); +	} + +	/** +	 * Returns system parameter +	 * +	 * @param string	$param_name	Name of the parameter +	 * +	 * @return mixed	Returns system parameter if it is defined, false otherwise +	 */ +	public function system_get($param_name) +	{ +		return (isset($this->system_data[$param_name])) ? $this->system_data[$param_name] : false; +	} + +	/** +	 * Returns remaining time until the run time limit +	 * +	 * @return int	Remaining time until the run time limit in seconds +	 */ +	public function get_time_remaining() +	{ +		if ($this->system_data['max_execution_time'] <= 0) +		{ +			return 1; +		} + +		return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time(); +	} + +	/** +	 * Returns remaining memory available for PHP +	 * +	 * @return int	Remaining memory until reaching the limit +	 */ +	public function get_memory_remaining() +	{ +		if ($this->system_data['memory_limit'] <= 0) +		{ +			return 1; +		} + +		if (function_exists('memory_get_usage')) +		{ +			return ($this->system_data['memory_limit'] - memory_get_usage()); +		} + +		// If we cannot get the information then just return a positive number (and cross fingers) +		return 1; +	} + +	/** +	 * Saves the latest executed task +	 * +	 * @param string	$task_service_name	Name of the installer task service +	 */ +	public function set_finished_task($task_service_name) +	{ +		$this->progress_data['last_task_name']	= $task_service_name; +	} + +	/** +	 * Set active module +	 * +	 * @param string	$module_service_name	Name of the installer module service +	 */ +	public function set_active_module($module_service_name) +	{ +		$this->progress_data['last_task_module_name']	= $module_service_name; +	} + +	/** +	 * Getter for progress data +	 * +	 * @return array +	 */ +	public function get_progress_data() +	{ +		return $this->progress_data; +	} + +	/** +	 * Recovers install configuration from file +	 */ +	public function load_config() +	{ +		if (!$this->filesystem->exists($this->install_config_file)) +		{ +			return; +		} + +		$file_content = @file_get_contents($this->install_config_file); +		$serialized_data = trim(substr($file_content, 8)); + +		$this->installer_config = array(); +		$this->progress_data = array(); +		$this->navigation_data = array(); + +		if (!empty($serialized_data)) +		{ +			$unserialized_data = json_decode($serialized_data, true); + +			$this->installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array(); +			$this->progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array(); +			$this->navigation_data = (is_array($unserialized_data['navigation_data'])) ? $unserialized_data['navigation_data'] : array(); +		} +	} + +	/** +	 * 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() +	{ +		if ($this->do_clean_up) +		{ +			@unlink($this->install_config_file); +			return; +		} + +		// Create array to save +		$save_array = array( +			'installer_config'	=> $this->installer_config, +			'progress_data'		=> $this->progress_data, +			'navigation_data'	=> $this->navigation_data, +		); + +		// Create file content +		$file_content = '<?php // '; +		$file_content .= json_encode($save_array); +		$file_content .= "\n"; + +		// Dump file_content to disk +		$fp = @fopen($this->install_config_file, 'w'); +		if (!$fp) +		{ +			throw new installer_config_not_writable_exception(); +		} + +		fwrite($fp, $file_content); +		fclose($fp); +	} + +	/** +	 * Increments the task progress +	 * +	 * @param int	$increment_by	The amount to increment by +	 */ +	public function increment_current_task_progress($increment_by = 1) +	{ +		$this->progress_data['current_task_progress'] += $increment_by; + +		if ($this->progress_data['current_task_progress'] > $this->progress_data['max_task_progress']) +		{ +			$this->progress_data['current_task_progress'] = $this->progress_data['max_task_progress']; +		} +	} + +	/** +	 * Sets the task progress to a specific number +	 * +	 * @param int	$task_progress	The task progress number to be set +	 */ +	public function set_current_task_progress($task_progress) +	{ +		$this->progress_data['current_task_progress'] = $task_progress; +	} + +	/** +	 * Sets the number of tasks belonging to the installer in the current mode. +	 * +	 * @param int	$task_progress_count	Number of tasks +	 */ +	public function set_task_progress_count($task_progress_count) +	{ +		$this->progress_data['max_task_progress'] = $task_progress_count; +	} + +	/** +	 * Returns the number of the current task being executed +	 * +	 * @return int +	 */ +	public function get_current_task_progress() +	{ +		return $this->progress_data['current_task_progress']; +	} + +	/** +	 * Returns the number of tasks belonging to the installer in the current mode. +	 * +	 * @return int +	 */ +	public function get_task_progress_count() +	{ +		return $this->progress_data['max_task_progress']; +	} + +	/** +	 * Marks stage as completed in the navigation bar +	 * +	 * @param array	$nav_path	Array to the navigation elem +	 */ +	public function set_finished_navigation_stage($nav_path) +	{ +		$this->navigation_data['finished'][] = $nav_path; +	} + +	/** +	 * Marks stage as active in the navigation bar +	 * +	 * @param array	$nav_path	Array to the navigation elem +	 */ +	public function set_active_navigation_stage($nav_path) +	{ +		$this->navigation_data['active'] = $nav_path; +	} + +	/** +	 * Returns navigation data +	 * +	 * @return array +	 */ +	public function get_navigation_data() +	{ +		return $this->navigation_data; +	} + +	/** +	 * Removes install config file +	 */ +	public function clean_up_config_file() +	{ +		$this->do_clean_up = true; +		@unlink($this->install_config_file); +	} + +	/** +	 * Filling up system_data array +	 */ +	protected function setup_system_data() +	{ +		// Query maximum runtime from php.ini +		$execution_time = $this->php_ini->getNumeric('max_execution_time'); +		$execution_time = min(15, $execution_time / 2); +		$this->system_data['max_execution_time'] = $execution_time; + +		// Set start time +		$this->system_data['start_time'] = time(); + +		// Get memory limit +		$this->system_data['memory_limit'] = $this->php_ini->getBytes('memory_limit'); +	} +} diff --git a/phpBB/phpbb/install/helper/container_factory.php b/phpBB/phpbb/install/helper/container_factory.php new file mode 100644 index 0000000000..6c1ecd2d02 --- /dev/null +++ b/phpBB/phpbb/install/helper/container_factory.php @@ -0,0 +1,194 @@ +<?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; + +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; + +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * @var \phpbb\request\request +	 */ +	protected $request; + +	/** +	 * @var update_helper +	 */ +	protected $update_helper; + +	/** +	 * The full phpBB container +	 * +	 * @var \Symfony\Component\DependencyInjection\ContainerInterface +	 */ +	protected $container; + +	/** +	 * Constructor +	 * +	 * @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(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; +	} + +	/** +	 * Container getter +	 * +	 * @param null|string	$service_name	Name of the service to return +	 * +	 * @return \Symfony\Component\DependencyInjection\ContainerInterface|Object	phpBB's dependency injection container +	 * 																			or the service specified in $service_name +	 * +	 * @throws \phpbb\install\exception\cannot_build_container_exception							When container cannot be built +	 * @throws \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException			If the service is not defined +	 * @throws \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException	When a circular reference is detected +	 * @throws \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException			When the service is not defined +	 */ +	public function get($service_name = null) +	{ +		// Check if container was built, if not try to build it +		if ($this->container === null) +		{ +			$this->build_container(); +		} + +		return ($service_name === null) ? $this->container : $this->container->get($service_name); +	} + +	/** +	 * Returns the specified parameter from the container +	 * +	 * @param string	$param_name +	 * +	 * @return mixed +	 * +	 * @throws \phpbb\install\exception\cannot_build_container_exception	When container cannot be built +	 */ +	public function get_parameter($param_name) +	{ +		// Check if container was built, if not try to build it +		if ($this->container === null) +		{ +			$this->build_container(); +		} + +		return $this->container->getParameter($param_name); +	} + +	/** +	 * Build dependency injection container +	 * +	 * @throws \phpbb\install\exception\cannot_build_container_exception	When container cannot be built +	 */ +	protected function build_container() +	{ +		// If the container has been already built just return. +		// Although this should never happen +		if ($this->container instanceof \Symfony\Component\DependencyInjection\ContainerInterface) +		{ +			return; +		} + +		// Check whether container can be built +		// We need config.php for that so let's check if it has been set up yet +		if (!filesize($this->phpbb_root_path . 'config.' . $this->php_ext)) +		{ +			throw new cannot_build_container_exception(); +		} + +		$phpbb_config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext); +		$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, $table_prefix; + +		$disable_super_globals = $this->request->super_globals_disabled(); + +		// This is needed because container_builder::get_env_parameters() uses $_SERVER +		if ($disable_super_globals) +		{ +			$this->request->enable_super_globals(); +		} + +		$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(); + +		// Setting request is required for the compatibility globals as those are generated from +		// this container +		$this->container->register('request')->setSynthetic(true); +		$this->container->set('request', $this->request); + +		$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 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 new file mode 100644 index 0000000000..c4c90a01a4 --- /dev/null +++ b/phpBB/phpbb/install/helper/database.php @@ -0,0 +1,456 @@ +<?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; + +use phpbb\install\exception\invalid_dbms_exception; + +/** + * Database related general functionality for installer + */ +class database +{ +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var array +	 */ +	protected $supported_dbms = array( +		// Note: php 5.5 alpha 2 deprecated mysql. +		// Keep mysqli before mysql in this list. +		'mysqli'	=> array( +			'LABEL'			=> 'MySQL with MySQLi Extension', +			'SCHEMA'		=> 'mysql_41', +			'MODULE'		=> 'mysqli', +			'DELIM'			=> ';', +			'DRIVER'		=> 'phpbb\db\driver\mysqli', +			'AVAILABLE'		=> true, +			'2.0.x'			=> true, +		), +		'mysql'		=> array( +			'LABEL'			=> 'MySQL', +			'SCHEMA'		=> 'mysql', +			'MODULE'		=> 'mysql', +			'DELIM'			=> ';', +			'DRIVER'		=> 'phpbb\db\driver\mysql', +			'AVAILABLE'		=> true, +			'2.0.x'			=> true, +		), +		'mssql'		=> array( +			'LABEL'			=> 'MS SQL Server 2000+', +			'SCHEMA'		=> 'mssql', +			'MODULE'		=> 'mssql', +			'DELIM'			=> 'GO', +			'DRIVER'		=> 'phpbb\db\driver\mssql', +			'AVAILABLE'		=> true, +			'2.0.x'			=> true, +		), +		'mssql_odbc'=>	array( +			'LABEL'			=> 'MS SQL Server [ ODBC ]', +			'SCHEMA'		=> 'mssql', +			'MODULE'		=> 'odbc', +			'DELIM'			=> 'GO', +			'DRIVER'		=> 'phpbb\db\driver\mssql_odbc', +			'AVAILABLE'		=> true, +			'2.0.x'			=> true, +		), +		'mssqlnative'		=> array( +			'LABEL'			=> 'MS SQL Server 2005+ [ Native ]', +			'SCHEMA'		=> 'mssql', +			'MODULE'		=> 'sqlsrv', +			'DELIM'			=> 'GO', +			'DRIVER'		=> 'phpbb\db\driver\mssqlnative', +			'AVAILABLE'		=> true, +			'2.0.x'			=> false, +		), +		'oracle'	=>	array( +			'LABEL'			=> 'Oracle', +			'SCHEMA'		=> 'oracle', +			'MODULE'		=> 'oci8', +			'DELIM'			=> '/', +			'DRIVER'		=> 'phpbb\db\driver\oracle', +			'AVAILABLE'		=> true, +			'2.0.x'			=> false, +		), +		'postgres' => array( +			'LABEL'			=> 'PostgreSQL 8.3+', +			'SCHEMA'		=> 'postgres', +			'MODULE'		=> 'pgsql', +			'DELIM'			=> ';', +			'DRIVER'		=> 'phpbb\db\driver\postgres', +			'AVAILABLE'		=> true, +			'2.0.x'			=> true, +		), +		'sqlite'		=> array( +			'LABEL'			=> 'SQLite', +			'SCHEMA'		=> 'sqlite', +			'MODULE'		=> 'sqlite', +			'DELIM'			=> ';', +			'DRIVER'		=> 'phpbb\db\driver\sqlite', +			'AVAILABLE'		=> true, +			'2.0.x'			=> false, +		), +		'sqlite3'		=> array( +			'LABEL'			=> 'SQLite3', +			'SCHEMA'		=> 'sqlite', +			'MODULE'		=> 'sqlite3', +			'DELIM'			=> ';', +			'DRIVER'		=> 'phpbb\db\driver\sqlite3', +			'AVAILABLE'		=> true, +			'2.0.x'			=> false, +		), +	); + +	/** +	 * Constructor +	 * +	 * @param \phpbb\filesystem\filesystem_interface	$filesystem			Filesystem interface +	 * @param string									$phpbb_root_path	Path to phpBB's root +	 */ +	public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) +	{ +		$this->filesystem		= $filesystem; +		$this->phpbb_root_path	= $phpbb_root_path; +	} + +	/** +	 * Returns an array of available DBMS supported by phpBB +	 * +	 * If a DBMS is specified it will only return data for that DBMS +	 * and will load its extension if necessary. +	 * +	 * @param	mixed	$dbms				name of the DBMS that's info is required or false for all DBMS info +	 * @param	bool	$return_unavailable	set it to true if you expect unavailable but supported DBMS +	 * 										returned as well +	 * @param	bool	$only_20x_options	set it to true if you only want to recover 2.0.x options +	 * +	 * @return	array	Array of available and supported DBMS +	 */ +	public function get_available_dbms($dbms = false, $return_unavailable = false, $only_20x_options = false) +	{ +		$available_dbms = $this->supported_dbms; + +		if ($dbms) +		{ +			if (isset($this->supported_dbms[$dbms])) +			{ +				$available_dbms = array($dbms => $this->supported_dbms[$dbms]); +			} +			else +			{ +				return array(); +			} +		} + +		$any_dbms_available = false; +		foreach ($available_dbms as $db_name => $db_array) +		{ +			if ($only_20x_options && !$db_array['2.0.x']) +			{ +				if ($return_unavailable) +				{ +					$available_dbms[$db_name]['AVAILABLE'] = false; +				} +				else +				{ +					unset($available_dbms[$db_name]); +				} + +				continue; +			} + +			$dll = $db_array['MODULE']; +			if (!@extension_loaded($dll)) +			{ +				if ($return_unavailable) +				{ +					$available_dbms[$db_name]['AVAILABLE'] = false; +				} +				else +				{ +					unset($available_dbms[$db_name]); +				} + +				continue; +			} + +			$any_dbms_available = true; +		} + +		if ($return_unavailable) +		{ +			$available_dbms['ANY_DB_SUPPORT'] = $any_dbms_available; +		} + +		return $available_dbms; +	} + +	/** +	 * Removes "/* style" as well as "# style" comments from $input. +	 * +	 * @param string $sql_query	Input string +	 * +	 * @return string Input string with comments removed +	 */ +	public function remove_comments($sql_query) +	{ +		// Remove /* */ comments (http://ostermiller.org/findcomment.html) +		$sql_query = preg_replace('#/\*(.|[\r\n])*?\*/#', "\n", $sql_query); + +		// Remove # style comments +		$sql_query = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql_query)); + +		return $sql_query; +	} + +	/** +	 * split_sql_file() will split an uploaded sql file into single sql statements. +	 * +	 * Note: expects trim() to have already been run on $sql. +	 * +	 * @param	string	$sql		SQL statements +	 * @param	string	$delimiter	Delimiter between sql statements +	 * +	 * @return array Array of sql statements +	 */ +	public function split_sql_file($sql, $delimiter) +	{ +		$sql = str_replace("\r" , '', $sql); +		$data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); + +		$data = array_map('trim', $data); + +		// The empty case +		$end_data = end($data); + +		if (empty($end_data)) +		{ +			unset($data[key($data)]); +		} + +		return $data; +	} + +	/** +	 * Validates table prefix +	 * +	 * @param string	$dbms			The selected dbms +	 * @param string	$table_prefix	The table prefix to validate +	 * +	 * @return bool|array	true if table prefix is valid, array of errors otherwise +	 * +	 * @throws \phpbb\install\exception\invalid_dbms_exception When $dbms is not a valid +	 */ +	public function validate_table_prefix($dbms, $table_prefix) +	{ +		$errors = array(); + +		if (!preg_match('#^[a-zA-Z][a-zA-Z0-9_]*$#', $table_prefix)) +		{ +			$errors[] = array( +				'title' => 'INST_ERR_DB_INVALID_PREFIX', +			); +		} + +		// Do dbms specific checks +		$dbms_info = $this->get_available_dbms($dbms); +		switch ($dbms_info[$dbms]['SCHEMA']) +		{ +			case 'mysql': +			case 'mysql_41': +				$prefix_length = 36; +			break; +			case 'mssql': +				$prefix_length = 90; +			break; +			case 'oracle': +				$prefix_length = 6; +			break; +			case 'postgres': +				$prefix_length = 36; +			break; +			case 'sqlite': +				$prefix_length = 200; +			break; +			default: +				throw new invalid_dbms_exception(); +			break; +		} + +		// Check the prefix length to ensure that index names are not too long +		if (strlen($table_prefix) > $prefix_length) +		{ +			$errors[] = array( +				'title' => array('INST_ERR_PREFIX_TOO_LONG', $prefix_length), +			); +		} + +		return (empty($errors)) ? true : $errors; +	} + +	/** +	 * Check if the user provided database parameters are correct +	 * +	 * This function checks the database connection data and also checks for +	 * any other problems that could cause an error during the installation +	 * such as if there is any database table names conflicting. +	 * +	 * Note: The function assumes that $table_prefix has been already validated +	 * with validate_table_prefix(). +	 * +	 * @param string	$dbms			Selected database type +	 * @param string	$dbhost			Database host address +	 * @param int		$dbport			Database port number +	 * @param string	$dbuser			Database username +	 * @param string	$dbpass			Database password +	 * @param string	$dbname			Database name +	 * @param string	$table_prefix	Database table prefix +	 * +	 * @return array|bool	Returns true if test is successful, array of errors otherwise +	 */ +	public function check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix) +	{ +		$dbms_info = $this->get_available_dbms($dbms); +		$dbms_info = $dbms_info[$dbms]; +		$errors = array(); + +		// Instantiate it and set return on error true +		/** @var \phpbb\db\driver\driver_interface $db */ +		$db = new $dbms_info['DRIVER']; +		$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'), true) && $dbname === '') +		{ +			$errors[] = array( +				'title' => 'INST_ERR_DB_NO_NAME', +			); +		} + +		// Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea +		if ($dbms_info['SCHEMA'] === 'sqlite' +			&& stripos($this->filesystem->realpath($dbhost), $this->filesystem->realpath($this->phpbb_root_path) === 0)) +		{ +			$errors[] = array( +				'title' =>'INST_ERR_DB_FORUM_PATH', +			); +		} + +		// Try to connect to db +		if (is_array($db->sql_connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, false, true))) +		{ +			$db_error = $db->sql_error(); +			$errors[] = array( +				'title' => 'INST_ERR_DB_CONNECT', +				'description' => ($db_error['message']) ? utf8_convert_message($db_error['message']) : 'INST_ERR_DB_NO_ERROR', +			); +		} +		else +		{ +			// Check if there is any table name collisions +			$temp_prefix = strtolower($table_prefix); +			$table_ary = array( +				$temp_prefix . 'attachments', +				$temp_prefix . 'config', +				$temp_prefix . 'sessions', +				$temp_prefix . 'topics', +				$temp_prefix . 'users', +			); + +			$db_tools_factory = new \phpbb\db\tools\factory(); +			$db_tools = $db_tools_factory->get($db); +			$tables = $db_tools->sql_list_tables(); +			$tables = array_map('strtolower', $tables); +			$table_intersect = array_intersect($tables, $table_ary); + +			if (sizeof($table_intersect)) +			{ +				$errors[] = array( +					'title' => 'INST_ERR_PREFIX', +				); +			} + +			// Check if database version is supported +			switch ($dbms) +			{ +				case 'mysqli': +					if (version_compare($db->sql_server_info(true), '4.1.3', '<')) +					{ +						$errors[] = array( +							'title' => 'INST_ERR_DB_NO_MYSQLI', +						); +					} +				break; +				case 'sqlite': +					if (version_compare($db->sql_server_info(true), '2.8.2', '<')) +					{ +						$errors[] = array( +							'title' => 'INST_ERR_DB_NO_SQLITE', +						); +					} +				break; +				case 'sqlite3': +					if (version_compare($db->sql_server_info(true), '3.6.15', '<')) +					{ +						$errors[] = array( +							'title' => 'INST_ERR_DB_NO_SQLITE3', +						); +					} +				break; +				case 'oracle': +					$sql = "SELECT * +						FROM NLS_DATABASE_PARAMETERS +						WHERE PARAMETER = 'NLS_RDBMS_VERSION' +							OR PARAMETER = 'NLS_CHARACTERSET'"; +					$result = $db->sql_query($sql); + +					while ($row = $db->sql_fetchrow($result)) +					{ +						$stats[$row['parameter']] = $row['value']; +					} +					$db->sql_freeresult($result); + +					if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<') && $stats['NLS_CHARACTERSET'] !== 'UTF8') +					{ +						$errors[] = array( +							'title' => 'INST_ERR_DB_NO_ORACLE', +						); +					} +				break; +				case 'postgres': +					$sql = "SHOW server_encoding;"; +					$result = $db->sql_query($sql); +					$row = $db->sql_fetchrow($result); +					$db->sql_freeresult($result); + +					if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8') +					{ +						$errors[] = array( +							'title' => 'INST_ERR_DB_NO_POSTGRES', +						); +					} +				break; +			} +		} + +		return (empty($errors)) ? true : $errors; +	} +} 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/install_helper.php b/phpBB/phpbb/install/helper/install_helper.php new file mode 100644 index 0000000000..ffe36cd645 --- /dev/null +++ b/phpBB/phpbb/install/helper/install_helper.php @@ -0,0 +1,60 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\install\helper; + +/** + * General helper functionality for the installer + */ +class install_helper +{ +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Constructor +	 * +	 * @param string	$phpbb_root_path	path to phpBB's root +	 * @param string	$php_ext			Extension of PHP files +	 */ +	public function __construct($phpbb_root_path, $php_ext) +	{ +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->php_ext			= $php_ext; +	} + +	/** +	 * Check whether phpBB is installed. +	 * +	 * @return bool +	 */ +	public function is_phpbb_installed() +	{ +		$config_path = $this->phpbb_root_path . 'config.' . $this->php_ext; +		$install_lock_path = $this->phpbb_root_path . 'cache/install_lock'; + +		if (file_exists($config_path) && !file_exists($install_lock_path) && filesize($config_path)) +		{ +			return true; +		} + +		return false; +	} +} diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php new file mode 100644 index 0000000000..1342ffa30f --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -0,0 +1,390 @@ +<?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\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; + +	/** +	 * @var \phpbb\template\template +	 */ +	protected $template; + +	/** +	 * @var router +	 */ +	protected $router; + +	/** +	 * @var string +	 */ +	protected $file_status; + +	/** +	 * @var string +	 */ +	protected $form; + +	/** +	 * @var bool +	 */ +	protected $request_client_refresh; + +	/** +	 * @var array +	 */ +	protected $nav_data; + +	/** +	 * @var array +	 */ +	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(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(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_input($name, $default, $multibyte = false) +	{ +		return $this->request->variable($name, $default, $multibyte); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_server_variable($name, $default = '') +	{ +		return $this->request->server($name, $default); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_header_variable($name, $default = '') +	{ +		return $this->request->header($name, $default); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function is_secure() +	{ +		return $this->request->is_secure(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_user_form_group($title, $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'])) +			{ +				continue; +			} + +			$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']); +			$tpl_ary['KEY'] = $input_name; +			$tpl_ary['S_EXPLAIN'] = false; + +			if (isset($input_options['default'])) +			{ +				$default = $input_options['default']; +				$default = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $default); +				$tpl_ary['DEFAULT'] = $default; +			} + +			if (isset($input_options['description'])) +			{ +				$tpl_ary['TITLE_EXPLAIN'] = $this->language->lang($input_options['description']); +				$tpl_ary['S_EXPLAIN'] = true; +			} + +			if (in_array($input_options['type'], array('select', 'radio'), true)) +			{ +				for ($i = 0, $total = sizeof($input_options['options']); $i < $total; $i++) +				{ +					if (isset($input_options['options'][$i]['label'])) +					{ +						$input_options['options'][$i]['label'] = $this->language->lang($input_options['options'][$i]['label']); +					} +				} + +				$tpl_ary['OPTIONS'] = $input_options['options']; +			} + +			$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', +		)); + +		$this->form = $this->template->assign_display('form_install'); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function send_response() +	{ +		$json_data_array = $this->prepare_json_array(); +		$json_data = json_encode($json_data_array); + +		// Try to push content to the browser +		print(str_pad(' ', 4096) . "\n"); +		print($json_data . "\n\n"); +		flush(); +	} + +	/** +	 * Prepares iohandler's data to be sent out to the client. +	 * +	 * @return array +	 */ +	protected function prepare_json_array() +	{ +		$json_array = array( +			'errors' => $this->errors, +			'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)) +		{ +			$json_array['progress'] = array( +				'task_name'		=> $this->current_task_name, +				'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(); +		} + +		if ($this->request_client_refresh) +		{ +			$json_array['refresh'] = true; +			$this->request_client_refresh = false; +		} + +		if (!empty($this->cookies)) +		{ +			$json_array['cookies'] = $this->cookies; +			$this->cookies = array(); +		} + +		return $json_array; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_progress($task_lang_key, $task_number) +	{ +		parent::set_progress($task_lang_key, $task_number); +		$this->send_response(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function request_refresh() +	{ +		$this->request_client_refresh = true; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_active_stage_menu($menu_path) +	{ +		$this->nav_data['active'] = $menu_path[sizeof($menu_path) - 1]; +		$this->send_response(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_finished_stage_menu($menu_path) +	{ +		$this->nav_data['finished'][] = $menu_path[sizeof($menu_path) - 1]; +		$this->send_response(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_cookie($cookie_name, $cookie_value) +	{ +		$this->cookies[] = array( +			'name' => $cookie_name, +			'value' => $cookie_value +		); +	} + +	/** +	 * {@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 +	 * @return string +	 */ +	public function lang_replace_callback($matches) +	{ +		if (!empty($matches[1])) +		{ +			return $this->language->lang($matches[1]); +		} + +		return ''; +	} +} diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php new file mode 100644 index 0000000000..89f3594378 --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -0,0 +1,292 @@ +<?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\iohandler; + +use phpbb\install\exception\installer_exception; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\OutputStyle; + +/** + * Input-Output handler for the CLI frontend + */ +class cli_iohandler extends iohandler_base +{ +	/** +	 * @var OutputInterface +	 */ +	protected $output; + +	/** +	 * @var OutputStyle +	 */ +	protected $io; + +	/** +	 * @var array +	 */ +	protected $input_values = array(); + +	/** +	 * @var \Symfony\Component\Console\Helper\ProgressBar +	 */ +	protected $progress_bar; + +	/** +	 * Set the style and output used to display feedback; +	 * +	 * @param OutputStyle 		$style +	 * @param OutputInterface	$output +	 */ +	public function set_style(OutputStyle $style, OutputInterface $output) +	{ +		$this->io = $style; +		$this->output = $output; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_input($name, $default, $multibyte = false) +	{ +		$result = $default; + +		if (isset($this->input_values[$name])) +		{ +			$result = $this->input_values[$name]; +		} + +		if ($multibyte) +		{ +			return utf8_normalize_nfc($result); +		} + +		return $result; +	} + +	public function set_input($name, $value) +	{ +		$this->input_values[$name] = $value; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_server_variable($name, $default = '') +	{ +		return $default; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_header_variable($name, $default = '') +	{ +		return $default; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function is_secure() +	{ +		return false; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_user_form_group($title, $form) +	{ +		throw new installer_exception('MISSING_DATA'); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function send_response() +	{ +	} + +	/** +	 * {@inheritdoc +	 */ +	public function add_error_message($error_title, $error_description = false) +	{ +		$this->io->newLine(); + +		if (strpos($error_title, '<br />') !== false) +		{ +			$error_title = strip_tags(str_replace('<br />', "\n", $error_title)); +		} +		$message = $this->translate_message($error_title, $error_description); +		$message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : ''); +		$this->io->error($message_string); + +		if ($this->progress_bar !== null) +		{ +			$this->io->newLine(2); +			$this->progress_bar->display(); +		} +	} + +	/** +	 * {@inheritdoc +	 */ +	public function add_warning_message($warning_title, $warning_description = false) +	{ +		$this->io->newLine(); + +		$message = $this->translate_message($warning_title, $warning_description); +		$message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : ''); +		$this->io->warning($message_string); + +		if ($this->progress_bar !== null) +		{ +			$this->io->newLine(2); +			$this->progress_bar->display(); +		} +	} + +	/** +	 * {@inheritdoc +	 */ +	public function add_log_message($log_title, $log_description = false) +	{ +		if ($this->output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) +		{ +			$message = $this->translate_message($log_title, $log_description); +			$this->output->writeln(sprintf('[%3d/%-3d] ---- %s', $this->current_task_progress, $this->task_progress_count, $message['title'])); +		} +	} + +	/** +	 * {@inheritdoc +	 */ +	public function add_success_message($error_title, $error_description = false) +	{ +		$this->io->newLine(); + +		$message = $this->translate_message($error_title, $error_description); +		$message_string = $message['title'] . (!empty($message['description']) ? "\n" . $message['description'] : ''); +		$this->io->success($message_string); + +		if ($this->progress_bar !== null) +		{ +			$this->io->newLine(2); +			$this->progress_bar->display(); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_task_count($task_count, $restart = false) +	{ +		parent::set_task_count($task_count, $restart); + +		if ($this->output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) +		{ +			$this->progress_bar = $this->io->createProgressBar($task_count); +			$this->progress_bar->setFormat( +				"    %current:3s%/%max:-3s% %bar%  %percent:3s%%\n" . +				"             %message%\n"); +			$this->progress_bar->setBarWidth(60); + +			if (!defined('PHP_WINDOWS_VERSION_BUILD')) +			{ +				$this->progress_bar->setEmptyBarCharacter('â–‘'); // light shade character \u2591 +				$this->progress_bar->setProgressCharacter(''); +				$this->progress_bar->setBarCharacter('â–“'); // dark shade character \u2593 +			} + +			$this->progress_bar->setMessage(''); +			$this->io->newLine(2); +			$this->progress_bar->start(); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_progress($task_lang_key, $task_number) +	{ +		parent::set_progress($task_lang_key, $task_number); + +		if ($this->progress_bar !== null) +		{ +			$this->progress_bar->setProgress($this->current_task_progress); +			$this->progress_bar->setMessage($this->current_task_name); +		} +		else +		{ +			$this->output->writeln(sprintf('[%3d/%-3d] %s', $this->current_task_progress, $this->task_progress_count, $this->current_task_name)); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function finish_progress($message_lang_key) +	{ +		parent::finish_progress($message_lang_key); + +		if ($this->progress_bar !== null) +		{ +			$this->progress_bar->finish(); +			$this->progress_bar = null; +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function request_refresh() +	{ +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_active_stage_menu($menu_path) +	{ +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_finished_stage_menu($menu_path) +	{ +	} + +	/** +	 * {@inheritdoc} +	 */ +	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/exception/iohandler_not_implemented_exception.php b/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php new file mode 100644 index 0000000000..f2ddeda6f7 --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/exception/iohandler_not_implemented_exception.php @@ -0,0 +1,19 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\install\helper\iohandler\exception; + +class iohandler_not_implemented_exception extends \Exception +{ + +} diff --git a/phpBB/phpbb/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php new file mode 100644 index 0000000000..52d24e49b2 --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/factory.php @@ -0,0 +1,81 @@ +<?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\iohandler; + +use phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception; + +/** + * Input-output handler factory + */ +class factory +{ +	/** +	 * @var \Symfony\Component\DependencyInjection\ContainerInterface +	 */ +	protected $container; + +	/** +	 * @var string +	 */ +	protected $environment; + +	/** +	 * Constructor +	 * +	 * @param \Symfony\Component\DependencyInjection\ContainerInterface $container Dependency injection container +	 */ +	public function __construct(\Symfony\Component\DependencyInjection\ContainerInterface $container) +	{ +		$this->container	= $container; +		$this->environment	= null; +	} + +	/** +	 * @param string	$environment	The name of the input-output handler to use +	 */ +	public function set_environment($environment) +	{ +		$this->environment = $environment; +	} + +	/** +	 * Factory getter for iohandler +	 * +	 * @return \phpbb\install\helper\iohandler\iohandler_interface +	 * +	 * @throws \phpbb\install\helper\iohandler\exception\iohandler_not_implemented_exception +	 * 		When the specified iohandler_interface does not exists +	 */ +	public function get() +	{ +		switch ($this->environment) +		{ +			case 'ajax': +				return $this->container->get('installer.helper.iohandler_ajax'); +			break; +			case 'nojs': +				// @todo replace this +				return $this->container->get('installer.helper.iohandler_ajax'); +			break; +			case 'cli': +				return $this->container->get('installer.helper.iohandler_cli'); +			break; +			default: +				throw new iohandler_not_implemented_exception(); +			break; +		} + +		throw new iohandler_not_implemented_exception(); +	} +} diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php new file mode 100644 index 0000000000..8dee5390a9 --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php @@ -0,0 +1,196 @@ +<?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\iohandler; + +/** + * Base class for installer input-output handlers + */ +abstract class iohandler_base implements iohandler_interface +{ +	/** +	 * Array of errors +	 * +	 * Errors should be added, when the installation cannot continue without +	 * user interaction. If the aim is to notify the user about something, please +	 * use a warning instead. +	 * +	 * @var array +	 */ +	protected $errors; + +	/** +	 * Array of warnings +	 * +	 * @var array +	 */ +	protected $warnings; + +	/** +	 * Array of logs +	 * +	 * @var array +	 */ +	protected $logs; + +	/** +	 * Array of success messages +	 * +	 * @var array +	 */ +	protected $success; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var int +	 */ +	protected $task_progress_count; + +	/** +	 * @var int +	 */ +	protected $current_task_progress; + +	/** +	 * @var string +	 */ +	protected $current_task_name; + +	/** +	 * Constructor +	 */ +	public function __construct() +	{ +		$this->errors	= array(); +		$this->warnings	= array(); +		$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		= ''; +	} + +	/** +	 * Set language service +	 * +	 * @param \phpbb\language\language $language +	 */ +	public function set_language(\phpbb\language\language $language) +	{ +		$this->language = $language; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_error_message($error_title, $error_description = false) +	{ +		if (strpos($error_title, '<br />') !== false) +		{ +			$error_title = strip_tags(htmlspecialchars_decode($error_title)); +		} +		$this->errors[] = $this->translate_message($error_title, $error_description); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_warning_message($warning_title, $warning_description = false) +	{ +		$this->warnings[] = $this->translate_message($warning_title, $warning_description); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_log_message($log_title, $log_description = false) +	{ +		$this->logs[] = $this->translate_message($log_title, $log_description); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function add_success_message($success_title, $success_description = false) +	{ +		$this->success[] = $this->translate_message($success_title, $success_description); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_task_count($task_count, $restart = false) +	{ +		$this->task_progress_count = $task_count; +		$this->restart_progress_bar = $restart; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function set_progress($task_lang_key, $task_number) +	{ +		$this->current_task_name = ''; + +		if (!empty($task_lang_key)) +		{ +			$this->current_task_name = $this->language->lang($task_lang_key); +		} + +		$this->current_task_progress = $task_number; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function finish_progress($message_lang_key) +	{ +		if (!empty($message_lang_key)) +		{ +			$this->current_task_name = $this->language->lang($message_lang_key); +		} + +		$this->current_task_progress = $this->task_progress_count; +	} + +	/** +	 * Localize message. +	 * +	 * Note: When an array is passed into the parameters below, it will be +	 * resolved as printf($param[0], $param[1], ...). +	 * +	 * @param array|string		$title			Title of the message +	 * @param array|string|bool	$description	Description of the message +	 * +	 * @return array	Localized message in an array +	 */ +	protected function translate_message($title, $description) +	{ +		$message_array = array(); + +		$message_array['title'] = call_user_func_array(array($this->language, 'lang'), (array) $title); + +		if ($description !== false) +		{ +			$message_array['description'] = call_user_func_array(array($this->language, 'lang'), (array) $description); +		} + +		return $message_array; +	} +} diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php new file mode 100644 index 0000000000..00aab3283e --- /dev/null +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php @@ -0,0 +1,191 @@ +<?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\iohandler; + +/** + * Input-Output handler interface for the installer + */ +interface iohandler_interface +{ +	/** +	 * Renders or returns response message +	 */ +	public function send_response(); + +	/** +	 * Returns input variable +	 * +	 * @param string	$name		Name of the input variable to obtain +	 * @param mixed		$default	A default value that is returned if the variable was not set. +	 * 								This function will always return a value of the same type as the default. +	 * @param bool		$multibyte	If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +	 *								Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks +	 * +	 * @return mixed	Value of the input variable +	 */ +	public function get_input($name, $default, $multibyte = false); + +	/** +	 * Returns server variable +	 * +	 * This function should work the same as request_interterface::server(). +	 * +	 * @param string	$name		Name of the server variable +	 * @param mixed		$default	Default value to return when the requested variable does not exist +	 * +	 * @return mixed	Value of the server variable +	 */ +	public function get_server_variable($name, $default = ''); + +	/** +	 * Wrapper function for request_interterface::header() +	 * +	 * @param string	$name		Name of the request header variable +	 * @param mixed		$default	Default value to return when the requested variable does not exist +	 * +	 * @return mixed +	 */ +	public function get_header_variable($name, $default = ''); + +	/** +	 * Returns true if the connection is encrypted +	 * +	 * @return bool +	 */ +	public function is_secure(); + +	/** +	 * Adds an error message to the rendering queue +	 * +	 * Note: When an array is passed into the parameters below, it will be +	 * resolved as printf($param[0], $param[1], ...). +	 * +	 * @param string|array		$error_title		Title of the error message. +	 * @param string|bool|array	$error_description	Description of the error (and possibly guidelines to resolve it), +	 * 												or false if the error description is not available. +	 */ +	public function add_error_message($error_title, $error_description = false); + +	/** +	 * Adds a warning message to the rendering queue +	 * +	 * Note: When an array is passed into the parameters below, it will be +	 * resolved as printf($param[0], $param[1], ...). +	 * +	 * @param string|array		$warning_title			Title of the warning message +	 * @param string|bool|array	$warning_description	Description of the warning (and possibly guidelines to resolve it), +	 * 													or false if the warning description is not available +	 */ +	public function add_warning_message($warning_title, $warning_description = false); + +	/** +	 * Adds a log message to the rendering queue +	 * +	 * Note: When an array is passed into the parameters below, it will be +	 * resolved as printf($param[0], $param[1], ...). +	 * +	 * @param string|array		$log_title			Title of the log message +	 * @param string|bool|array	$log_description	Description of the log, +	 * 												or false if the log description is not available +	 */ +	public function add_log_message($log_title, $log_description = false); + +	/** +	 * Adds a success message to the rendering queue +	 * +	 * Note: When an array is passed into the parameters below, it will be +	 * resolved as printf($param[0], $param[1], ...). +	 * +	 * @param string|array		$success_title			Title of the success message +	 * @param string|bool|array	$success_description	Description of the success, +	 * 													or false if the success description is not available +	 * +	 * @return null +	 */ +	public function add_success_message($success_title, $success_description = false); + +	/** +	 * Adds a requested data group to the rendering queue +	 * +	 * @param string	$title	Language variable with the title of the form +	 * @param array		$form	An array describing the required data (options etc) +	 */ +	public function add_user_form_group($title, $form); + +	/** +	 * 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, $restart = false); + +	/** +	 * Sets the progress information +	 * +	 * @param string	$task_lang_key	Language key for the name of the task +	 * @param int		$task_number	Position of the current task in the task queue +	 */ +	public function set_progress($task_lang_key, $task_number); + +	/** +	 * Sends refresh request to the client +	 */ +	public function request_refresh(); + +	/** +	 * Marks stage as active in the navigation bar +	 * +	 * @param array	$menu_path	Array to the navigation elem +	 */ +	public function set_active_stage_menu($menu_path); + +	/** +	 * Marks stage as completed in the navigation bar +	 * +	 * @param array	$menu_path	Array to the navigation elem +	 */ +	public function set_finished_stage_menu($menu_path); + +	/** +	 * Finish the progress bar +	 * +	 * @param string	$message_lang_key	Language key for the message +	 */ +	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 +	 * @param string	$cookie_value	Value of the cookie to set +	 */ +	public function set_cookie($cookie_name, $cookie_value); +} diff --git a/phpBB/phpbb/install/helper/navigation/install_navigation.php b/phpBB/phpbb/install/helper/navigation/install_navigation.php new file mode 100644 index 0000000000..f690f8de76 --- /dev/null +++ b/phpBB/phpbb/install/helper/navigation/install_navigation.php @@ -0,0 +1,75 @@ +<?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 install_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( +			'install'	=> array( +				'label'	=> 'INSTALL', +				'route'	=> 'phpbb_installer_install', +				'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, +					), +					'install'	=> array( +						'label'	=> 'STAGE_INSTALL', +						'stage'	=> true, +						'order'	=> 3, +					), +				), +			), +		); +	} +} diff --git a/phpBB/phpbb/install/helper/navigation/main_navigation.php b/phpBB/phpbb/install/helper/navigation/main_navigation.php new file mode 100644 index 0000000000..214bb04963 --- /dev/null +++ b/phpBB/phpbb/install/helper/navigation/main_navigation.php @@ -0,0 +1,48 @@ +<?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; + +class main_navigation implements navigation_interface +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get() +	{ +		return array( +			'overview'	=> array( +				'label'	=> 'MENU_OVERVIEW', +				'route'	=> 'phpbb_installer_index', +				'order'	=> 0, +				array( +					'introduction'	=> array( +						'label'	=> 'MENU_INTRO', +						'route'	=> 'phpbb_installer_index', +						'order'	=> 0, +					), +					'support'	=> array( +						'label'	=> 'MENU_SUPPORT', +						'route'	=> 'phpbb_installer_support', +						'order'	=> 1, +					), +					'license'	=> array( +						'label'	=> 'MENU_LICENSE', +						'route'	=> 'phpbb_installer_license', +						'order'	=> 2, +					), +				), +			), +		); +	} +} diff --git a/phpBB/phpbb/install/helper/navigation/navigation_interface.php b/phpBB/phpbb/install/helper/navigation/navigation_interface.php new file mode 100644 index 0000000000..eebdbe923f --- /dev/null +++ b/phpBB/phpbb/install/helper/navigation/navigation_interface.php @@ -0,0 +1,43 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\install\helper\navigation; + +/** + * Interface for installer's navigation defining services + */ +interface navigation_interface +{ +	/** +	 * Returns an array with the navigation items +	 * +	 * The returned array should have the following format: +	 * <code> +	 * array( +	 * 	'parent_nav_name' => array( +	 * 		'nav_name' => array( +	 * 			'label' => 'MY_MENU', +	 * 			'route' => 'phpbb_route_name', +	 * 		) +	 * 	) +	 * ) +	 * </code> +	 * +	 * Navigation item setting options: +	 * 	- label: The language variable name +	 * 	- route: Name of the route which it is belongs to +	 * +	 * @return array +	 */ +	public function get(); +} diff --git a/phpBB/phpbb/install/helper/navigation/navigation_provider.php b/phpBB/phpbb/install/helper/navigation/navigation_provider.php new file mode 100644 index 0000000000..d52aec8999 --- /dev/null +++ b/phpBB/phpbb/install/helper/navigation/navigation_provider.php @@ -0,0 +1,121 @@ +<?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\di\service_collection; + +/** + * Installers navigation provider + */ +class navigation_provider +{ +	/** +	 * @var array +	 */ +	private $menu_collection; + +	/** +	 * Constructor +	 * +	 * @param service_collection		$plugins +	 */ +	public function __construct(service_collection $plugins) +	{ +		$this->menu_collection	= array(); + +		foreach ($plugins as $plugin => $plugin_instance) +		{ +			$this->register($plugin_instance); +		} +	} + +	/** +	 * Returns navigation array +	 * +	 * @return array +	 */ +	public function get() +	{ +		return $this->menu_collection; +	} + +	/** +	 * Registers a navigation provider's navigation items +	 * +	 * @param navigation_interface	$navigation +	 */ +	public function register(navigation_interface $navigation) +	{ +		$nav_arry = $navigation->get(); +		$this->menu_collection = $this->merge($nav_arry, $this->menu_collection); +	} + +	/** +	 * Set a property in the navigation array +	 * +	 * @param array	$nav_element	Array to the navigation elem +	 * @param array	$property_array	Array with the properties to set +	 */ +	public function set_nav_property($nav_element, $property_array) +	{ +		$array_pointer = array(); +		$array_root_pointer = &$array_pointer; +		foreach ($nav_element as $array_path) +		{ +			$array_pointer[$array_path] = array(); +			$array_pointer = &$array_pointer[$array_path]; +		} + +		$array_pointer = $property_array; + +		$this->menu_collection = $this->merge($array_root_pointer, $this->menu_collection); +	} + +	/** +	 * Recursive array merge +	 * +	 * This function is necessary to be able to replace the options of +	 * already set navigation items. +	 * +	 * @param array	$array_to_merge +	 * @param array	$array_to_merge_into +	 * +	 * @return array	Merged array +	 */ +	private function merge($array_to_merge, $array_to_merge_into) +	{ +		$merged_array = $array_to_merge_into; + +		foreach ($array_to_merge as $key => $value) +		{ +			if (isset($array_to_merge_into[$key])) +			{ +				if (is_array($array_to_merge_into[$key]) && is_array($value)) +				{ +					$merged_array[$key] = $this->merge($value, $array_to_merge_into[$key]); +				} +				else +				{ +					$merged_array[$key] = $value; +				} +			} +			else +			{ +				$merged_array[$key] = $value; +			} +		} + +		return $merged_array; +	} +} 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 new file mode 100644 index 0000000000..a41b4cd6a6 --- /dev/null +++ b/phpBB/phpbb/install/installer.php @@ -0,0 +1,275 @@ +<?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; + +use phpbb\cache\driver\driver_interface; +use phpbb\di\ordered_service_collection; +use phpbb\install\exception\installer_config_not_writable_exception; +use phpbb\install\exception\jump_to_restart_point_exception; +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 +{ +	/** +	 * @var driver_interface +	 */ +	protected $cache; + +	/** +	 * @var config +	 */ +	protected $install_config; + +	/** +	 * @var array +	 */ +	protected $installer_modules; + +	/** +	 * @var iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var string +	 */ +	protected $web_root; + +	/** +	 * Stores the number of steps that a given module has +	 * +	 * @var array +	 */ +	protected $module_step_count; + +	/** +	 * Constructor +	 * +	 * @param driver_interface	$cache			Cache service +	 * @param config			$config			Installer config handler +	 * @param path_helper		$path_helper	Path helper +	 */ +	public function __construct(driver_interface $cache, config $config, path_helper $path_helper) +	{ +		$this->cache				= $cache; +		$this->install_config		= $config; +		$this->installer_modules	= null; +		$this->web_root				= $path_helper->get_web_root_path(); +	} + +	/** +	 * Sets modules to execute +	 * +	 * Note: The installer will run modules in the order they are set in +	 * the array. +	 * +	 * @param ordered_service_collection	$modules	Service collection of module service names +	 */ +	public function set_modules(ordered_service_collection $modules) +	{ +		$this->installer_modules = $modules; +	} + +	/** +	 * Sets input-output handler objects +	 * +	 * @param iohandler_interface	$iohandler +	 */ +	public function set_iohandler(iohandler_interface $iohandler) +	{ +		$this->iohandler = $iohandler; +	} + +	/** +	 * Run phpBB installer +	 */ +	public function run() +	{ +		// Load install progress +		$this->install_config->load_config(); + +		// Recover install progress +		$module_name = $this->recover_progress(); +		$module_found = false; + +		// 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')); +		$this->iohandler->set_finished_stage_menu(array('install', 0, 'introduction')); + +		if ($this->install_config->get_task_progress_count() === 0) +		{ +			// Count all tasks in the current installer modules +			$step_count = 0; + +			/** @var \phpbb\install\module_interface $module */ +			foreach ($this->installer_modules as $name => $module) +			{ +				$module_step_count = $module->get_step_count(); +				$step_count += $module_step_count; +				$this->module_step_count[$name] = $module_step_count; +			} + +			// Set task count +			$this->install_config->set_task_progress_count($step_count); +		} + +		// Set up progress information +		$this->iohandler->set_task_count( +			$this->install_config->get_task_progress_count() +		); + +		try +		{ +			foreach ($this->installer_modules as $name => $module) +			{ +				// Skip forward until the current task is reached +				if (!$module_found) +				{ +					if ($module_name === $name || empty($module_name)) +					{ +						$module_found = true; +					} +					else +					{ +						continue; +					} +				} + +				// Log progress +				$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) +				{ +					throw new resource_limit_reached_exception(); +				} + +				// Check if module should be executed +				if (!$module->is_essential() && !$module->check_requirements()) +				{ +					$this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); +					$this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); + +					$this->iohandler->add_log_message(array( +						'SKIP_MODULE', +						$name, +					)); +					$this->install_config->increment_current_task_progress($this->module_step_count[$name]); +					continue; +				} + +				// Set the correct stage in the navigation bar +				$this->install_config->set_active_navigation_stage($module->get_navigation_stage_path()); +				$this->iohandler->set_active_stage_menu($module->get_navigation_stage_path()); + +				$module->run(); + +				$this->install_config->set_finished_navigation_stage($module->get_navigation_stage_path()); +				$this->iohandler->set_finished_stage_menu($module->get_navigation_stage_path()); +			} + +			// Installation finished +			$install_finished = true; + +			if ($this->iohandler instanceof cli_iohandler) +			{ +				$this->iohandler->add_success_message('INSTALLER_FINISHED'); +			} +			else +			{ +				global $SID; +				$acp_url = $this->web_root . 'adm/index.php' . $SID; +				$this->iohandler->add_success_message('INSTALLER_FINISHED', array( +					'ACP_LINK', +					$acp_url, +				)); +			} +		} +		catch (user_interaction_required_exception $e) +		{ +			// Do nothing +		} +		catch (resource_limit_reached_exception $e) +		{ +			$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) +		{ +			$this->iohandler->add_error_message($e->getMessage()); +			$this->iohandler->send_response(); +			$fail_cleanup = true; +		} + +		if ($install_finished) +		{ +			// Send install finished message +			$this->iohandler->set_progress('INSTALLER_FINISHED', $this->install_config->get_task_progress_count()); +		} +		else if ($send_refresh) +		{ +			$this->iohandler->request_refresh(); +			$this->iohandler->send_response(); +		} + +		// Save install progress +		try +		{ +			if ($install_finished || $fail_cleanup) +			{ +				$this->install_config->clean_up_config_file(); +				$this->cache->purge(); +			} +			else +			{ +				$this->install_config->save_config(); +			} +		} +		catch (installer_config_not_writable_exception $e) +		{ +			// It is allowed to fail this test during requirements testing +			$progress_data = $this->install_config->get_progress_data(); + +			if ($progress_data['last_task_module_name'] !== 'installer.module.requirements_install') +			{ +				$this->iohandler->add_error_message('INSTALLER_CONFIG_NOT_WRITABLE'); +			} +		} +	} + +	/** +	 * Recover install progress +	 * +	 * @return string	Index of the next installer module to execute +	 */ +	protected function recover_progress() +	{ +		$progress_array = $this->install_config->get_progress_data(); +		return $progress_array['last_task_module_name']; +	} +} diff --git a/phpBB/phpbb/install/installer_configuration.php b/phpBB/phpbb/install/installer_configuration.php new file mode 100644 index 0000000000..ab02da8686 --- /dev/null +++ b/phpBB/phpbb/install/installer_configuration.php @@ -0,0 +1,140 @@ +<?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; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +class installer_configuration implements ConfigurationInterface +{ + +	/** +	 * Generates the configuration tree builder. +	 * +	 * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder +	 */ +	public function getConfigTreeBuilder() +	{ +		$treeBuilder = new TreeBuilder(); +		$rootNode = $treeBuilder->root('installer'); +		$rootNode +			->children() +				->arrayNode('admin') +					->children() +						->scalarNode('name')->defaultValue('admin')->cannotBeEmpty()->end() +						->scalarNode('password')->defaultValue('adminadmin')->cannotBeEmpty()->end() +						->scalarNode('email')->defaultValue('admin@example.org')->cannotBeEmpty()->end() +					->end() +				->end() +				->arrayNode('board') +					->children() +						->scalarNode('lang') +							->defaultValue('en') +							->cannotBeEmpty() +							->end() +						->scalarNode('name') +							->defaultValue('My Board') +							->cannotBeEmpty() +							->end() +						->scalarNode('description') +						->defaultValue('My amazing new phpBB board') +						->cannotBeEmpty() +						->end() +					->end() +				->end() +				->arrayNode('database') +					->children() +						->scalarNode('dbms') +							->defaultValue('sqlite3') +							->cannotBeEmpty() +							->isRequired() +							->end() +						->scalarNode('dbhost') +							->defaultValue(null) +							->end() +						->scalarNode('dbport') +							->defaultValue(null) +							->end() +						->scalarNode('dbuser') +							->defaultValue(null) +							->end() +						->scalarNode('dbpasswd') +							->defaultValue(null) +							->end() +						->scalarNode('dbname') +							->defaultValue(null) +							->end() +						->scalarNode('table_prefix') +							->defaultValue('phpbb_') +							->cannotBeEmpty() +							->isRequired() +							->end() +					->end() +				->end() +				->arrayNode('email') +					->canBeEnabled() +					->addDefaultsIfNotSet() +					->children() +						->booleanNode('smtp_delivery') +							->defaultValue(false) +							->treatNullLike(false) +							->end() +						->scalarNode('smtp_host') +							->defaultValue(null) +							->end() +						->scalarNode('smtp_auth') +							->defaultValue(null) +							->end() +						->scalarNode('smtp_user') +							->defaultValue(null) +							->end() +						->scalarNode('smtp_pass') +							->defaultValue(null) +							->end() +					->end() +				->end() +				->arrayNode('server') +					->children() +						->booleanNode('cookie_secure') +							->defaultValue(false) +							->treatNullLike(false) +							->end() +						->scalarNode('server_protocol') +							->defaultValue('http://') +							->cannotBeEmpty() +							->end() +						->booleanNode('force_server_vars') +							->defaultValue(false) +							->treatNullLike(false) +							->end() +						->scalarNode('server_name') +							->defaultValue('localhost') +							->cannotBeEmpty() +							->end() +						->integerNode('server_port') +							->defaultValue(80) +							->min(1) +							->cannotBeEmpty() +							->end() +						->scalarNode('script_path') +							->defaultValue('/') +							->cannotBeEmpty() +							 ->end() +					->end() +				->end() +			->end() +		; +		return $treeBuilder; +	} +} diff --git a/phpBB/phpbb/install/module/install_data/module.php b/phpBB/phpbb/install/module/install_data/module.php new file mode 100644 index 0000000000..77f1f73f1f --- /dev/null +++ b/phpBB/phpbb/install/module/install_data/module.php @@ -0,0 +1,28 @@ +<?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\install_data; + +/** + * Installer module for recovering and installing default data installation + */ +class module extends \phpbb\install\module_base +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get_navigation_stage_path() +	{ +		return array('install', 0, 'install'); +	} +} diff --git a/phpBB/phpbb/install/module/install_data/task/add_bots.php b/phpBB/phpbb/install/module/install_data/task/add_bots.php new file mode 100644 index 0000000000..2ee641ff63 --- /dev/null +++ b/phpBB/phpbb/install/module/install_data/task/add_bots.php @@ -0,0 +1,242 @@ +<?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\install_data\task; + +class add_bots extends \phpbb\install\task_base +{ +	/** +	 * A list of the web-crawlers/bots we recognise by default +	 * +	 * Candidates but not included: +	 * 'Accoona [Bot]'				'Accoona-AI-Agent/' +	 * 'ASPseek [Crawler]'			'ASPseek/' +	 * 'Boitho [Crawler]'			'boitho.com-dc/' +	 * 'Bunnybot [Bot]'				'powered by www.buncat.de' +	 * 'Cosmix [Bot]'				'cfetch/' +	 * 'Crawler Search [Crawler]'	'.Crawler-Search.de' +	 * 'Findexa [Crawler]'			'Findexa Crawler (' +	 * 'GBSpider [Spider]'			'GBSpider v' +	 * 'genie [Bot]'				'genieBot (' +	 * 'Hogsearch [Bot]'			'oegp v. 1.3.0' +	 * 'Insuranco [Bot]'			'InsurancoBot' +	 * 'IRLbot [Bot]'				'http://irl.cs.tamu.edu/crawler' +	 * 'ISC Systems [Bot]'			'ISC Systems iRc Search' +	 * 'Jyxobot [Bot]'				'Jyxobot/' +	 * 'Kraehe [Metasuche]'			'-DIE-KRAEHE- META-SEARCH-ENGINE/' +	 * 'LinkWalker'					'LinkWalker' +	 * 'MMSBot [Bot]'				'http://www.mmsweb.at/bot.html' +	 * 'Naver [Bot]'				'nhnbot@naver.com)' +	 * 'NetResearchServer'			'NetResearchServer/' +	 * 'Nimble [Crawler]'			'NimbleCrawler' +	 * 'Ocelli [Bot]'				'Ocelli/' +	 * 'Onsearch [Bot]'				'onCHECK-Robot' +	 * 'Orange [Spider]'			'OrangeSpider' +	 * 'Sproose [Bot]'				'http://www.sproose.com/bot' +	 * 'Susie [Sync]'				'!Susie (http://www.sync2it.com/susie)' +	 * 'Tbot [Bot]'					'Tbot/' +	 * 'Thumbshots [Capture]'		'thumbshots-de-Bot' +	 * 'Vagabondo [Crawler]'		'http://webagent.wise-guys.nl/' +	 * 'Walhello [Bot]'				'appie 1.1 (www.walhello.com)' +	 * 'WissenOnline [Bot]'			'WissenOnline-Bot' +	 * 'WWWeasel [Bot]'				'WWWeasel Robot v' +	 * 'Xaldon [Spider]'			'Xaldon WebSpider' +	 * +	 * @var array +	 */ +	protected $bot_list = array( +		'AdsBot [Google]'			=> array('AdsBot-Google', ''), +		'Alexa [Bot]'				=> array('ia_archiver', ''), +		'Alta Vista [Bot]'			=> array('Scooter/', ''), +		'Ask Jeeves [Bot]'			=> array('Ask Jeeves', ''), +		'Baidu [Spider]'			=> array('Baiduspider', ''), +		'Bing [Bot]'				=> array('bingbot/', ''), +		'Exabot [Bot]'				=> array('Exabot', ''), +		'FAST Enterprise [Crawler]'	=> array('FAST Enterprise Crawler', ''), +		'FAST WebCrawler [Crawler]'	=> array('FAST-WebCrawler/', ''), +		'Francis [Bot]'				=> array('http://www.neomo.de/', ''), +		'Gigabot [Bot]'				=> array('Gigabot/', ''), +		'Google Adsense [Bot]'		=> array('Mediapartners-Google', ''), +		'Google Desktop'			=> array('Google Desktop', ''), +		'Google Feedfetcher'		=> array('Feedfetcher-Google', ''), +		'Google [Bot]'				=> array('Googlebot', ''), +		'Heise IT-Markt [Crawler]'	=> array('heise-IT-Markt-Crawler', ''), +		'Heritrix [Crawler]'		=> array('heritrix/1.', ''), +		'IBM Research [Bot]'		=> array('ibm.com/cs/crawler', ''), +		'ICCrawler - ICjobs'		=> array('ICCrawler - ICjobs', ''), +		'ichiro [Crawler]'			=> array('ichiro/', ''), +		'Majestic-12 [Bot]'			=> array('MJ12bot/', ''), +		'Metager [Bot]'				=> array('MetagerBot/', ''), +		'MSN NewsBlogs'				=> array('msnbot-NewsBlogs/', ''), +		'MSN [Bot]'					=> array('msnbot/', ''), +		'MSNbot Media'				=> array('msnbot-media/', ''), +		'Nutch [Bot]'				=> array('http://lucene.apache.org/nutch/', ''), +		'Online link [Validator]'	=> array('online link validator', ''), +		'psbot [Picsearch]'			=> array('psbot/0', ''), +		'Sensis [Crawler]'			=> array('Sensis Web Crawler', ''), +		'SEO Crawler'				=> array('SEO search Crawler/', ''), +		'Seoma [Crawler]'			=> array('Seoma [SEO Crawler]', ''), +		'SEOSearch [Crawler]'		=> array('SEOsearch/', ''), +		'Snappy [Bot]'				=> array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), +		'Steeler [Crawler]'			=> array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), +		'Telekom [Bot]'				=> array('crawleradmin.t-info@telekom.de', ''), +		'TurnitinBot [Bot]'			=> array('TurnitinBot/', ''), +		'Voyager [Bot]'				=> array('voyager/', ''), +		'W3 [Sitesearch]'			=> array('W3 SiteSearch Crawler', ''), +		'W3C [Linkcheck]'			=> array('W3C-checklink/', ''), +		'W3C [Validator]'			=> array('W3C_Validator', ''), +		'YaCy [Bot]'				=> array('yacybot', ''), +		'Yahoo MMCrawler [Bot]'		=> array('Yahoo-MMCrawler/', ''), +		'Yahoo Slurp [Bot]'			=> array('Yahoo! DE Slurp', ''), +		'Yahoo [Bot]'				=> array('Yahoo! Slurp', ''), +		'YahooSeeker [Bot]'			=> array('YahooSeeker/', ''), +	); + +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$install_config		Installer's config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler			Input-output handler for the installer +	 * @param \phpbb\install\helper\container_factory				$container			Installer's DI container +	 * @param \phpbb\language\language								$language			Language provider +	 * @param string												$phpbb_root_path	Relative path to phpBB root +	 * @param string												$php_ext			PHP extension +	 */ +	public function __construct(\phpbb\install\helper\config $install_config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\install\helper\container_factory $container, +								\phpbb\language\language $language, +								$phpbb_root_path, +								$php_ext) +	{ +		parent::__construct(true); + +		$this->db				= $container->get('dbal.conn'); +		$this->install_config	= $install_config; +		$this->io_handler		= $iohandler; +		$this->language			= $language; +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->php_ext			= $php_ext; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$sql = 'SELECT group_id +			FROM ' . GROUPS_TABLE . " +			WHERE group_name = 'BOTS'"; +		$result = $this->db->sql_query($sql); +		$group_id = (int) $this->db->sql_fetchfield('group_id'); +		$this->db->sql_freeresult($result); + +		if (!$group_id) +		{ +			// If we reach this point then something has gone very wrong +			$this->io_handler->add_error_message('NO_GROUP'); +		} + +		foreach ($this->bot_list as $bot_name => $bot_ary) +		{ +			$user_row = array( +				'user_type'				=> USER_IGNORE, +				'group_id'				=> $group_id, +				'username'				=> $bot_name, +				'user_regdate'			=> time(), +				'user_password'			=> '', +				'user_colour'			=> '9E8DA7', +				'user_email'			=> '', +				'user_lang'				=> $this->install_config->get('default_lang'), +				'user_style'			=> 1, +				'user_timezone'			=> 'UTC', +				'user_dateformat'		=> $this->language->lang('default_dateformat'), +				'user_allow_massemail'	=> 0, +				'user_allow_pm'			=> 0, +			); + +			if (!function_exists('user_add')) +			{ +				include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext); +			} + +			$user_id = user_add($user_row); + +			if (!$user_id) +			{ +				// If we can't insert this user then continue to the next one to avoid inconsistent data +				$this->io_handler->add_error_message('CONV_ERROR_INSERT_BOT'); + +				continue; +			} + +			$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array( +				'bot_active'	=> 1, +				'bot_name'		=> (string) $bot_name, +				'user_id'		=> (int) $user_id, +				'bot_agent'		=> (string) $bot_ary[0], +				'bot_ip'		=> (string) $bot_ary[1], +			)); + +			$this->db->sql_query($sql); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_ADD_BOTS'; +	} +} diff --git a/phpBB/phpbb/install/module/install_data/task/add_languages.php b/phpBB/phpbb/install/module/install_data/task/add_languages.php new file mode 100644 index 0000000000..7ffdf4f276 --- /dev/null +++ b/phpBB/phpbb/install/module/install_data/task/add_languages.php @@ -0,0 +1,121 @@ +<?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\install_data\task; + +class add_languages extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var \phpbb\language\language_file_helper +	 */ +	protected $language_helper; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler			Installer's input-output handler +	 * @param \phpbb\install\helper\container_factory				$container			Installer's DI container +	 * @param \phpbb\language\language_file_helper					$language_helper	Language file helper service +	 */ +	public function __construct(\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\install\helper\container_factory $container, +								\phpbb\language\language_file_helper $language_helper) +	{ +		$this->db				= $container->get('dbal.conn'); +		$this->iohandler		= $iohandler; +		$this->language_helper	= $language_helper; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$languages = $this->language_helper->get_available_languages(); +		$installed_languages = array(); + +		foreach ($languages as $lang_info) +		{ +			$lang_pack = array( +				'lang_iso'			=> $lang_info['iso'], +				'lang_dir'			=> $lang_info['iso'], +				'lang_english_name'	=> htmlspecialchars($lang_info['name']), +				'lang_local_name'	=> htmlspecialchars($lang_info['local_name'], ENT_COMPAT, 'UTF-8'), +				'lang_author'		=> htmlspecialchars($lang_info['author'], ENT_COMPAT, 'UTF-8'), +			); + +			$this->db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $this->db->sql_build_array('INSERT', $lang_pack)); + +			$installed_languages[] = (int) $this->db->sql_nextid(); +			if ($this->db->get_sql_error_triggered()) +			{ +				$error = $this->db->sql_error($this->db->get_sql_error_sql()); +				$this->iohandler->add_error_message($error['message']); +			} +		} + +		$sql = 'SELECT * FROM ' . PROFILE_FIELDS_TABLE; +		$result = $this->db->sql_query($sql); + +		$insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE); +		while ($row = $this->db->sql_fetchrow($result)) +		{ +			foreach ($installed_languages as $lang_id) +			{ +				$insert_buffer->insert(array( +					'field_id'				=> $row['field_id'], +					'lang_id'				=> $lang_id, + +					// Remove phpbb_ from field name +					'lang_name'				=> strtoupper(substr($row['field_name'], 6)), +					'lang_explain'			=> '', +					'lang_default_value'	=> '', +				)); +			} +		} + +		$this->db->sql_freeresult($result); + +		$insert_buffer->flush(); +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_ADD_LANGUAGES'; +	} +} diff --git a/phpBB/phpbb/install/module/install_data/task/add_modules.php b/phpBB/phpbb/install/module/install_data/task/add_modules.php new file mode 100644 index 0000000000..bfbe6282bc --- /dev/null +++ b/phpBB/phpbb/install/module/install_data/task/add_modules.php @@ -0,0 +1,462 @@ +<?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\install_data\task; + +class add_modules extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\extension\manager +	 */ +	protected $extension_manager; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var \phpbb\module\module_manager +	 */ +	protected $module_manager; + +	/** +	 * Define the module structure so that we can populate the database without +	 * needing to hard-code module_id values +	 * +	 * @var array +	 */ +	protected $module_categories = array( +		'acp' => array( +			'ACP_CAT_GENERAL' => array( +				'ACP_QUICK_ACCESS', +				'ACP_BOARD_CONFIGURATION', +				'ACP_CLIENT_COMMUNICATION', +				'ACP_SERVER_CONFIGURATION', +			), +			'ACP_CAT_FORUMS' => array( +				'ACP_MANAGE_FORUMS', +				'ACP_FORUM_BASED_PERMISSIONS', +			), +			'ACP_CAT_POSTING' => array( +				'ACP_MESSAGES', +				'ACP_ATTACHMENTS', +			), +			'ACP_CAT_USERGROUP' => array( +				'ACP_CAT_USERS', +				'ACP_GROUPS', +				'ACP_USER_SECURITY', +			), +			'ACP_CAT_PERMISSIONS' => array( +				'ACP_GLOBAL_PERMISSIONS', +				'ACP_FORUM_BASED_PERMISSIONS', +				'ACP_PERMISSION_ROLES', +				'ACP_PERMISSION_MASKS', +			), +			'ACP_CAT_CUSTOMISE' => array( +				'ACP_STYLE_MANAGEMENT', +				'ACP_EXTENSION_MANAGEMENT', +				'ACP_LANGUAGE', +			), +			'ACP_CAT_MAINTENANCE' => array( +				'ACP_FORUM_LOGS', +				'ACP_CAT_DATABASE', +			), +			'ACP_CAT_SYSTEM' => array( +				'ACP_AUTOMATION', +				'ACP_GENERAL_TASKS', +				'ACP_MODULE_MANAGEMENT', +			), +			'ACP_CAT_DOT_MODS' => null, +		), +		'mcp' => array( +			'MCP_MAIN'		=> null, +			'MCP_QUEUE'		=> null, +			'MCP_REPORTS'	=> null, +			'MCP_NOTES'		=> null, +			'MCP_WARN'		=> null, +			'MCP_LOGS'		=> null, +			'MCP_BAN'		=> null, +		), +		'ucp' => array( +			'UCP_MAIN'			=> null, +			'UCP_PROFILE'		=> null, +			'UCP_PREFS'			=> null, +			'UCP_PM'			=> null, +			'UCP_USERGROUPS'	=> null, +			'UCP_ZEBRA'			=> null, +		), +	); + +	/** +	 * @var array +	 */ +	protected $module_categories_basenames = array( +		'UCP_PM' => 'ucp_pm', +	); + +	/** +	 * @var array +	 */ +	protected $module_extras = array( +		'acp'	=> array( +			'ACP_QUICK_ACCESS' => array( +				'ACP_MANAGE_USERS', +				'ACP_GROUPS_MANAGE', +				'ACP_MANAGE_FORUMS', +				'ACP_MOD_LOGS', +				'ACP_BOTS', +				'ACP_PHP_INFO', +			), +			'ACP_FORUM_BASED_PERMISSIONS' => array( +				'ACP_FORUM_PERMISSIONS', +				'ACP_FORUM_PERMISSIONS_COPY', +				'ACP_FORUM_MODERATORS', +				'ACP_USERS_FORUM_PERMISSIONS', +				'ACP_GROUPS_FORUM_PERMISSIONS', +			), +		), +	); + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler	Installer's input-output handler +	 * @param \phpbb\install\helper\container_factory				$container	Installer's DI container +	 */ +	public function __construct(\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\install\helper\container_factory $container) +	{ +		$this->db					= $container->get('dbal.conn'); +		$this->extension_manager	= $container->get('ext.manager'); +		$this->iohandler			= $iohandler; +		$this->module_manager		= $container->get('module.manager'); + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$module_classes = array('acp', 'mcp', 'ucp'); +		foreach ($module_classes as $module_class) +		{ +			$categories = array(); + +			foreach ($this->module_categories[$module_class] as $cat_name => $subs) +			{ +				// Check if this sub-category has a basename. If it has, use it. +				$basename = (isset($this->module_categories_basenames[$cat_name])) ? $this->module_categories_basenames[$cat_name] : ''; + +				$module_data = array( +					'module_basename'	=> $basename, +					'module_enabled'	=> 1, +					'module_display'	=> 1, +					'parent_id'			=> 0, +					'module_class'		=> $module_class, +					'module_langname'	=> $cat_name, +					'module_mode'		=> '', +					'module_auth'		=> '', +				); + +				$this->module_manager->update_module_data($module_data); + +				// Check for last sql error happened +				if ($this->db->get_sql_error_triggered()) +				{ +					$error = $this->db->sql_error($this->db->get_sql_error_sql()); +					$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +				} + +				$categories[$cat_name]['id'] = (int) $module_data['module_id']; +				$categories[$cat_name]['parent_id'] = 0; + +				if (is_array($subs)) +				{ +					foreach ($subs as $level2_name) +					{ +						// Check if this sub-category has a basename. If it has, use it. +						$basename = (isset($this->module_categories_basenames[$level2_name])) ? $this->module_categories_basenames[$level2_name] : ''; + +						$module_data = array( +							'module_basename'	=> $basename, +							'module_enabled'	=> 1, +							'module_display'	=> 1, +							'parent_id'			=> (int) $categories[$cat_name]['id'], +							'module_class'		=> $module_class, +							'module_langname'	=> $level2_name, +							'module_mode'		=> '', +							'module_auth'		=> '', +						); + +						$this->module_manager->update_module_data($module_data); + +						// Check for last sql error happened +						if ($this->db->get_sql_error_triggered()) +						{ +							$error = $this->db->sql_error($this->db->get_sql_error_sql()); +							$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +						} + +						$categories[$level2_name]['id'] = (int) $module_data['module_id']; +						$categories[$level2_name]['parent_id'] = (int) $categories[$cat_name]['id']; +					} +				} +			} + +			// Get the modules we want to add... returned sorted by name +			$module_info = $this->module_manager->get_module_infos($module_class); + +			foreach ($module_info as $module_basename => $fileinfo) +			{ +				foreach ($fileinfo['modes'] as $module_mode => $row) +				{ +					foreach ($row['cat'] as $cat_name) +					{ +						if (!isset($categories[$cat_name])) +						{ +							continue; +						} + +						$module_data = array( +							'module_basename'	=> $module_basename, +							'module_enabled'	=> 1, +							'module_display'	=> (isset($row['display'])) ? (int) $row['display'] : 1, +							'parent_id'			=> (int) $categories[$cat_name]['id'], +							'module_class'		=> $module_class, +							'module_langname'	=> $row['title'], +							'module_mode'		=> $module_mode, +							'module_auth'		=> $row['auth'], +						); + +						$this->module_manager->update_module_data($module_data); + +						// Check for last sql error happened +						if ($this->db->get_sql_error_triggered()) +						{ +							$error = $this->db->sql_error($this->db->get_sql_error_sql()); +							$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +						} +					} +				} +			} + +			// Move some of the modules around since the code above will put them in the wrong place +			if ($module_class === 'acp') +			{ +				// Move main module 4 up... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'acp_main' +						AND module_class = 'acp' +						AND module_mode = 'main'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'acp', 'move_up', 4); + +				// Move permissions intro screen module 4 up... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'acp_permissions' +						AND module_class = 'acp' +						AND module_mode = 'intro'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'acp', 'move_up', 4); + +				// Move manage users screen module 5 up... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'acp_users' +						AND module_class = 'acp' +						AND module_mode = 'overview'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'acp', 'move_up', 5); + +				// Move extension management module 1 up... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_langname = 'ACP_EXTENSION_MANAGEMENT' +						AND module_class = 'acp' +						AND module_mode = '' +						AND module_basename = ''"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'acp', 'move_up', 1); +			} + +			if ($module_class == 'mcp') +			{ +				// Move pm report details module 3 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'mcp_pm_reports' +						AND module_class = 'mcp' +						AND module_mode = 'pm_report_details'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); + +				// Move closed pm reports module 3 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'mcp_pm_reports' +						AND module_class = 'mcp' +						AND module_mode = 'pm_reports_closed'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); + +				// Move open pm reports module 3 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'mcp_pm_reports' +						AND module_class = 'mcp' +						AND module_mode = 'pm_reports'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'mcp', 'move_down', 3); +			} + +			if ($module_class == 'ucp') +			{ +				// Move attachment module 4 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'ucp_attachments' +						AND module_class = 'ucp' +						AND module_mode = 'attachments'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'ucp', 'move_down', 4); + +				// Move notification options module 4 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'ucp_notifications' +						AND module_class = 'ucp' +						AND module_mode = 'notification_options'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'ucp', 'move_down', 4); + +				// Move OAuth module 5 down... +				$sql = 'SELECT * +					FROM ' . MODULES_TABLE . " +					WHERE module_basename = 'ucp_auth_link' +						AND module_class = 'ucp' +						AND module_mode = 'auth_link'"; +				$result = $this->db->sql_query($sql); +				$row = $this->db->sql_fetchrow($result); +				$this->db->sql_freeresult($result); + +				$this->module_manager->move_module_by($row, 'ucp', 'move_down', 5); +			} + +			// And now for the special ones +			// (these are modules which appear in multiple categories and thus get added manually +			// to some for more control) +			if (isset($this->module_extras[$module_class])) +			{ +				foreach ($this->module_extras[$module_class] as $cat_name => $mods) +				{ +					$sql = 'SELECT module_id, left_id, right_id +						FROM ' . MODULES_TABLE . " +						WHERE module_langname = '" . $this->db->sql_escape($cat_name) . "' +							AND module_class = '" . $this->db->sql_escape($module_class) . "'"; +					$result = $this->db->sql_query_limit($sql, 1); +					$row2 = $this->db->sql_fetchrow($result); +					$this->db->sql_freeresult($result); + +					foreach ($mods as $mod_name) +					{ +						$sql = 'SELECT * +							FROM ' . MODULES_TABLE . " +							WHERE module_langname = '" . $this->db->sql_escape($mod_name) . "' +								AND module_class = '" . $this->db->sql_escape($module_class) . "' +								AND module_basename <> ''"; +						$result = $this->db->sql_query_limit($sql, 1); +						$row = $this->db->sql_fetchrow($result); +						$this->db->sql_freeresult($result); + +						$module_data = array( +							'module_basename'	=> $row['module_basename'], +							'module_enabled'	=> (int) $row['module_enabled'], +							'module_display'	=> (int) $row['module_display'], +							'parent_id'			=> (int) $row2['module_id'], +							'module_class'		=> $row['module_class'], +							'module_langname'	=> $row['module_langname'], +							'module_mode'		=> $row['module_mode'], +							'module_auth'		=> $row['module_auth'], +						); + +						$this->module_manager->update_module_data($module_data); + +						// Check for last sql error happened +						if ($this->db->get_sql_error_triggered()) +						{ +							$error = $this->db->sql_error($this->db->get_sql_error_sql()); +							$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +						} +					} +				} +			} + +			$this->module_manager->remove_cache_file($module_class); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_ADD_MODULES'; +	} +} diff --git a/phpBB/phpbb/install/module/install_database/module.php b/phpBB/phpbb/install/module/install_database/module.php new file mode 100644 index 0000000000..0d8b33087f --- /dev/null +++ b/phpBB/phpbb/install/module/install_database/module.php @@ -0,0 +1,28 @@ +<?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\install_database; + +/** + * Installer module for database installation + */ +class module extends \phpbb\install\module_base +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get_navigation_stage_path() +	{ +		return array('install', 0, 'install'); +	} +} diff --git a/phpBB/phpbb/install/module/install_database/task/add_config_settings.php b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php new file mode 100644 index 0000000000..6fb03ff73d --- /dev/null +++ b/phpBB/phpbb/install/module/install_database/task/add_config_settings.php @@ -0,0 +1,341 @@ +<?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\install_database\task; + +/** + * Create database schema + */ +class add_config_settings extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var \phpbb\passwords\manager +	 */ +	protected $password_manager; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var string +	 */ +	protected $config_table; + +	/** +	 * @var string +	 */ +	protected $user_table; + +	/** +	 * @var string +	 */ +	protected $topics_table; + +	/** +	 * @var string +	 */ +	protected $forums_table; + +	/** +	 * @var string +	 */ +	protected $posts_table; + +	/** +	 * @var string +	 */ +	protected $moderator_cache_table; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\filesystem\filesystem_interface				$filesystem			Filesystem service +	 * @param \phpbb\install\helper\config							$install_config		Installer's config helper +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler			Installer's input-output handler +	 * @param \phpbb\install\helper\container_factory				$container			Installer's DI container +	 * @param \phpbb\language\language								$language			Language service +	 * @param string												$phpbb_root_path	Path to phpBB's root +	 */ +	public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, +								\phpbb\install\helper\config $install_config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\install\helper\container_factory $container, +								\phpbb\language\language $language, +								$phpbb_root_path) +	{ +		$this->db				= $container->get('dbal.conn'); +		$this->filesystem		= $filesystem; +		$this->install_config	= $install_config; +		$this->iohandler		= $iohandler; +		$this->language			= $language; +		$this->password_manager	= $container->get('passwords.manager'); +		$this->phpbb_root_path	= $phpbb_root_path; + +		// Table names +		$this->config_table				= $container->get_parameter('tables.config'); +		$this->forums_table				= $container->get_parameter('tables.forums'); +		$this->topics_table				= $container->get_parameter('tables.topics'); +		$this->user_table				= $container->get_parameter('tables.users'); +		$this->moderator_cache_table	= $container->get_parameter('tables.moderator_cache'); +		$this->posts_table				= $container->get_parameter('tables.posts'); + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$server_name	= $this->install_config->get('server_name'); +		$cookie_domain	= $this->install_config->get('cookie_domain'); +		$current_time 	= time(); +		$user_ip		= phpbb_ip_normalise($this->iohandler->get_server_variable('REMOTE_ADDR')); +		$user_ip		= ($user_ip === false) ? '' : $user_ip; +		$referer		= $this->iohandler->get_server_variable('REFERER'); + +		// Set default config and post data, this applies to all DB's +		$sql_ary = array( +			'INSERT INTO ' . $this->config_table . " (config_name, config_value) +				VALUES ('board_startdate', '$current_time')", + +			'INSERT INTO ' . $this->config_table . " (config_name, config_value) +				VALUES ('default_lang', '" . $this->db->sql_escape($this->install_config->get('default_lang')) . "')", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('img_imagick')) . "' +				WHERE config_name = 'img_imagick'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_name')) . "' +				WHERE config_name = 'server_name'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_port')) . "' +				WHERE config_name = 'server_port'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "' +				WHERE config_name = 'board_email'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_email')) . "' +				WHERE config_name = 'board_contact'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($cookie_domain) . "' +				WHERE config_name = 'cookie_domain'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "' +				WHERE config_name = 'default_dateformat'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('email_enable')) . "' +				WHERE config_name = 'email_enable'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_delivery')) . "' +				WHERE config_name = 'smtp_delivery'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_host')) . "' +				WHERE config_name = 'smtp_host'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_auth')) . "' +				WHERE config_name = 'smtp_auth_method'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_user')) . "' +				WHERE config_name = 'smtp_username'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('smtp_pass')) . "' +				WHERE config_name = 'smtp_password'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('cookie_secure')) . "' +				WHERE config_name = 'cookie_secure'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('force_server_vars')) . "' +				WHERE config_name = 'force_server_vars'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('script_path')) . "' +				WHERE config_name = 'script_path'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('server_protocol')) . "' +				WHERE config_name = 'server_protocol'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' +				WHERE config_name = 'newest_username'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . md5(mt_rand()) . "' +				WHERE config_name = 'avatar_salt'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . md5(mt_rand()) . "' +				WHERE config_name = 'plupload_salt'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_name')) . "' +				WHERE config_name = 'sitename'", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->install_config->get('board_description')) . "' +				WHERE config_name = 'site_desc'", + +			'UPDATE ' . $this->user_table . " +				SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "', +					user_password='" . $this->password_manager->hash($this->install_config->get('admin_passwd')) . "', +					user_ip = '" . $this->db->sql_escape($user_ip) . "', +					user_lang = '" . $this->db->sql_escape($this->install_config->get('user_language', 'en')) . "', +					user_email='" . $this->db->sql_escape($this->install_config->get('board_email')) . "', +					user_dateformat='" . $this->db->sql_escape($this->language->lang('default_dateformat')) . "', +					user_email_hash = " . $this->db->sql_escape(phpbb_email_hash($this->install_config->get('board_email'))) . ", +					username_clean = '" . $this->db->sql_escape(utf8_clean_string($this->install_config->get('admin_name'))) . "' +				WHERE username = 'Admin'", + +			'UPDATE ' . $this->moderator_cache_table . " +				SET username = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' +				WHERE username = 'Admin'", + +			'UPDATE ' . $this->forums_table . " +				SET forum_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' +				WHERE forum_last_poster_name = 'Admin'", + +			'UPDATE ' . $this->topics_table . " +				SET topic_first_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "', +				topic_last_poster_name = '" . $this->db->sql_escape($this->install_config->get('admin_name')) . "' +				WHERE topic_first_poster_name = 'Admin' +					OR topic_last_poster_name = 'Admin'", + +			'UPDATE ' . $this->user_table . " +				SET user_regdate = $current_time", + +			'UPDATE ' . $this->posts_table . " +				SET post_time = $current_time, poster_ip = '" . $this->db->sql_escape($user_ip) . "'", + +			'UPDATE ' . $this->topics_table . " +				SET topic_time = $current_time, topic_last_post_time = $current_time", + +			'UPDATE ' . $this->forums_table . " +				SET forum_last_post_time = $current_time", + +			'UPDATE ' . $this->config_table . " +				SET config_value = '" . $this->db->sql_escape($this->db->sql_server_info(true)) . "' +				WHERE config_name = 'dbms_version'", +		); + +		if (@extension_loaded('gd')) +		{ +			$sql_ary[] = 'UPDATE ' . $this->config_table . " +				SET config_value = 'core.captcha.plugins.gd' +				WHERE config_name = 'captcha_plugin'"; + +			$sql_ary[] = 'UPDATE ' . $this->config_table . " +				SET config_value = '1' +				WHERE config_name = 'captcha_gd'"; +		} + +		$ref = substr($referer, strpos($referer, '://') + 3); +		if (!(stripos($ref, $server_name) === 0)) +		{ +			$sql_ary[] = 'UPDATE ' . $this->config_table . " +				SET config_value = '0' +				WHERE config_name = 'referer_validation'"; +		} + +		// We set a (semi-)unique cookie name to bypass login issues related to the cookie name. +		$cookie_name = 'phpbb3_'; +		$rand_str = md5(mt_rand()); +		$rand_str = str_replace('0', 'z', base_convert($rand_str, 16, 35)); +		$rand_str = substr($rand_str, 0, 5); +		$cookie_name .= strtolower($rand_str); + +		$sql_ary[] = 'UPDATE ' . $this->config_table . " +			SET config_value = '" . $this->db->sql_escape($cookie_name) . "' +			WHERE config_name = 'cookie_name'"; + +		// Disable avatars if upload directory is not writable +		if (!$this->filesystem->is_writable($this->phpbb_root_path . 'images/avatars/upload/')) +		{ +			$sql_ary[] = 'UPDATE ' . $this->config_table . " +				SET config_value = '0' +				WHERE config_name = 'allow_avatar'"; + +			$sql_ary[] = 'UPDATE ' . $this->config_table . " +				SET config_value = '0' +				WHERE config_name = 'allow_avatar_upload'"; +		} + +		foreach ($sql_ary as $sql) +		{ +			if (!$this->db->sql_query($sql)) +			{ +				$error = $this->db->sql_error($this->db->get_sql_error_sql()); +				$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +			} +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_ADD_CONFIG_SETTINGS'; +	} +} diff --git a/phpBB/phpbb/install/module/install_database/task/add_default_data.php b/phpBB/phpbb/install/module/install_database/task/add_default_data.php new file mode 100644 index 0000000000..3d73a74618 --- /dev/null +++ b/phpBB/phpbb/install/module/install_database/task/add_default_data.php @@ -0,0 +1,163 @@ +<?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\install_database\task; + +/** + * Create database schema + */ +class add_default_data extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\install\helper\database +	 */ +	protected $database_helper; + +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\database						$db_helper	Installer's database helper +	 * @param \phpbb\install\helper\config							$config		Installer config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler	Installer's input-output handler +	 * @param \phpbb\install\helper\container_factory				$container	Installer's DI container +	 * @param \phpbb\language\language								$language	Language service +	 * @param string												$root_path	Root path of phpBB +	 */ +	public function __construct(\phpbb\install\helper\database $db_helper, +								\phpbb\install\helper\config $config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\install\helper\container_factory $container, +								\phpbb\language\language $language, +								$root_path) +	{ +		$this->db				= $container->get('dbal.conn.driver'); +		$this->database_helper	= $db_helper; +		$this->config			= $config; +		$this->iohandler		= $iohandler; +		$this->language			= $language; +		$this->phpbb_root_path	= $root_path; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$table_prefix = $this->config->get('table_prefix'); +		$dbms = $this->config->get('dbms'); +		$dbms_info = $this->database_helper->get_available_dbms($dbms); + +		// Get schema data from file +		$sql_query = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema_data.sql'); + +		// Clean up SQL +		$sql_query = $this->replace_dbms_specific_sql($sql_query); +		$sql_query = preg_replace('# phpbb_([^\s]*) #i', ' ' . $table_prefix . '\1 ', $sql_query); +		$sql_query = preg_replace_callback('#\{L_([A-Z0-9\-_]*)\}#s', array($this, 'lang_replace_callback'), $sql_query); +		$sql_query = $this->database_helper->remove_comments($sql_query); +		$sql_query = $this->database_helper->split_sql_file($sql_query, $dbms_info[$dbms]['DELIM']); + +		foreach ($sql_query as $sql) +		{ +			if (!$this->db->sql_query($sql)) +			{ +				$error = $this->db->sql_error($this->db->get_sql_error_sql()); +				$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +			} +		} +	} + +	/** +	 * Process DB specific SQL +	 * +	 * @return string +	 */ +	protected function replace_dbms_specific_sql($query) +	{ +		if ($this->db instanceof \phpbb\db\driver\mssql_base || $this->db instanceof \phpbb\db\driver\mssql) +		{ +			$query = preg_replace('#\# MSSQL IDENTITY (phpbb_[a-z_]+) (ON|OFF) \##s', 'SET IDENTITY_INSERT \1 \2;', $query); +		} +		else if ($this->db instanceof \phpbb\db\driver\postgres) +		{ +			$query = preg_replace('#\# POSTGRES (BEGIN|COMMIT) \##s', '\1; ', $query); +		} +		else if ($this->db instanceof \phpbb\db\driver\mysql_base) +		{ +			$query = str_replace('\\', '\\\\', $query); +		} + +		return $query; +	} + +	/** +	 * Callback function for language replacing +	 * +	 * @param array	$matches +	 * @return string +	 */ +	public function lang_replace_callback($matches) +	{ +		if (!empty($matches[1])) +		{ +			return $this->db->sql_escape($this->language->lang($matches[1])); +		} + +		return ''; +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_ADD_DEFAULT_DATA'; +	} +} diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php new file mode 100644 index 0000000000..cabb78787f --- /dev/null +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -0,0 +1,221 @@ +<?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\install_database\task; + +/** + * Create database schema + */ +class create_schema extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $config; + +	/** +	 * @var \phpbb\db\driver\driver_interface +	 */ +	protected $db; + +	/** +	 * @var \phpbb\db\tools\tools_interface +	 */ +	protected $db_tools; + +	/** +	 * @var \phpbb\install\helper\database +	 */ +	protected $database_helper; + +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$config				Installer's config provider +	 * @param \phpbb\install\helper\database						$db_helper			Installer's database helper +	 * @param \phpbb\filesystem\filesystem_interface				$filesystem			Filesystem service +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler			Installer's input-output handler +	 * @param string												$phpbb_root_path	Path phpBB's root +	 * @param string												$php_ext			Extension of PHP files +	 */ +	public function __construct(\phpbb\install\helper\config $config, +								\phpbb\install\helper\database $db_helper, +								\phpbb\filesystem\filesystem_interface $filesystem, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								$phpbb_root_path, +								$php_ext) +	{ +		$dbms = $db_helper->get_available_dbms($config->get('dbms')); +		$dbms = $dbms[$config->get('dbms')]['DRIVER']; +		$factory = new \phpbb\db\tools\factory(); + +		$this->db				= new $dbms(); +		$this->db->sql_connect( +			$config->get('dbhost'), +			$config->get('dbuser'), +			$config->get('dbpasswd'), +			$config->get('dbname'), +			$config->get('dbport'), +			false, +			false +		); + +		$this->config			= $config; +		$this->db_tools			= $factory->get($this->db); +		$this->database_helper	= $db_helper; +		$this->filesystem		= $filesystem; +		$this->iohandler		= $iohandler; +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->php_ext			= $php_ext; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->db->sql_return_on_error(true); + +		$dbms = $this->config->get('dbms'); +		$dbms_info = $this->database_helper->get_available_dbms($dbms); +		$schema_name = $dbms_info[$dbms]['SCHEMA']; +		$delimiter = $dbms_info[$dbms]['DELIM']; +		$table_prefix = $this->config->get('table_prefix'); + +		if ($dbms === 'mysql') +		{ +			if (version_compare($this->db->sql_server_info(true), '4.1.3', '>=')) +			{ +				$schema_name .= '_41'; +			} +			else +			{ +				$schema_name .= '_40'; +			} +		} + +		$db_schema_path = $this->phpbb_root_path . 'install/schemas/' . $schema_name . '_schema.sql'; + +		// Load database vendor specific code if there is any +		if ($this->filesystem->exists($db_schema_path)) +		{ +			$sql_query = @file_get_contents($db_schema_path); +			$sql_query = preg_replace('#phpbb_#i', $table_prefix, $sql_query); +			$sql_query = $this->database_helper->remove_comments($sql_query); +			$sql_query = $this->database_helper->split_sql_file($sql_query, $delimiter); + +			foreach ($sql_query as $sql) +			{ +				if (!$this->db->sql_query($sql)) +				{ +					$error = $this->db->sql_error($this->db->get_sql_error_sql()); +					$this->iohandler->add_error_message('INST_ERR_DB', $error['message']); +				} +			} + +			unset($sql_query); +		} + +		$change_prefix = false; + +		// Generate database schema +		if ($this->filesystem->exists($this->phpbb_root_path . 'install/schemas/schema.json')) +		{ +			$db_table_schema = @file_get_contents($this->phpbb_root_path . 'install/schemas/schema.json'); +			$db_table_schema = json_decode($db_table_schema, true); +			$change_prefix = true; +		} +		else +		{ +			global $table_prefix; + +			$table_prefix = $this->config->get('table_prefix'); + +			if (!defined('CONFIG_TABLE')) +			{ +				// We need to include the constants file for the table constants +				// when we generate the schema from the migration files. +				include ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext); +			} + +			$finder = new \phpbb\finder($this->filesystem, $this->phpbb_root_path, null, $this->php_ext); +			$migrator_classes = $finder->core_path('phpbb/db/migration/data/')->get_classes(); +			$factory = new \phpbb\db\tools\factory(); +			$db_tools = $factory->get($this->db, true); +			$schema_generator = new \phpbb\db\migration\schema_generator( +				$migrator_classes, +				new \phpbb\config\config(array()), +				$this->db, +				$db_tools, +				$this->phpbb_root_path, +				$this->php_ext, +				$table_prefix +			); +			$db_table_schema = $schema_generator->get_schema(); +		} + +		if (!defined('CONFIG_TABLE')) +		{ +			// CONFIG_TABLE is required by sql_create_index() to check the +			// length of index names. However table_prefix is not defined +			// here yet, so we need to create the constant ourselves. +			define('CONFIG_TABLE', $table_prefix . 'config'); +		} + +		foreach ($db_table_schema as $table_name => $table_data) +		{ +			$this->db_tools->sql_create_table( +				( ($change_prefix) ? ($table_prefix . substr($table_name, 6)) : $table_name ), +				$table_data +			); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_CREATE_DATABASE_SCHEMA'; +	} +} diff --git a/phpBB/phpbb/install/module/install_filesystem/module.php b/phpBB/phpbb/install/module/install_filesystem/module.php new file mode 100644 index 0000000000..7215449664 --- /dev/null +++ b/phpBB/phpbb/install/module/install_filesystem/module.php @@ -0,0 +1,28 @@ +<?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\install_filesystem; + +/** + * Installer module for filesystem installation + */ +class module extends \phpbb\install\module_base +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get_navigation_stage_path() +	{ +		return array('install', 0, 'install'); +	} +} diff --git a/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php new file mode 100644 index 0000000000..e0890a929c --- /dev/null +++ b/phpBB/phpbb/install/module/install_filesystem/task/create_config_file.php @@ -0,0 +1,246 @@ +<?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\install_filesystem\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * Dumps config file + */ +class create_config_file extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * @var \phpbb\install\helper\database +	 */ +	protected $db_helper; + +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * @var array +	 */ +	protected $options; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\filesystem\filesystem_interface				$filesystem +	 * @param \phpbb\install\helper\config							$install_config +	 * @param \phpbb\install\helper\database						$db_helper +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler +	 * @param string												$phpbb_root_path +	 * @param string												$php_ext +	 * @param array													$options +	 */ +	public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, +								\phpbb\install\helper\config $install_config, +								\phpbb\install\helper\database $db_helper, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								$phpbb_root_path, +								$php_ext, +								$options = array()) +	{ +		$this->install_config	= $install_config; +		$this->db_helper		= $db_helper; +		$this->filesystem		= $filesystem; +		$this->iohandler		= $iohandler; +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->php_ext			= $php_ext; +		$this->options			= array_merge(array( +			'debug' => false, +			'debug_container' => false, +			'environment' => null, +		), $options); + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$config_written = true; + +		// Create config.php +		$path_to_config = $this->phpbb_root_path . 'config.' . $this->php_ext; + +		$fp = @fopen($path_to_config, 'w'); +		if (!$fp) +		{ +			$config_written = false; +		} + +		$config_content = $this->get_config_data($this->options['debug'], $this->options['debug_container'], $this->options['environment']); + +		if (!@fwrite($fp, $config_content)) +		{ +			$config_written = false; +		} + +		@fclose($fp); + +		// chmod config.php to be only readable +		if ($config_written) +		{ +			try +			{ +				$this->filesystem->phpbb_chmod($path_to_config, \phpbb\filesystem\filesystem_interface::CHMOD_READ); +			} +			catch (\phpbb\filesystem\exception\filesystem_exception $e) +			{ +				// Do nothing, the user will get a notice later +			} +		} +		else +		{ +			$this->iohandler->add_error_message('UNABLE_TO_WRITE_CONFIG_FILE'); +			$this->iohandler->send_response(); +			throw new user_interaction_required_exception(); +		} + +		// Create a lock file to indicate that there is an install in progress +		$fp = @fopen($this->phpbb_root_path . 'cache/install_lock', 'wb'); +		if ($fp === false) +		{ +			// We were unable to create the lock file - abort +			$this->iohandler->add_error_message('UNABLE_TO_WRITE_LOCK'); +			$this->iohandler->send_response(); +			throw new user_interaction_required_exception(); +		} +		@fclose($fp); + +		try +		{ +			$this->filesystem->phpbb_chmod($this->phpbb_root_path . 'cache/install_lock', 0777); +		} +		catch (\phpbb\filesystem\exception\filesystem_exception $e) +		{ +			// Do nothing, the user will get a notice later +		} +	} + +	/** +	 * Returns the content which should be dumped to config.php +	 * +	 * @param bool		$debug 				If the debug constants should be enabled by default or not +	 * @param bool		$debug_container 	If the container should be compiled on +	 *										every page load or not +	 * @param string	$environment		The environment to use +	 * +	 * @return string	content to be written to the config file +	 */ +	protected function get_config_data($debug = false, $debug_container = false, $environment = null) +	{ +		$config_content = "<?php\n"; +		$config_content .= "// phpBB 3.2.x auto-generated configuration file\n// Do not change anything in this file!\n"; + +		$dbms = $this->install_config->get('dbms'); +		$db_driver = $this->db_helper->get_available_dbms($dbms); +		$db_driver = $db_driver[$dbms]['DRIVER']; + +		$config_data_array = array( +			'dbms'			=> $db_driver, +			'dbhost'		=> $this->install_config->get('dbhost'), +			'dbport'		=> $this->install_config->get('dbport'), +			'dbname'		=> $this->install_config->get('dbname'), +			'dbuser'		=> $this->install_config->get('dbuser'), +			'dbpasswd'		=> $this->install_config->get('dbpasswd'), +			'table_prefix'	=> $this->install_config->get('table_prefix'), + +			'phpbb_adm_relative_path'	=> 'adm/', + +			'acm_type'		=> 'phpbb\cache\driver\file', +		); + +		foreach ($config_data_array as $key => $value) +		{ +			$config_content .= "\${$key} = '" . str_replace("'", "\\'", str_replace('\\', '\\\\', $value)) . "';\n"; +		} + +		$config_content .= "\n@define('PHPBB_INSTALLED', true);\n"; +		$config_content .= "// @define('PHPBB_DISPLAY_LOAD_TIME', true);\n"; + +		if ($environment) +		{ +			$config_content .= "@define('PHPBB_ENVIRONMENT', 'test');\n"; +		} +		else if ($debug) +		{ +			$config_content .= "@define('PHPBB_ENVIRONMENT', 'development');\n"; +		} +		else +		{ +			$config_content .= "@define('PHPBB_ENVIRONMENT', 'production');\n"; +		} + +		if ($debug_container) +		{ +			$config_content .= "@define('DEBUG_CONTAINER', true);\n"; +		} +		else +		{ +			$config_content .= "// @define('DEBUG_CONTAINER', true);\n"; +		} + +		if ($environment === 'test') +		{ +			$config_content .= "@define('DEBUG_TEST', true);\n"; + +			// Mandatory for the functional tests, will be removed by PHPBB3-12623 +			$config_content .= "@define('DEBUG', true);\n"; +		} + +		return $config_content; +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_CREATE_CONFIG_FILE'; +	} +} diff --git a/phpBB/phpbb/install/module/install_finish/module.php b/phpBB/phpbb/install/module/install_finish/module.php new file mode 100644 index 0000000000..3a7544b84f --- /dev/null +++ b/phpBB/phpbb/install/module/install_finish/module.php @@ -0,0 +1,28 @@ +<?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\install_finish; + +/** + * Installer module for filesystem installation + */ +class module extends \phpbb\install\module_base +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get_navigation_stage_path() +	{ +		return array('install', 0, 'install'); +	} +} diff --git a/phpBB/phpbb/install/module/install_finish/task/notify_user.php b/phpBB/phpbb/install/module/install_finish/task/notify_user.php new file mode 100644 index 0000000000..5268b85a42 --- /dev/null +++ b/phpBB/phpbb/install/module/install_finish/task/notify_user.php @@ -0,0 +1,170 @@ +<?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\install_finish\task; + +use phpbb\config\db; + +/** + * Logs installation and sends an email to the admin + */ +class notify_user extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var \phpbb\auth\auth +	 */ +	protected $auth; + +	/** +	 * @var \phpbb\config\db +	 */ +	protected $config; + +	/** +	 * @var \phpbb\language\language +	 */ +	protected $language; + +	/** +	 * @var \phpbb\log\log_interface +	 */ +	protected $log; + +	/** +	 * @var \phpbb\user +	 */ +	protected $user; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var string +	 */ +	protected $php_ext; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\container_factory				$container +	 * @param \phpbb\install\helper\config							$install_config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler +	 * @param string												$phpbb_root_path +	 * @param string												$php_ext +	 */ +	public function __construct(\phpbb\install\helper\container_factory $container, \phpbb\install\helper\config $install_config, \phpbb\install\helper\iohandler\iohandler_interface $iohandler, $phpbb_root_path, $php_ext) +	{ +		$this->install_config	= $install_config; +		$this->iohandler		= $iohandler; + +		$this->auth				= $container->get('auth'); +		$this->language			= $container->get('language'); +		$this->log				= $container->get('log'); +		$this->user				= $container->get('user'); +		$this->phpbb_root_path	= $phpbb_root_path; +		$this->php_ext			= $php_ext; + +		// We need to reload config for cases when it doesn't have all values +		$this->config = new db( +			$container->get('dbal.conn'), +			$container->get('cache.driver'), +			$container->get_parameter('tables.config') +		); + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->user->session_begin(); +		$this->user->setup('common'); + +		if ($this->config['email_enable']) +		{ +			include ($this->phpbb_root_path . 'includes/functions_messenger.' . $this->php_ext); + +			// functions_messenger.php uses config to determine language paths +			// Remove when able +			global $config; +			$config = $this->config; + +			$messenger = new \messenger(false); +			$messenger->template('installed', $this->install_config->get('user_language', 'en')); +			$messenger->to($this->config['board_email'], $this->install_config->get('admin_name')); +			$messenger->anti_abuse_headers($this->config, $this->user); +			$messenger->assign_vars(array( +					'USERNAME'		=> htmlspecialchars_decode($this->install_config->get('admin_name')), +					'PASSWORD'		=> htmlspecialchars_decode($this->install_config->get('admin_passwd'))) +			); +			$messenger->send(NOTIFY_EMAIL); +		} + +		// Login admin +		// Ugly but works +		$this->auth->login( +			$this->install_config->get('admin_name'), +			$this->install_config->get('admin_passwd'), +			false, +			true, +			true +		); + +		$this->iohandler->set_cookie($this->config['cookie_name'] . '_sid', $this->user->session_id); +		$this->iohandler->set_cookie($this->config['cookie_name'] . '_u', $this->user->cookie_data['u']); +		$this->iohandler->set_cookie($this->config['cookie_name'] . '_k', $this->user->cookie_data['k']); + +		// Create log +		$this->log->add( +			'admin', +			$this->user->data['user_id'], +			$this->user->ip, +			'LOG_INSTALL_INSTALLED', +			false, +			array($this->config['version']) +		); + +		// Remove install_lock +		@unlink($this->phpbb_root_path . 'cache/install_lock'); +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_NOTIFY_USER'; +	} +} diff --git a/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php new file mode 100644 index 0000000000..8629d9aea3 --- /dev/null +++ b/phpBB/phpbb/install/module/install_finish/task/populate_migrations.php @@ -0,0 +1,72 @@ +<?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\install_finish\task; + +/** + * Populates migrations + */ +class populate_migrations extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\extension\manager +	 */ +	protected $extension_manager; + +	/** +	 * @var \phpbb\db\migrator +	 */ +	protected $migrator; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\container_factory	$container	phpBB's DI contianer +	 */ +	public function __construct(\phpbb\install\helper\container_factory $container) +	{ +		$this->extension_manager	= $container->get('ext.manager'); +		$this->migrator				= $container->get('migrator'); + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$finder = $this->extension_manager->get_finder(); + +		$migrations = $finder +			->core_path('phpbb/db/migration/data/') +			->get_classes(); +		$this->migrator->populate_migrations($migrations); +	} + +	/** +	 * {@inheritdoc} +	 */ +	static public function get_step_count() +	{ +		return 1; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_task_lang_name() +	{ +		return 'TASK_POPULATE_MIGRATIONS'; +	} +} diff --git a/phpBB/phpbb/install/module/obtain_data/install_module.php b/phpBB/phpbb/install/module/obtain_data/install_module.php new file mode 100644 index 0000000000..deb4be90d8 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/install_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 install_module extends \phpbb\install\module_base +{ +	/** +	 * {@inheritdoc} +	 */ +	public function get_navigation_stage_path() +	{ +		return array('install', 0, 'obtain_data'); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_step_count() +	{ +		return 0; +	} +} 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 new file mode 100644 index 0000000000..ac305e8ab5 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_admin_data.php @@ -0,0 +1,219 @@ +<?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; + +/** + * This class requests and validates admin account data from the user + */ +class obtain_admin_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$install_config	Installer's config helper +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler		Installer's input-output handler +	 */ +	public function __construct(\phpbb\install\helper\config $install_config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler) +	{ +		$this->install_config	= $install_config; +		$this->io_handler		= $iohandler; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// Check if data is sent +		if ($this->io_handler->get_input('submit_admin', false)) +		{ +			$this->process_form(); +		} +		else +		{ +			$this->request_form_data(); +		} +	} + +	/** +	 * Process form data +	 */ +	protected function process_form() +	{ +		// Admin data +		$admin_name		= $this->io_handler->get_input('admin_name', '', true); +		$admin_pass1	= $this->io_handler->get_input('admin_pass1', '', true); +		$admin_pass2	= $this->io_handler->get_input('admin_pass2', '', true); +		$board_email	= $this->io_handler->get_input('board_email', '', true); + +		$admin_data_valid = $this->check_admin_data($admin_name, $admin_pass1, $admin_pass2, $board_email); + +		if ($admin_data_valid) +		{ +			$this->install_config->set('admin_name', $admin_name); +			$this->install_config->set('admin_passwd', $admin_pass1); +			$this->install_config->set('board_email', $board_email); +		} +		else +		{ +			$this->request_form_data(true); +		} +	} + +	/** +	 * Request data from the user +	 * +	 * @param bool $use_request_data Whether to use submited data +	 * +	 * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data +	 */ +	protected function request_form_data($use_request_data = false) +	{ +		if ($use_request_data) +		{ +			$admin_username	= $this->io_handler->get_input('admin_name', '', true); +			$admin_email	= $this->io_handler->get_input('board_email', '', true); +		} +		else +		{ +			$admin_username	= ''; +			$admin_email	= ''; +		} + +		$admin_form = array( +			'admin_name'	=> array( +				'label'			=> 'ADMIN_USERNAME', +				'description'	=> 'ADMIN_USERNAME_EXPLAIN', +				'type'			=> 'text', +				'default'		=> $admin_username, +			), +			'board_email'	=> array( +				'label'		=> 'CONTACT_EMAIL', +				'type'		=> 'email', +				'default'	=> $admin_email, +			), +			'admin_pass1'	=> array( +				'label'			=> 'ADMIN_PASSWORD', +				'description'	=> 'ADMIN_PASSWORD_EXPLAIN', +				'type'			=> 'password', +			), +			'admin_pass2'	=> array( +				'label'	=> 'ADMIN_PASSWORD_CONFIRM', +				'type'	=> 'password', +			), +			'submit_admin'	=> array( +				'label'	=> 'SUBMIT', +				'type'	=> 'submit', +			), +		); + +		$this->io_handler->add_user_form_group('ADMIN_CONFIG', $admin_form); + +		// Require user interaction +		$this->io_handler->send_response(); +		throw new user_interaction_required_exception(); +	} + +	/** +	 * Check admin data +	 * +	 * @param string	$username	Admin username +	 * @param string	$pass1		Admin password +	 * @param string	$pass2		Admin password confirmation +	 * @param string	$email		Admin e-mail address +	 * +	 * @return bool	True if data is valid, false otherwise +	 */ +	protected function check_admin_data($username, $pass1, $pass2, $email) +	{ +		$data_valid = true; + +		// Check if none of admin data is empty +		if (in_array('', array($username, $pass1, $pass2, $email), true)) +		{ +			$this->io_handler->add_error_message('INST_ERR_MISSING_DATA'); +			$data_valid = false; +		} + +		if (utf8_strlen($username) < 3) +		{ +			$this->io_handler->add_error_message('INST_ERR_USER_TOO_SHORT'); +			$data_valid = false; +		} + +		if (utf8_strlen($username) > 20) +		{ +			$this->io_handler->add_error_message('INST_ERR_USER_TOO_LONG'); +			$data_valid = false; +		} + +		if ($pass1 !== $pass2 && $pass1 !== '') +		{ +			$this->io_handler->add_error_message('INST_ERR_PASSWORD_MISMATCH'); +			$data_valid = false; +		} + +		// Test against the default password rules +		if (utf8_strlen($pass1) < 6) +		{ +			$this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_SHORT'); +			$data_valid = false; +		} + +		if (utf8_strlen($pass1) > 30) +		{ +			$this->io_handler->add_error_message('INST_ERR_PASSWORD_TOO_LONG'); +			$data_valid = false; +		} + +		if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) +		{ +			$this->io_handler->add_error_message('INST_ERR_EMAIL_INVALID'); +			$data_valid = false; +		} + +		return $data_valid; +	} + +	/** +	 * {@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_board_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.php new file mode 100644 index 0000000000..6c54561d14 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_board_data.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\obtain_data\task; + +use phpbb\install\exception\user_interaction_required_exception; + +/** + * This class obtains default data from the user related to board (Board name, Board descritpion, etc...) + */ +class obtain_board_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * @var \phpbb\language\language_file_helper +	 */ +	protected $language_helper; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$config			Installer's config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler		Installer's input-output handler +	 * @param \phpbb\language\language_file_helper					$lang_helper	Language file helper +	 */ +	public function __construct(\phpbb\install\helper\config $config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler, +								\phpbb\language\language_file_helper $lang_helper) +	{ +		$this->install_config	= $config; +		$this->io_handler		= $iohandler; +		$this->language_helper	= $lang_helper; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// Check if data is sent +		if ($this->io_handler->get_input('submit_board', false)) +		{ +			$this->process_form(); +		} +		else +		{ +			$this->request_form_data(); +		} +	} + +	/** +	 * Process form data +	 */ +	protected function process_form() +	{ +		// Board data +		$default_lang	= $this->io_handler->get_input('default_lang', ''); +		$board_name		= $this->io_handler->get_input('board_name', '', true); +		$board_desc		= $this->io_handler->get_input('board_description', '', true); + +		// Check default lang +		$langs = $this->language_helper->get_available_languages(); +		$lang_valid = false; + +		foreach ($langs as $lang) +		{ +			if ($lang['iso'] === $default_lang) +			{ +				$lang_valid = true; +				break; +			} +		} + +		$this->install_config->set('board_name', $board_name); +		$this->install_config->set('board_description', $board_desc); + +		if ($lang_valid) +		{ +			$this->install_config->set('default_lang', $default_lang); +		} +		else +		{ +			$this->request_form_data(true); +		} +	} + +	/** +	 * Request data from the user +	 * +	 * @param bool $use_request_data Whether to use submited data +	 * +	 * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data +	 */ +	protected function request_form_data($use_request_data = false) +	{ +		if ($use_request_data) +		{ +			$board_name		= $this->io_handler->get_input('board_name', '', true); +			$board_desc		= $this->io_handler->get_input('board_description', '', true); +		} +		else +		{ +			$board_name		= '{L_CONFIG_SITENAME}'; +			$board_desc		= '{L_CONFIG_SITE_DESC}'; +		} + +		// Use language because we only check this to be valid +		$default_lang	= $this->install_config->get('user_language', 'en'); + +		$langs = $this->language_helper->get_available_languages(); +		$lang_options = array(); + +		foreach ($langs as $lang) +		{ +			$lang_options[] = array( +				'value'		=> $lang['iso'], +				'label'		=> $lang['local_name'], +				'selected'	=> ($default_lang === $lang['iso']), +			); +		} + +		$board_form = array( +			'default_lang' => array( +				'label'		=> 'DEFAULT_LANGUAGE', +				'type'		=> 'select', +				'options'	=> $lang_options, +			), +			'board_name' => array( +				'label'		=> 'BOARD_NAME', +				'type'		=> 'text', +				'default'	=> $board_name, +			), +			'board_description' => array( +				'label'		=> 'BOARD_DESCRIPTION', +				'type'		=> 'text', +				'default'	=> $board_desc, +			), +			'submit_board'	=> array( +				'label'	=> 'SUBMIT', +				'type'	=> 'submit', +			), +		); + +		$this->io_handler->add_user_form_group('BOARD_CONFIG', $board_form); + +		$this->io_handler->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_database_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php new file mode 100644 index 0000000000..f0e7f1f686 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_database_data.php @@ -0,0 +1,271 @@ +<?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; + +/** + * This class requests and validates database information from the user + */ +class obtain_database_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\database +	 */ +	protected $database_helper; + +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\database						$database_helper	Installer's database helper +	 * @param \phpbb\install\helper\config							$install_config		Installer's config helper +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler			Installer's input-output handler +	 */ +	public function __construct(\phpbb\install\helper\database $database_helper, +								\phpbb\install\helper\config $install_config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler) +	{ +		$this->database_helper	= $database_helper; +		$this->install_config	= $install_config; +		$this->io_handler		= $iohandler; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// Check if data is sent +		if ($this->io_handler->get_input('submit_database', false)) +		{ +			$this->process_form(); +		} +		else +		{ +			$this->request_form_data(); +		} +	} + +	/** +	 * Process form data +	 */ +	protected function process_form() +	{ +		// Collect database data +		$dbms			= $this->io_handler->get_input('dbms', ''); +		$dbhost			= $this->io_handler->get_input('dbhost', ''); +		$dbport			= $this->io_handler->get_input('dbport', ''); +		$dbuser			= $this->io_handler->get_input('dbuser', ''); +		$dbpasswd		= $this->io_handler->get_input('dbpasswd', '', true); +		$dbname			= $this->io_handler->get_input('dbname', ''); +		$table_prefix	= $this->io_handler->get_input('table_prefix', ''); + +		// Check database data +		$user_data_vaild = $this->check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpasswd, $dbname, $table_prefix); + +		// Save database data if it is correct +		if ($user_data_vaild) +		{ +			$this->install_config->set('dbms', $dbms); +			$this->install_config->set('dbhost', $dbhost); +			$this->install_config->set('dbport', $dbport); +			$this->install_config->set('dbuser', $dbuser); +			$this->install_config->set('dbpasswd', $dbpasswd); +			$this->install_config->set('dbname', $dbname); +			$this->install_config->set('table_prefix', $table_prefix); +		} +		else +		{ +			$this->request_form_data(true); +		} +	} + +	/** +	 * Request data from the user +	 * +	 * @param bool $use_request_data Whether to use submited data +	 * +	 * @throws \phpbb\install\exception\user_interaction_required_exception When the user is required to provide data +	 */ +	protected function request_form_data($use_request_data = false) +	{ +		if ($use_request_data) +		{ +			$dbms			= $this->io_handler->get_input('dbms', ''); +			$dbhost			= $this->io_handler->get_input('dbhost', ''); +			$dbport			= $this->io_handler->get_input('dbport', ''); +			$dbuser			= $this->io_handler->get_input('dbuser', ''); +			$dbname			= $this->io_handler->get_input('dbname', ''); +			$table_prefix	= $this->io_handler->get_input('table_prefix', 'phpbb_'); +		} +		else +		{ +			$dbms			= ''; +			$dbhost			= ''; +			$dbport			= ''; +			$dbuser			= ''; +			$dbname			= ''; +			$table_prefix	= 'phpbb_'; +		} + +		$dbms_select = array(); +		foreach ($this->database_helper->get_available_dbms() as $dbms_key => $dbms_array) +		{ +			$dbms_select[] = array( +				'value'		=> $dbms_key, +				'label'		=> 'DB_OPTION_' . strtoupper($dbms_key), +				'selected'	=> ($dbms_key === $dbms), +			); +		} + +		$database_form = array( +			'dbms' => array( +				'label'		=> 'DBMS', +				'type'		=> 'select', +				'options'	=> $dbms_select, +			), +			'dbhost' => array( +				'label'			=> 'DB_HOST', +				'description'	=> 'DB_HOST_EXPLAIN', +				'type'			=> 'text', +				'default'		=> $dbhost, +			), +			'dbport' => array( +				'label'			=> 'DB_PORT', +				'description'	=> 'DB_PORT_EXPLAIN', +				'type'			=> 'text', +				'default'		=> $dbport, +			), +			'dbuser' => array( +				'label'		=> 'DB_USERNAME', +				'type'		=> 'text', +				'default'	=> $dbuser, +			), +			'dbpasswd' => array( +				'label'		=> 'DB_PASSWORD', +				'type'	=> 'password', +			), +			'dbname' => array( +				'label'		=> 'DB_NAME', +				'type'		=> 'text', +				'default'	=> $dbname, +			), +			'table_prefix' => array( +				'label'			=> 'TABLE_PREFIX', +				'description'	=> 'TABLE_PREFIX_EXPLAIN', +				'type'			=> 'text', +				'default'		=> $table_prefix, +			), +			'submit_database' => array( +				'label'	=> 'SUBMIT', +				'type'	=> 'submit', +			), +		); + +		$this->io_handler->add_user_form_group('DB_CONFIG', $database_form); + +		// Require user interaction +		$this->io_handler->send_response(); +		throw new user_interaction_required_exception(); +	} + +	/** +	 * Check database data +	 * +	 * @param string	$dbms			Selected database type +	 * @param string	$dbhost			Database host address +	 * @param int		$dbport			Database port number +	 * @param string	$dbuser			Database username +	 * @param string	$dbpass			Database password +	 * @param string	$dbname			Database name +	 * @param string	$table_prefix	Database table prefix +	 * +	 * @return bool	True if database data is correct, false otherwise +	 */ +	protected function check_database_data($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix) +	{ +		$available_dbms = $this->database_helper->get_available_dbms(); +		$data_valid = true; + +		// Check if PHP has the database extensions for the specified DBMS +		if (!isset($available_dbms[$dbms])) +		{ +			$this->io_handler->add_error_message('INST_ERR_NO_DB'); +			$data_valid = false; +		} + +		// Validate table prefix +		$prefix_valid = $this->database_helper->validate_table_prefix($dbms, $table_prefix); +		if (is_array($prefix_valid)) +		{ +			foreach ($prefix_valid as $error) +			{ +				$this->io_handler->add_error_message( +					$error['title'], +					(isset($error['description'])) ? $error['description'] : false +				); +			} + +			$data_valid = false; +		} + +		// Try to connect to database if all provided data is valid +		if ($data_valid) +		{ +			$connect_test = $this->database_helper->check_database_connection($dbms, $dbhost, $dbport, $dbuser, $dbpass, $dbname, $table_prefix); +			if (is_array($connect_test)) +			{ +				foreach ($connect_test as $error) +				{ +					$this->io_handler->add_error_message( +						$error['title'], +						(isset($error['description'])) ? $error['description'] : false +					); +				} + +				$data_valid = false; +			} +		} + +		return $data_valid; +	} + +	/** +	 * {@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_email_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php new file mode 100644 index 0000000000..b04b8e353f --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_email_data.php @@ -0,0 +1,167 @@ +<?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; + +class obtain_email_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$config		Installer's config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler	Installer's input-output handler +	 */ +	public function __construct(\phpbb\install\helper\config $config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler) +	{ +		$this->install_config	= $config; +		$this->io_handler		= $iohandler; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// E-mail data +		$email_enable	= $this->io_handler->get_input('email_enable', true); +		$smtp_delivery	= $this->io_handler->get_input('smtp_delivery', ''); +		$smtp_host		= $this->io_handler->get_input('smtp_host', ''); +		$smtp_auth		= $this->io_handler->get_input('smtp_auth', ''); +		$smtp_user		= $this->io_handler->get_input('smtp_user', ''); +		$smtp_passwd	= $this->io_handler->get_input('smtp_pass', ''); + +		$auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); + +		// Check if data is sent +		if ($this->io_handler->get_input('submit_email', false)) +		{ +			$this->install_config->set('email_enable', $email_enable); +			$this->install_config->set('smtp_delivery', $smtp_delivery); +			$this->install_config->set('smtp_host', $smtp_host); +			$this->install_config->set('smtp_auth', $smtp_auth); +			$this->install_config->set('smtp_user', $smtp_user); +			$this->install_config->set('smtp_pass', $smtp_passwd); +		} +		else +		{ +			$auth_options = array(); +			foreach ($auth_methods as $method) +			{ +				$auth_options[] = array( +					'value'		=> $method, +					'label'		=> 'SMTP_' . str_replace('-', '_', $method), +					'selected'	=> false, +				); +			} + +			$email_form = array( +				'email_enable' => array( +					'label'			=> 'ENABLE_EMAIL', +					'description'	=> 'COOKIE_SECURE_EXPLAIN', +					'type'			=> 'radio', +					'options'		=> array( +						array( +							'value'		=> 1, +							'label'		=> 'ENABLE', +							'selected'	=> true, +						), +						array( +							'value'		=> 0, +							'label'		=> 'DISABLE', +							'selected'	=> false, +						), +					), +				), +				'smtp_delivery' => array( +					'label'			=> 'USE_SMTP', +					'description'	=> 'USE_SMTP_EXPLAIN', +					'type'			=> 'radio', +					'options'		=> array( +						array( +							'value'		=> 0, +							'label'		=> 'NO', +							'selected'	=> true, +						), +						array( +							'value'		=> 1, +							'label'		=> 'YES', +							'selected'	=> false, +						), +					), +				), +				'smtp_host' => array( +					'label'			=> 'SMTP_SERVER', +					'type'			=> 'text', +					'default'		=> $smtp_host, +				), +				'smtp_auth' => array( +					'label'			=> 'SMTP_AUTH_METHOD', +					'description'	=> 'SMTP_AUTH_METHOD_EXPLAIN', +					'type'			=> 'select', +					'options'		=> $auth_options, +				), +				'smtp_user' => array( +					'label'			=> 'SMTP_USERNAME', +					'description'	=> 'SMTP_USERNAME_EXPLAIN', +					'type'			=> 'text', +					'default'		=> $smtp_user, +				), +				'smtp_pass' => array( +					'label'			=> 'SMTP_PASSWORD', +					'description'	=> 'SMTP_PASSWORD_EXPLAIN', +					'type'			=> 'password', +				), +				'submit_email' => array( +					'label'	=> 'SUBMIT', +					'type'	=> 'submit', +				), +			); + +			$this->io_handler->add_user_form_group('EMAIL_CONFIG', $email_form); + +			$this->io_handler->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_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_imagick_path.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php new file mode 100644 index 0000000000..9f74b61770 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_imagick_path.php @@ -0,0 +1,89 @@ +<?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; + +class obtain_imagick_path extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $config; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config	$config	Installer's config +	 */ +	public function __construct(\phpbb\install\helper\config $config) +	{ +		$this->config = $config; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// Can we find Imagemagick anywhere on the system? +		$exe = (DIRECTORY_SEPARATOR == '\\') ? '.exe' : ''; + +		$magic_home = getenv('MAGICK_HOME'); +		$img_imagick = ''; +		if (empty($magic_home)) +		{ +			$locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); +			$path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); + +			$locations = array_merge($path_locations, $locations); +			foreach ($locations as $location) +			{ +				// The path might not end properly, fudge it +				if (substr($location, -1, 1) !== '/') +				{ +					$location .= '/'; +				} + +				if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) +				{ +					$img_imagick = str_replace('\\', '/', $location); +					continue; +				} +			} +		} +		else +		{ +			$img_imagick = str_replace('\\', '/', $magic_home); +		} + +		$this->config->set('img_imagick', $img_imagick); +	} + +	/** +	 * {@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_server_data.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php new file mode 100644 index 0000000000..654b5534a9 --- /dev/null +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_server_data.php @@ -0,0 +1,203 @@ +<?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; + +/** + * This class requests and saves some information about the server + */ +class obtain_server_data extends \phpbb\install\task_base implements \phpbb\install\task_interface +{ +	/** +	 * @var \phpbb\install\helper\config +	 */ +	protected $install_config; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $io_handler; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\install\helper\config							$config		Installer's config +	 * @param \phpbb\install\helper\iohandler\iohandler_interface	$iohandler	Installer's input-output handler +	 */ +	public function __construct(\phpbb\install\helper\config $config, +								\phpbb\install\helper\iohandler\iohandler_interface $iohandler) +	{ +		$this->install_config	= $config; +		$this->io_handler		= $iohandler; + +		parent::__construct(true); +	} +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$cookie_secure = $this->io_handler->is_secure(); +		$server_protocol = ($this->io_handler->is_secure()) ? 'https://' : 'http://'; +		$server_port = $this->io_handler->get_server_variable('SERVER_PORT', 0); + +		// HTTP_HOST is having the correct browser url in most cases... +		$server_name = strtolower(htmlspecialchars_decode($this->io_handler->get_header_variable( +			'Host', +			$this->io_handler->get_server_variable('SERVER_NAME') +		))); + +		// HTTP HOST can carry a port number... +		if (strpos($server_name, ':') !== false) +		{ +			$server_name = substr($server_name, 0, strpos($server_name, ':')); +		} + +		$script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('PHP_SELF')); + +		if (!$script_path) +		{ +			$script_path = htmlspecialchars_decode($this->io_handler->get_server_variable('REQUEST_URI')); +		} + +		$script_path = str_replace(array('\\', '//'), '/', $script_path); +		$script_path = trim(dirname(dirname(dirname($script_path)))); // Because we are in install/app.php/route_name + +		// Server data +		$cookie_secure		= $this->io_handler->get_input('cookie_secure', $cookie_secure); +		$server_protocol	= $this->io_handler->get_input('server_protocol', $server_protocol); +		$force_server_vars	= $this->io_handler->get_input('force_server_vars', 0); +		$server_name		= $this->io_handler->get_input('server_name', $server_name); +		$server_port		= $this->io_handler->get_input('server_port', $server_port); +		$script_path		= $this->io_handler->get_input('script_path', $script_path); + +		// Clean up script path +		if ($script_path !== '/') +		{ +			// Adjust destination path (no trailing slash) +			if (substr($script_path, -1) === '/') +			{ +				$script_path = substr($script_path, 0, -1); +			} + +			$script_path = str_replace(array('../', './'), '', $script_path); + +			if ($script_path[0] !== '/') +			{ +				$script_path = '/' . $script_path; +			} +		} + +		// Check if data is sent +		if ($this->io_handler->get_input('submit_server', false)) +		{ +			$this->install_config->set('cookie_secure', $cookie_secure); +			$this->install_config->set('server_protocol', $server_protocol); +			$this->install_config->set('force_server_vars', $force_server_vars); +			$this->install_config->set('server_name', $server_name); +			$this->install_config->set('server_port', $server_port); +			$this->install_config->set('script_path', $script_path); +		} +		else +		{ +			// Render form +			$server_form = array( +				'cookie_secure' => array( +					'label'			=> 'COOKIE_SECURE', +					'description'	=> 'COOKIE_SECURE_EXPLAIN', +					'type'			=> 'radio', +					'options'		=> array( +						array( +							'value'		=> 0, +							'label'		=> 'NO', +							'selected'	=> (!$cookie_secure), +						), +						array( +							'value'		=> 1, +							'label'		=> 'YES', +							'selected'	=> ($cookie_secure), +						), +					), +				), +				'force_server_vars' => array( +					'label'			=> 'FORCE_SERVER_VARS', +					'description'	=> 'FORCE_SERVER_VARS_EXPLAIN', +					'type'			=> 'radio', +					'options'		=> array( +						array( +							'value'		=> 0, +							'label'		=> 'NO', +							'selected'	=> true, +						), +						array( +							'value'		=> 1, +							'label'		=> 'YES', +							'selected'	=> false, +						), +					), +				), +				'server_protocol' => array( +					'label'			=> 'SERVER_PROTOCOL', +					'description'	=> 'SERVER_PROTOCOL_EXPLAIN', +					'type'			=> 'text', +					'default'		=> $server_protocol, +				), +				'server_name' => array( +					'label'			=> 'SERVER_NAME', +					'description'	=> 'SERVER_NAME_EXPLAIN', +					'type'			=> 'text', +					'default'		=> $server_name, +				), +				'server_port' => array( +					'label'			=> 'SERVER_PORT', +					'description'	=> 'SERVER_PORT_EXPLAIN', +					'type'			=> 'text', +					'default'		=> $server_port, +				), +				'script_path' => array( +					'label'			=> 'SCRIPT_PATH', +					'description'	=> 'SCRIPT_PATH_EXPLAIN', +					'type'			=> 'text', +					'default'		=> $script_path, +				), +				'submit_server' => array( +					'label'	=> 'SUBMIT', +					'type'	=> 'submit', +				) +			); + +			$this->io_handler->add_user_form_group('SERVER_CONFIG', $server_form); + +			$this->io_handler->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_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/abstract_requirements_module.php b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php new file mode 100644 index 0000000000..26593e6777 --- /dev/null +++ b/phpBB/phpbb/install/module/requirements/abstract_requirements_module.php @@ -0,0 +1,106 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +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; + +/** + * Base class for requirements installer module + */ +abstract class abstract_requirements_module extends module_base +{ +	public function run() +	{ +		$tests_passed = true; + +		// Recover install progress +		$task_name = $this->recover_progress(); +		$task_found = false; + +		/** +		 * @var string							$name	ID of the service +		 * @var \phpbb\install\task_interface	$task	Task object +		 */ +		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) +			{ +				throw new resource_limit_reached_exception(); +			} + +			// Skip forward until the next task is reached +			if (!$task_found) +			{ +				if ($name === $task_name || empty($task_name)) +				{ +					$task_found = true; + +					if ($name === $task_name) +					{ +						continue; +					} +				} +				else +				{ +					continue; +				} +			} + +			// Check if we can run the task +			if (!$task->is_essential() && !$task->check_requirements()) +			{ +				continue; +			} + +			if ($this->allow_progress_bar) +			{ +				$this->install_config->increment_current_task_progress(); +			} + +			$test_result = $task->run(); +			$tests_passed = ($tests_passed) ? $test_result : false; +		} + +		// Module finished, so clear task progress +		$this->install_config->set_finished_task(''); + +		// Check if tests have failed +		if (!$tests_passed) +		{ +			// If requirements are not met, exit form installer +			// Set up UI for retesting +			$this->iohandler->add_user_form_group('', array( +				'install'	=> array( +					'label'	=> 'RETEST_REQUIREMENTS', +					'type'	=> 'submit', +				), +			)); + +			// Send the response and quit +			$this->iohandler->send_response(); +			throw new user_interaction_required_exception(); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_step_count() +	{ +		return 0; +	} +} 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 new file mode 100644 index 0000000000..2aec3915e0 --- /dev/null +++ b/phpBB/phpbb/install/module/requirements/task/check_filesystem.php @@ -0,0 +1,275 @@ +<?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; + +/** + * Checks filesystem requirements + */ +class check_filesystem extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\filesystem\filesystem_interface +	 */ +	protected $filesystem; + +	/** +	 * @var array +	 */ +	protected $files_to_check; + +	/** +	 * @var bool +	 */ +	protected $tests_passed; + +	/** +	 * @var string +	 */ +	protected $phpbb_root_path; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $response; + +	/** +	 * Constructor +	 * +	 * @param \phpbb\filesystem\filesystem_interface				$filesystem			filesystem handler +	 * @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, $check_config_php = true) +	{ +		parent::__construct(true); + +		$this->filesystem		= $filesystem; +		$this->response			= $response; +		$this->phpbb_root_path	= $phpbb_root_path; + +		$this->tests_passed = false; + +		// Files/Directories to check +		// All file/directory names must be relative to phpBB's root path +		$this->files_to_check = array( +			array( +				'path' => 'cache/', +				'failable' => false, +				'is_file' => false, +			), +			array( +				'path' => 'store/', +				'failable' => false, +				'is_file' => false, +			), +			array( +				'path' => 'files/', +				'failable' => false, +				'is_file' => false, +			), +			array( +				'path' => 'images/avatars/upload/', +				'failable' => true, +				'is_file' => false, +			), +		); + +		if ($check_config_php) +		{ +			$this->files_to_check[] = array( +				'path' => "config.$php_ext", +				'failable' => false, +				'is_file' => true, +			); +		} +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		$this->tests_passed = true; + +		// Check files/directories to be writable +		foreach ($this->files_to_check as $file) +		{ +			if ($file['is_file']) +			{ +				$this->check_file($file['path'], $file['failable']); +			} +			else +			{ +				$this->check_dir($file['path'], $file['failable']); +			} +		} + +		return $this->tests_passed; +	} + +	/** +	 * 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) ? false : $is_passed; +	} + +	/** +	 * Check if a file is readable and writable +	 * +	 * @param string	$file		Filename +	 * @param bool		$failable	Whether failing test should interrupt installation process +	 */ +	protected function check_file($file, $failable = false) +	{ +		$path = $this->phpbb_root_path . $file; +		$exists = $writable = true; + +		// Try to create file if it does not exists +		if (!file_exists($path)) +		{ +			$fp = @fopen($path, 'w'); +			@fclose($fp); +			try +			{ +				$this->filesystem->phpbb_chmod($path, +					\phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE +				); +				$exists = true; +			} +			catch (\phpbb\filesystem\exception\filesystem_exception $e) +			{ +				// Do nothing +			} +		} + +		if (file_exists($path)) +		{ +			if (!$this->filesystem->is_writable($path)) +			{ +				$writable = false; +			} +		} +		else +		{ +			$exists = $writable = false; +		} + +		$this->set_test_passed(($exists && $writable) || $failable); + +		if (!($exists && $writable)) +		{ +			$title = ($exists) ? 'FILE_NOT_WRITABLE' : 'FILE_NOT_EXISTS'; +			$description = array($title . '_EXPLAIN', $file); + +			if ($failable) +			{ +				$this->response->add_warning_message($title, $description); +			} +			else +			{ +				$this->response->add_error_message($title, $description); +			} +		} +	} + +	/** +	 * Check if a directory is readable and writable +	 * +	 * @param string	$dir		Filename +	 * @param bool		$failable	Whether failing test should abort the installation process +	 */ +	protected function check_dir($dir, $failable = false) +	{ +		$path = $this->phpbb_root_path . $dir; +		$exists = $writable = false; + +		// Try to create the directory if it does not exist +		if (!file_exists($path)) +		{ +			try +			{ +				$this->filesystem->mkdir($path, 0777); +				$this->filesystem->phpbb_chmod($path, +					\phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE +				); +				$exists = true; +			} +			catch (\phpbb\filesystem\exception\filesystem_exception $e) +			{ +				// Do nothing +			} +		} + +		// Now really check +		if (file_exists($path) && is_dir($path)) +		{ +			try +			{ +				$exists = true; +				$this->filesystem->phpbb_chmod($path, +					\phpbb\filesystem\filesystem_interface::CHMOD_READ | \phpbb\filesystem\filesystem_interface::CHMOD_WRITE +				); +			} +			catch (\phpbb\filesystem\exception\filesystem_exception $e) +			{ +				// Do nothing +			} +		} + +		if ($this->filesystem->is_writable($path)) +		{ +			$writable = true; +		} + +		$this->set_test_passed(($exists && $writable) || $failable); + +		if (!($exists && $writable)) +		{ +			$title = ($exists) ? 'DIRECTORY_NOT_WRITABLE' : 'DIRECTORY_NOT_EXISTS'; +			$description = array($title . '_EXPLAIN', $dir); + +			if ($failable) +			{ +				$this->response->add_warning_message($title, $description); +			} +			else +			{ +				$this->response->add_error_message($title, $description); +			} +		} +	} + +	/** +	 * {@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/task/check_server_environment.php b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php new file mode 100644 index 0000000000..62485a2097 --- /dev/null +++ b/phpBB/phpbb/install/module/requirements/task/check_server_environment.php @@ -0,0 +1,190 @@ +<?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; + +/** + * Installer task that checks if the server meats phpBB requirements + */ +class check_server_environment extends \phpbb\install\task_base +{ +	/** +	 * @var \phpbb\install\helper\database +	 */ +	protected $database_helper; + +	/** +	 * @var \phpbb\install\helper\iohandler\iohandler_interface +	 */ +	protected $response_helper; + +	/** +	 * @var bool +	 */ +	protected $tests_passed; + +	/** +	 * Constructor +	 * +	 * @param	\phpbb\install\helper\database	$database_helper +	 * @param	\phpbb\install\helper\iohandler\iohandler_interface	$response +	 */ +	public function __construct(\phpbb\install\helper\database $database_helper, +								\phpbb\install\helper\iohandler\iohandler_interface $response) +	{ +		$this->database_helper	= $database_helper; +		$this->response_helper	= $response; +		$this->tests_passed		= true; + +		parent::__construct(true); +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// +		// Check requirements +		// The error messages should be set in the check_ functions +		// + +		// Check PHP version +		$this->check_php_version(); + +		// Check for getimagesize() +		$this->check_image_size(); + +		// Check for PCRE support +		$this->check_pcre(); + +		// Check for JSON support +		$this->check_json(); + +		// Check for dbms support +		$this->check_available_dbms(); + +		return $this->tests_passed; +	} + +	/** +	 * 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) ? false : $is_passed; +	} + +	/** +	 * Check if the requirements for PHP version is met +	 */ +	protected function check_php_version() +	{ +		$php_version = PHP_VERSION; + +		if (version_compare($php_version, '5.4') < 0) +		{ +			$this->response_helper->add_error_message('PHP_VERSION_REQD', 'PHP_VERSION_REQD_EXPLAIN'); + +			$this->set_test_passed(false); +			return; +		} + +		$this->set_test_passed(true); +	} + +	/** +	 * Checks if the installed PHP has getimagesize() available +	 */ +	protected function check_image_size() +	{ +		if (!@function_exists('getimagesize')) +		{ +			$this->response_helper->add_error_message('PHP_GETIMAGESIZE_SUPPORT', 'PHP_GETIMAGESIZE_SUPPORT_EXPLAIN'); + +			$this->set_test_passed(false); +			return; +		} + +		$this->set_test_passed(true); +	} + +	/** +	 * Checks if the installed PHP supports PCRE +	 */ +	protected function check_pcre() +	{ +		if (@preg_match('//u', '')) +		{ +			$this->set_test_passed(true); +			return; +		} + +		$this->response_helper->add_error_message('PCRE_UTF_SUPPORT', 'PCRE_UTF_SUPPORT_EXPLAIN'); + +		$this->set_test_passed(false); +	} + +	/** +	 * Checks whether PHP's JSON extension is available or not +	 */ +	protected function check_json() +	{ +		if (@extension_loaded('json')) +		{ +			$this->set_test_passed(true); +			return; +		} + +		$this->response_helper->add_error_message('PHP_JSON_SUPPORT', 'PHP_JSON_SUPPORT_EXPLAIN'); + +		$this->set_test_passed(false); +	} + +	/** +	 * Check if any supported DBMS is available +	 */ +	protected function check_available_dbms() +	{ +		$available_dbms = $this->database_helper->get_available_dbms(false, true); + +		if ($available_dbms['ANY_DB_SUPPORT']) +		{ +			$this->set_test_passed(true); +			return; +		} + +		$this->response_helper->add_error_message('PHP_SUPPORTED_DB', 'PHP_SUPPORTED_DB_EXPLAIN'); + +		$this->set_test_passed(false); +	} + +	/** +	 * {@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/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..84ec6f73f5 --- /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', +				(isset($this->user->data['user_id'])) ? $this->user->data['user_id'] : ANONYMOUS, +				$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..e712b8ad6a --- /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, +						base64_decode($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..fbb465cc66 --- /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, +								base64_decode($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 new file mode 100644 index 0000000000..fb68c3aca2 --- /dev/null +++ b/phpBB/phpbb/install/module_base.php @@ -0,0 +1,218 @@ +<?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; + +use phpbb\di\ordered_service_collection; +use phpbb\install\exception\resource_limit_reached_exception; +use phpbb\install\helper\config; +use phpbb\install\helper\iohandler\iohandler_interface; + +/** + * Base class for installer module + */ +abstract class module_base implements module_interface +{ +	/** +	 * @var config +	 */ +	protected $install_config; + +	/** +	 * @var iohandler_interface +	 */ +	protected $iohandler; + +	/** +	 * @var bool +	 */ +	protected $is_essential; + +	/** +	 * Array of tasks for installer module +	 * +	 * @var ordered_service_collection +	 */ +	protected $task_collection; + +	/** +	 * @var array +	 */ +	protected $task_step_count; + +	/** +	 * @var bool +	 */ +	protected $allow_progress_bar; + +	/** +	 * Installer module constructor +	 * +	 * @param ordered_service_collection	$tasks				array of installer tasks for installer module +	 * @param bool							$essential			flag indicating whether the module is essential or not +	 * @param bool							$allow_progress_bar	flag indicating whether or not to send progress information from within the module +	 */ +	public function __construct(ordered_service_collection $tasks, $essential = true, $allow_progress_bar = true) +	{ +		$this->task_collection		= $tasks; +		$this->is_essential			= $essential; +		$this->allow_progress_bar	= $allow_progress_bar; +	} + +	/** +	 * Dependency getter +	 * +	 * @param config				$config +	 * @param iohandler_interface	$iohandler +	 */ +	public function setup(config $config, iohandler_interface $iohandler) +	{ +		$this->install_config	= $config; +		$this->iohandler		= $iohandler; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function is_essential() +	{ +		return $this->is_essential; +	} + +	/** +	 * {@inheritdoc} +	 * +	 * Overwrite this method if your task is non-essential! +	 */ +	public function check_requirements() +	{ +		return true; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function run() +	{ +		// Recover install progress +		$task_name = $this->recover_progress(); +		$task_found = false; + +		/** +		 * @var string							$name	ID of the service +		 * @var \phpbb\install\task_interface	$task	Task object +		 */ +		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) +			{ +				throw new resource_limit_reached_exception(); +			} + +			// Skip forward until the next task is reached +			if (!$task_found) +			{ +				if ($name === $task_name || empty($task_name)) +				{ +					$task_found = true; + +					if ($name === $task_name) +					{ +						continue; +					} +				} +				else +				{ +					continue; +				} +			} + +			// Send progress information +			if ($this->allow_progress_bar) +			{ +				$this->iohandler->set_progress( +					$task->get_task_lang_name(), +					$this->install_config->get_current_task_progress() +				); +			} + +			// Check if we can run the task +			if (!$task->is_essential() && !$task->check_requirements()) +			{ +				$this->iohandler->add_log_message(array( +					'SKIP_TASK', +					$name, +				)); + +				$this->install_config->increment_current_task_progress($this->task_step_count[$name]); +				continue; +			} + +			if ($this->allow_progress_bar) +			{ +				// Only increment progress by one, as if a task has more than one steps +				// then that should be incremented in the task itself +				$this->install_config->increment_current_task_progress(); +			} + +			$task->run(); + +			// Log install progress +			$this->install_config->set_finished_task($name); + +			// Send progress information +			if ($this->allow_progress_bar) +			{ +				$this->iohandler->set_progress( +					$task->get_task_lang_name(), +					$this->install_config->get_current_task_progress() +				); +			} + +			$this->iohandler->send_response(); +		} + +		// Module finished, so clear task progress +		$this->install_config->set_finished_task(''); +	} + +	/** +	 * Returns the next task's name +	 * +	 * @return string	Index of the array element of the next task +	 */ +	protected function recover_progress() +	{ +		$progress_array = $this->install_config->get_progress_data(); +		return $progress_array['last_task_name']; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function get_step_count() +	{ +		$task_step_count = 0; +		$task_class_names = $this->task_collection->get_service_classes(); + +		foreach ($task_class_names as $name => $task_class) +		{ +			$step_count = $task_class::get_step_count(); +			$task_step_count += $step_count; +			$this->task_step_count[$name] = $step_count; +		} + +		return $task_step_count; +	} +} diff --git a/phpBB/phpbb/install/module_interface.php b/phpBB/phpbb/install/module_interface.php new file mode 100644 index 0000000000..a2d61e3958 --- /dev/null +++ b/phpBB/phpbb/install/module_interface.php @@ -0,0 +1,63 @@ +<?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; + +/** + * Interface for installer modules + * + * An installer module is a task collection which executes installer tasks. + */ +interface module_interface +{ +	/** +	 * Checks if the execution of the module is essential to install phpBB or it can be skipped +	 * +	 * Note: Please note that all the non-essential modules have to implement check_requirements() +	 * method. +	 * +	 * @return	bool	true if the module is essential, false otherwise +	 */ +	public function is_essential(); + +	/** +	 * Checks requirements for the tasks +	 * +	 * Note: Only need to be implemented for non-essential tasks, as essential tasks +	 * requirements should be checked in the requirements install module. +	 * +	 * @return bool	true if the task's requirements are met +	 */ +	public function check_requirements(); + +	/** +	 * Executes the task +	 * +	 * @return	null +	 */ +	public function run(); + +	/** +	 * Returns the number of tasks in the module +	 * +	 * @return int +	 */ +	public function get_step_count(); + +	/** +	 * Returns an array to the correct navigation stage +	 * +	 * @return array +	 */ +	public function get_navigation_stage_path(); +} diff --git a/phpBB/phpbb/install/task_base.php b/phpBB/phpbb/install/task_base.php new file mode 100644 index 0000000000..b5199be4af --- /dev/null +++ b/phpBB/phpbb/install/task_base.php @@ -0,0 +1,53 @@ +<?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; + +/** + * Base class for installer task + */ +abstract class task_base implements task_interface +{ +	/** +	 * @var bool +	 */ +	protected $is_essential; + +	/** +	 * Constructor +	 * +	 * @param bool $essential +	 */ +	public function __construct($essential = true) +	{ +		$this->is_essential = $essential; +	} + +	/** +	 * {@inheritdoc} +	 */ +	public function is_essential() +	{ +		return $this->is_essential; +	} + +	/** +	 * {@inheritdoc} +	 * +	 * Note: Overwrite this method if your task is non-essential! +	 */ +	public function check_requirements() +	{ +		return true; +	} +} diff --git a/phpBB/phpbb/install/task_interface.php b/phpBB/phpbb/install/task_interface.php new file mode 100644 index 0000000000..794cb16482 --- /dev/null +++ b/phpBB/phpbb/install/task_interface.php @@ -0,0 +1,61 @@ +<?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; + +/** + * Interface for installer tasks + */ +interface task_interface +{ +	/** +	 * Returns the number of steps the task contains +	 * +	 * This is a helper method to provide a better progress bar for the front-end. +	 * +	 * @return int	The number of steps that the task contains +	 */ +	static public function get_step_count(); + +	/** +	 * Checks if the task is essential to install phpBB or it can be skipped +	 * +	 * Note: Please note that all the non-essential modules have to implement check_requirements() +	 * method. +	 * +	 * @return	bool	true if the task is essential, false otherwise +	 */ +	public function is_essential(); + +	/** +	 * Checks requirements for the tasks +	 * +	 * Note: Only need to be implemented for non-essential tasks, as essential tasks +	 * requirements should be checked in the requirements install module. +	 * +	 * @return bool	true if the task's requirements are met +	 */ +	public function check_requirements(); + +	/** +	 * Executes the task +	 */ +	public function run(); + +	/** +	 * Returns the language key of the name of the task +	 * +	 * @return string +	 */ +	public function get_task_lang_name(); +} | 
