diff --git a/phpBB/config/default/container/services_attachment.yml b/phpBB/config/default/container/services_attachment.yml index 5b614d2f60..afabbd6f95 100644 --- a/phpBB/config/default/container/services_attachment.yml +++ b/phpBB/config/default/container/services_attachment.yml @@ -36,4 +36,5 @@ services: - '@dispatcher' - '@plupload' - '@storage.attachment' + - '@filesystem.temp' - '@user' diff --git a/phpBB/config/default/container/services_db.yml b/phpBB/config/default/container/services_db.yml index d538177603..fe7d42937d 100644 --- a/phpBB/config/default/container/services_db.yml +++ b/phpBB/config/default/container/services_db.yml @@ -34,7 +34,7 @@ services: class: phpbb\db\extractor\mssql_extractor shared: false arguments: - - '%core.root_path%' + - '@filesystem.temp' - '@request' - '@dbal.conn.driver' @@ -42,7 +42,7 @@ services: class: phpbb\db\extractor\mysql_extractor shared: false arguments: - - '%core.root_path%' + - '@filesystem.temp' - '@request' - '@dbal.conn.driver' @@ -50,7 +50,7 @@ services: class: phpbb\db\extractor\oracle_extractor shared: false arguments: - - '%core.root_path%' + - '@filesystem.temp' - '@request' - '@dbal.conn.driver' @@ -58,7 +58,7 @@ services: class: phpbb\db\extractor\postgres_extractor shared: false arguments: - - '%core.root_path%' + - '@filesystem.temp' - '@request' - '@dbal.conn.driver' @@ -66,6 +66,6 @@ services: class: phpbb\db\extractor\sqlite3_extractor shared: false arguments: - - '%core.root_path%' + - '@filesystem.temp' - '@request' - '@dbal.conn.driver' diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml index 96682d6713..d1114c9c68 100644 --- a/phpBB/config/default/container/services_files.yml +++ b/phpBB/config/default/container/services_files.yml @@ -71,10 +71,10 @@ services: arguments: - '@config' - '@files.factory' + - '@filesystem.temp' - '@language' - '@php_ini' - '@request' - - '%core.root_path%' files.types.remote_storage: class: phpbb\files\types\remote_storage @@ -82,7 +82,7 @@ services: arguments: - '@config' - '@files.factory' + - '@filesystem.temp' - '@language' - '@php_ini' - '@request' - - '%core.root_path%' diff --git a/phpBB/config/default/container/services_filesystem.yml b/phpBB/config/default/container/services_filesystem.yml index 828f9076dd..15206314b9 100644 --- a/phpBB/config/default/container/services_filesystem.yml +++ b/phpBB/config/default/container/services_filesystem.yml @@ -1,3 +1,12 @@ +parameters: + core.filesystem.cache_temp_dir: '%core.cache_dir%tmp/' + services: filesystem: class: phpbb\filesystem\filesystem + + filesystem.temp: + class: phpbb\filesystem\temp + arguments: + - '@filesystem' + - '%core.filesystem.cache_temp_dir%' diff --git a/phpBB/config/default/container/services_storage.yml b/phpBB/config/default/container/services_storage.yml index f114dc1dfe..7216b4b5c4 100644 --- a/phpBB/config/default/container/services_storage.yml +++ b/phpBB/config/default/container/services_storage.yml @@ -17,6 +17,14 @@ services: tags: - { name: storage } + storage.backup: + class: phpbb\storage\storage + arguments: + - '@storage.adapter.factory' + - 'backup' + tags: + - { name: storage } + # Factory storage.adapter.factory: class: phpbb\storage\adapter_factory diff --git a/phpBB/config/default/container/tables.yml b/phpBB/config/default/container/tables.yml index 4aed35710b..6adacca0d0 100644 --- a/phpBB/config/default/container/tables.yml +++ b/phpBB/config/default/container/tables.yml @@ -8,6 +8,7 @@ parameters: tables.auth_provider_oauth_token_storage: '%core.table_prefix%oauth_tokens' tables.auth_provider_oauth_states: '%core.table_prefix%oauth_states' tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts' + tables.backups: '%core.table_prefix%backups' tables.banlist: '%core.table_prefix%banlist' tables.bbcodes: '%core.table_prefix%bbcodes' tables.bookmarks: '%core.table_prefix%bookmarks' diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index b98756a34b..c26ecdb849 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -21,15 +21,18 @@ if (!defined('IN_PHPBB')) class acp_database { - var $db_tools; - var $u_action; + protected $db_tools; + protected $temp; + public $u_action; function main($id, $mode) { global $cache, $db, $user, $template, $table_prefix, $request; - global $phpbb_root_path, $phpbb_container, $phpbb_log; + global $phpbb_root_path, $phpbb_container, $phpbb_log, $table_prefix; $this->db_tools = $phpbb_container->get('dbal.tools'); + $this->temp = $phpbb_container->get('filesystem.temp'); + $storage = $phpbb_container->get('storage.backup'); $user->add_lang('acp/database'); @@ -98,50 +101,107 @@ class acp_database $filename = 'backup_' . $time . '_' . unique_id(); - $extractor = $phpbb_container->get('dbal.extractor'); - $extractor->init_extractor($format, $filename, $time, $download, $store); - - $extractor->write_start($table_prefix); - - foreach ($table as $table_name) + try { - // Get the table structure - if ($structure) + $extractor = $phpbb_container->get('dbal.extractor'); + $extractor->init_extractor($format, $filename, $time, $download, $store); + + $extractor->write_start($table_prefix); + + foreach ($table as $table_name) { - $extractor->write_table($table_name); - } - else - { - // We might wanna empty out all that junk :D - switch ($db->get_sql_layer()) + // Get the table structure + if ($structure) { - case 'sqlite3': - $extractor->flush('DELETE FROM ' . $table_name . ";\n"); - break; + // Add table structure to the backup + // This method also add a "drop the table if exists" after trying to write the table structure + $extractor->write_table($table_name); + } + else + { + // Add command to empty table before write data on it + switch ($db->get_sql_layer()) + { + case 'sqlite3': + $extractor->flush('DELETE FROM ' . $table_name . ";\n"); + break; - case 'mssql_odbc': - case 'mssqlnative': - $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); - break; + case 'mssql_odbc': + case 'mssqlnative': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); + break; - case 'oracle': - $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); - break; + case 'oracle': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); + break; - default: - $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); - break; + default: + $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); + break; + } + } + + // Write schema data if it exists + if ($schema_data) + { + $extractor->write_data($table_name); } } - // Data - if ($schema_data) - { - $extractor->write_data($table_name); - } + $extractor->write_end(); + } + catch (\phpbb\exception\runtime_exception $e) + { + trigger_error($e->getMessage(), E_USER_ERROR); } - $extractor->write_end(); + try + { + if ($store) + { + // Get file name + switch ($format) + { + case 'text': + $ext = '.sql'; + break; + case 'bzip2': + $ext = '.sql.gz2'; + break; + case 'gzip': + $ext = '.sql.gz'; + break; + } + + $file = $filename . $ext; + + // Copy to storage using streams + $temp_dir = $this->temp->get_dir(); + + $fp = fopen($temp_dir . '/' . $file, 'rb'); + + if ($fp === false) + { + throw new \phpbb\exception\runtime_exception('CANNOT_OPEN_FILE'); + } + + $storage->write_stream($file, $fp); + + fclose($fp); + + // Remove file from tmp + @unlink($temp_dir . '/' . $file); + + // Save to database + $sql = "INSERT INTO " . $table_prefix . "backups (filename) + VALUES ('$file');"; + $db->sql_query($sql); + } + } + catch (\phpbb\exception\runtime_exception $e) + { + trigger_error($e->getMessage(), E_USER_ERROR); + } $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP'); @@ -208,9 +268,9 @@ class acp_database trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } - $file_name = $phpbb_root_path . 'store/' . $matches[0]; + $file_name = $matches[0]; - if (!file_exists($file_name) || !is_readable($file_name)) + if (!$storage->exists($file_name)) { trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -219,8 +279,24 @@ class acp_database { if (confirm_box(true)) { - unlink($file_name); - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); + try + { + // Delete from storage + $storage->delete($file_name); + + // Add log entry + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); + + // Remove from database + $sql = "DELETE FROM " . $table_prefix . "backups + WHERE filename = '" . $db->sql_escape($file_name) . "';"; + $db->sql_query($sql); + } + catch (\Exception $e) + { + trigger_error($user->lang['BACKUP_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); + } + trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); } else @@ -253,25 +329,47 @@ class acp_database @set_time_limit(0); - $fp = @fopen($file_name, 'rb'); - - if ($fp !== false) + try { + $fp = $storage->read_stream($file_name); + while (!feof($fp)) { echo fread($fp, 8192); } fclose($fp); } + catch (\phpbb\storage\exception\exception $e) + { + // If open fails, just finish + } flush(); exit; } + // Copy file to temp folder to decompress it + $temp_file_name = $this->temp->get_dir() . '/' . $file_name; + + try + { + $stream = $storage->read_stream($file_name); + $fp = fopen($temp_file_name, 'w+b'); + + stream_copy_to_stream($stream, $fp); + + fclose($fp); + fclose($stream); + } + catch (\phpbb\storage\exception\exception $e) + { + trigger_error($user->lang['RESTORE_DOWNLOAD_FAIL'] . adm_back_link($this->u_action)); + } + switch ($matches[1]) { case 'sql': - $fp = fopen($file_name, 'rb'); + $fp = fopen($temp_file_name, 'rb'); $read = 'fread'; $seek = 'fseek'; $eof = 'feof'; @@ -280,7 +378,7 @@ class acp_database break; case 'sql.bz2': - $fp = bzopen($file_name, 'r'); + $fp = bzopen($temp_file_name, 'r'); $read = 'bzread'; $seek = ''; $eof = 'feof'; @@ -289,7 +387,7 @@ class acp_database break; case 'sql.gz': - $fp = gzopen($file_name, 'rb'); + $fp = gzopen($temp_file_name, 'rb'); $read = 'gzread'; $seek = 'gzseek'; $eof = 'gzeof'; @@ -368,6 +466,8 @@ class acp_database $close($fp); + @unlink($temp_file_name); + // Purge the cache due to updated data $cache->purge(); @@ -393,26 +493,25 @@ class acp_database $methods[] = $type; } - $dir = $phpbb_root_path . 'store/'; - $dh = @opendir($dir); + $sql = 'SELECT filename + FROM ' . BACKUPS_TABLE; + $result = $db->sql_query($sql); $backup_files = array(); - if ($dh) + while ($row = $db->sql_fetchrow($result)) { - while (($file = readdir($dh)) !== false) + if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $row['filename'], $matches)) { - if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + if (in_array($matches[2], $methods)) { - if (in_array($matches[2], $methods)) - { - $backup_files[(int) $matches[1]] = $file; - } + $backup_files[(int) $matches[1]] = $row['filename']; } } - closedir($dh); } + $db->sql_freeresult($result); + if (!empty($backup_files)) { krsort($backup_files); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 2fa11e4d86..ee8b642b9b 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -239,6 +239,7 @@ define('ACL_ROLES_DATA_TABLE', $table_prefix . 'acl_roles_data'); define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles'); define('ACL_USERS_TABLE', $table_prefix . 'acl_users'); define('ATTACHMENTS_TABLE', $table_prefix . 'attachments'); +define('BACKUPS_TABLE', $table_prefix . 'backups'); define('BANLIST_TABLE', $table_prefix . 'banlist'); define('BBCODES_TABLE', $table_prefix . 'bbcodes'); define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks'); diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index c6a60af67b..14c63fab72 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -291,6 +291,8 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\attachment INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\attachment\config\path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\avatar\provider', 'phpbb\storage\provider\local'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\avatar\config\path', 'images/avatars/upload'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\backup\provider', 'phpbb\storage\provider\local'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('storage\backup\config\path', 'store'); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cache_last_gc', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1); diff --git a/phpBB/language/en/acp/database.php b/phpBB/language/en/acp/database.php index ab85701eaa..7170cefe8e 100644 --- a/phpBB/language/en/acp/database.php +++ b/phpBB/language/en/acp/database.php @@ -43,6 +43,7 @@ $lang = array_merge($lang, array( 'BACKUP_DELETE' => 'The backup file has been deleted successfully.', 'BACKUP_INVALID' => 'The selected file to backup is invalid.', + 'BACKUP_ERROR' => 'Error while saving file.', 'BACKUP_OPTIONS' => 'Backup options', 'BACKUP_SUCCESS' => 'The backup file has been created successfully.', 'BACKUP_TYPE' => 'Backup type', @@ -58,6 +59,7 @@ $lang = array_merge($lang, array( 'FILE_WRITE_FAIL' => 'Unable to write file to storage folder.', 'FULL_BACKUP' => 'Full', + 'RESTORE_DOWNLOAD_FAIL' => 'Error while copying file from storage to local temporary folder.', 'RESTORE_FAILURE' => 'The backup file may be corrupt.', 'RESTORE_OPTIONS' => 'Restore options', 'RESTORE_SELECTED_BACKUP' => 'Are you sure you want to restore the selected backup?', diff --git a/phpBB/phpbb/attachment/upload.php b/phpBB/phpbb/attachment/upload.php index 82a7578380..54515fd0a6 100644 --- a/phpBB/phpbb/attachment/upload.php +++ b/phpBB/phpbb/attachment/upload.php @@ -21,6 +21,7 @@ use \phpbb\language\language; use \phpbb\mimetype\guesser; use \phpbb\plupload\plupload; use \phpbb\storage\storage; +use \phpbb\filesystem\temp; use \phpbb\user; /** @@ -55,6 +56,9 @@ class upload /** @var storage */ protected $storage; + /** @var temp */ + protected $temp; + /** @var user */ protected $user; @@ -80,9 +84,10 @@ class upload * @param guesser $mimetype_guesser * @param dispatcher $phpbb_dispatcher * @param plupload $plupload + * @param temp $temp * @param user $user */ - public function __construct(auth $auth, service $cache, config $config, \phpbb\files\upload $files_upload, language $language, guesser $mimetype_guesser, dispatcher $phpbb_dispatcher, plupload $plupload, storage $storage, user $user) + public function __construct(auth $auth, service $cache, config $config, \phpbb\files\upload $files_upload, language $language, guesser $mimetype_guesser, dispatcher $phpbb_dispatcher, plupload $plupload, storage $storage, temp $temp, user $user) { $this->auth = $auth; $this->cache = $cache; @@ -93,6 +98,7 @@ class upload $this->phpbb_dispatcher = $phpbb_dispatcher; $this->plupload = $plupload; $this->storage = $storage; + $this->temp = $temp; $this->user = $user; } @@ -234,7 +240,7 @@ class upload { $source = $this->file->get('filename'); $destination_name = 'thumb_' . $this->file->get('realname'); - $destination = sys_get_temp_dir() . '/' . $destination_name; + $destination = $this->temp->get_dir() . '/' . $destination_name; if (create_thumbnail($source, $destination, $this->file->get('mimetype'))) { diff --git a/phpBB/phpbb/db/extractor/base_extractor.php b/phpBB/phpbb/db/extractor/base_extractor.php index 547c85f066..106e047eaa 100644 --- a/phpBB/phpbb/db/extractor/base_extractor.php +++ b/phpBB/phpbb/db/extractor/base_extractor.php @@ -22,9 +22,9 @@ use phpbb\db\extractor\exception\extractor_not_initialized_exception; abstract class base_extractor implements extractor_interface { /** - * @var string phpBB root path + * @var \phpbb\filesystem\temp */ - protected $phpbb_root_path; + protected $temp; /** * @var \phpbb\request\request_interface @@ -84,13 +84,13 @@ abstract class base_extractor implements extractor_interface /** * Constructor * - * @param string $phpbb_root_path + * @param \phpbb\filesystem\temp $temp * @param \phpbb\request\request_interface $request * @param \phpbb\db\driver\driver_interface $db */ - public function __construct($phpbb_root_path, \phpbb\request\request_interface $request, \phpbb\db\driver\driver_interface $db) + public function __construct(\phpbb\filesystem\temp $temp, \phpbb\request\request_interface $request, \phpbb\db\driver\driver_interface $db) { - $this->phpbb_root_path = $phpbb_root_path; + $this->temp = $temp; $this->request = $request; $this->db = $db; $this->fp = null; @@ -164,13 +164,13 @@ abstract class base_extractor implements extractor_interface if ($store === true) { - $file = $this->phpbb_root_path . 'store/' . $filename . $ext; + $file = $this->temp->get_dir() . '/' . $filename . $ext; $this->fp = $open($file, 'w'); if (!$this->fp) { - trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); + throw new \phpbb\exception\runtime_exception('FILE_WRITE_FAIL'); } } diff --git a/phpBB/phpbb/db/migration/data/v330/storage_backup.php b/phpBB/phpbb/db/migration/data/v330/storage_backup.php new file mode 100644 index 0000000000..316ba4c104 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v330/storage_backup.php @@ -0,0 +1,40 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v330; + +class storage_backup extends \phpbb\db\migration\migration +{ + public function update_schema() + { + return array( + 'add_tables' => array( + $this->table_prefix . 'backups' => array( + 'COLUMNS' => array( + 'backup_id' => array('UINT', null, 'auto_increment'), + 'filename' => array('VCHAR', ''), + ), + 'PRIMARY_KEY' => 'backup_id', + ), + ), + ); + } + + public function update_data() + { + return array( + array('config.add', array('storage\\backup\\provider', \phpbb\storage\provider\local::class)), + array('config.add', array('storage\\backup\\config\\path', 'store')), + ); + } +} diff --git a/phpBB/phpbb/files/types/remote.php b/phpBB/phpbb/files/types/remote.php index e64e360b6a..17c3d7a614 100644 --- a/phpBB/phpbb/files/types/remote.php +++ b/phpBB/phpbb/files/types/remote.php @@ -17,6 +17,7 @@ use bantu\IniGetWrapper\IniGetWrapper; use phpbb\config\config; use phpbb\files\factory; use phpbb\files\filespec; +use phpbb\filesystem\temp; use phpbb\language\language; use phpbb\request\request_interface; @@ -28,30 +29,36 @@ class remote extends base /** @var factory Files factory */ protected $factory; + /** @var filesystem Filesystem temp */ + protected $temp; + + /** @var language */ + protected $language; + + /** @var IniGetWrapper */ + protected $php_ini; + /** @var request_interface */ protected $request; - /** @var string phpBB root path */ - protected $phpbb_root_path; - /** * Construct a form upload type * * @param config $config phpBB config * @param factory $factory Files factory + * @param temp $temp Filesystem temp * @param language $language Language class * @param IniGetWrapper $php_ini ini_get() wrapper * @param request_interface $request Request object - * @param string $phpbb_root_path phpBB root path */ - public function __construct(config $config, factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path) + public function __construct(config $config, factory $factory, temp $temp, language $language, IniGetWrapper $php_ini, request_interface $request) { $this->config = $config; $this->factory = $factory; + $this->temp = $temp; $this->language = $language; $this->php_ini = $php_ini; $this->request = $request; - $this->phpbb_root_path = $phpbb_root_path; } /** @@ -139,7 +146,7 @@ class remote extends base $data = $response->getBody(); - $filename = tempnam(sys_get_temp_dir(), unique_id() . '-'); + $filename = tempnam($this->temp->get_dir(), unique_id() . '-'); if (!($fp = @fopen($filename, 'wb'))) { diff --git a/phpBB/phpbb/files/types/remote_storage.php b/phpBB/phpbb/files/types/remote_storage.php index 3e6953703e..d542c5e2f4 100644 --- a/phpBB/phpbb/files/types/remote_storage.php +++ b/phpBB/phpbb/files/types/remote_storage.php @@ -17,6 +17,7 @@ use bantu\IniGetWrapper\IniGetWrapper; use phpbb\config\config; use phpbb\files\factory; use phpbb\files\filespec; +use phpbb\filesystem\temp; use phpbb\language\language; use phpbb\request\request_interface; @@ -28,30 +29,36 @@ class remote_storage extends base /** @var factory Files factory */ protected $factory; + /** @var temp Filesystem temp */ + protected $temp; + + /** @var language */ + protected $language; + + /** @var IniGetWrapper */ + protected $php_ini; + /** @var request_interface */ protected $request; - /** @var string phpBB root path */ - protected $phpbb_root_path; - /** * Construct a form upload type * * @param config $config phpBB config * @param factory $factory Files factory + * @param temp $temp Filesystem temp * @param language $language Language class * @param IniGetWrapper $php_ini ini_get() wrapper * @param request_interface $request Request object - * @param string $phpbb_root_path phpBB root path */ - public function __construct(config $config, factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path) + public function __construct(config $config, factory $factory, temp $temp, language $language, IniGetWrapper $php_ini, request_interface $request) { $this->config = $config; $this->factory = $factory; + $this->temp = $temp; $this->language = $language; $this->php_ini = $php_ini; $this->request = $request; - $this->phpbb_root_path = $phpbb_root_path; } /** @@ -138,7 +145,7 @@ class remote_storage extends base $data = $response->getBody(); - $filename = tempnam(sys_get_temp_dir(), unique_id() . '-'); + $filename = tempnam($this->temp->get_dir(), unique_id() . '-'); if (!($fp = @fopen($filename, 'wb'))) { diff --git a/phpBB/phpbb/filesystem/temp.php b/phpBB/phpbb/filesystem/temp.php new file mode 100644 index 0000000000..649221d802 --- /dev/null +++ b/phpBB/phpbb/filesystem/temp.php @@ -0,0 +1,54 @@ + + * @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; + +class temp +{ + /** + * @var string Temporary directory path + */ + protected $temp_dir; + + /** + * Constructor + */ + public function __construct($filesystem, $cache_temp_dir) + { + $tmp_dir = (function_exists('sys_get_temp_dir')) ? sys_get_temp_dir() : ''; + + // Prevent trying to write to system temp dir in case of open_basedir + // restrictions being in effect + if (empty($tmp_dir) || !@file_exists($tmp_dir) || !@is_writable($tmp_dir)) + { + $tmp_dir = $cache_temp_dir; + + if (!is_dir($tmp_dir)) + { + $filesystem->mkdir($tmp_dir, 0777); + } + } + + $this->temp_dir = helper::realpath($tmp_dir); + } + + /** + * Get a temporary directory to write files + * + * @return string returns the directory + */ + public function get_dir() + { + return $this->temp_dir; + } +} diff --git a/tests/attachment/upload_test.php b/tests/attachment/upload_test.php index 2d577db107..a9567510c8 100644 --- a/tests/attachment/upload_test.php +++ b/tests/attachment/upload_test.php @@ -54,8 +54,12 @@ class phpbb_attachment_upload_test extends \phpbb_database_test_case /** @var \phpbb\attachment\upload */ protected $upload; + /** @var \phpbb\filesystem\filesystem */ private $filesystem; + /** @var \phpbb\filesystem\temp */ + protected $temp; + /** @var \Symfony\Component\DependencyInjection\ContainerInterface */ protected $container; @@ -143,6 +147,7 @@ class phpbb_attachment_upload_test extends \phpbb_database_test_case $this->factory = new \phpbb\files\factory($this->container); $this->files_upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $this->phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $this->temp = new \phpbb\filesystem\temp($this->filesystem, ''); $this->user = new \phpbb\user($this->language, '\phpbb\datetime'); $this->upload = new \phpbb\attachment\upload( @@ -155,6 +160,7 @@ class phpbb_attachment_upload_test extends \phpbb_database_test_case $this->phpbb_dispatcher, $this->plupload, $this->storage, + $this->temp, $this->user ); } @@ -247,6 +253,7 @@ class phpbb_attachment_upload_test extends \phpbb_database_test_case $this->phpbb_dispatcher, $this->plupload, $this->storage, + $this->temp, $this->user ); @@ -411,6 +418,7 @@ class phpbb_attachment_upload_test extends \phpbb_database_test_case $this->phpbb_dispatcher, $plupload, $this->storage, + $this->temp, $this->user ); diff --git a/tests/files/types_remote_test.php b/tests/files/types_remote_test.php index 85ec2a528b..ea869bb85c 100644 --- a/tests/files/types_remote_test.php +++ b/tests/files/types_remote_test.php @@ -15,10 +15,15 @@ require_once dirname(__FILE__) . '/type_foo.php'; class phpbb_files_types_remote_test extends phpbb_test_case { + /** @var string */ private $path; + /** @var \phpbb\filesystem\filesystem */ private $filesystem; + /** @var \phpbb\filesystem\temp */ + private $temp; + /** @var \phpbb\config\config */ protected $config; @@ -49,7 +54,9 @@ class phpbb_files_types_remote_test extends phpbb_test_case $this->config->set('remote_upload_verify', 0); $this->request = $this->createMock('\phpbb\request\request'); + $cache_path = $phpbb_root_path . 'cache/files'; $this->filesystem = new \phpbb\filesystem\filesystem(); + $this->temp = new \phpbb\filesystem\temp($this->filesystem, $cache_path); $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; @@ -71,7 +78,7 @@ class phpbb_files_types_remote_test extends phpbb_test_case public function test_upload_fsock_fail() { - $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); + $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->temp, $this->language, $this->php_ini, $this->request); $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_allowed_extensions(array('png')); $type_remote->set_upload($upload); @@ -106,7 +113,7 @@ class phpbb_files_types_remote_test extends phpbb_test_case $php_ini->expects($this->any()) ->method('getString') ->willReturn($max_file_size); - $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->language, $php_ini, $this->request, $this->phpbb_root_path); + $type_remote = new \phpbb\files\types\remote($this->config, $this->factory, $this->temp, $this->language, $php_ini, $this->request); $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_allowed_extensions(array('png')); $type_remote->set_upload($upload); @@ -118,7 +125,7 @@ class phpbb_files_types_remote_test extends phpbb_test_case public function test_upload_wrong_path() { - $type_remote = new \phpbb\files\types\foo($this->config, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); + $type_remote = new \phpbb\files\types\foo($this->config, $this->factory, $this->temp, $this->language, $this->php_ini, $this->request); $upload = new \phpbb\files\upload($this->filesystem, $this->factory, $this->language, $this->php_ini, $this->request, $this->phpbb_root_path); $upload->set_allowed_extensions(array('png')); $type_remote->set_upload($upload); diff --git a/tests/functional/fileupload_remote_test.php b/tests/functional/fileupload_remote_test.php index 4fced5700a..0d09d5fcc8 100644 --- a/tests/functional/fileupload_remote_test.php +++ b/tests/functional/fileupload_remote_test.php @@ -19,6 +19,9 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case /** @var \phpbb\filesystem\filesystem_interface */ protected $filesystem; + /** @var \phpbb\filesystem\temp */ + protected $temp; + /** @var \phpbb\files\factory */ protected $factory; @@ -53,6 +56,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $config['remote_upload_verify'] = 0; $this->filesystem = new \phpbb\filesystem\filesystem(); + $this->temp = new \phpbb\filesystem\temp($this->filesystem, ''); $this->language = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); $this->request = $this->createMock('\phpbb\request\request'); $this->php_ini = new \bantu\IniGetWrapper\IniGetWrapper; @@ -61,7 +65,7 @@ class phpbb_functional_fileupload_remote_test extends phpbb_functional_test_case $container->set('files.filespec', new \phpbb\files\filespec($this->filesystem, $this->language, $this->php_ini, new \FastImageSize\FastImageSize(), $this->phpbb_root_path)); $this->factory = new \phpbb\files\factory($container); $container->set('files.factory', $this->factory); - $container->set('files.types.remote', new \phpbb\files\types\remote($config, $this->factory, $this->language, $this->php_ini, $this->request, $phpbb_root_path)); + $container->set('files.types.remote', new \phpbb\files\types\remote($config, $this->factory, $this->temp, $this->language, $this->php_ini, $this->request)); $this->phpbb_root_path = $phpbb_root_path; }