PDF rausgenommen

This commit is contained in:
aschwarz
2023-01-23 11:03:31 +01:00
parent 82d562a322
commit a6523903eb
28078 changed files with 4247552 additions and 2 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,453 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
interface driver_interface
{
/**
* Gets the name of the sql layer.
*
* @return string
*/
public function get_sql_layer();
/**
* Gets the name of the database.
*
* @return string
*/
public function get_db_name();
/**
* Wildcards for matching any (%) character within LIKE expressions
*
* @return string
*/
public function get_any_char();
/**
* Wildcards for matching exactly one (_) character within LIKE expressions
*
* @return string
*/
public function get_one_char();
/**
* Gets the time spent into the queries
*
* @return int
*/
public function get_sql_time();
/**
* Gets the connect ID.
*
* @return mixed
*/
public function get_db_connect_id();
/**
* Indicates if an error was triggered.
*
* @return bool
*/
public function get_sql_error_triggered();
/**
* Gets the last faulty query
*
* @return string
*/
public function get_sql_error_sql();
/**
* Indicates if we are in a transaction.
*
* @return bool
*/
public function get_transaction();
/**
* Gets the returned error.
*
* @return array
*/
public function get_sql_error_returned();
/**
* Indicates if multiple insertion can be used
*
* @return bool
*/
public function get_multi_insert();
/**
* Set if multiple insertion can be used
*
* @param bool $multi_insert
*/
public function set_multi_insert($multi_insert);
/**
* Gets the exact number of rows in a specified table.
*
* @param string $table_name Table name
* @return string Exact number of rows in $table_name.
*/
public function get_row_count($table_name);
/**
* Gets the estimated number of rows in a specified table.
*
* @param string $table_name Table name
* @return string Number of rows in $table_name.
* Prefixed with ~ if estimated (otherwise exact).
*/
public function get_estimated_row_count($table_name);
/**
* Run LOWER() on DB column of type text (i.e. neither varchar nor char).
*
* @param string $column_name The column name to use
* @return string A SQL statement like "LOWER($column_name)"
*/
public function sql_lower_text($column_name);
/**
* Display sql error page
*
* @param string $sql The SQL query causing the error
* @return mixed Returns the full error message, if $this->return_on_error
* is set, null otherwise
*/
public function sql_error($sql = '');
/**
* Returns whether results of a query need to be buffered to run a
* transaction while iterating over them.
*
* @return bool Whether buffering is required.
*/
public function sql_buffer_nested_transactions();
/**
* Run binary OR operator on DB column.
*
* @param string $column_name The column name to use
* @param int $bit The value to use for the OR operator,
* will be converted to (1 << $bit). Is used by options,
* using the number schema... 0, 1, 2...29
* @param string $compare Any custom SQL code after the check (e.g. "= 0")
* @return string A SQL statement like "$column | (1 << $bit) {$compare}"
*/
public function sql_bit_or($column_name, $bit, $compare = '');
/**
* Version information about used database
*
* @param bool $raw Only return the fetched sql_server_version
* @param bool $use_cache Is it safe to retrieve the value from the cache
* @return string sql server version
*/
public function sql_server_info($raw = false, $use_cache = true);
/**
* Return on error or display error message
*
* @param bool $fail Should we return on errors, or stop
* @return null
*/
public function sql_return_on_error($fail = false);
/**
* Build sql statement from an array
*
* @param string $query Should be on of the following strings:
* INSERT, INSERT_SELECT, UPDATE, SELECT, DELETE
* @param array $assoc_ary Array with "column => value" pairs
* @return string A SQL statement like "c1 = 'a' AND c2 = 'b'"
*/
public function sql_build_array($query, $assoc_ary = array());
/**
* Fetch all rows
*
* @param mixed $query_id Already executed query to get the rows from,
* if false, the last query will be used.
* @return mixed Nested array if the query had rows, false otherwise
*/
public function sql_fetchrowset($query_id = false);
/**
* SQL Transaction
*
* @param string $status Should be one of the following strings:
* begin, commit, rollback
* @return mixed Buffered, seekable result handle, false on error
*/
public function sql_transaction($status = 'begin');
/**
* Build a concatenated expression
*
* @param string $expr1 Base SQL expression where we append the second one
* @param string $expr2 SQL expression that is appended to the first expression
* @return string Concatenated string
*/
public function sql_concatenate($expr1, $expr2);
/**
* Build a case expression
*
* Note: The two statements action_true and action_false must have the same
* data type (int, vchar, ...) in the database!
*
* @param string $condition The condition which must be true,
* to use action_true rather then action_else
* @param string $action_true SQL expression that is used, if the condition is true
* @param mixed $action_false SQL expression that is used, if the condition is false
* @return string CASE expression including the condition and statements
*/
public function sql_case($condition, $action_true, $action_false = false);
/**
* Build sql statement from array for select and select distinct statements
*
* Possible query values: SELECT, SELECT_DISTINCT
*
* @param string $query Should be one of: SELECT, SELECT_DISTINCT
* @param array $array Array with the query data:
* SELECT A comma imploded list of columns to select
* FROM Array with "table => alias" pairs,
* (alias can also be an array)
* Optional: LEFT_JOIN Array of join entries:
* FROM Table that should be joined
* ON Condition for the join
* Optional: WHERE Where SQL statement
* Optional: GROUP_BY Group by SQL statement
* Optional: ORDER_BY Order by SQL statement
* @return string A SQL statement ready for execution
*/
public function sql_build_query($query, $array);
/**
* Fetch field
* if rownum is false, the current row is used, else it is pointing to the row (zero-based)
*
* @param string $field Name of the column
* @param mixed $rownum Row number, if false the current row will be used
* and the row curser will point to the next row
* Note: $rownum is 0 based
* @param mixed $query_id Already executed query to get the rows from,
* if false, the last query will be used.
* @return mixed String value of the field in the selected row,
* false, if the row does not exist
*/
public function sql_fetchfield($field, $rownum = false, $query_id = false);
/**
* Fetch current row
*
* @param mixed $query_id Already executed query to get the rows from,
* if false, the last query will be used.
* @return mixed Array with the current row,
* false, if the row does not exist
*/
public function sql_fetchrow($query_id = false);
/**
* Returns SQL string to cast a string expression to an int.
*
* @param string $expression An expression evaluating to string
* @return string Expression returning an int
*/
public function cast_expr_to_bigint($expression);
/**
* Get last inserted id after insert statement
*
* @return string Autoincrement value of the last inserted row
*/
public function sql_nextid();
/**
* Add to query count
*
* @param bool $cached Is this query cached?
* @return null
*/
public function sql_add_num_queries($cached = false);
/**
* Build LIMIT query
*
* @param string $query The SQL query to execute
* @param int $total The number of rows to select
* @param int $offset
* @param int $cache_ttl Either 0 to avoid caching or
* the time in seconds which the result shall be kept in cache
* @return mixed Buffered, seekable result handle, false on error
*/
public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0);
/**
* Base query method
*
* @param string $query The SQL query to execute
* @param int $cache_ttl Either 0 to avoid caching or
* the time in seconds which the result shall be kept in cache
* @return mixed Buffered, seekable result handle, false on error
*/
public function sql_query($query = '', $cache_ttl = 0);
/**
* Returns SQL string to cast an integer expression to a string.
*
* @param string $expression An expression evaluating to int
* @return string Expression returning a string
*/
public function cast_expr_to_string($expression);
/**
* Connect to server
*
* @param string $sqlserver Address of the database server
* @param string $sqluser User name of the SQL user
* @param string $sqlpassword Password of the SQL user
* @param string $database Name of the database
* @param mixed $port Port of the database server
* @param bool $persistency
* @param bool $new_link Should a new connection be established
* @return mixed Connection ID on success, string error message otherwise
*/
public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false);
/**
* Run binary AND operator on DB column.
* Results in sql statement: "{$column_name} & (1 << {$bit}) {$compare}"
*
* @param string $column_name The column name to use
* @param int $bit The value to use for the AND operator,
* will be converted to (1 << $bit). Is used by
* options, using the number schema: 0, 1, 2...29
* @param string $compare Any custom SQL code after the check (for example "= 0")
* @return string A SQL statement like: "{$column} & (1 << {$bit}) {$compare}"
*/
public function sql_bit_and($column_name, $bit, $compare = '');
/**
* Free sql result
*
* @param mixed $query_id Already executed query result,
* if false, the last query will be used.
* @return null
*/
public function sql_freeresult($query_id = false);
/**
* Return number of sql queries and cached sql queries used
*
* @param bool $cached Should we return the number of cached or normal queries?
* @return int Number of queries that have been executed
*/
public function sql_num_queries($cached = false);
/**
* Run more than one insert statement.
*
* @param string $table Table name to run the statements on
* @param array $sql_ary Multi-dimensional array holding the statement data
* @return bool false if no statements were executed.
*/
public function sql_multi_insert($table, $sql_ary);
/**
* Return number of affected rows
*
* @return mixed Number of the affected rows by the last query
* false if no query has been run before
*/
public function sql_affectedrows();
/**
* DBAL garbage collection, close SQL connection
*
* @return mixed False if no connection was opened before,
* Server response otherwise
*/
public function sql_close();
/**
* Seek to given row number
*
* @param mixed $rownum Row number the curser should point to
* Note: $rownum is 0 based
* @param mixed $query_id ID of the query to set the row cursor on
* if false, the last query will be used.
* $query_id will then be set correctly
* @return bool False if something went wrong
*/
public function sql_rowseek($rownum, &$query_id);
/**
* Escape string used in sql query
*
* @param string $msg String to be escaped
* @return string Escaped version of $msg
*/
public function sql_escape($msg);
/**
* Correctly adjust LIKE expression for special characters
* Some DBMS are handling them in a different way
*
* @param string $expression The expression to use. Every wildcard is
* escaped, except $this->any_char and $this->one_char
* @return string A SQL statement like: "LIKE 'bertie_%'"
*/
public function sql_like_expression($expression);
/**
* Correctly adjust NOT LIKE expression for special characters
* Some DBMS are handling them in a different way
*
* @param string $expression The expression to use. Every wildcard is
* escaped, except $this->any_char and $this->one_char
* @return string A SQL statement like: "NOT LIKE 'bertie_%'"
*/
public function sql_not_like_expression($expression);
/**
* Explain queries
*
* @param string $mode Available modes: display, start, stop,
* add_select_row, fromcache, record_fromcache
* @param string $query The Query that should be explained
* @return mixed Either a full HTML page, boolean or null
*/
public function sql_report($mode, $query = '');
/**
* Build IN or NOT IN sql comparison string, uses <> or = on single element
* arrays to improve comparison speed
*
* @param string $field Name of the sql column that shall be compared
* @param array $array Array of values that are (not) allowed
* @param bool $negate true for NOT IN (), false for IN ()
* @param bool $allow_empty_set If true, allow $array to be empty,
* this function will return 1=1 or 1=0 then.
* @return string A SQL statement like: "IN (1, 2, 3, 4)" or "= 1"
*/
public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false);
}

View File

@@ -0,0 +1,443 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
use \Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Database Abstraction Layer
*/
class factory implements driver_interface
{
/**
* @var driver_interface
*/
protected $driver = null;
/**
* @var ContainerInterface
*/
protected $container;
/**
* Constructor.
*
* @param ContainerInterface $container A ContainerInterface instance
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/**
* Return the current driver (and retrieved it from the container if necessary)
*
* @return driver_interface
*/
protected function get_driver()
{
if ($this->driver === null)
{
$this->driver = $this->container->get('dbal.conn.driver');
}
return $this->driver;
}
/**
* Set the current driver
*
* @param driver_interface $driver
*/
public function set_driver(driver_interface $driver)
{
$this->driver = $driver;
}
/**
* {@inheritdoc}
*/
public function get_sql_layer()
{
return $this->get_driver()->get_sql_layer();
}
/**
* {@inheritdoc}
*/
public function get_db_name()
{
return $this->get_driver()->get_db_name();
}
/**
* {@inheritdoc}
*/
public function get_any_char()
{
return $this->get_driver()->get_any_char();
}
/**
* {@inheritdoc}
*/
public function get_one_char()
{
return $this->get_driver()->get_one_char();
}
/**
* {@inheritdoc}
*/
public function get_db_connect_id()
{
return $this->get_driver()->get_db_connect_id();
}
/**
* {@inheritdoc}
*/
public function get_sql_error_triggered()
{
return $this->get_driver()->get_sql_error_triggered();
}
/**
* {@inheritdoc}
*/
public function get_sql_error_sql()
{
return $this->get_driver()->get_sql_error_sql();
}
/**
* {@inheritdoc}
*/
public function get_transaction()
{
return $this->get_driver()->get_transaction();
}
/**
* {@inheritdoc}
*/
public function get_sql_time()
{
return $this->get_driver()->get_sql_time();
}
/**
* {@inheritdoc}
*/
public function get_sql_error_returned()
{
return $this->get_driver()->get_sql_error_returned();
}
/**
* {@inheritdoc}
*/
public function get_multi_insert()
{
return $this->get_driver()->get_multi_insert();
}
/**
* {@inheritdoc}
*/
public function set_multi_insert($multi_insert)
{
$this->get_driver()->set_multi_insert($multi_insert);
}
/**
* {@inheritdoc}
*/
public function get_row_count($table_name)
{
return $this->get_driver()->get_row_count($table_name);
}
/**
* {@inheritdoc}
*/
public function get_estimated_row_count($table_name)
{
return $this->get_driver()->get_estimated_row_count($table_name);
}
/**
* {@inheritdoc}
*/
public function sql_lower_text($column_name)
{
return $this->get_driver()->sql_lower_text($column_name);
}
/**
* {@inheritdoc}
*/
public function sql_error($sql = '')
{
return $this->get_driver()->sql_error($sql);
}
/**
* {@inheritdoc}
*/
public function sql_buffer_nested_transactions()
{
return $this->get_driver()->sql_buffer_nested_transactions();
}
/**
* {@inheritdoc}
*/
public function sql_bit_or($column_name, $bit, $compare = '')
{
return $this->get_driver()->sql_bit_or($column_name, $bit, $compare);
}
/**
* {@inheritdoc}
*/
public function sql_server_info($raw = false, $use_cache = true)
{
return $this->get_driver()->sql_server_info($raw, $use_cache);
}
/**
* {@inheritdoc}
*/
public function sql_return_on_error($fail = false)
{
return $this->get_driver()->sql_return_on_error($fail);
}
/**
* {@inheritdoc}
*/
public function sql_build_array($query, $assoc_ary = array())
{
return $this->get_driver()->sql_build_array($query, $assoc_ary);
}
/**
* {@inheritdoc}
*/
public function sql_fetchrowset($query_id = false)
{
return $this->get_driver()->sql_fetchrowset($query_id);
}
/**
* {@inheritdoc}
*/
public function sql_transaction($status = 'begin')
{
return $this->get_driver()->sql_transaction($status);
}
/**
* {@inheritdoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $this->get_driver()->sql_concatenate($expr1, $expr2);
}
/**
* {@inheritdoc}
*/
public function sql_case($condition, $action_true, $action_false = false)
{
return $this->get_driver()->sql_case($condition, $action_true, $action_false);
}
/**
* {@inheritdoc}
*/
public function sql_build_query($query, $array)
{
return $this->get_driver()->sql_build_query($query, $array);
}
/**
* {@inheritdoc}
*/
public function sql_fetchfield($field, $rownum = false, $query_id = false)
{
return $this->get_driver()->sql_fetchfield($field, $rownum, $query_id);
}
/**
* {@inheritdoc}
*/
public function sql_fetchrow($query_id = false)
{
return $this->get_driver()->sql_fetchrow($query_id);
}
/**
* {@inheritdoc}
*/
public function cast_expr_to_bigint($expression)
{
return $this->get_driver()->cast_expr_to_bigint($expression);
}
/**
* {@inheritdoc}
*/
public function sql_nextid()
{
return $this->get_driver()->sql_nextid();
}
/**
* {@inheritdoc}
*/
public function sql_add_num_queries($cached = false)
{
return $this->get_driver()->sql_add_num_queries($cached);
}
/**
* {@inheritdoc}
*/
public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
return $this->get_driver()->sql_query_limit($query, $total, $offset, $cache_ttl);
}
/**
* {@inheritdoc}
*/
public function sql_query($query = '', $cache_ttl = 0)
{
return $this->get_driver()->sql_query($query, $cache_ttl);
}
/**
* {@inheritdoc}
*/
public function cast_expr_to_string($expression)
{
return $this->get_driver()->cast_expr_to_string($expression);
}
/**
* {@inheritdoc}
*/
public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
throw new \Exception('Disabled method.');
}
/**
* {@inheritdoc}
*/
public function sql_bit_and($column_name, $bit, $compare = '')
{
return $this->get_driver()->sql_bit_and($column_name, $bit, $compare);
}
/**
* {@inheritdoc}
*/
public function sql_freeresult($query_id = false)
{
return $this->get_driver()->sql_freeresult($query_id);
}
/**
* {@inheritdoc}
*/
public function sql_num_queries($cached = false)
{
return $this->get_driver()->sql_num_queries($cached);
}
/**
* {@inheritdoc}
*/
public function sql_multi_insert($table, $sql_ary)
{
return $this->get_driver()->sql_multi_insert($table, $sql_ary);
}
/**
* {@inheritdoc}
*/
public function sql_affectedrows()
{
return $this->get_driver()->sql_affectedrows();
}
/**
* {@inheritdoc}
*/
public function sql_close()
{
return $this->get_driver()->sql_close();
}
/**
* {@inheritdoc}
*/
public function sql_rowseek($rownum, &$query_id)
{
return $this->get_driver()->sql_rowseek($rownum, $query_id);
}
/**
* {@inheritdoc}
*/
public function sql_escape($msg)
{
return $this->get_driver()->sql_escape($msg);
}
/**
* {@inheritdoc}
*/
public function sql_like_expression($expression)
{
return $this->get_driver()->sql_like_expression($expression);
}
/**
* {@inheritdoc}
*/
public function sql_not_like_expression($expression)
{
return $this->get_driver()->sql_not_like_expression($expression);
}
/**
* {@inheritdoc}
*/
public function sql_report($mode, $query = '')
{
return $this->get_driver()->sql_report($mode, $query);
}
/**
* {@inheritdoc}
*/
public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false)
{
return $this->get_driver()->sql_in_set($field, $array, $negate, $allow_empty_set);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* MSSQL Database Base Abstraction Layer
*/
abstract class mssql_base extends \phpbb\db\driver\driver
{
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return $expr1 . ' + ' . $expr2;
}
/**
* {@inheritDoc}
*/
function sql_escape($msg)
{
return str_replace(array("'", "\0"), array("''", ''), $msg);
}
/**
* {@inheritDoc}
*/
function sql_lower_text($column_name)
{
return "LOWER(SUBSTRING($column_name, 1, DATALENGTH($column_name)))";
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/**
* Build NOT LIKE expression
* @access private
*/
function _sql_not_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/**
* {@inheritDoc}
*/
function cast_expr_to_bigint($expression)
{
return 'CONVERT(BIGINT, ' . $expression . ')';
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
return $data;
}
}

View File

@@ -0,0 +1,385 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* Unified ODBC functions
* Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere...
* Here we only support MSSQL Server 2000+ because of the provided schema
*
* @note number of bytes returned for returning data depends on odbc.defaultlrl php.ini setting.
* If it is limited to 4K for example only 4K of data is returned max, resulting in incomplete theme data for example.
* @note odbc.defaultbinmode may affect UTF8 characters
*/
class mssql_odbc extends \phpbb\db\driver\mssql_base
{
var $last_query_text = '';
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
$this->persistency = $persistency;
$this->user = $sqluser;
$this->dbname = $database;
$port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':';
$this->server = $sqlserver . (($port) ? $port_delimiter . $port : '');
$max_size = @ini_get('odbc.defaultlrl');
if (!empty($max_size))
{
$unit = strtolower(substr($max_size, -1, 1));
$max_size = (int) $max_size;
if ($unit == 'k')
{
$max_size = floor($max_size / 1024);
}
else if ($unit == 'g')
{
$max_size *= 1024;
}
else if (is_numeric($unit))
{
$max_size = floor((int) ($max_size . $unit) / 1048576);
}
$max_size = max(8, $max_size) . 'M';
@ini_set('odbc.defaultlrl', $max_size);
}
if ($this->persistency)
{
if (!function_exists('odbc_pconnect'))
{
$this->connect_error = 'odbc_pconnect function does not exist, is odbc extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @odbc_pconnect($this->server, $this->user, $sqlpassword);
}
else
{
if (!function_exists('odbc_connect'))
{
$this->connect_error = 'odbc_connect function does not exist, is odbc extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @odbc_connect($this->server, $this->user, $sqlpassword);
}
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssqlodbc_version')) === false)
{
$result_id = @odbc_exec($this->db_connect_id, "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')");
$row = false;
if ($result_id)
{
$row = odbc_fetch_array($result_id);
odbc_free_result($result_id);
}
$this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0;
if (!empty($cache) && $use_cache)
{
$cache->put('mssqlodbc_version', $this->sql_server_version);
}
}
if ($raw)
{
return $this->sql_server_version;
}
return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)';
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return @odbc_exec($this->db_connect_id, 'BEGIN TRANSACTION');
break;
case 'commit':
return @odbc_exec($this->db_connect_id, 'COMMIT TRANSACTION');
break;
case 'rollback':
return @odbc_exec($this->db_connect_id, 'ROLLBACK TRANSACTION');
break;
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->last_query_text = $query;
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if (($this->query_result = @odbc_exec($this->db_connect_id, $query)) === false)
{
$this->sql_error($query);
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows)
if ($total)
{
// We need to grab the total number of rows + the offset number of rows to get the correct result
if (strpos($query, 'SELECT DISTINCT') === 0)
{
$query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15);
}
else
{
$query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6);
}
}
$result = $this->sql_query($query, $cache_ttl);
// Seek by $offset rows
if ($offset)
{
$this->sql_rowseek($offset, $result);
}
return $result;
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
return ($this->db_connect_id) ? @odbc_num_rows($this->query_result) : false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
return ($query_id) ? odbc_fetch_array($query_id) : false;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
$result_id = @odbc_exec($this->db_connect_id, 'SELECT @@IDENTITY');
if ($result_id)
{
if (odbc_fetch_array($result_id))
{
$id = odbc_result($result_id, 1);
odbc_free_result($result_id);
return $id;
}
odbc_free_result($result_id);
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
return odbc_free_result($query_id);
}
return false;
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
if (function_exists('odbc_errormsg'))
{
$error = array(
'message' => @odbc_errormsg(),
'code' => @odbc_error(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @odbc_close($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
switch ($mode)
{
case 'start':
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @odbc_exec($this->db_connect_id, $query);
if ($result)
{
while ($void = odbc_fetch_array($result))
{
// Take the time spent on parsing rows into account
}
odbc_free_result($result);
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,451 @@
<?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.
*
*/
/**
* This is the MS SQL Server Native database abstraction layer.
* PHP mssql native driver required.
* @author Chris Pucci
*
*/
namespace phpbb\db\driver;
class mssqlnative extends \phpbb\db\driver\mssql_base
{
var $m_insert_id = null;
var $last_query_text = '';
var $query_options = array();
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
// Test for driver support, to avoid suppressed fatal error
if (!function_exists('sqlsrv_connect'))
{
$this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx';
return $this->sql_error('');
}
//set up connection variables
$this->persistency = $persistency;
$this->user = $sqluser;
$this->dbname = $database;
$port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':';
$this->server = $sqlserver . (($port) ? $port_delimiter . $port : '');
//connect to database
$this->db_connect_id = sqlsrv_connect($this->server, array(
'Database' => $this->dbname,
'UID' => $this->user,
'PWD' => $sqlpassword,
'CharacterSet' => 'UTF-8'
));
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mssql_version')) === false)
{
$arr_server_info = sqlsrv_server_info($this->db_connect_id);
$this->sql_server_version = $arr_server_info['SQLServerVersion'];
if (!empty($cache) && $use_cache)
{
$cache->put('mssql_version', $this->sql_server_version);
}
}
if ($raw)
{
return $this->sql_server_version;
}
return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL';
}
/**
* {@inheritDoc}
*/
function sql_buffer_nested_transactions()
{
return true;
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return sqlsrv_begin_transaction($this->db_connect_id);
break;
case 'commit':
return sqlsrv_commit($this->db_connect_id);
break;
case 'rollback':
return sqlsrv_rollback($this->db_connect_id);
break;
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->last_query_text = $query;
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if (($this->query_result = @sqlsrv_query($this->db_connect_id, $query, array(), $this->query_options)) === false)
{
$this->sql_error($query);
}
// reset options for next query
$this->query_options = array();
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// total == 0 means all results - not zero results
if ($offset == 0 && $total !== 0)
{
if (strpos($query, "SELECT") === false)
{
$query = "TOP {$total} " . $query;
}
else
{
$query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP '.$total, $query);
}
}
else if ($offset > 0)
{
$query = preg_replace('/SELECT(\s*DISTINCT)?/Dsi', 'SELECT$1 TOP(10000000) ', $query);
$query = 'SELECT *
FROM (SELECT sub2.*, ROW_NUMBER() OVER(ORDER BY sub2.line2) AS line3
FROM (SELECT 1 AS line2, sub1.* FROM (' . $query . ') AS sub1) as sub2) AS sub3';
if ($total > 0)
{
$query .= ' WHERE line3 BETWEEN ' . ($offset+1) . ' AND ' . ($offset + $total);
}
else
{
$query .= ' WHERE line3 > ' . $offset;
}
}
$result = $this->sql_query($query, $cache_ttl);
return $result;
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->query_result) : false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
if (!$query_id)
{
return false;
}
$row = sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC);
if ($row)
{
foreach ($row as $key => $value)
{
$row[$key] = ($value === ' ' || $value === null) ? '' : $value;
}
// remove helper values from LIMIT queries
if (isset($row['line2']))
{
unset($row['line2'], $row['line3']);
}
}
return ($row !== null) ? $row : false;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
$result_id = @sqlsrv_query($this->db_connect_id, 'SELECT @@IDENTITY');
if ($result_id)
{
$row = sqlsrv_fetch_array($result_id);
$id = $row[0];
sqlsrv_free_stmt($result_id);
return $id;
}
else
{
return false;
}
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
return sqlsrv_free_stmt($query_id);
}
return false;
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
if (function_exists('sqlsrv_errors'))
{
$errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS);
$error_message = '';
$code = 0;
if ($errors != null)
{
foreach ($errors as $error)
{
$error_message .= "SQLSTATE: " . $error['SQLSTATE'] . "\n";
$error_message .= "code: " . $error['code'] . "\n";
$code = $error['code'];
$error_message .= "message: " . $error['message'] . "\n";
}
$this->last_error_result = $error_message;
$error = $this->last_error_result;
}
else
{
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
}
$error = array(
'message' => $error,
'code' => $code,
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @sqlsrv_close($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
switch ($mode)
{
case 'start':
$html_table = false;
@sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT ON;');
if ($result = @sqlsrv_query($this->db_connect_id, $query))
{
sqlsrv_next_result($result);
while ($row = sqlsrv_fetch_array($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
sqlsrv_free_stmt($result);
}
@sqlsrv_query($this->db_connect_id, 'SET SHOWPLAN_TEXT OFF;');
if ($html_table)
{
$this->html_hold .= '</table>';
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @sqlsrv_query($this->db_connect_id, $query);
if ($result)
{
while ($void = sqlsrv_fetch_array($result))
{
// Take the time spent on parsing rows into account
}
sqlsrv_free_stmt($result);
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
/**
* Utility method used to retrieve number of rows
* Emulates mysql_num_rows
* Used in acp_database.php -> write_data_mssqlnative()
* Requires a static or keyset cursor to be definde via
* mssqlnative_set_query_options()
*/
function mssqlnative_num_rows($res)
{
if ($res !== false)
{
return sqlsrv_num_rows($res);
}
else
{
return false;
}
}
/**
* Allows setting mssqlnative specific query options passed to sqlsrv_query as 4th parameter.
*/
function mssqlnative_set_query_options($options)
{
$this->query_options = $options;
}
}

View File

@@ -0,0 +1,503 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* MySQL4 Database Abstraction Layer
* Compatible with:
* MySQL 3.23+
* MySQL 4.0+
* MySQL 4.1+
* MySQL 5.0+
*/
class mysql extends \phpbb\db\driver\mysql_base
{
var $multi_insert = true;
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
$this->persistency = $persistency;
$this->user = $sqluser;
$this->server = $sqlserver . (($port) ? ':' . $port : '');
$this->dbname = $database;
$this->sql_layer = 'mysql4';
if ($this->persistency)
{
if (!function_exists('mysql_pconnect'))
{
$this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword);
}
else
{
if (!function_exists('mysql_connect'))
{
$this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link);
}
if ($this->db_connect_id && $this->dbname != '')
{
if (@mysql_select_db($this->dbname, $this->db_connect_id))
{
// Determine what version we are using and if it natively supports UNICODE
if (version_compare($this->sql_server_info(true), '4.1.0', '>='))
{
@mysql_query("SET NAMES 'utf8'", $this->db_connect_id);
// enforce strict mode on databases that support it
if (version_compare($this->sql_server_info(true), '5.0.2', '>='))
{
$result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id);
if ($result)
{
$row = mysql_fetch_assoc($result);
mysql_free_result($result);
$modes = array_map('trim', explode(',', $row['sql_mode']));
}
else
{
$modes = array();
}
// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
if (!in_array('TRADITIONAL', $modes))
{
if (!in_array('STRICT_ALL_TABLES', $modes))
{
$modes[] = 'STRICT_ALL_TABLES';
}
if (!in_array('STRICT_TRANS_TABLES', $modes))
{
$modes[] = 'STRICT_TRANS_TABLES';
}
}
$mode = implode(',', $modes);
@mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id);
}
}
else if (version_compare($this->sql_server_info(true), '4.0.0', '<'))
{
$this->sql_layer = 'mysql';
}
return $this->db_connect_id;
}
}
return $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysql_version')) === false)
{
$result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id);
if ($result)
{
$row = mysql_fetch_assoc($result);
mysql_free_result($result);
$this->sql_server_version = $row['version'];
if (!empty($cache) && $use_cache)
{
$cache->put('mysql_version', $this->sql_server_version);
}
}
}
return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version;
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return @mysql_query('BEGIN', $this->db_connect_id);
break;
case 'commit':
return @mysql_query('COMMIT', $this->db_connect_id);
break;
case 'rollback':
return @mysql_query('ROLLBACK', $this->db_connect_id);
break;
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if (($this->query_result = @mysql_query($query, $this->db_connect_id)) === false)
{
$this->sql_error($query);
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
if ($this->db_connect_id)
{
// We always want the number of matched rows
// instead of changed rows, when running an update.
// So when mysql_info() returns the number of matched rows
// we return that one instead of mysql_affected_rows()
$mysql_info = @mysql_info($this->db_connect_id);
if ($mysql_info !== false)
{
$match = array();
preg_match('#^Rows matched: (\d)+ Changed: (\d)+ Warnings: (\d)+$#', $mysql_info, $match);
if (isset($match[1]))
{
return $match[1];
}
}
return @mysql_affected_rows($this->db_connect_id);
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
return ($query_id) ? mysql_fetch_assoc($query_id) : false;
}
/**
* {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
return ($query_id !== false) ? @mysql_data_seek($query_id, $rownum) : false;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false;
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
return mysql_free_result($query_id);
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_escape($msg)
{
if (!$this->db_connect_id)
{
return @mysql_real_escape_string($msg);
}
return @mysql_real_escape_string($msg, $this->db_connect_id);
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
if ($this->db_connect_id)
{
$error = array(
'message' => @mysql_error($this->db_connect_id),
'code' => @mysql_errno($this->db_connect_id),
);
}
else if (function_exists('mysql_error'))
{
$error = array(
'message' => @mysql_error(),
'code' => @mysql_errno(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @mysql_close($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
static $test_prof;
// current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING
if ($test_prof === null)
{
$test_prof = false;
if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<'))
{
$test_prof = true;
}
}
switch ($mode)
{
case 'start':
$explain_query = $query;
if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
if (preg_match('/^SELECT/', $explain_query))
{
$html_table = false;
// begin profiling
if ($test_prof)
{
@mysql_query('SET profiling = 1;', $this->db_connect_id);
}
if ($result = @mysql_query("EXPLAIN $explain_query", $this->db_connect_id))
{
while ($row = mysql_fetch_assoc($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
mysql_free_result($result);
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
if ($test_prof)
{
$html_table = false;
// get the last profile
if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id))
{
$this->html_hold .= '<br />';
while ($row = mysql_fetch_assoc($result))
{
// make <unknown> HTML safe
if (!empty($row['Source_function']))
{
$row['Source_function'] = str_replace(array('<', '>'), array('&lt;', '&gt;'), $row['Source_function']);
}
// remove unsupported features
foreach ($row as $key => $val)
{
if ($val === null)
{
unset($row[$key]);
}
}
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
mysql_free_result($result);
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
@mysql_query('SET profiling = 0;', $this->db_connect_id);
}
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @mysql_query($query, $this->db_connect_id);
if ($result)
{
while ($void = mysql_fetch_assoc($result))
{
// Take the time spent on parsing rows into account
}
mysql_free_result($result);
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* Abstract MySQL Database Base Abstraction Layer
*/
abstract class mysql_base extends \phpbb\db\driver\driver
{
/**
* {@inheritDoc}
*/
public function sql_concatenate($expr1, $expr2)
{
return 'CONCAT(' . $expr1 . ', ' . $expr2 . ')';
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
// MySQL 4.1+ no longer supports -1 in limit queries
$total = '18446744073709551615';
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
return $this->sql_query($query, $cache_ttl);
}
/**
* {@inheritDoc}
*/
function get_estimated_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']))
{
if ($table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
{
return '~' . $table_status['Rows'];
}
}
return parent::get_row_count($table_name);
}
/**
* {@inheritDoc}
*/
function get_row_count($table_name)
{
$table_status = $this->get_table_status($table_name);
if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
{
return $table_status['Rows'];
}
return parent::get_row_count($table_name);
}
/**
* Gets some information about the specified table.
*
* @param string $table_name Table name
*
* @return array
*
* @access protected
*/
function get_table_status($table_name)
{
$sql = "SHOW TABLE STATUS
LIKE '" . $this->sql_escape($table_name) . "'";
$result = $this->sql_query($sql);
$table_status = $this->sql_fetchrow($result);
$this->sql_freeresult($result);
return $table_status;
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build NOT LIKE expression
* @access private
*/
function _sql_not_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
switch ($stage)
{
case 'FROM':
$data = '(' . $data . ')';
break;
}
return $data;
}
}

View File

@@ -0,0 +1,490 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* MySQLi Database Abstraction Layer
* mysqli-extension has to be compiled with:
* MySQL 4.1+ or MySQL 5.0+
*/
class mysqli extends \phpbb\db\driver\mysql_base
{
var $multi_insert = true;
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
if (!function_exists('mysqli_connect'))
{
$this->connect_error = 'mysqli_connect function does not exist, is mysqli extension installed?';
return $this->sql_error('');
}
$this->persistency = $persistency;
$this->user = $sqluser;
// If persistent connection, set dbhost to localhost when empty and prepend it with 'p:' prefix
$this->server = ($this->persistency) ? 'p:' . (($sqlserver) ? $sqlserver : 'localhost') : $sqlserver;
$this->dbname = $database;
$port = (!$port) ? null : $port;
// If port is set and it is not numeric, most likely mysqli socket is set.
// Try to map it to the $socket parameter.
$socket = null;
if ($port)
{
if (is_numeric($port))
{
$port = (int) $port;
}
else
{
$socket = $port;
$port = null;
}
}
$this->db_connect_id = mysqli_init();
if (!@mysqli_real_connect($this->db_connect_id, $this->server, $this->user, $sqlpassword, $this->dbname, $port, $socket, MYSQLI_CLIENT_FOUND_ROWS))
{
$this->db_connect_id = '';
}
if ($this->db_connect_id && $this->dbname != '')
{
@mysqli_query($this->db_connect_id, "SET NAMES 'utf8'");
// enforce strict mode on databases that support it
if (version_compare($this->sql_server_info(true), '5.0.2', '>='))
{
$result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode');
if ($result)
{
$row = mysqli_fetch_assoc($result);
mysqli_free_result($result);
$modes = array_map('trim', explode(',', $row['sql_mode']));
}
else
{
$modes = array();
}
// TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES
if (!in_array('TRADITIONAL', $modes))
{
if (!in_array('STRICT_ALL_TABLES', $modes))
{
$modes[] = 'STRICT_ALL_TABLES';
}
if (!in_array('STRICT_TRANS_TABLES', $modes))
{
$modes[] = 'STRICT_TRANS_TABLES';
}
}
$mode = implode(',', $modes);
@mysqli_query($this->db_connect_id, "SET SESSION sql_mode='{$mode}'");
}
return $this->db_connect_id;
}
return $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('mysqli_version')) === false)
{
$result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version');
if ($result)
{
$row = mysqli_fetch_assoc($result);
mysqli_free_result($result);
$this->sql_server_version = $row['version'];
if (!empty($cache) && $use_cache)
{
$cache->put('mysqli_version', $this->sql_server_version);
}
}
}
return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version;
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return @mysqli_autocommit($this->db_connect_id, false);
break;
case 'commit':
$result = @mysqli_commit($this->db_connect_id);
@mysqli_autocommit($this->db_connect_id, true);
return $result;
break;
case 'rollback':
$result = @mysqli_rollback($this->db_connect_id);
@mysqli_autocommit($this->db_connect_id, true);
return $result;
break;
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if (($this->query_result = @mysqli_query($this->db_connect_id, $query)) === false)
{
$this->sql_error($query);
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
return ($this->db_connect_id) ? @mysqli_affected_rows($this->db_connect_id) : false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
if ($query_id)
{
$result = mysqli_fetch_assoc($query_id);
return $result !== null ? $result : false;
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
return ($query_id) ? @mysqli_data_seek($query_id, $rownum) : false;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
return ($this->db_connect_id) ? @mysqli_insert_id($this->db_connect_id) : false;
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (!$query_id)
{
return false;
}
if ($query_id === true)
{
return true;
}
return mysqli_free_result($query_id);
}
/**
* {@inheritDoc}
*/
function sql_escape($msg)
{
return @mysqli_real_escape_string($this->db_connect_id, $msg);
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
if ($this->db_connect_id)
{
$error = array(
'message' => @mysqli_error($this->db_connect_id),
'code' => @mysqli_errno($this->db_connect_id)
);
}
else if (function_exists('mysqli_connect_error'))
{
$error = array(
'message' => @mysqli_connect_error(),
'code' => @mysqli_connect_errno(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @mysqli_close($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
static $test_prof;
// current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING
if ($test_prof === null)
{
$test_prof = false;
if (strpos(mysqli_get_server_info($this->db_connect_id), 'community') !== false)
{
$ver = mysqli_get_server_version($this->db_connect_id);
if ($ver >= 50037 && $ver < 50100)
{
$test_prof = true;
}
}
}
switch ($mode)
{
case 'start':
$explain_query = $query;
if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
if (preg_match('/^SELECT/', $explain_query))
{
$html_table = false;
// begin profiling
if ($test_prof)
{
@mysqli_query($this->db_connect_id, 'SET profiling = 1;');
}
if ($result = @mysqli_query($this->db_connect_id, "EXPLAIN $explain_query"))
{
while ($row = mysqli_fetch_assoc($result))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
mysqli_free_result($result);
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
if ($test_prof)
{
$html_table = false;
// get the last profile
if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;'))
{
$this->html_hold .= '<br />';
while ($row = mysqli_fetch_assoc($result))
{
// make <unknown> HTML safe
if (!empty($row['Source_function']))
{
$row['Source_function'] = str_replace(array('<', '>'), array('&lt;', '&gt;'), $row['Source_function']);
}
// remove unsupported features
foreach ($row as $key => $val)
{
if ($val === null)
{
unset($row[$key]);
}
}
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
mysqli_free_result($result);
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
@mysqli_query($this->db_connect_id, 'SET profiling = 0;');
}
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @mysqli_query($this->db_connect_id, $query);
if ($result)
{
while ($void = mysqli_fetch_assoc($result))
{
// Take the time spent on parsing rows into account
}
mysqli_free_result($result);
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,822 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* Oracle Database Abstraction Layer
*/
class oracle extends \phpbb\db\driver\driver
{
var $last_query_text = '';
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
$this->persistency = $persistency;
$this->user = $sqluser;
$this->server = $sqlserver . (($port) ? ':' . $port : '');
$this->dbname = $database;
$connect = $database;
// support for "easy connect naming"
if ($sqlserver !== '' && $sqlserver !== '/')
{
if (substr($sqlserver, -1, 1) == '/')
{
$sqlserver == substr($sqlserver, 0, -1);
}
$connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database;
}
if ($new_link)
{
if (!function_exists('ocinlogon'))
{
$this->connect_error = 'ocinlogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8');
}
else if ($this->persistency)
{
if (!function_exists('ociplogon'))
{
$this->connect_error = 'ociplogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8');
}
else
{
if (!function_exists('ocilogon'))
{
$this->connect_error = 'ocilogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8');
}
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
/**
* force $use_cache false. I didn't research why the caching code below is commented out
* but I assume its because the Oracle extension provides a direct method to access it
* without a query.
*/
/*
global $cache;
if (empty($cache) || ($this->sql_server_version = $cache->get('oracle_version')) === false)
{
$result = @ociparse($this->db_connect_id, 'SELECT * FROM v$version WHERE banner LIKE \'Oracle%\'');
@ociexecute($result, OCI_DEFAULT);
@ocicommit($this->db_connect_id);
$row = array();
@ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS);
@ocifreestatement($result);
$this->sql_server_version = trim($row['BANNER']);
$cache->put('oracle_version', $this->sql_server_version);
}
*/
$this->sql_server_version = @ociserverversion($this->db_connect_id);
return $this->sql_server_version;
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return true;
break;
case 'commit':
return @ocicommit($this->db_connect_id);
break;
case 'rollback':
return @ocirollback($this->db_connect_id);
break;
}
return true;
}
/**
* Oracle specific code to handle the fact that it does not compare columns properly
* @access private
*/
function _rewrite_col_compare($args)
{
if (count($args) == 4)
{
if ($args[2] == '=')
{
return '(' . $args[0] . ' OR (' . $args[1] . ' is NULL AND ' . $args[3] . ' is NULL))';
}
else if ($args[2] == '<>')
{
// really just a fancy way of saying foo <> bar or (foo is NULL XOR bar is NULL) but SQL has no XOR :P
return '(' . $args[0] . ' OR ((' . $args[1] . ' is NULL AND ' . $args[3] . ' is NOT NULL) OR (' . $args[1] . ' is NOT NULL AND ' . $args[3] . ' is NULL)))';
}
}
else
{
return $this->_rewrite_where($args[0]);
}
}
/**
* Oracle specific code to handle it's lack of sanity
* @access private
*/
function _rewrite_where($where_clause)
{
preg_match_all('/\s*(AND|OR)?\s*([\w_.()]++)\s*(?:(=|<[=>]?|>=?|LIKE)\s*((?>\'(?>[^\']++|\'\')*+\'|[\d-.()]+))|((NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))/', $where_clause, $result, PREG_SET_ORDER);
$out = '';
foreach ($result as $val)
{
if (!isset($val[5]))
{
if ($val[4] !== "''")
{
$out .= $val[0];
}
else
{
$out .= ' ' . $val[1] . ' ' . $val[2];
if ($val[3] == '=')
{
$out .= ' is NULL';
}
else if ($val[3] == '<>')
{
$out .= ' is NOT NULL';
}
}
}
else
{
$in_clause = array();
$sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1);
$extra = false;
preg_match_all('/\'(?>[^\']++|\'\')*+\'|[\d-.]++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER);
$i = 0;
foreach ($sub_vals[0] as $sub_val)
{
// two things:
// 1) This determines if an empty string was in the IN clausing, making us turn it into a NULL comparison
// 2) This fixes the 1000 list limit that Oracle has (ORA-01795)
if ($sub_val !== "''")
{
$in_clause[(int) $i++/1000][] = $sub_val;
}
else
{
$extra = true;
}
}
if (!$extra && $i < 1000)
{
$out .= $val[0];
}
else
{
$out .= ' ' . $val[1] . '(';
$in_array = array();
// constuct each IN() clause
foreach ($in_clause as $in_values)
{
$in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')';
}
// Join the IN() clauses against a few ORs (IN is just a nicer OR anyway)
$out .= implode(' OR ', $in_array);
// handle the empty string case
if ($extra)
{
$out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL';
}
$out .= ')';
unset($in_array, $in_clause);
}
}
}
return $out;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->last_query_text = $query;
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
$in_transaction = false;
if (!$this->transaction)
{
$this->sql_transaction('begin');
}
else
{
$in_transaction = true;
}
$array = array();
// We overcome Oracle's 4000 char limit by binding vars
if (strlen($query) > 4000)
{
if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/sU', $query, $regs))
{
if (strlen($regs[3]) > 4000)
{
$cols = explode(', ', $regs[2]);
preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER);
/* The code inside this comment block breaks clob handling, but does allow the
database restore script to work. If you want to allow no posts longer than 4KB
and/or need the db restore script, uncomment this.
if (count($cols) !== count($vals))
{
// Try to replace some common data we know is from our restore script or from other sources
$regs[3] = str_replace("'||chr(47)||'", '/', $regs[3]);
$_vals = explode(', ', $regs[3]);
$vals = array();
$is_in_val = false;
$i = 0;
$string = '';
foreach ($_vals as $value)
{
if (strpos($value, "'") === false && !$is_in_val)
{
$vals[$i++] = $value;
continue;
}
if (substr($value, -1) === "'")
{
$vals[$i] = $string . (($is_in_val) ? ', ' : '') . $value;
$string = '';
$is_in_val = false;
if ($vals[$i][0] !== "'")
{
$vals[$i] = "''" . $vals[$i];
}
$i++;
continue;
}
else
{
$string .= (($is_in_val) ? ', ' : '') . $value;
$is_in_val = true;
}
}
if ($string)
{
// New value if cols != value
$vals[(count($cols) !== count($vals)) ? $i : $i - 1] .= $string;
}
$vals = array(0 => $vals);
}
*/
$inserts = $vals[0];
unset($vals);
foreach ($inserts as $key => $value)
{
if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) // check to see if this thing is greater than the max + 'x2
{
$inserts[$key] = ':' . strtoupper($cols[$key]);
$array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1));
}
}
$query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')';
}
}
else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER))
{
if (strlen($data[0][2]) > 4000)
{
$update = $data[0][1];
$where = $data[0][3];
preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER);
unset($data);
$cols = array();
foreach ($temp as $value)
{
if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) // check to see if this thing is greater than the max + 'x2
{
$cols[] = $value[1] . '=:' . strtoupper($value[1]);
$array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1));
}
else
{
$cols[] = $value[1] . '=' . $value[2];
}
}
$query = $update . implode(', ', $cols) . ' ' . $where;
unset($cols);
}
}
}
switch (substr($query, 0, 6))
{
case 'DELETE':
if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs))
{
$query = $regs[1] . $this->_rewrite_where($regs[2]);
unset($regs);
}
break;
case 'UPDATE':
if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s', $query, $regs))
{
$query = $regs[1] . $this->_rewrite_where($regs[2]);
unset($regs);
}
break;
case 'SELECT':
$query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query);
break;
}
$this->query_result = @ociparse($this->db_connect_id, $query);
foreach ($array as $key => $value)
{
@ocibindbyname($this->query_result, $key, $array[$key], -1);
}
$success = @ociexecute($this->query_result, OCI_DEFAULT);
if (!$success)
{
$this->sql_error($query);
$this->query_result = false;
}
else
{
if (!$in_transaction)
{
$this->sql_transaction('commit');
}
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
$query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset;
return $this->sql_query($query, $cache_ttl);
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
return ($this->query_result) ? @ocirowcount($this->query_result) : false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
if ($query_id)
{
$row = array();
$result = ocifetchinto($query_id, $row, OCI_ASSOC + OCI_RETURN_NULLS);
if (!$result || !$row)
{
return false;
}
$result_row = array();
foreach ($row as $key => $value)
{
// Oracle treats empty strings as null
if (is_null($value))
{
$value = '';
}
// OCI->CLOB?
if (is_object($value))
{
$value = $value->load();
}
$result_row[strtolower($key)] = $value;
}
return $result_row;
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
if (!$query_id)
{
return false;
}
// Reset internal pointer
@ociexecute($query_id, OCI_DEFAULT);
// We do not fetch the row for rownum == 0 because then the next resultset would be the second row
for ($i = 0; $i < $rownum; $i++)
{
if (!$this->sql_fetchrow($query_id))
{
return false;
}
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
$query_id = $this->query_result;
if ($query_id !== false && $this->last_query_text != '')
{
if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename))
{
$query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL';
$stmt = @ociparse($this->db_connect_id, $query);
if ($stmt)
{
$success = @ociexecute($stmt, OCI_DEFAULT);
if ($success)
{
$temp_result = ocifetchinto($stmt, $temp_array, OCI_ASSOC + OCI_RETURN_NULLS);
ocifreestatement($stmt);
if ($temp_result)
{
return $temp_array['CURRVAL'];
}
else
{
return false;
}
}
}
}
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
return ocifreestatement($query_id);
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_escape($msg)
{
return str_replace(array("'", "\0"), array("''", ''), $msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
/**
* Build NOT LIKE expression
* @access private
*/
function _sql_not_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
function _sql_custom_build($stage, $data)
{
return $data;
}
function _sql_bit_and($column_name, $bit, $compare = '')
{
return 'BITAND(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
}
function _sql_bit_or($column_name, $bit, $compare = '')
{
return 'BITOR(' . $column_name . ', ' . (1 << $bit) . ')' . (($compare) ? ' ' . $compare : '');
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
if (function_exists('ocierror'))
{
$error = @ocierror();
$error = (!$error) ? @ocierror($this->query_result) : $error;
$error = (!$error) ? @ocierror($this->db_connect_id) : $error;
if ($error)
{
$this->last_error_result = $error;
}
else
{
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
}
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @ocilogoff($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
switch ($mode)
{
case 'start':
$html_table = false;
// Grab a plan table, any will do
$sql = "SELECT table_name
FROM USER_TABLES
WHERE table_name LIKE '%PLAN_TABLE%'";
$stmt = ociparse($this->db_connect_id, $sql);
ociexecute($stmt);
$result = array();
if (ocifetchinto($stmt, $result, OCI_ASSOC + OCI_RETURN_NULLS))
{
$table = $result['TABLE_NAME'];
// This is the statement_id that will allow us to track the plan
$statement_id = substr(md5($query), 0, 30);
// Remove any stale plans
$stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
ociexecute($stmt2);
ocifreestatement($stmt2);
// Explain the plan
$sql = "EXPLAIN PLAN
SET STATEMENT_ID = '$statement_id'
FOR $query";
$stmt2 = ociparse($this->db_connect_id, $sql);
ociexecute($stmt2);
ocifreestatement($stmt2);
// Get the data from the plan
$sql = "SELECT operation, options, object_name, object_type, cardinality, cost
FROM plan_table
START WITH id = 0 AND statement_id = '$statement_id'
CONNECT BY PRIOR id = parent_id
AND statement_id = '$statement_id'";
$stmt2 = ociparse($this->db_connect_id, $sql);
ociexecute($stmt2);
$row = array();
while (ocifetchinto($stmt2, $row, OCI_ASSOC + OCI_RETURN_NULLS))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
ocifreestatement($stmt2);
// Remove the plan we just made, we delete them on request anyway
$stmt2 = ociparse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'");
ociexecute($stmt2);
ocifreestatement($stmt2);
}
ocifreestatement($stmt);
if ($html_table)
{
$this->html_hold .= '</table>';
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @ociparse($this->db_connect_id, $query);
if ($result)
{
$success = @ociexecute($result, OCI_DEFAULT);
if ($success)
{
$row = array();
while (ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS))
{
// Take the time spent on parsing rows into account
}
@ocifreestatement($result);
}
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,501 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* PostgreSQL Database Abstraction Layer
* Minimum Requirement is Version 8.3+
*/
class postgres extends \phpbb\db\driver\driver
{
var $multi_insert = true;
var $last_query_text = '';
var $connect_error = '';
/**
* {@inheritDoc}
*/
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
$connect_string = '';
if ($sqluser)
{
$connect_string .= "user=$sqluser ";
}
if ($sqlpassword)
{
$connect_string .= "password=$sqlpassword ";
}
if ($sqlserver)
{
// $sqlserver can carry a port separated by : for compatibility reasons
// If $sqlserver has more than one : it's probably an IPv6 address.
// In this case we only allow passing a port via the $port variable.
if (substr_count($sqlserver, ':') === 1)
{
list($sqlserver, $port) = explode(':', $sqlserver);
}
if ($sqlserver !== 'localhost')
{
$connect_string .= "host=$sqlserver ";
}
if ($port)
{
$connect_string .= "port=$port ";
}
}
$schema = '';
if ($database)
{
$this->dbname = $database;
if (strpos($database, '.') !== false)
{
list($database, $schema) = explode('.', $database);
}
$connect_string .= "dbname=$database";
}
$this->persistency = $persistency;
if ($this->persistency)
{
if (!function_exists('pg_pconnect'))
{
$this->connect_error = 'pg_pconnect function does not exist, is pgsql extension installed?';
return $this->sql_error('');
}
$collector = new \phpbb\error_collector;
$collector->install();
$this->db_connect_id = (!$new_link) ? @pg_pconnect($connect_string) : @pg_pconnect($connect_string, PGSQL_CONNECT_FORCE_NEW);
}
else
{
if (!function_exists('pg_connect'))
{
$this->connect_error = 'pg_connect function does not exist, is pgsql extension installed?';
return $this->sql_error('');
}
$collector = new \phpbb\error_collector;
$collector->install();
$this->db_connect_id = (!$new_link) ? @pg_connect($connect_string) : @pg_connect($connect_string, PGSQL_CONNECT_FORCE_NEW);
}
$collector->uninstall();
if ($this->db_connect_id)
{
if ($schema !== '')
{
@pg_query($this->db_connect_id, 'SET search_path TO ' . $schema);
}
return $this->db_connect_id;
}
$this->connect_error = $collector->format_errors();
return $this->sql_error('');
}
/**
* {@inheritDoc}
*/
function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('pgsql_version')) === false)
{
$query_id = @pg_query($this->db_connect_id, 'SELECT VERSION() AS version');
if ($query_id)
{
$row = pg_fetch_assoc($query_id, null);
pg_free_result($query_id);
$this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0;
if (!empty($cache) && $use_cache)
{
$cache->put('pgsql_version', $this->sql_server_version);
}
}
}
return ($raw) ? $this->sql_server_version : 'PostgreSQL ' . $this->sql_server_version;
}
/**
* SQL Transaction
* @access private
*/
function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return @pg_query($this->db_connect_id, 'BEGIN');
break;
case 'commit':
return @pg_query($this->db_connect_id, 'COMMIT');
break;
case 'rollback':
return @pg_query($this->db_connect_id, 'ROLLBACK');
break;
}
return true;
}
/**
* {@inheritDoc}
*/
function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->last_query_text = $query;
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if (($this->query_result = @pg_query($this->db_connect_id, $query)) === false)
{
$this->sql_error($query);
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
else if (strpos($query, 'SELECT') === 0)
{
$this->open_queries[(int) $this->query_result] = $this->query_result;
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* Build db-specific query data
* @access private
*/
function _sql_custom_build($stage, $data)
{
return $data;
}
/**
* Build LIMIT query
*/
function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
$total = 'ALL';
}
$query .= "\n LIMIT $total OFFSET $offset";
return $this->sql_query($query, $cache_ttl);
}
/**
* {@inheritDoc}
*/
function sql_affectedrows()
{
return ($this->query_result) ? @pg_affected_rows($this->query_result) : false;
}
/**
* {@inheritDoc}
*/
function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
return ($query_id) ? pg_fetch_assoc($query_id, null) : false;
}
/**
* {@inheritDoc}
*/
function sql_rowseek($rownum, &$query_id)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && $cache->sql_exists($query_id))
{
return $cache->sql_rowseek($rownum, $query_id);
}
return ($query_id) ? @pg_result_seek($query_id, $rownum) : false;
}
/**
* {@inheritDoc}
*/
function sql_nextid()
{
$query_id = $this->query_result;
if ($query_id !== false && $this->last_query_text != '')
{
if (preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text, $tablename))
{
$query = "SELECT currval('" . $tablename[1] . "_seq') AS last_value";
$temp_q_id = @pg_query($this->db_connect_id, $query);
if (!$temp_q_id)
{
return false;
}
$temp_result = pg_fetch_assoc($temp_q_id, null);
pg_free_result($query_id);
return ($temp_result) ? $temp_result['last_value'] : false;
}
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if (isset($this->open_queries[(int) $query_id]))
{
unset($this->open_queries[(int) $query_id]);
return pg_free_result($query_id);
}
return false;
}
/**
* {@inheritDoc}
*/
function sql_escape($msg)
{
return @pg_escape_string($msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build NOT LIKE expression
* @access private
*/
function _sql_not_like_expression($expression)
{
return $expression;
}
/**
* {@inheritDoc}
*/
function cast_expr_to_bigint($expression)
{
return 'CAST(' . $expression . ' as DECIMAL(255, 0))';
}
/**
* {@inheritDoc}
*/
function cast_expr_to_string($expression)
{
return 'CAST(' . $expression . ' as VARCHAR(255))';
}
/**
* return sql error array
* @access private
*/
function _sql_error()
{
// pg_last_error only works when there is an established connection.
// Connection errors have to be tracked by us manually.
if ($this->db_connect_id)
{
$message = @pg_last_error($this->db_connect_id);
}
else
{
$message = $this->connect_error;
}
return array(
'message' => $message,
'code' => ''
);
}
/**
* Close sql connection
* @access private
*/
function _sql_close()
{
return @pg_close($this->db_connect_id);
}
/**
* Build db-specific report
* @access private
*/
function _sql_report($mode, $query = '')
{
switch ($mode)
{
case 'start':
$explain_query = $query;
if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
if (preg_match('/^SELECT/', $explain_query))
{
$html_table = false;
if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query"))
{
while ($row = pg_fetch_assoc($result, null))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
pg_free_result($result);
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = @pg_query($this->db_connect_id, $query);
if ($result)
{
while ($void = pg_fetch_assoc($result, null))
{
// Take the time spent on parsing rows into account
}
pg_free_result($result);
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,431 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\driver;
/**
* SQLite3 Database Abstraction Layer
* Minimum Requirement: 3.6.15+
*/
class sqlite3 extends \phpbb\db\driver\driver
{
/**
* @var string Stores errors during connection setup in case the driver is not available
*/
protected $connect_error = '';
/**
* @var \SQLite3 The SQLite3 database object to operate against
*/
protected $dbo = null;
/**
* {@inheritDoc}
*/
public function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{
$this->persistency = false;
$this->user = $sqluser;
$this->server = $sqlserver . (($port) ? ':' . $port : '');
$this->dbname = $database;
if (!class_exists('SQLite3', false))
{
$this->connect_error = 'SQLite3 not found, is the extension installed?';
return $this->sql_error('');
}
try
{
$this->dbo = new \SQLite3($this->server, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE);
$this->dbo->busyTimeout(60000);
$this->db_connect_id = true;
}
catch (\Exception $e)
{
$this->connect_error = $e->getMessage();
return array('message' => $this->connect_error);
}
return true;
}
/**
* {@inheritDoc}
*/
public function sql_server_info($raw = false, $use_cache = true)
{
global $cache;
if (!$use_cache || empty($cache) || ($this->sql_server_version = $cache->get('sqlite_version')) === false)
{
$version = \SQLite3::version();
$this->sql_server_version = $version['versionString'];
if (!empty($cache) && $use_cache)
{
$cache->put('sqlite_version', $this->sql_server_version);
}
}
return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version;
}
/**
* SQL Transaction
*
* @param string $status Should be one of the following strings:
* begin, commit, rollback
* @return bool Success/failure of the transaction query
*/
protected function _sql_transaction($status = 'begin')
{
switch ($status)
{
case 'begin':
return $this->dbo->exec('BEGIN IMMEDIATE');
break;
case 'commit':
return $this->dbo->exec('COMMIT');
break;
case 'rollback':
return @$this->dbo->exec('ROLLBACK');
break;
}
return true;
}
/**
* {@inheritDoc}
*/
public function sql_query($query = '', $cache_ttl = 0)
{
if ($query != '')
{
global $cache;
// EXPLAIN only in extra debug mode
if (defined('DEBUG'))
{
$this->sql_report('start', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->curtime = microtime(true);
}
$this->last_query_text = $query;
$this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result);
if ($this->query_result === false)
{
if ($this->transaction === true && strpos($query, 'INSERT') === 0)
{
$query = preg_replace('/^INSERT INTO/', 'INSERT OR ROLLBACK INTO', $query);
}
if (($this->query_result = @$this->dbo->query($query)) === false)
{
// Try to recover a lost database connection
if ($this->dbo && !@$this->dbo->lastErrorMsg())
{
if ($this->sql_connect($this->server, $this->user, '', $this->dbname))
{
$this->query_result = @$this->dbo->query($query);
}
}
if ($this->query_result === false)
{
$this->sql_error($query);
}
}
if (defined('DEBUG'))
{
$this->sql_report('stop', $query);
}
else if (defined('PHPBB_DISPLAY_LOAD_TIME'))
{
$this->sql_time += microtime(true) - $this->curtime;
}
if (!$this->query_result)
{
return false;
}
if ($cache && $cache_ttl)
{
$this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
}
}
else if (defined('DEBUG'))
{
$this->sql_report('fromcache', $query);
}
}
else
{
return false;
}
return $this->query_result;
}
/**
* Build LIMIT query
*
* @param string $query The SQL query to execute
* @param int $total The number of rows to select
* @param int $offset
* @param int $cache_ttl Either 0 to avoid caching or
* the time in seconds which the result shall be kept in cache
* @return mixed Buffered, seekable result handle, false on error
*/
protected function _sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0)
{
$this->query_result = false;
// if $total is set to 0 we do not want to limit the number of rows
if ($total == 0)
{
$total = -1;
}
$query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total);
return $this->sql_query($query, $cache_ttl);
}
/**
* {@inheritDoc}
*/
public function sql_affectedrows()
{
return ($this->db_connect_id) ? $this->dbo->changes() : false;
}
/**
* {@inheritDoc}
*/
public function sql_fetchrow($query_id = false)
{
global $cache;
if ($query_id === false)
{
/** @var \SQLite3Result $query_id */
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_fetchrow($query_id);
}
return is_object($query_id) ? @$query_id->fetchArray(SQLITE3_ASSOC) : false;
}
/**
* {@inheritDoc}
*/
public function sql_nextid()
{
return ($this->db_connect_id) ? $this->dbo->lastInsertRowID() : false;
}
/**
* {@inheritDoc}
*/
public function sql_freeresult($query_id = false)
{
global $cache;
if ($query_id === false)
{
$query_id = $this->query_result;
}
if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{
return $cache->sql_freeresult($query_id);
}
if ($query_id)
{
return @$query_id->finalize();
}
}
/**
* {@inheritDoc}
*/
public function sql_escape($msg)
{
return \SQLite3::escapeString($msg);
}
/**
* {@inheritDoc}
*
* For SQLite an underscore is an unknown character.
*/
public function sql_like_expression($expression)
{
// Unlike LIKE, GLOB is unfortunately case sensitive.
// We only catch * and ? here, not the character map possible on file globbing.
$expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
$expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
$expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
return 'GLOB \'' . $this->sql_escape($expression) . '\'';
}
/**
* {@inheritDoc}
*
* For SQLite an underscore is an unknown character.
*/
public function sql_not_like_expression($expression)
{
// Unlike NOT LIKE, NOT GLOB is unfortunately case sensitive
// We only catch * and ? here, not the character map possible on file globbing.
$expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
$expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
$expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
return 'NOT GLOB \'' . $this->sql_escape($expression) . '\'';
}
/**
* return sql error array
*
* @return array
*/
protected function _sql_error()
{
if (class_exists('SQLite3', false) && isset($this->dbo))
{
$error = array(
'message' => $this->dbo->lastErrorMsg(),
'code' => $this->dbo->lastErrorCode(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
}
/**
* Build db-specific query data
*
* @param string $stage Available stages: FROM, WHERE
* @param mixed $data A string containing the CROSS JOIN query or an array of WHERE clauses
*
* @return string The db-specific query fragment
*/
protected function _sql_custom_build($stage, $data)
{
return $data;
}
/**
* Close sql connection
*
* @return bool False if failure
*/
protected function _sql_close()
{
return $this->dbo->close();
}
/**
* Build db-specific report
*
* @param string $mode Available modes: display, start, stop,
* add_select_row, fromcache, record_fromcache
* @param string $query The Query that should be explained
* @return mixed Either a full HTML page, boolean or null
*/
protected function _sql_report($mode, $query = '')
{
switch ($mode)
{
case 'start':
$explain_query = $query;
if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m))
{
$explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2];
}
if (preg_match('/^SELECT/', $explain_query))
{
$html_table = false;
if ($result = $this->dbo->query("EXPLAIN QUERY PLAN $explain_query"))
{
while ($row = $result->fetchArray(SQLITE3_ASSOC))
{
$html_table = $this->sql_report('add_select_row', $query, $html_table, $row);
}
}
if ($html_table)
{
$this->html_hold .= '</table>';
}
}
break;
case 'fromcache':
$endtime = explode(' ', microtime());
$endtime = $endtime[0] + $endtime[1];
$result = $this->dbo->query($query);
if ($result)
{
while ($void = $result->fetchArray(SQLITE3_ASSOC))
{
// Take the time spent on parsing rows into account
}
}
$splittime = explode(' ', microtime());
$splittime = $splittime[0] + $splittime[1];
$this->sql_report('record_fromcache', $query, $endtime, $splittime);
break;
}
}
}

View File

@@ -0,0 +1,252 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\invalid_format_exception;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
/**
* Abstract base class for database extraction
*/
abstract class base_extractor implements extractor_interface
{
/**
* @var string phpBB root path
*/
protected $phpbb_root_path;
/**
* @var \phpbb\request\request_interface
*/
protected $request;
/**
* @var \phpbb\db\driver\driver_interface
*/
protected $db;
/**
* @var bool
*/
protected $download;
/**
* @var bool
*/
protected $store;
/**
* @var int
*/
protected $time;
/**
* @var string
*/
protected $format;
/**
* @var resource
*/
protected $fp;
/**
* @var string
*/
protected $write;
/**
* @var string
*/
protected $close;
/**
* @var bool
*/
protected $run_comp;
/**
* @var bool
*/
protected $is_initialized;
/**
* Constructor
*
* @param string $phpbb_root_path
* @param \phpbb\request\request_interface $request
* @param \phpbb\db\driver\driver_interface $db
*/
public function __construct($phpbb_root_path, \phpbb\request\request_interface $request, \phpbb\db\driver\driver_interface $db)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->request = $request;
$this->db = $db;
$this->fp = null;
$this->is_initialized = false;
}
/**
* {@inheritdoc}
*/
public function init_extractor($format, $filename, $time, $download = false, $store = false)
{
$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;
default:
throw new invalid_format_exception();
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($this->request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($this->request->header('User-Agent')), 'msie') === false)
{
ob_start('ob_gzhandler');
}
else
{
$this->run_comp = true;
}
break;
}
}
if ($store === true)
{
$file = $this->phpbb_root_path . 'store/' . $filename . $ext;
$this->fp = $open($file, 'w');
if (!$this->fp)
{
trigger_error('FILE_WRITE_FAIL', E_USER_ERROR);
}
}
$this->is_initialized = true;
}
/**
* {@inheritdoc}
*/
public function write_end()
{
static $close;
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
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);
}
}
/**
* {@inheritdoc}
*/
public function flush($data)
{
static $write;
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
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();
}
}
}
}
}

View File

@@ -0,0 +1,24 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor\exception;
use phpbb\exception\runtime_exception;
/**
* This exception is thrown when invalid format is given to the extractor
*/
class extractor_not_initialized_exception extends runtime_exception
{
}

View File

@@ -0,0 +1,22 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor\exception;
/**
* This exception is thrown when invalid format is given to the extractor
*/
class invalid_format_exception extends \InvalidArgumentException
{
}

View File

@@ -0,0 +1,80 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
/**
* Database extractor interface
*/
interface extractor_interface
{
/**
* Start the extraction of the database
*
* This function initialize the database extraction. It is required to call this
* function before calling any other extractor functions.
*
* @param string $format
* @param string $filename
* @param int $time
* @param bool $download
* @param bool $store
* @return null
* @throws \phpbb\db\extractor\exception\invalid_format_exception when $format is invalid
*/
public function init_extractor($format, $filename, $time, $download = false, $store = false);
/**
* Writes header comments to the database backup
*
* @param string $table_prefix prefix of phpBB database tables
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_start($table_prefix);
/**
* Closes file and/or dumps download data
*
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_end();
/**
* Extracts database table structure
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_table($table_name);
/**
* Extracts data from database table
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_data($table_name);
/**
* Writes data to file/download content
*
* @param string $data
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function flush($data);
}

View File

@@ -0,0 +1,75 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
/**
* A factory which serves the suitable extractor instance for the given dbal
*/
class factory
{
/**
* @var \phpbb\db\driver\driver_interface
*/
protected $db;
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
/**
* Extractor factory constructor
*
* @param \phpbb\db\driver\driver_interface $db
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
*/
public function __construct(\phpbb\db\driver\driver_interface $db, \Symfony\Component\DependencyInjection\ContainerInterface $container)
{
$this->db = $db;
$this->container = $container;
}
/**
* DB extractor factory getter
*
* @return \phpbb\db\extractor\extractor_interface an appropriate instance of the database extractor for the used database driver
* @throws \InvalidArgumentException when the database driver is unknown
*/
public function get()
{
// Return the appropriate DB extractor
if ($this->db instanceof \phpbb\db\driver\mssql_base)
{
return $this->container->get('dbal.extractor.extractors.mssql_extractor');
}
else if ($this->db instanceof \phpbb\db\driver\mysql_base)
{
return $this->container->get('dbal.extractor.extractors.mysql_extractor');
}
else if ($this->db instanceof \phpbb\db\driver\oracle)
{
return $this->container->get('dbal.extractor.extractors.oracle_extractor');
}
else if ($this->db instanceof \phpbb\db\driver\postgres)
{
return $this->container->get('dbal.extractor.extractors.postgres_extractor');
}
else if ($this->db instanceof \phpbb\db\driver\sqlite3)
{
return $this->container->get('dbal.extractor.extractors.sqlite3_extractor');
}
throw new \InvalidArgumentException('Invalid database driver given');
}
}

View File

@@ -0,0 +1,415 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class mssql_extractor extends base_extractor
{
/**
* Writes closing line(s) to database backup
*
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_end()
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$this->flush("COMMIT\nGO\n");
parent::write_end();
}
/**
* {@inheritdoc}
*/
public function write_start($table_prefix)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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";
$sql_data .= "BEGIN TRANSACTION\n";
$sql_data .= "GO\n";
$this->flush($sql_data);
}
/**
* {@inheritdoc}
*/
public function write_table($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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 = $this->db->sql_query($sql);
while ($row = $this->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;
}
$this->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 = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (!count($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 (count($rows))
{
$sql_data .= implode(",\n", $rows);
$sql_data .= "\n\t) ON [PRIMARY] \nGO\n";
}
$this->db->sql_freeresult($result);
$index = array();
$sql = "EXEC sp_statistics '$table_name'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if ($row['TYPE'] == 3)
{
$index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']';
}
}
$this->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);
}
/**
* {@inheritdoc}
*/
public function write_data($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
if ($this->db->get_sql_layer() === 'mssqlnative')
{
$this->write_data_mssqlnative($table_name);
}
else
{
$this->write_data_odbc($table_name);
}
}
/**
* Extracts data from database table (for MSSQL Native driver)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function write_data_mssqlnative($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$ary_type = $ary_name = array();
$ident_set = false;
$sql_data = '';
// Grab all of the data from current table.
$sql = "SELECT * FROM $table_name";
$this->db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC));
$result = $this->db->sql_query($sql);
$retrieved_data = $this->db->mssqlnative_num_rows($result);
if (!$retrieved_data)
{
$this->db->sql_freeresult($result);
return;
}
$sql = "SELECT COLUMN_NAME, DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $this->db->sql_escape($table_name) . "'";
$result_fields = $this->db->sql_query($sql);
$i_num_fields = 0;
while ($row = $this->db->sql_fetchrow($result_fields))
{
$ary_type[$i_num_fields] = $row['DATA_TYPE'];
$ary_name[$i_num_fields] = $row['COLUMN_NAME'];
$i_num_fields++;
}
$this->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 = $this->db->sql_query($sql);
$row2 = $this->db->sql_fetchrow($result2);
if (!empty($row2['has_identity']))
{
$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
$ident_set = true;
}
$this->db->sql_freeresult($result2);
while ($row = $this->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 = '';
}
$this->db->sql_freeresult($result);
if ($ident_set)
{
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
}
$this->flush($sql_data);
}
/**
* Extracts data from database table (for ODBC driver)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function write_data_odbc($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$ary_type = $ary_name = array();
$ident_set = false;
$sql_data = '';
// Grab all of the data from current table.
$sql = "SELECT *
FROM $table_name";
$result = $this->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 = $this->db->sql_query($sql);
$row2 = $this->db->sql_fetchrow($result2);
if (!empty($row2['has_identity']))
{
$sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n";
$ident_set = true;
}
$this->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 = $this->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 = '';
}
$this->db->sql_freeresult($result);
if ($retrieved_data && $ident_set)
{
$sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n";
}
$this->flush($sql_data);
}
}

View File

@@ -0,0 +1,403 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class mysql_extractor extends base_extractor
{
/**
* {@inheritdoc}
*/
public function write_start($table_prefix)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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);
}
/**
* {@inheritdoc}
*/
public function write_table($table_name)
{
static $new_extract;
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
if ($new_extract === null)
{
if ($this->db->get_sql_layer() === 'mysqli' || version_compare($this->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);
}
}
/**
* {@inheritdoc}
*/
public function write_data($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
if ($this->db->get_sql_layer() === 'mysqli')
{
$this->write_data_mysqli($table_name);
}
else
{
$this->write_data_mysql($table_name);
}
}
/**
* Extracts data from database table (for MySQLi driver)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function write_data_mysqli($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$sql = "SELECT *
FROM $table_name";
$result = mysqli_query($this->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");
}
}
}
/**
* Extracts data from database table (for MySQL driver)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function write_data_mysql($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$sql = "SELECT *
FROM $table_name";
$result = mysql_unbuffered_query($sql, $this->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");
}
}
}
/**
* Extracts database table structure (for MySQLi or MySQL 3.23.20+)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function new_write_table($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$sql = 'SHOW CREATE TABLE ' . $table_name;
$result = $this->db->sql_query($sql);
$row = $this->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");
$this->db->sql_freeresult($result);
}
/**
* Extracts database table structure (for MySQL verisons older than 3.23.20)
*
* @param string $table_name name of the database table
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
protected function old_write_table($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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 = $this->db->sql_query($sql);
while ($row = $this->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;
}
$this->db->sql_freeresult($result);
$sql = "SHOW KEYS
FROM $table_name";
$result = $this->db->sql_query($sql);
$index = array();
while ($row = $this->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'];
}
$this->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);
}
}

View File

@@ -0,0 +1,263 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class oracle_extractor extends base_extractor
{
/**
* {@inheritdoc}
*/
public function write_table($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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 = $this->db->sql_query($sql);
$rows = array();
while ($row = $this->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;
}
$this->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 = $this->db->sql_query($sql);
$primary_key = array();
$constraint_name = '';
while ($row = $this->db->sql_fetchrow($result))
{
$constraint_name = '"' . $row['constraint_name'] . '"';
$primary_key[] = '"' . $row['column_name'] . '"';
}
$this->db->sql_freeresult($result);
if (count($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 = $this->db->sql_query($sql);
$unique = array();
$constraint_name = '';
while ($row = $this->db->sql_fetchrow($result))
{
$constraint_name = '"' . $row['constraint_name'] . '"';
$unique[] = '"' . $row['column_name'] . '"';
}
$this->db->sql_freeresult($result);
if (count($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 = $this->db->sql_query($sql);
$type = $this->request->variable('type', '');
while ($row = $this->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";
}
$this->db->sql_freeresult($result);
$sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY
FROM USER_TRIGGERS
WHERE TABLE_NAME = '{$table_name}'";
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n";
}
$this->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 = $this->db->sql_query($sql);
$index = array();
while ($row = $this->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";
}
$this->db->sql_freeresult($result);
$this->flush($sql_data);
}
/**
* {@inheritdoc}
*/
public function write_data($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$ary_type = $ary_name = array();
// Grab all of the data from current table.
$sql = "SELECT *
FROM $table_name";
$result = $this->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);
}
while ($row = $this->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);
}
$this->db->sql_freeresult($result);
}
/**
* {@inheritdoc}
*/
public function write_start($table_prefix)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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);
}
}

View File

@@ -0,0 +1,339 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class postgres_extractor extends base_extractor
{
/**
* {@inheritdoc}
*/
public function write_start($table_prefix)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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";
$sql_data .= "BEGIN TRANSACTION;\n";
$this->flush($sql_data);
}
/**
* {@inheritdoc}
*/
public function write_table($table_name)
{
static $domains_created = array();
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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 = $this->db->sql_query($sql);
while ($row = $this->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");
}
}
$this->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 = $this->db->sql_query($sql);
// We don't even care about storing the results. We already know the answer if we get rows back.
if ($this->db->sql_fetchrow($result))
{
$sql_data .= "DROP SEQUENCE IF EXISTS {$table_name}_seq;\n";
$sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n";
}
$this->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 = '" . $this->db->sql_escape($table_name) . "'
AND a.attnum > 0
AND a.attrelid = c.oid
AND a.atttypid = t.oid
ORDER BY a.attnum";
$result = $this->db->sql_query($field_query);
$sql_data .= "CREATE TABLE $table_name(\n";
$lines = array();
while ($row = $this->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 = '" . $this->db->sql_escape($table_name) . "')
AND (c.oid = d.adrelid)
AND d.adnum = " . $row['attnum'];
$def_res = $this->db->sql_query($sql_get_default);
$def_row = $this->db->sql_fetchrow($def_res);
$this->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;
}
$this->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 = '" . $this->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 = $this->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 = $this->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'];
}
}
$this->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 = '" . $this->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 = $this->db->sql_query($sql_checks);
// Add the constraints to the sql file.
while ($row = $this->db->sql_fetchrow($result))
{
if (!is_null($row['consrc']))
{
$lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc'];
}
}
$this->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);
}
/**
* {@inheritdoc}
*/
public function write_data($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
// Grab all of the data from current table.
$sql = "SELECT *
FROM $table_name";
$result = $this->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 = $this->db->sql_query($sql);
if ($row = $this->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 = $this->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");
}
$this->db->sql_freeresult($result);
$this->flush("\\.\n");
// Write out the sequence statements
$this->flush($seq);
}
/**
* Writes closing line(s) to database backup
*
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_end()
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$this->flush("COMMIT;\n");
parent::write_end();
}
}

View File

@@ -0,0 +1,151 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\extractor;
use phpbb\db\extractor\exception\extractor_not_initialized_exception;
class sqlite3_extractor extends base_extractor
{
/**
* {@inheritdoc}
*/
public function write_start($table_prefix)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$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";
$sql_data .= "BEGIN TRANSACTION;\n";
$this->flush($sql_data);
}
/**
* {@inheritdoc}
*/
public function write_table($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$sql_data = '-- Table: ' . $table_name . "\n";
$sql_data .= "DROP TABLE $table_name;\n";
$sql = "SELECT sql
FROM sqlite_master
WHERE type = 'table'
AND name = '" . $this->db->sql_escape($table_name) . "'
ORDER BY name ASC;";
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
// Create Table
$sql_data .= $row['sql'] . ";\n";
$result = $this->db->sql_query("PRAGMA index_list('" . $this->db->sql_escape($table_name) . "');");
while ($row = $this->db->sql_fetchrow($result))
{
if (strpos($row['name'], 'autoindex') !== false)
{
continue;
}
$result2 = $this->db->sql_query("PRAGMA index_info('" . $this->db->sql_escape($row['name']) . "');");
$fields = array();
while ($row2 = $this->db->sql_fetchrow($result2))
{
$fields[] = $row2['name'];
}
$this->db->sql_freeresult($result2);
$sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n";
}
$this->db->sql_freeresult($result);
$this->flush($sql_data . "\n");
}
/**
* {@inheritdoc}
*/
public function write_data($table_name)
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$result = $this->db->sql_query("PRAGMA table_info('" . $this->db->sql_escape($table_name) . "');");
$col_types = array();
while ($row = $this->db->sql_fetchrow($result))
{
$col_types[$row['name']] = $row['type'];
}
$this->db->sql_freeresult($result);
$sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES (';
$sql = "SELECT *
FROM $table_name";
$result = $this->db->sql_query($sql);
while ($row = $this->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");
}
}
/**
* Writes closing line(s) to database backup
*
* @return null
* @throws \phpbb\db\extractor\exception\extractor_not_initialized_exception when calling this function before init_extractor()
*/
public function write_end()
{
if (!$this->is_initialized)
{
throw new extractor_not_initialized_exception();
}
$this->flush("COMMIT;\n");
parent::write_end();
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Abstract base class for container aware database migrations.
*/
abstract class container_aware_migration extends migration implements ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
protected $container;
/**
* {@inheritdoc}
*/
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
}

View File

@@ -0,0 +1,33 @@
# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from
# module mod_authz_host to a new module called mod_access_compat (which may be
# disabled) and a new "Require" syntax has been introduced to mod_authz_host.
# We could just conditionally provide both versions, but unfortunately Apache
# does not explicitly tell us its version if the module mod_version is not
# available. In this case, we check for the availability of module
# mod_authz_core (which should be on 2.4 or higher only) as a best guess.
<IfModule mod_version.c>
<IfVersion < 2.4>
<Files "*">
Order Allow,Deny
Deny from All
</Files>
</IfVersion>
<IfVersion >= 2.4>
<Files "*">
Require all denied
</Files>
</IfVersion>
</IfModule>
<IfModule !mod_version.c>
<IfModule !mod_authz_core.c>
<Files "*">
Order Allow,Deny
Deny from All
</Files>
</IfModule>
<IfModule mod_authz_core.c>
<Files "*">
Require all denied
</Files>
</IfModule>
</IfModule>

View File

@@ -0,0 +1,70 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class local_url_bbcode extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc1');
}
public function update_data()
{
return array(
array('custom', array(array($this, 'update_local_url_bbcode'))),
);
}
/**
* Update BBCodes that currently use the LOCAL_URL tag
*
* To fix http://tracker.phpbb.com/browse/PHPBB3-8319 we changed
* the second_pass_replace value, so that needs updating for existing ones
*/
public function update_local_url_bbcode()
{
$sql = 'SELECT *
FROM ' . BBCODES_TABLE . '
WHERE bbcode_match ' . $this->db->sql_like_expression($this->db->get_any_char() . 'LOCAL_URL' . $this->db->get_any_char());
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (!class_exists('acp_bbcodes'))
{
if (function_exists('phpbb_require_updated'))
{
phpbb_require_updated('includes/acp/acp_bbcodes.' . $this->php_ext);
}
else
{
require($this->phpbb_root_path . 'includes/acp/acp_bbcodes.' . $this->php_ext);
}
}
$bbcode_match = $row['bbcode_match'];
$bbcode_tpl = $row['bbcode_tpl'];
$acp_bbcodes = new \acp_bbcodes();
$sql_ary = $acp_bbcodes->build_regexp($bbcode_match, $bbcode_tpl);
$sql = 'UPDATE ' . BBCODES_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE bbcode_id = ' . (int) $row['bbcode_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_1_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.1')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_10 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.10', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10')),
);
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_10_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.10-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_9');
}
public function update_data()
{
return array(
array('config.add', array('email_max_chunk_size', 50)),
array('config.update', array('version', '3.0.10-RC1')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_10_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.10-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10-RC2')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_10_rc3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.10-RC3', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_10_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.10-RC3')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_11 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.11', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.11')),
);
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_11_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.11-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_10');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'cleanup_deactivated_styles'))),
array('custom', array(array(&$this, 'delete_orphan_private_messages'))),
array('config.update', array('version', '3.0.11-RC1')),
);
}
public function cleanup_deactivated_styles()
{
// Updates users having current style a deactivated one
$sql = 'SELECT style_id
FROM ' . STYLES_TABLE . '
WHERE style_active = 0';
$result = $this->sql_query($sql);
$deactivated_style_ids = array();
while ($style_id = $this->db->sql_fetchfield('style_id', false, $result))
{
$deactivated_style_ids[] = (int) $style_id;
}
$this->db->sql_freeresult($result);
if (!empty($deactivated_style_ids))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_style = ' . (int) $this->config['default_style'] .'
WHERE ' . $this->db->sql_in_set('user_style', $deactivated_style_ids);
$this->sql_query($sql);
}
}
public function delete_orphan_private_messages()
{
// Delete orphan private messages
$batch_size = 500;
$sql_array = array(
'SELECT' => 'p.msg_id',
'FROM' => array(
PRIVMSGS_TABLE => 'p',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(PRIVMSGS_TO_TABLE => 't'),
'ON' => 'p.msg_id = t.msg_id',
),
),
'WHERE' => 't.user_id IS NULL',
);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $batch_size);
$delete_pms = array();
while ($row = $this->db->sql_fetchrow($result))
{
$delete_pms[] = (int) $row['msg_id'];
}
$this->db->sql_freeresult($result);
if (!empty($delete_pms))
{
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
WHERE ' . $this->db->sql_in_set('msg_id', $delete_pms);
$this->sql_query($sql);
// Return false to have the Migrator call this function again
return false;
}
}
}

View File

@@ -0,0 +1,56 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_11_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.11-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11_rc1');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_novalue' => array('BOOL', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_novalue',
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.11-RC2')),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_12 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.12', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc3');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.12', '<'),
array('config.update', array('version', '3.0.12')),
)),
);
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
/** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.12-RC1 **/
class release_3_0_12_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.12-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_module_auth'))),
array('custom', array(array(&$this, 'disable_bots_from_receiving_pms'))),
array('config.update', array('version', '3.0.12-RC1')),
);
}
public function disable_bots_from_receiving_pms()
{
// Disable receiving pms for bots
$sql = 'SELECT user_id
FROM ' . BOTS_TABLE;
$result = $this->db->sql_query($sql);
$bot_user_ids = array();
while ($row = $this->db->sql_fetchrow($result))
{
$bot_user_ids[] = (int) $row['user_id'];
}
$this->db->sql_freeresult($result);
if (!empty($bot_user_ids))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET user_allow_pm = 0
WHERE ' . $this->db->sql_in_set('user_id', $bot_user_ids);
$this->sql_query($sql);
}
}
public function update_module_auth()
{
$sql = 'UPDATE ' . MODULES_TABLE . '
SET module_auth = \'acl_u_sig\'
WHERE module_class = \'ucp\'
AND module_basename = \'profile\'
AND module_mode = \'signature\'';
$this->sql_query($sql);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_12_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.12-RC2', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc1');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.12-RC2', '<'),
array('config.update', array('version', '3.0.12-RC2')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_12_rc3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.12-RC3', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_12_rc2');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.12-RC3', '<'),
array('config.update', array('version', '3.0.12-RC3')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_13 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.13', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_13_rc1');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.13', '<'),
array('config.update', array('version', '3.0.13')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_13_pl1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.13-PL1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_13');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.13-PL1', '<'),
array('config.update', array('version', '3.0.13-PL1')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_13_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.13-RC1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_12');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.13-RC1', '<'),
array('config.update', array('version', '3.0.13-RC1')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_14 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.14', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_14_rc1');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.14', '<'),
array('config.update', array('version', '3.0.14')),
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_14_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.14-RC1', '>=') && phpbb_version_compare($this->config['version'], '3.1.0-dev', '<');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_13');
}
public function update_data()
{
return array(
array('if', array(
phpbb_version_compare($this->config['version'], '3.0.14-RC1', '<'),
array('config.update', array('version', '3.0.14-RC1')),
)),
);
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_1_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.1-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_0');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'forums' => array(
'display_subforum_list' => array('BOOL', 1),
),
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array('UINT', 0),
),
),
'drop_keys' => array(
$this->table_prefix . 'groups' => array(
'group_legend',
),
),
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array('session_forum_id'),
),
$this->table_prefix . 'groups' => array(
'group_legend_name' => array('group_legend', 'group_name'),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'forums' => array(
'display_subforum_list',
),
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
),
'add_index' => array(
$this->table_prefix . 'groups' => array(
'group_legend' => array('group_legend'),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
$this->table_prefix . 'groups' => array(
'group_legend_name',
),
),
);
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'fix_unset_last_view_time'))),
array('custom', array(array(&$this, 'reset_smiley_size'))),
array('config.update', array('version', '3.0.1-RC1')),
);
}
public function fix_unset_last_view_time()
{
$sql = 'UPDATE ' . $this->table_prefix . "topics
SET topic_last_view_time = topic_last_post_time
WHERE topic_last_view_time = 0";
$this->sql_query($sql);
}
public function reset_smiley_size()
{
// Update smiley sizes
$smileys = array('icon_e_surprised.gif', 'icon_eek.gif', 'icon_cool.gif', 'icon_lol.gif', 'icon_mad.gif', 'icon_razz.gif', 'icon_redface.gif', 'icon_cry.gif', 'icon_evil.gif', 'icon_twisted.gif', 'icon_rolleyes.gif', 'icon_exclaim.gif', 'icon_question.gif', 'icon_idea.gif', 'icon_arrow.gif', 'icon_neutral.gif', 'icon_mrgreen.gif', 'icon_e_ugeek.gif');
foreach ($smileys as $smiley)
{
if (file_exists($this->phpbb_root_path . 'images/smilies/' . $smiley))
{
list($width, $height) = getimagesize($this->phpbb_root_path . 'images/smilies/' . $smiley);
$sql = 'UPDATE ' . SMILIES_TABLE . '
SET smiley_width = ' . $width . ', smiley_height = ' . $height . "
WHERE smiley_url = '" . $this->db->sql_escape($smiley) . "'";
$this->sql_query($sql);
}
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_2_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.2')),
);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_2_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.2-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_1');
}
public function update_data()
{
return array(
array('config.add', array('referer_validation', '1')),
array('config.add', array('check_attachment_content', '1')),
array('config.add', array('mime_triggers', 'body|head|html|img|plaintext|a href|pre|script|table|title')),
array('config.update', array('version', '3.0.2-RC1')),
);
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_2_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.2-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_2_rc1');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'drafts' => array(
'draft_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'forums' => array(
'forum_last_post_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'posts' => array(
'post_subject' => array('STEXT_UNI', '', 'true_sort'),
),
$this->table_prefix . 'privmsgs' => array(
'message_subject' => array('STEXT_UNI', ''),
),
$this->table_prefix . 'topics' => array(
'topic_title' => array('STEXT_UNI', '', 'true_sort'),
'topic_last_post_subject' => array('STEXT_UNI', ''),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id',
),
),
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_fid' => array('session_forum_id'),
),
),
);
}
public function revert_schema()
{
return array(
'add_index' => array(
$this->table_prefix . 'sessions' => array(
'session_forum_id' => array(
'session_forum_id',
),
),
),
'drop_keys' => array(
$this->table_prefix . 'sessions' => array(
'session_fid',
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.2-RC2')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.3', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_3_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.3')),
);
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_3_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.3-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_2');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'styles_template' => array(
'template_inherits_id' => array('UINT:4', 0),
'template_inherit_path' => array('VCHAR', ''),
),
$this->table_prefix . 'groups' => array(
'group_max_recipients' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'styles_template' => array(
'template_inherits_id',
'template_inherit_path',
),
$this->table_prefix . 'groups' => array(
'group_max_recipients',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('enable_queue_trigger', '0')),
array('config.add', array('queue_trigger_posts', '3')),
array('config.add', array('pm_max_recipients', '0')),
array('custom', array(array(&$this, 'set_group_default_max_recipients'))),
array('config.add', array('dbms_version', $this->db->sql_server_info(true))),
array('permission.add', array('u_masspm_group', true, 'u_masspm')),
array('custom', array(array(&$this, 'correct_acp_email_permissions'))),
array('config.update', array('version', '3.0.3-RC1')),
);
}
public function correct_acp_email_permissions()
{
$sql = 'UPDATE ' . $this->table_prefix . 'modules
SET module_auth = \'acl_a_email && cfg_email_enable\'
WHERE module_class = \'acp\'
AND module_basename = \'email\'';
$this->sql_query($sql);
}
public function set_group_default_max_recipients()
{
// Set maximum number of recipients for the registered users, bots, guests group
$sql = 'UPDATE ' . GROUPS_TABLE . ' SET group_max_recipients = 5
WHERE ' . $this->db->sql_in_set('group_name', array('GUESTS', 'REGISTERED', 'REGISTERED_COPPA', 'BOTS'));
$this->sql_query($sql);
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_4 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.4', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_4_rc1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'rename_log_delete_topic'))),
array('config.update', array('version', '3.0.4')),
);
}
public function rename_log_delete_topic()
{
if ($this->db->get_sql_layer() == 'oracle')
{
// log_operation is CLOB - but we can change this later
$sql = 'UPDATE ' . $this->table_prefix . "log
SET log_operation = 'LOG_DELETE_TOPIC'
WHERE log_operation LIKE 'LOG_TOPIC_DELETED'";
$this->sql_query($sql);
}
else
{
$sql = 'UPDATE ' . $this->table_prefix . "log
SET log_operation = 'LOG_DELETE_TOPIC'
WHERE log_operation = 'LOG_TOPIC_DELETED'";
$this->sql_query($sql);
}
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_4_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.4-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_3');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_profile' => array('BOOL', 0),
),
),
'change_columns' => array(
$this->table_prefix . 'styles' => array(
'style_id' => array('UINT', NULL, 'auto_increment'),
'template_id' => array('UINT', 0),
'theme_id' => array('UINT', 0),
'imageset_id' => array('UINT', 0),
),
$this->table_prefix . 'styles_imageset' => array(
'imageset_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_imageset_data' => array(
'image_id' => array('UINT', NULL, 'auto_increment'),
'imageset_id' => array('UINT', 0),
),
$this->table_prefix . 'styles_theme' => array(
'theme_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_template' => array(
'template_id' => array('UINT', NULL, 'auto_increment'),
),
$this->table_prefix . 'styles_template_data' => array(
'template_id' => array('UINT', 0),
),
$this->table_prefix . 'forums' => array(
'forum_style' => array('UINT', 0),
),
$this->table_prefix . 'users' => array(
'user_style' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'profile_fields' => array(
'field_show_profile',
),
),
);
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_custom_profile_fields'))),
array('config.update', array('version', '3.0.4-RC1')),
);
}
public function update_custom_profile_fields()
{
// Update the Custom Profile Fields based on previous settings to the new \format
$sql = 'SELECT field_id, field_required, field_show_on_reg, field_hide
FROM ' . PROFILE_FIELDS_TABLE;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql_ary = array(
'field_required' => 0,
'field_show_on_reg' => 0,
'field_hide' => 0,
'field_show_profile'=> 0,
);
if ($row['field_required'])
{
$sql_ary['field_required'] = $sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1;
}
else if ($row['field_show_on_reg'])
{
$sql_ary['field_show_on_reg'] = $sql_ary['field_show_profile'] = 1;
}
else if ($row['field_hide'])
{
// Only administrators and moderators can see this CPF, if the view is enabled, they can see it, otherwise just admins in the acp_users module
$sql_ary['field_hide'] = 1;
}
else
{
// equivelant to "none", which is the "Display in user control panel" option
$sql_ary['field_show_profile'] = 1;
}
$this->sql_query('UPDATE ' . $this->table_prefix . 'profile_fields SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE field_id = ' . $row['field_id'], $errored, $error_ary);
}
$this->db->sql_freeresult($result);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_5 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.5', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_5_rc1part2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.5')),
);
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
use phpbb\db\migration\container_aware_migration;
class release_3_0_5_rc1 extends container_aware_migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.5-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_4');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'forums' => array(
'forum_style' => array('UINT', 0),
),
),
);
}
public function update_data()
{
$search_indexing_state = $this->config['search_indexing_state'];
return array(
array('config.add', array('captcha_gd_wave', 0)),
array('config.add', array('captcha_gd_3d_noise', 1)),
array('config.add', array('captcha_gd_fonts', 1)),
array('config.add', array('confirm_refresh', 1)),
array('config.add', array('max_num_search_keywords', 10)),
array('config.remove', array('search_indexing_state')),
array('config.add', array('search_indexing_state', $search_indexing_state, true)),
array('custom', array(array(&$this, 'hash_old_passwords'))),
array('custom', array(array(&$this, 'update_ichiro_bot'))),
);
}
public function hash_old_passwords()
{
/* @var $passwords_manager \phpbb\passwords\manager */
$passwords_manager = $this->container->get('passwords.manager');
$sql = 'SELECT user_id, user_password
FROM ' . $this->table_prefix . 'users
WHERE user_pass_convert = 1';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
if (strlen($row['user_password']) == 32)
{
$sql_ary = array(
'user_password' => '$CP$' . $passwords_manager->hash($row['user_password'], 'passwords.driver.salted_md5'),
);
$this->sql_query('UPDATE ' . $this->table_prefix . 'users SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . ' WHERE user_id = ' . $row['user_id']);
}
}
$this->db->sql_freeresult($result);
}
public function update_ichiro_bot()
{
// Adjust bot entry
$sql = 'UPDATE ' . $this->table_prefix . "bots
SET bot_agent = 'ichiro/'
WHERE bot_agent = 'ichiro/2'";
$this->sql_query($sql);
}
public function remove_duplicate_auth_options()
{
// Before we are able to add a unique key to auth_option, we need to remove duplicate entries
$sql = 'SELECT auth_option
FROM ' . $this->table_prefix . 'acl_options
GROUP BY auth_option
HAVING COUNT(*) >= 2';
$result = $this->db->sql_query($sql);
$auth_options = array();
while ($row = $this->db->sql_fetchrow($result))
{
$auth_options[] = $row['auth_option'];
}
$this->db->sql_freeresult($result);
// Remove specific auth options
if (!empty($auth_options))
{
foreach ($auth_options as $option)
{
// Select auth_option_ids... the largest id will be preserved
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option = '" . $this->db->sql_escape($option) . "'
ORDER BY auth_option_id DESC";
// sql_query_limit not possible here, due to bug in postgresql layer
$result = $this->db->sql_query($sql);
// Skip first row, this is our original auth option we want to preserve
$this->db->sql_fetchrow($result);
while ($row = $this->db->sql_fetchrow($result))
{
// Ok, remove this auth option...
$this->sql_query('DELETE FROM ' . ACL_OPTIONS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_GROUPS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
$this->sql_query('DELETE FROM ' . ACL_USERS_TABLE . ' WHERE auth_option_id = ' . $row['auth_option_id']);
}
$this->db->sql_freeresult($result);
}
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_5_rc1part2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.5-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_5_rc1');
}
public function update_schema()
{
return array(
'drop_keys' => array(
$this->table_prefix . 'acl_options' => array('auth_option'),
),
'add_unique_index' => array(
$this->table_prefix . 'acl_options' => array(
'auth_option' => array('auth_option'),
),
),
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.5-RC1')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_6 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.6', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc4');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6')),
);
}
}

View File

@@ -0,0 +1,364 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_6_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.6-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_5');
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'confirm' => array(
'attempts' => array('UINT', 0),
),
$this->table_prefix . 'users' => array(
'user_new' => array('BOOL', 1),
'user_reminded' => array('TINT:4', 0),
'user_reminded_time' => array('TIMESTAMP', 0),
),
$this->table_prefix . 'groups' => array(
'group_skip_auth' => array('BOOL', 0, 'after' => 'group_founder_manage'),
),
$this->table_prefix . 'privmsgs' => array(
'message_reported' => array('BOOL', 0),
),
$this->table_prefix . 'reports' => array(
'pm_id' => array('UINT', 0),
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_vt' => array('BOOL', 0),
),
$this->table_prefix . 'forums' => array(
'forum_options' => array('UINT:20', 0),
),
),
'change_columns' => array(
$this->table_prefix . 'users' => array(
'user_options' => array('UINT:11', 230271),
),
),
'add_index' => array(
$this->table_prefix . 'reports' => array(
'post_id' => array('post_id'),
'pm_id' => array('pm_id'),
),
$this->table_prefix . 'posts' => array(
'post_username' => array('post_username:255'),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'confirm' => array(
'attempts',
),
$this->table_prefix . 'users' => array(
'user_new',
'user_reminded',
'user_reminded_time',
),
$this->table_prefix . 'groups' => array(
'group_skip_auth',
),
$this->table_prefix . 'privmsgs' => array(
'message_reported',
),
$this->table_prefix . 'reports' => array(
'pm_id',
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_vt',
),
$this->table_prefix . 'forums' => array(
'forum_options',
),
),
'drop_keys' => array(
$this->table_prefix . 'reports' => array(
'post_id',
'pm_id',
),
$this->table_prefix . 'posts' => array(
'post_username',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('captcha_plugin', 'phpbb_captcha_nogd')),
array('if', array(
($this->config['captcha_gd']),
array('config.update', array('captcha_plugin', 'phpbb_captcha_gd')),
)),
array('config.add', array('feed_enable', 0)),
array('config.add', array('feed_limit', 10)),
array('config.add', array('feed_overall_forums', 1)),
array('config.add', array('feed_overall_forums_limit', 15)),
array('config.add', array('feed_overall_topics', 0)),
array('config.add', array('feed_overall_topics_limit', 15)),
array('config.add', array('feed_forum', 1)),
array('config.add', array('feed_topic', 1)),
array('config.add', array('feed_item_statistics', 1)),
array('config.add', array('smilies_per_page', 50)),
array('config.add', array('allow_pm_report', 1)),
array('config.add', array('min_post_chars', 1)),
array('config.add', array('allow_quick_reply', 1)),
array('config.add', array('new_member_post_limit', 0)),
array('config.add', array('new_member_group_default', 0)),
array('config.add', array('delete_time', $this->config['edit_time'])),
array('config.add', array('allow_avatar', 0)),
array('if', array(
($this->config['allow_avatar_upload'] || $this->config['allow_avatar_local'] || $this->config['allow_avatar_remote']),
array('config.update', array('allow_avatar', 1)),
)),
array('config.add', array('allow_avatar_remote_upload', 0)),
array('if', array(
($this->config['allow_avatar_remote'] && $this->config['allow_avatar_upload']),
array('config.update', array('allow_avatar_remote_upload', 1)),
)),
array('module.add', array(
'acp',
'ACP_BOARD_CONFIGURATION',
array(
'module_basename' => 'acp_board',
'module_langname' => 'ACP_FEED_SETTINGS',
'module_mode' => 'feed',
'module_auth' => 'acl_a_board',
'after' => array('signature', 'ACP_SIGNATURE_SETTINGS'),
),
)),
array('module.add', array(
'acp',
'ACP_CAT_USERS',
array(
'module_basename' => 'acp_users',
'module_langname' => 'ACP_USER_WARNINGS',
'module_mode' => 'warnings',
'module_auth' => 'acl_a_user',
'module_display' => false,
'after' => array('feedback', 'ACP_USER_FEEDBACK'),
),
)),
array('module.add', array(
'acp',
'ACP_SERVER_CONFIGURATION',
array(
'module_basename' => 'acp_send_statistics',
'module_langname' => 'ACP_SEND_STATISTICS',
'module_mode' => 'send_statistics',
'module_auth' => 'acl_a_server',
),
)),
array('module.add', array(
'acp',
'ACP_FORUM_BASED_PERMISSIONS',
array(
'module_basename' => 'acp_permissions',
'module_langname' => 'ACP_FORUM_PERMISSIONS_COPY',
'module_mode' => 'setting_forum_copy',
'module_auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth',
'after' => array('setting_forum_local', 'ACP_FORUM_PERMISSIONS'),
),
)),
array('module.add', array(
'mcp',
'MCP_REPORTS',
array(
'module_basename' => 'mcp_pm_reports',
'module_langname' => 'MCP_PM_REPORTS_OPEN',
'module_mode' => 'pm_reports',
'module_auth' => 'acl_m_pm_report',
),
)),
array('module.add', array(
'mcp',
'MCP_REPORTS',
array(
'module_basename' => 'mcp_pm_reports',
'module_langname' => 'MCP_PM_REPORTS_CLOSED',
'module_mode' => 'pm_reports_closed',
'module_auth' => 'acl_m_pm_report',
),
)),
array('module.add', array(
'mcp',
'MCP_REPORTS',
array(
'module_basename' => 'mcp_pm_reports',
'module_langname' => 'MCP_PM_REPORT_DETAILS',
'module_mode' => 'pm_report_details',
'module_auth' => 'acl_m_pm_report',
),
)),
array('custom', array(array(&$this, 'add_newly_registered_group'))),
array('custom', array(array(&$this, 'set_user_options_default'))),
array('config.update', array('version', '3.0.6-RC1')),
);
}
public function set_user_options_default()
{
// 229376 is the added value to enable all three signature options
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_options = user_options + 229376';
$this->sql_query($sql);
}
public function add_newly_registered_group()
{
// Add newly_registered group... but check if it already exists (we always supported running the updater on any schema)
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'NEWLY_REGISTERED'";
$result = $this->db->sql_query($sql);
$group_id = (int) $this->db->sql_fetchfield('group_id');
$this->db->sql_freeresult($result);
if (!$group_id)
{
$sql = 'INSERT INTO ' . GROUPS_TABLE . " (group_name, group_type, group_founder_manage, group_colour, group_legend, group_avatar, group_desc, group_desc_uid, group_max_recipients) VALUES ('NEWLY_REGISTERED', 3, 0, '', 0, '', '', '', 5)";
$this->sql_query($sql);
$group_id = $this->db->sql_nextid();
}
// Insert new user role... at the end of the chain
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = 'ROLE_USER_NEW_MEMBER'
AND role_type = 'u_'";
$result = $this->db->sql_query($sql);
$u_role = (int) $this->db->sql_fetchfield('role_id');
$this->db->sql_freeresult($result);
if (!$u_role)
{
$sql = 'SELECT MAX(role_order) as max_order_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = 'u_'";
$result = $this->db->sql_query($sql);
$next_order_id = (int) $this->db->sql_fetchfield('max_order_id');
$this->db->sql_freeresult($result);
$next_order_id++;
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_USER_NEW_MEMBER', 'ROLE_DESCRIPTION_USER_NEW_MEMBER', 'u_', $next_order_id)";
$this->sql_query($sql);
$u_role = $this->db->sql_nextid();
// Now add the correct data to the roles...
// The standard role says that new users are not able to send a PM, Mass PM, are not able to PM groups
$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $u_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'u_%' AND auth_option IN ('u_sendpm', 'u_masspm', 'u_masspm_group')";
$this->sql_query($sql);
// Add user role to group
$sql = 'INSERT INTO ' . ACL_GROUPS_TABLE . " (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES ($group_id, 0, 0, $u_role, 0)";
$this->sql_query($sql);
}
// Insert new forum role
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = 'ROLE_FORUM_NEW_MEMBER'
AND role_type = 'f_'";
$result = $this->db->sql_query($sql);
$f_role = (int) $this->db->sql_fetchfield('role_id');
$this->db->sql_freeresult($result);
if (!$f_role)
{
$sql = 'SELECT MAX(role_order) as max_order_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = 'f_'";
$result = $this->db->sql_query($sql);
$next_order_id = (int) $this->db->sql_fetchfield('max_order_id');
$this->db->sql_freeresult($result);
$next_order_id++;
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . " (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', $next_order_id)";
$this->sql_query($sql);
$f_role = $this->db->sql_nextid();
$sql = 'INSERT INTO ' . ACL_ROLES_DATA_TABLE . " (role_id, auth_option_id, auth_setting) SELECT $f_role, auth_option_id, 0 FROM " . ACL_OPTIONS_TABLE . " WHERE auth_option LIKE 'f_%' AND auth_option IN ('f_noapprove')";
$this->sql_query($sql);
}
// Set every members user_new column to 0 (old users) only if there is no one yet (this makes sure we do not execute this more than once)
$sql = 'SELECT 1
FROM ' . USERS_TABLE . '
WHERE user_new = 0';
$result = $this->db->sql_query_limit($sql, 1);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$row)
{
$sql = 'UPDATE ' . USERS_TABLE . ' SET user_new = 0';
$this->sql_query($sql);
}
// To mimick the old "feature" we will assign the forum role to every forum, regardless of the setting (this makes sure there are no "this does not work!!!! YUO!!!" posts...
// Check if the role is already assigned...
$sql = 'SELECT forum_id
FROM ' . ACL_GROUPS_TABLE . '
WHERE group_id = ' . $group_id . '
AND auth_role_id = ' . $f_role;
$result = $this->db->sql_query($sql);
$is_options = (int) $this->db->sql_fetchfield('forum_id');
$this->db->sql_freeresult($result);
// Not assigned at all... :/
if (!$is_options)
{
// Get postable forums
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . '
WHERE forum_type != ' . FORUM_LINK;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$this->sql_query('INSERT INTO ' . ACL_GROUPS_TABLE . ' (group_id, forum_id, auth_option_id, auth_role_id, auth_setting) VALUES (' . $group_id . ', ' . (int) $row['forum_id'] . ', 0, ' . $f_role . ', 0)');
}
$this->db->sql_freeresult($result);
}
// Clear permissions...
include_once($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
$auth_admin = new \auth_admin();
$auth_admin->acl_clear_prefetch();
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_6_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.6-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6-RC2')),
);
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_6_rc3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.6-RC3', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc2');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_cp_fields'))),
array('config.update', array('version', '3.0.6-RC3')),
);
}
public function update_cp_fields()
{
// Update the Custom Profile Fields based on previous settings to the new \format
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . '
SET field_show_on_vt = 1
WHERE field_hide = 0
AND (field_required = 1 OR field_show_on_reg = 1 OR field_show_profile = 1)';
$this->sql_query($sql);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_6_rc4 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.6-RC4', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_6_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.6-RC4')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_7 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.7', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_7_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.7')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_7_pl1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.7-pl1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_7');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.7-pl1')),
);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_7_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.7-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_6');
}
public function update_schema()
{
return array(
'drop_keys' => array(
$this->table_prefix . 'log' => array(
'log_time',
),
),
'add_index' => array(
$this->table_prefix . 'topics_track' => array(
'topic_id' => array('topic_id'),
),
),
);
}
public function revert_schema()
{
return array(
'add_index' => array(
$this->table_prefix . 'log' => array(
'log_time' => array('log_time'),
),
),
'drop_keys' => array(
$this->table_prefix . 'topics_track' => array(
'topic_id',
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('feed_overall', 1)),
array('config.add', array('feed_http_auth', 0)),
array('config.add', array('feed_limit_post', $this->config['feed_limit'])),
array('config.add', array('feed_limit_topic', $this->config['feed_overall_topics_limit'])),
array('config.add', array('feed_topics_new', $this->config['feed_overall_topics'])),
array('config.add', array('feed_topics_active', $this->config['feed_overall_topics'])),
array('custom', array(array(&$this, 'delete_text_templates'))),
array('config.update', array('version', '3.0.7-RC1')),
);
}
public function delete_text_templates()
{
// Delete all text-templates from the template_data
$sql = 'DELETE FROM ' . STYLES_TEMPLATE_DATA_TABLE . '
WHERE template_filename ' . $this->db->sql_like_expression($this->db->get_any_char() . '.txt');
$this->sql_query($sql);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_7_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.7-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_7_rc1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_email_hash'))),
array('config.update', array('version', '3.0.7-RC2')),
);
}
public function update_email_hash($start = 0)
{
$limit = 1000;
$sql = 'SELECT user_id, user_email, user_email_hash
FROM ' . USERS_TABLE . '
WHERE user_type <> ' . USER_IGNORE . "
AND user_email <> ''";
$result = $this->db->sql_query_limit($sql, $limit, $start);
$i = 0;
while ($row = $this->db->sql_fetchrow($result))
{
$i++;
// Snapshot of the phpbb_email_hash() function
// We cannot call it directly because the auto updater updates the DB first. :/
$user_email_hash = sprintf('%u', crc32(strtolower($row['user_email']))) . strlen($row['user_email']);
if ($user_email_hash != $row['user_email_hash'])
{
$sql_ary = array(
'user_email_hash' => $user_email_hash,
);
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE user_id = ' . (int) $row['user_id'];
$this->sql_query($sql);
}
}
$this->db->sql_freeresult($result);
if ($i < $limit)
{
// Completed
return;
}
// Return the next start, will be sent to $start when this function is called again
return $start + $limit;
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_8 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.8', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_8_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.8')),
);
}
}

View File

@@ -0,0 +1,170 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_8_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.8-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_7_pl1');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_file_extension_group_names'))),
array('custom', array(array(&$this, 'update_module_auth'))),
array('custom', array(array(&$this, 'delete_orphan_shadow_topics'))),
array('module.add', array(
'acp',
'ACP_MESSAGES',
array(
'module_basename' => 'acp_board',
'module_langname' => 'ACP_POST_SETTINGS',
'module_mode' => 'post',
'module_auth' => 'acl_a_board',
'after' => array('message', 'ACP_MESSAGE_SETTINGS'),
),
)),
array('config.add', array('load_unreads_search', 1)),
array('config.update_if_equals', array(600, 'queue_interval', 60)),
array('config.update_if_equals', array(50, 'email_package_size', 20)),
array('config.update', array('version', '3.0.8-RC1')),
);
}
public function update_file_extension_group_names()
{
// Update file extension group names to use language strings.
$sql = 'SELECT lang_dir
FROM ' . LANG_TABLE;
$result = $this->db->sql_query($sql);
$extension_groups_updated = array();
while ($row = $this->db->sql_fetchrow($result))
{
if (empty($row['lang_dir']))
{
continue;
}
$lang_dir = basename($row['lang_dir']);
// The language strings we need are either in language/.../acp/attachments.php
// in the update package if we're updating to 3.0.8-RC1 or later,
// or they are in language/.../install.php when we're updating from 3.0.7-PL1 or earlier.
// On an already updated board, they can also already be in language/.../acp/attachments.php
// in the board root.
$lang_files = array(
"{$this->phpbb_root_path}install/update/new/language/$lang_dir/acp/attachments.{$this->php_ext}",
"{$this->phpbb_root_path}language/$lang_dir/install.{$this->php_ext}",
"{$this->phpbb_root_path}language/$lang_dir/acp/attachments.{$this->php_ext}",
);
foreach ($lang_files as $lang_file)
{
if (!file_exists($lang_file))
{
continue;
}
$lang = array();
include($lang_file);
foreach($lang as $lang_key => $lang_val)
{
if (isset($extension_groups_updated[$lang_key]) || strpos($lang_key, 'EXT_GROUP_') !== 0)
{
continue;
}
$sql_ary = array(
'group_name' => substr($lang_key, 10), // Strip off 'EXT_GROUP_'
);
$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . "
WHERE group_name = '" . $this->db->sql_escape($lang_val) . "'";
$this->sql_query($sql);
$extension_groups_updated[$lang_key] = true;
}
}
}
$this->db->sql_freeresult($result);
}
public function update_module_auth()
{
$sql = 'UPDATE ' . MODULES_TABLE . '
SET module_auth = \'cfg_allow_avatar && (cfg_allow_avatar_local || cfg_allow_avatar_remote || cfg_allow_avatar_upload || cfg_allow_avatar_remote_upload)\'
WHERE module_class = \'ucp\'
AND module_basename = \'profile\'
AND module_mode = \'avatar\'';
$this->sql_query($sql);
}
public function delete_orphan_shadow_topics()
{
// Delete shadow topics pointing to not existing topics
$batch_size = 500;
// Set of affected forums we have to resync
$sync_forum_ids = array();
$sql_array = array(
'SELECT' => 't1.topic_id, t1.forum_id',
'FROM' => array(
TOPICS_TABLE => 't1',
),
'LEFT_JOIN' => array(
array(
'FROM' => array(TOPICS_TABLE => 't2'),
'ON' => 't1.topic_moved_id = t2.topic_id',
),
),
'WHERE' => 't1.topic_moved_id <> 0
AND t2.topic_id IS NULL',
);
$sql = $this->db->sql_build_query('SELECT', $sql_array);
$result = $this->db->sql_query_limit($sql, $batch_size);
$topic_ids = array();
while ($row = $this->db->sql_fetchrow($result))
{
$topic_ids[] = (int) $row['topic_id'];
$sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id'];
}
$this->db->sql_freeresult($result);
if (!empty($topic_ids))
{
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
WHERE ' . $this->db->sql_in_set('topic_id', $topic_ids);
$this->db->sql_query($sql);
// Sync the forums we have deleted shadow topics from.
sync('forum', 'forum_id', $sync_forum_ids, true, true);
return false;
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_9 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.9', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc4');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9')),
);
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_9_rc1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.9-RC1', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_8');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'login_attempts' => array(
'COLUMNS' => array(
// this column was removed from the database updater
// after 3.0.9-RC3 was released. It might still exist
// in 3.0.9-RCX installations and has to be dropped as
// soon as the \phpbb\db\tools\tools class is capable of properly
// removing a primary key.
// 'attempt_id' => array('UINT', NULL, 'auto_increment'),
'attempt_ip' => array('VCHAR:40', ''),
'attempt_browser' => array('VCHAR:150', ''),
'attempt_forwarded_for' => array('VCHAR:255', ''),
'attempt_time' => array('TIMESTAMP', 0),
'user_id' => array('UINT', 0),
'username' => array('VCHAR_UNI:255', 0),
'username_clean' => array('VCHAR_CI', 0),
),
//'PRIMARY_KEY' => 'attempt_id',
'KEYS' => array(
'att_ip' => array('INDEX', array('attempt_ip', 'attempt_time')),
'att_for' => array('INDEX', array('attempt_forwarded_for', 'attempt_time')),
'att_time' => array('INDEX', array('attempt_time')),
'user_id' => array('INDEX', 'user_id'),
),
),
),
'change_columns' => array(
$this->table_prefix . 'bbcodes' => array(
'bbcode_id' => array('USINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'login_attempts',
),
);
}
public function update_data()
{
return array(
array('config.add', array('ip_login_limit_max', 50)),
array('config.add', array('ip_login_limit_time', 21600)),
array('config.add', array('ip_login_limit_use_forwarded', 0)),
array('custom', array(array(&$this, 'update_file_extension_group_names'))),
array('custom', array(array(&$this, 'fix_firebird_qa_captcha'))),
array('config.update', array('version', '3.0.9-RC1')),
);
}
public function update_file_extension_group_names()
{
// Update file extension group names to use language strings, again.
$sql = 'SELECT group_id, group_name
FROM ' . EXTENSION_GROUPS_TABLE . '
WHERE group_name ' . $this->db->sql_like_expression('EXT_GROUP_' . $this->db->get_any_char());
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$sql_ary = array(
'group_name' => substr($row['group_name'], 10), // Strip off 'EXT_GROUP_'
);
$sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . '
WHERE group_id = ' . $row['group_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
public function fix_firebird_qa_captcha()
{
// Recover from potentially broken Q&A CAPTCHA table on firebird
// Q&A CAPTCHA was uninstallable, so it's safe to remove these
// without data loss
if ($this->db_tools->sql_layer == 'firebird')
{
$tables = array(
$this->table_prefix . 'captcha_questions',
$this->table_prefix . 'captcha_answers',
$this->table_prefix . 'qa_confirm',
);
foreach ($tables as $table)
{
if ($this->db_tools->sql_table_exists($table))
{
$this->db_tools->sql_table_drop($table);
}
}
}
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_9_rc2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.9-RC2', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc1');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-RC2')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_9_rc3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.9-RC3', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc2');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-RC3')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v30x;
class release_3_0_9_rc4 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.0.9-RC4', '>=');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_9_rc3');
}
public function update_data()
{
return array(
array('config.update', array('version', '3.0.9-RC4')),
);
}
}

View File

@@ -0,0 +1,33 @@
# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from
# module mod_authz_host to a new module called mod_access_compat (which may be
# disabled) and a new "Require" syntax has been introduced to mod_authz_host.
# We could just conditionally provide both versions, but unfortunately Apache
# does not explicitly tell us its version if the module mod_version is not
# available. In this case, we check for the availability of module
# mod_authz_core (which should be on 2.4 or higher only) as a best guess.
<IfModule mod_version.c>
<IfVersion < 2.4>
<Files "*">
Order Allow,Deny
Deny from All
</Files>
</IfVersion>
<IfVersion >= 2.4>
<Files "*">
Require all denied
</Files>
</IfVersion>
</IfModule>
<IfModule !mod_version.c>
<IfModule !mod_authz_core.c>
<Files "*">
Order Allow,Deny
Deny from All
</Files>
</IfModule>
<IfModule mod_authz_core.c>
<Files "*">
Require all denied
</Files>
</IfModule>
</IfModule>

View File

@@ -0,0 +1,76 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class acp_prune_users_module extends \phpbb\db\migration\container_aware_migration
{
public function effectively_installed()
{
$sql = 'SELECT module_id
FROM ' . MODULES_TABLE . "
WHERE module_class = 'acp'
AND module_langname = 'ACP_CAT_USERS'";
$result = $this->db->sql_query($sql);
$acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
$sql = 'SELECT parent_id
FROM ' . MODULES_TABLE . "
WHERE module_class = 'acp'
AND module_basename = 'acp_prune'
AND module_mode = 'users'";
$result = $this->db->sql_query($sql);
$acp_prune_users_parent = (int) $this->db->sql_fetchfield('parent_id');
$this->db->sql_freeresult($result);
// Skip migration if "Users" category has been deleted
// or the module has already been moved to that category
return !$acp_cat_users_id || $acp_cat_users_id === $acp_prune_users_parent;
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\beta1');
}
public function update_data()
{
return array(
array('custom', array(array($this, 'move_prune_users_module'))),
);
}
public function move_prune_users_module()
{
$sql = 'SELECT module_id
FROM ' . MODULES_TABLE . "
WHERE module_class = 'acp'
AND module_basename = 'acp_prune'
AND module_mode = 'users'";
$result = $this->db->sql_query($sql);
$acp_prune_users_id = (int) $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
$sql = 'SELECT module_id
FROM ' . MODULES_TABLE . "
WHERE module_class = 'acp'
AND module_langname = 'ACP_CAT_USERS'";
$result = $this->db->sql_query($sql);
$acp_cat_users_id = (int) $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
$module_manager = $this->container->get('module.manager');
$module_manager->move_module($acp_prune_users_id, $acp_cat_users_id, 'acp');
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class acp_style_components_module extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
$sql = 'SELECT module_id
FROM ' . MODULES_TABLE . "
WHERE module_class = 'acp'
AND module_langname = 'ACP_STYLE_COMPONENTS'";
$result = $this->db->sql_query($sql);
$module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
return $module_id == false;
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\dev');
}
public function update_data()
{
return array(
array('module.remove', array(
'acp',
false,
'ACP_STYLE_COMPONENTS',
)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class allow_cdn extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['allow_cdn']);
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\jquery_update',
);
}
public function update_data()
{
return array(
array('config.add', array('allow_cdn', (int) $this->config['load_jquery_cdn'])),
array('config.remove', array('load_jquery_cdn')),
);
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class alpha1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-a1', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v30x\local_url_bbcode',
'\phpbb\db\migration\data\v30x\release_3_0_12',
'\phpbb\db\migration\data\v310\acp_style_components_module',
'\phpbb\db\migration\data\v310\allow_cdn',
'\phpbb\db\migration\data\v310\auth_provider_oauth',
'\phpbb\db\migration\data\v310\avatars',
'\phpbb\db\migration\data\v310\boardindex',
'\phpbb\db\migration\data\v310\config_db_text',
'\phpbb\db\migration\data\v310\forgot_password',
'\phpbb\db\migration\data\v310\mod_rewrite',
'\phpbb\db\migration\data\v310\mysql_fulltext_drop',
'\phpbb\db\migration\data\v310\namespaces',
'\phpbb\db\migration\data\v310\notifications_cron',
'\phpbb\db\migration\data\v310\notification_options_reconvert',
'\phpbb\db\migration\data\v310\plupload',
'\phpbb\db\migration\data\v310\signature_module_auth',
'\phpbb\db\migration\data\v310\softdelete_mcp_modules',
'\phpbb\db\migration\data\v310\teampage',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-a1')),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class alpha2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-a2', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\alpha1',
'\phpbb\db\migration\data\v310\notifications_cron_p2',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-a2')),
);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class alpha3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-a3', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\alpha2',
'\phpbb\db\migration\data\v310\avatar_types',
'\phpbb\db\migration\data\v310\passwords',
'\phpbb\db\migration\data\v310\profilefield_types',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-a3')),
);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class auth_provider_oauth extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'oauth_tokens');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_0');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'oauth_tokens' => array(
'COLUMNS' => array(
'user_id' => array('UINT', 0), // phpbb_users.user_id
'session_id' => array('CHAR:32', ''), // phpbb_sessions.session_id used only when user_id not set
'provider' => array('VCHAR', ''), // Name of the OAuth provider
'oauth_token' => array('MTEXT', ''), // Serialized token
),
'KEYS' => array(
'user_id' => array('INDEX', 'user_id'),
'provider' => array('INDEX', 'provider'),
),
),
$this->table_prefix . 'oauth_accounts' => array(
'COLUMNS' => array(
'user_id' => array('UINT', 0),
'provider' => array('VCHAR', ''),
'oauth_provider_id' => array('TEXT_UNI', ''),
),
'PRIMARY_KEY' => array(
'user_id',
'provider',
),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'oauth_tokens',
$this->table_prefix . 'oauth_accounts',
),
);
}
public function update_data()
{
return array(
array('module.add', array(
'ucp',
'UCP_PROFILE',
array(
'module_basename' => 'ucp_auth_link',
'module_langname' => 'UCP_AUTH_LINK_MANAGE',
'module_mode' => 'auth_link',
'module_auth' => 'authmethod_oauth',
),
)),
);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class auth_provider_oauth2 extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\auth_provider_oauth',
);
}
public function update_data()
{
return array(
array('custom', array(
array($this, 'update_auth_link_module_auth'),
)),
);
}
public function update_auth_link_module_auth()
{
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_auth = 'authmethod_oauth'
WHERE module_class = 'ucp'
AND module_basename = 'ucp_auth_link'
AND module_mode = 'auth_link'
AND module_auth = ''";
$this->db->sql_query($sql);
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class avatar_types extends \phpbb\db\migration\migration
{
/**
* @var avatar type map
*/
protected $avatar_type_map = array(
AVATAR_UPLOAD => 'avatar.driver.upload',
AVATAR_REMOTE => 'avatar.driver.remote',
AVATAR_GALLERY => 'avatar.driver.local',
);
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\dev',
'\phpbb\db\migration\data\v310\avatars',
);
}
public function update_data()
{
return array(
array('custom', array(array($this, 'update_user_avatar_type'))),
array('custom', array(array($this, 'update_group_avatar_type'))),
);
}
public function update_user_avatar_type()
{
foreach ($this->avatar_type_map as $old => $new)
{
$sql = 'UPDATE ' . $this->table_prefix . "users
SET user_avatar_type = '$new'
WHERE user_avatar_type = '$old'";
$this->db->sql_query($sql);
}
}
public function update_group_avatar_type()
{
foreach ($this->avatar_type_map as $old => $new)
{
$sql = 'UPDATE ' . $this->table_prefix . "groups
SET group_avatar_type = '$new'
WHERE group_avatar_type = '$old'";
$this->db->sql_query($sql);
}
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class avatars extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
// Get current avatar type of guest user
$sql = 'SELECT user_avatar_type
FROM ' . $this->table_prefix . 'users
WHERE user_id = ' . ANONYMOUS;
$result = $this->db->sql_query($sql);
$backup_type = $this->db->sql_fetchfield('user_avatar_type');
$this->db->sql_freeresult($result);
// Try to set avatar type to string
$sql = 'UPDATE ' . $this->table_prefix . "users
SET user_avatar_type = 'avatar.driver.upload'
WHERE user_id = " . ANONYMOUS;
$this->db->sql_return_on_error(true);
$effectively_installed = $this->db->sql_query($sql);
$this->db->sql_return_on_error();
// Restore avatar type of guest user to previous state
$sql = 'UPDATE ' . $this->table_prefix . "users
SET user_avatar_type = '{$backup_type}'
WHERE user_id = " . ANONYMOUS;
$this->db->sql_query($sql);
return $effectively_installed !== false;
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11');
}
public function update_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'users' => array(
'user_avatar_type' => array('VCHAR:255', ''),
),
$this->table_prefix . 'groups' => array(
'group_avatar_type' => array('VCHAR:255', ''),
),
),
);
}
public function revert_schema()
{
return array(
'change_columns' => array(
$this->table_prefix . 'users' => array(
'user_avatar_type' => array('TINT:2', ''),
),
$this->table_prefix . 'groups' => array(
'group_avatar_type' => array('TINT:2', ''),
),
),
);
}
public function update_data()
{
return array(
array('config.add', array('allow_avatar_gravatar', 0)),
array('custom', array(array($this, 'update_module_auth'))),
);
}
public function update_module_auth()
{
$sql = 'UPDATE ' . $this->table_prefix . "modules
SET module_auth = 'cfg_allow_avatar'
WHERE module_class = 'ucp'
AND module_basename = 'ucp_profile'
AND module_mode = 'avatar'";
$this->db->sql_query($sql);
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class beta1 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-b1', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\alpha3',
'\phpbb\db\migration\data\v310\passwords_p2',
'\phpbb\db\migration\data\v310\postgres_fulltext_drop',
'\phpbb\db\migration\data\v310\profilefield_change_load_settings',
'\phpbb\db\migration\data\v310\profilefield_location',
'\phpbb\db\migration\data\v310\soft_delete_mod_convert2',
'\phpbb\db\migration\data\v310\ucp_popuppm_module',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-b1')),
);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class beta2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-b2', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\beta1',
'\phpbb\db\migration\data\v310\acp_prune_users_module',
'\phpbb\db\migration\data\v310\profilefield_location_cleanup',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-b2')),
);
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class beta3 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-b3', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\beta2',
'\phpbb\db\migration\data\v310\auth_provider_oauth2',
'\phpbb\db\migration\data\v310\board_contact_name',
'\phpbb\db\migration\data\v310\jquery_update2',
'\phpbb\db\migration\data\v310\live_searches_config',
'\phpbb\db\migration\data\v310\prune_shadow_topics',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-b3')),
);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class beta4 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0-b4', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\beta3',
'\phpbb\db\migration\data\v310\extensions_version_check_force_unstable',
'\phpbb\db\migration\data\v310\reset_missing_captcha_plugin',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0-b4')),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class board_contact_name extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['board_contact_name']);
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\beta2');
}
public function update_data()
{
return array(
array('config.add', array('board_contact_name', '')),
);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class boardindex extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['board_index_text']);
}
public function update_data()
{
return array(
array('config.add', array('board_index_text', '')),
);
}
}

View File

@@ -0,0 +1,150 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class bot_update extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\rc6');
}
public function update_data()
{
return array(
array('custom', array(array(&$this, 'update_bing_bot'))),
array('custom', array(array(&$this, 'update_bots'))),
);
}
public function update_bing_bot()
{
$bot_name = 'Bing [Bot]';
$bot_name_clean = utf8_clean_string($bot_name);
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . "
WHERE username_clean = '" . $this->db->sql_escape($bot_name_clean) . "'";
$result = $this->db->sql_query($sql);
$bing_already_added = (bool) $this->db->sql_fetchfield('user_id');
$this->db->sql_freeresult($result);
if (!$bing_already_added)
{
$bot_agent = 'bingbot/';
$bot_ip = '';
$sql = 'SELECT group_id, group_colour
FROM ' . GROUPS_TABLE . "
WHERE group_name = 'BOTS'";
$result = $this->db->sql_query($sql);
$group_row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if (!$group_row)
{
// default fallback, should never get here
$group_row['group_id'] = 6;
$group_row['group_colour'] = '9E8DA7';
}
if (!function_exists('user_add'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$user_row = array(
'user_type' => USER_IGNORE,
'group_id' => $group_row['group_id'],
'username' => $bot_name,
'user_regdate' => time(),
'user_password' => '',
'user_colour' => $group_row['group_colour'],
'user_email' => '',
'user_lang' => $this->config['default_lang'],
'user_style' => $this->config['default_style'],
'user_timezone' => 0,
'user_dateformat' => $this->config['default_dateformat'],
'user_allow_massemail' => 0,
);
$user_id = user_add($user_row);
$sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $this->db->sql_build_array('INSERT', array(
'bot_active' => 1,
'bot_name' => (string) $bot_name,
'user_id' => (int) $user_id,
'bot_agent' => (string) $bot_agent,
'bot_ip' => (string) $bot_ip,
));
$this->sql_query($sql);
}
}
public function update_bots()
{
// Update bots
if (!function_exists('user_delete'))
{
include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
}
$bots_updates = array(
// Bot Deletions
'NG-Search [Bot]' => false,
'Nutch/CVS [Bot]' => false,
'OmniExplorer [Bot]' => false,
'Seekport [Bot]' => false,
'Synoo [Bot]' => false,
'WiseNut [Bot]' => false,
// Bot Updates
// Bot name to bot user agent map
'Baidu [Spider]' => 'Baiduspider',
'Exabot [Bot]' => 'Exabot',
'Voyager [Bot]' => 'voyager/',
'W3C [Validator]' => 'W3C_Validator',
);
foreach ($bots_updates as $bot_name => $bot_agent)
{
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . '
WHERE user_type = ' . USER_IGNORE . "
AND username_clean = '" . $this->db->sql_escape(utf8_clean_string($bot_name)) . "'";
$result = $this->db->sql_query($sql);
$bot_user_id = (int) $this->db->sql_fetchfield('user_id');
$this->db->sql_freeresult($result);
if ($bot_user_id)
{
if ($bot_agent === false)
{
$sql = 'DELETE FROM ' . BOTS_TABLE . "
WHERE user_id = $bot_user_id";
$this->sql_query($sql);
user_delete('retain', $bot_user_id);
}
else
{
$sql = 'UPDATE ' . BOTS_TABLE . "
SET bot_agent = '" . $this->db->sql_escape($bot_agent) . "'
WHERE user_id = $bot_user_id";
$this->sql_query($sql);
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class captcha_plugins extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\rc2',
);
}
public function update_data()
{
$captcha_plugin = $this->config['captcha_plugin'];
if (strpos($captcha_plugin, 'phpbb_captcha_') === 0)
{
$captcha_plugin = substr($captcha_plugin, strlen('phpbb_captcha_'));
}
else if (strpos($captcha_plugin, 'phpbb_') === 0)
{
$captcha_plugin = substr($captcha_plugin, strlen('phpbb_'));
}
return array(
array('if', array(
(is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)),
array('config.update', array('captcha_plugin', 'core.captcha.plugins.' . $captcha_plugin)),
)),
array('if', array(
(!is_file($this->phpbb_root_path . 'phpbb/captcha/plugins/' . $captcha_plugin . '.' . $this->php_ext)),
array('config.update', array('captcha_plugin', 'core.captcha.plugins.nogd')),
)),
);
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class config_db_text extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'config_text');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'config_text' => array(
'COLUMNS' => array(
'config_name' => array('VCHAR', ''),
'config_value' => array('MTEXT', ''),
),
'PRIMARY_KEY' => 'config_name',
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'config_text',
),
);
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class contact_admin_acp_module extends \phpbb\db\migration\migration
{
public function update_data()
{
return array(
array('module.add', array(
'acp',
'ACP_BOARD_CONFIGURATION',
array(
'module_basename' => 'acp_contact',
'module_langname' => 'ACP_CONTACT_SETTINGS',
'module_mode' => 'contact',
'module_auth' => 'acl_a_board',
),
)),
);
}
}

View File

@@ -0,0 +1,46 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class contact_admin_form extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['contact_admin_form_enable']);
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\config_db_text');
}
public function update_data()
{
return array(
array('config.add', array('contact_admin_form_enable', 1)),
array('custom', array(array($this, 'contact_admin_info'))),
);
}
public function contact_admin_info()
{
$text_config = new \phpbb\config\db_text($this->db, $this->table_prefix . 'config_text');
$text_config->set_array(array(
'contact_admin_info' => '',
'contact_admin_info_uid' => '',
'contact_admin_info_bitfield' => '',
'contact_admin_info_flags' => OPTION_FLAG_BBCODE + OPTION_FLAG_SMILIES + OPTION_FLAG_LINKS,
));
}
}

View File

@@ -0,0 +1,427 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class dev extends \phpbb\db\migration\container_aware_migration
{
public function effectively_installed()
{
return version_compare($this->config['version'], '3.1.0-dev', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\extensions',
'\phpbb\db\migration\data\v310\style_update_p2',
'\phpbb\db\migration\data\v310\timezone_p2',
'\phpbb\db\migration\data\v310\reported_posts_display',
'\phpbb\db\migration\data\v310\migrations_table',
);
}
public function update_schema()
{
return array(
'add_columns' => array(
$this->table_prefix . 'groups' => array(
'group_teampage' => array('UINT', 0, 'after' => 'group_legend'),
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_pm' => array('BOOL', 0),
),
$this->table_prefix . 'styles' => array(
'style_path' => array('VCHAR:100', ''),
'bbcode_bitfield' => array('VCHAR:255', 'kNg='),
'style_parent_id' => array('UINT:4', 0),
'style_parent_tree' => array('TEXT', ''),
),
$this->table_prefix . 'reports' => array(
'reported_post_text' => array('MTEXT_UNI', ''),
'reported_post_uid' => array('VCHAR:8', ''),
'reported_post_bitfield' => array('VCHAR:255', ''),
),
),
'change_columns' => array(
$this->table_prefix . 'groups' => array(
'group_legend' => array('UINT', 0),
),
),
);
}
public function revert_schema()
{
return array(
'drop_columns' => array(
$this->table_prefix . 'groups' => array(
'group_teampage',
),
$this->table_prefix . 'profile_fields' => array(
'field_show_on_pm',
),
$this->table_prefix . 'styles' => array(
'style_path',
'bbcode_bitfield',
'style_parent_id',
'style_parent_tree',
),
$this->table_prefix . 'reports' => array(
'reported_post_text',
'reported_post_uid',
'reported_post_bitfield',
),
),
);
}
public function update_data()
{
return array(
array('if', array(
(strpos('phpbb_search_', $this->config['search_type']) !== 0),
array('config.update', array('search_type', 'phpbb_search_' . $this->config['search_type'])),
)),
array('config.add', array('fulltext_postgres_ts_name', 'simple')),
array('config.add', array('fulltext_postgres_min_word_len', 4)),
array('config.add', array('fulltext_postgres_max_word_len', 254)),
array('config.add', array('fulltext_sphinx_stopwords', 0)),
array('config.add', array('fulltext_sphinx_indexer_mem_limit', 512)),
array('config.add', array('load_jquery_cdn', 0)),
array('config.add', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js')),
array('config.add', array('use_system_cron', 0)),
array('config.add', array('legend_sort_groupname', 0)),
array('config.add', array('teampage_forums', 1)),
array('config.add', array('teampage_memberships', 1)),
array('config.add', array('load_cpf_pm', 0)),
array('config.add', array('display_last_subject', 1)),
array('config.add', array('assets_version', 1)),
array('config.add', array('site_home_url', '')),
array('config.add', array('site_home_text', '')),
array('permission.add', array('u_chgprofileinfo', true, 'u_sig')),
array('module.add', array(
'acp',
'ACP_GROUPS',
array(
'module_basename' => 'acp_groups',
'module_langname' => 'ACP_GROUPS_POSITION',
'module_mode' => 'position',
'module_auth' => 'acl_a_group',
),
)),
array('module.add', array(
'acp',
'ACP_ATTACHMENTS',
array(
'module_basename' => 'acp_attachments',
'module_langname' => 'ACP_MANAGE_ATTACHMENTS',
'module_mode' => 'manage',
'module_auth' => 'acl_a_attach',
),
)),
array('module.add', array(
'acp',
'ACP_STYLE_MANAGEMENT',
array(
'module_basename' => 'acp_styles',
'module_langname' => 'ACP_STYLES_INSTALL',
'module_mode' => 'install',
'module_auth' => 'acl_a_styles',
),
)),
array('module.add', array(
'acp',
'ACP_STYLE_MANAGEMENT',
array(
'module_basename' => 'acp_styles',
'module_langname' => 'ACP_STYLES_CACHE',
'module_mode' => 'cache',
'module_auth' => 'acl_a_styles',
),
)),
array('module.add', array(
'ucp',
'UCP_PROFILE',
array(
'module_basename' => 'ucp_profile',
'module_langname' => 'UCP_PROFILE_AUTOLOGIN_KEYS',
'module_mode' => 'autologin_keys',
),
)),
// Module will be renamed later
array('module.add', array(
'acp',
'ACP_CAT_STYLES',
'ACP_LANGUAGE'
)),
array('module.remove', array(
'acp',
false,
'ACP_TEMPLATES',
)),
array('module.remove', array(
'acp',
false,
'ACP_THEMES',
)),
array('module.remove', array(
'acp',
false,
'ACP_IMAGESETS',
)),
array('custom', array(array($this, 'rename_module_basenames'))),
array('custom', array(array($this, 'rename_styles_module'))),
array('custom', array(array($this, 'add_group_teampage'))),
array('custom', array(array($this, 'update_group_legend'))),
array('custom', array(array($this, 'localise_global_announcements'))),
array('custom', array(array($this, 'update_ucp_pm_basename'))),
array('custom', array(array($this, 'update_ucp_profile_auth'))),
array('custom', array(array($this, 'move_customise_modules'))),
array('config.update', array('version', '3.1.0-dev')),
);
}
public function move_customise_modules()
{
// Move language management to new location in the Customise tab
// First get language module id
$sql = 'SELECT module_id FROM ' . MODULES_TABLE . "
WHERE module_basename = 'acp_language'";
$result = $this->db->sql_query($sql);
$language_module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
// Next get language management module id of the one just created
$sql = 'SELECT module_id FROM ' . MODULES_TABLE . "
WHERE module_langname = 'ACP_LANGUAGE'";
$result = $this->db->sql_query($sql);
$language_management_module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
// acp_modules calls adm_back_link, which is undefined at this point
if (!function_exists('adm_back_link'))
{
include($this->phpbb_root_path . 'includes/functions_acp.' . $this->php_ext);
}
$module_manager = $this->container->get('module.manager');
$module_manager->move_module($language_module_id, $language_management_module_id, 'acp');
}
public function update_ucp_pm_basename()
{
$sql = 'SELECT module_id, module_basename
FROM ' . MODULES_TABLE . "
WHERE module_basename <> 'ucp_pm' AND
module_langname='UCP_PM'";
$result = $this->db->sql_query_limit($sql, 1);
if ($row = $this->db->sql_fetchrow($result))
{
// This update is still not applied. Applying it
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_basename = 'ucp_pm'
WHERE module_id = " . (int) $row['module_id'];
$this->sql_query($sql);
}
$this->db->sql_freeresult($result);
}
public function update_ucp_profile_auth()
{
// Update the auth setting for the module
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_auth = 'acl_u_chgprofileinfo'
WHERE module_class = 'ucp'
AND module_basename = 'ucp_profile'
AND module_mode = 'profile_info'";
$this->sql_query($sql);
}
public function rename_styles_module()
{
// Rename styles module to Customise
$sql = 'UPDATE ' . MODULES_TABLE . "
SET module_langname = 'ACP_CAT_CUSTOMISE'
WHERE module_langname = 'ACP_CAT_STYLES'";
$this->sql_query($sql);
}
public function rename_module_basenames()
{
// rename all module basenames to full classname
$sql = 'SELECT module_id, module_basename, module_class
FROM ' . MODULES_TABLE;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$module_id = (int) $row['module_id'];
unset($row['module_id']);
if (!empty($row['module_basename']) && !empty($row['module_class']))
{
// all the class names start with class name or with phpbb_ for auto loading
if (strpos($row['module_basename'], $row['module_class'] . '_') !== 0 &&
strpos($row['module_basename'], 'phpbb_') !== 0)
{
$row['module_basename'] = $row['module_class'] . '_' . $row['module_basename'];
$sql_update = $this->db->sql_build_array('UPDATE', $row);
$sql = 'UPDATE ' . MODULES_TABLE . '
SET ' . $sql_update . '
WHERE module_id = ' . $module_id;
$this->sql_query($sql);
}
}
}
$this->db->sql_freeresult($result);
}
public function add_group_teampage()
{
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_teampage = 1
WHERE group_type = ' . GROUP_SPECIAL . "
AND group_name = 'ADMINISTRATORS'";
$this->sql_query($sql);
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_teampage = 2
WHERE group_type = ' . GROUP_SPECIAL . "
AND group_name = 'GLOBAL_MODERATORS'";
$this->sql_query($sql);
}
public function update_group_legend()
{
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . '
WHERE group_legend = 1
ORDER BY group_name ASC';
$result = $this->db->sql_query($sql);
$next_legend = 1;
while ($row = $this->db->sql_fetchrow($result))
{
$sql = 'UPDATE ' . GROUPS_TABLE . '
SET group_legend = ' . $next_legend . '
WHERE group_id = ' . (int) $row['group_id'];
$this->sql_query($sql);
$next_legend++;
}
$this->db->sql_freeresult($result);
}
public function localise_global_announcements()
{
// Localise Global Announcements
$sql = 'SELECT topic_id, topic_approved, (topic_replies + 1) AS topic_posts, topic_last_post_id, topic_last_post_subject, topic_last_post_time, topic_last_poster_id, topic_last_poster_name, topic_last_poster_colour
FROM ' . TOPICS_TABLE . '
WHERE forum_id = 0
AND topic_type = ' . POST_GLOBAL;
$result = $this->db->sql_query($sql);
$global_announcements = $update_lastpost_data = array();
$update_lastpost_data['forum_last_post_time'] = 0;
$update_forum_data = array(
'forum_posts' => 0,
'forum_topics' => 0,
'forum_topics_real' => 0,
);
while ($row = $this->db->sql_fetchrow($result))
{
$global_announcements[] = (int) $row['topic_id'];
$update_forum_data['forum_posts'] += (int) $row['topic_posts'];
$update_forum_data['forum_topics_real']++;
if ($row['topic_approved'])
{
$update_forum_data['forum_topics']++;
}
if ($update_lastpost_data['forum_last_post_time'] < $row['topic_last_post_time'])
{
$update_lastpost_data = array(
'forum_last_post_id' => (int) $row['topic_last_post_id'],
'forum_last_post_subject' => $row['topic_last_post_subject'],
'forum_last_post_time' => (int) $row['topic_last_post_time'],
'forum_last_poster_id' => (int) $row['topic_last_poster_id'],
'forum_last_poster_name' => $row['topic_last_poster_name'],
'forum_last_poster_colour' => $row['topic_last_poster_colour'],
);
}
}
$this->db->sql_freeresult($result);
if (!empty($global_announcements))
{
// Update the post/topic-count for the forum and the last-post if needed
$sql = 'SELECT forum_id
FROM ' . FORUMS_TABLE . '
WHERE forum_type = ' . FORUM_POST;
$result = $this->db->sql_query_limit($sql, 1);
$ga_forum_id = $this->db->sql_fetchfield('forum_id');
$this->db->sql_freeresult($result);
$sql = 'SELECT forum_last_post_time
FROM ' . FORUMS_TABLE . '
WHERE forum_id = ' . $ga_forum_id;
$result = $this->db->sql_query($sql);
$lastpost = (int) $this->db->sql_fetchfield('forum_last_post_time');
$this->db->sql_freeresult($result);
$sql_update = 'forum_posts = forum_posts + ' . $update_forum_data['forum_posts'] . ', ';
$sql_update .= 'forum_topics_real = forum_topics_real + ' . $update_forum_data['forum_topics_real'] . ', ';
$sql_update .= 'forum_topics = forum_topics + ' . $update_forum_data['forum_topics'];
if ($lastpost < $update_lastpost_data['forum_last_post_time'])
{
$sql_update .= ', ' . $this->db->sql_build_array('UPDATE', $update_lastpost_data);
}
$sql = 'UPDATE ' . FORUMS_TABLE . '
SET ' . $sql_update . '
WHERE forum_id = ' . $ga_forum_id;
$this->sql_query($sql);
// Update some forum_ids
$table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);
foreach ($table_ary as $table)
{
$sql = "UPDATE $table
SET forum_id = $ga_forum_id
WHERE " . $this->db->sql_in_set('topic_id', $global_announcements);
$this->sql_query($sql);
}
unset($table_ary);
}
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class extensions extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return $this->db_tools->sql_table_exists($this->table_prefix . 'ext');
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11');
}
public function update_schema()
{
return array(
'add_tables' => array(
$this->table_prefix . 'ext' => array(
'COLUMNS' => array(
'ext_name' => array('VCHAR', ''),
'ext_active' => array('BOOL', 0),
'ext_state' => array('TEXT', ''),
),
'KEYS' => array(
'ext_name' => array('UNIQUE', 'ext_name'),
),
),
),
);
}
public function revert_schema()
{
return array(
'drop_tables' => array(
$this->table_prefix . 'ext',
),
);
}
public function update_data()
{
return array(
// Module will be renamed later
array('module.add', array(
'acp',
'ACP_CAT_STYLES',
'ACP_EXTENSION_MANAGEMENT'
)),
array('module.add', array(
'acp',
'ACP_EXTENSION_MANAGEMENT',
array(
'module_basename' => 'acp_extensions',
'module_langname' => 'ACP_EXTENSIONS',
'module_mode' => 'main',
'module_auth' => 'acl_a_extensions',
),
)),
array('permission.add', array('a_extensions', true, 'a_styles')),
);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class extensions_version_check_force_unstable extends \phpbb\db\migration\migration
{
static public function depends_on()
{
return array('\phpbb\db\migration\data\v310\dev');
}
public function update_data()
{
return array(
array('config.add', array('extension_force_unstable', false)),
);
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class forgot_password extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['allow_password_reset']);
}
static public function depends_on()
{
return array('\phpbb\db\migration\data\v30x\release_3_0_11');
}
public function update_data()
{
return array(
array('config.add', array('allow_password_reset', 1)),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class gold extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return phpbb_version_compare($this->config['version'], '3.1.0', '>=');
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\rc6',
'\phpbb\db\migration\data\v310\bot_update',
);
}
public function update_data()
{
return array(
array('config.update', array('version', '3.1.0')),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class jquery_update extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js';
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\dev',
);
}
public function update_data()
{
return array(
array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js')),
);
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class jquery_update2 extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return $this->config['load_jquery_url'] !== '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js';
}
static public function depends_on()
{
return array(
'\phpbb\db\migration\data\v310\jquery_update',
);
}
public function update_data()
{
return array(
array('config.update', array('load_jquery_url', '//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js')),
);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\db\migration\data\v310;
class live_searches_config extends \phpbb\db\migration\migration
{
public function effectively_installed()
{
return isset($this->config['allow_live_searches']);
}
public function update_data()
{
return array(
array('config.add', array('allow_live_searches', '1')),
);
}
}

Some files were not shown because too many files have changed in this diff Show More