diff options
author | MateBartus <mate.bartus@gmail.com> | 2015-03-12 00:25:00 +0100 |
---|---|---|
committer | MateBartus <mate.bartus@gmail.com> | 2015-04-16 13:24:10 +0200 |
commit | 4bdef6fd21a5dcab455b0cd1ee2652de606929c3 (patch) | |
tree | 33eae92e90b43770b2c1e2e4508dbcf35d6bd7da /phpBB/phpbb | |
parent | f86c5d905bb82967505ef3e07fa429b59c112871 (diff) | |
download | forums-4bdef6fd21a5dcab455b0cd1ee2652de606929c3.tar forums-4bdef6fd21a5dcab455b0cd1ee2652de606929c3.tar.gz forums-4bdef6fd21a5dcab455b0cd1ee2652de606929c3.tar.bz2 forums-4bdef6fd21a5dcab455b0cd1ee2652de606929c3.tar.xz forums-4bdef6fd21a5dcab455b0cd1ee2652de606929c3.zip |
[ticket/13697] Moving filesystem related functions to filesystem service
* Moving filesystem service to \phpbb\filesystem namespace
* Wraping Symfony's Filesystem component
* Moving filesystem related functions from includes/functions.php
into \phpbb\filesystem\filesystem
Functions moved (and deprecated):
- phpbb_chmod
- phpbb_is_writable
- phpbb_is_absolute
- phpbb_own_realpath
- phpbb_realpath
* Adding interface for filesystem service
PHPBB3-13697
Diffstat (limited to 'phpBB/phpbb')
-rw-r--r-- | phpBB/phpbb/avatar/driver/upload.php | 15 | ||||
-rw-r--r-- | phpBB/phpbb/cache/driver/base.php | 8 | ||||
-rw-r--r-- | phpBB/phpbb/cache/driver/file.php | 25 | ||||
-rw-r--r-- | phpBB/phpbb/console/command/db/migrate.php | 8 | ||||
-rw-r--r-- | phpBB/phpbb/controller/helper.php | 6 | ||||
-rw-r--r-- | phpBB/phpbb/db/log_wrapper_migrator_output_handler.php | 11 | ||||
-rw-r--r-- | phpBB/phpbb/di/container_builder.php | 3 | ||||
-rw-r--r-- | phpBB/phpbb/di/extension/core.php | 3 | ||||
-rw-r--r-- | phpBB/phpbb/extension/di/extension_base.php | 3 | ||||
-rw-r--r-- | phpBB/phpbb/extension/manager.php | 4 | ||||
-rw-r--r-- | phpBB/phpbb/filesystem.php | 35 | ||||
-rw-r--r-- | phpBB/phpbb/filesystem/exception/filesystem_exception.php | 42 | ||||
-rw-r--r-- | phpBB/phpbb/filesystem/filesystem.php | 916 | ||||
-rw-r--r-- | phpBB/phpbb/filesystem/filesystem_interface.php | 284 | ||||
-rw-r--r-- | phpBB/phpbb/finder.php | 4 | ||||
-rw-r--r-- | phpBB/phpbb/path_helper.php | 6 | ||||
-rw-r--r-- | phpBB/phpbb/routing/router.php | 11 | ||||
-rw-r--r-- | phpBB/phpbb/session.php | 4 | ||||
-rw-r--r-- | phpBB/phpbb/template/twig/loader.php | 22 | ||||
-rw-r--r-- | phpBB/phpbb/viewonline_helper.php | 6 |
20 files changed, 1336 insertions, 80 deletions
diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 003b23659f..2ad84c087d 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -19,6 +19,11 @@ namespace phpbb\avatar\driver; class upload extends \phpbb\avatar\driver\driver { /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * @var \phpbb\mimetype\guesser */ protected $mimetype_guesser; @@ -29,15 +34,17 @@ class upload extends \phpbb\avatar\driver\driver * @param \phpbb\config\config $config phpBB configuration * @param string $phpbb_root_path Path to the phpBB root * @param string $php_ext PHP file extension - * @param \phpbb_path_helper $path_helper phpBB path helper + * @param \phpbb\filesystem\filesystem_interface phpBB filesystem helper + * @param \phpbb\path_helper $path_helper phpBB path helper * @param \phpbb\mimetype\guesser $mimetype_guesser Mimetype guesser * @param \phpbb\cache\driver\driver_interface $cache Cache driver */ - public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) + public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\path_helper $path_helper, \phpbb\mimetype\guesser $mimetype_guesser, \phpbb\cache\driver\driver_interface $cache = null) { $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $php_ext; + $this->filesystem = $filesystem; $this->path_helper = $path_helper; $this->mimetype_guesser = $mimetype_guesser; $this->cache = $cache; @@ -88,7 +95,7 @@ class upload extends \phpbb\avatar\driver\driver include($this->phpbb_root_path . 'includes/functions_upload.' . $this->php_ext); } - $upload = new \fileupload('AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); + $upload = new \fileupload($this->filesystem, 'AVATAR_', $this->allowed_extensions, $this->config['avatar_filesize'], $this->config['avatar_min_width'], $this->config['avatar_min_height'], $this->config['avatar_max_width'], $this->config['avatar_max_height'], (isset($this->config['mime_triggers']) ? explode('|', $this->config['mime_triggers']) : false)); $url = $request->variable('avatar_upload_url', ''); $upload_file = $request->file('avatar_upload_file'); @@ -209,6 +216,6 @@ class upload extends \phpbb\avatar\driver\driver */ protected function can_upload() { - return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && phpbb_is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); + return (file_exists($this->phpbb_root_path . $this->config['avatar_path']) && $this->filesystem->is_writable($this->phpbb_root_path . $this->config['avatar_path']) && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')); } } diff --git a/phpBB/phpbb/cache/driver/base.php b/phpBB/phpbb/cache/driver/base.php index c83b928a12..55cd4668de 100644 --- a/phpBB/phpbb/cache/driver/base.php +++ b/phpBB/phpbb/cache/driver/base.php @@ -177,13 +177,9 @@ abstract class base implements \phpbb\cache\driver\driver_interface */ function remove_file($filename, $check = false) { - if (!function_exists('phpbb_is_writable')) - { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/functions.' . $phpEx); - } + global $phpbb_filesystem; - if ($check && !phpbb_is_writable($this->cache_dir)) + if ($check && !$phpbb_filesystem->is_writable($this->cache_dir)) { // E_USER_ERROR - not using language entry - intended. trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); diff --git a/phpBB/phpbb/cache/driver/file.php b/phpBB/phpbb/cache/driver/file.php index 32086458ee..bb055d3acf 100644 --- a/phpBB/phpbb/cache/driver/file.php +++ b/phpBB/phpbb/cache/driver/file.php @@ -21,6 +21,11 @@ class file extends \phpbb\cache\driver\base var $var_expires = array(); /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Set cache path * * @param string $cache_dir Define the path to the cache directory (default: $phpbb_root_path . 'cache/') @@ -30,6 +35,7 @@ class file extends \phpbb\cache\driver\base global $phpbb_root_path, $phpbb_container; $this->cache_dir = !is_null($cache_dir) ? $cache_dir : $phpbb_root_path . 'cache/' . $phpbb_container->getParameter('core.environment') . '/'; + $this->filesystem = new \phpbb\filesystem\filesystem(); if (!is_dir($this->cache_dir)) { @@ -69,14 +75,8 @@ class file extends \phpbb\cache\driver\base if (!$this->_write('data_global')) { - if (!function_exists('phpbb_is_writable')) - { - global $phpbb_root_path; - include($phpbb_root_path . 'includes/functions.' . $phpEx); - } - // Now, this occurred how often? ... phew, just tell the user then... - if (!phpbb_is_writable($this->cache_dir)) + if (!$this->filesystem->is_writable($this->cache_dir)) { // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) die('Fatal: ' . $this->cache_dir . ' is NOT writable.'); @@ -574,13 +574,14 @@ class file extends \phpbb\cache\driver\base fclose($handle); - if (!function_exists('phpbb_chmod')) + try { - global $phpbb_root_path; - include($phpbb_root_path . 'includes/functions.' . $phpEx); + $this->filesystem->phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing } - - phpbb_chmod($file, CHMOD_READ | CHMOD_WRITE); $return_value = true; } diff --git a/phpBB/phpbb/console/command/db/migrate.php b/phpBB/phpbb/console/command/db/migrate.php index 87c2a057d1..2490bf1310 100644 --- a/phpBB/phpbb/console/command/db/migrate.php +++ b/phpBB/phpbb/console/command/db/migrate.php @@ -35,13 +35,17 @@ class migrate extends \phpbb\console\command\command /** @var string phpBB root path */ protected $phpbb_root_path; - function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, $phpbb_root_path) + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + + function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) { $this->migrator = $migrator; $this->extension_manager = $extension_manager; $this->config = $config; $this->cache = $cache; $this->log = $log; + $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; parent::__construct($user); $this->user->add_lang(array('common', 'install', 'migrator')); @@ -57,7 +61,7 @@ class migrate extends \phpbb\console\command\command protected function execute(InputInterface $input, OutputInterface $output) { - $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log')); + $this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem)); $this->migrator->create_migrations_table(); diff --git a/phpBB/phpbb/controller/helper.php b/phpBB/phpbb/controller/helper.php index 2790ea4277..1e1cf5e4e8 100644 --- a/phpBB/phpbb/controller/helper.php +++ b/phpBB/phpbb/controller/helper.php @@ -53,7 +53,7 @@ class helper protected $request; /** - * @var \phpbb\filesystem The filesystem object + * @var \phpbb\filesystem\filesystem_interface The filesystem object */ protected $filesystem; @@ -78,11 +78,11 @@ class helper * @param \phpbb\routing\router $router phpBB router * @param \phpbb\symfony_request $symfony_request Symfony Request object * @param \phpbb\request\request_interface $request phpBB request object - * @param \phpbb\filesystem $filesystem The filesystem object + * @param \phpbb\filesystem\filesystem_interface $filesystem The filesystem object * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension */ - public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem $filesystem, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\template\template $template, \phpbb\user $user, \phpbb\config\config $config, \phpbb\routing\router $router, \phpbb\symfony_request $symfony_request, \phpbb\request\request_interface $request, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path, $php_ext) { $this->template = $template; $this->user = $user; diff --git a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php b/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php index 94c293dc45..4c85bf4d67 100644 --- a/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php +++ b/phpBB/phpbb/db/log_wrapper_migrator_output_handler.php @@ -38,16 +38,23 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int protected $file_handle = false; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Constructor * * @param user $user User object * @param migrator_output_handler_interface $migrator Migrator output handler * @param string $log_file File to log to + * @param \phpbb\filesystem\filesystem_interface phpBB filesystem object */ - public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file) + public function __construct(user $user, migrator_output_handler_interface $migrator, $log_file, \phpbb\filesystem\filesystem_interface $filesystem) { $this->user = $user; $this->migrator = $migrator; + $this->filesystem = $filesystem; $this->file_open($log_file); } @@ -58,7 +65,7 @@ class log_wrapper_migrator_output_handler implements migrator_output_handler_int */ protected function file_open($file) { - if (phpbb_is_writable(dirname($file))) + if ($this->filesystem->is_writable(dirname($file))) { $this->file_handle = fopen($file, 'w'); } diff --git a/phpBB/phpbb/di/container_builder.php b/phpBB/phpbb/di/container_builder.php index 125ae28e9b..2a410db9bd 100644 --- a/phpBB/phpbb/di/container_builder.php +++ b/phpBB/phpbb/di/container_builder.php @@ -192,7 +192,8 @@ class container_builder } } - $loader = new YamlFileLoader($this->container, new FileLocator(phpbb_realpath($this->get_config_path()))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($this->container, new FileLocator($filesystem->realpath($this->get_config_path()))); $loader->load($this->container->getParameter('core.environment') . '/config.yml'); $this->inject_custom_parameters(); diff --git a/phpBB/phpbb/di/extension/core.php b/phpBB/phpbb/di/extension/core.php index 451efc8e35..c71dc61280 100644 --- a/phpBB/phpbb/di/extension/core.php +++ b/phpBB/phpbb/di/extension/core.php @@ -50,7 +50,8 @@ class core extends Extension */ public function load(array $configs, ContainerBuilder $container) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($this->config_path))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($this->config_path))); $loader->load($container->getParameter('core.environment') . '/container/environment.yml'); $config = $this->getConfiguration($configs, $container); diff --git a/phpBB/phpbb/extension/di/extension_base.php b/phpBB/phpbb/extension/di/extension_base.php index 30cc37dbb6..ba74615e70 100644 --- a/phpBB/phpbb/extension/di/extension_base.php +++ b/phpBB/phpbb/extension/di/extension_base.php @@ -94,7 +94,8 @@ class extension_base extends Extension if ($services_directory && $services_file) { - $loader = new YamlFileLoader($container, new FileLocator(phpbb_realpath($services_directory))); + $filesystem = new \phpbb\filesystem\filesystem(); + $loader = new YamlFileLoader($container, new FileLocator($filesystem->realpath($services_directory))); $loader->load($services_file); } } diff --git a/phpBB/phpbb/extension/manager.php b/phpBB/phpbb/extension/manager.php index 880973d5fb..40fda74065 100644 --- a/phpBB/phpbb/extension/manager.php +++ b/phpBB/phpbb/extension/manager.php @@ -39,7 +39,7 @@ class manager * @param ContainerInterface $container A container * @param \phpbb\db\driver\driver_interface $db A database connection * @param \phpbb\config\config $config Config object - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param \phpbb\user $user User object * @param string $extension_table The name of the table holding extensions * @param string $phpbb_root_path Path to the phpbb includes directory. @@ -47,7 +47,7 @@ class manager * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $cache_name The name of the cache variable, defaults to _ext */ - public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') + public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\user $user, $extension_table, $phpbb_root_path, $php_ext = 'php', \phpbb\cache\driver\driver_interface $cache = null, $cache_name = '_ext') { $this->cache = $cache; $this->cache_name = $cache_name; diff --git a/phpBB/phpbb/filesystem.php b/phpBB/phpbb/filesystem.php index 77517082e5..af56d78845 100644 --- a/phpBB/phpbb/filesystem.php +++ b/phpBB/phpbb/filesystem.php @@ -14,37 +14,8 @@ namespace phpbb; /** -* A class with various functions that are related to paths, files and the filesystem -*/ -class filesystem + * @deprecated 3.2.0-dev (To be removed 3.3.0) use \phpbb\filesystem\filesystem instead + */ +class filesystem extends \phpbb\filesystem\filesystem { - /** - * Eliminates useless . and .. components from specified path. - * - * @param string $path Path to clean - * @return string Cleaned path - */ - public function clean_path($path) - { - $exploded = explode('/', $path); - $filtered = array(); - foreach ($exploded as $part) - { - if ($part === '.' && !empty($filtered)) - { - continue; - } - - if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') - { - array_pop($filtered); - } - else - { - $filtered[] = $part; - } - } - $path = implode('/', $filtered); - return $path; - } } diff --git a/phpBB/phpbb/filesystem/exception/filesystem_exception.php b/phpBB/phpbb/filesystem/exception/filesystem_exception.php new file mode 100644 index 0000000000..d68fa9adf3 --- /dev/null +++ b/phpBB/phpbb/filesystem/exception/filesystem_exception.php @@ -0,0 +1,42 @@ +<?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\filesystem\exception; + +class filesystem_exception extends \phpbb\exception\runtime_exception +{ + /** + * Constructor + * + * @param string $message The Exception message to throw (must be a language variable). + * @param string $filename The file that caused the error. + * @param array $parameters The parameters to use with the language var. + * @param \Exception $previous The previous runtime_exception used for the runtime_exception chaining. + * @param integer $code The Exception code. + */ + public function __construct($message = "", $filename = '', $parameters = array(), \Exception $previous = null, $code = 0) + { + parent::__construct($message, array_merge(array('filename' => $filename), $parameters), $previous, $code); + } + + /** + * Returns the filename that triggered the error + * + * @return string + */ + public function get_filename() + { + $parameters = parent::get_parameters(); + return $parameters['filename']; + } +} diff --git a/phpBB/phpbb/filesystem/filesystem.php b/phpBB/phpbb/filesystem/filesystem.php new file mode 100644 index 0000000000..370dff77e5 --- /dev/null +++ b/phpBB/phpbb/filesystem/filesystem.php @@ -0,0 +1,916 @@ +<?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\filesystem; + +use phpbb\filesystem\exception\filesystem_exception; + +/** + * A class with various functions that are related to paths, files and the filesystem + */ +class filesystem implements filesystem_interface +{ + /** + * Store some information about file ownership for phpBB's chmod function + * + * @var array + */ + protected $chmod_info; + + /** + * Stores current working directory + * + * @var string|bool current working directory or false if it cannot be recovered + */ + protected $working_directory; + + /** + * Symfony's Filesystem component + * + * @var \Symfony\Component\Filesystem\Filesystem + */ + protected $symfony_filesystem; + + /** + * Constructor + */ + public function __construct() + { + $this->chmod_info = array(); + $this->symfony_filesystem = new \Symfony\Component\Filesystem\Filesystem(); + $this->working_directory = null; + } + + /** + * {@inheritdoc} + */ + public function chgrp($files, $group, $recursive = false) + { + try + { + $this->symfony_filesystem->chgrp($files, $group, $recursive); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false) + { + if (is_null($perms)) + { + // Default to read permission for compatibility reasons + $perms = self::CHMOD_READ; + } + + // Check if we got a permission flag + if ($perms > self::CHMOD_ALL) + { + $file_perm = $perms; + + // Extract permissions + //$owner = ($file_perm >> 6) & 7; // This will be ignored + $group = ($file_perm >> 3) & 7; + $other = ($file_perm >> 0) & 7; + + // Does any permissions provided? if so we add execute bit for directories + $group = ($group !== 0) ? ($group | self::CHMOD_EXECUTE) : $group; + $other = ($other !== 0) ? ($other | self::CHMOD_EXECUTE) : $other; + + // Compute directory permissions + $dir_perm = (self::CHMOD_ALL << 6) + ($group << 3) + ($other << 3); + } + else + { + // Add execute bit to owner if execute bit is among perms + $owner_perm = (self::CHMOD_READ | self::CHMOD_WRITE) | ($perms & self::CHMOD_EXECUTE); + $file_perm = ($owner_perm << 6) + ($perms << 3) + ($perms << 0); + + // Compute directory permissions + $perm = ($perms !== 0) ? ($perms | self::CHMOD_EXECUTE) : $perms; + $dir_perm = (($owner_perm | self::CHMOD_EXECUTE) << 6) + ($perm << 3) + ($perm << 0); + } + + // Symfony's filesystem component does not support extra execution flags on directories + // so we need to implement it again + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + $this->chmod(new \FilesystemIterator($file), $perms, true); + } + + // Don't chmod links as mostly those require 0777 and that cannot be changed + if (is_dir($file) || (is_link($file) && $force_chmod_link)) + { + if (true !== @chmod($file, $dir_perm)) + { + throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array()); + } + } + else if (is_file($file)) + { + if (true !== @chmod($file, $file_perm)) + { + throw new filesystem_exception('CANNOT_CHANGE_FILE_PERMISSIONS', $file, array()); + } + } + } + } + + /** + * {@inheritdoc} + */ + public function chown($files, $user, $recursive = false) + { + try + { + $this->symfony_filesystem->chown($files, $user, $recursive); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_CHANGE_FILE_GROUP', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function clean_path($path) + { + $exploded = explode('/', $path); + $filtered = array(); + foreach ($exploded as $part) + { + if ($part === '.' && !empty($filtered)) + { + continue; + } + + if ($part === '..' && !empty($filtered) && $filtered[sizeof($filtered) - 1] !== '.' && $filtered[sizeof($filtered) - 1] !== '..') + { + array_pop($filtered); + } + else + { + $filtered[] = $part; + } + } + $path = implode('/', $filtered); + return $path; + } + + /** + * {@inheritdoc} + */ + public function copy($origin_file, $target_file, $override = false) + { + try + { + $this->symfony_filesystem->copy($origin_file, $target_file, $override); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_COPY_FILES', '', array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function dump_file($filename, $content) + { + try + { + $this->symfony_filesystem->dumpFile($filename, $content); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_DUMP_FILE', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function exists($files) + { + return $this->symfony_filesystem->exists($files); + } + + /** + * {@inheritdoc} + */ + public function is_absolute_path($path) + { + return (isset($path[0]) && $path[0] === '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; + } + + /** + * {@inheritdoc} + */ + public function is_readable($files, $recursive = false) + { + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_readable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!is_readable($file)) + { + return false; + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function is_writable($files, $recursive = false) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR') || !function_exists('is_writable')) + { + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_writable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!$this->phpbb_is_writable($file)) + { + return false; + } + } + } + else + { + // use built in is_writable + foreach ($this->to_iterator($files) as $file) + { + if ($recursive && is_dir($file) && !is_link($file)) + { + if (!$this->is_writable(new \FilesystemIterator($file), true)) + { + return false; + } + } + + if (!is_writable($file)) + { + return false; + } + } + } + + return true; + } + + /** + * {@inheritdoc} + */ + public function make_path_relative($end_path, $start_path) + { + return $this->symfony_filesystem->makePathRelative($end_path, $start_path); + } + + /** + * {@inheritdoc} + */ + public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array()) + { + try + { + $this->symfony_filesystem->mirror($origin_dir, $target_dir, $iterator, $options); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_MIRROR_DIRECTORY', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function mkdir($dirs, $mode = 0777) + { + try + { + $this->symfony_filesystem->mkdir($dirs, $mode); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_CREATE_DIRECTORY', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function phpbb_chmod($files, $perms = null, $recursive = false, $force_chmod_link = false) + { + if (is_null($perms)) + { + // Default to read permission for compatibility reasons + $perms = self::CHMOD_READ; + } + + if (empty($this->chmod_info)) + { + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + $this->chmod_info['process'] = false; + } + else + { + $common_php_owner = @fileowner(__FILE__); + $common_php_group = @filegroup(__FILE__); + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posic_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + // If we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $this->chmod_info['process'] = false; + } + else + { + $this->chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } + } + + if ($this->chmod_info['process']) + { + try + { + foreach ($this->to_iterator($files) as $file) + { + $file_uid = @fileowner($file); + $file_gid = @filegroup($file); + + // Change owner + if ($file_uid !== $this->chmod_info['common_owner']) + { + $this->chown($file, $this->chmod_info['common_owner'], $recursive); + } + + // Change group + if ($file_gid !== $this->chmod_info['common_group']) + { + $this->chgrp($file, $this->chmod_info['common_group'], $recursive); + } + + clearstatcache(); + $file_uid = @fileowner($file); + $file_gid = @filegroup($file); + } + } + catch (filesystem_exception $e) + { + $this->chmod_info['process'] = false; + } + } + + // Still able to process? + if ($this->chmod_info['process']) + { + if ($file_uid === $this->chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $this->chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $this->chmod_info['process'] = false; + } + } + + // We are not able to determine or change something + if (!$this->chmod_info['process']) + { + $php = 'other'; + } + + switch ($php) + { + case 'owner': + try + { + $this->chmod($files, $perms, $recursive, $force_chmod_link); + clearstatcache(); + if ($this->is_readable($files) && $this->is_writable($files)) + { + break; + } + } + catch (filesystem_exception $e) + { + // Do nothing + } + case 'group': + try + { + $this->chmod($files, $perms, $recursive, $force_chmod_link); + clearstatcache(); + if ((!($perms & self::CHMOD_READ) || $this->is_readable($files, $recursive)) && (!($perms & self::CHMOD_WRITE) || $this->is_writable($files, $recursive))) + { + break; + } + } + catch (filesystem_exception $e) + { + // Do nothing + } + case 'other': + default: + $this->chmod($files, $perms, $recursive, $force_chmod_link); + break; + } + } + + /** + * {@inheritdoc} + */ + public function realpath($path) + { + if (!function_exists('realpath')) + { + return $this->phpbb_own_realpath($path); + } + + $realpath = realpath($path); + + // Strangely there are provider not disabling realpath but returning strange values. :o + // We at least try to cope with them. + if ((!$this->is_absolute_path($path) && $realpath === $path) || $realpath === false) + { + return $this->phpbb_own_realpath($path); + } + + // Check for DIRECTORY_SEPARATOR at the end (and remove it!) + if (substr($realpath, -1) === DIRECTORY_SEPARATOR) + { + $realpath = substr($realpath, 0, -1); + } + + return $realpath; + } + + /** + * {@inheritdoc} + */ + public function remove($files) + { + try + { + $this->symfony_filesystem->remove($files); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_DELETE_FILES', $file, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function rename($origin, $target, $overwrite = false) + { + try + { + $this->symfony_filesystem->rename($origin, $target, $overwrite); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + $msg = $e->getMessage(); + $filename = substr($msg, strpos($msg, '"'), strrpos($msg, '"')); + + throw new filesystem_exception('CANNOT_RENAME_FILE', $filename, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function symlink($origin_dir, $target_dir, $copy_on_windows = false) + { + try + { + $this->symfony_filesystem->symlink($origin_dir, $target_dir, $copy_on_windows); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + throw new filesystem_exception('CANNOT_CREATE_SYMLINK', $origin_dir, array(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function touch($files, $time = null, $access_time = null) + { + try + { + $this->symfony_filesystem->touch($files, $time, $access_time); + } + catch (\Symfony\Component\Filesystem\Exception\IOException $e) + { + // Try to recover filename + // By the time this is written that is at the end of the message + $error = trim($e->getMessage()); + $file = substr($error, strrpos($error, ' ')); + + throw new filesystem_exception('CANNOT_TOUCH_FILES', $file, array(), $e); + } + } + + /** + * phpBB's implementation of is_writable + * + * @todo Investigate if is_writable is still buggy + * + * @param string $file file/directory to check if writable + * + * @return bool true if the given path is writable + */ + protected function phpbb_is_writable($file) + { + if (file_exists($file)) + { + // Canonicalise path to absolute path + $file = $this->realpath($file); + + if (is_dir($file)) + { + // Test directory by creating a file inside the directory + $result = @tempnam($file, 'i_w'); + + if (is_string($result) && file_exists($result)) + { + unlink($result); + + // Ensure the file is actually in the directory (returned realpathed) + return (strpos($result, $file) === 0) ? true : false; + } + } + else + { + $handle = @fopen($file, 'w'); + + if (is_resource($handle)) + { + fclose($handle); + return true; + } + } + } + else + { + // file does not exist test if we can write to the directory + $dir = dirname($file); + + if (file_exists($dir) && is_dir($dir) && $this->phpbb_is_writable($dir)) + { + return true; + } + } + + return false; + } + + /** + * Try to resolve real path when PHP's realpath failes to do so + * + * @param string $path + * @return bool|string + */ + protected function phpbb_own_realpath($path) + { + // Replace all directory separators with '/' + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + + $is_absolute_path = false; + $path_prefix = ''; + + if ($this->is_absolute_path($path)) + { + $is_absolute_path = true; + } + else + { + // Resolve working directory and store it + if (is_null($this->working_directory)) + { + if (function_exists('getcwd')) + { + $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()); + } + + // + // From this point on we really just guessing + // If chdir were called we screwed + // + else if (function_exists('debug_backtrace')) + { + $call_stack = debug_backtrace(0); + $this->working_directory = str_replace(DIRECTORY_SEPARATOR, '/', dirname($call_stack[sizeof($call_stack) - 1]['file'])); + } + else + { + // + // Assuming that the working directory is phpBB root + // we could use this as a fallback, when phpBB will use controllers + // everywhere this will be a safe assumption + // + //$dir_parts = explode(DIRECTORY_SEPARATOR, __DIR__); + //$namespace_parts = explode('\\', trim(__NAMESPACE__, '\\')); + + //$namespace_part_count = sizeof($namespace_parts); + + // Check if we still loading from root + //if (array_slice($dir_parts, -$namespace_part_count) === $namespace_parts) + //{ + // $this->working_directory = implode('/', array_slice($dir_parts, 0, -$namespace_part_count)); + //} + //else + //{ + // $this->working_directory = false; + //} + + $this->working_directory = false; + } + } + + if ($this->working_directory !== false) + { + $is_absolute_path = true; + $path = $this->working_directory . '/' . $path; + } + } + + if ($is_absolute_path) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) + { + $path_prefix = $path[0] . ':'; + $path = substr($path, 2); + } + else + { + $path_prefix = ''; + } + } + + $resolved_path = $this->resolve_path($path, $path_prefix, $is_absolute_path); + if ($resolved_path === false) + { + return false; + } + + if (!@file_exists($resolved_path) || (!@is_dir($resolved_path . '/') && !is_file($resolved_path))) + { + return false; + } + + // Return OS specific directory separators + $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved_path); + + // Check for DIRECTORY_SEPARATOR at the end (and remove it!) + if (substr($resolved, -1) === DIRECTORY_SEPARATOR) + { + return substr($resolved, 0, -1); + } + + return $resolved; + } + + /** + * Convert file(s) to \Traversable object + * + * This is the same function as Symfony's toIterator, but that is private + * so we cannot use it. + * + * @param string|array|\Traversable $files filename/list of filenames + * @return \Traversable + */ + protected function to_iterator($files) + { + if (!$files instanceof \Traversable) + { + $files = new \ArrayObject(is_array($files) ? $files : array($files)); + } + + return $files; + } + + /** + * Try to resolve symlinks in path + * + * @param string $path The path to resolve + * @param string $prefix The path prefix (on windows the drive letter) + * @param bool $absolute Whether or not the path is absolute + * @param bool $return_array Whether or not to return path parts + * + * @return string|array|bool returns the resolved path or an array of parts of the path if $return_array is true + * or false if path cannot be resolved + */ + protected function resolve_path($path, $prefix = '', $absolute = false, $return_array = false) + { + if ($return_array) + { + $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); + } + + trim ($path, '/'); + $path_parts = explode('/', $path); + $resolved = array(); + $resolved_path = $prefix; + $file_found = false; + + foreach ($path_parts as $path_part) + { + if ($file_found) + { + return false; + } + + if (empty($path_part) || ($path_part === '.' && ($absolute || !empty($resolved)))) + { + continue; + } + else if ($absolute && $path_part === '..') + { + if (empty($resolved)) + { + // No directories above root + return false; + } + + array_pop($resolved); + $resolved_path = false; + } + else if ($path_part === '..' && !empty($resolved) && !in_array($resolved[sizeof($resolved) - 1], array('.', '..'))) + { + array_pop($resolved); + $resolved_path = false; + } + else + { + if ($resolved_path === false) + { + if (empty($resolved)) + { + $resolved_path = ($absolute) ? $prefix . '/' . $path_part : $path_part; + } + else + { + $tmp_array = $resolved; + if ($absolute) + { + array_unshift($tmp_array, $prefix); + } + + $resolved_path = implode('/', $tmp_array); + } + } + + $current_path = $resolved_path . '/' . $path_part; + + // Resolve symlinks + if (is_link($current_path)) + { + if (!function_exists('readlink')) + { + return false; + } + + $link = readlink($current_path); + + // Is link has an absolute path in it? + if ($this->is_absolute_path($link)) + { + if (defined('PHP_WINDOWS_VERSION_MAJOR')) + { + $prefix = $link[0] . ':'; + $link = substr($link, 2); + } + else + { + $prefix = ''; + } + + $resolved = $this->resolve_path($link, $prefix, true, true); + $absolute = true; + } + else + { + $resolved = $this->resolve_path($resolved_path . '/' . $link, $prefix, $absolute, true); + } + + if (!$resolved) + { + return false; + } + + $resolved_path = false; + } + else if (is_dir($current_path . '/')) + { + $resolved[] = $path_part; + $resolved_path = $current_path; + } + else if (is_file($current_path)) + { + $resolved[] = $path_part; + $resolved_path = $current_path; + $file_found = true; + } + else + { + return false; + } + } + } + + // If at the end of the path there were a .. or . + // we need to build the path again. + // Only doing this when a string is expected in return + if ($resolved_path === false && $return_array === false) + { + if (empty($resolved)) + { + $resolved_path = ($absolute) ? $prefix . '/' : './'; + } + else + { + $tmp_array = $resolved; + if ($absolute) + { + array_unshift($tmp_array, $prefix); + } + + $resolved_path = implode('/', $tmp_array); + } + } + + return ($return_array) ? $resolved : $resolved_path; + } +} diff --git a/phpBB/phpbb/filesystem/filesystem_interface.php b/phpBB/phpbb/filesystem/filesystem_interface.php new file mode 100644 index 0000000000..21ad8252f8 --- /dev/null +++ b/phpBB/phpbb/filesystem/filesystem_interface.php @@ -0,0 +1,284 @@ +<?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\filesystem; + +/** + * Interface for phpBB's filesystem service + */ +interface filesystem_interface +{ + /** + * chmod all permissions flag + * + * @var int + */ + const CHMOD_ALL = 7; + + /** + * chmod read permissions flag + * + * @var int + */ + const CHMOD_READ = 4; + + /** + * chmod write permissions flag + * + * @var int + */ + const CHMOD_WRITE = 2; + + /** + * chmod execute permissions flag + * + * @var int + */ + const CHMOD_EXECUTE = 1; + + /** + * Change owner group of files/directories + * + * @param string|array|\Traversable $files The file(s)/directorie(s) to change group + * @param string $group The group that should own the files/directories + * @param bool $recursive If the group should be changed recursively + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chgrp($files, $group, $recursive = false); + + /** + * Global function for chmodding directories and files for internal use + * + * The function accepts filesystem_interface::CHMOD_ flags in the permission argument + * or the user can specify octal values (or any integer if it makes sense). All directories will have + * an execution bit appended, if the user group (owner, group or other) has any bit specified. + * + * @param string|array|\Traversable $file The file/directory to be chmodded + * @param int $perms Permissions to set + * @param bool $recursive If the permissions should be changed recursively + * @param bool $force_chmod_link Try to apply permissions to symlinks as well + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chmod($files, $perms = null, $recursive = false, $force_chmod_link = false); + + /** + * Change owner group of files/directories + * + * @param string|array|\Traversable $files The file(s)/directorie(s) to change group + * @param string $user The owner user name + * @param bool $recursive Whether change the owner recursively or not + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function chown($files, $user, $recursive = false); + + /** + * Eliminates useless . and .. components from specified path. + * + * @param string $path Path to clean + * + * @return string Cleaned path + */ + public function clean_path($path); + + /** + * Copies a file. + * + * This method only copies the file if the origin file is newer than the target file. + * + * By default, if the target already exists, it is not overridden. + * + * @param string $origin_file The original filename + * @param string $target_file The target filename + * @param bool $override Whether to override an existing file or not + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied + */ + public function copy($origin_file, $target_file, $override = false); + + /** + * Atomically dumps content into a file. + * + * @param string $filename The file to be written to. + * @param string $content The data to write into the file. + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be written + */ + public function dump_file($filename, $content); + + /** + * Checks the existence of files or directories. + * + * @param string|array|\Traversable $files files/directories to check + * + * @return bool Returns true if all files/directories exist, false otherwise + */ + public function exists($files); + + /** + * Checks if a path is absolute or not + * + * @param string $path Path to check + * + * @return bool true if the path is absolute, false otherwise + */ + public function is_absolute_path($path); + + /** + * Checks if files/directories are readable + * + * @param string|array|\Traversable $files files/directories to check + * @param bool $recursive Whether or not directories should be checked recursively + * + * @return bool True when the files/directories are readable, otherwise false. + */ + public function is_readable($files, $recursive = false); + + /** + * Test if a file/directory is writable + * + * @param string|array|\Traversable $files files/directories to perform write test on + * @param bool $recursive Whether or not directories should be checked recursively + * + * @return bool True when the files/directories are writable, otherwise false. + */ + public function is_writable($files, $recursive = false); + + /** + * Given an existing path, convert it to a path relative to a given starting path + * + * @param string $end_path Absolute path of target + * @param string $start_path Absolute path where traversal begins + * + * @return string Path of target relative to starting path + */ + public function make_path_relative($end_path, $start_path); + + /** + * Mirrors a directory to another. + * + * @param string $origin_dir The origin directory + * @param string $target_dir The target directory + * @param \Traversable $iterator A Traversable instance + * @param array $options An array of boolean options + * Valid options are: + * - $options['override'] Whether to override an existing file on copy or not (see copy()) + * - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink()) + * - $options['delete'] Whether to delete files that are not in the source directory (defaults to false) + * + * @throws \phpbb\filesystem\exception\filesystem_exception When the file cannot be copied. + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function mirror($origin_dir, $target_dir, \Traversable $iterator = null, $options = array()); + + /** + * Creates a directory recursively. + * + * @param string|array|\Traversable $dirs The directory path + * @param int $mode The directory mode + * + * @throws \phpbb\filesystem\exception\filesystem_exception On any directory creation failure + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function mkdir($dirs, $mode = 0777); + + /** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * filesystem_interface::CHMOD_ALL - all permissions (7) + * filesystem_interface::CHMOD_READ - read permission (4) + * filesystem_interface::CHMOD_WRITE - write permission (2) + * filesystem_interface::CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string|array|\Traversable $file The file/directory to be chmodded + * @param int $perms Permissions to set + * @param bool $recursive If the permissions should be changed recursively + * @param bool $force_chmod_link Try to apply permissions to symlinks as well + * + * @throws \phpbb\filesystem\exception\filesystem_exception the filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function phpbb_chmod($file, $perms = null, $recursive = false, $force_chmod_link = false); + + /** + * A wrapper for PHP's realpath + * + * Try to resolve realpath when PHP's realpath is not available, or + * known to be buggy. + * + * @param string $path Path to resolve + * + * @return string Resolved path + */ + public function realpath($path); + + /** + * Removes files or directories. + * + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove + * + * @throws \phpbb\filesystem\exception\filesystem_exception When removal fails. + * The filename which triggered the error can be + * retrieved by filesystem_exception::get_filename() + */ + public function remove($files); + + /** + * Renames a file or a directory. + * + * @param string $origin The origin filename or directory + * @param string $target The new filename or directory + * @param bool $overwrite Whether to overwrite the target if it already exists + * + * @throws \phpbb\filesystem\exception\filesystem_exception When target file or directory already exists, + * or origin cannot be renamed. + */ + public function rename($origin, $target, $overwrite = false); + + /** + * Creates a symbolic link or copy a directory. + * + * @param string $origin_dir The origin directory path + * @param string $target_dir The symbolic link name + * @param bool $copy_on_windows Whether to copy files if on Windows + * + * @throws \phpbb\filesystem\exception\filesystem_exception When symlink fails + */ + public function symlink($origin_dir, $target_dir, $copy_on_windows = false); + + /** + * Sets access and modification time of file. + * + * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create + * @param int $time The touch time as a Unix timestamp + * @param int $access_time The access time as a Unix timestamp + * + * @throws \phpbb\filesystem\exception\filesystem_exception When touch fails + */ + public function touch($files, $time = null, $access_time = null); +} diff --git a/phpBB/phpbb/finder.php b/phpBB/phpbb/finder.php index 28f28825ba..58bc27084e 100644 --- a/phpBB/phpbb/finder.php +++ b/phpBB/phpbb/finder.php @@ -48,14 +48,14 @@ class finder /** * Creates a new finder instance with its dependencies * - * @param \phpbb\filesystem $filesystem Filesystem instance + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem instance * @param string $phpbb_root_path Path to the phpbb root directory * @param \phpbb\cache\driver\driver_interface $cache A cache instance or null * @param string $php_ext php file extension * @param string $cache_name The name of the cache variable, defaults to * _ext_finder */ - public function __construct(\phpbb\filesystem $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path = '', \phpbb\cache\driver\driver_interface $cache = null, $php_ext = 'php', $cache_name = '_ext_finder') { $this->filesystem = $filesystem; $this->phpbb_root_path = $phpbb_root_path; diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index 5400c1c5a6..7b0d6f0fba 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -21,7 +21,7 @@ class path_helper /** @var \phpbb\symfony_request */ protected $symfony_request; - /** @var \phpbb\filesystem */ + /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; /** @var \phpbb\request\request_interface */ @@ -43,13 +43,13 @@ class path_helper * Constructor * * @param \phpbb\symfony_request $symfony_request - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param \phpbb\request\request_interface $request * @param string $phpbb_root_path Relative path to phpBB root * @param string $php_ext PHP file extension * @param mixed $adm_relative_path Relative path admin path to adm/ root */ - public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null) + public function __construct(\phpbb\symfony_request $symfony_request, \phpbb\filesystem\filesystem_interface $filesystem, \phpbb\request\request_interface $request, $phpbb_root_path, $php_ext, $adm_relative_path = null) { $this->symfony_request = $symfony_request; $this->filesystem = $filesystem; diff --git a/phpBB/phpbb/routing/router.php b/phpBB/phpbb/routing/router.php index 4ccd3cf5e3..5313106b0a 100644 --- a/phpBB/phpbb/routing/router.php +++ b/phpBB/phpbb/routing/router.php @@ -86,16 +86,23 @@ class router implements RouterInterface protected $route_collection; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Construct method * + * @param \phpbb\filesystem\filesystem_interface $filesystem Filesystem helper * @param manager $extension_manager Extension manager * @param string $phpbb_root_path phpBB root path * @param string $php_ext PHP file extension * @param string $environment Name of the current environment * @param array $routing_files Array of strings containing paths to YAML files holding route information */ - public function __construct(manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, manager $extension_manager, $phpbb_root_path, $php_ext, $environment, $routing_files = array()) { + $this->filesystem = $filesystem; $this->extension_manager = $extension_manager; $this->routing_files = $routing_files; $this->phpbb_root_path = $phpbb_root_path; @@ -148,7 +155,7 @@ class router implements RouterInterface $this->route_collection = new RouteCollection; foreach ($this->routing_files as $file_path) { - $loader = new YamlFileLoader(new FileLocator(phpbb_realpath($base_path))); + $loader = new YamlFileLoader(new FileLocator($this->filesystem->realpath($base_path))); $this->route_collection->addCollection($loader->load($file_path)); } } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index d49f88b676..6154f384f3 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -92,8 +92,8 @@ class session } // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path))); - $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./'))); + $root_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath($root_path))); + $page_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath('./'))); $intersection = array_intersect_assoc($root_dirs, $page_dirs); $root_dirs = array_diff_assoc($root_dirs, $intersection); diff --git a/phpBB/phpbb/template/twig/loader.php b/phpBB/phpbb/template/twig/loader.php index 2f8ffaa776..df8183c019 100644 --- a/phpBB/phpbb/template/twig/loader.php +++ b/phpBB/phpbb/template/twig/loader.php @@ -21,6 +21,24 @@ class loader extends \Twig_Loader_Filesystem protected $safe_directories = array(); /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** + * Constructor + * + * @param \phpbb\filesystem\filesystem_interface $filesystem + * @param string|array $paths + */ + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem, $paths = array()) + { + $this->filesystem = $filesystem; + + parent::__construct($paths); + } + + /** * Set safe directories * * @param array $directories Array of directories that are safe (empty to clear) @@ -49,7 +67,7 @@ class loader extends \Twig_Loader_Filesystem */ public function addSafeDirectory($directory) { - $directory = phpbb_realpath($directory); + $directory = $this->filesystem->realpath($directory); if ($directory !== false) { @@ -118,7 +136,7 @@ class loader extends \Twig_Loader_Filesystem // can now check if we're within a "safe" directory // Find the real path of the directory the file is in - $directory = phpbb_realpath(dirname($file)); + $directory = $this->filesystem->realpath(dirname($file)); if ($directory === false) { diff --git a/phpBB/phpbb/viewonline_helper.php b/phpBB/phpbb/viewonline_helper.php index b722f9d911..89915f2228 100644 --- a/phpBB/phpbb/viewonline_helper.php +++ b/phpBB/phpbb/viewonline_helper.php @@ -18,13 +18,13 @@ namespace phpbb; */ class viewonline_helper { - /** @var \phpbb\filesystem */ + /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; /** - * @param \phpbb\filesystem $filesystem + * @param \phpbb\filesystem\filesystem_interface $filesystem phpBB's filesystem service */ - public function __construct(\phpbb\filesystem $filesystem) + public function __construct(\phpbb\filesystem\filesystem_interface $filesystem) { $this->filesystem = $filesystem; } |