[ticket/15311] Use storage in backups

PHPBB3-15311
This commit is contained in:
Rubén Calvo 2017-08-09 18:56:35 +02:00
parent 1b11013988
commit fb716743d2
9 changed files with 207 additions and 68 deletions

View file

@ -34,7 +34,6 @@ services:
class: phpbb\db\extractor\mssql_extractor class: phpbb\db\extractor\mssql_extractor
shared: false shared: false
arguments: arguments:
- '%core.root_path%'
- '@request' - '@request'
- '@dbal.conn.driver' - '@dbal.conn.driver'
@ -42,7 +41,6 @@ services:
class: phpbb\db\extractor\mysql_extractor class: phpbb\db\extractor\mysql_extractor
shared: false shared: false
arguments: arguments:
- '%core.root_path%'
- '@request' - '@request'
- '@dbal.conn.driver' - '@dbal.conn.driver'
@ -50,7 +48,6 @@ services:
class: phpbb\db\extractor\oracle_extractor class: phpbb\db\extractor\oracle_extractor
shared: false shared: false
arguments: arguments:
- '%core.root_path%'
- '@request' - '@request'
- '@dbal.conn.driver' - '@dbal.conn.driver'
@ -58,7 +55,6 @@ services:
class: phpbb\db\extractor\postgres_extractor class: phpbb\db\extractor\postgres_extractor
shared: false shared: false
arguments: arguments:
- '%core.root_path%'
- '@request' - '@request'
- '@dbal.conn.driver' - '@dbal.conn.driver'
@ -66,6 +62,5 @@ services:
class: phpbb\db\extractor\sqlite3_extractor class: phpbb\db\extractor\sqlite3_extractor
shared: false shared: false
arguments: arguments:
- '%core.root_path%'
- '@request' - '@request'
- '@dbal.conn.driver' - '@dbal.conn.driver'

View file

@ -17,6 +17,14 @@ services:
tags: tags:
- { name: storage } - { name: storage }
storage.backup:
class: phpbb\storage\storage
arguments:
- '@storage.adapter.factory'
- 'backup'
tags:
- { name: storage }
# Factory # Factory
storage.adapter.factory: storage.adapter.factory:
class: phpbb\storage\adapter_factory class: phpbb\storage\adapter_factory

View file

@ -8,6 +8,7 @@ parameters:
tables.auth_provider_oauth_token_storage: '%core.table_prefix%oauth_tokens' 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_states: '%core.table_prefix%oauth_states'
tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts' tables.auth_provider_oauth_account_assoc: '%core.table_prefix%oauth_accounts'
tables.backups: '%core.table_prefix%backups'
tables.banlist: '%core.table_prefix%banlist' tables.banlist: '%core.table_prefix%banlist'
tables.bbcodes: '%core.table_prefix%bbcodes' tables.bbcodes: '%core.table_prefix%bbcodes'
tables.bookmarks: '%core.table_prefix%bookmarks' tables.bookmarks: '%core.table_prefix%bookmarks'

View file

@ -27,9 +27,10 @@ class acp_database
function main($id, $mode) function main($id, $mode)
{ {
global $cache, $db, $user, $template, $table_prefix, $request; 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->db_tools = $phpbb_container->get('dbal.tools');
$storage = $phpbb_container->get('storage.backup');
$user->add_lang('acp/database'); $user->add_lang('acp/database');
@ -98,6 +99,8 @@ class acp_database
$filename = 'backup_' . $time . '_' . unique_id(); $filename = 'backup_' . $time . '_' . unique_id();
try
{
$extractor = $phpbb_container->get('dbal.extractor'); $extractor = $phpbb_container->get('dbal.extractor');
$extractor->init_extractor($format, $filename, $time, $download, $store); $extractor->init_extractor($format, $filename, $time, $download, $store);
@ -142,6 +145,57 @@ class acp_database
} }
$extractor->write_end(); $extractor->write_end();
}
catch (\phpbb\exception\runtime_exception $e)
{
trigger_error($e->getMessage(), E_USER_ERROR);
}
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
$fp = fopen(sys_get_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(sys_get_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'); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP');
@ -208,9 +262,9 @@ class acp_database
trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); 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); trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
} }
@ -219,8 +273,24 @@ class acp_database
{ {
if (confirm_box(true)) if (confirm_box(true))
{ {
unlink($file_name); try
{
// Delete from storage
$storage->delete($file_name);
// Add log entry
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE'); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_DELETE');
// Remove from database
$sql = "DELETE FROM " . $table_prefix . "backups
WHERE filename = '" . $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)); trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action));
} }
else else
@ -253,25 +323,51 @@ class acp_database
@set_time_limit(0); @set_time_limit(0);
$fp = @fopen($file_name, 'rb'); try
if ($fp !== false)
{ {
$fp = $storage->read_stream($file_name);
while (!feof($fp)) while (!feof($fp))
{ {
echo fread($fp, 8192); echo fread($fp, 8192);
} }
fclose($fp); fclose($fp);
} }
catch (\phpbb\storage\exception\exception $e)
{
}
flush(); flush();
exit; exit;
} }
// Copy file to temp folder to decompress it
$temp_file_name = sys_get_temp_dir() . '/' . $file_name;
try
{
$stream = $storage->read_stream($file_name);
$fp = fopen($temp_file_name, 'w+b');
while (!feof($stream))
{
fwrite($fp, fread($stream, 8192));
}
fclose($fp);
fclose($stream);
}
catch (\phpbb\storage\exception\exception $e)
{
// Error while copying file from storage to temp
exit;
}
switch ($matches[1]) switch ($matches[1])
{ {
case 'sql': case 'sql':
$fp = fopen($file_name, 'rb'); $fp = fopen($temp_file_name, 'rb');
$read = 'fread'; $read = 'fread';
$seek = 'fseek'; $seek = 'fseek';
$eof = 'feof'; $eof = 'feof';
@ -280,7 +376,7 @@ class acp_database
break; break;
case 'sql.bz2': case 'sql.bz2':
$fp = bzopen($file_name, 'r'); $fp = bzopen($temp_file_name, 'r');
$read = 'bzread'; $read = 'bzread';
$seek = ''; $seek = '';
$eof = 'feof'; $eof = 'feof';
@ -289,7 +385,7 @@ class acp_database
break; break;
case 'sql.gz': case 'sql.gz':
$fp = gzopen($file_name, 'rb'); $fp = gzopen($temp_file_name, 'rb');
$read = 'gzread'; $read = 'gzread';
$seek = 'gzseek'; $seek = 'gzseek';
$eof = 'gzeof'; $eof = 'gzeof';
@ -368,6 +464,8 @@ class acp_database
$close($fp); $close($fp);
@unlink($temp_file_name);
// Purge the cache due to updated data // Purge the cache due to updated data
$cache->purge(); $cache->purge();
@ -393,25 +491,24 @@ class acp_database
$methods[] = $type; $methods[] = $type;
} }
$dir = $phpbb_root_path . 'store/'; $sql = 'SELECT filename
$dh = @opendir($dir); FROM ' . BACKUPS_TABLE;
$result = $db->sql_query($sql);
$backup_files = array(); $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)) if (!empty($backup_files))
{ {

View file

@ -239,6 +239,7 @@ define('ACL_ROLES_DATA_TABLE', $table_prefix . 'acl_roles_data');
define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles'); define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles');
define('ACL_USERS_TABLE', $table_prefix . 'acl_users'); define('ACL_USERS_TABLE', $table_prefix . 'acl_users');
define('ATTACHMENTS_TABLE', $table_prefix . 'attachments'); define('ATTACHMENTS_TABLE', $table_prefix . 'attachments');
define('BACKUPS_TABLE', $table_prefix . 'backups');
define('BANLIST_TABLE', $table_prefix . 'banlist'); define('BANLIST_TABLE', $table_prefix . 'banlist');
define('BBCODES_TABLE', $table_prefix . 'bbcodes'); define('BBCODES_TABLE', $table_prefix . 'bbcodes');
define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks'); define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks');

View file

@ -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\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\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\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 ('cache_last_gc', '0', 1);
INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1); INSERT INTO phpbb_config (config_name, config_value, is_dynamic) VALUES ('cron_lock', '0', 1);

View file

@ -43,6 +43,7 @@ $lang = array_merge($lang, array(
'BACKUP_DELETE' => 'The backup file has been deleted successfully.', 'BACKUP_DELETE' => 'The backup file has been deleted successfully.',
'BACKUP_INVALID' => 'The selected file to backup is invalid.', 'BACKUP_INVALID' => 'The selected file to backup is invalid.',
'BACKUP_ERROR' => 'Error when saving file.',
'BACKUP_OPTIONS' => 'Backup options', 'BACKUP_OPTIONS' => 'Backup options',
'BACKUP_SUCCESS' => 'The backup file has been created successfully.', 'BACKUP_SUCCESS' => 'The backup file has been created successfully.',
'BACKUP_TYPE' => 'Backup type', 'BACKUP_TYPE' => 'Backup type',

View file

@ -21,10 +21,6 @@ use phpbb\db\extractor\exception\extractor_not_initialized_exception;
*/ */
abstract class base_extractor implements extractor_interface abstract class base_extractor implements extractor_interface
{ {
/**
* @var string phpBB root path
*/
protected $phpbb_root_path;
/** /**
* @var \phpbb\request\request_interface * @var \phpbb\request\request_interface
@ -84,13 +80,11 @@ abstract class base_extractor implements extractor_interface
/** /**
* Constructor * Constructor
* *
* @param string $phpbb_root_path
* @param \phpbb\request\request_interface $request * @param \phpbb\request\request_interface $request
* @param \phpbb\db\driver\driver_interface $db * @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\request\request_interface $request, \phpbb\db\driver\driver_interface $db)
{ {
$this->phpbb_root_path = $phpbb_root_path;
$this->request = $request; $this->request = $request;
$this->db = $db; $this->db = $db;
$this->fp = null; $this->fp = null;
@ -164,13 +158,13 @@ abstract class base_extractor implements extractor_interface
if ($store === true) if ($store === true)
{ {
$file = $this->phpbb_root_path . 'store/' . $filename . $ext; $file = sys_get_temp_dir() . '/' . $filename . $ext;
$this->fp = $open($file, 'w'); $this->fp = $open($file, 'w');
if (!$this->fp) if (!$this->fp)
{ {
trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); throw new \phpbb\exception\runtime_exception('FILE_WRITE_FAIL');
} }
} }

View file

@ -0,0 +1,40 @@
<?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\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')),
);
}
}