mirror of
https://github.com/phpbb/phpbb.git
synced 2025-06-11 22:08:54 +00:00
This will further harden the ACP security by adding link hashes to links and form tokens to forms that did not have these yet and result in modified settings or write action on the filesystem or database. These few links and forms were still relying on the global ACP protection, mainly due to them not posing further risks of compromising data. After this change these will now also be properly protected against tampering. PHPBB3-14789
2277 lines
54 KiB
PHP
2277 lines
54 KiB
PHP
<?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.
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
if (!defined('IN_PHPBB'))
|
|
{
|
|
exit;
|
|
}
|
|
|
|
class acp_database
|
|
{
|
|
var $db_tools;
|
|
var $u_action;
|
|
|
|
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;
|
|
|
|
$form_key = 'acp_database';
|
|
add_form_key($form_key);
|
|
|
|
if ($submit && !check_form_key($form_key))
|
|
{
|
|
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
|
}
|
|
|
|
$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
|
|
FROM information_schema.domains
|
|
WHERE 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
class base_extractor
|
|
{
|
|
var $fh;
|
|
var $fp;
|
|
var $write;
|
|
var $close;
|
|
var $store;
|
|
var $download;
|
|
var $time;
|
|
var $format;
|
|
var $run_comp = false;
|
|
|
|
function base_extractor($format, $filename, $time, $download = false, $store = false)
|
|
{
|
|
global $request;
|
|
|
|
$this->download = $download;
|
|
$this->store = $store;
|
|
$this->time = $time;
|
|
$this->format = $format;
|
|
|
|
switch ($format)
|
|
{
|
|
case 'text':
|
|
$ext = '.sql';
|
|
$open = 'fopen';
|
|
$this->write = 'fwrite';
|
|
$this->close = 'fclose';
|
|
$mimetype = 'text/x-sql';
|
|
break;
|
|
case 'bzip2':
|
|
$ext = '.sql.bz2';
|
|
$open = 'bzopen';
|
|
$this->write = 'bzwrite';
|
|
$this->close = 'bzclose';
|
|
$mimetype = 'application/x-bzip2';
|
|
break;
|
|
case 'gzip':
|
|
$ext = '.sql.gz';
|
|
$open = 'gzopen';
|
|
$this->write = 'gzwrite';
|
|
$this->close = 'gzclose';
|
|
$mimetype = 'application/x-gzip';
|
|
break;
|
|
}
|
|
|
|
if ($download == true)
|
|
{
|
|
$name = $filename . $ext;
|
|
header('Cache-Control: private, no-cache');
|
|
header("Content-Type: $mimetype; name=\"$name\"");
|
|
header("Content-disposition: attachment; filename=$name");
|
|
|
|
switch ($format)
|
|
{
|
|
case 'bzip2':
|
|
ob_start();
|
|
break;
|
|
|
|
case 'gzip':
|
|
if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false)
|
|
{
|
|
ob_start('ob_gzhandler');
|
|
}
|
|
else
|
|
{
|
|
$this->run_comp = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($store == true)
|
|
{
|
|
global $phpbb_root_path;
|
|
$file = $phpbb_root_path . 'store/' . $filename . $ext;
|
|
|
|
$this->fp = $open($file, 'w');
|
|
|
|
if (!$this->fp)
|
|
{
|
|
trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
function write_end()
|
|
{
|
|
static $close;
|
|
|
|
if ($this->store)
|
|
{
|
|
if ($close === null)
|
|
{
|
|
$close = $this->close;
|
|
}
|
|
$close($this->fp);
|
|
}
|
|
|
|
// bzip2 must be written all the way at the end
|
|
if ($this->download && $this->format === 'bzip2')
|
|
{
|
|
$c = ob_get_clean();
|
|
echo bzcompress($c);
|
|
}
|
|
}
|
|
|
|
function flush($data)
|
|
{
|
|
static $write;
|
|
if ($this->store === true)
|
|
{
|
|
if ($write === null)
|
|
{
|
|
$write = $this->write;
|
|
}
|
|
$write($this->fp, $data);
|
|
}
|
|
|
|
if ($this->download === true)
|
|
{
|
|
if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp))
|
|
{
|
|
echo $data;
|
|
}
|
|
|
|
// we can write the gzip data as soon as we get it
|
|
if ($this->format === 'gzip')
|
|
{
|
|
if ($this->run_comp)
|
|
{
|
|
echo gzencode($data);
|
|
}
|
|
else
|
|
{
|
|
ob_flush();
|
|
flush();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class mysql_extractor extends base_extractor
|
|
{
|
|
function write_start($table_prefix)
|
|
{
|
|
$sql_data = "#\n";
|
|
$sql_data .= "# phpBB Backup Script\n";
|
|
$sql_data .= "# Dump of tables for $table_prefix\n";
|
|
$sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "#\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
static $new_extract;
|
|
|
|
if ($new_extract === null)
|
|
{
|
|
if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>='))
|
|
{
|
|
$new_extract = true;
|
|
}
|
|
else
|
|
{
|
|
$new_extract = false;
|
|
}
|
|
}
|
|
|
|
if ($new_extract)
|
|
{
|
|
$this->new_write_table($table_name);
|
|
}
|
|
else
|
|
{
|
|
$this->old_write_table($table_name);
|
|
}
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
if ($db->get_sql_layer() === 'mysqli')
|
|
{
|
|
$this->write_data_mysqli($table_name);
|
|
}
|
|
else
|
|
{
|
|
$this->write_data_mysql($table_name);
|
|
}
|
|
}
|
|
|
|
function write_data_mysqli($table_name)
|
|
{
|
|
global $db;
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT);
|
|
if ($result != false)
|
|
{
|
|
$fields_cnt = mysqli_num_fields($result);
|
|
|
|
// Get field information
|
|
$field = mysqli_fetch_fields($result);
|
|
$field_set = array();
|
|
|
|
for ($j = 0; $j < $fields_cnt; $j++)
|
|
{
|
|
$field_set[] = $field[$j]->name;
|
|
}
|
|
|
|
$search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
|
|
$replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
|
|
$fields = implode(', ', $field_set);
|
|
$sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
|
|
$first_set = true;
|
|
$query_len = 0;
|
|
$max_len = get_usable_memory();
|
|
|
|
while ($row = mysqli_fetch_row($result))
|
|
{
|
|
$values = array();
|
|
if ($first_set)
|
|
{
|
|
$query = $sql_data . '(';
|
|
}
|
|
else
|
|
{
|
|
$query .= ',(';
|
|
}
|
|
|
|
for ($j = 0; $j < $fields_cnt; $j++)
|
|
{
|
|
if (!isset($row[$j]) || is_null($row[$j]))
|
|
{
|
|
$values[$j] = 'NULL';
|
|
}
|
|
else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024))
|
|
{
|
|
$values[$j] = $row[$j];
|
|
}
|
|
else
|
|
{
|
|
$values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
|
|
}
|
|
}
|
|
$query .= implode(', ', $values) . ')';
|
|
|
|
$query_len += strlen($query);
|
|
if ($query_len > $max_len)
|
|
{
|
|
$this->flush($query . ";\n\n");
|
|
$query = '';
|
|
$query_len = 0;
|
|
$first_set = true;
|
|
}
|
|
else
|
|
{
|
|
$first_set = false;
|
|
}
|
|
}
|
|
mysqli_free_result($result);
|
|
|
|
// check to make sure we have nothing left to flush
|
|
if (!$first_set && $query)
|
|
{
|
|
$this->flush($query . ";\n\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
function write_data_mysql($table_name)
|
|
{
|
|
global $db;
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = mysql_unbuffered_query($sql, $db->get_db_connect_id());
|
|
|
|
if ($result != false)
|
|
{
|
|
$fields_cnt = mysql_num_fields($result);
|
|
|
|
// Get field information
|
|
$field = array();
|
|
for ($i = 0; $i < $fields_cnt; $i++)
|
|
{
|
|
$field[] = mysql_fetch_field($result, $i);
|
|
}
|
|
$field_set = array();
|
|
|
|
for ($j = 0; $j < $fields_cnt; $j++)
|
|
{
|
|
$field_set[] = $field[$j]->name;
|
|
}
|
|
|
|
$search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"');
|
|
$replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"');
|
|
$fields = implode(', ', $field_set);
|
|
$sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES ';
|
|
$first_set = true;
|
|
$query_len = 0;
|
|
$max_len = get_usable_memory();
|
|
|
|
while ($row = mysql_fetch_row($result))
|
|
{
|
|
$values = array();
|
|
if ($first_set)
|
|
{
|
|
$query = $sql_data . '(';
|
|
}
|
|
else
|
|
{
|
|
$query .= ',(';
|
|
}
|
|
|
|
for ($j = 0; $j < $fields_cnt; $j++)
|
|
{
|
|
if (!isset($row[$j]) || is_null($row[$j]))
|
|
{
|
|
$values[$j] = 'NULL';
|
|
}
|
|
else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp'))
|
|
{
|
|
$values[$j] = $row[$j];
|
|
}
|
|
else
|
|
{
|
|
$values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'";
|
|
}
|
|
}
|
|
$query .= implode(', ', $values) . ')';
|
|
|
|
$query_len += strlen($query);
|
|
if ($query_len > $max_len)
|
|
{
|
|
$this->flush($query . ";\n\n");
|
|
$query = '';
|
|
$query_len = 0;
|
|
$first_set = true;
|
|
}
|
|
else
|
|
{
|
|
$first_set = false;
|
|
}
|
|
}
|
|
mysql_free_result($result);
|
|
|
|
// check to make sure we have nothing left to flush
|
|
if (!$first_set && $query)
|
|
{
|
|
$this->flush($query . ";\n\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
function new_write_table($table_name)
|
|
{
|
|
global $db;
|
|
|
|
$sql = 'SHOW CREATE TABLE ' . $table_name;
|
|
$result = $db->sql_query($sql);
|
|
$row = $db->sql_fetchrow($result);
|
|
|
|
$sql_data = '# Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
|
|
$this->flush($sql_data . $row['Create Table'] . ";\n\n");
|
|
|
|
$db->sql_freeresult($result);
|
|
}
|
|
|
|
function old_write_table($table_name)
|
|
{
|
|
global $db;
|
|
|
|
$sql_data = '# Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE IF EXISTS $table_name;\n";
|
|
$sql_data .= "CREATE TABLE $table_name(\n";
|
|
$rows = array();
|
|
|
|
$sql = "SHOW FIELDS
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$line = ' ' . $row['Field'] . ' ' . $row['Type'];
|
|
|
|
if (!is_null($row['Default']))
|
|
{
|
|
$line .= " DEFAULT '{$row['Default']}'";
|
|
}
|
|
|
|
if ($row['Null'] != 'YES')
|
|
{
|
|
$line .= ' NOT NULL';
|
|
}
|
|
|
|
if ($row['Extra'] != '')
|
|
{
|
|
$line .= ' ' . $row['Extra'];
|
|
}
|
|
|
|
$rows[] = $line;
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql = "SHOW KEYS
|
|
FROM $table_name";
|
|
|
|
$result = $db->sql_query($sql);
|
|
|
|
$index = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$kname = $row['Key_name'];
|
|
|
|
if ($kname != 'PRIMARY')
|
|
{
|
|
if ($row['Non_unique'] == 0)
|
|
{
|
|
$kname = "UNIQUE|$kname";
|
|
}
|
|
}
|
|
|
|
if ($row['Sub_part'])
|
|
{
|
|
$row['Column_name'] .= '(' . $row['Sub_part'] . ')';
|
|
}
|
|
$index[$kname][] = $row['Column_name'];
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
foreach ($index as $key => $columns)
|
|
{
|
|
$line = ' ';
|
|
|
|
if ($key == 'PRIMARY')
|
|
{
|
|
$line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')';
|
|
}
|
|
else if (strpos($key, 'UNIQUE') === 0)
|
|
{
|
|
$line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')';
|
|
}
|
|
else if (strpos($key, 'FULLTEXT') === 0)
|
|
{
|
|
$line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')';
|
|
}
|
|
else
|
|
{
|
|
$line .= "KEY $key (" . implode(', ', $columns) . ')';
|
|
}
|
|
|
|
$rows[] = $line;
|
|
}
|
|
|
|
$sql_data .= implode(",\n", $rows);
|
|
$sql_data .= "\n);\n\n";
|
|
|
|
$this->flush($sql_data);
|
|
}
|
|
}
|
|
|
|
class sqlite_extractor extends base_extractor
|
|
{
|
|
function write_start($prefix)
|
|
{
|
|
$sql_data = "--\n";
|
|
$sql_data .= "-- phpBB Backup Script\n";
|
|
$sql_data .= "-- Dump of tables for $prefix\n";
|
|
$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "--\n";
|
|
$sql_data .= "BEGIN TRANSACTION;\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
$sql_data = '-- Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE $table_name;\n";
|
|
|
|
$sql = "SELECT sql
|
|
FROM sqlite_master
|
|
WHERE type = 'table'
|
|
AND name = '" . $db->sql_escape($table_name) . "'
|
|
ORDER BY type DESC, name;";
|
|
$result = $db->sql_query($sql);
|
|
$row = $db->sql_fetchrow($result);
|
|
$db->sql_freeresult($result);
|
|
|
|
// Create Table
|
|
$sql_data .= $row['sql'] . ";\n";
|
|
|
|
$result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
|
|
|
|
$ar = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$ar[] = $row;
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
foreach ($ar as $value)
|
|
{
|
|
if (strpos($value['name'], 'autoindex') !== false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');");
|
|
|
|
$fields = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$fields[] = $row['name'];
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
|
|
}
|
|
|
|
$this->flush($sql_data . "\n");
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
|
|
$col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name);
|
|
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql);
|
|
$rows = sqlite_fetch_all($result, SQLITE_ASSOC);
|
|
$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
|
|
foreach ($rows as $row)
|
|
{
|
|
foreach ($row as $column_name => $column_data)
|
|
{
|
|
if (is_null($column_data))
|
|
{
|
|
$row[$column_name] = 'NULL';
|
|
}
|
|
else if ($column_data == '')
|
|
{
|
|
$row[$column_name] = "''";
|
|
}
|
|
else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false)
|
|
{
|
|
$row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
|
|
}
|
|
}
|
|
$this->flush($sql_insert . implode(', ', $row) . ");\n");
|
|
}
|
|
}
|
|
|
|
function write_end()
|
|
{
|
|
$this->flush("COMMIT;\n");
|
|
parent::write_end();
|
|
}
|
|
}
|
|
|
|
class sqlite3_extractor extends base_extractor
|
|
{
|
|
function write_start($prefix)
|
|
{
|
|
$sql_data = "--\n";
|
|
$sql_data .= "-- phpBB Backup Script\n";
|
|
$sql_data .= "-- Dump of tables for $prefix\n";
|
|
$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "--\n";
|
|
$sql_data .= "BEGIN TRANSACTION;\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
$sql_data = '-- Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE $table_name;\n";
|
|
|
|
$sql = "SELECT sql
|
|
FROM sqlite_master
|
|
WHERE type = 'table'
|
|
AND name = '" . $db->sql_escape($table_name) . "'
|
|
ORDER BY name ASC;";
|
|
$result = $db->sql_query($sql);
|
|
$row = $db->sql_fetchrow($result);
|
|
$db->sql_freeresult($result);
|
|
|
|
// Create Table
|
|
$sql_data .= $row['sql'] . ";\n";
|
|
|
|
$result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');");
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if (strpos($row['name'], 'autoindex') !== false)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');");
|
|
|
|
$fields = array();
|
|
while ($row2 = $db->sql_fetchrow($result2))
|
|
{
|
|
$fields[] = $row2['name'];
|
|
}
|
|
$db->sql_freeresult($result2);
|
|
|
|
$sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$this->flush($sql_data . "\n");
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
|
|
$result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');");
|
|
|
|
$col_types = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$col_types[$row['name']] = $row['type'];
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
|
|
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
foreach ($row as $column_name => $column_data)
|
|
{
|
|
if (is_null($column_data))
|
|
{
|
|
$row[$column_name] = 'NULL';
|
|
}
|
|
else if ($column_data === '')
|
|
{
|
|
$row[$column_name] = "''";
|
|
}
|
|
else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false)
|
|
{
|
|
$row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data));
|
|
}
|
|
}
|
|
$this->flush($sql_insert . implode(', ', $row) . ");\n");
|
|
}
|
|
}
|
|
|
|
function write_end()
|
|
{
|
|
$this->flush("COMMIT;\n");
|
|
parent::write_end();
|
|
}
|
|
}
|
|
|
|
class postgres_extractor extends base_extractor
|
|
{
|
|
function write_start($prefix)
|
|
{
|
|
$sql_data = "--\n";
|
|
$sql_data .= "-- phpBB Backup Script\n";
|
|
$sql_data .= "-- Dump of tables for $prefix\n";
|
|
$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "--\n";
|
|
$sql_data .= "BEGIN TRANSACTION;\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
static $domains_created = array();
|
|
|
|
$sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default
|
|
FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b
|
|
WHERE a.domain_name = b.domain_name
|
|
AND b.table_name = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if (empty($domains_created[$row['domain_name']]))
|
|
{
|
|
$domains_created[$row['domain_name']] = true;
|
|
//$sql_data = "DROP DOMAIN {$row['domain_name']};\n";
|
|
$sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}";
|
|
if (!empty($row['character_maximum_length']))
|
|
{
|
|
$sql_data .= '(' . $row['character_maximum_length'] . ')';
|
|
}
|
|
$sql_data .= ' NOT NULL';
|
|
if (!empty($row['domain_default']))
|
|
{
|
|
$sql_data .= ' DEFAULT ' . $row['domain_default'];
|
|
}
|
|
$this->flush($sql_data . ";\n");
|
|
}
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql_data = '-- Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE $table_name;\n";
|
|
// PGSQL does not "tightly" bind sequences and tables, we must guess...
|
|
$sql = "SELECT relname
|
|
FROM pg_class
|
|
WHERE relkind = 'S'
|
|
AND relname = '{$table_name}_seq'";
|
|
$result = $db->sql_query($sql);
|
|
// We don't even care about storing the results. We already know the answer if we get rows back.
|
|
if ($db->sql_fetchrow($result))
|
|
{
|
|
$sql_data .= "DROP SEQUENCE {$table_name}_seq;\n";
|
|
$sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull
|
|
FROM pg_class c, pg_attribute a, pg_type t
|
|
WHERE c.relname = '" . $db->sql_escape($table_name) . "'
|
|
AND a.attnum > 0
|
|
AND a.attrelid = c.oid
|
|
AND a.atttypid = t.oid
|
|
ORDER BY a.attnum";
|
|
$result = $db->sql_query($field_query);
|
|
|
|
$sql_data .= "CREATE TABLE $table_name(\n";
|
|
$lines = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
// Get the data from the table
|
|
$sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
|
|
FROM pg_attrdef d, pg_class c
|
|
WHERE (c.relname = '" . $db->sql_escape($table_name) . "')
|
|
AND (c.oid = d.adrelid)
|
|
AND d.adnum = " . $row['attnum'];
|
|
$def_res = $db->sql_query($sql_get_default);
|
|
$def_row = $db->sql_fetchrow($def_res);
|
|
$db->sql_freeresult($def_res);
|
|
|
|
if (empty($def_row))
|
|
{
|
|
unset($row['rowdefault']);
|
|
}
|
|
else
|
|
{
|
|
$row['rowdefault'] = $def_row['rowdefault'];
|
|
}
|
|
|
|
if ($row['type'] == 'bpchar')
|
|
{
|
|
// Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement.
|
|
$row['type'] = 'char';
|
|
}
|
|
|
|
$line = ' ' . $row['field'] . ' ' . $row['type'];
|
|
|
|
if (strpos($row['type'], 'char') !== false)
|
|
{
|
|
if ($row['lengthvar'] > 0)
|
|
{
|
|
$line .= '(' . ($row['lengthvar'] - 4) . ')';
|
|
}
|
|
}
|
|
|
|
if (strpos($row['type'], 'numeric') !== false)
|
|
{
|
|
$line .= '(';
|
|
$line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff));
|
|
$line .= ')';
|
|
}
|
|
|
|
if (isset($row['rowdefault']))
|
|
{
|
|
$line .= ' DEFAULT ' . $row['rowdefault'];
|
|
}
|
|
|
|
if ($row['notnull'] == 't')
|
|
{
|
|
$line .= ' NOT NULL';
|
|
}
|
|
|
|
$lines[] = $line;
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
// Get the listing of primary keys.
|
|
$sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key
|
|
FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia
|
|
WHERE (bc.oid = i.indrelid)
|
|
AND (ic.oid = i.indexrelid)
|
|
AND (ia.attrelid = i.indexrelid)
|
|
AND (ta.attrelid = bc.oid)
|
|
AND (bc.relname = '" . $db->sql_escape($table_name) . "')
|
|
AND (ta.attrelid = i.indrelid)
|
|
AND (ta.attnum = i.indkey[ia.attnum-1])
|
|
ORDER BY index_name, tab_name, column_name";
|
|
|
|
$result = $db->sql_query($sql_pri_keys);
|
|
|
|
$index_create = $index_rows = $primary_key = array();
|
|
|
|
// We do this in two steps. It makes placing the comma easier
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if ($row['primary_key'] == 't')
|
|
{
|
|
$primary_key[] = $row['column_name'];
|
|
$primary_key_name = $row['index_name'];
|
|
}
|
|
else
|
|
{
|
|
// We have to store this all this info because it is possible to have a multi-column key...
|
|
// we can loop through it again and build the statement
|
|
$index_rows[$row['index_name']]['table'] = $table_name;
|
|
$index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false;
|
|
$index_rows[$row['index_name']]['column_names'][] = $row['column_name'];
|
|
}
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if (!empty($index_rows))
|
|
{
|
|
foreach ($index_rows as $idx_name => $props)
|
|
{
|
|
$index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");";
|
|
}
|
|
}
|
|
|
|
if (!empty($primary_key))
|
|
{
|
|
$lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")";
|
|
}
|
|
|
|
// Generate constraint clauses for CHECK constraints
|
|
$sql_checks = "SELECT conname as index_name, consrc
|
|
FROM pg_constraint, pg_class bc
|
|
WHERE conrelid = bc.oid
|
|
AND bc.relname = '" . $db->sql_escape($table_name) . "'
|
|
AND NOT EXISTS (
|
|
SELECT *
|
|
FROM pg_constraint as c, pg_inherits as i
|
|
WHERE i.inhrelid = pg_constraint.conrelid
|
|
AND c.conname = pg_constraint.conname
|
|
AND c.consrc = pg_constraint.consrc
|
|
AND c.conrelid = i.inhparent
|
|
)";
|
|
$result = $db->sql_query($sql_checks);
|
|
|
|
// Add the constraints to the sql file.
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if (!is_null($row['consrc']))
|
|
{
|
|
$lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
|
|
}
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql_data .= implode(", \n", $lines);
|
|
$sql_data .= "\n);\n";
|
|
|
|
if (!empty($index_create))
|
|
{
|
|
$sql_data .= implode("\n", $index_create) . "\n\n";
|
|
}
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
// Grab all of the data from current table.
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$i_num_fields = pg_num_fields($result);
|
|
$seq = '';
|
|
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$ary_type[] = pg_field_type($result, $i);
|
|
$ary_name[] = pg_field_name($result, $i);
|
|
|
|
$sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault
|
|
FROM pg_attrdef d, pg_class c
|
|
WHERE (c.relname = '{$table_name}')
|
|
AND (c.oid = d.adrelid)
|
|
AND d.adnum = " . strval($i + 1);
|
|
$result2 = $db->sql_query($sql);
|
|
if ($row = $db->sql_fetchrow($result2))
|
|
{
|
|
// Determine if we must reset the sequences
|
|
if (strpos($row['rowdefault'], "nextval('") === 0)
|
|
{
|
|
$seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n");
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$schema_vals = array();
|
|
|
|
// Build the SQL statement to recreate the data.
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$str_val = $row[$ary_name[$i]];
|
|
|
|
if (preg_match('#char|text|bool|bytea#i', $ary_type[$i]))
|
|
{
|
|
$str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val));
|
|
$str_empty = '';
|
|
}
|
|
else
|
|
{
|
|
$str_empty = '\N';
|
|
}
|
|
|
|
if (empty($str_val) && $str_val !== '0')
|
|
{
|
|
$str_val = $str_empty;
|
|
}
|
|
|
|
$schema_vals[] = $str_val;
|
|
}
|
|
|
|
// Take the ordered fields and their associated data and build it
|
|
// into a valid sql statement to recreate that field in the data.
|
|
$this->flush(implode("\t", $schema_vals) . "\n");
|
|
}
|
|
$db->sql_freeresult($result);
|
|
$this->flush("\\.\n");
|
|
|
|
// Write out the sequence statements
|
|
$this->flush($seq);
|
|
}
|
|
|
|
function write_end()
|
|
{
|
|
$this->flush("COMMIT;\n");
|
|
parent::write_end();
|
|
}
|
|
}
|
|
|
|
class mssql_extractor extends base_extractor
|
|
{
|
|
function write_end()
|
|
{
|
|
$this->flush("COMMIT\nGO\n");
|
|
parent::write_end();
|
|
}
|
|
|
|
function write_start($prefix)
|
|
{
|
|
$sql_data = "--\n";
|
|
$sql_data .= "-- phpBB Backup Script\n";
|
|
$sql_data .= "-- Dump of tables for $prefix\n";
|
|
$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "--\n";
|
|
$sql_data .= "BEGIN TRANSACTION\n";
|
|
$sql_data .= "GO\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
$sql_data = '-- Table: ' . $table_name . "\n";
|
|
$sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n";
|
|
$sql_data .= "DROP TABLE $table_name;\n";
|
|
$sql_data .= "GO\n";
|
|
$sql_data .= "\nCREATE TABLE [$table_name] (\n";
|
|
$rows = array();
|
|
|
|
$text_flag = false;
|
|
|
|
$sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE TABLE_NAME = '$table_name'";
|
|
$result = $db->sql_query($sql);
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]";
|
|
|
|
if ($row['DATA_TYPE'] == 'text')
|
|
{
|
|
$text_flag = true;
|
|
}
|
|
|
|
if ($row['IS_IDENTITY'])
|
|
{
|
|
$line .= ' IDENTITY (1 , 1)';
|
|
}
|
|
|
|
if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text')
|
|
{
|
|
$line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')';
|
|
}
|
|
|
|
if ($row['IS_NULLABLE'] == 'YES')
|
|
{
|
|
$line .= ' NULL';
|
|
}
|
|
else
|
|
{
|
|
$line .= ' NOT NULL';
|
|
}
|
|
|
|
if ($row['COLUMN_DEFAULT'])
|
|
{
|
|
$line .= ' DEFAULT ' . $row['COLUMN_DEFAULT'];
|
|
}
|
|
|
|
$rows[] = $line;
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql_data .= implode(",\n", $rows);
|
|
$sql_data .= "\n) ON [PRIMARY]";
|
|
|
|
if ($text_flag)
|
|
{
|
|
$sql_data .= " TEXTIMAGE_ON [PRIMARY]";
|
|
}
|
|
|
|
$sql_data .= "\nGO\n\n";
|
|
$rows = array();
|
|
|
|
$sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME
|
|
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
|
|
WHERE TABLE_NAME = '$table_name'";
|
|
$result = $db->sql_query($sql);
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if (!sizeof($rows))
|
|
{
|
|
$sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n";
|
|
$sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n";
|
|
}
|
|
$rows[] = "\t\t[{$row['COLUMN_NAME']}]";
|
|
}
|
|
if (sizeof($rows))
|
|
{
|
|
$sql_data .= implode(",\n", $rows);
|
|
$sql_data .= "\n\t) ON [PRIMARY] \nGO\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$index = array();
|
|
$sql = "EXEC sp_statistics '$table_name'";
|
|
$result = $db->sql_query($sql);
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
if ($row['TYPE'] == 3)
|
|
{
|
|
$index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
|
|
}
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
foreach ($index as $index_name => $column_name)
|
|
{
|
|
$index[$index_name] = implode(', ', $column_name);
|
|
}
|
|
|
|
foreach ($index as $index_name => $columns)
|
|
{
|
|
$sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n";
|
|
}
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
|
|
if ($db->get_sql_layer() === 'mssql')
|
|
{
|
|
$this->write_data_mssql($table_name);
|
|
}
|
|
else if ($db->get_sql_layer() === 'mssqlnative')
|
|
{
|
|
$this->write_data_mssqlnative($table_name);
|
|
}
|
|
else
|
|
{
|
|
$this->write_data_odbc($table_name);
|
|
}
|
|
}
|
|
|
|
function write_data_mssql($table_name)
|
|
{
|
|
global $db;
|
|
$ary_type = $ary_name = array();
|
|
$ident_set = false;
|
|
$sql_data = '';
|
|
|
|
// Grab all of the data from current table.
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$retrieved_data = mssql_num_rows($result);
|
|
|
|
$i_num_fields = mssql_num_fields($result);
|
|
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$ary_type[$i] = mssql_field_type($result, $i);
|
|
$ary_name[$i] = mssql_field_name($result, $i);
|
|
}
|
|
|
|
if ($retrieved_data)
|
|
{
|
|
$sql = "SELECT 1 as has_identity
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
|
|
$result2 = $db->sql_query($sql);
|
|
$row2 = $db->sql_fetchrow($result2);
|
|
if (!empty($row2['has_identity']))
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
|
|
$ident_set = true;
|
|
}
|
|
$db->sql_freeresult($result2);
|
|
}
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$schema_vals = $schema_fields = array();
|
|
|
|
// Build the SQL statement to recreate the data.
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$str_val = $row[$ary_name[$i]];
|
|
|
|
if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = "''";
|
|
$str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
|
|
}
|
|
else if (preg_match('#date|timestamp#i', $ary_type[$i]))
|
|
{
|
|
if (empty($str_val))
|
|
{
|
|
$str_quote = '';
|
|
}
|
|
else
|
|
{
|
|
$str_quote = "'";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = 'NULL';
|
|
}
|
|
|
|
if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
|
|
{
|
|
$str_val = $str_empty;
|
|
}
|
|
|
|
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
|
|
$schema_fields[$i] = $ary_name[$i];
|
|
}
|
|
|
|
// Take the ordered fields and their associated data and build it
|
|
// into a valid sql statement to recreate that field in the data.
|
|
$sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
|
|
|
|
$this->flush($sql_data);
|
|
$sql_data = '';
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if ($retrieved_data && $ident_set)
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
|
|
}
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_data_mssqlnative($table_name)
|
|
{
|
|
global $db;
|
|
$ary_type = $ary_name = array();
|
|
$ident_set = false;
|
|
$sql_data = '';
|
|
|
|
// Grab all of the data from current table.
|
|
$sql = "SELECT * FROM $table_name";
|
|
$db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
|
|
$result = $db->sql_query($sql);
|
|
|
|
$retrieved_data = $db->mssqlnative_num_rows($result);
|
|
|
|
if (!$retrieved_data)
|
|
{
|
|
$db->sql_freeresult($result);
|
|
return;
|
|
}
|
|
|
|
$sql = "SELECT COLUMN_NAME, DATA_TYPE
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'";
|
|
$result_fields = $db->sql_query($sql);
|
|
|
|
$i_num_fields = 0;
|
|
while ($row = $db->sql_fetchrow($result_fields))
|
|
{
|
|
$ary_type[$i_num_fields] = $row['DATA_TYPE'];
|
|
$ary_name[$i_num_fields] = $row['COLUMN_NAME'];
|
|
$i_num_fields++;
|
|
}
|
|
$db->sql_freeresult($result_fields);
|
|
|
|
$sql = "SELECT 1 as has_identity
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
|
|
$result2 = $db->sql_query($sql);
|
|
$row2 = $db->sql_fetchrow($result2);
|
|
|
|
if (!empty($row2['has_identity']))
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
|
|
$ident_set = true;
|
|
}
|
|
$db->sql_freeresult($result2);
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$schema_vals = $schema_fields = array();
|
|
|
|
// Build the SQL statement to recreate the data.
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$str_val = $row[$ary_name[$i]];
|
|
|
|
// defaults to type number - better quote just to be safe, so check for is_int too
|
|
if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = "''";
|
|
$str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
|
|
}
|
|
else if (preg_match('#date|timestamp#i', $ary_type[$i]))
|
|
{
|
|
if (empty($str_val))
|
|
{
|
|
$str_quote = '';
|
|
}
|
|
else
|
|
{
|
|
$str_quote = "'";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = 'NULL';
|
|
}
|
|
|
|
if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
|
|
{
|
|
$str_val = $str_empty;
|
|
}
|
|
|
|
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
|
|
$schema_fields[$i] = $ary_name[$i];
|
|
}
|
|
|
|
// Take the ordered fields and their associated data and build it
|
|
// into a valid sql statement to recreate that field in the data.
|
|
$sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
|
|
|
|
$this->flush($sql_data);
|
|
$sql_data = '';
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if ($ident_set)
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
|
|
}
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_data_odbc($table_name)
|
|
{
|
|
global $db;
|
|
$ary_type = $ary_name = array();
|
|
$ident_set = false;
|
|
$sql_data = '';
|
|
|
|
// Grab all of the data from current table.
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$retrieved_data = odbc_num_rows($result);
|
|
|
|
if ($retrieved_data)
|
|
{
|
|
$sql = "SELECT 1 as has_identity
|
|
FROM INFORMATION_SCHEMA.COLUMNS
|
|
WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1";
|
|
$result2 = $db->sql_query($sql);
|
|
$row2 = $db->sql_fetchrow($result2);
|
|
if (!empty($row2['has_identity']))
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
|
|
$ident_set = true;
|
|
}
|
|
$db->sql_freeresult($result2);
|
|
}
|
|
|
|
$i_num_fields = odbc_num_fields($result);
|
|
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$ary_type[$i] = odbc_field_type($result, $i + 1);
|
|
$ary_name[$i] = odbc_field_name($result, $i + 1);
|
|
}
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$schema_vals = $schema_fields = array();
|
|
|
|
// Build the SQL statement to recreate the data.
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$str_val = $row[$ary_name[$i]];
|
|
|
|
if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i]))
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = "''";
|
|
$str_val = sanitize_data_mssql(str_replace("'", "''", $str_val));
|
|
}
|
|
else if (preg_match('#date|timestamp#i', $ary_type[$i]))
|
|
{
|
|
if (empty($str_val))
|
|
{
|
|
$str_quote = '';
|
|
}
|
|
else
|
|
{
|
|
$str_quote = "'";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = 'NULL';
|
|
}
|
|
|
|
if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val)))
|
|
{
|
|
$str_val = $str_empty;
|
|
}
|
|
|
|
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
|
|
$schema_fields[$i] = $ary_name[$i];
|
|
}
|
|
|
|
// Take the ordered fields and their associated data and build it
|
|
// into a valid sql statement to recreate that field in the data.
|
|
$sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n";
|
|
|
|
$this->flush($sql_data);
|
|
|
|
$sql_data = '';
|
|
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if ($retrieved_data && $ident_set)
|
|
{
|
|
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
|
|
}
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
}
|
|
|
|
class oracle_extractor extends base_extractor
|
|
{
|
|
function write_table($table_name)
|
|
{
|
|
global $db;
|
|
$sql_data = '-- Table: ' . $table_name . "\n";
|
|
$sql_data .= "DROP TABLE $table_name\n/\n";
|
|
$sql_data .= "\nCREATE TABLE $table_name (\n";
|
|
|
|
$sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT
|
|
FROM ALL_TAB_COLS
|
|
WHERE table_name = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$rows = array();
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$line = ' "' . $row['column_name'] . '" ' . $row['data_type'];
|
|
|
|
if ($row['data_type'] !== 'CLOB')
|
|
{
|
|
if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR')
|
|
{
|
|
$line .= '(' . $row['data_precision'] . ')';
|
|
}
|
|
else
|
|
{
|
|
$line .= '(' . $row['data_length'] . ')';
|
|
}
|
|
}
|
|
|
|
if (!empty($row['data_default']))
|
|
{
|
|
$line .= ' DEFAULT ' . $row['data_default'];
|
|
}
|
|
|
|
if ($row['nullable'] == 'N')
|
|
{
|
|
$line .= ' NOT NULL';
|
|
}
|
|
$rows[] = $line;
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
|
|
FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
|
|
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
|
|
AND B.CONSTRAINT_TYPE = 'P'
|
|
AND A.TABLE_NAME = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$primary_key = array();
|
|
$contraint_name = '';
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$constraint_name = '"' . $row['constraint_name'] . '"';
|
|
$primary_key[] = '"' . $row['column_name'] . '"';
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if (sizeof($primary_key))
|
|
{
|
|
$rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')';
|
|
}
|
|
|
|
$sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME
|
|
FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B
|
|
WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME
|
|
AND B.CONSTRAINT_TYPE = 'U'
|
|
AND A.TABLE_NAME = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$unique = array();
|
|
$contraint_name = '';
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$constraint_name = '"' . $row['constraint_name'] . '"';
|
|
$unique[] = '"' . $row['column_name'] . '"';
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
if (sizeof($unique))
|
|
{
|
|
$rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')';
|
|
}
|
|
|
|
$sql_data .= implode(",\n", $rows);
|
|
$sql_data .= "\n)\n/\n";
|
|
|
|
$sql = "SELECT A.REFERENCED_NAME, C.*
|
|
FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C
|
|
WHERE A.REFERENCED_TYPE = 'SEQUENCE'
|
|
AND A.NAME = B.TRIGGER_NAME
|
|
AND B.TABLE_NAME = '{$table_name}'
|
|
AND C.SEQUENCE_NAME = A.REFERENCED_NAME";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$type = request_var('type', '');
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n";
|
|
$sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\"";
|
|
|
|
if ($type == 'full')
|
|
{
|
|
$sql_data .= ' START WITH ' . $row['last_number'];
|
|
}
|
|
|
|
$sql_data .= "\n/\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
|
|
FROM USER_TRIGGERS
|
|
WHERE TABLE_NAME = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
|
|
$sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME
|
|
FROM USER_INDEXES A, USER_IND_COLUMNS B
|
|
WHERE A.UNIQUENESS = 'NONUNIQUE'
|
|
AND A.INDEX_NAME = B.INDEX_NAME
|
|
AND B.TABLE_NAME = '{$table_name}'";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$index = array();
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$index[$row['index_name']][] = $row['column_name'];
|
|
}
|
|
|
|
foreach ($index as $index_name => $column_names)
|
|
{
|
|
$sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n";
|
|
}
|
|
$db->sql_freeresult($result);
|
|
$this->flush($sql_data);
|
|
}
|
|
|
|
function write_data($table_name)
|
|
{
|
|
global $db;
|
|
$ary_type = $ary_name = array();
|
|
|
|
// Grab all of the data from current table.
|
|
$sql = "SELECT *
|
|
FROM $table_name";
|
|
$result = $db->sql_query($sql);
|
|
|
|
$i_num_fields = ocinumcols($result);
|
|
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
$ary_type[$i] = ocicolumntype($result, $i + 1);
|
|
$ary_name[$i] = ocicolumnname($result, $i + 1);
|
|
}
|
|
|
|
$sql_data = '';
|
|
|
|
while ($row = $db->sql_fetchrow($result))
|
|
{
|
|
$schema_vals = $schema_fields = array();
|
|
|
|
// Build the SQL statement to recreate the data.
|
|
for ($i = 0; $i < $i_num_fields; $i++)
|
|
{
|
|
// Oracle uses uppercase - we use lowercase
|
|
$str_val = $row[strtolower($ary_name[$i])];
|
|
|
|
if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i]))
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = "''";
|
|
$str_val = sanitize_data_oracle($str_val);
|
|
}
|
|
else if (preg_match('#date|timestamp#i', $ary_type[$i]))
|
|
{
|
|
if (empty($str_val))
|
|
{
|
|
$str_quote = '';
|
|
}
|
|
else
|
|
{
|
|
$str_quote = "'";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$str_quote = '';
|
|
$str_empty = 'NULL';
|
|
}
|
|
|
|
if (empty($str_val) && $str_val !== '0')
|
|
{
|
|
$str_val = $str_empty;
|
|
}
|
|
|
|
$schema_vals[$i] = $str_quote . $str_val . $str_quote;
|
|
$schema_fields[$i] = '"' . $ary_name[$i] . '"';
|
|
}
|
|
|
|
// Take the ordered fields and their associated data and build it
|
|
// into a valid sql statement to recreate that field in the data.
|
|
$sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n";
|
|
|
|
$this->flush($sql_data);
|
|
}
|
|
$db->sql_freeresult($result);
|
|
}
|
|
|
|
function write_start($prefix)
|
|
{
|
|
$sql_data = "--\n";
|
|
$sql_data .= "-- phpBB Backup Script\n";
|
|
$sql_data .= "-- Dump of tables for $prefix\n";
|
|
$sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n";
|
|
$sql_data .= "--\n";
|
|
$this->flush($sql_data);
|
|
}
|
|
}
|
|
|
|
// get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P)
|
|
function get_usable_memory()
|
|
{
|
|
$val = trim(@ini_get('memory_limit'));
|
|
|
|
if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs))
|
|
{
|
|
$memory_limit = (int) $regs[1];
|
|
switch ($regs[2])
|
|
{
|
|
|
|
case 'k':
|
|
case 'K':
|
|
$memory_limit *= 1024;
|
|
break;
|
|
|
|
case 'm':
|
|
case 'M':
|
|
$memory_limit *= 1048576;
|
|
break;
|
|
|
|
case 'g':
|
|
case 'G':
|
|
$memory_limit *= 1073741824;
|
|
break;
|
|
}
|
|
|
|
// how much memory PHP requires at the start of export (it is really a little less)
|
|
if ($memory_limit > 6100000)
|
|
{
|
|
$memory_limit -= 6100000;
|
|
}
|
|
|
|
// allow us to consume half of the total memory available
|
|
$memory_limit /= 2;
|
|
}
|
|
else
|
|
{
|
|
// set the buffer to 1M if we have no clue how much memory PHP will give us :P
|
|
$memory_limit = 1048576;
|
|
}
|
|
|
|
return $memory_limit;
|
|
}
|
|
|
|
function sanitize_data_mssql($text)
|
|
{
|
|
$data = preg_split('/[\n\t\r\b\f]/', $text);
|
|
preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
|
|
|
|
$val = array();
|
|
|
|
foreach ($data as $value)
|
|
{
|
|
if (strlen($value))
|
|
{
|
|
$val[] = "'" . $value . "'";
|
|
}
|
|
if (sizeof($matches[0]))
|
|
{
|
|
$val[] = 'char(' . ord(array_shift($matches[0])) . ')';
|
|
}
|
|
}
|
|
|
|
return implode('+', $val);
|
|
}
|
|
|
|
function sanitize_data_oracle($text)
|
|
{
|
|
// $data = preg_split('/[\0\n\t\r\b\f\'"\/\\\]/', $text);
|
|
// preg_match_all('/[\0\n\t\r\b\f\'"\/\\\]/', $text, $matches);
|
|
$data = preg_split('/[\0\b\f\'\/]/', $text);
|
|
preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches);
|
|
|
|
$val = array();
|
|
|
|
foreach ($data as $value)
|
|
{
|
|
if (strlen($value))
|
|
{
|
|
$val[] = "'" . $value . "'";
|
|
}
|
|
if (sizeof($matches[0]))
|
|
{
|
|
$val[] = 'chr(' . ord(array_shift($matches[0])) . ')';
|
|
}
|
|
}
|
|
|
|
return implode('||', $val);
|
|
}
|
|
|
|
function sanitize_data_generic($text)
|
|
{
|
|
$data = preg_split('/[\n\t\r\b\f]/', $text);
|
|
preg_match_all('/[\n\t\r\b\f]/', $text, $matches);
|
|
|
|
$val = array();
|
|
|
|
foreach ($data as $value)
|
|
{
|
|
if (strlen($value))
|
|
{
|
|
$val[] = "'" . $value . "'";
|
|
}
|
|
if (sizeof($matches[0]))
|
|
{
|
|
$val[] = "'" . array_shift($matches[0]) . "'";
|
|
}
|
|
}
|
|
|
|
return implode('||', $val);
|
|
}
|
|
|
|
// modified from PHP.net
|
|
function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
|
|
{
|
|
$record = '';
|
|
$delim_len = strlen($delim);
|
|
|
|
while (!$eof($fp))
|
|
{
|
|
$pos = strpos($record, $delim);
|
|
if ($pos === false)
|
|
{
|
|
$record .= $read($fp, $buffer);
|
|
if ($eof($fp) && ($pos = strpos($record, $delim)) !== false)
|
|
{
|
|
$seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
|
|
return substr($record, 0, $pos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR);
|
|
return substr($record, 0, $pos);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192)
|
|
{
|
|
static $array = array();
|
|
static $record = '';
|
|
|
|
if (!sizeof($array))
|
|
{
|
|
while (!$eof($fp))
|
|
{
|
|
if (strpos($record, $delim) !== false)
|
|
{
|
|
$array = explode($delim, $record);
|
|
$record = array_pop($array);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
$record .= $read($fp, $buffer);
|
|
}
|
|
}
|
|
if ($eof($fp) && strpos($record, $delim) !== false)
|
|
{
|
|
$array = explode($delim, $record);
|
|
$record = array_pop($array);
|
|
}
|
|
}
|
|
|
|
if (sizeof($array))
|
|
{
|
|
return array_shift($array);
|
|
}
|
|
|
|
return false;
|
|
}
|