diff options
Diffstat (limited to 'phpBB/includes')
-rw-r--r-- | phpBB/includes/acp/acp_bbcodes.php | 5 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_database.php | 1662 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_icons.php | 6 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_main.php | 5 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_styles.php | 12 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_words.php | 4 | ||||
-rw-r--r-- | phpBB/includes/functions_content.php | 121 | ||||
-rw-r--r-- | phpBB/includes/mcp/mcp_main.php | 25 | ||||
-rw-r--r-- | phpBB/includes/message_parser.php | 140 |
9 files changed, 198 insertions, 1782 deletions
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index a5cd48c444..d451b4d899 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -25,7 +25,7 @@ class acp_bbcodes function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; + global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $user->add_lang('acp/posting'); @@ -269,6 +269,7 @@ class acp_bbcodes $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_ADDED'; $log_action = 'LOG_BBCODE_ADD'; @@ -280,6 +281,7 @@ class acp_bbcodes WHERE bbcode_id = ' . $bbcode_id; $db->sql_query($sql); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_EDITED'; $log_action = 'LOG_BBCODE_EDIT'; @@ -319,6 +321,7 @@ class acp_bbcodes { $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); if ($request->is_ajax()) diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index 25cddaa5d4..984301a38f 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -90,36 +90,9 @@ class acp_database $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 = $phpbb_container->get('dbal.extractor'); + $extractor->init_extractor($format, $filename, $time, $download, $store); $extractor->write_start($table_prefix); @@ -461,1637 +434,6 @@ class acp_database } } -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"); - } - } - - $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, $request; - - $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->variable('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() { diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index fdf366097a..5d1756de45 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -28,7 +28,7 @@ class acp_icons function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; global $request, $phpbb_container; @@ -486,6 +486,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; @@ -661,6 +662,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } @@ -783,6 +785,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { @@ -848,6 +851,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index 21c6edfccf..8680b7786a 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -352,6 +352,11 @@ class acp_main $config->increment('assets_version', 1); $cache->purge(); + // Remove old renderers from the text_formatter service. Since this + // operation is performed after the cache is purged, there is not "current" + // renderer and in effect all renderers will be purged + $phpbb_container->get('text_formatter.cache')->tidy(); + // Clear permissions $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 45f224f8b1..b652fd6587 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -53,6 +53,9 @@ class acp_styles /** @var \phpbb\auth\auth */ protected $auth; + /** @var \phpbb\textformatter\cache_interface */ + protected $text_formatter_cache; + /** @var string */ protected $phpbb_root_path; @@ -61,7 +64,7 @@ class acp_styles public function main($id, $mode) { - global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config; + global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_container; $this->db = $db; $this->user = $user; @@ -69,6 +72,7 @@ class acp_styles $this->request = $request; $this->cache = $cache; $this->auth = $auth; + $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache'); $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; @@ -216,6 +220,12 @@ class acp_styles } } + // Invalidate the text formatter's cache for the new styles to take effect + if (!empty($installed_names)) + { + $this->text_formatter_cache->invalidate(); + } + // Show message if (!count($messages)) { diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index d28aa8e60b..ea8d47a109 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -28,7 +28,7 @@ class acp_words function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_log, $request; + global $db, $user, $auth, $template, $cache, $phpbb_log, $request, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/posting'); @@ -115,6 +115,7 @@ class acp_words } $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; @@ -148,6 +149,7 @@ class acp_words $db->sql_query($sql); $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index bdbc8a92fa..60511d89a4 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -389,46 +389,68 @@ function phpbb_clean_search_string($search_string) /** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... +* +* NOTE: special chars are kept encoded +* +* @param string &$message Original message, passed by reference +* @param string $bbcode_uid BBCode UID +* @return null */ function decode_message(&$message, $bbcode_uid = '') { - global $config; + global $phpbb_container; - if ($bbcode_uid) + if (preg_match('#^<[rt][ >]#', $message)) { - $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); + $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT); } else { - $match = array('<br />'); - $replace = array("\n"); - } + if ($bbcode_uid) + { + $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); + $replace = array("\n", '', '', '', ''); + } + else + { + $match = array('<br />'); + $replace = array("\n"); + } - $message = str_replace($match, $replace, $message); + $message = str_replace($match, $replace, $message); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $message = preg_replace($match, $replace, $message); + $message = preg_replace($match, $replace, $message); + } } /** -* Strips all bbcode from a text and returns the plain content +* Strips all bbcode from a text in place */ function strip_bbcode(&$text, $uid = '') { - if (!$uid) + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $text)) { - $uid = '[0-9a-z]{5,}'; + $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text); } + else + { + if (!$uid) + { + $uid = '[0-9a-z]{5,}'; + } - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); + $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $text = preg_replace($match, $replace, $text); + $text = preg_replace($match, $replace, $text); + } } /** @@ -438,7 +460,7 @@ function strip_bbcode(&$text, $uid = '') function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true) { static $bbcode; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if ($text === '') { @@ -459,34 +481,56 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text $vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars))); - if ($censor_text) + if (preg_match('#^<[rt][ >]#', $text)) { - $text = censor_text($text); - } + $renderer = $phpbb_container->get('text_formatter.renderer'); - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) - { - if (!class_exists('bbcode')) + // Temporarily switch off viewcensors if applicable + $old_censor = $renderer->get_viewcensors(); + if ($old_censor !== $censor_text) { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $renderer->set_viewcensors($censor_text); } - if (empty($bbcode)) + $text = $renderer->render($text); + + // Restore the previous value + if ($old_censor !== $censor_text) { - $bbcode = new bbcode($bitfield); + $renderer->set_viewcensors($old_censor); } - else + } + else + { + if ($censor_text) { - $bbcode->bbcode($bitfield); + $text = censor_text($text); } - $bbcode->bbcode_second_pass($text, $uid); - } + // Parse bbcode if bbcode uid stored and bbcode enabled + if ($uid && ($flags & OPTION_FLAG_BBCODE)) + { + if (!class_exists('bbcode')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } + + if (empty($bbcode)) + { + $bbcode = new bbcode($bitfield); + } + else + { + $bbcode->bbcode($bitfield); + } - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + $bbcode->bbcode_second_pass($text, $uid); + } + + $text = bbcode_nl2br($text); + $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + } /** * Use this event to modify the text after it is parsed @@ -550,11 +594,6 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb $uid = $bitfield = ''; $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - if ($text === '') - { - return; - } - if (!class_exists('parse_message')) { include($phpbb_root_path . 'includes/message_parser.' . $phpEx); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index e3fbbc0418..e8ab0167f5 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -226,6 +226,31 @@ class mcp_main break; default: + if ($quickmod) + { + switch ($action) + { + case 'lock': + case 'unlock': + case 'make_announce': + case 'make_sticky': + case 'make_global': + case 'make_normal': + case 'make_onindex': + case 'move': + case 'fork': + case 'delete_topic': + trigger_error('TOPIC_NOT_EXIST'); + break; + + case 'lock_post': + case 'unlock_post': + case 'delete_post': + trigger_error('POST_NOT_EXIST'); + break; + } + } + trigger_error('NO_MODE', E_USER_ERROR); break; } diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ccb953adbe..8353ae6843 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -21,6 +21,19 @@ if (!defined('IN_PHPBB')) if (!class_exists('bbcode')) { + // The following lines are for extensions which include message_parser.php + // while $phpbb_root_path and $phpEx are out of the script scope + // which may lead to the 'Undefined variable' and 'failed to open stream' errors + if (!isset($phpbb_root_path)) + { + global $phpbb_root_path; + } + + if (!isset($phpEx)) + { + global $phpEx; + } + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); } @@ -1103,7 +1116,7 @@ class parse_message extends bbcode_firstpass */ function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') { - global $config, $db, $user, $phpbb_dispatcher; + global $config, $db, $user, $phpbb_dispatcher, $phpbb_container; $this->mode = $mode; @@ -1132,12 +1145,6 @@ class parse_message extends bbcode_firstpass $this->decode_message(); } - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - // Store message length... $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); @@ -1210,47 +1217,29 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } + // Get the parser + $parser = $phpbb_container->get('text_formatter.parser'); - $this->prepare_bbcodes(); - } + // Set the parser's options + ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes(); + ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url(); + ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies(); + ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img'); + ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash'); + ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote'); + ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url'); - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } + // Set some config values + $parser->set_vars(array( + 'max_font_size' => $config['max_' . $this->mode . '_font_size'], + 'max_img_height' => $config['max_' . $this->mode . '_img_height'], + 'max_img_width' => $config['max_' . $this->mode . '_img_width'], + 'max_smilies' => $config['max_' . $this->mode . '_smilies'], + 'max_urls' => $config['max_' . $this->mode . '_urls'] + )); - $num_urls = 0; - - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } - - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); - - if ($config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\<!-- ([lmwe]) --\>.*?\<!-- \1 --\>#', $this->message, $matches); - } - } + // Parse this message + $this->message = $parser->parse(htmlspecialchars_decode($this->message, ENT_QUOTES)); // Check for out-of-bounds characters that are currently // not supported by utf8_bin in MySQL @@ -1269,10 +1258,12 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Check number of links - if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls']) + // Check for errors + $errors = $parser->get_errors(); + if ($errors) { - $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $config['max_' . $mode . '_urls']); + $this->warn_msg = array_merge($this->warn_msg, $errors); + return (!$update_this_message) ? $return_message : $this->warn_msg; } @@ -1292,7 +1283,7 @@ class parse_message extends bbcode_firstpass */ function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true) { - global $phpbb_dispatcher; + global $phpbb_container, $phpbb_dispatcher; // If false, then the parsed message get returned but internal message not processed. if (!$update_this_message) @@ -1301,26 +1292,25 @@ class parse_message extends bbcode_firstpass $return_message = &$this->message; } - if ($this->message_status == 'plain') + // NOTE: message_status is unreliable for detecting unparsed text because some callers + // change $this->message without resetting $this->message_status to 'plain' so we + // inspect the message instead + //if ($this->message_status == 'plain') + if (!preg_match('/^<[rt][ >]/', $this->message)) { // Force updating message - of course. $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true); } - // Replace naughty words such as farty pants - $this->message = censor_text($this->message); - - // Parse BBcode - if ($allow_bbcode) + // There's a bug when previewing a topic with no poll, because the empty title of the poll + // gets parsed but $this->message still ends up empty. This fixes it, until a proper fix is + // devised + if ($this->message === '') { - $this->bbcode_cache_init(); - - // We are giving those parameters to be able to use the bbcode class on its own - $this->bbcode_second_pass($this->message, $this->bbcode_uid); + $this->message = $phpbb_container->get('text_formatter.parser')->parse($this->message); } - $this->message = bbcode_nl2br($this->message); - $this->message = smiley_text($this->message, !$allow_smilies); + $this->message = $phpbb_container->get('text_formatter.renderer')->render($this->message); $text = $this->message; $uid = $this->bbcode_uid; @@ -1784,24 +1774,22 @@ class parse_message extends bbcode_firstpass $poll_max_options = $poll['poll_max_options']; - // Parse Poll Option text ;) + // Parse Poll Option text $tmp_message = $this->message; - $this->message = $poll['poll_option_text']; - $bbcode_bitfield = $this->bbcode_bitfield; - $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); + $poll['poll_options_size'] = sizeof($poll['poll_options']); - $bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; + foreach ($poll['poll_options'] as &$poll_option) + { + $this->message = $poll_option; + $poll_option = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + } + unset($poll_option); + $poll['poll_option_text'] = implode("\n", $poll['poll_options']); // Parse Poll Title - $tmp_message = $this->message; $this->message = $poll['poll_title']; - $this->bbcode_bitfield = $bbcode_bitfield; - - $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); - $poll['poll_options_size'] = sizeof($poll['poll_options']); - if (!$poll['poll_title'] && $poll['poll_options_size']) { $this->warn_msg[] = $user->lang['NO_POLL_TITLE']; @@ -1819,10 +1807,6 @@ class parse_message extends bbcode_firstpass } } - $this->bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; - unset($tmp_message); - if (sizeof($poll['poll_options']) == 1) { $this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS']; @@ -1837,6 +1821,8 @@ class parse_message extends bbcode_firstpass } $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']); + + $this->message = $tmp_message; } /** |