function main($id, $mode) { global $cache, $db, $user, $auth, $template, $table_prefix; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $this->db_tools = new \phpbb\db\tools($db); $user->add_lang('acp/database'); $this->tpl_name = 'acp_database'; $this->page_title = 'ACP_DATABASE'; $action = request_var('action', ''); $submit = isset($_POST['submit']) ? true : false; $template->assign_vars(array('MODE' => $mode)); switch ($mode) { case 'backup': $this->page_title = 'ACP_BACKUP'; switch ($action) { case 'download': $type = request_var('type', ''); $table = array_intersect($this->db_tools->sql_list_tables(), request_var('table', array(''))); $format = request_var('method', ''); $where = request_var('where', ''); if (!sizeof($table)) { trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); } $store = $download = $structure = $schema_data = false; if ($where == 'store_and_download' || $where == 'store') { $store = true; } if ($where == 'store_and_download' || $where == 'download') { $download = true; } if ($type == 'full' || $type == 'structure') { $structure = true; } if ($type == 'full' || $type == 'data') { $schema_data = true; } @set_time_limit(1200); @set_time_limit(0); $time = time(); $filename = 'backup_' . $time . '_' . unique_id(); switch ($db->get_sql_layer()) { case 'mysqli': case 'mysql4': case 'mysql': $extractor = new mysql_extractor($format, $filename, $time, $download, $store); break; case 'sqlite': $extractor = new sqlite_extractor($format, $filename, $time, $download, $store); break; case 'sqlite3': $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store); break; case 'postgres': $extractor = new postgres_extractor($format, $filename, $time, $download, $store); break; case 'oracle': $extractor = new oracle_extractor($format, $filename, $time, $download, $store); break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': $extractor = new mssql_extractor($format, $filename, $time, $download, $store); break; } $extractor->write_start($table_prefix); foreach ($table as $table_name) { // Get the table structure if ($structure) { $extractor->write_table($table_name); } else { // We might wanna empty out all that junk :D switch ($db->get_sql_layer()) { case 'sqlite': case 'sqlite3': $extractor->flush('DELETE FROM ' . $table_name . ";\n"); break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); break; case 'oracle': $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); break; default: $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); break; } } // Data if ($schema_data) { $extractor->write_data($table_name); } } $extractor->write_end(); add_log('admin', 'LOG_DB_BACKUP'); if ($download == true) { exit; } trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); break; default: $tables = $this->db_tools->sql_list_tables(); asort($tables); foreach ($tables as $table_name) { if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0) { $template->assign_block_vars('tables', array('TABLE' => $table_name)); } } unset($tables); $template->assign_vars(array('U_ACTION' => $this->u_action . '&action=download')); $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); foreach ($available_methods as $type => $module) { if (!@extension_loaded($module)) { continue; } $template->assign_block_vars('methods', array('TYPE' => $type)); } $template->assign_block_vars('methods', array('TYPE' => 'text')); break; } break; case 'restore': $this->page_title = 'ACP_RESTORE'; switch ($action) { case 'submit': $delete = request_var('delete', ''); $file = request_var('file', ''); $download = request_var('download', ''); if (!preg_match('#^backup_\\d{10,}_[a-z\\d]{16}\\.(sql(?:\\.(?:gz|bz2))?)$#', $file, $matches)) { trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } $file_name = $phpbb_root_path . 'store/' . $matches[0]; if (!file_exists($file_name) || !is_readable($file_name)) { trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); } if ($delete) { if (confirm_box(true)) { unlink($file_name); add_log('admin', 'LOG_DB_DELETE'); trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); } else { confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); } } else { if ($download || confirm_box(true)) { if ($download) { $name = $matches[0]; switch ($matches[1]) { case 'sql': $mimetype = 'text/x-sql'; break; case 'sql.bz2': $mimetype = 'application/x-bzip2'; break; case 'sql.gz': $mimetype = 'application/x-gzip'; break; } header('Cache-Control: private, no-cache'); header("Content-Type: {$mimetype}; name=\"{$name}\""); header("Content-disposition: attachment; filename={$name}"); @set_time_limit(0); $fp = @fopen($file_name, 'rb'); if ($fp !== false) { while (!feof($fp)) { echo fread($fp, 8192); } fclose($fp); } flush(); exit; } switch ($matches[1]) { case 'sql': $fp = fopen($file_name, 'rb'); $read = 'fread'; $seek = 'fseek'; $eof = 'feof'; $close = 'fclose'; $fgetd = 'fgetd'; break; case 'sql.bz2': $fp = bzopen($file_name, 'r'); $read = 'bzread'; $seek = ''; $eof = 'feof'; $close = 'bzclose'; $fgetd = 'fgetd_seekless'; break; case 'sql.gz': $fp = gzopen($file_name, 'rb'); $read = 'gzread'; $seek = 'gzseek'; $eof = 'gzeof'; $close = 'gzclose'; $fgetd = 'fgetd'; break; } switch ($db->get_sql_layer()) { case 'mysql': case 'mysql4': case 'mysqli': case 'sqlite': case 'sqlite3': while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false) { $db->sql_query($sql); } break; case 'postgres': $delim = ";\n"; while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) { $query = trim($sql); if (substr($query, 0, 13) == 'CREATE DOMAIN') { list(, , $domain) = explode(' ', $query); $sql = "SELECT domain_name\n\t\t\t\t\t\t\t\t\t\t\t\tFROM information_schema.domains\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE domain_name = '{$domain}';"; $result = $db->sql_query($sql); if (!$db->sql_fetchrow($result)) { $db->sql_query($query); } $db->sql_freeresult($result); } else { $db->sql_query($query); } if (substr($query, 0, 4) == 'COPY') { while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\\.') { if ($sub === false) { trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); } pg_put_line($db->get_db_connect_id(), $sub . "\n"); } pg_put_line($db->get_db_connect_id(), "\\.\n"); pg_end_copy($db->get_db_connect_id()); } } break; case 'oracle': while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false) { $db->sql_query($sql); } break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false) { $db->sql_query($sql); } break; } $close($fp); // Purge the cache due to updated data $cache->purge(); add_log('admin', 'LOG_DB_RESTORE'); trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); break; } else { if (!$download) { confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file))); } } } default: $methods = array('sql'); $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2'); foreach ($available_methods as $type => $module) { if (!@extension_loaded($module)) { continue; } $methods[] = $type; } $dir = $phpbb_root_path . 'store/'; $dh = @opendir($dir); $backup_files = array(); if ($dh) { while (($file = readdir($dh)) !== false) { if (preg_match('#^backup_(\\d{10,})_[a-z\\d]{16}\\.(sql(?:\\.(?:gz|bz2))?)$#', $file, $matches)) { if (in_array($matches[2], $methods)) { $backup_files[(int) $matches[1]] = $file; } } } closedir($dh); } if (!empty($backup_files)) { krsort($backup_files); foreach ($backup_files as $name => $file) { $template->assign_block_vars('files', array('FILE' => $file, 'NAME' => $user->format_date($name, 'd-m-Y H:i:s', true), 'SUPPORTED' => true)); } } $template->assign_vars(array('U_ACTION' => $this->u_action . '&action=submit')); break; } break; } }
function display_options() { global $db, $template, $config, $user; $submit = request_var('sa', false); $tables = request_var('table_select', array('')); $gzip = request_var('gzip', true); $where = request_var('action', 'store'); $type = request_var('type', 'full'); $format = request_var('method', '', true); $sql_layer = $db->get_sql_layer(); if ($format === $user->lang['NO']) { $format = 'text'; } $store = $download = $structure = $schema_data = $screen = false; if ($where == 'store') { $store = true; } if ($where == 'download') { $download = true; } if ($where == 'screen') { $format = 'screen'; } if ($type == 'full' || $type == 'structure') { $structure = true; } if ($type == 'full' || $type == 'data') { $schema_data = true; } $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); foreach ($available_methods as $zip_type => $module) { if (!@extension_loaded($module)) { continue; } $template->assign_block_vars('methods', array('TYPE' => $zip_type)); } $template->assign_block_vars('methods', array('TYPE' => $user->lang['NO'])); switch ($sql_layer) { case 'mysql': case 'mysql4': case 'mysqli': $sql = 'SHOW TABLES'; break; case 'sqlite': $sql = 'SELECT name FROM sqlite_master WHERE type = "table"'; break; case 'sqlite3': $sql = 'SELECT name FROM sqlite_master WHERE type = "table" AND name <> "sqlite_sequence"'; break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': $sql = "SELECT name\n\t\t\t\t\tFROM sysobjects\n\t\t\t\t\tWHERE type='U'"; break; case 'postgres': $sql = 'SELECT relname FROM pg_stat_user_tables'; break; case 'oracle': $sql = 'SELECT table_name FROM USER_TABLES'; break; } $result = $db->sql_query($sql); $option_list = ''; while ($row = $db->sql_fetchrow($result)) { $name = current($row); $option_list .= "<option value='{$name}'>{$name}</option>"; } $db->sql_freeresult($result); if ($submit && !empty($tables)) { $filename = 'back_' . $user->format_date(time(), 'Y_m_d_H_i_s'); if ($format == 'screen') { $template->assign_vars(array('DUMP' => true)); $this->back($tables, $type); } else { $time = time(); if ($sql_layer == 'mysqli' || $sql_layer == 'mysql4' || $sql_layer == 'mysql') { $extractor = new mysql_dumper_extractor($format, $filename, $time, $download, $store); } else { include PHPBB_ROOT_PATH . 'includes/acp/acp_database.' . PHP_EXT; switch ($db->get_sql_layer()) { case 'sqlite': $extractor = new sqlite_extractor($format, $filename, $time, $download, $store); break; case 'sqlite3': $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store); break; case 'postgres': $extractor = new postgres_extractor($format, $filename, $time, $download, $store); break; case 'oracle': $extractor = new oracle_extractor($format, $filename, $time, $download, $store); break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': $extractor = new mssql_extractor($format, $filename, $time, $download, $store); break; } } $extractor->write_start($tables); foreach ($tables as $table_name) { // Get the table structure if ($structure) { $extractor->write_table($table_name); } else { // We might wanna empty out all that junk :D switch ($db->get_sql_layer()) { case 'sqlite': case 'sqlite3': $extractor->flush('DELETE FROM ' . $table_name . ";\n"); break; case 'mssql': case 'mssql_odbc': case 'mssqlnative': $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); break; case 'oracle': $extractor->flush('TRUNCATE TABLE ' . $table_name . "/\n"); break; default: $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n/*!40000 ALTER TABLE `" . $table_name . "` DISABLE KEYS */;\n"); break; } } // Data if ($schema_data) { $extractor->write_data($table_name); } } $extractor->write_end(); if ($download == true) { exit; } meta_refresh(3, append_sid(STK_ROOT_PATH . 'index.' . PHP_EXT, 'c=admin&t=db_backup')); trigger_error($user->lang['BACKUP_SUCCESS']); } } page_header($user->lang['DB_BACKUP']); $template->assign_vars(array('S_SELECT' => $option_list, 'SCREEN_ENABLE' => $sql_layer == 'mysqli' || $sql_layer == 'mysql4' || $sql_layer == 'mysql' ? true : false, 'U_DISPLAY_ACTION' => append_sid(STK_INDEX, 'c=admin&t=db_backup&go=1'))); $template->set_filenames(array('body' => 'tools/db_backup.html')); page_footer(); }
/** * Runs this cron task. * * @return null */ public function run() { include $this->phpbb_root_path . 'includes/acp/acp_database.' . $this->php_ext; $backup_date = getdate($this->config['auto_db_backup_last_gc']); $last_backup_date = mktime($backup_date['hours'], $backup_date['minutes'], 0, date("m"), date("j"), date("Y")); $this->config->set('auto_db_backup_last_gc', $last_backup_date, false); // Optimize database tables before backup them (only unoptimized tables) if ($this->config['auto_db_backup_optimize']) { if ($result = $this->db->sql_query('SHOW TABLE STATUS')) { $tables = $this->db->sql_fetchrowset($result); $size = sizeof($tables); for ($i = 0; $i < $size; $i++) { if ($tables[$i]['Data_free'] != 0) { $for_optimize[] = $tables[$i]['Name']; } } if (!empty($for_optimize)) { $tables = implode(',', $for_optimize); $this->db->sql_query('OPTIMIZE TABLE ' . $tables); } } } @set_time_limit(1200); @set_time_limit(0); $time = time(); $format = $this->config['auto_db_backup_filetype']; $filename = 'backup_' . $time . '_' . unique_id(); switch ($this->db->get_sql_layer()) { case 'mysqli': case 'mysql4': case 'mysql': $extractor = new \mysql_extractor($format, $filename, $time, false, true); break; case 'sqlite': $extractor = new \sqlite_extractor($format, $filename, $time, false, true); break; case 'sqlite3': $extractor = new \sqlite3_extractor($format, $filename, $time, false, true); break; case 'postgres': $extractor = new \postgres_extractor($format, $filename, $time, false, true); break; case 'oracle': $extractor = new \oracle_extractor($format, $filename, $time, false, true); break; case 'mssql': case 'mssql_odbc': $extractor = new \mssql_extractor($format, $filename, $time, false, true); break; } global $table_prefix; $tables = $this->db_tools->sql_list_tables(); $extractor->write_start($table_prefix); foreach ($tables as $table_name) { $extractor->write_table($table_name); $extractor->write_data($table_name); } $extractor->write_end(); $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_AUTO_DB_BACKUP'); // Delete backup if ($this->config['auto_db_backup_copies']) { $rep = $this->phpbb_root_path . '/store/'; $dir = opendir($rep); $files = array(); while (($file = readdir($dir)) !== false) { if (is_file($rep . $file) && (substr($file, -3) == '.gz' || substr($file, -4) == '.bz2' || substr($file, -4) == '.sql')) { $files[$file] = fileatime($rep . $file); } } closedir($dir); arsort($files); reset($files); if (sizeof($files) > $this->config['auto_db_backup_copies']) { $i = 0; while (list($key, $val) = each($files)) { $i++; if ($i > $this->config['auto_db_backup_copies']) { @unlink($rep . $key); } } } } }