mirror of
https://github.com/phpbb/phpbb.git
synced 2025-07-31 22:10:45 +02:00
[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
This commit is contained in:
@@ -18,6 +18,11 @@ namespace phpbb\avatar\driver;
|
||||
*/
|
||||
class upload extends \phpbb\avatar\driver\driver
|
||||
{
|
||||
/**
|
||||
* @var \phpbb\filesystem\filesystem_interface
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* @var \phpbb\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'));
|
||||
}
|
||||
}
|
||||
|
8
phpBB/phpbb/cache/driver/base.php
vendored
8
phpBB/phpbb/cache/driver/base.php
vendored
@@ -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);
|
||||
|
25
phpBB/phpbb/cache/driver/file.php
vendored
25
phpBB/phpbb/cache/driver/file.php
vendored
@@ -20,6 +20,11 @@ class file extends \phpbb\cache\driver\base
|
||||
{
|
||||
var $var_expires = array();
|
||||
|
||||
/**
|
||||
* @var \phpbb\filesystem\filesystem_interface
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* Set cache path
|
||||
*
|
||||
@@ -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;
|
||||
}
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -37,17 +37,24 @@ 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');
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
42
phpBB/phpbb/filesystem/exception/filesystem_exception.php
Normal file
42
phpBB/phpbb/filesystem/exception/filesystem_exception.php
Normal file
@@ -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'];
|
||||
}
|
||||
}
|
916
phpBB/phpbb/filesystem/filesystem.php
Normal file
916
phpBB/phpbb/filesystem/filesystem.php
Normal file
@@ -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;
|
||||
}
|
||||
}
|
284
phpBB/phpbb/filesystem/filesystem_interface.php
Normal file
284
phpBB/phpbb/filesystem/filesystem_interface.php
Normal file
@@ -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);
|
||||
}
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -85,17 +85,24 @@ 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));
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -20,6 +20,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
|
||||
*
|
||||
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user