diff options
Diffstat (limited to 'phpBB/includes')
44 files changed, 1144 insertions, 2817 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 6bef42c472..7413152e7a 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -36,13 +36,16 @@ class acp_attachments /** @var \phpbb\user */ protected $user; + /** @var \phpbb\filesystem\filesystem_interface */ + protected $filesystem; + public $id; public $u_action; protected $new_config; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_container; + global $db, $user, $auth, $template, $cache, $phpbb_container, $phpbb_filesystem; global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx, $phpbb_log, $request; $this->id = $id; @@ -51,6 +54,7 @@ class acp_attachments $this->template = $template; $this->user = $user; $this->phpbb_container = $phpbb_container; + $this->filesystem = $phpbb_filesystem; $user->add_lang(array('posting', 'viewtopic', 'acp/attachments')); @@ -153,7 +157,7 @@ class acp_attachments 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int:0:999999999999999', 'type' => 'number:0:999999999999999', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), - 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'path', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), + 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'absolute_path', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0:9999', 'type' => 'dimension:0:9999', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), ) @@ -1501,7 +1505,15 @@ class acp_attachments if (!file_exists($phpbb_root_path . $upload_dir)) { @mkdir($phpbb_root_path . $upload_dir, 0777); - phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($phpbb_root_path . $upload_dir, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -1517,7 +1529,7 @@ class acp_attachments return; } - if (!phpbb_is_writable($phpbb_root_path . $upload_dir)) + if (!$this->filesystem->is_writable($phpbb_root_path . $upload_dir)) { $error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir); return; diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index a5cd48c444..2b438e5670 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -25,7 +25,7 @@ class acp_bbcodes function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher; + global $db, $user, $auth, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; $user->add_lang('acp/posting'); @@ -269,6 +269,7 @@ class acp_bbcodes $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_ADDED'; $log_action = 'LOG_BBCODE_ADD'; @@ -280,6 +281,7 @@ class acp_bbcodes WHERE bbcode_id = ' . $bbcode_id; $db->sql_query($sql); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $lang = 'BBCODE_EDITED'; $log_action = 'LOG_BBCODE_EDIT'; @@ -319,6 +321,7 @@ class acp_bbcodes { $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); $cache->destroy('sql', BBCODES_TABLE); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($row['bbcode_tag'])); if ($request->is_ajax()) @@ -413,8 +416,6 @@ class acp_bbcodes // Allow unicode characters for URL|LOCAL_URL|RELATIVE_URL|INTTEXT tokens $utf8 = preg_match('/(URL|LOCAL_URL|RELATIVE_URL|INTTEXT)/', $bbcode_match); - $utf8_pcre_properties = phpbb_pcre_utf8_support(); - $fp_match = preg_quote($bbcode_match, '!'); $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace); @@ -445,7 +446,7 @@ class acp_bbcodes '!([a-zA-Z0-9-+.,_ ]+)!' => "$1" ), 'INTTEXT' => array( - ($utf8_pcre_properties) ? '!([\p{L}\p{N}\-+,_. ]+)!u' : '!([a-zA-Z0-9\-+,_. ]+)!u' => "$1" + '!([\p{L}\p{N}\-+,_. ]+)!u' => "$1" ), 'IDENTIFIER' => array( '!([a-zA-Z0-9-_]+)!' => "$1" @@ -465,7 +466,7 @@ class acp_bbcodes 'EMAIL' => '(' . get_preg_expression('email') . ')', 'TEXT' => '(.*?)', 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', - 'INTTEXT' => ($utf8_pcre_properties) ? '([\p{L}\p{N}\-+,_. ]+)' : '([a-zA-Z0-9\-+,_. ]+)', + 'INTTEXT' => '([\p{L}\p{N}\-+,_. ]+)', 'IDENTIFIER' => '([a-zA-Z0-9-_]+)', 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)', 'NUMBER' => '([0-9]+)', @@ -473,7 +474,7 @@ class acp_bbcodes $pad = 0; $modifiers = 'i'; - $modifiers .= ($utf8 && $utf8_pcre_properties) ? 'u' : ''; + $modifiers .= ($utf8) ? 'u' : ''; if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m)) { diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 965f1a6f70..ff3b50174b 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -515,7 +515,8 @@ class acp_board if ($config_name == 'guest_style') { - if (isset($cfg_array[$config_name])) { + if (isset($cfg_array[$config_name])) + { $this->guest_style_set($cfg_array[$config_name]); } continue; diff --git a/phpBB/includes/acp/acp_contact.php b/phpBB/includes/acp/acp_contact.php index 2aa6620835..1a4d5b95a3 100644 --- a/phpBB/includes/acp/acp_contact.php +++ b/phpBB/includes/acp/acp_contact.php @@ -105,6 +105,9 @@ class acp_contact $contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'ERRORS' => $error, 'CONTACT_ENABLED' => $config['contact_admin_form_enable'], @@ -116,7 +119,7 @@ class acp_contact 'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'], 'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'], - 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'], 'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'], 'FLASH_STATUS' => $user->lang['FLASH_IS_ON'], diff --git a/phpBB/includes/acp/acp_database.php b/phpBB/includes/acp/acp_database.php index fb02e58b13..984301a38f 100644 --- a/phpBB/includes/acp/acp_database.php +++ b/phpBB/includes/acp/acp_database.php @@ -26,10 +26,10 @@ class acp_database function main($id, $mode) { - global $cache, $db, $user, $auth, $template, $table_prefix, $request; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_log; + global $cache, $db, $user, $template, $table_prefix, $request; + global $phpbb_root_path, $phpbb_container, $phpbb_log; - $this->db_tools = new \phpbb\db\tools\tools($db); + $this->db_tools = $phpbb_container->get('dbal.tools'); $user->add_lang('acp/database'); @@ -90,36 +90,9 @@ class acp_database $time = time(); $filename = 'backup_' . $time . '_' . unique_id(); - switch ($db->get_sql_layer()) - { - case 'mysqli': - case 'mysql4': - case 'mysql': - $extractor = new mysql_extractor($format, $filename, $time, $download, $store); - break; - - case 'sqlite': - $extractor = new sqlite_extractor($format, $filename, $time, $download, $store); - break; - case 'sqlite3': - $extractor = new sqlite3_extractor($format, $filename, $time, $download, $store); - break; - - case 'postgres': - $extractor = new postgres_extractor($format, $filename, $time, $download, $store); - break; - - case 'oracle': - $extractor = new oracle_extractor($format, $filename, $time, $download, $store); - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $extractor = new mssql_extractor($format, $filename, $time, $download, $store); - break; - } + $extractor = $phpbb_container->get('dbal.extractor'); + $extractor->init_extractor($format, $filename, $time, $download, $store); $extractor->write_start($table_prefix); @@ -461,1637 +434,6 @@ class acp_database } } -class base_extractor -{ - var $fh; - var $fp; - var $write; - var $close; - var $store; - var $download; - var $time; - var $format; - var $run_comp = false; - - function base_extractor($format, $filename, $time, $download = false, $store = false) - { - global $request; - - $this->download = $download; - $this->store = $store; - $this->time = $time; - $this->format = $format; - - switch ($format) - { - case 'text': - $ext = '.sql'; - $open = 'fopen'; - $this->write = 'fwrite'; - $this->close = 'fclose'; - $mimetype = 'text/x-sql'; - break; - case 'bzip2': - $ext = '.sql.bz2'; - $open = 'bzopen'; - $this->write = 'bzwrite'; - $this->close = 'bzclose'; - $mimetype = 'application/x-bzip2'; - break; - case 'gzip': - $ext = '.sql.gz'; - $open = 'gzopen'; - $this->write = 'gzwrite'; - $this->close = 'gzclose'; - $mimetype = 'application/x-gzip'; - break; - } - - if ($download == true) - { - $name = $filename . $ext; - header('Cache-Control: private, no-cache'); - header("Content-Type: $mimetype; name=\"$name\""); - header("Content-disposition: attachment; filename=$name"); - - switch ($format) - { - case 'bzip2': - ob_start(); - break; - - case 'gzip': - if (strpos($request->header('Accept-Encoding'), 'gzip') !== false && strpos(strtolower($request->header('User-Agent')), 'msie') === false) - { - ob_start('ob_gzhandler'); - } - else - { - $this->run_comp = true; - } - break; - } - } - - if ($store == true) - { - global $phpbb_root_path; - $file = $phpbb_root_path . 'store/' . $filename . $ext; - - $this->fp = $open($file, 'w'); - - if (!$this->fp) - { - trigger_error('FILE_WRITE_FAIL', E_USER_ERROR); - } - } - } - - function write_end() - { - static $close; - - if ($this->store) - { - if ($close === null) - { - $close = $this->close; - } - $close($this->fp); - } - - // bzip2 must be written all the way at the end - if ($this->download && $this->format === 'bzip2') - { - $c = ob_get_clean(); - echo bzcompress($c); - } - } - - function flush($data) - { - static $write; - if ($this->store === true) - { - if ($write === null) - { - $write = $this->write; - } - $write($this->fp, $data); - } - - if ($this->download === true) - { - if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) - { - echo $data; - } - - // we can write the gzip data as soon as we get it - if ($this->format === 'gzip') - { - if ($this->run_comp) - { - echo gzencode($data); - } - else - { - ob_flush(); - flush(); - } - } - } - } -} - -class mysql_extractor extends base_extractor -{ - function write_start($table_prefix) - { - $sql_data = "#\n"; - $sql_data .= "# phpBB Backup Script\n"; - $sql_data .= "# Dump of tables for $table_prefix\n"; - $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "#\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $new_extract; - - if ($new_extract === null) - { - if ($db->get_sql_layer() === 'mysqli' || version_compare($db->sql_server_info(true), '3.23.20', '>=')) - { - $new_extract = true; - } - else - { - $new_extract = false; - } - } - - if ($new_extract) - { - $this->new_write_table($table_name); - } - else - { - $this->old_write_table($table_name); - } - } - - function write_data($table_name) - { - global $db; - if ($db->get_sql_layer() === 'mysqli') - { - $this->write_data_mysqli($table_name); - } - else - { - $this->write_data_mysql($table_name); - } - } - - function write_data_mysqli($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysqli_query($db->get_db_connect_id(), $sql, MYSQLI_USE_RESULT); - if ($result != false) - { - $fields_cnt = mysqli_num_fields($result); - - // Get field information - $field = mysqli_fetch_fields($result); - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysqli_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysqli_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function write_data_mysql($table_name) - { - global $db; - $sql = "SELECT * - FROM $table_name"; - $result = mysql_unbuffered_query($sql, $db->get_db_connect_id()); - - if ($result != false) - { - $fields_cnt = mysql_num_fields($result); - - // Get field information - $field = array(); - for ($i = 0; $i < $fields_cnt; $i++) - { - $field[] = mysql_fetch_field($result, $i); - } - $field_set = array(); - - for ($j = 0; $j < $fields_cnt; $j++) - { - $field_set[] = $field[$j]->name; - } - - $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); - $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); - $fields = implode(', ', $field_set); - $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; - $first_set = true; - $query_len = 0; - $max_len = get_usable_memory(); - - while ($row = mysql_fetch_row($result)) - { - $values = array(); - if ($first_set) - { - $query = $sql_data . '('; - } - else - { - $query .= ',('; - } - - for ($j = 0; $j < $fields_cnt; $j++) - { - if (!isset($row[$j]) || is_null($row[$j])) - { - $values[$j] = 'NULL'; - } - else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) - { - $values[$j] = $row[$j]; - } - else - { - $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; - } - } - $query .= implode(', ', $values) . ')'; - - $query_len += strlen($query); - if ($query_len > $max_len) - { - $this->flush($query . ";\n\n"); - $query = ''; - $query_len = 0; - $first_set = true; - } - else - { - $first_set = false; - } - } - mysql_free_result($result); - - // check to make sure we have nothing left to flush - if (!$first_set && $query) - { - $this->flush($query . ";\n\n"); - } - } - } - - function new_write_table($table_name) - { - global $db; - - $sql = 'SHOW CREATE TABLE ' . $table_name; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $this->flush($sql_data . $row['Create Table'] . ";\n\n"); - - $db->sql_freeresult($result); - } - - function old_write_table($table_name) - { - global $db; - - $sql_data = '# Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; - $sql_data .= "CREATE TABLE $table_name(\n"; - $rows = array(); - - $sql = "SHOW FIELDS - FROM $table_name"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = ' ' . $row['Field'] . ' ' . $row['Type']; - - if (!is_null($row['Default'])) - { - $line .= " DEFAULT '{$row['Default']}'"; - } - - if ($row['Null'] != 'YES') - { - $line .= ' NOT NULL'; - } - - if ($row['Extra'] != '') - { - $line .= ' ' . $row['Extra']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SHOW KEYS - FROM $table_name"; - - $result = $db->sql_query($sql); - - $index = array(); - while ($row = $db->sql_fetchrow($result)) - { - $kname = $row['Key_name']; - - if ($kname != 'PRIMARY') - { - if ($row['Non_unique'] == 0) - { - $kname = "UNIQUE|$kname"; - } - } - - if ($row['Sub_part']) - { - $row['Column_name'] .= '(' . $row['Sub_part'] . ')'; - } - $index[$kname][] = $row['Column_name']; - } - $db->sql_freeresult($result); - - foreach ($index as $key => $columns) - { - $line = ' '; - - if ($key == 'PRIMARY') - { - $line .= 'PRIMARY KEY (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'UNIQUE') === 0) - { - $line .= 'UNIQUE ' . substr($key, 7) . ' (' . implode(', ', $columns) . ')'; - } - else if (strpos($key, 'FULLTEXT') === 0) - { - $line .= 'FULLTEXT ' . substr($key, 9) . ' (' . implode(', ', $columns) . ')'; - } - else - { - $line .= "KEY $key (" . implode(', ', $columns) . ')'; - } - - $rows[] = $line; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n);\n\n"; - - $this->flush($sql_data); - } -} - -class sqlite_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . $db->sql_escape($table_name) . "' - ORDER BY type DESC, name;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create Table - $sql_data .= $row['sql'] . ";\n"; - - $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); - - $ar = array(); - while ($row = $db->sql_fetchrow($result)) - { - $ar[] = $row; - } - $db->sql_freeresult($result); - - foreach ($ar as $value) - { - if (strpos($value['name'], 'autoindex') !== false) - { - continue; - } - - $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');"); - - $fields = array(); - while ($row = $db->sql_fetchrow($result)) - { - $fields[] = $row['name']; - } - $db->sql_freeresult($result); - - $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; - } - - $this->flush($sql_data . "\n"); - } - - function write_data($table_name) - { - global $db; - - $col_types = sqlite_fetch_column_types($db->get_db_connect_id(), $table_name); - - $sql = "SELECT * - FROM $table_name"; - $result = sqlite_unbuffered_query($db->get_db_connect_id(), $sql); - $rows = sqlite_fetch_all($result, SQLITE_ASSOC); - $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; - foreach ($rows as $row) - { - foreach ($row as $column_name => $column_data) - { - if (is_null($column_data)) - { - $row[$column_name] = 'NULL'; - } - else if ($column_data == '') - { - $row[$column_name] = "''"; - } - else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) - { - $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); - } - } - $this->flush($sql_insert . implode(', ', $row) . ");\n"); - } - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class sqlite3_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '" . $db->sql_escape($table_name) . "' - ORDER BY name ASC;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // Create Table - $sql_data .= $row['sql'] . ";\n"; - - $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); - - while ($row = $db->sql_fetchrow($result)) - { - if (strpos($row['name'], 'autoindex') !== false) - { - continue; - } - - $result2 = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($row['name']) . "');"); - - $fields = array(); - while ($row2 = $db->sql_fetchrow($result2)) - { - $fields[] = $row2['name']; - } - $db->sql_freeresult($result2); - - $sql_data .= 'CREATE ' . ($row['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $row['name'] . ' ON ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; - } - $db->sql_freeresult($result); - - $this->flush($sql_data . "\n"); - } - - function write_data($table_name) - { - global $db; - - $result = $db->sql_query("PRAGMA table_info('" . $db->sql_escape($table_name) . "');"); - - $col_types = array(); - while ($row = $db->sql_fetchrow($result)) - { - $col_types[$row['name']] = $row['type']; - } - $db->sql_freeresult($result); - - $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; - - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - foreach ($row as $column_name => $column_data) - { - if (is_null($column_data)) - { - $row[$column_name] = 'NULL'; - } - else if ($column_data === '') - { - $row[$column_name] = "''"; - } - else if (stripos($col_types[$column_name], 'text') !== false || stripos($col_types[$column_name], 'char') !== false || stripos($col_types[$column_name], 'blob') !== false) - { - $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); - } - } - $this->flush($sql_insert . implode(', ', $row) . ");\n"); - } - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class postgres_extractor extends base_extractor -{ - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION;\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - static $domains_created = array(); - - $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default - FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b - WHERE a.domain_name = b.domain_name - AND b.table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (empty($domains_created[$row['domain_name']])) - { - $domains_created[$row['domain_name']] = true; - //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; - $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; - if (!empty($row['character_maximum_length'])) - { - $sql_data .= '(' . $row['character_maximum_length'] . ')'; - } - $sql_data .= ' NOT NULL'; - if (!empty($row['domain_default'])) - { - $sql_data .= ' DEFAULT ' . $row['domain_default']; - } - $this->flush($sql_data . ";\n"); - } - } - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $db->sql_query($sql); - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($db->sql_fetchrow($result)) - { - $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; - $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; - } - $db->sql_freeresult($result); - - $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull - FROM pg_class c, pg_attribute a, pg_type t - WHERE c.relname = '" . $db->sql_escape($table_name) . "' - AND a.attnum > 0 - AND a.attrelid = c.oid - AND a.atttypid = t.oid - ORDER BY a.attnum"; - $result = $db->sql_query($field_query); - - $sql_data .= "CREATE TABLE $table_name(\n"; - $lines = array(); - while ($row = $db->sql_fetchrow($result)) - { - // Get the data from the table - $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '" . $db->sql_escape($table_name) . "') - AND (c.oid = d.adrelid) - AND d.adnum = " . $row['attnum']; - $def_res = $db->sql_query($sql_get_default); - $def_row = $db->sql_fetchrow($def_res); - $db->sql_freeresult($def_res); - - if (empty($def_row)) - { - unset($row['rowdefault']); - } - else - { - $row['rowdefault'] = $def_row['rowdefault']; - } - - if ($row['type'] == 'bpchar') - { - // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. - $row['type'] = 'char'; - } - - $line = ' ' . $row['field'] . ' ' . $row['type']; - - if (strpos($row['type'], 'char') !== false) - { - if ($row['lengthvar'] > 0) - { - $line .= '(' . ($row['lengthvar'] - 4) . ')'; - } - } - - if (strpos($row['type'], 'numeric') !== false) - { - $line .= '('; - $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); - $line .= ')'; - } - - if (isset($row['rowdefault'])) - { - $line .= ' DEFAULT ' . $row['rowdefault']; - } - - if ($row['notnull'] == 't') - { - $line .= ' NOT NULL'; - } - - $lines[] = $line; - } - $db->sql_freeresult($result); - - // Get the listing of primary keys. - $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key - FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (ia.attrelid = i.indexrelid) - AND (ta.attrelid = bc.oid) - AND (bc.relname = '" . $db->sql_escape($table_name) . "') - AND (ta.attrelid = i.indrelid) - AND (ta.attnum = i.indkey[ia.attnum-1]) - ORDER BY index_name, tab_name, column_name"; - - $result = $db->sql_query($sql_pri_keys); - - $index_create = $index_rows = $primary_key = array(); - - // We do this in two steps. It makes placing the comma easier - while ($row = $db->sql_fetchrow($result)) - { - if ($row['primary_key'] == 't') - { - $primary_key[] = $row['column_name']; - $primary_key_name = $row['index_name']; - } - else - { - // We have to store this all this info because it is possible to have a multi-column key... - // we can loop through it again and build the statement - $index_rows[$row['index_name']]['table'] = $table_name; - $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; - $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; - } - } - $db->sql_freeresult($result); - - if (!empty($index_rows)) - { - foreach ($index_rows as $idx_name => $props) - { - $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; - } - } - - if (!empty($primary_key)) - { - $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; - } - - // Generate constraint clauses for CHECK constraints - $sql_checks = "SELECT conname as index_name, consrc - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '" . $db->sql_escape($table_name) . "' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - $result = $db->sql_query($sql_checks); - - // Add the constraints to the sql file. - while ($row = $db->sql_fetchrow($result)) - { - if (!is_null($row['consrc'])) - { - $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; - } - } - $db->sql_freeresult($result); - - $sql_data .= implode(", \n", $lines); - $sql_data .= "\n);\n"; - - if (!empty($index_create)) - { - $sql_data .= implode("\n", $index_create) . "\n\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = pg_num_fields($result); - $seq = ''; - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[] = pg_field_type($result, $i); - $ary_name[] = pg_field_name($result, $i); - - $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault - FROM pg_attrdef d, pg_class c - WHERE (c.relname = '{$table_name}') - AND (c.oid = d.adrelid) - AND d.adnum = " . strval($i + 1); - $result2 = $db->sql_query($sql); - if ($row = $db->sql_fetchrow($result2)) - { - // Determine if we must reset the sequences - if (strpos($row['rowdefault'], "nextval('") === 0) - { - $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; - } - } - } - - $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) - { - $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); - $str_empty = ''; - } - else - { - $str_empty = '\N'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[] = $str_val; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $this->flush(implode("\t", $schema_vals) . "\n"); - } - $db->sql_freeresult($result); - $this->flush("\\.\n"); - - // Write out the sequence statements - $this->flush($seq); - } - - function write_end() - { - $this->flush("COMMIT;\n"); - parent::write_end(); - } -} - -class mssql_extractor extends base_extractor -{ - function write_end() - { - $this->flush("COMMIT\nGO\n"); - parent::write_end(); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $sql_data .= "BEGIN TRANSACTION\n"; - $sql_data .= "GO\n"; - $this->flush($sql_data); - } - - function write_table($table_name) - { - global $db; - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; - $sql_data .= "DROP TABLE $table_name;\n"; - $sql_data .= "GO\n"; - $sql_data .= "\nCREATE TABLE [$table_name] (\n"; - $rows = array(); - - $text_flag = false; - - $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY - FROM INFORMATION_SCHEMA.COLUMNS - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; - - if ($row['DATA_TYPE'] == 'text') - { - $text_flag = true; - } - - if ($row['IS_IDENTITY']) - { - $line .= ' IDENTITY (1 , 1)'; - } - - if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') - { - $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; - } - - if ($row['IS_NULLABLE'] == 'YES') - { - $line .= ' NULL'; - } - else - { - $line .= ' NOT NULL'; - } - - if ($row['COLUMN_DEFAULT']) - { - $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; - } - - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n) ON [PRIMARY]"; - - if ($text_flag) - { - $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; - } - - $sql_data .= "\nGO\n\n"; - $rows = array(); - - $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME - FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE - WHERE TABLE_NAME = '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if (!sizeof($rows)) - { - $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; - $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; - } - $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; - } - if (sizeof($rows)) - { - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; - } - $db->sql_freeresult($result); - - $index = array(); - $sql = "EXEC sp_statistics '$table_name'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; - } - } - $db->sql_freeresult($result); - - foreach ($index as $index_name => $column_name) - { - $index[$index_name] = implode(', ', $column_name); - } - - foreach ($index as $index_name => $columns) - { - $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - - if ($db->get_sql_layer() === 'mssql') - { - $this->write_data_mssql($table_name); - } - else if($db->get_sql_layer() === 'mssqlnative') - { - $this->write_data_mssqlnative($table_name); - } - else - { - $this->write_data_odbc($table_name); - } - } - - function write_data_mssql($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = mssql_num_rows($result); - - $i_num_fields = mssql_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = mssql_field_type($result, $i); - $ary_name[$i] = mssql_field_name($result, $i); - } - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_mssqlnative($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * FROM $table_name"; - $db->mssqlnative_set_query_options(array('Scrollable' => SQLSRV_CURSOR_STATIC)); - $result = $db->sql_query($sql); - - $retrieved_data = $db->mssqlnative_num_rows($result); - - if (!$retrieved_data) - { - $db->sql_freeresult($result); - return; - } - - $sql = "SELECT COLUMN_NAME, DATA_TYPE - FROM INFORMATION_SCHEMA.COLUMNS - WHERE INFORMATION_SCHEMA.COLUMNS.TABLE_NAME = '" . $db->sql_escape($table_name) . "'"; - $result_fields = $db->sql_query($sql); - - $i_num_fields = 0; - while ($row = $db->sql_fetchrow($result_fields)) - { - $ary_type[$i_num_fields] = $row['DATA_TYPE']; - $ary_name[$i_num_fields] = $row['COLUMN_NAME']; - $i_num_fields++; - } - $db->sql_freeresult($result_fields); - - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - // defaults to type number - better quote just to be safe, so check for is_int too - if (is_int($ary_type[$i]) || preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - $sql_data = ''; - } - $db->sql_freeresult($result); - - if ($ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - - function write_data_odbc($table_name) - { - global $db; - $ary_type = $ary_name = array(); - $ident_set = false; - $sql_data = ''; - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $retrieved_data = odbc_num_rows($result); - - if ($retrieved_data) - { - $sql = "SELECT 1 as has_identity - FROM INFORMATION_SCHEMA.COLUMNS - WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; - $result2 = $db->sql_query($sql); - $row2 = $db->sql_fetchrow($result2); - if (!empty($row2['has_identity'])) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; - $ident_set = true; - } - $db->sql_freeresult($result2); - } - - $i_num_fields = odbc_num_fields($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = odbc_field_type($result, $i + 1); - $ary_name[$i] = odbc_field_name($result, $i + 1); - } - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - $str_val = $row[$ary_name[$i]]; - - if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = $ary_name[$i]; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; - - $this->flush($sql_data); - - $sql_data = ''; - - } - $db->sql_freeresult($result); - - if ($retrieved_data && $ident_set) - { - $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; - } - $this->flush($sql_data); - } - -} - -class oracle_extractor extends base_extractor -{ - function write_table($table_name) - { - global $db, $request; - - $sql_data = '-- Table: ' . $table_name . "\n"; - $sql_data .= "DROP TABLE $table_name\n/\n"; - $sql_data .= "\nCREATE TABLE $table_name (\n"; - - $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT - FROM ALL_TAB_COLS - WHERE table_name = '{$table_name}'"; - $result = $db->sql_query($sql); - - $rows = array(); - while ($row = $db->sql_fetchrow($result)) - { - $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; - - if ($row['data_type'] !== 'CLOB') - { - if ($row['data_type'] !== 'VARCHAR2' && $row['data_type'] !== 'CHAR') - { - $line .= '(' . $row['data_precision'] . ')'; - } - else - { - $line .= '(' . $row['data_length'] . ')'; - } - } - - if (!empty($row['data_default'])) - { - $line .= ' DEFAULT ' . $row['data_default']; - } - - if ($row['nullable'] == 'N') - { - $line .= ' NOT NULL'; - } - $rows[] = $line; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'P' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $primary_key = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $primary_key[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($primary_key)) - { - $rows[] = " CONSTRAINT {$constraint_name} PRIMARY KEY (" . implode(', ', $primary_key) . ')'; - } - - $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME - FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B - WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME - AND B.CONSTRAINT_TYPE = 'U' - AND A.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $unique = array(); - $contraint_name = ''; - while ($row = $db->sql_fetchrow($result)) - { - $constraint_name = '"' . $row['constraint_name'] . '"'; - $unique[] = '"' . $row['column_name'] . '"'; - } - $db->sql_freeresult($result); - - if (sizeof($unique)) - { - $rows[] = " CONSTRAINT {$constraint_name} UNIQUE (" . implode(', ', $unique) . ')'; - } - - $sql_data .= implode(",\n", $rows); - $sql_data .= "\n)\n/\n"; - - $sql = "SELECT A.REFERENCED_NAME, C.* - FROM USER_DEPENDENCIES A, USER_TRIGGERS B, USER_SEQUENCES C - WHERE A.REFERENCED_TYPE = 'SEQUENCE' - AND A.NAME = B.TRIGGER_NAME - AND B.TABLE_NAME = '{$table_name}' - AND C.SEQUENCE_NAME = A.REFERENCED_NAME"; - $result = $db->sql_query($sql); - - $type = $request->variable('type', ''); - - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nDROP SEQUENCE \"{$row['referenced_name']}\"\n/\n"; - $sql_data .= "\nCREATE SEQUENCE \"{$row['referenced_name']}\""; - - if ($type == 'full') - { - $sql_data .= ' START WITH ' . $row['last_number']; - } - - $sql_data .= "\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY - FROM USER_TRIGGERS - WHERE TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\n/\n"; - } - $db->sql_freeresult($result); - - $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME - FROM USER_INDEXES A, USER_IND_COLUMNS B - WHERE A.UNIQUENESS = 'NONUNIQUE' - AND A.INDEX_NAME = B.INDEX_NAME - AND B.TABLE_NAME = '{$table_name}'"; - $result = $db->sql_query($sql); - - $index = array(); - - while ($row = $db->sql_fetchrow($result)) - { - $index[$row['index_name']][] = $row['column_name']; - } - - foreach ($index as $index_name => $column_names) - { - $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n/\n"; - } - $db->sql_freeresult($result); - $this->flush($sql_data); - } - - function write_data($table_name) - { - global $db; - $ary_type = $ary_name = array(); - - // Grab all of the data from current table. - $sql = "SELECT * - FROM $table_name"; - $result = $db->sql_query($sql); - - $i_num_fields = ocinumcols($result); - - for ($i = 0; $i < $i_num_fields; $i++) - { - $ary_type[$i] = ocicolumntype($result, $i + 1); - $ary_name[$i] = ocicolumnname($result, $i + 1); - } - - $sql_data = ''; - - while ($row = $db->sql_fetchrow($result)) - { - $schema_vals = $schema_fields = array(); - - // Build the SQL statement to recreate the data. - for ($i = 0; $i < $i_num_fields; $i++) - { - // Oracle uses uppercase - we use lowercase - $str_val = $row[strtolower($ary_name[$i])]; - - if (preg_match('#char|text|bool|raw|clob#i', $ary_type[$i])) - { - $str_quote = ''; - $str_empty = "''"; - $str_val = sanitize_data_oracle($str_val); - } - else if (preg_match('#date|timestamp#i', $ary_type[$i])) - { - if (empty($str_val)) - { - $str_quote = ''; - } - else - { - $str_quote = "'"; - } - } - else - { - $str_quote = ''; - $str_empty = 'NULL'; - } - - if (empty($str_val) && $str_val !== '0') - { - $str_val = $str_empty; - } - - $schema_vals[$i] = $str_quote . $str_val . $str_quote; - $schema_fields[$i] = '"' . $ary_name[$i] . '"'; - } - - // Take the ordered fields and their associated data and build it - // into a valid sql statement to recreate that field in the data. - $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ")\n/\n"; - - $this->flush($sql_data); - } - $db->sql_freeresult($result); - } - - function write_start($prefix) - { - $sql_data = "--\n"; - $sql_data .= "-- phpBB Backup Script\n"; - $sql_data .= "-- Dump of tables for $prefix\n"; - $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; - $sql_data .= "--\n"; - $this->flush($sql_data); - } -} - // get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) function get_usable_memory() { diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index 89fdc8b863..0373a3b115 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -70,15 +70,16 @@ class acp_extensions // If they've specified an extension, let's load the metadata manager and validate it. if ($ext_name) { - $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $user, $phpbb_root_path); + $md_manager = new \phpbb\extension\metadata_manager($ext_name, $config, $phpbb_extension_manager, $template, $phpbb_root_path); try { $md_manager->get_metadata('all'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { - trigger_error($e, E_USER_WARNING); + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); + trigger_error($message, E_USER_WARNING); } } @@ -174,11 +175,6 @@ class acp_extensions trigger_error($user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING); } - if ($phpbb_extension_manager->is_enabled($ext_name)) - { - redirect($this->u_action); - } - try { while ($phpbb_extension_manager->enable_step($ext_name)) @@ -357,10 +353,11 @@ class acp_extensions $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } @@ -413,10 +410,11 @@ class acp_extensions $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } @@ -472,10 +470,11 @@ class acp_extensions $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { + $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( - 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $e), + 'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message), 'S_VERSIONCHECK' => false, )); } diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index fdf366097a..5d1756de45 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -28,7 +28,7 @@ class acp_icons function main($id, $mode) { - global $db, $user, $auth, $template, $cache; + global $db, $user, $auth, $template, $cache, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; global $request, $phpbb_container; @@ -486,6 +486,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); $level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING; $errormsgs = ''; @@ -661,6 +662,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); } @@ -783,6 +785,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { @@ -848,6 +851,7 @@ class acp_icons $cache->destroy('_icons'); $cache->destroy('sql', $table); + $phpbb_container->get('text_formatter.cache')->invalidate(); if ($request->is_ajax()) { diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 3fd118b0dd..e7ee7f47d6 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -31,7 +31,7 @@ class acp_language function main($id, $mode) { - global $config, $db, $user, $template, $phpbb_log; + global $config, $db, $user, $template, $phpbb_log, $phpbb_container; global $phpbb_root_path, $phpEx, $request; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -377,37 +377,19 @@ class acp_language $db->sql_freeresult($result); $new_ary = $iso = array(); - $dp = @opendir("{$phpbb_root_path}language"); - if ($dp) + /** @var \phpbb\language\language_file_helper $language_helper */ + $language_helper = $phpbb_container->get('language.helper.language_file'); + $iso = $language_helper->get_available_languages(); + + foreach ($iso as $lang_array) { - while (($file = readdir($dp)) !== false) - { - if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file)) - { - continue; - } + $lang_iso = $lang_array['iso']; - if (file_exists("{$phpbb_root_path}language/$file/iso.txt")) - { - if (!in_array($file, $installed)) - { - if ($iso = file("{$phpbb_root_path}language/$file/iso.txt")) - { - if (sizeof($iso) == 3) - { - $new_ary[$file] = array( - 'iso' => $file, - 'name' => trim($iso[0]), - 'local_name'=> trim($iso[1]), - 'author' => trim($iso[2]) - ); - } - } - } - } + if (!in_array($lang_iso, $installed)) + { + $new_ary[$lang_iso] = $lang_array; } - closedir($dp); } unset($installed); diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index c49ccdf479..8680b7786a 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -26,7 +26,7 @@ class acp_main function main($id, $mode) { global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log; - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher; + global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher, $phpbb_filesystem; // Show restore permissions notice if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) @@ -352,6 +352,11 @@ class acp_main $config->increment('assets_version', 1); $cache->purge(); + // Remove old renderers from the text_formatter service. Since this + // operation is performed after the cache is purged, there is not "current" + // renderer and in effect all renderers will be purged + $phpbb_container->get('text_formatter.cache')->tidy(); + // Clear permissions $auth->acl_clear_prefetch(); phpbb_cache_moderators($db, $cache, $auth); @@ -644,7 +649,7 @@ class acp_main } } - if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) + if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && $phpbb_filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx)) { // World-Writable? (000x) $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002)); diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index c2a6151833..146e116cfd 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -117,7 +117,7 @@ class acp_profile $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); - /* @var $db_tools \phpbb\db\tools */ + /* @var $db_tools \phpbb\db\tools\tools_interface */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident); @@ -466,7 +466,7 @@ class acp_profile if (!$cp->vars[$key] && $action == 'edit') { - $cp->vars[$key] = $$key; + $cp->vars[$key] = ${$key}; } $field_data = $cp->vars; @@ -886,8 +886,7 @@ class acp_profile if ($action == 'create') { $field_ident = 'pf_' . $field_ident; - - /* @var $db_tools \phpbb\db\tools */ + /* @var $db_tools \phpbb\db\tools\tools_interface */ $db_tools = $phpbb_container->get('dbal.tools'); $db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null)); } diff --git a/phpBB/includes/acp/acp_prune.php b/phpBB/includes/acp/acp_prune.php index 5a97cf2169..63a103aa0c 100644 --- a/phpBB/includes/acp/acp_prune.php +++ b/phpBB/includes/acp/acp_prune.php @@ -508,7 +508,7 @@ class acp_prune AND ug.user_id <> ' . ANONYMOUS . ' AND u.user_type <> ' . USER_FOUNDER . ' AND ug.user_pending = 0 ' . - ((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '') . ' + ((!empty($user_ids)) ? ' AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '') . ' AND u.user_id = ug.user_id'; $result = $db->sql_query($sql); @@ -534,7 +534,7 @@ class acp_prune FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u WHERE u.user_id <> ' . ANONYMOUS . ' AND u.user_type <> ' . USER_FOUNDER . - ((!empty($user_ids)) ? 'AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . ' + ((!empty($user_ids)) ? ' AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . ' AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) . ' AND u.user_id = p.poster_id GROUP BY p.poster_id diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index f7382f826d..e0991158fe 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -445,7 +445,6 @@ class acp_search $search = null; $error = false; - $search_options = ''; foreach ($search_types as $type) { if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 45f224f8b1..b652fd6587 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -53,6 +53,9 @@ class acp_styles /** @var \phpbb\auth\auth */ protected $auth; + /** @var \phpbb\textformatter\cache_interface */ + protected $text_formatter_cache; + /** @var string */ protected $phpbb_root_path; @@ -61,7 +64,7 @@ class acp_styles public function main($id, $mode) { - global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config; + global $db, $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request, $cache, $auth, $config, $phpbb_container; $this->db = $db; $this->user = $user; @@ -69,6 +72,7 @@ class acp_styles $this->request = $request; $this->cache = $cache; $this->auth = $auth; + $this->text_formatter_cache = $phpbb_container->get('text_formatter.cache'); $this->config = $config; $this->phpbb_root_path = $phpbb_root_path; $this->php_ext = $phpEx; @@ -216,6 +220,12 @@ class acp_styles } } + // Invalidate the text formatter's cache for the new styles to take effect + if (!empty($installed_names)) + { + $this->text_formatter_cache->invalidate(); + } + // Show message if (!count($messages)) { diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 4cefdc2b4f..0ec17ccf0c 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -1451,6 +1451,18 @@ class acp_users $error[] = 'FORM_INVALID'; } + /** + * Validate profile data in ACP before submitting to the database + * + * @event core.acp_users_profile_validate + * @var bool submit Flag indicating if submit button has been pressed + * @var array data Array with user profile data + * @var array error Array with the form errors + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data', 'error'); + extract($phpbb_dispatcher->trigger_event('core.acp_users_profile_validate', compact($vars))); + if (!sizeof($error)) { $sql_ary = array( @@ -1466,9 +1478,10 @@ class acp_users * @var array data Array with user profile data * @var int user_id The user id * @var array user_row Array with the full user data + * @var array sql_ary Array with sql data * @since 3.1.4-RC1 */ - $vars = array('cp_data', 'data', 'user_id', 'user_row'); + $vars = array('cp_data', 'data', 'user_id', 'user_row', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.acp_users_profile_modify_sql_ary', compact($vars))); $sql = 'UPDATE ' . USERS_TABLE . ' @@ -2019,6 +2032,9 @@ class acp_users $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'S_SIGNATURE' => true, @@ -2029,7 +2045,7 @@ class acp_users 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index d28aa8e60b..ea8d47a109 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -28,7 +28,7 @@ class acp_words function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $phpbb_log, $request; + global $db, $user, $auth, $template, $cache, $phpbb_log, $request, $phpbb_container; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; $user->add_lang('acp/posting'); @@ -115,6 +115,7 @@ class acp_words } $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; @@ -148,6 +149,7 @@ class acp_words $db->sql_query($sql); $cache->destroy('_word_censors'); + $phpbb_container->get('text_formatter.cache')->invalidate(); $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($deleted_word)); diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index ee911b5ec5..dcbf33a3c4 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -129,7 +129,7 @@ class bbcode */ function bbcode_cache_init() { - global $phpbb_root_path, $phpEx, $config, $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_path_helper, $phpbb_container; + global $phpbb_root_path, $phpEx, $config, $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_path_helper, $phpbb_container, $phpbb_filesystem; if (empty($this->template_filename)) { @@ -138,17 +138,20 @@ class bbcode $template = new \phpbb\template\twig\twig( $phpbb_container->get('path_helper'), $phpbb_container->get('config'), - $phpbb_container->get('user'), new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), $phpbb_container->get('path_helper'), $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader() + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), $phpbb_container->get('template.twig.extensions.collection'), $phpbb_extension_manager ); @@ -199,6 +202,8 @@ class bbcode $db->sql_freeresult($result); } + // To perform custom second pass in extension, use $this->bbcode_second_pass_by_extension() + // method which accepts variable number of parameters foreach ($bbcode_ids as $bbcode_id) { switch ($bbcode_id) @@ -630,4 +635,36 @@ class bbcode return $code; } + + /** + * Function to perform custom bbcode second pass by extensions + * can be used to assign bbcode pattern replacement + * Example: '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_second_pass_by_extension('\$1')" + * + * Accepts variable number of parameters + * + * @return mixed Second pass result + */ + function bbcode_second_pass_by_extension() + { + global $phpbb_dispatcher; + + $return = false; + $params_array = func_get_args(); + + /** + * Event to perform bbcode second pass with + * the custom validating methods provided by extensions + * + * @event core.bbcode_second_pass_by_extension + * @var array params_array Array with the function parameters + * @var mixed return Second pass result to return + * + * @since 3.1.5-RC1 + */ + $vars = array('params_array', 'return'); + extract($phpbb_dispatcher->trigger_event('core.bbcode_second_pass_by_extension', compact($vars))); + + return $return; + } } diff --git a/phpBB/includes/compatibility_globals.php b/phpBB/includes/compatibility_globals.php index b0919aefb3..5c18793655 100644 --- a/phpBB/includes/compatibility_globals.php +++ b/phpBB/includes/compatibility_globals.php @@ -48,7 +48,7 @@ $phpbb_log = $phpbb_container->get('log'); /* @var $symfony_request \phpbb\symfony_request */ $symfony_request = $phpbb_container->get('symfony_request'); -/* @var $phpbb_filesystem \phpbb\filesystem */ +/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */ $phpbb_filesystem = $phpbb_container->get('filesystem'); /* @var $phpbb_path_helper \phpbb\path_helper */ diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index ce2528750e..b722c30416 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -311,448 +311,6 @@ function phpbb_version_compare($version1, $version2, $operator = null) } } -/** -* Global function for chmodding directories and files for internal use -* -* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. -* The function determines owner and group from common.php file and sets the same to the provided file. -* The function uses bit fields to build the permissions. -* The function sets the appropiate execute bit on directories. -* -* Supported constants representing bit fields are: -* -* CHMOD_ALL - all permissions (7) -* CHMOD_READ - read permission (4) -* CHMOD_WRITE - write permission (2) -* CHMOD_EXECUTE - execute permission (1) -* -* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. -* -* @param string $filename The file/directory to be chmodded -* @param int $perms Permissions to set -* -* @return bool true on success, otherwise false -*/ -function phpbb_chmod($filename, $perms = CHMOD_READ) -{ - static $_chmod_info; - - // Return if the file no longer exists. - if (!file_exists($filename)) - { - return false; - } - - // Determine some common vars - if (empty($_chmod_info)) - { - if (!function_exists('fileowner') || !function_exists('filegroup')) - { - // No need to further determine owner/group - it is unknown - $_chmod_info['process'] = false; - } - else - { - global $phpbb_root_path, $phpEx; - - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = @fileowner($phpbb_root_path . 'common.' . $phpEx); - $common_php_group = @filegroup($phpbb_root_path . 'common.' . $phpEx); - - // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; - $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; - - // If we are unable to get owner/group, then do not try to set them by guessing - if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) - { - $_chmod_info['process'] = false; - } - else - { - $_chmod_info = array( - 'process' => true, - 'common_owner' => $common_php_owner, - 'common_group' => $common_php_group, - 'php_uid' => $php_uid, - 'php_gids' => $php_gids, - ); - } - } - } - - if ($_chmod_info['process']) - { - $file_uid = @fileowner($filename); - $file_gid = @filegroup($filename); - - // Change owner - if (@chown($filename, $_chmod_info['common_owner'])) - { - clearstatcache(); - $file_uid = @fileowner($filename); - } - - // Change group - if (@chgrp($filename, $_chmod_info['common_group'])) - { - clearstatcache(); - $file_gid = @filegroup($filename); - } - - // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something - if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) - { - $_chmod_info['process'] = false; - } - } - - // Still able to process? - if ($_chmod_info['process']) - { - if ($file_uid == $_chmod_info['php_uid']) - { - $php = 'owner'; - } - else if (in_array($file_gid, $_chmod_info['php_gids'])) - { - $php = 'group'; - } - else - { - // Since we are setting the everyone bit anyway, no need to do expensive operations - $_chmod_info['process'] = false; - } - } - - // We are not able to determine or change something - if (!$_chmod_info['process']) - { - $php = 'other'; - } - - // Owner always has read/write permission - $owner = CHMOD_READ | CHMOD_WRITE; - if (is_dir($filename)) - { - $owner |= CHMOD_EXECUTE; - - // Only add execute bit to the permission if the dir needs to be readable - if ($perms & CHMOD_READ) - { - $perms |= CHMOD_EXECUTE; - } - } - - switch ($php) - { - case 'owner': - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); - - clearstatcache(); - - if (is_readable($filename) && phpbb_is_writable($filename)) - { - break; - } - - case 'group': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - case 'other': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); - - clearstatcache(); - - if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename))) - { - break; - } - - default: - return false; - break; - } - - return $result; -} - -/** -* Test if a file/directory is writable -* -* This function calls the native is_writable() when not running under -* Windows and it is not disabled. -* -* @param string $file Path to perform write test on -* @return bool True when the path is writable, otherwise false. -*/ -function phpbb_is_writable($file) -{ - if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) - { - if (file_exists($file)) - { - // Canonicalise path to absolute path - $file = phpbb_realpath($file); - - if (is_dir($file)) - { - // Test directory by creating a file inside the directory - $result = @tempnam($file, 'i_w'); - - if (is_string($result) && file_exists($result)) - { - unlink($result); - - // Ensure the file is actually in the directory (returned realpathed) - return (strpos($result, $file) === 0) ? true : false; - } - } - else - { - $handle = @fopen($file, 'r+'); - - if (is_resource($handle)) - { - fclose($handle); - return true; - } - } - } - else - { - // file does not exist test if we can write to the directory - $dir = dirname($file); - - if (file_exists($dir) && is_dir($dir) && phpbb_is_writable($dir)) - { - return true; - } - } - - return false; - } - else - { - return is_writable($file); - } -} - -/** -* Checks if a path ($path) is absolute or relative -* -* @param string $path Path to check absoluteness of -* @return boolean -*/ -function phpbb_is_absolute($path) -{ - return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; -} - -/** -* @author Chris Smith <chris@project-minerva.org> -* @copyright 2006 Project Minerva Team -* @param string $path The path which we should attempt to resolve. -* @return mixed -*/ -function phpbb_own_realpath($path) -{ - global $request; - - // Now to perform funky shizzle - - // Switch to use UNIX slashes - $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); - $path_prefix = ''; - - // Determine what sort of path we have - if (phpbb_is_absolute($path)) - { - $absolute = true; - - if ($path[0] == '/') - { - // Absolute path, *NIX style - $path_prefix = ''; - } - else - { - // Absolute path, Windows style - // Remove the drive letter and colon - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - } - else - { - // Relative Path - // Prepend the current working directory - if (function_exists('getcwd')) - { - // This is the best method, hopefully it is enabled! - $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path; - $absolute = true; - if (preg_match('#^[a-z]:#i', $path)) - { - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - else - { - $path_prefix = ''; - } - } - else if ($request->server('SCRIPT_FILENAME')) - { - // Warning: If chdir() has been used this will lie! - // Warning: This has some problems sometime (CLI can create them easily) - $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME')); - $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($filename)) . '/' . $path; - $absolute = true; - $path_prefix = ''; - } - else - { - // We have no way of getting the absolute path, just run on using relative ones. - $absolute = false; - $path_prefix = '.'; - } - } - - // Remove any repeated slashes - $path = preg_replace('#/{2,}#', '/', $path); - - // Remove the slashes from the start and end of the path - $path = trim($path, '/'); - - // Break the string into little bits for us to nibble on - $bits = explode('/', $path); - - // Remove any . in the path, renumber array for the loop below - $bits = array_values(array_diff($bits, array('.'))); - - // Lets get looping, run over and resolve any .. (up directory) - for ($i = 0, $max = sizeof($bits); $i < $max; $i++) - { - // @todo Optimise - if ($bits[$i] == '..' ) - { - if (isset($bits[$i - 1])) - { - if ($bits[$i - 1] != '..') - { - // We found a .. and we are able to traverse upwards, lets do it! - unset($bits[$i]); - unset($bits[$i - 1]); - $i -= 2; - $max -= 2; - $bits = array_values($bits); - } - } - else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute - { - // We have an absolute path trying to descend above the root of the filesystem - // ... Error! - return false; - } - } - } - - // Prepend the path prefix - array_unshift($bits, $path_prefix); - - $resolved = ''; - - $max = sizeof($bits) - 1; - - // Check if we are able to resolve symlinks, Windows (prior to Vista and Server 2008) cannot. - $symlink_resolve = (function_exists('readlink')) ? true : false; - - foreach ($bits as $i => $bit) - { - if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit"))) - { - // Path Exists - if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit"))) - { - // Resolved a symlink. - $resolved = $link . (($i == $max) ? '' : '/'); - continue; - } - } - else - { - // Something doesn't exist here! - // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic - // return false; - } - $resolved .= $bit . (($i == $max) ? '' : '/'); - } - - // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it - // because we must be inside that basedir, the question is where... - // @internal The slash in is_dir() gets around an open_basedir restriction - if (!@file_exists($resolved) || (!@is_dir($resolved . '/') && !is_file($resolved))) - { - return false; - } - - // Put the slashes back to the native operating systems slashes - $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved); - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($resolved, -1) == DIRECTORY_SEPARATOR) - { - return substr($resolved, 0, -1); - } - - return $resolved; // We got here, in the end! -} - -if (!function_exists('realpath')) -{ - /** - * A wrapper for realpath - * @ignore - */ - function phpbb_realpath($path) - { - return phpbb_own_realpath($path); - } -} -else -{ - /** - * A wrapper for realpath - */ - function phpbb_realpath($path) - { - $realpath = realpath($path); - - // Strangely there are provider not disabling realpath but returning strange values. :o - // We at least try to cope with them. - if ($realpath === $path || $realpath === false) - { - return phpbb_own_realpath($path); - } - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($realpath, -1) == DIRECTORY_SEPARATOR) - { - $realpath = substr($realpath, 0, -1); - } - - return $realpath; - } -} - // functions used for building option fields /** @@ -1029,7 +587,7 @@ function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $ /** * This event is used for performing actions directly before marking forums, * topics or posts as read. - * + * * It is also possible to prevent the marking. For that, the $should_markread parameter * should be set to FALSE. * @@ -2161,7 +1719,7 @@ function redirect($url, $return = false, $disable_cd_check = false) $failover_flag = false; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->add_lang('common'); } @@ -2182,7 +1740,7 @@ function redirect($url, $return = false, $disable_cd_check = false) // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work) if (!$disable_cd_check && $url_parts['host'] !== $user->host) { - $url = generate_board_url(); + trigger_error('INSECURE_REDIRECT', E_USER_ERROR); } } else if ($url[0] == '/') @@ -2220,7 +1778,7 @@ function redirect($url, $return = false, $disable_cd_check = false) // Clean URL and check if we go outside the forum directory $url = $phpbb_path_helper->clean_url($url); - if (!$disable_cd_check && strpos($url, generate_board_url(true)) === false) + if (!$disable_cd_check && strpos($url, generate_board_url(true) . '/') !== 0) { trigger_error('INSECURE_REDIRECT', E_USER_ERROR); } @@ -2262,7 +1820,7 @@ function redirect($url, $return = false, $disable_cd_check = false) } // Redirect via an HTML form for PITA webservers - if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) + if (@preg_match('#WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) { header('Refresh: 0; URL=' . $url); @@ -2417,13 +1975,19 @@ function phpbb_request_http_version() { global $request; + $version = ''; if ($request && $request->server('SERVER_PROTOCOL')) { - return $request->server('SERVER_PROTOCOL'); + $version = $request->server('SERVER_PROTOCOL'); } else if (isset($_SERVER['SERVER_PROTOCOL'])) { - return $_SERVER['SERVER_PROTOCOL']; + $version = $_SERVER['SERVER_PROTOCOL']; + } + + if (!empty($version) && is_string($version) && preg_match('#^HTTP/[0-9]\.[0-9]$#', $version)) + { + return $version; } return 'HTTP/1.0'; @@ -2679,7 +2243,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $err = ''; // Make sure user->setup() has been called - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -2793,19 +2357,6 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa // Special cases... determine switch ($result['status']) { - case LOGIN_ERROR_ATTEMPTS: - - $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); - $captcha->init(CONFIRM_LOGIN); - // $captcha->reset(); - - $template->assign_vars(array( - 'CAPTCHA_TEMPLATE' => $captcha->get_template(), - )); - - $err = $user->lang[$result['error_msg']]; - break; - case LOGIN_ERROR_PASSWORD_CONVERT: $err = sprintf( $user->lang[$result['error_msg']], @@ -2816,6 +2367,17 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa ); break; + case LOGIN_ERROR_ATTEMPTS: + + $captcha = $phpbb_container->get('captcha.factory')->get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_LOGIN); + // $captcha->reset(); + + $template->assign_vars(array( + 'CAPTCHA_TEMPLATE' => $captcha->get_template(), + )); + // no break; + // Username, password, etc... default: $err = $user->lang[$result['error_msg']]; @@ -3176,7 +2738,7 @@ function get_preg_expression($mode) case 'email': // Regex written by James Watts and Francisco Jose Martin Moreno // http://fightingforalostcause.net/misc/2006/compare-email-regex.php - return '([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; + return '((?:[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*(?:[\w\!\#$\%\'\*\+\-\/\=\?\^\`{\|\}\~]|&)+)@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,63})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)'; break; case 'bbcode_htm': @@ -3249,31 +2811,19 @@ function get_preg_expression($mode) * Depends on whether installed PHP version supports unicode properties * * @param string $word word template to be replaced -* @param bool $use_unicode whether or not to take advantage of PCRE supporting unicode * * @return string $preg_expr regex to use with word censor */ -function get_censor_preg_expression($word, $use_unicode = true) +function get_censor_preg_expression($word) { // Unescape the asterisk to simplify further conversions $word = str_replace('\*', '*', preg_quote($word, '#')); - if ($use_unicode && phpbb_pcre_utf8_support()) - { - // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes - $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); - - // Generate the final substitution - $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu'; - } - else - { - // Replace the asterisk inside the pattern, at the start and at the end of it with regexes - $word = preg_replace(array('#(?<=\S)\*+(?=\S)#iu', '#^\*+#', '#\*+$#'), array('(\x20*?\S*?)', '\S*?', '\S*?'), $word); + // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes + $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); - // Generate the final substitution - $preg_expr = '#(?<!\S)(' . $word . ')(?!\S)#iu'; - } + // Generate the final substitution + $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu'; return $preg_expr; } @@ -3706,7 +3256,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) case E_USER_ERROR: - if (!empty($user) && !empty($user->lang)) + if (!empty($user) && $user->is_setup()) { $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); @@ -3826,7 +3376,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // We re-init the auth array to get correct results on login/logout $auth->acl($user->data); - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -3915,11 +3465,13 @@ function msg_handler($errno, $msg_text, $errfile, $errline) */ function phpbb_filter_root_path($errfile) { + global $phpbb_filesystem; + static $root_path; if (empty($root_path)) { - $root_path = phpbb_realpath(dirname(__FILE__) . '/../'); + $root_path = $phpbb_filesystem->realpath(dirname(__FILE__) . '/../'); } return str_replace(array($root_path, '\\'), array('[ROOT]', '/'), $errfile); @@ -4045,9 +3597,10 @@ function obtain_users_online($item_id = 0, $item = 'forum') */ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum') { - global $config, $db, $user, $auth; + global $config, $db, $user, $auth, $phpbb_dispatcher; - $user_online_link = $online_userlist = ''; + $guests_online = $hidden_online = $l_online_users = $online_userlist = $visible_online = ''; + $user_online_link = $rowset = array(); // Need caps version of $item for language-strings $item_caps = strtoupper($item); @@ -4057,9 +3610,28 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' FROM ' . USERS_TABLE . ' WHERE ' . $db->sql_in_set('user_id', $online_users['online_users']) . ' ORDER BY username_clean ASC'; + + /** + * Modify SQL query to obtain online users data + * + * @event core.obtain_users_online_string_sql + * @var array online_users Array with online users data + * from obtain_users_online() + * @var int item_id Restrict online users to item id + * @var string item Restrict online users to a certain + * session item, e.g. forum for + * session_forum_id + * @var string sql SQL query to obtain users online data + * @since 3.1.4-RC1 + */ + $vars = array('online_users', 'item_id', 'item', 'sql'); + extract($phpbb_dispatcher->trigger_event('core.obtain_users_online_string_sql', compact($vars))); + $result = $db->sql_query($sql); + $rowset = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); - while ($row = $db->sql_fetchrow($result)) + foreach ($rowset as $row) { // User is logged in and therefore not a guest if ($row['user_id'] != ANONYMOUS) @@ -4071,13 +3643,12 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' if (!isset($online_users['hidden_users'][$row['user_id']]) || $auth->acl_get('u_viewonline')) { - $user_online_link = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); - $online_userlist .= ($online_userlist != '') ? ', ' . $user_online_link : $user_online_link; + $user_online_link[$row['user_id']] = get_username_string(($row['user_type'] <> USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); } } } - $db->sql_freeresult($result); } + $online_userlist = implode(', ', $user_online_link); if (!$online_userlist) { @@ -4110,6 +3681,33 @@ function obtain_users_online_string($online_users, $item_id = 0, $item = 'forum' $l_online_users = $user->lang('ONLINE_USERS_TOTAL', (int) $online_users['total_online'], $visible_online, $hidden_online); } + /** + * Modify online userlist data + * + * @event core.obtain_users_online_string_modify + * @var array online_users Array with online users data + * from obtain_users_online() + * @var int item_id Restrict online users to item id + * @var string item Restrict online users to a certain + * session item, e.g. forum for + * session_forum_id + * @var array rowset Array with online users data + * @var array user_online_link Array with online users items (usernames) + * @var string online_userlist String containing users online list + * @var string l_online_users String with total online users count info + * @since 3.1.4-RC1 + */ + $vars = array( + 'online_users', + 'item_id', + 'item', + 'rowset', + 'user_online_link', + 'online_userlist', + 'l_online_users', + ); + extract($phpbb_dispatcher->trigger_event('core.obtain_users_online_string_modify', compact($vars))); + return array( 'online_userlist' => $online_userlist, 'l_online_users' => $l_online_users, @@ -4152,178 +3750,6 @@ function phpbb_optionset($bit, $set, $data) } /** -* Determine which plural form we should use. -* For some languages this is not as simple as for English. -* -* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules -* @param $number int|float The number we want to get the plural case for. Float numbers are floored. -* @return int The plural-case we need to use for the number plural-rule combination -*/ -function phpbb_get_plural_form($rule, $number) -{ - $number = (int) $number; - - if ($rule > 15 || $rule < 0) - { - trigger_error('INVALID_PLURAL_RULE'); - } - - /** - * The following plural rules are based on a list published by the Mozilla Developer Network - * https://developer.mozilla.org/en/Localization_and_Plurals - */ - switch ($rule) - { - case 0: - /** - * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao - * 1 - everything: 0, 1, 2, ... - */ - return 1; - - case 1: - /** - * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) - * 1 - 1 - * 2 - everything else: 0, 2, 3, ... - */ - return ($number == 1) ? 1 : 2; - - case 2: - /** - * Families: Romanic (French, Brazilian Portuguese) - * 1 - 0, 1 - * 2 - everything else: 2, 3, ... - */ - return (($number == 0) || ($number == 1)) ? 1 : 2; - - case 3: - /** - * Families: Baltic (Latvian) - * 1 - 0 - * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... - * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3); - - case 4: - /** - * Families: Celtic (Scottish Gaelic) - * 1 - is 1 or 11: 1, 11 - * 2 - is 2 or 12: 2, 12 - * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 - * 4 - everything else: 0, 20, 21, ... - */ - return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); - - case 5: - /** - * Families: Romanic (Romanian) - * 1 - 1 - * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... - * 3 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); - - case 6: - /** - * Families: Baltic (Lithuanian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... - * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); - - case 7: - /** - * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... - * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); - - case 8: - /** - * Families: Slavic (Slovak, Czech) - * 1 - 1 - * 2 - 2, 3, 4 - * 3 - everything else: 0, 5, 6, 7, ... - */ - return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); - - case 9: - /** - * Families: Slavic (Polish) - * 1 - 1 - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... - * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... - */ - return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); - - case 10: - /** - * Families: Slavic (Slovenian, Sorbian) - * 1 - ends in 01: 1, 101, 201, ... - * 2 - ends in 02: 2, 102, 202, ... - * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... - * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... - */ - return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4)); - - case 11: - /** - * Families: Celtic (Irish Gaeilge) - * 1 - 1 - * 2 - 2 - * 3 - is 3-6: 3, 4, 5, 6 - * 4 - is 7-10: 7, 8, 9, 10 - * 5 - everything else: 0, 11, 12, ... - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); - - case 12: - /** - * Families: Semitic (Arabic) - * 1 - 1 - * 2 - 2 - * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... - * 4 - ends in 11-99: 11, ... 99, 111, 112, ... - * 5 - everything else: 100, 101, 102, 200, 201, 202, ... - * 6 - 0 - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); - - case 13: - /** - * Families: Semitic (Maltese) - * 1 - 1 - * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... - * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... - * 4 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); - - case 14: - /** - * Families: Slavic (Macedonian) - * 1 - ends in 1: 1, 11, 21, ... - * 2 - ends in 2: 2, 12, 22, ... - * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... - */ - return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3); - - case 15: - /** - * Families: Icelandic - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... - * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2; - } -} - -/** * Login using http authenticate. * * @param array $param Parameter array, see $param_defaults array. @@ -4816,6 +4242,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id = } } + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); $notification_mark_hash = generate_link_hash('mark_all_notifications_read'); // The following assigns all _common_ variables that may be used at any point in a template. @@ -4869,7 +4297,7 @@ function page_header($page_title = '', $display_online_list = false, $item_id = 'U_PROFILE' => append_sid("{$phpbb_root_path}ucp.$phpEx"), 'U_USER_PROFILE' => get_username_string('profile', $user->data['user_id'], $user->data['username'], $user->data['user_colour']), 'U_MODCP' => append_sid("{$phpbb_root_path}mcp.$phpEx", false, true, $user->session_id), - 'U_FAQ' => append_sid("{$phpbb_root_path}faq.$phpEx"), + 'U_FAQ' => $controller_helper->route('phpbb_help_faq_controller'), 'U_SEARCH_SELF' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=egosearch'), 'U_SEARCH_NEW' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=newposts'), 'U_SEARCH_UNANSWERED' => append_sid("{$phpbb_root_path}search.$phpEx", 'search_id=unanswered'), @@ -5251,22 +4679,6 @@ function phpbb_user_session_handler() } /** -* Check if PCRE has UTF-8 support -* PHP may not be linked with the bundled PCRE lib and instead with an older version -* -* @return bool Returns true if PCRE (the regular expressions library) supports UTF-8 encoding -*/ -function phpbb_pcre_utf8_support() -{ - static $utf8_pcre_properties = null; - if (is_null($utf8_pcre_properties)) - { - $utf8_pcre_properties = (@preg_match('/\p{L}/u', 'a') !== false); - } - return $utf8_pcre_properties; -} - -/** * Casts a numeric string $input to an appropriate numeric type (i.e. integer or float) * * @param string $input A numeric string. diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index e30c6da505..6d59b513af 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -405,7 +405,7 @@ function build_cfg_template($tpl_type, $key, &$new, $config_key, $vars) */ function validate_config_vars($config_vars, &$cfg_array, &$error) { - global $phpbb_root_path, $user, $phpbb_dispatcher; + global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem; $type = 0; $min = 1; @@ -550,6 +550,9 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) $cfg_array[$config_name] = trim($destination); + // Absolute file path + case 'absolute_path': + case 'absolute_path_writable': // Path being relative (still prefixed by phpbb_root_path), but with the ability to escape the root dir... case 'path': case 'wpath': @@ -568,20 +571,22 @@ function validate_config_vars($config_vars, &$cfg_array, &$error) break; } - if (!file_exists($phpbb_root_path . $cfg_array[$config_name])) + $path = in_array($config_definition['validate'], array('wpath', 'path', 'rpath', 'rwpath')) ? $phpbb_root_path . $cfg_array[$config_name] : $cfg_array[$config_name]; + + if (!file_exists($path)) { $error[] = sprintf($user->lang['DIRECTORY_DOES_NOT_EXIST'], $cfg_array[$config_name]); } - if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !is_dir($phpbb_root_path . $cfg_array[$config_name])) + if (file_exists($path) && !is_dir($path)) { $error[] = sprintf($user->lang['DIRECTORY_NOT_DIR'], $cfg_array[$config_name]); } // Check if the path is writable - if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath') + if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath' || $config_definition['validate'] === 'absolute_path_writable') { - if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !phpbb_is_writable($phpbb_root_path . $cfg_array[$config_name])) + if (file_exists($path) && !$phpbb_filesystem->is_writable($path)) { $error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]); } diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 1c9440934b..fce4bf841b 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -618,7 +618,7 @@ function move_posts($post_ids, $topic_id, $auto_sync = true) */ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true) { - global $db, $config, $phpbb_container; + global $db, $config, $phpbb_container, $phpbb_dispatcher; $approved_topics = 0; $forum_ids = $topic_ids = array(); @@ -672,6 +672,20 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s $table_ary = array(BOOKMARKS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); + /** + * Perform additional actions before topic(s) deletion + * + * @event core.delete_topics_before_query + * @var array table_ary Array of tables from which all rows will be deleted that hold a topic_id occuring in topic_ids + * @var array topic_ids Array of topic ids to delete + * @since 3.1.4-RC1 + */ + $vars = array( + 'table_ary', + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_topics_before_query', compact($vars))); + foreach ($table_ary as $table) { $sql = "DELETE FROM $table @@ -680,6 +694,18 @@ function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_s } unset($table_ary); + /** + * Perform additional actions after topic(s) deletion + * + * @event core.delete_topics_after_query + * @var array topic_ids Array of topic ids that were deleted + * @since 3.1.4-RC1 + */ + $vars = array( + 'topic_ids', + ); + extract($phpbb_dispatcher->trigger_event('core.delete_topics_after_query', compact($vars))); + $moved_topic_ids = array(); // update the other forums diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 8d9f5018fa..31019061a9 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -117,7 +117,7 @@ function phpbb_clean_path($path) new phpbb\symfony_request( $request ), - new phpbb\filesystem(), + new phpbb\filesystem\filesystem(), $request, $phpbb_root_path, $phpEx @@ -384,3 +384,129 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false, $ } return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST); } + +/** + * Get tables of a database + * + * @deprecated 3.1.0 (To be removed: 3.3.0) + */ +function get_tables(&$db) +{ + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + + return $db_tools->sql_list_tables(); +} + +/** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * CHMOD_ALL - all permissions (7) + * CHMOD_READ - read permission (4) + * CHMOD_WRITE - write permission (2) + * CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string $filename The file/directory to be chmodded + * @param int $perms Permissions to set + * + * @return bool true on success, otherwise false + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::phpbb_chmod() instead + */ +function phpbb_chmod($filename, $perms = CHMOD_READ) +{ + global $phpbb_filesystem; + + try + { + $phpbb_filesystem->phpbb_chmod($filename, $perms); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + return false; + } + + return true; +} + +/** + * Test if a file/directory is writable + * + * This function calls the native is_writable() when not running under + * Windows and it is not disabled. + * + * @param string $file Path to perform write test on + * @return bool True when the path is writable, otherwise false. + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_writable() instead + */ +function phpbb_is_writable($file) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_writable($file); +} + +/** + * Checks if a path ($path) is absolute or relative + * + * @param string $path Path to check absoluteness of + * @return boolean + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_absolute_path() instead + */ +function phpbb_is_absolute($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->is_absolute_path($path); +} + +/** + * A wrapper for realpath + * + * @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::realpath() instead + */ +function phpbb_realpath($path) +{ + global $phpbb_filesystem; + + return $phpbb_filesystem->realpath($path); +} + +/** + * Determine which plural form we should use. + * For some languages this is not as simple as for English. + * + * @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules + * @param $number int|float The number we want to get the plural case for. Float numbers are floored. + * @return int The plural-case we need to use for the number plural-rule combination + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ +function phpbb_get_plural_form($rule, $number) +{ + global $phpbb_container; + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + return $language->get_plural_form($number, $rule); +} + +/** +* @return bool Always true +* @deprecated 3.2.0-dev +*/ +function phpbb_pcre_utf8_support() +{ + return true; +} diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php index a7ee29dd91..e768a0f47b 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -184,7 +184,7 @@ class compress } /** -* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, +* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, * Marc Delisle, http://www.phpmyadmin.net/ * * Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com @@ -204,11 +204,19 @@ class compress_zip extends compress var $datasec_len = 0; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Constructor */ function compress_zip($mode, $file) { + global $phpbb_filesystem; + $this->fp = @fopen($file, $mode . 'b'); + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); if (!$this->fp) { @@ -286,7 +294,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -315,7 +331,15 @@ class compress_zip extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -539,10 +563,17 @@ class compress_tar extends compress var $wrote = false; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Constructor */ function compress_tar($mode, $file, $type = '') { + global $phpbb_filesystem; + $type = (!$type) ? $file : $type; $this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type); $this->isbz = preg_match('#\.tar\.bz2$#', $type); @@ -551,6 +582,8 @@ class compress_tar extends compress $this->file = &$file; $this->type = &$type; $this->open(); + + $this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem(); } /** @@ -601,7 +634,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } } @@ -628,7 +669,15 @@ class compress_tar extends compress { trigger_error("Could not create directory $folder"); } - phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + + try + { + $this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -637,7 +686,15 @@ class compress_tar extends compress { trigger_error("Couldn't create file $filename"); } - phpbb_chmod($target_filename, CHMOD_READ); + + try + { + $this->filesystem->phpbb_chmod($target_filename, CHMOD_READ); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } // Grab the file contents fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php index 8e1705d320..5cebc54eb2 100644 --- a/phpBB/includes/functions_content.php +++ b/phpBB/includes/functions_content.php @@ -78,7 +78,7 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, foreach ($sorts as $name => $sort_ary) { $key = $sort_ary['key']; - $selected = $$sort_ary['key']; + $selected = ${$sort_ary['key']}; // Check if the key is selectable. If not, we reset to the default or first key found. // This ensures the values are always valid. We also set $sort_dir/sort_key/etc. to the @@ -87,12 +87,12 @@ function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, { if ($sort_ary['default'] !== false) { - $selected = $$key = $sort_ary['default']; + $selected = ${$key} = $sort_ary['default']; } else { @reset($sort_ary['options']); - $selected = $$key = key($sort_ary['options']); + $selected = ${$key} = key($sort_ary['options']); } } @@ -389,46 +389,68 @@ function phpbb_clean_search_string($search_string) /** * Decode text whereby text is coming from the db and expected to be pre-parsed content * We are placing this outside of the message parser because we are often in need of it... +* +* NOTE: special chars are kept encoded +* +* @param string &$message Original message, passed by reference +* @param string $bbcode_uid BBCode UID +* @return null */ function decode_message(&$message, $bbcode_uid = '') { - global $config; + global $phpbb_container; - if ($bbcode_uid) + if (preg_match('#^<[rt][ >]#', $message)) { - $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); + $message = htmlspecialchars($phpbb_container->get('text_formatter.utils')->unparse($message), ENT_COMPAT); } else { - $match = array('<br />'); - $replace = array("\n"); - } + if ($bbcode_uid) + { + $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); + $replace = array("\n", '', '', '', ''); + } + else + { + $match = array('<br />'); + $replace = array("\n"); + } - $message = str_replace($match, $replace, $message); + $message = str_replace($match, $replace, $message); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $message = preg_replace($match, $replace, $message); + $message = preg_replace($match, $replace, $message); + } } /** -* Strips all bbcode from a text and returns the plain content +* Strips all bbcode from a text in place */ function strip_bbcode(&$text, $uid = '') { - if (!$uid) + global $phpbb_container; + + if (preg_match('#^<[rt][ >]#', $text)) { - $uid = '[0-9a-z]{5,}'; + $text = $phpbb_container->get('text_formatter.utils')->clean_formatting($text); } + else + { + if (!$uid) + { + $uid = '[0-9a-z]{5,}'; + } - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); + $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); + $match = get_preg_expression('bbcode_htm'); + $replace = array('\1', '\1', '\2', '\1', '', ''); - $text = preg_replace($match, $replace, $text); + $text = preg_replace($match, $replace, $text); + } } /** @@ -438,7 +460,7 @@ function strip_bbcode(&$text, $uid = '') function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text = true) { static $bbcode; - global $phpbb_dispatcher; + global $phpbb_dispatcher, $phpbb_container; if ($text === '') { @@ -459,34 +481,56 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text $vars = array('text', 'uid', 'bitfield', 'flags', 'censor_text'); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_display_before', compact($vars))); - if ($censor_text) + if (preg_match('#^<[rt][ >]#', $text)) { - $text = censor_text($text); - } + $renderer = $phpbb_container->get('text_formatter.renderer'); - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) - { - if (!class_exists('bbcode')) + // Temporarily switch off viewcensors if applicable + $old_censor = $renderer->get_viewcensors(); + if ($old_censor !== $censor_text) { - global $phpbb_root_path, $phpEx; - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + $renderer->set_viewcensors($censor_text); } - if (empty($bbcode)) + $text = $renderer->render($text); + + // Restore the previous value + if ($old_censor !== $censor_text) { - $bbcode = new bbcode($bitfield); + $renderer->set_viewcensors($old_censor); } - else + } + else + { + if ($censor_text) { - $bbcode->bbcode($bitfield); + $text = censor_text($text); } - $bbcode->bbcode_second_pass($text, $uid); - } + // Parse bbcode if bbcode uid stored and bbcode enabled + if ($uid && ($flags & OPTION_FLAG_BBCODE)) + { + if (!class_exists('bbcode')) + { + global $phpbb_root_path, $phpEx; + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); + } + + if (empty($bbcode)) + { + $bbcode = new bbcode($bitfield); + } + else + { + $bbcode->bbcode($bitfield); + } - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + $bbcode->bbcode_second_pass($text, $uid); + } + + $text = bbcode_nl2br($text); + $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); + } /** * Use this event to modify the text after it is parsed @@ -516,10 +560,14 @@ function generate_text_for_display($text, $uid, $bitfield, $flags, $censor_text * @param bool $allow_bbcode If BBCode is allowed (i.e. if BBCode is parsed) * @param bool $allow_urls If urls is allowed * @param bool $allow_smilies If smilies are allowed +* @param bool $allow_img_bbcode +* @param bool $allow_flash_bbcode +* @param bool $allow_quote_bbcode +* @param bool $allow_url_bbcode * * @return array An array of string with the errors that occurred while parsing */ -function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false) +function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true) { global $phpbb_root_path, $phpEx, $phpbb_dispatcher; @@ -534,6 +582,10 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb * @var bool allow_bbcode Whether or not to parse BBCode * @var bool allow_urls Whether or not to parse URLs * @var bool allow_smilies Whether or not to parse Smilies + * @var bool allow_img_bbcode Whether or not to parse the [img] BBCode + * @var bool allow_flash_bbcode Whether or not to parse the [flash] BBCode + * @var bool allow_quote_bbcode Whether or not to parse the [quote] BBCode + * @var bool allow_url_bbcode Whether or not to parse the [url] BBCode * @since 3.1.0-a1 */ $vars = array( @@ -544,24 +596,23 @@ function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bb 'allow_bbcode', 'allow_urls', 'allow_smilies', + 'allow_img_bbcode', + 'allow_flash_bbcode', + 'allow_quote_bbcode', + 'allow_url_bbcode', ); extract($phpbb_dispatcher->trigger_event('core.modify_text_for_storage_before', compact($vars))); $uid = $bitfield = ''; $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - if ($text === '') - { - return; - } - if (!class_exists('parse_message')) { include($phpbb_root_path . 'includes/message_parser.' . $phpEx); } $message_parser = new parse_message($text); - $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies); + $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies, $allow_img_bbcode, $allow_flash_bbcode, $allow_quote_bbcode, $allow_url_bbcode); $text = $message_parser->message; $uid = $message_parser->bbcode_uid; diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index ea7816077d..ad693f4019 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -2316,7 +2316,10 @@ function convert_bbcode($message, $convert_size = true, $extended_bbcodes = fals function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $config, $user, $db, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; if (substr($trg, -1) == '/') { @@ -2349,7 +2352,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour } } - if (!phpbb_is_writable($path)) + if (!$filesystem->is_writable($path)) { @chmod($path, 0777); } @@ -2370,7 +2373,10 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true) { - global $convert, $phpbb_root_path, $config, $user, $db; + global $convert, $phpbb_root_path, $config, $user, $db, $phpbb_filesystem; + + /** @var \phpbb\filesystem\filesystem_interface $filesystem */ + $filesystem = $phpbb_filesystem; $dirlist = $filelist = $bad_dirs = array(); $src = path($src, $source_relative_path); @@ -2384,7 +2390,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path, 0777); } - if (!phpbb_is_writable($trg_path)) + if (!$filesystem->is_writable($trg_path)) { $bad_dirs[] = path($config['script_path']) . $trg; } @@ -2451,7 +2457,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_ @chmod($trg_path . $dir, 0777); } - if (!phpbb_is_writable($trg_path . $dir)) + if (!$filesystem->is_writable($trg_path . $dir)) { $bad_dirs[] = $trg . $dir; $bad_dirs[] = $trg_path . $dir; diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 1d208a272b..f89068327c 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -376,6 +376,28 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod get_moderators($forum_moderators, $forum_ids_moderator); } + /** + * Event to perform additional actions before the forum list is being generated + * + * @event core.display_forums_before + * @var array active_forum_ary Array with forum data to display active topics + * @var bool display_moderators Flag indicating if we display forum moderators + * @var array forum_moderators Array with forum moderators list + * @var array forum_rows Data array of all forums we display + * @var bool return_moderators Flag indicating if moderators list should be returned + * @var array root_data Array with the root forum data + * @since 3.1.4-RC1 + */ + $vars = array( + 'active_forum_ary', + 'display_moderators', + 'forum_moderators', + 'forum_rows', + 'return_moderators', + 'root_data', + ); + extract($phpbb_dispatcher->trigger_event('core.display_forums_before', compact($vars))); + // Used to tell whatever we have to create a dummy category or not. $last_catless = true; foreach ($forum_rows as $row) @@ -711,13 +733,15 @@ function generate_forum_rules(&$forum_data) function generate_forum_nav(&$forum_data) { global $db, $user, $template, $auth, $config; - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_dispatcher; if (!$auth->acl_get('f_list', $forum_data['forum_id'])) { return; } + $navlinks = $navlinks_parents = $forum_template_data = array(); + // Get forum parents $forum_parents = get_forum_parents($forum_data); @@ -736,35 +760,59 @@ function generate_forum_nav(&$forum_data) continue; } - $template->assign_block_vars('navlinks', array( + $navlinks_parents[] = array( 'S_IS_CAT' => ($parent_type == FORUM_CAT) ? true : false, 'S_IS_LINK' => ($parent_type == FORUM_LINK) ? true : false, 'S_IS_POST' => ($parent_type == FORUM_POST) ? true : false, 'FORUM_NAME' => $parent_name, 'FORUM_ID' => $parent_forum_id, 'MICRODATA' => $microdata_attr . '="' . $parent_forum_id . '"', - 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $parent_forum_id)) + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $parent_forum_id), ); } } - $template->assign_block_vars('navlinks', array( + $navlinks = array( 'S_IS_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, 'S_IS_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, 'S_IS_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, 'FORUM_NAME' => $forum_data['forum_name'], 'FORUM_ID' => $forum_data['forum_id'], 'MICRODATA' => $microdata_attr . '="' . $forum_data['forum_id'] . '"', - 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id'])) + 'U_VIEW_FORUM' => append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $forum_data['forum_id']), ); - $template->assign_vars(array( + $forum_template_data = array( 'FORUM_ID' => $forum_data['forum_id'], 'FORUM_NAME' => $forum_data['forum_name'], 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']), 'S_ENABLE_FEEDS_FORUM' => ($config['feed_forum'] && $forum_data['forum_type'] == FORUM_POST && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $forum_data['forum_options'])) ? true : false, - )); + ); + + /** + * Event to modify the navlinks text + * + * @event core.generate_forum_nav + * @var array forum_data Array with the forum data + * @var array forum_template_data Array with generic forum template data + * @var string microdata_attr The microdata attribute + * @var array navlinks_parents Array with the forum parents navlinks data + * @var array navlinks Array with the forum navlinks data + * @since 3.1.5-RC1 + */ + $vars = array( + 'forum_data', + 'forum_template_data', + 'microdata_attr', + 'navlinks_parents', + 'navlinks', + ); + extract($phpbb_dispatcher->trigger_event('core.generate_forum_nav', compact($vars))); + + $template->assign_block_vars_array('navlinks', $navlinks_parents); + $template->assign_block_vars('navlinks', $navlinks); + $template->assign_vars($forum_template_data); return; } @@ -1075,33 +1123,14 @@ function display_custom_bbcodes() /** * Display reasons +* +* @deprecated 3.2.0-dev */ function display_reasons($reason_id = 0) { - global $db, $user, $template; + global $phpbb_container; - $sql = 'SELECT * - FROM ' . REPORTS_REASONS_TABLE . ' - ORDER BY reason_order ASC'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - // If the reason is defined within the language file, we will use the localized version, else just use the database entry... - if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) - { - $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; - $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; - } - - $template->assign_block_vars('reason', array( - 'ID' => $row['reason_id'], - 'TITLE' => $row['reason_title'], - 'DESCRIPTION' => $row['reason_description'], - 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false) - ); - } - $db->sql_freeresult($result); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } /** diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php index 956e5a5180..d9d073e984 100644 --- a/phpBB/includes/functions_install.php +++ b/phpBB/includes/functions_install.php @@ -182,18 +182,6 @@ function dbms_select($default = '', $only_20x_options = false) } /** -* Get tables of a database -* -* @deprecated -*/ -function get_tables(&$db) -{ - $db_tools = new \phpbb\db\tools\tools($db); - - return $db_tools->sql_list_tables(); -} - -/** * Used to test whether we are able to connect to the database the user has specified * and identify any problems (eg there are already tables with the names we want to use * @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()} @@ -201,7 +189,7 @@ function get_tables(&$db) */ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, $prefix_may_exist = false, $load_dbal = true, $unicode_check = true) { - global $phpbb_root_path, $phpEx, $config, $lang; + global $phpbb_root_path, $phpEx, $config, $lang, $phpbb_filesystem; $dbms = $dbms_details['DRIVER']; @@ -217,7 +205,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, } // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea - if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) + if (($dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite' || $dbms_details['DRIVER'] == 'phpbb\db\driver\sqlite3') && stripos($phpbb_filesystem->realpath($dbhost), $phpbb_filesystem->realpath('../')) === 0) { $error[] = $lang['INST_ERR_DB_FORUM_PATH']; return false; @@ -276,7 +264,9 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix, $temp_prefix = strtolower($table_prefix); $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users'); - $tables = get_tables($db); + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($db); + $tables = $db_tools->sql_list_tables(); $tables = array_map('strtolower', $tables); $table_intersect = array_intersect($tables, $table_ary); diff --git a/phpBB/includes/functions_mcp.php b/phpBB/includes/functions_mcp.php index f17a088d64..46e85c5674 100644 --- a/phpBB/includes/functions_mcp.php +++ b/phpBB/includes/functions_mcp.php @@ -369,7 +369,7 @@ function phpbb_get_pm_data($pm_ids) */ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by_sql, &$sort_order_sql, &$total, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE') { - global $db, $user, $auth, $template, $request; + global $db, $user, $auth, $template, $request, $phpbb_dispatcher; $sort_days = $request->variable('st', 0); $min_time = ($sort_days) ? time() - ($sort_days * 86400) : 0; @@ -554,6 +554,56 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by break; } + // Default total to -1 to allow editing by the event + $total = -1; + + /** + * This event allows you to control the SQL query used to get the total number + * of reports the user can access. + * + * This total is used for the pagination and for displaying the total number + * of reports to the user + * + * + * @event core.mcp_sorting_query_before + * @var string sql The current SQL search string + * @var string mode An id related to the module(s) the user is viewing + * @var string type Which kind of information is this being used for displaying. Posts, topics, etc... + * @var int forum_id The forum id of the posts the user is trying to access, if not 0 + * @var int topic_id The topic id of the posts the user is trying to access, if not 0 + * @var int sort_days The max age of the oldest report to be shown, in days + * @var string sort_key The way the user has decided to sort the data. + * The valid values must be in the keys of the sort_by_* variables + * @var string sort_dir Either 'd' for "DESC" or 'a' for 'ASC' in the SQL query + * @var int limit_days The possible max ages of the oldest report for the user to choose, in days. + * @var array sort_by_sql SQL text (values) for the possible names of the ways of sorting data (keys). + * @var array sort_by_text Language text (values) for the possible names of the ways of sorting data (keys). + * @var int min_time Integer with the minimum post time that the user is searching for + * @var int limit_time_sql Time limiting options used in the SQL query. + * @var int total The total number of reports that exist. Only set if you want to override the result + * @var string where_sql Extra information included in the WHERE clause. It must end with "WHERE" or "AND" or "OR". + * Set to "WHERE" and set total above -1 to override the total value + * @since 3.1.4-RC1 + */ + $vars = array( + 'sql', + 'mode', + 'type', + 'forum_id', + 'topic_id', + 'sort_days', + 'sort_key', + 'sort_dir', + 'limit_days', + 'sort_by_sql', + 'sort_by_text', + 'min_time', + 'limit_time_sql', + 'total', + 'where_sql', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_sorting_query_before', compact($vars))); + if (!isset($sort_by_sql[$sort_key])) { $sort_key = $default_key; @@ -585,7 +635,7 @@ function phpbb_mcp_sorting($mode, &$sort_days, &$sort_key, &$sort_dir, &$sort_by $total = (int) $db->sql_fetchfield('total'); $db->sql_freeresult($result); } - else + else if ($total < -1) { $total = -1; } diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index 199cda829d..6abfb40b01 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -504,7 +504,7 @@ class messenger foreach ($address_ary as $which_ary) { - $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']); + ${$type} .= ((${$type} != '') ? ', ' : '') . (($which_ary['name'] != '') ? mail_encode($which_ary['name'], $encode_eol) . ' <' . $which_ary['email'] . '>' : $which_ary['email']); } } @@ -623,7 +623,7 @@ class messenger */ protected function setup_template() { - global $config, $phpbb_path_helper, $user, $phpbb_extension_manager, $phpbb_container; + global $config, $phpbb_path_helper, $user, $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem; if ($this->template instanceof \phpbb\template\template) { @@ -633,17 +633,20 @@ class messenger $this->template = new \phpbb\template\twig\twig( $phpbb_container->get('path_helper'), $phpbb_container->get('config'), - $phpbb_container->get('user'), new \phpbb\template\context(), new \phpbb\template\twig\environment( $phpbb_container->get('config'), + $phpbb_container->get('filesystem'), $phpbb_container->get('path_helper'), $phpbb_container, $phpbb_container->getParameter('core.root_path') . 'cache/', $phpbb_container->get('ext.manager'), - new \phpbb\template\twig\loader() + new \phpbb\template\twig\loader( + $phpbb_filesystem + ) ), $phpbb_container->getParameter('core.root_path') . 'cache/', + $phpbb_container->get('user'), $phpbb_container->get('template.twig.extensions.collection'), $phpbb_extension_manager ); @@ -672,14 +675,20 @@ class queue var $eol = "\n"; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * constructor */ function queue() { - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $phpbb_filesystem; $this->data = array(); $this->cache_file = "{$phpbb_root_path}cache/queue.$phpEx"; + $this->filesystem = $phpbb_filesystem; } /** @@ -865,7 +874,14 @@ class queue fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } } @@ -907,7 +923,14 @@ class queue fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); fclose($fp); - phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + try + { + $this->filesystem->phpbb_chmod($this->cache_file, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } $lock->release(); diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index d0d09fe9fb..01d3f000c4 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -1088,7 +1088,7 @@ class p_master ->core_path('language/' . $user->lang_name . '/mods/') ->find(); - $lang_files = array_unique(array_merge($user_lang_files, $english_lang_files, $default_lang_files)); + $lang_files = array_merge($english_lang_files, $default_lang_files, $user_lang_files); foreach ($lang_files as $lang_file => $ext_name) { $user->add_lang_ext($ext_name, $lang_file); diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index b93a89e773..fcab667cb2 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -407,14 +407,14 @@ function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) { global $auth, $user, $config, $db, $cache; - global $phpbb_root_path, $phpEx, $phpbb_dispatcher; + global $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_filesystem; $filedata = array( 'error' => array() ); include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); - $upload = new fileupload(); + $upload = new fileupload($phpbb_filesystem); if ($config['check_attachment_content'] && isset($config['mime_triggers'])) { @@ -668,7 +668,7 @@ function get_supported_image_types($type = false) */ function create_thumbnail($source, $destination, $mimetype) { - global $config; + global $config, $phpbb_filesystem; $min_filesize = (int) $config['img_min_thumb_filesize']; $img_filesize = (file_exists($source)) ? @filesize($source) : false; @@ -820,7 +820,14 @@ function create_thumbnail($source, $destination, $mimetype) return false; } - phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + try + { + $phpbb_filesystem->phpbb_chmod($destination, CHMOD_READ | CHMOD_WRITE); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } return true; } @@ -1037,7 +1044,7 @@ function load_drafts($topic_id = 0, $forum_id = 0, $id = 0, $pm_action = '', $ms */ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) { - global $user, $auth, $db, $template, $bbcode, $cache; + global $user, $auth, $db, $template, $cache; global $config, $phpbb_root_path, $phpEx, $phpbb_container, $phpbb_dispatcher; /* @var $phpbb_content_visibility \phpbb\content_visibility */ @@ -1096,13 +1103,11 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); - $bbcode_bitfield = ''; $rowset = array(); $has_attachments = false; while ($row = $db->sql_fetchrow($result)) { $rowset[$row['post_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); if ($row['post_attachment']) { @@ -1111,13 +1116,6 @@ function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id } $db->sql_freeresult($result); - // Instantiate BBCode class - if (!isset($bbcode) && $bbcode_bitfield !== '') - { - include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - // Grab extensions $extensions = $attachments = array(); if ($has_attachments && $auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id)) diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php index 0465f3b00f..245b1c0d1a 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1418,9 +1418,9 @@ function rebuild_header($check_ary) $_types = array('u', 'g'); foreach ($_types as $type) { - if (sizeof($$type)) + if (sizeof(${$type})) { - foreach ($$type as $id) + foreach (${$type} as $id) { $address[$type][$id] = $check_type; } @@ -1961,7 +1961,7 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true) */ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false) { - global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode; + global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth; // Select all receipts and the author from the pm we currently view, to only display their pm-history $sql = 'SELECT author_id, user_id @@ -2013,7 +2013,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode $title = $row['message_subject']; $rowset = array(); - $bbcode_bitfield = ''; $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder='; do @@ -2029,7 +2028,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode else { $rowset[$row['msg_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } } while ($row = $db->sql_fetchrow($result)); @@ -2040,16 +2038,6 @@ function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode return false; } - // Instantiate BBCode class - if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '') - { - if (!class_exists('bbcode')) - { - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); - } - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - $title = censor_text($title); $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm'); diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index f179b2fd70..dcc9bc4874 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -47,6 +47,11 @@ class filespec var $upload = ''; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * The plupload object * @var \phpbb\plupload\plupload */ @@ -62,7 +67,7 @@ class filespec * File Class * @access private */ - function filespec($upload_ary, $upload_namespace, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) + function filespec($upload_ary, $upload_namespace, \phpbb\filesystem\filesystem_interface $phpbb_filesystem, \phpbb\mimetype\guesser $mimetype_guesser = null, \phpbb\plupload\plupload $plupload = null) { if (!isset($upload_ary)) { @@ -97,6 +102,7 @@ class filespec $this->upload = $upload_namespace; $this->plupload = $plupload; $this->mimetype_guesser = $mimetype_guesser; + $this->filesystem = $phpbb_filesystem; } /** @@ -213,6 +219,8 @@ class filespec */ static public function get_extension($filename) { + $filename = utf8_basename($filename); + if (strpos($filename, '.') === false) { return ''; @@ -374,7 +382,14 @@ class filespec return false; } - phpbb_chmod($this->destination_file, $chmod); + try + { + $this->filesystem->phpbb_chmod($this->destination_file, $chmod); + } + catch (\phpbb\filesystem\exception\filesystem_exception $e) + { + // Do nothing + } } // Try to get real filesize from destination folder @@ -387,28 +402,28 @@ class filespec { $this->width = $this->height = 0; - if (($this->image_info = @getimagesize($this->destination_file)) !== false) - { - $this->width = $this->image_info[0]; - $this->height = $this->image_info[1]; + // Get imagesize class + $imagesize = new \fastImageSize\fastImageSize(); - if (!empty($this->image_info['mime'])) - { - $this->mimetype = $this->image_info['mime']; - } + $this->image_info = $imagesize->getImageSize($this->destination_file, $this->mimetype); + + if ($this->image_info !== false) + { + $this->width = $this->image_info['width']; + $this->height = $this->image_info['height']; // Check image type $types = fileupload::image_types(); - if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) + if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']])) { - if (!isset($types[$this->image_info[2]])) + if (!isset($types[$this->image_info['type']])) { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype); + $this->error[] = $user->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype); } else { - $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension); + $this->error[] = $user->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension); } } @@ -500,8 +515,14 @@ class fileupload var $upload_timeout = 6; /** + * @var \phpbb\filesystem\filesystem_interface + */ + protected $filesystem; + + /** * Init file upload class. * + * @param \phpbb\filesystem\filesystem_interface $filesystem * @param string $error_prefix Used error messages will get prefixed by this string * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png') * @param int $max_filesize Maximum filesize @@ -513,13 +534,14 @@ class fileupload * contain any of its values. Defaults to false. * */ - function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) + function fileupload(\phpbb\filesystem\filesystem_interface $filesystem, $error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) { $this->set_allowed_extensions($allowed_extensions); $this->set_max_filesize($max_filesize); $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height); $this->set_error_prefix($error_prefix); $this->set_disallowed_content($disallowed_content); + $this->filesystem = $filesystem; } /** @@ -613,7 +635,7 @@ class fileupload } } - $file = new filespec($upload, $this, $mimetype_guesser, $plupload); + $file = new filespec($upload, $this, $this->filesystem, $mimetype_guesser, $plupload); if ($file->init_error) { @@ -694,7 +716,7 @@ class fileupload $upload['type'] = $filedata['type']; } - $file = new filespec($upload, $this, $mimetype_guesser); + $file = new filespec($upload, $this, $this->filesystem, $mimetype_guesser); if ($file->init_error) { @@ -932,7 +954,7 @@ class fileupload $upload_ary['tmp_name'] = $filename; - $file = new filespec($upload_ary, $this, $mimetype_guesser); + $file = new filespec($upload_ary, $this, $this->filesystem, $mimetype_guesser); $this->common_checks($file); return $file; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index e4f237b686..85b6f2be62 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -44,13 +44,13 @@ function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; - if ($$which_ary && !is_array($$which_ary)) + if (${$which_ary} && !is_array(${$which_ary})) { - $$which_ary = array($$which_ary); + ${$which_ary} = array(${$which_ary}); } - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary); - unset($$which_ary); + $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', ${$which_ary}) : array_map('utf8_clean_string', ${$which_ary}); + unset(${$which_ary}); $user_id_ary = $username_ary = array(); @@ -400,7 +400,7 @@ function user_add($user_row, $cp_data = false, $notifications_data = null) */ function user_delete($mode, $user_ids, $retain_username = true) { - global $cache, $config, $db, $user, $phpbb_dispatcher; + global $cache, $config, $db, $user, $phpbb_dispatcher, $phpbb_container; global $phpbb_root_path, $phpEx; $db->sql_transaction('begin'); @@ -674,6 +674,9 @@ function user_delete($mode, $user_ids, $retain_username = true) } phpbb_delete_users_pms($user_ids); + $phpbb_notifications = $phpbb_container->get('notification_manager'); + $phpbb_notifications->delete_notifications('notification.type.admin_activate_user', $user_ids); + $db->sql_transaction('commit'); /** @@ -1644,89 +1647,37 @@ function validate_username($username, $allowed_username = false) return 'INVALID_CHARS'; } - $mbstring = $pcre = false; - - // generic UTF-8 character types supported? - if (phpbb_pcre_utf8_support()) - { - $pcre = true; - } - else if (function_exists('mb_ereg_match')) - { - mb_regex_encoding('UTF-8'); - $mbstring = true; - } - switch ($config['allow_name_chars']) { case 'USERNAME_CHARS_ANY': - $pcre = true; $regex = '.+'; break; case 'USERNAME_ALPHA_ONLY': - $pcre = true; $regex = '[A-Za-z0-9]+'; break; case 'USERNAME_ALPHA_SPACERS': - $pcre = true; $regex = '[A-Za-z0-9-[\]_+ ]+'; break; case 'USERNAME_LETTER_NUM': - if ($pcre) - { - $regex = '[\p{Lu}\p{Ll}\p{N}]+'; - } - else if ($mbstring) - { - $regex = '[[:upper:][:lower:][:digit:]]+'; - } - else - { - $pcre = true; - $regex = '[a-zA-Z0-9]+'; - } + $regex = '[\p{Lu}\p{Ll}\p{N}]+'; break; case 'USERNAME_LETTER_NUM_SPACERS': - if ($pcre) - { - $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; - } - else if ($mbstring) - { - $regex = '[-\]_+ \[[:upper:][:lower:][:digit:]]+'; - } - else - { - $pcre = true; - $regex = '[-\]_+ [a-zA-Z0-9]+'; - } + $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; break; case 'USERNAME_ASCII': default: - $pcre = true; $regex = '[\x01-\x7F]+'; break; } - if ($pcre) + if (!preg_match('#^' . $regex . '$#u', $username)) { - if (!preg_match('#^' . $regex . '$#u', $username)) - { - return 'INVALID_CHARS'; - } - } - else if ($mbstring) - { - mb_ereg_search_init($username, '^' . $regex . '$'); - if (!mb_ereg_search()) - { - return 'INVALID_CHARS'; - } + return 'INVALID_CHARS'; } $sql = 'SELECT username @@ -1781,35 +1732,10 @@ function validate_password($password) return false; } - $pcre = $mbstring = false; - - // generic UTF-8 character types supported? - if (phpbb_pcre_utf8_support()) - { - $upp = '\p{Lu}'; - $low = '\p{Ll}'; - $num = '\p{N}'; - $sym = '[^\p{Lu}\p{Ll}\p{N}]'; - $pcre = true; - } - else if (function_exists('mb_ereg_match')) - { - mb_regex_encoding('UTF-8'); - $upp = '[[:upper:]]'; - $low = '[[:lower:]]'; - $num = '[[:digit:]]'; - $sym = '[^[:upper:][:lower:][:digit:]]'; - $mbstring = true; - } - else - { - $upp = '[A-Z]'; - $low = '[a-z]'; - $num = '[0-9]'; - $sym = '[^A-Za-z0-9]'; - $pcre = true; - } - + $upp = '\p{Lu}'; + $low = '\p{Ll}'; + $num = '\p{N}'; + $sym = '[^\p{Lu}\p{Ll}\p{N}]'; $chars = array(); switch ($config['pass_complex']) @@ -1832,24 +1758,11 @@ function validate_password($password) $chars[] = $upp; } - if ($pcre) - { - foreach ($chars as $char) - { - if (!preg_match('#' . $char . '#u', $password)) - { - return 'INVALID_CHARS'; - } - } - } - else if ($mbstring) + foreach ($chars as $char) { - foreach ($chars as $char) + if (!preg_match('#' . $char . '#u', $password)) { - if (mb_ereg($char, $password) === false) - { - return 'INVALID_CHARS'; - } + return 'INVALID_CHARS'; } } @@ -3381,7 +3294,7 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) + if (!$row || ($row['group_type'] == GROUP_SPECIAL && !$user->is_setup())) { return ''; } diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index ea17f55402..0d03a37731 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -41,10 +41,27 @@ function mcp_front_view($id, $mode, $action) if (!empty($forum_list)) { - $sql = 'SELECT COUNT(post_id) AS total - FROM ' . POSTS_TABLE . ' - WHERE ' . $db->sql_in_set('forum_id', $forum_list) . ' - AND ' . $db->sql_in_set('post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)); + $sql_ary = array( + 'SELECT' => 'COUNT(post_id) AS total', + 'FROM' => array( + POSTS_TABLE => 'p', + ), + 'WHERE' => $db->sql_in_set('p.forum_id', $forum_list) . ' + AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) + ); + + /** + * Allow altering the query to get the number of unapproved posts + * + * @event core.mcp_front_queue_unapproved_total_before + * @var int sql_ary Query to get the total number of unapproved posts + * @var array forum_list List of forums to look for unapproved posts + * @since 3.1.5-RC1 + */ + $vars = array('sql_ary', 'forum_list'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_queue_unapproved_total_before', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query($sql); $total = (int) $db->sql_fetchfield('total'); $db->sql_freeresult($result); @@ -157,6 +174,18 @@ function mcp_front_view($id, $mode, $action) AND r.pm_id = 0 AND r.report_closed = 0 AND ' . $db->sql_in_set('p.forum_id', $forum_list); + + /** + * Alter sql query to count the number of reported posts + * + * @event core.mcp_front_reports_count_query_before + * @var int sql The query string used to get the number of reports that exist + * @var array forum_list List of forums that contain the posts + * @since 3.1.5-RC1 + */ + $vars = array('sql', 'forum_list'); + extract($phpbb_dispatcher->trigger_event('core.mcp_front_reports_count_query_before', compact($vars))); + $result = $db->sql_query($sql); $total = (int) $db->sql_fetchfield('total'); $db->sql_freeresult($result); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index e3fbbc0418..e8ab0167f5 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -226,6 +226,31 @@ class mcp_main break; default: + if ($quickmod) + { + switch ($action) + { + case 'lock': + case 'unlock': + case 'make_announce': + case 'make_sticky': + case 'make_global': + case 'make_normal': + case 'make_onindex': + case 'move': + case 'fork': + case 'delete_topic': + trigger_error('TOPIC_NOT_EXIST'); + break; + + case 'lock_post': + case 'unlock_post': + case 'delete_post': + trigger_error('POST_NOT_EXIST'); + break; + } + } + trigger_error('NO_MODE', E_USER_ERROR); break; } diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index 84db205fec..5cc158de5f 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -1402,11 +1402,6 @@ class mcp_queue } else { - if (!function_exists('display_reasons')) - { - include($phpbb_root_path . 'includes/functions_display.' . $phpEx); - } - $show_notify = false; foreach ($post_info as $post_data) @@ -1426,7 +1421,7 @@ class mcp_queue $confirm_template = 'mcp_approve.html'; if ($is_disapproving) { - display_reasons($reason_id); + $phpbb_container->get('phpbb.report.report_reason_list_provider')->display_reasons($reason_id); } else { diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php index bcfbd25c0f..30a2188b98 100644 --- a/phpBB/includes/mcp/mcp_reports.php +++ b/phpBB/includes/mcp/mcp_reports.php @@ -74,17 +74,66 @@ class mcp_reports // closed reports are accessed by report id $report_id = $request->variable('r', 0); - $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour - FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u - WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' + $sql_ary = array( + 'SELECT' => 'r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour', + + 'FROM' => array( + REPORTS_TABLE => 'r', + REPORTS_REASONS_TABLE => 'rr', + USERS_TABLE => 'u', + ), + + 'WHERE' => (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' AND rr.reason_id = r.reason_id AND r.user_id = u.user_id - AND r.pm_id = 0 - ORDER BY report_closed ASC'; + AND r.pm_id = 0', + + 'ORDER_BY' => 'report_closed ASC', + ); + + /** + * Allow changing the query to obtain the user-submitted report. + * + * @event core.mcp_reports_report_details_query_before + * @var array sql_ary The array in the format of the query builder with the query + * @var mixed forum_id The forum_id, the number in the f GET parameter + * @var int post_id The post_id of the report being viewed (if 0, it is meaningless) + * @var int report_id The report_id of the report being viewed + * @since 3.1.5-RC1 + */ + $vars = array( + 'sql_ary', + 'forum_id', + 'post_id', + 'report_id', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_reports_report_details_query_before', compact($vars))); + + $sql = $db->sql_build_query('SELECT', $sql_ary); $result = $db->sql_query_limit($sql, 1); $report = $db->sql_fetchrow($result); $db->sql_freeresult($result); + /** + * Allow changing the data obtained from the user-submitted report. + * + * @event core.mcp_reports_report_details_query_after + * @var array sql_ary The array in the format of the query builder with the query that had been executted + * @var mixed forum_id The forum_id, the number in the f GET parameter + * @var int post_id The post_id of the report being viewed (if 0, it is meaningless) + * @var int report_id The report_id of the report being viewed + * @var int report The query's resulting row. + * @since 3.1.5-RC1 + */ + $vars = array( + 'sql_ary', + 'forum_id', + 'post_id', + 'report_id', + 'report', + ); + extract($phpbb_dispatcher->trigger_event('core.mcp_reports_report_details_query_after', compact($vars))); + if (!$report) { trigger_error('NO_REPORT'); @@ -491,6 +540,7 @@ function close_report($report_id_list, $mode, $action, $pm = false) { $post_id_list[] = $row[$id_column]; } + $db->sql_freeresult($result); $post_id_list = array_unique($post_id_list); if ($pm) diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php index 0b8c663304..66bcdad72c 100644 --- a/phpBB/includes/mcp/mcp_topic.php +++ b/phpBB/includes/mcp/mcp_topic.php @@ -149,21 +149,13 @@ function mcp_topic_view($id, $mode, $action) $result = $db->sql_query_limit($sql, $posts_per_page, $start); $rowset = $post_id_list = array(); - $bbcode_bitfield = ''; while ($row = $db->sql_fetchrow($result)) { $rowset[] = $row; $post_id_list[] = $row['post_id']; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); } $db->sql_freeresult($result); - if ($bbcode_bitfield !== '') - { - include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - $topic_tracking_info = array(); // Get topic tracking info @@ -269,6 +261,8 @@ function mcp_topic_view($id, $mode, $action) * @var int current_row_number Number of the post on this page * @var array post_row Template block array of the current post * @var array row Array with original post and user data + * @var array topic_info Array with topic data + * @var int total Total posts count * @since 3.1.4-RC1 */ $vars = array( @@ -280,6 +274,8 @@ function mcp_topic_view($id, $mode, $action) 'current_row_number', 'post_row', 'row', + 'topic_info', + 'total', ); extract($phpbb_dispatcher->trigger_event('core.mcp_topic_review_modify_row', compact($vars))); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index ccb953adbe..cbd2282e96 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -21,6 +21,19 @@ if (!defined('IN_PHPBB')) if (!class_exists('bbcode')) { + // The following lines are for extensions which include message_parser.php + // while $phpbb_root_path and $phpEx are out of the script scope + // which may lead to the 'Undefined variable' and 'failed to open stream' errors + if (!isset($phpbb_root_path)) + { + global $phpbb_root_path; + } + + if (!isset($phpEx)) + { + global $phpEx; + } + include($phpbb_root_path . 'includes/bbcode.' . $phpEx); } @@ -115,6 +128,9 @@ class bbcode_firstpass extends bbcode // [quote] in second position. // To parse multiline URL we enable dotall option setting only for URL text // but not for link itself, thus [url][/url] is not affected. + // + // To perform custom validation in extension, use $this->validate_bbcode_by_extension() + // method which accepts variable number of parameters $this->bbcodes = array( 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")), 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")), @@ -326,22 +342,23 @@ class bbcode_firstpass extends bbcode if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width']) { - $stats = @getimagesize(htmlspecialchars_decode($in)); + $imagesize = new \fastImageSize\fastImageSize(); + $size_info = $imagesize->getImageSize(htmlspecialchars_decode($in)); - if ($stats === false) + if ($size_info === false) { $error = true; $this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE']; } else { - if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1]) + if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $size_info['height']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']); } - if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0]) + if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $size_info['width']) { $error = true; $this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']); @@ -1103,7 +1120,7 @@ class parse_message extends bbcode_firstpass */ function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') { - global $config, $db, $user, $phpbb_dispatcher; + global $config, $db, $user, $phpbb_dispatcher, $phpbb_container; $this->mode = $mode; @@ -1132,12 +1149,6 @@ class parse_message extends bbcode_firstpass $this->decode_message(); } - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - // Store message length... $message_length = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); @@ -1210,56 +1221,29 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } + // Get the parser + $parser = $phpbb_container->get('text_formatter.parser'); - $this->prepare_bbcodes(); - } + // Set the parser's options + ($allow_bbcode) ? $parser->enable_bbcodes() : $parser->disable_bbcodes(); + ($allow_magic_url) ? $parser->enable_magic_url() : $parser->disable_magic_url(); + ($allow_smilies) ? $parser->enable_smilies() : $parser->disable_smilies(); + ($allow_img_bbcode) ? $parser->enable_bbcode('img') : $parser->disable_bbcode('img'); + ($allow_flash_bbcode) ? $parser->enable_bbcode('flash') : $parser->disable_bbcode('flash'); + ($allow_quote_bbcode) ? $parser->enable_bbcode('quote') : $parser->disable_bbcode('quote'); + ($allow_url_bbcode) ? $parser->enable_bbcode('url') : $parser->disable_bbcode('url'); - // Parse smilies - if ($allow_smilies) - { - $this->smilies($config['max_' . $mode . '_smilies']); - } + // Set some config values + $parser->set_vars(array( + 'max_font_size' => $config['max_' . $this->mode . '_font_size'], + 'max_img_height' => $config['max_' . $this->mode . '_img_height'], + 'max_img_width' => $config['max_' . $this->mode . '_img_width'], + 'max_smilies' => $config['max_' . $this->mode . '_smilies'], + 'max_urls' => $config['max_' . $this->mode . '_urls'] + )); - $num_urls = 0; - - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } - - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); - - if ($config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\<!-- ([lmwe]) --\>.*?\<!-- \1 --\>#', $this->message, $matches); - } - } - - // Check for out-of-bounds characters that are currently - // not supported by utf8_bin in MySQL - if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $this->message, $matches)) - { - $character_list = implode('<br />', $matches[0]); - $this->warn_msg[] = $user->lang('UNSUPPORTED_CHARACTERS_MESSAGE', $character_list); - return $update_this_message ? $this->warn_msg : $return_message; - } + // Parse this message + $this->message = $parser->parse(htmlspecialchars_decode($this->message, ENT_QUOTES)); // Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length. // The maximum length check happened before any parsings. @@ -1269,10 +1253,27 @@ class parse_message extends bbcode_firstpass return (!$update_this_message) ? $return_message : $this->warn_msg; } - // Check number of links - if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls']) + // Remove quotes that are nested too deep + if ($config['max_quote_depth'] > 0) + { + $this->message = $phpbb_container->get('text_formatter.utils')->remove_bbcode( + $this->message, + 'quote', + $config['max_quote_depth'] + ); + } + + // Check for errors + $errors = $parser->get_errors(); + if ($errors) { - $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $config['max_' . $mode . '_urls']); + foreach ($errors as $i => $args) + { + // Translate each error with $user->lang() + $errors[$i] = call_user_func_array(array($user, 'lang'), $args); + } + $this->warn_msg = array_merge($this->warn_msg, $errors); + return (!$update_this_message) ? $return_message : $this->warn_msg; } @@ -1292,7 +1293,7 @@ class parse_message extends bbcode_firstpass */ function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true) { - global $phpbb_dispatcher; + global $phpbb_container, $phpbb_dispatcher; // If false, then the parsed message get returned but internal message not processed. if (!$update_this_message) @@ -1301,26 +1302,25 @@ class parse_message extends bbcode_firstpass $return_message = &$this->message; } - if ($this->message_status == 'plain') + // NOTE: message_status is unreliable for detecting unparsed text because some callers + // change $this->message without resetting $this->message_status to 'plain' so we + // inspect the message instead + //if ($this->message_status == 'plain') + if (!preg_match('/^<[rt][ >]/', $this->message)) { // Force updating message - of course. $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true); } - // Replace naughty words such as farty pants - $this->message = censor_text($this->message); - - // Parse BBcode - if ($allow_bbcode) + // There's a bug when previewing a topic with no poll, because the empty title of the poll + // gets parsed but $this->message still ends up empty. This fixes it, until a proper fix is + // devised + if ($this->message === '') { - $this->bbcode_cache_init(); - - // We are giving those parameters to be able to use the bbcode class on its own - $this->bbcode_second_pass($this->message, $this->bbcode_uid); + $this->message = $phpbb_container->get('text_formatter.parser')->parse($this->message); } - $this->message = bbcode_nl2br($this->message); - $this->message = smiley_text($this->message, !$allow_smilies); + $this->message = $phpbb_container->get('text_formatter.renderer')->render($this->message); $text = $this->message; $uid = $this->bbcode_uid; @@ -1784,24 +1784,22 @@ class parse_message extends bbcode_firstpass $poll_max_options = $poll['poll_max_options']; - // Parse Poll Option text ;) + // Parse Poll Option text $tmp_message = $this->message; - $this->message = $poll['poll_option_text']; - $bbcode_bitfield = $this->bbcode_bitfield; - $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); + $poll['poll_options_size'] = sizeof($poll['poll_options']); - $bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; + foreach ($poll['poll_options'] as &$poll_option) + { + $this->message = $poll_option; + $poll_option = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false, 'poll'); + } + unset($poll_option); + $poll['poll_option_text'] = implode("\n", $poll['poll_options']); // Parse Poll Title - $tmp_message = $this->message; $this->message = $poll['poll_title']; - $this->bbcode_bitfield = $bbcode_bitfield; - - $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); - $poll['poll_options_size'] = sizeof($poll['poll_options']); - if (!$poll['poll_title'] && $poll['poll_options_size']) { $this->warn_msg[] = $user->lang['NO_POLL_TITLE']; @@ -1819,10 +1817,6 @@ class parse_message extends bbcode_firstpass } } - $this->bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; - unset($tmp_message); - if (sizeof($poll['poll_options']) == 1) { $this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS']; @@ -1837,6 +1831,8 @@ class parse_message extends bbcode_firstpass } $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']); + + $this->message = $tmp_message; } /** @@ -1862,4 +1858,36 @@ class parse_message extends bbcode_firstpass { $this->mimetype_guesser = $mimetype_guesser; } + + /** + * Function to perform custom bbcode validation by extensions + * can be used in bbcode_init() to assign regexp replacement + * Example: 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->validate_bbcode_by_extension('\$1')") + * + * Accepts variable number of parameters + * + * @return mixed Validation result + */ + public function validate_bbcode_by_extension() + { + global $phpbb_dispatcher; + + $return = false; + $params_array = func_get_args(); + + /** + * Event to validate bbcode with the custom validating methods + * provided by extensions + * + * @event core.validate_bbcode_by_extension + * @var array params_array Array with the function parameters + * @var mixed return Validation result to return + * + * @since 3.1.5-RC1 + */ + $vars = array('params_array', 'return'); + extract($phpbb_dispatcher->trigger_event('core.validate_bbcode_by_extension', compact($vars))); + + return $return; + } } diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index 8c69346f03..4ff27e8cf1 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -90,6 +90,32 @@ function compose_pm($id, $mode, $action, $user_folders = array()) // we include the language file here $user->add_lang('viewtopic'); + /** + * Modify the default vars before composing a PM + * + * @event core.ucp_pm_compose_modify_data + * @var int msg_id post_id in the page request + * @var int to_user_id The id of whom the message is to + * @var int to_group_id The id of the group the message is to + * @var bool submit Whether the form has been submitted + * @var bool preview Whether the user is previewing the PM or not + * @var string action One of: post, reply, quote, forward, quotepost, edit, delete, smilies + * @var bool delete Whether the user is deleting the PM + * @var int reply_to_all Value of reply_to_all request variable. + * @since 3.1.4-RC1 + */ + $vars = array( + 'msg_id', + 'to_user_id', + 'to_group_id', + 'submit', + 'preview', + 'action', + 'delete', + 'reply_to_all', + ); + extract($phpbb_dispatcher->trigger_event('core.ucp_pm_compose_modify_data', compact($vars))); + // Output PM_TO box if message composing if ($action != 'edit') { @@ -915,7 +941,11 @@ function compose_pm($id, $mode, $action, $user_folders = array()) { $message_link = ''; } - $message_parser->message = $message_link . '[quote="' . $quote_username . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text(trim($message_parser->message)), + array('author' => $quote_username) + ); + $message_parser->message = $message_link . $quote_text . "\n"; } if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) @@ -943,7 +973,11 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); $forward_text[] = sprintf($user->lang['FWD_TO'], implode($user->lang['COMMA_SEPARATOR'], $fwd_to_field['to'])); - $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $quote_text = $phpbb_container->get('text_formatter.utils')->generate_quote( + censor_text(trim($message_parser->message)), + array('author' => $quote_username) + ); + $message_parser->message = implode("\n", $forward_text) . "\n\n" . $quote_text; $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); } @@ -1114,6 +1148,9 @@ function compose_pm($id, $mode, $action, $user_folders = array()) $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + // Start assigning vars for main posting page ... $template->assign_vars(array( 'L_POST_A' => $page_title, @@ -1122,7 +1159,7 @@ function compose_pm($id, $mode, $action, $user_folders = array()) 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', 'MESSAGE' => $message_text, - 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($bbcode_status ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index b3220ef4d6..44564ed562 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -53,15 +53,6 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) // Grab icons $icons = $cache->obtain_icons(); - $bbcode = false; - - // Instantiate BBCode if need be - if ($message_row['bbcode_bitfield']) - { - include($phpbb_root_path . 'includes/bbcode.' . $phpEx); - $bbcode = new bbcode($message_row['bbcode_bitfield']); - } - // Load the custom profile fields if ($config['load_cpf_pm']) { @@ -241,7 +232,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EMAIL' => $user_info['email'], - 'U_REPORT' => ($config['allow_pm_report']) ? append_sid("{$phpbb_root_path}report.$phpEx", "pm=" . $message_row['msg_id']) : '', + 'U_REPORT' => ($config['allow_pm_report']) ? $phpbb_container->get('controller.helper')->route('phpbb_report_pm_controller', array('id' => $message_row['msg_id'])) : '', 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index cbaa71c33e..215a870007 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -69,7 +69,7 @@ class ucp_prefs * @var array data Array with current ucp options data * @var array error Array with list of errors * @since 3.1.0-a1 - * @changed 3.1.4-rc1 Added error variable to the event + * @changed 3.1.4-RC1 Added error variable to the event */ $vars = array('submit', 'data', 'error'); extract($phpbb_dispatcher->trigger_event('core.ucp_prefs_personal_data', compact($vars))); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index dd225783ab..2f4d650ed0 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -114,6 +114,18 @@ class ucp_profile $error[] = 'FORM_INVALID'; } + /** + * Validate user data on editing registration data in UCP + * + * @event core.ucp_profile_reg_details_validate + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @var array error Array of any generated errors + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_reg_details_validate', compact($vars))); + if (!sizeof($error)) { $sql_ary = array( @@ -366,6 +378,18 @@ class ucp_profile $error[] = 'FORM_INVALID'; } + /** + * Validate user data on editing profile in UCP + * + * @event core.ucp_profile_validate_profile_info + * @var array data Array with user profile data + * @var bool submit Flag indicating if submit button has been pressed + * @var array error Array of any generated errors + * @since 3.1.4-RC1 + */ + $vars = array('data', 'submit', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_profile_validate_profile_info', compact($vars))); + if (!sizeof($error)) { $data['notify'] = $user->data['user_notify_type']; @@ -393,9 +417,10 @@ class ucp_profile * @event core.ucp_profile_info_modify_sql_ary * @var array cp_data Array with the user custom profile fields data * @var array data Array with user profile data + * @var array sql_ary user options data we update * @since 3.1.4-RC1 */ - $vars = array('cp_data', 'data'); + $vars = array('cp_data', 'data', 'sql_ary'); extract($phpbb_dispatcher->trigger_event('core.ucp_profile_info_modify_sql_ary', compact($vars))); $sql = 'UPDATE ' . USERS_TABLE . ' @@ -535,6 +560,9 @@ class ucp_profile $decoded_message = generate_text_for_edit($signature, $bbcode_uid, $bbcode_bitfield); + /** @var \phpbb\controller\helper $controller_helper */ + $controller_helper = $phpbb_container->get('controller.helper'); + $template->assign_vars(array( 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', 'SIGNATURE' => $decoded_message['text'], @@ -544,7 +572,7 @@ class ucp_profile 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', - 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid("{$phpbb_root_path}faq.$phpEx", 'mode=bbcode') . '">', '</a>'), + 'BBCODE_STATUS' => $user->lang(($config['allow_sig_bbcode'] ? 'BBCODE_IS_ON' : 'BBCODE_IS_OFF'), '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'), 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 776bf80481..7ff6506292 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -30,7 +30,7 @@ class ucp_register function main($id, $mode) { global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; - global $request, $phpbb_container; + global $request, $phpbb_container, $phpbb_dispatcher; // if ($config['require_activation'] == USER_ACTIVATION_DISABLE || @@ -199,6 +199,19 @@ class ucp_register 'lang' => basename($request->variable('lang', $user->lang_name)), 'tz' => $request->variable('tz', $timezone), ); + /** + * Add UCP register data before they are assigned to the template or submitted + * + * To assign data to the template, use $template->assign_vars() + * + * @event core.ucp_register_data_before + * @var bool submit Do we display the form only + * or did the user press submit + * @var array data Array with current ucp registration data + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_data_before', compact($vars))); // Check and initialize some variables if needed if ($submit) @@ -259,6 +272,19 @@ class ucp_register $error[] = $user->lang['NEW_PASSWORD_ERROR']; } } + /** + * Check UCP registration data after they are submitted + * + * @event core.ucp_register_data_after + * @var bool submit Do we display the form only + * or did the user press submit + * @var array data Array with current ucp registration data + * @var array cp_data Array with custom profile fields data + * @var array error Array with list of errors + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'data', 'cp_data', 'error'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_data_after', compact($vars))); if (!sizeof($error)) { @@ -322,6 +348,20 @@ class ucp_register { $user_row['user_new'] = 1; } + /** + * Add into $user_row before user_add + * + * user_add allows adding more data into the users table + * + * @event core.ucp_register_user_row_after + * @var bool submit Do we display the form only + * or did the user press submit + * @var array cp_data Array with custom profile fields data + * @var array user_row Array with current ucp registration data + * @since 3.1.4-RC1 + */ + $vars = array('submit', 'cp_data', 'user_row'); + extract($phpbb_dispatcher->trigger_event('core.ucp_register_user_row_after', compact($vars))); // Register user... $user_id = user_add($user_row, $cp_data); |