From af21b8b6c147f19e6c4aba1e0d4f558200dc2411 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Wed, 19 Jul 2017 14:26:07 +0200 Subject: [PATCH 01/20] [ticket/15287] Update storage PHPBB3-15287 --- .../storage/adapter/adapter_interface.php | 7 +++ phpBB/phpbb/storage/adapter/local.php | 16 +++++- phpBB/phpbb/storage/adapter_factory.php | 57 +++++++++++++++++++ phpBB/phpbb/storage/provider/local.php | 27 +++++++++ .../storage/provider/provider_interface.php | 20 +++++++ phpBB/phpbb/storage/storage.php | 4 +- 6 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 phpBB/phpbb/storage/adapter_factory.php create mode 100644 phpBB/phpbb/storage/provider/local.php create mode 100644 phpBB/phpbb/storage/provider/provider_interface.php diff --git a/phpBB/phpbb/storage/adapter/adapter_interface.php b/phpBB/phpbb/storage/adapter/adapter_interface.php index 70eb6f1cc7..c92a429ec8 100644 --- a/phpBB/phpbb/storage/adapter/adapter_interface.php +++ b/phpBB/phpbb/storage/adapter/adapter_interface.php @@ -15,6 +15,13 @@ namespace phpbb\storage\adapter; interface adapter_interface { + /** + * Set adapter parameters + * + * @param array options Storage-specific options. + */ + public function configure($options); + /** * Dumps content into a file. * diff --git a/phpBB/phpbb/storage/adapter/local.php b/phpBB/phpbb/storage/adapter/local.php index 68b9ce0c2c..1d229abf7b 100644 --- a/phpBB/phpbb/storage/adapter/local.php +++ b/phpBB/phpbb/storage/adapter/local.php @@ -15,7 +15,6 @@ namespace phpbb\storage\adapter; use phpbb\storage\exception\exception; use phpbb\filesystem\exception\filesystem_exception; -use phpbb\config\config; use phpbb\filesystem\filesystem; /** @@ -30,16 +29,27 @@ class local implements adapter_interface */ protected $filesystem; + /** @var string path */ + protected $phpbb_root_path; + /** @var string path */ protected $root_path; /** * Constructor */ - public function __construct(config $config, filesystem $filesystem, $phpbb_root_path, $path_key) + public function __construct(filesystem $filesystem, $phpbb_root_path) { $this->filesystem = $filesystem; - $this->root_path = $phpbb_root_path . $config[$path_key]; + $this->phpbb_root_path = $phpbb_root_path; + } + + /** + * {@inheritdoc} + */ + public function configure($options) + { + $this->root_path = $this->phpbb_root_path . $options['path']; if (substr($this->root_path, -1, 1) != DIRECTORY_SEPARATOR) { diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php new file mode 100644 index 0000000000..b63a10fea6 --- /dev/null +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -0,0 +1,57 @@ + + * @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\storage; + +use phpbb\config\config; +use phpbb\di\service_collection; +use Symfony\Component\DependencyInjection\ContainerInterface; + +class adapter_factory +{ + protected $config; + protected $container; + protected $adapters; + protected $providers; + + public function __construct(config $config, ContainerInterface $container, service_collection $adapters, service_collection $providers) + { + $this->config = $config; + $this->container = $container; + $this->adapters = $adapters; + $this->providers = $providers; + } + + public function get($storage_name) + { + $provider_class = $this->config['storage\\' . $storage_name . '\\adapter']; + $provider = $this->providers->get_by_class($provider_class); + + $adapter = $this->adapters->get_by_class($provider->get_class()); + $adapter->configure($this->build_options($storage_name, $provider->get_options())); + + return $adapter; + } + + public function build_options($storage_name, array $definitions) + { + $options = []; + + foreach ($definitions as $def) + { + $options[$def] = $this->config['storage\\' . $storage_name . '\\config\\' . $def]; + } + + return $options; + } +} diff --git a/phpBB/phpbb/storage/provider/local.php b/phpBB/phpbb/storage/provider/local.php new file mode 100644 index 0000000000..6369c626c7 --- /dev/null +++ b/phpBB/phpbb/storage/provider/local.php @@ -0,0 +1,27 @@ + + * @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\storage\provider; + +class local implements provider_interface +{ + public function get_class() + { + return \phpbb\storage\adapter\local::class; + } + + public function get_options() + { + return ['path']; + } +} diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php new file mode 100644 index 0000000000..4d9a550e9a --- /dev/null +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -0,0 +1,20 @@ + + * @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\storage\provider; + +interface provider_interface +{ + public function get_class(); + public function get_options(); +} diff --git a/phpBB/phpbb/storage/storage.php b/phpBB/phpbb/storage/storage.php index f532f4d95f..04a66396e8 100644 --- a/phpBB/phpbb/storage/storage.php +++ b/phpBB/phpbb/storage/storage.php @@ -20,9 +20,9 @@ class storage { protected $adapter; - public function __construct($adapter) + public function __construct($factory, $storage_name) { - $this->adapter = $adapter; + $this->adapter = $factory->get($storage_name); } public function put_contents($path, $content) From 5897876f2ffc6c0655826f52ddfd06d1ee7c497f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Wed, 19 Jul 2017 14:33:35 +0200 Subject: [PATCH 02/20] [ticket/15287] Apply suggested change PHPBB3-15287 --- phpBB/phpbb/storage/adapter/local.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/storage/adapter/local.php b/phpBB/phpbb/storage/adapter/local.php index 1d229abf7b..cdf06176d5 100644 --- a/phpBB/phpbb/storage/adapter/local.php +++ b/phpBB/phpbb/storage/adapter/local.php @@ -51,7 +51,7 @@ class local implements adapter_interface { $this->root_path = $this->phpbb_root_path . $options['path']; - if (substr($this->root_path, -1, 1) != DIRECTORY_SEPARATOR) + if (substr($this->root_path, -1, 1) !== DIRECTORY_SEPARATOR) { $this->root_path = $this->root_path . DIRECTORY_SEPARATOR; } From 95ebd5d8945e525ba7f8229f60d95c042feeb9ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Wed, 19 Jul 2017 14:41:40 +0200 Subject: [PATCH 03/20] [ticket/15287] Update test PHPBB3-15287 --- tests/storage/adapter/local_test.php | 64 +++++++++++++++------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/tests/storage/adapter/local_test.php b/tests/storage/adapter/local_test.php index 42b4c5929b..a2725cd387 100644 --- a/tests/storage/adapter/local_test.php +++ b/tests/storage/adapter/local_test.php @@ -13,47 +13,51 @@ class phpbb_storage_adapter_local_test extends phpbb_test_case { - protected $adapter; + protected $adapter; + + protected $path; public function setUp() { parent::setUp(); - $config = new \phpbb\config\config(array( - 'test_path' => '.', - )); $filesystem = new \phpbb\filesystem\filesystem(); $phpbb_root_path = getcwd() . DIRECTORY_SEPARATOR; - $path_key = 'test_path'; - $this->adapter = new \phpbb\storage\adapter\local($config, $filesystem, $phpbb_root_path, $path_key); + + $this->adapter = new \phpbb\storage\adapter\local($filesystem, $phpbb_root_path); + $this->adapter->configure(['path' => 'test_path']); + + $this->path = $phpbb_root_path . 'test_path/'; + mkdir($this->path); } public function data_test_exists() { - yield ['README.md', true]; - yield ['nonexistent_file.php', false]; - yield ['phpBB/phpbb', true]; - yield ['nonexistent/folder', false]; + yield [$this->path . '../README.md', true]; + yield [$this->path . 'nonexistent_file.php', false]; + yield [$this->path . '../phpBB/phpbb', true]; + yield [$this->path . 'nonexistent/folder', false]; } public function tearDown() { $this->adapter = null; + rmdir($this->path); } public function test_put_contents() { $this->adapter->put_contents('file.txt', 'abc'); - $this->assertTrue(file_exists('file.txt')); - $this->assertEquals(file_get_contents('file.txt'), 'abc'); - unlink('file.txt'); + $this->assertTrue(file_exists($this->path . 'file.txt')); + $this->assertEquals(file_get_contents($this->path . 'file.txt'), 'abc'); + unlink($this->path . 'file.txt'); } public function test_get_contents() { - file_put_contents('file.txt', 'abc'); + file_put_contents($this->path . 'file.txt', 'abc'); $this->assertEquals($this->adapter->get_contents('file.txt'), 'abc'); - unlink('file.txt'); + unlink($this->path . 'file.txt'); } /** @@ -66,37 +70,37 @@ public function test_delete_file() { - file_put_contents('file.txt', ''); - $this->assertTrue(file_exists('file.txt')); + file_put_contents($this->path . 'file.txt', ''); + $this->assertTrue(file_exists($this->path . 'file.txt')); $this->adapter->delete('file.txt'); - $this->assertFalse(file_exists('file.txt')); + $this->assertFalse(file_exists($this->path . 'file.txt')); } public function test_delete_folder() { - mkdir('path/to/dir', 0777, true); - $this->assertTrue(file_exists('path/to/dir')); + mkdir($this->path . 'path/to/dir', 0777, true); + $this->assertTrue(file_exists($this->path . 'path/to/dir')); $this->adapter->delete('path'); - $this->assertFalse(file_exists('path/to/dir')); + $this->assertFalse(file_exists($this->path . 'path/to/dir')); } public function test_rename() { - file_put_contents('file.txt', ''); + file_put_contents($this->path . 'file.txt', ''); $this->adapter->rename('file.txt', 'file2.txt'); - $this->assertFalse(file_exists('file.txt')); - $this->assertTrue(file_exists('file2.txt')); - unlink('file2.txt'); + $this->assertFalse(file_exists($this->path . 'file.txt')); + $this->assertTrue(file_exists($this->path . 'file2.txt')); + unlink($this->path . 'file2.txt'); } public function test_copy() { - file_put_contents('file.txt', 'abc'); + file_put_contents($this->path . 'file.txt', 'abc'); $this->adapter->copy('file.txt', 'file2.txt'); - $this->assertEquals(file_get_contents('file.txt'), 'abc'); - $this->assertEquals(file_get_contents('file.txt'), 'abc'); - unlink('file.txt'); - unlink('file2.txt'); + $this->assertEquals(file_get_contents($this->path . 'file.txt'), 'abc'); + $this->assertEquals(file_get_contents($this->path . 'file.txt'), 'abc'); + unlink($this->path . 'file.txt'); + unlink($this->path . 'file2.txt'); } } From 440ef369ca64746d4c711a9e8ca5e5436363a795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 04:03:37 +0200 Subject: [PATCH 04/20] [ticket/15287] Add services PHPBB3-15287 --- phpBB/config/default/container/services.yml | 1 + .../default/container/services_files.yml | 32 +++++++++++++++ .../default/container/services_storage.yml | 41 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 phpBB/config/default/container/services_storage.yml diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 2f5a4bd5a6..950b8ae295 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -25,6 +25,7 @@ imports: - { resource: services_profilefield.yml } - { resource: services_report.yml } - { resource: services_routing.yml } + - { resource: services_storage.yml } - { resource: services_text_formatter.yml } - { resource: services_text_reparser.yml } - { resource: services_twig.yml } diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml index ba1fdb4c9a..44da208d8e 100644 --- a/phpBB/config/default/container/services_files.yml +++ b/phpBB/config/default/container/services_files.yml @@ -16,6 +16,17 @@ services: - '@mimetype.guesser' - '@plupload' + files.filespec_storage: + class: phpbb\files\filespec_storage + shared: false + arguments: + - '@language' + - '@php_ini' + - '@upload_imagesize' + - '%core.root_path%' + - '@mimetype.guesser' + - '@plupload' + files.upload: class: phpbb\files\upload shared: false @@ -36,6 +47,16 @@ services: - '@plupload' - '@request' + files.types.form_storage: + class: phpbb\files\types\form_storage + shared: false + arguments: + - '@files.factory' + - '@language' + - '@php_ini' + - '@plupload' + - '@request' + files.types.local: class: phpbb\files\types\local shared: false @@ -55,3 +76,14 @@ services: - '@php_ini' - '@request' - '%core.root_path%' + + files.types.remote_storage: + class: phpbb\files\types\remote_storage + shared: false + arguments: + - '@config' + - '@files.factory' + - '@language' + - '@php_ini' + - '@request' + - '%core.root_path%' diff --git a/phpBB/config/default/container/services_storage.yml b/phpBB/config/default/container/services_storage.yml new file mode 100644 index 0000000000..4a14f00962 --- /dev/null +++ b/phpBB/config/default/container/services_storage.yml @@ -0,0 +1,41 @@ +services: +# Factory + storage.adapter.factory: + class: phpbb\storage\adapter_factory + arguments: + - '@config' + - '@service_container' + - '@storage.adapter_collection' + - '@storage.provider_collection' + +# Collections + storage.adapter_collection: + class: phpbb\di\service_collection + arguments: + - '@service_container' + tags: + - { name: service_collection, tag: storage.adapter, class_name_aware: true } + + storage.provider_collection: + class: phpbb\di\service_collection + arguments: + - '@service_container' + tags: + - { name: service_collection, tag: storage.provider, class_name_aware: true } + +# Adapters + storage.adapter.local: + class: phpbb\storage\adapter\local + shared: false + arguments: + - '@filesystem' + - '%core.root_path%' + tags: + - { name: storage.adapter } + +# Providers + storage.provider.local: + class: phpbb\storage\provider\local + arguments: + tags: + - { name: storage.provider } From 1dbf75c32c024fb952ff824db74902f6913c0aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 04:08:52 +0200 Subject: [PATCH 05/20] [ticket/15287] Add filespec for storage PHPBB3-15287 --- phpBB/phpbb/files/filespec_storage.php | 510 +++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 phpBB/phpbb/files/filespec_storage.php diff --git a/phpBB/phpbb/files/filespec_storage.php b/phpBB/phpbb/files/filespec_storage.php new file mode 100644 index 0000000000..32204e075d --- /dev/null +++ b/phpBB/phpbb/files/filespec_storage.php @@ -0,0 +1,510 @@ + + * @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\files; + +use phpbb\language\language; + +/** + * Responsible for holding all file relevant information, as well as doing file-specific operations. + * The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on. + */ +class filespec_storage +{ + /** @var string File name */ + protected $filename = ''; + + /** @var string Real name of file */ + protected $realname = ''; + + /** @var string Upload name of file */ + protected $uploadname = ''; + + /** @var string Mimetype of file */ + protected $mimetype = ''; + + /** @var string File extension */ + protected $extension = ''; + + /** @var int File size */ + protected $filesize = 0; + + /** @var int Width of file */ + protected $width = 0; + + /** @var int Height of file */ + protected $height = 0; + + /** @var array Image info including type and size */ + protected $image_info = array(); + + /** @var string Destination file name */ + protected $destination_file = ''; + + /** @var string Destination file path */ + protected $destination_path = ''; + + /** @var bool Whether file was moved */ + protected $file_moved = false; + + /** @var bool Whether file is local */ + protected $local = false; + + /** @var bool Class initialization flag */ + protected $class_initialized = false; + + /** @var array Error array */ + public $error = array(); + + /** @var upload Instance of upload class */ + public $upload; + + /** @var \bantu\IniGetWrapper\IniGetWrapper ini_get() wrapper class */ + protected $php_ini; + + /** @var \FastImageSize\FastImageSize */ + protected $imagesize; + + /** @var language Language class */ + protected $language; + + /** @var \phpbb\plupload\plupload The plupload object */ + protected $plupload; + + /** @var \phpbb\mimetype\guesser phpBB Mimetype guesser */ + protected $mimetype_guesser; + + /** + * File upload class + * + * @param language $language Language + * @param \bantu\IniGetWrapper\IniGetWrapper $php_ini ini_get() wrapper + * @param \FastImageSize\FastImageSize $imagesize Imagesize class + * @param \phpbb\mimetype\guesser $mimetype_guesser Mime type guesser + * @param \phpbb\plupload\plupload $plupload Plupload + */ + public function __construct(language $language, \bantu\IniGetWrapper\IniGetWrapper $php_ini, \FastImageSize\FastImageSize $imagesize, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) + { + $this->language = $language; + $this->php_ini = $php_ini; + $this->imagesize = $imagesize; + $this->plupload = $plupload; + $this->mimetype_guesser = $mimetype_guesser; + } + + /** + * Set upload ary + * + * @param array $upload_ary Upload ary + * + * @return filespec This instance of the filespec class + */ + public function set_upload_ary($upload_ary) + { + if (!isset($upload_ary) || !sizeof($upload_ary)) + { + return $this; + } + + $this->class_initialized = true; + $this->filename = $upload_ary['tmp_name']; + $this->filesize = $upload_ary['size']; + $name = $upload_ary['name']; + $name = trim(utf8_basename($name)); + $this->realname = $this->uploadname = $name; + $this->mimetype = $upload_ary['type']; + + // Opera adds the name to the mime type + $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype; + + if (!$this->mimetype) + { + $this->mimetype = 'application/octet-stream'; + } + + $this->extension = strtolower(self::get_extension($this->realname)); + + // Try to get real filesize from temporary folder (not always working) ;) + $this->filesize = ($this->get_filesize($this->filename)) ?: $this->filesize; + + $this->width = $this->height = 0; + $this->file_moved = false; + + $this->local = (isset($upload_ary['local_mode'])) ? true : false; + + return $this; + } + + /** + * Set the upload namespace + * + * @param upload $namespace Instance of upload class + * + * @return filespec This instance of the filespec class + */ + public function set_upload_namespace($namespace) + { + $this->upload = $namespace; + + return $this; + } + + /** + * Check if class members were not properly initialised yet + * + * @return bool True if there was an init error, false if not + */ + public function init_error() + { + return !$this->class_initialized; + } + + /** + * Set error in error array + * + * @param mixed $error Content for error array + * + * @return \phpbb\files\filespec This instance of the filespec class + */ + public function set_error($error) + { + $this->error[] = $error; + + return $this; + } + + /** + * Cleans destination filename + * + * @param string $mode Either real, unique, or unique_ext. Real creates a + * realname, filtering some characters, lowering every + * character. Unique creates a unique filename. + * @param string $prefix Prefix applied to filename + * @param string $user_id The user_id is only needed for when cleaning a user's avatar + */ + public function clean_filename($mode = 'unique', $prefix = '', $user_id = '') + { + if ($this->init_error()) + { + return; + } + + switch ($mode) + { + case 'real': + // Remove every extension from filename (to not let the mime bug being exposed) + if (strpos($this->realname, '.') !== false) + { + $this->realname = substr($this->realname, 0, strpos($this->realname, '.')); + } + + // Replace any chars which may cause us problems with _ + $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|'); + + $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname))); + $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname); + + $this->realname = $prefix . $this->realname . '.' . $this->extension; + break; + + case 'unique': + $this->realname = $prefix . md5(unique_id()); + break; + + case 'avatar': + $this->extension = strtolower($this->extension); + $this->realname = $prefix . $user_id . '.' . $this->extension; + + break; + + case 'unique_ext': + default: + $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension; + } + } + + /** + * Get property from file object + * + * @param string $property Name of property + * + * @return mixed Content of property + */ + public function get($property) + { + if ($this->init_error() || !isset($this->$property)) + { + return false; + } + + return $this->$property; + } + + /** + * Check if file is an image (mime type) + * + * @return bool true if it is an image, false if not + */ + public function is_image() + { + return (strpos($this->mimetype, 'image/') === 0); + } + + /** + * Check if the file got correctly uploaded + * + * @return bool true if it is a valid upload, false if not + */ + public function is_uploaded() + { + $is_plupload = $this->plupload && $this->plupload->is_active(); + + if (!$this->local && !$is_plupload && !is_uploaded_file($this->filename)) + { + return false; + } + + if (($this->local || $is_plupload) && !file_exists($this->filename)) + { + return false; + } + + return true; + } + + /** + * Remove file + */ + public function remove($storage) + { + if ($this->file_moved) + { + $storage->delete($this->destination_file); + } + } + + /** + * Get file extension + * + * @param string $filename Filename that needs to be checked + * + * @return string Extension of the supplied filename + */ + static public function get_extension($filename) + { + $filename = utf8_basename($filename); + + if (strpos($filename, '.') === false) + { + return ''; + } + + $filename = explode('.', $filename); + return array_pop($filename); + } + + /** + * Get mime type + * + * @param string $filename Filename that needs to be checked + * @return string Mime type of supplied filename + */ + public function get_mimetype($filename) + { + if ($this->mimetype_guesser !== null) + { + $mimetype = $this->mimetype_guesser->guess($filename, $this->uploadname); + + if ($mimetype !== 'application/octet-stream') + { + $this->mimetype = $mimetype; + } + } + + return $this->mimetype; + } + + /** + * Get file size + * + * @param string $filename File name of file to check + * + * @return int File size + */ + public function get_filesize($filename) + { + return @filesize($filename); + } + + + /** + * Check the first 256 bytes for forbidden content + * + * @param array $disallowed_content Array containg disallowed content + * + * @return bool False if disallowed content found, true if not + */ + public function check_content($disallowed_content) + { + if (empty($disallowed_content)) + { + return true; + } + + $fp = @fopen($this->filename, 'rb'); + + if ($fp !== false) + { + $ie_mime_relevant = fread($fp, 256); + fclose($fp); + foreach ($disallowed_content as $forbidden) + { + if (stripos($ie_mime_relevant, '<' . $forbidden) !== false) + { + return false; + } + } + } + return true; + } + + /** + * Move file to destination folder + * + * @param bool $overwrite If set to true, an already existing file will be overwritten + * @param bool $skip_image_check If set to true, the check for the file to be a valid image is skipped + * + * @return bool True if file was moved, false if not + * @access public + */ + public function move_file($storage, $overwrite = false, $skip_image_check = false) + { + if (sizeof($this->error)) + { + return false; + } + + $this->destination_file = utf8_basename($this->realname); + + // Try to get real filesize from destination folder + $this->filesize = ($this->get_filesize($this->filename)) ?: $this->filesize; + + // Get mimetype of supplied file + $this->mimetype = $this->get_mimetype($this->filename); + + if ($this->is_image() && !$skip_image_check) + { + $this->width = $this->height = 0; + + $this->image_info = $this->imagesize->getImageSize($this->filename, $this->mimetype); + + if ($this->image_info !== false) + { + $this->width = $this->image_info['width']; + $this->height = $this->image_info['height']; + + // Check image type + $types = upload::image_types(); + + if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']])) + { + if (!isset($types[$this->image_info['type']])) + { + $this->error[] = $this->language->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype); + } + else + { + $this->error[] = $this->language->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension); + } + } + + // Make sure the dimensions match a valid image + if (empty($this->width) || empty($this->height)) + { + $this->error[] = $this->language->lang('ATTACHED_IMAGE_NOT_IMAGE'); + } + } + else + { + $this->error[] = $this->language->lang('UNABLE_GET_IMAGE_SIZE'); + } + } + + if($overwrite && $storage->exists($this->destination_file)) + { + $storage->delete($this->destination_file); + } + + try + { + $storage->put_contents($this->destination_file, file_get_contents($this->filename)); + } + catch (\phpbb\storage\exception\exception $e) + { + $this->error[] = $this->language->lang($this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR', $this->destination_file); + $this->file_moved = false; + } + + // Remove temporary filename + @unlink($this->filename); + + if (sizeof($this->error)) + { + return false; + } + + $this->file_moved = true; + $this->additional_checks(); + unset($this->upload); + + return true; + } + + /** + * Performing additional checks + * + * @return bool False if issue was found, true if not + */ + public function additional_checks() + { + if (!$this->file_moved) + { + return false; + } + + // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form + if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0)) + { + $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); + + $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit']); + + return false; + } + + if (!$this->upload->valid_dimensions($this)) + { + $this->error[] = $this->language->lang($this->upload->error_prefix . 'WRONG_SIZE', + $this->language->lang('PIXELS', (int) $this->upload->min_width), + $this->language->lang('PIXELS', (int) $this->upload->min_height), + $this->language->lang('PIXELS', (int) $this->upload->max_width), + $this->language->lang('PIXELS', (int) $this->upload->max_height), + $this->language->lang('PIXELS', (int) $this->width), + $this->language->lang('PIXELS', (int) $this->height)); + + return false; + } + + return true; + } +} From 67f1f85146c92f71b9dbfa9226d1150f2f654bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 04:11:46 +0200 Subject: [PATCH 06/20] [ticket/15287] Remove unused services PHPBB3-15287 --- phpBB/config/default/container/services_storage.yml | 1 - phpBB/phpbb/storage/adapter_factory.php | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/phpBB/config/default/container/services_storage.yml b/phpBB/config/default/container/services_storage.yml index 4a14f00962..abf51d5f97 100644 --- a/phpBB/config/default/container/services_storage.yml +++ b/phpBB/config/default/container/services_storage.yml @@ -4,7 +4,6 @@ services: class: phpbb\storage\adapter_factory arguments: - '@config' - - '@service_container' - '@storage.adapter_collection' - '@storage.provider_collection' diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index b63a10fea6..f7a0a5f06e 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -15,19 +15,16 @@ namespace phpbb\storage; use phpbb\config\config; use phpbb\di\service_collection; -use Symfony\Component\DependencyInjection\ContainerInterface; class adapter_factory { protected $config; - protected $container; protected $adapters; protected $providers; - public function __construct(config $config, ContainerInterface $container, service_collection $adapters, service_collection $providers) + public function __construct(config $config, service_collection $adapters, service_collection $providers) { $this->config = $config; - $this->container = $container; $this->adapters = $adapters; $this->providers = $providers; } From ff86178667826ef0e023822433e34238b6cfaeef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 04:32:00 +0200 Subject: [PATCH 07/20] [ticket/15287] Add PHPDoc PHPBB3-15287 --- phpBB/phpbb/storage/adapter/local.php | 8 ++- phpBB/phpbb/storage/adapter_factory.php | 33 +++++++++ phpBB/phpbb/storage/provider/local.php | 6 ++ .../storage/provider/provider_interface.php | 11 +++ phpBB/phpbb/storage/storage.php | 69 ++++++++++++++++++- 5 files changed, 124 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/storage/adapter/local.php b/phpBB/phpbb/storage/adapter/local.php index cdf06176d5..0d05676a78 100644 --- a/phpBB/phpbb/storage/adapter/local.php +++ b/phpBB/phpbb/storage/adapter/local.php @@ -29,10 +29,14 @@ class local implements adapter_interface */ protected $filesystem; - /** @var string path */ + /** + * @var string path + */ protected $phpbb_root_path; - /** @var string path */ + /** + * @var string path + */ protected $root_path; /** diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index f7a0a5f06e..8f66ca5331 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -18,10 +18,28 @@ use phpbb\di\service_collection; class adapter_factory { + /** + * @var \phpbb\config\config + */ protected $config; + + /** + * @var \phpbb\di\service_collection + */ protected $adapters; + + /** + * @var \phpbb\di\service_collection + */ protected $providers; + /** + * Constructor + * + * @param \phpbb\config\config $config + * @param \phpbb\di\service_collection $adapters + * @param \phpbb\di\service_collection $providers + */ public function __construct(config $config, service_collection $adapters, service_collection $providers) { $this->config = $config; @@ -29,6 +47,13 @@ class adapter_factory $this->providers = $providers; } + /** + * Obtains a configured adapters for a given storage + * + * @param string $storage_name + * + * @return \phpbb\storage\adapter\adapter_interface + */ public function get($storage_name) { $provider_class = $this->config['storage\\' . $storage_name . '\\adapter']; @@ -40,6 +65,14 @@ class adapter_factory return $adapter; } + /** + * Obtains configuration for a given storage + * + * @param string $storage_name + * @param array $definitions + * + * @return array Returns storage configuration values + */ public function build_options($storage_name, array $definitions) { $options = []; diff --git a/phpBB/phpbb/storage/provider/local.php b/phpBB/phpbb/storage/provider/local.php index 6369c626c7..e248b7060d 100644 --- a/phpBB/phpbb/storage/provider/local.php +++ b/phpBB/phpbb/storage/provider/local.php @@ -15,11 +15,17 @@ namespace phpbb\storage\provider; class local implements provider_interface { + /** + * {@inheritdoc} + */ public function get_class() { return \phpbb\storage\adapter\local::class; } + /** + * {@inheritdoc} + */ public function get_options() { return ['path']; diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php index 4d9a550e9a..5632ae6803 100644 --- a/phpBB/phpbb/storage/provider/provider_interface.php +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -15,6 +15,17 @@ namespace phpbb\storage\provider; interface provider_interface { + /** + * Gets adapter class. + * + * @return \phpbb\storage\adapter\adapter_interface + */ public function get_class(); + + /** + * Gets adapter options. + * + * @return string Configuration keys + */ public function get_options(); } diff --git a/phpBB/phpbb/storage/storage.php b/phpBB/phpbb/storage/storage.php index 04a66396e8..6268d7495e 100644 --- a/phpBB/phpbb/storage/storage.php +++ b/phpBB/phpbb/storage/storage.php @@ -18,43 +18,110 @@ namespace phpbb\storage; */ class storage { + /** + * @var \phpbb\storage\adapter\adapter_interface + */ protected $adapter; - public function __construct($factory, $storage_name) + /** + * Constructor + * + * @param \phpbb\storage\adapter_factory $factory + * @param string $storage_name + */ + public function __construct(adapter_factory $factory, $storage_name) { $this->adapter = $factory->get($storage_name); } + /** + * Dumps content into a file. + * + * @param string path The file to be written to. + * @param string content The data to write into the file. + * + * @throws \phpbb\storage\exception\exception When the file already exists + * When the file cannot be written + */ public function put_contents($path, $content) { $this->adapter->put_contents($path, $content); } + /** + * Read the contents of a file + * + * @param string $path The file to read + * + * @throws \phpbb\storage\exception\exception When the file dont exists + * When cannot read file contents + * @return string Returns file contents + * + */ public function get_contents($path) { return $this->adapter->get_contents($path); } + /** + * Checks the existence of files or directories. + * + * @param string $path file/directory to check + * + * @return bool Returns true if all files/directories exist, false otherwise + */ public function exists($path) { return $this->adapter->exists($path); } + /** + * Removes files or directories. + * + * @param string $path file/directory to remove + * + * @throws \phpbb\storage\exception\exception When removal fails. + */ public function delete($path) { $this->adapter->delete($path); } + /** + * Rename a file or a directory. + * + * @param string $path_orig The original file/direcotry + * @param string $path_dest The target file/directory + * + * @throws \phpbb\storage\exception\exception When target exists + * When file/directory cannot be renamed + */ public function rename($path_orig, $path_dest) { $this->adapter->rename($path_orig, $path_dest); } + /** + * Copies a file. + * + * @param string $path_orig The original filename + * @param string $path_dest The target filename + * + * @throws \phpbb\storage\exception\exception When target exists + * When the file cannot be copied + */ public function copy($path_orig, $path_dest) { $this->adapter->copy($path_orig, $path_dest); } + /** + * Creates a directory recursively. + * + * @param string $path The directory path + * + * @throws \phpbb\storage\exception\exception On any directory creation failure + */ public function create_dir($path) { $this->adapter->create_dir($path); From a710bc616ada10bab8f20fa1db336a2ee70e4953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 05:09:30 +0200 Subject: [PATCH 08/20] [ticket/15287] Fix code style PHPBB3-15287 --- phpBB/phpbb/files/filespec_storage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/files/filespec_storage.php b/phpBB/phpbb/files/filespec_storage.php index 32204e075d..b4042ebf10 100644 --- a/phpBB/phpbb/files/filespec_storage.php +++ b/phpBB/phpbb/files/filespec_storage.php @@ -440,7 +440,7 @@ class filespec_storage } } - if($overwrite && $storage->exists($this->destination_file)) + if ($overwrite && $storage->exists($this->destination_file)) { $storage->delete($this->destination_file); } From 4d37063cd705df89bf2ab6270ec605e3e775de7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 05:10:06 +0200 Subject: [PATCH 09/20] [ticket/15287] Travis PHPBB3-15287 --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6c1fd12463..a684a96a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,3 +53,5 @@ script: - sh -c "if [ '$NOTESTS' != '1' -a '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --verbose --stop-on-error; fi" - sh -c "if [ '$SLOWTESTS' = '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --group slow; fi" - sh -c "set -x;if [ '$NOTESTS' = '1' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi" + +sudo: required From 3e89fdca6d23dc394afabccca6ca1d35a7757db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 08:14:16 +0200 Subject: [PATCH 10/20] [ticket/15287] Remove unused argument PHPBB3-15287 --- phpBB/config/default/container/services_files.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml index 44da208d8e..96682d6713 100644 --- a/phpBB/config/default/container/services_files.yml +++ b/phpBB/config/default/container/services_files.yml @@ -23,7 +23,6 @@ services: - '@language' - '@php_ini' - '@upload_imagesize' - - '%core.root_path%' - '@mimetype.guesser' - '@plupload' From 18ca46a66c7de374cc38e91d74651bb11d0ac909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Thu, 20 Jul 2017 19:57:29 +0200 Subject: [PATCH 11/20] [ticket/15287] Travis PHPBB3-15287 --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a684a96a09..6c1fd12463 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,5 +53,3 @@ script: - sh -c "if [ '$NOTESTS' != '1' -a '$SLOWTESTS' != '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --verbose --stop-on-error; fi" - sh -c "if [ '$SLOWTESTS' = '1' ]; then phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml --group slow; fi" - sh -c "set -x;if [ '$NOTESTS' = '1' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi" - -sudo: required From 69bfc48dd2ea1ec29b877d96616a5c961a3c10e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 07:25:58 +0200 Subject: [PATCH 12/20] [ticket/15287] Load the adapter lazily PHPBB3-15287 --- phpBB/phpbb/storage/storage.php | 42 ++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/phpBB/phpbb/storage/storage.php b/phpBB/phpbb/storage/storage.php index 6268d7495e..7468a0d782 100644 --- a/phpBB/phpbb/storage/storage.php +++ b/phpBB/phpbb/storage/storage.php @@ -18,6 +18,16 @@ namespace phpbb\storage; */ class storage { + /** + * @var string + */ + protected $storage_name; + + /** + * @var \phpbb\storage\adapter_factory + */ + protected $factory; + /** * @var \phpbb\storage\adapter\adapter_interface */ @@ -31,7 +41,23 @@ class storage */ public function __construct(adapter_factory $factory, $storage_name) { - $this->adapter = $factory->get($storage_name); + $this->factory = $factory; + $this->storage_name = $storage_name; + } + + /** + * Returns an adapter instance + * + * @return \phpbb\storage\adapter\adapter_interface + */ + protected function get_adapter() + { + if ($this->adapter === null) + { + $this->adapter = $this->factory->get($this->storage_name); + } + + return $this->adapter; } /** @@ -45,7 +71,7 @@ class storage */ public function put_contents($path, $content) { - $this->adapter->put_contents($path, $content); + $this->get_adapter()->put_contents($path, $content); } /** @@ -60,7 +86,7 @@ class storage */ public function get_contents($path) { - return $this->adapter->get_contents($path); + return $this->get_adapter()->get_contents($path); } /** @@ -72,7 +98,7 @@ class storage */ public function exists($path) { - return $this->adapter->exists($path); + return $this->get_adapter()->exists($path); } /** @@ -84,7 +110,7 @@ class storage */ public function delete($path) { - $this->adapter->delete($path); + $this->get_adapter()->delete($path); } /** @@ -98,7 +124,7 @@ class storage */ public function rename($path_orig, $path_dest) { - $this->adapter->rename($path_orig, $path_dest); + $this->get_adapter()->rename($path_orig, $path_dest); } /** @@ -112,7 +138,7 @@ class storage */ public function copy($path_orig, $path_dest) { - $this->adapter->copy($path_orig, $path_dest); + $this->get_adapter()->copy($path_orig, $path_dest); } /** @@ -124,6 +150,6 @@ class storage */ public function create_dir($path) { - $this->adapter->create_dir($path); + $this->get_adapter()->create_dir($path); } } From e2b02c15a547c2b25858bc659fa2a0ea914a709d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 07:29:34 +0200 Subject: [PATCH 13/20] [ticket/15287] Rename class PHPBB3-15287 --- phpBB/phpbb/storage/adapter_factory.php | 2 +- phpBB/phpbb/storage/provider/provider_interface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index 8f66ca5331..429437ab28 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -59,7 +59,7 @@ class adapter_factory $provider_class = $this->config['storage\\' . $storage_name . '\\adapter']; $provider = $this->providers->get_by_class($provider_class); - $adapter = $this->adapters->get_by_class($provider->get_class()); + $adapter = $this->adapters->get_by_class($provider->get_adapter_class()); $adapter->configure($this->build_options($storage_name, $provider->get_options())); return $adapter; diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php index 5632ae6803..439d5a5a7f 100644 --- a/phpBB/phpbb/storage/provider/provider_interface.php +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -20,7 +20,7 @@ interface provider_interface * * @return \phpbb\storage\adapter\adapter_interface */ - public function get_class(); + public function geti_adapter_class(); /** * Gets adapter options. From 2a19e213e8f0214af2ddf38679bded01024e58a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 08:07:57 +0200 Subject: [PATCH 14/20] [ticket/15287] Ensures that the target file directory exists PHPBB3-15287 --- .../storage/adapter/adapter_interface.php | 9 ------ phpBB/phpbb/storage/adapter/local.php | 30 +++++++++++++++++-- phpBB/phpbb/storage/storage.php | 12 -------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/phpBB/phpbb/storage/adapter/adapter_interface.php b/phpBB/phpbb/storage/adapter/adapter_interface.php index c92a429ec8..207f001fad 100644 --- a/phpBB/phpbb/storage/adapter/adapter_interface.php +++ b/phpBB/phpbb/storage/adapter/adapter_interface.php @@ -84,13 +84,4 @@ interface adapter_interface * When the file cannot be copied */ public function copy($path_orig, $path_dest); - - /** - * Creates a directory recursively. - * - * @param string $path The directory path - * - * @throws \phpbb\storage\exception\exception On any directory creation failure - */ - public function create_dir($path); } diff --git a/phpBB/phpbb/storage/adapter/local.php b/phpBB/phpbb/storage/adapter/local.php index 0d05676a78..319308527d 100644 --- a/phpBB/phpbb/storage/adapter/local.php +++ b/phpBB/phpbb/storage/adapter/local.php @@ -16,6 +16,7 @@ namespace phpbb\storage\adapter; use phpbb\storage\exception\exception; use phpbb\filesystem\exception\filesystem_exception; use phpbb\filesystem\filesystem; +use phpbb\filesystem\helper as filesystem_helper; /** * @internal Experimental @@ -66,6 +67,8 @@ class local implements adapter_interface */ public function put_contents($path, $content) { + $this->ensure_directory_exists($path); + if ($this->exists($path)) { throw new exception('STORAGE_FILE_EXISTS', $path); @@ -129,6 +132,8 @@ class local implements adapter_interface */ public function rename($path_orig, $path_dest) { + $this->ensure_directory_exists($path_dest); + try { $this->filesystem->rename($this->root_path . $path_orig, $this->root_path . $path_dest, false); @@ -144,6 +149,8 @@ class local implements adapter_interface */ public function copy($path_orig, $path_dest) { + $this->ensure_directory_exists($path_dest); + try { $this->filesystem->copy($this->root_path . $path_orig, $this->root_path . $path_dest, false); @@ -155,9 +162,13 @@ class local implements adapter_interface } /** - * {@inheritdoc} + * Creates a directory recursively. + * + * @param string $path The directory path + * + * @throws \phpbb\storage\exception\exception On any directory creation failure */ - public function create_dir($path) + protected function create_dir($path) { try { @@ -169,4 +180,19 @@ class local implements adapter_interface } } + /** + * Ensures that the directory of a file exists. + * + * @param string $path The file path + */ + protected function ensure_directory_exists($path) + { + $path = dirname($this->root_path . $path); + $path = filesystem_helper::make_path_relative($directory, $this->root_path); + + if (!$this->exists($path)) + { + $this->create_dir($path); + } + } } diff --git a/phpBB/phpbb/storage/storage.php b/phpBB/phpbb/storage/storage.php index 7468a0d782..65a4f6eb72 100644 --- a/phpBB/phpbb/storage/storage.php +++ b/phpBB/phpbb/storage/storage.php @@ -140,16 +140,4 @@ class storage { $this->get_adapter()->copy($path_orig, $path_dest); } - - /** - * Creates a directory recursively. - * - * @param string $path The directory path - * - * @throws \phpbb\storage\exception\exception On any directory creation failure - */ - public function create_dir($path) - { - $this->get_adapter()->create_dir($path); - } } From 8d7e8d4311c04b623465e5d5718d366e876fa1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 11:12:02 +0200 Subject: [PATCH 15/20] [ticket/15287] Fix method name PHPBB3-15287 --- phpBB/phpbb/storage/provider/local.php | 2 +- phpBB/phpbb/storage/provider/provider_interface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/storage/provider/local.php b/phpBB/phpbb/storage/provider/local.php index e248b7060d..16e57608ae 100644 --- a/phpBB/phpbb/storage/provider/local.php +++ b/phpBB/phpbb/storage/provider/local.php @@ -18,7 +18,7 @@ class local implements provider_interface /** * {@inheritdoc} */ - public function get_class() + public function get_adapter_class() { return \phpbb\storage\adapter\local::class; } diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php index 439d5a5a7f..ed7e768b13 100644 --- a/phpBB/phpbb/storage/provider/provider_interface.php +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -20,7 +20,7 @@ interface provider_interface * * @return \phpbb\storage\adapter\adapter_interface */ - public function geti_adapter_class(); + public function get_adapter_class(); /** * Gets adapter options. From a09a50670cde5d077d7eb07393b006126f514f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 12:04:06 +0200 Subject: [PATCH 16/20] [ticket/15287] Fix variable name PHPBB3-15287 --- phpBB/phpbb/storage/adapter/local.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/storage/adapter/local.php b/phpBB/phpbb/storage/adapter/local.php index 319308527d..a8498d6d8c 100644 --- a/phpBB/phpbb/storage/adapter/local.php +++ b/phpBB/phpbb/storage/adapter/local.php @@ -188,7 +188,7 @@ class local implements adapter_interface protected function ensure_directory_exists($path) { $path = dirname($this->root_path . $path); - $path = filesystem_helper::make_path_relative($directory, $this->root_path); + $path = filesystem_helper::make_path_relative($path, $this->root_path); if (!$this->exists($path)) { From 23e67da3312e3740364a096ac2b16788f222fb2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 21 Jul 2017 20:23:38 +0200 Subject: [PATCH 17/20] [ticket/15287] Fix annotation return type PHPBB3-15287 --- phpBB/phpbb/storage/provider/provider_interface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php index ed7e768b13..b832025508 100644 --- a/phpBB/phpbb/storage/provider/provider_interface.php +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -25,7 +25,7 @@ interface provider_interface /** * Gets adapter options. * - * @return string Configuration keys + * @return array Configuration keys */ public function get_options(); } From ba8cda4d052b41c053933b8650010c7515895498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Mon, 24 Jul 2017 01:33:07 +0200 Subject: [PATCH 18/20] [ticket/15287] Add is_available method PHPBB3-15287 --- phpBB/phpbb/storage/provider/local.php | 8 ++++++++ phpBB/phpbb/storage/provider/provider_interface.php | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/phpBB/phpbb/storage/provider/local.php b/phpBB/phpbb/storage/provider/local.php index 16e57608ae..370178cf47 100644 --- a/phpBB/phpbb/storage/provider/local.php +++ b/phpBB/phpbb/storage/provider/local.php @@ -30,4 +30,12 @@ class local implements provider_interface { return ['path']; } + + /** + * {@inheritdoc} + */ + public function is_available() + { + return true; + } } diff --git a/phpBB/phpbb/storage/provider/provider_interface.php b/phpBB/phpbb/storage/provider/provider_interface.php index b832025508..d2e78d907f 100644 --- a/phpBB/phpbb/storage/provider/provider_interface.php +++ b/phpBB/phpbb/storage/provider/provider_interface.php @@ -28,4 +28,11 @@ interface provider_interface * @return array Configuration keys */ public function get_options(); + + /** + * Return true if the adapter is available. + * + * @return bool + */ + public function is_available(); } From e41d4b0d0caa233cf78ed3d50d67d50279689e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Mon, 24 Jul 2017 09:37:10 +0200 Subject: [PATCH 19/20] [ticket/15287] Launch exception if storage is not available PHPBB3-15287 --- phpBB/language/en/common.php | 1 + phpBB/phpbb/storage/adapter_factory.php | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index 1414f0fd1a..006582772a 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -727,6 +727,7 @@ $lang = array_merge($lang, array( 'SUBJECT' => 'Subject', 'SUBMIT' => 'Submit', + 'STORAGE_ADAPTER_NOT_AVAILABLE' => 'Selected storage is not available.', 'STORAGE_FILE_EXISTS' => 'File already exists.', 'STORAGE_FILE_NO_EXIST' => 'File does not exist.', 'STORAGE_CANNOT_WRITE_FILE' => 'Can not write to file.', diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index 429437ab28..85a3ef03f7 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -15,6 +15,7 @@ namespace phpbb\storage; use phpbb\config\config; use phpbb\di\service_collection; +use phpbb\storage\exception\exception; class adapter_factory { @@ -59,6 +60,11 @@ class adapter_factory $provider_class = $this->config['storage\\' . $storage_name . '\\adapter']; $provider = $this->providers->get_by_class($provider_class); + if (!$provider->is_available()) + { + throw new exception('STORAGE_ADAPTER_NOT_AVAILABLE'); + } + $adapter = $this->adapters->get_by_class($provider->get_adapter_class()); $adapter->configure($this->build_options($storage_name, $provider->get_options())); From 42dcce34de5a18e3bee7245db876bc0e4b5974c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Calvo?= Date: Fri, 28 Jul 2017 15:32:15 +0200 Subject: [PATCH 20/20] [ticket/15287] Change adapter to provider in config_name PHPBB3-15287 --- phpBB/phpbb/storage/adapter_factory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/phpbb/storage/adapter_factory.php b/phpBB/phpbb/storage/adapter_factory.php index 85a3ef03f7..4b27269524 100644 --- a/phpBB/phpbb/storage/adapter_factory.php +++ b/phpBB/phpbb/storage/adapter_factory.php @@ -57,7 +57,7 @@ class adapter_factory */ public function get($storage_name) { - $provider_class = $this->config['storage\\' . $storage_name . '\\adapter']; + $provider_class = $this->config['storage\\' . $storage_name . '\\provider']; $provider = $this->providers->get_by_class($provider_class); if (!$provider->is_available())