示例#1
0
 public static function dec($config_name, $decrement)
 {
     if (gettype(self::$default_config[$config_name]) != 'int' && gettype(self::$default_config[$config_name]) != 'integer') {
         return false;
     }
     set_config_count(self::$prefix . $config_name, 0 - (int) $decrement, self::is_dynamic($config_name));
     self::$config[$config_name] -= (int) $decrement;
     return true;
 }
示例#2
0
 protected function setUp()
 {
     parent::setUp();
     global $cache, $config, $db, $phpbb_dispatcher, $phpbb_container;
     $db = $this->db = $this->new_dbal();
     $config = new \phpbb\config\config(array('load_online_time' => 5, 'search_type' => '\\phpbb\\search\\fulltext_mysql'));
     set_config(false, false, false, $config);
     set_config_count(false, false, false, $config);
     $cache = new phpbb_mock_null_cache();
     $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
     $phpbb_container = new phpbb_mock_container_builder();
     $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
 }
示例#3
0
 public function setUp()
 {
     global $phpbb_root_path, $phpEx, $phpbb_dispatcher, $user, $cache, $auth;
     parent::setUp();
     $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
     $db = $this->new_dbal();
     $config = new \phpbb\config\config(array());
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     $cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), $config, $db, $phpbb_root_path, $phpEx);
     $auth = $this->getMock('\\phpbb\\auth\\auth');
     $auth->expects($this->any())->method('acl_get')->with($this->stringContains('_'), $this->anything())->will($this->returnValueMap(array(array('u_viewprofile', 1, false))));
     $user = new \phpbb\user('\\phpbb\\datetime');
     $user->data = array('user_lang' => 'en');
     $user->add_lang('common');
     $user_loader = new phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
     $user_loader->load_users(array(2, 3, 4, 5, 6));
     $this->notification = new phpbb_mock_notification_type_post($user_loader, null, null, $user, null, null, $phpbb_root_path, $phpEx, null, null, null);
 }
示例#4
0
 public function setUp()
 {
     parent::setUp();
     global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $user, $request, $phpEx, $phpbb_root_path;
     // Database
     $this->db = $this->new_dbal();
     $db = $this->db;
     // Auth
     $auth = $this->getMock('\\phpbb\\auth\\auth');
     $auth->expects($this->any())->method('acl_get')->with($this->stringContains('_'), $this->anything())->will($this->returnValueMap(array(array('f_noapprove', 1, true), array('f_postcount', 1, true), array('m_edit', 1, false))));
     // Config
     $config = new \phpbb\config\config(array('num_topics' => 1, 'num_posts' => 1));
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     $cache = new \phpbb\cache\service(new \phpbb\cache\driver\null(), $config, $db, $phpbb_root_path, $phpEx);
     // Event dispatcher
     $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
     // User
     $user = $this->getMock('\\phpbb\\user', array(), array('\\phpbb\\datetime'));
     $user->ip = '';
     $user->data = array('user_id' => 2, 'username' => 'user-name', 'is_registered' => true, 'user_colour' => '');
     // Request
     $type_cast_helper = $this->getMock('\\phpbb\\request\\type_cast_helper_interface');
     $request = $this->getMock('\\phpbb\\request\\request');
     // Container
     $phpbb_container = new phpbb_mock_container_builder();
     $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
     $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
     $user_loader = new \phpbb\user_loader($db, $phpbb_root_path, $phpEx, USERS_TABLE);
     // Notification Types
     $notification_types = array('quote', 'bookmark', 'post', 'post_in_queue', 'topic', 'topic_in_queue', 'approve_topic', 'approve_post');
     $notification_types_array = array();
     foreach ($notification_types as $type) {
         $class_name = '\\phpbb\\notification\\type\\' . $type;
         $class = new $class_name($user_loader, $db, $cache->get_driver(), $user, $auth, $config, $phpbb_root_path, $phpEx, NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE);
         $phpbb_container->set('notification.type.' . $type, $class);
         $notification_types_array['notification.type.' . $type] = $class;
     }
     // Notification Manager
     $phpbb_notifications = new \phpbb\notification\manager($notification_types_array, array(), $phpbb_container, $user_loader, $config, $phpbb_dispatcher, $db, $cache, $user, $phpbb_root_path, $phpEx, NOTIFICATION_TYPES_TABLE, NOTIFICATIONS_TABLE, USER_NOTIFICATIONS_TABLE);
     $phpbb_container->set('notification_manager', $phpbb_notifications);
 }
示例#5
0
    /**
     * @dataProvider delete_post_data
     */
    public function test_delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $reason, $expected_posts, $expected_topic, $expected_forum, $expected_user)
    {
        global $auth, $cache, $config, $db, $phpbb_container, $phpbb_dispatcher, $phpbb_root_path, $phpEx;
        $config['search_type'] = 'phpbb_mock_search';
        $cache = new phpbb_mock_cache();
        $db = $this->new_dbal();
        $phpbb_config = new \phpbb\config\config(array('num_posts' => 3, 'num_topics' => 1));
        $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
        set_config_count(null, null, null, $phpbb_config);
        // Create auth mock
        $auth = $this->getMock('\\phpbb\\auth\\auth');
        $auth->expects($this->any())->method('acl_get')->with($this->stringContains('_'), $this->anything())->will($this->returnValueMap(array(array('m_approve', 1, true))));
        $user = new \phpbb\user('\\phpbb\\datetime');
        $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
        $phpbb_container = new phpbb_mock_container_builder();
        $phpbb_container->set('notification_manager', new phpbb_mock_notification_manager());
        $phpbb_container->set('content.visibility', new \phpbb\content_visibility($auth, $phpbb_config, $phpbb_dispatcher, $db, $user, $phpbb_root_path, $phpEx, FORUMS_TABLE, POSTS_TABLE, TOPICS_TABLE, USERS_TABLE));
        delete_post($forum_id, $topic_id, $post_id, $data, $is_soft, $reason);
        $result = $db->sql_query('SELECT post_id, post_visibility, post_delete_reason
			FROM phpbb_posts
			WHERE topic_id = ' . $topic_id . '
			ORDER BY post_id ASC');
        $this->assertEquals($expected_posts, $db->sql_fetchrowset($result));
        $db->sql_freeresult($result);
        $result = $db->sql_query('SELECT topic_visibility, topic_first_post_id, topic_last_post_id, topic_posts_approved, topic_posts_unapproved, topic_posts_softdeleted, topic_delete_reason
			FROM phpbb_topics
			WHERE topic_id = ' . $topic_id);
        $this->assertEquals($expected_topic, $db->sql_fetchrowset($result));
        $db->sql_freeresult($result);
        $result = $db->sql_query('SELECT forum_posts_approved, forum_posts_unapproved, forum_posts_softdeleted, forum_topics_approved, forum_topics_unapproved, forum_topics_softdeleted, forum_last_post_id
			FROM phpbb_forums
			WHERE forum_id = ' . $forum_id);
        $this->assertEquals($expected_forum, $db->sql_fetchrowset($result));
        $db->sql_freeresult($result);
        $sql = 'SELECT user_posts
			FROM ' . USERS_TABLE . '
			WHERE user_id = ' . (int) $data['poster_id'];
        $result = $db->sql_query($sql);
        $this->assertEquals($expected_user, $db->sql_fetchrowset($result));
        $db->sql_freeresult($result);
    }
示例#6
0
/**
 * Sets compatibility globals in the global scope
 *
 * This function registers compatibility variables to the global
 * variable scope. This is required to make it possible to include this file
 * in a service.
 */
function register_compatibility_globals()
{
    global $phpbb_container;
    global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $phpbb_log;
    global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;
    // set up caching
    /* @var $cache \phpbb\cache\service */
    $cache = $phpbb_container->get('cache');
    // Instantiate some basic classes
    /* @var $phpbb_dispatcher \phpbb\event\dispatcher */
    $phpbb_dispatcher = $phpbb_container->get('dispatcher');
    /* @var $request \phpbb\request\request_interface */
    $request = $phpbb_container->get('request');
    // Inject request instance, so only this instance is used with request_var
    request_var('', 0, false, false, $request);
    /* @var $user \phpbb\user */
    $user = $phpbb_container->get('user');
    /* @var $auth \phpbb\auth\auth */
    $auth = $phpbb_container->get('auth');
    /* @var $db \phpbb\db\driver\driver_interface */
    $db = $phpbb_container->get('dbal.conn');
    // Grab global variables, re-cache if necessary
    /* @var $config phpbb\config\db */
    $config = $phpbb_container->get('config');
    set_config('', '', false, $config);
    set_config_count('', 0, false, $config);
    /* @var $phpbb_log \phpbb\log\log_interface */
    $phpbb_log = $phpbb_container->get('log');
    /* @var $symfony_request \phpbb\symfony_request */
    $symfony_request = $phpbb_container->get('symfony_request');
    /* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */
    $phpbb_filesystem = $phpbb_container->get('filesystem');
    /* @var $phpbb_path_helper \phpbb\path_helper */
    $phpbb_path_helper = $phpbb_container->get('path_helper');
    // load extensions
    /* @var $phpbb_extension_manager \phpbb\extension\manager */
    $phpbb_extension_manager = $phpbb_container->get('ext.manager');
    /* @var $template \phpbb\template\template */
    $template = $phpbb_container->get('template');
}
示例#7
0
/**
* Flips user_type from active to inactive and vice versa, handles group membership updates
*
* @param string $mode can be flip for flipping from active/inactive, activate or deactivate
*/
function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
{
    global $config, $db, $user, $auth;
    $deactivated = $activated = 0;
    $sql_statements = array();
    if (!is_array($user_id_ary)) {
        $user_id_ary = array($user_id_ary);
    }
    if (!sizeof($user_id_ary)) {
        return;
    }
    $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason
		FROM ' . USERS_TABLE . '
		WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        $sql_ary = array();
        if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER || $mode == 'activate' && $row['user_type'] != USER_INACTIVE || $mode == 'deactivate' && $row['user_type'] == USER_INACTIVE) {
            continue;
        }
        if ($row['user_type'] == USER_INACTIVE) {
            $activated++;
        } else {
            $deactivated++;
            // Remove the users session key...
            $user->reset_login_keys($row['user_id']);
        }
        $sql_ary += array('user_type' => $row['user_type'] == USER_NORMAL ? USER_INACTIVE : USER_NORMAL, 'user_inactive_time' => $row['user_type'] == USER_NORMAL ? time() : 0, 'user_inactive_reason' => $row['user_type'] == USER_NORMAL ? $reason : 0);
        $sql_statements[$row['user_id']] = $sql_ary;
    }
    $db->sql_freeresult($result);
    if (sizeof($sql_statements)) {
        foreach ($sql_statements as $user_id => $sql_ary) {
            $sql = 'UPDATE ' . USERS_TABLE . '
				SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
				WHERE user_id = ' . $user_id;
            $db->sql_query($sql);
        }
        $auth->acl_clear_prefetch(array_keys($sql_statements));
    }
    if ($deactivated) {
        set_config_count('num_users', $deactivated * -1, true);
    }
    if ($activated) {
        set_config_count('num_users', $activated, true);
    }
    // Update latest username
    update_last_username();
}
/**
* Submit Post
* @todo Split up and create lightweight, simple API for this.
*/
function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
{
    global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher;
    /**
     * Modify the data for post submitting
     *
     * @event core.modify_submit_post_data
     * @var	string	mode				Variable containing posting mode value
     * @var	string	subject				Variable containing post subject value
     * @var	string	username			Variable containing post author name
     * @var	int		topic_type			Variable containing topic type value
     * @var	array	poll				Array with the poll data for the post
     * @var	array	data				Array with the data for the post
     * @var	bool	update_message		Flag indicating if the post will be updated
     * @var	bool	update_search_index	Flag indicating if the search index will be updated
     * @since 3.1.0-a4
     */
    $vars = array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'update_message', 'update_search_index');
    extract($phpbb_dispatcher->trigger_event('core.modify_submit_post_data', compact($vars)));
    // We do not handle erasing posts here
    if ($mode == 'delete') {
        return false;
    }
    $current_time = time();
    if ($mode == 'post') {
        $post_mode = 'post';
        $update_message = true;
    } else {
        if ($mode != 'edit') {
            $post_mode = 'reply';
            $update_message = true;
        } else {
            if ($mode == 'edit') {
                $post_mode = $data['topic_posts_approved'] + $data['topic_posts_unapproved'] + $data['topic_posts_softdeleted'] == 1 ? 'edit_topic' : ($data['topic_first_post_id'] == $data['post_id'] ? 'edit_first_post' : ($data['topic_last_post_id'] == $data['post_id'] ? 'edit_last_post' : 'edit'));
            }
        }
    }
    // First of all make sure the subject and topic title are having the correct length.
    // To achieve this without cutting off between special chars we convert to an array and then count the elements.
    $subject = truncate_string($subject, 120);
    $data['topic_title'] = truncate_string($data['topic_title'], 120);
    // Collect some basic information about which tables and which rows to update/insert
    $sql_data = $topic_row = array();
    $poster_id = $mode == 'edit' ? $data['poster_id'] : (int) $user->data['user_id'];
    // Retrieve some additional information if not present
    if ($mode == 'edit' && (!isset($data['post_visibility']) || !isset($data['topic_visibility']) || $data['post_visibility'] === false || $data['topic_visibility'] === false)) {
        $sql = 'SELECT p.post_visibility, t.topic_type, t.topic_posts_approved, t.topic_posts_unapproved, t.topic_posts_softdeleted, t.topic_visibility
			FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
			WHERE t.topic_id = p.topic_id
				AND p.post_id = ' . $data['post_id'];
        $result = $db->sql_query($sql);
        $topic_row = $db->sql_fetchrow($result);
        $db->sql_freeresult($result);
        $data['topic_visibility'] = $topic_row['topic_visibility'];
        $data['post_visibility'] = $topic_row['post_visibility'];
    }
    // This variable indicates if the user is able to post or put into the queue
    $post_visibility = ITEM_APPROVED;
    // Check the permissions for post approval.
    // Moderators must go through post approval like ordinary users.
    if (!$auth->acl_get('f_noapprove', $data['forum_id'])) {
        // Post not approved, but in queue
        $post_visibility = ITEM_UNAPPROVED;
        switch ($post_mode) {
            case 'edit_first_post':
            case 'edit':
            case 'edit_last_post':
            case 'edit_topic':
                $post_visibility = ITEM_REAPPROVE;
                break;
        }
    }
    // MODs/Extensions are able to force any visibility on posts
    if (isset($data['force_approved_state'])) {
        $post_visibility = in_array((int) $data['force_approved_state'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE)) ? (int) $data['force_approved_state'] : $post_visibility;
    }
    if (isset($data['force_visibility'])) {
        $post_visibility = in_array((int) $data['force_visibility'], array(ITEM_APPROVED, ITEM_UNAPPROVED, ITEM_DELETED, ITEM_REAPPROVE)) ? (int) $data['force_visibility'] : $post_visibility;
    }
    // Start the transaction here
    $db->sql_transaction('begin');
    // Collect Information
    switch ($post_mode) {
        case 'post':
        case 'reply':
            $sql_data[POSTS_TABLE]['sql'] = array('forum_id' => $data['forum_id'], 'poster_id' => (int) $user->data['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_visibility' => $post_visibility, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => !$user->data['is_registered'] ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => $auth->acl_get('f_postcount', $data['forum_id']) ? 1 : 0, 'post_edit_locked' => $data['post_edit_locked']);
            break;
        case 'edit_first_post':
        case 'edit':
        case 'edit_last_post':
        case 'edit_topic':
            // If edit reason is given always display edit info
            // If editing last post then display no edit info
            // If m_edit permission then display no edit info
            // If normal edit display edit info
            // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
            if ($data['post_edit_reason'] || !$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')) {
                $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
                $sql_data[POSTS_TABLE]['sql'] = array('post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user']);
                $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
            } else {
                if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) {
                    $sql_data[POSTS_TABLE]['sql'] = array('post_edit_reason' => '');
                }
            }
            // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
            // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
            if ($user->data['user_id'] != $poster_id) {
                $log_subject = $subject ? $subject : $data['topic_title'];
                add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, !empty($username) ? $username : $user->lang['GUEST'], $data['post_edit_reason']);
            }
            if (!isset($sql_data[POSTS_TABLE]['sql'])) {
                $sql_data[POSTS_TABLE]['sql'] = array();
            }
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('forum_id' => $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => $username && $data['poster_id'] == ANONYMOUS ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']));
            if ($update_message) {
                $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
            }
            break;
    }
    $topic_row = array();
    // And the topic ladies and gentlemen
    switch ($post_mode) {
        case 'post':
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_posts_approved' => $post_visibility == ITEM_APPROVED ? 1 : 0, 'topic_posts_softdeleted' => $post_visibility == ITEM_DELETED ? 1 : 0, 'topic_posts_unapproved' => $post_visibility == ITEM_UNAPPROVED ? 1 : 0, 'topic_visibility' => $post_visibility, 'topic_delete_user' => $post_visibility != ITEM_APPROVED ? (int) $user->data['user_id'] : 0, 'topic_title' => $subject, 'topic_first_poster_name' => !$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : 0);
            if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
                $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array('poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']));
            }
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED ? ', user_posts = user_posts + 1' : '');
            if ($post_visibility == ITEM_APPROVED) {
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_approved = forum_topics_approved + 1';
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
            } else {
                if ($post_visibility == ITEM_UNAPPROVED) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_unapproved = forum_topics_unapproved + 1';
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
                } else {
                    if ($post_visibility == ITEM_DELETED) {
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_softdeleted = forum_topics_softdeleted + 1';
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
                    }
                }
            }
            break;
        case 'reply':
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
				topic_bumped = 0,
				topic_bumper = 0' . ($post_visibility == ITEM_APPROVED ? ', topic_posts_approved = topic_posts_approved + 1' : '') . ($post_visibility == ITEM_UNAPPROVED ? ', topic_posts_unapproved = topic_posts_unapproved + 1' : '') . ($post_visibility == ITEM_DELETED ? ', topic_posts_softdeleted = topic_posts_softdeleted + 1' : '') . (!empty($data['attachment_data']) || isset($data['topic_attachment']) && $data['topic_attachment'] ? ', topic_attachment = 1' : '');
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_visibility == ITEM_APPROVED ? ', user_posts = user_posts + 1' : '');
            if ($post_visibility == ITEM_APPROVED) {
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_approved = forum_posts_approved + 1';
            } else {
                if ($post_visibility == ITEM_UNAPPROVED) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_unapproved = forum_posts_unapproved + 1';
                } else {
                    if ($post_visibility == ITEM_DELETED) {
                        $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts_softdeleted = forum_posts_softdeleted + 1';
                    }
                }
            }
            break;
        case 'edit_topic':
        case 'edit_first_post':
            if (isset($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] || empty($poll['poll_options']) ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
            }
            $sql_data[TOPICS_TABLE]['sql'] = array('forum_id' => $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'poll_title' => isset($poll['poll_options']) ? $poll['poll_title'] : '', 'poll_start' => isset($poll['poll_options']) ? $poll_start : 0, 'poll_max_options' => isset($poll['poll_options']) ? $poll['poll_max_options'] : 1, 'poll_length' => isset($poll['poll_options']) ? $poll_length : 0, 'poll_vote_change' => isset($poll['poll_vote_change']) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0));
            break;
    }
    /**
     * Modify sql query data for post submitting
     *
     * @event core.submit_post_modify_sql_data
     * @var	array	data				Array with the data for the post
     * @var	array	poll				Array with the poll data for the post
     * @var	string	post_mode			Variable containing posting mode value
     * @var	bool	sql_data			Array with the data for the posting SQL query
     * @var	string	subject				Variable containing post subject value
     * @var	int		topic_type			Variable containing topic type value
     * @var	string	username			Variable containing post author name
     * @since 3.1.3-RC1
     */
    $vars = array('data', 'poll', 'post_mode', 'sql_data', 'subject', 'topic_type', 'username');
    extract($phpbb_dispatcher->trigger_event('core.submit_post_modify_sql_data', compact($vars)));
    // Submit new topic
    if ($post_mode == 'post') {
        $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['topic_id'] = $db->sql_nextid();
        $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        unset($sql_data[TOPICS_TABLE]['sql']);
    }
    // Submit new post
    if ($post_mode == 'post' || $post_mode == 'reply') {
        if ($post_mode == 'reply') {
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        }
        $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['post_id'] = $db->sql_nextid();
        if ($post_mode == 'post' || $post_visibility == ITEM_APPROVED) {
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => $sql_data[POSTS_TABLE]['sql']['poster_id'], 'topic_last_poster_name' => $user->data['user_id'] == ANONYMOUS ? $sql_data[POSTS_TABLE]['sql']['post_username'] : $user->data['username'], 'topic_last_poster_colour' => $user->data['user_colour'], 'topic_last_post_subject' => (string) $subject);
        }
        if ($post_mode == 'post') {
            $sql_data[TOPICS_TABLE]['sql']['topic_first_post_id'] = $data['post_id'];
        }
        // Update total post count and forum information
        if ($post_visibility == ITEM_APPROVED) {
            if ($post_mode == 'post') {
                set_config_count('num_topics', 1, true);
            }
            set_config_count('num_posts', 1, true);
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(!$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : '')) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
        }
        unset($sql_data[POSTS_TABLE]['sql']);
    }
    // Update the topics table
    if (isset($sql_data[TOPICS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . TOPICS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
			WHERE topic_id = ' . $data['topic_id'];
        $db->sql_query($sql);
        unset($sql_data[TOPICS_TABLE]['sql']);
    }
    // Update the posts table
    if (isset($sql_data[POSTS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
			WHERE post_id = ' . $data['post_id'];
        $db->sql_query($sql);
        unset($sql_data[POSTS_TABLE]['sql']);
    }
    // Update Poll Tables
    if (isset($poll['poll_options'])) {
        $cur_poll_options = array();
        if ($mode == 'edit') {
            $sql = 'SELECT *
				FROM ' . POLL_OPTIONS_TABLE . '
				WHERE topic_id = ' . $data['topic_id'] . '
				ORDER BY poll_option_id';
            $result = $db->sql_query($sql);
            $cur_poll_options = array();
            while ($row = $db->sql_fetchrow($result)) {
                $cur_poll_options[] = $row;
            }
            $db->sql_freeresult($result);
        }
        $sql_insert_ary = array();
        for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) {
            if (strlen(trim($poll['poll_options'][$i]))) {
                if (empty($cur_poll_options[$i])) {
                    // If we add options we need to put them to the end to be able to preserve votes...
                    $sql_insert_ary[] = array('poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i]);
                } else {
                    if ($poll['poll_options'][$i] != $cur_poll_options[$i]) {
                        $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "\n\t\t\t\t\t\tSET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'\n\t\t\t\t\t\tWHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
							AND topic_id = ' . $data['topic_id'];
                        $db->sql_query($sql);
                    }
                }
            }
        }
        $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
        if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) {
            $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
				WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
					AND topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        }
        // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
        if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) {
            $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
            $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
        }
    }
    // Submit Attachments
    if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) {
        $space_taken = $files_added = 0;
        $orphan_rows = array();
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            $orphan_rows[(int) $attach_row['attach_id']] = array();
        }
        if (sizeof($orphan_rows)) {
            $sql = 'SELECT attach_id, filesize, physical_filename
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
					AND is_orphan = 1
					AND poster_id = ' . $user->data['user_id'];
            $result = $db->sql_query($sql);
            $orphan_rows = array();
            while ($row = $db->sql_fetchrow($result)) {
                $orphan_rows[$row['attach_id']] = $row;
            }
            $db->sql_freeresult($result);
        }
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) {
                continue;
            }
            if (!$attach_row['is_orphan']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\tSET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'\n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'] . '
						AND is_orphan = 0';
                $db->sql_query($sql);
            } else {
                // insert attachment into db
                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) {
                    continue;
                }
                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
                $files_added++;
                $attach_sql = array('post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment']);
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
					WHERE attach_id = ' . $attach_row['attach_id'] . '
						AND is_orphan = 1
						AND poster_id = ' . $user->data['user_id'];
                $db->sql_query($sql);
            }
        }
        if ($space_taken && $files_added) {
            set_config_count('upload_dir_size', $space_taken, true);
            set_config_count('num_files', $files_added, true);
        }
    }
    $first_post_has_topic_info = $post_mode == 'edit_first_post' && ($post_visibility == ITEM_DELETED && $data['topic_posts_softdeleted'] == 1 || $post_visibility == ITEM_UNAPPROVED && $data['topic_posts_unapproved'] == 1 || $post_visibility == ITEM_REAPPROVE && $data['topic_posts_unapproved'] == 1 || $post_visibility == ITEM_APPROVED && $data['topic_posts_approved'] == 1);
    // Fix the post's and topic's visibility and first/last post information, when the post is edited
    if ($post_mode != 'post' && $post_mode != 'reply' && $data['post_visibility'] != $post_visibility) {
        // If the post was not approved, it could also be the starter,
        // so we sync the starter after approving/restoring, to ensure that the stats are correct
        // Same applies for the last post
        $is_starter = $post_mode == 'edit_first_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED;
        $is_latest = $post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $data['post_visibility'] != ITEM_APPROVED;
        $phpbb_content_visibility = $phpbb_container->get('content.visibility');
        $phpbb_content_visibility->set_post_visibility($post_visibility, $data['post_id'], $data['topic_id'], $data['forum_id'], $user->data['user_id'], time(), '', $is_starter, $is_latest);
    } else {
        if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $first_post_has_topic_info) {
            if ($post_visibility == ITEM_APPROVED || $data['topic_visibility'] == $post_visibility) {
                // only the subject can be changed from edit
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
                // Maybe not only the subject, but also changing anonymous usernames. ;)
                if ($data['poster_id'] == ANONYMOUS) {
                    $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
                }
                if ($post_visibility == ITEM_APPROVED) {
                    // this does not _necessarily_ mean that we must update the info again,
                    // it just means that we might have to
                    $sql = 'SELECT forum_last_post_id, forum_last_post_subject
					FROM ' . FORUMS_TABLE . '
					WHERE forum_id = ' . (int) $data['forum_id'];
                    $result = $db->sql_query($sql);
                    $row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                    // this post is the latest post in the forum, better update
                    if ($row['forum_last_post_id'] == $data['post_id'] && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) {
                        // the post's subject changed
                        if ($row['forum_last_post_subject'] !== $subject) {
                            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
                        }
                        // Update the user name if poster is anonymous... just in case a moderator changed it
                        if ($data['poster_id'] == ANONYMOUS) {
                            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
                        }
                    }
                }
            }
        }
    }
    // Update forum stats
    $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id);
    foreach ($sql_data as $table => $update_ary) {
        if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) {
            $sql = "UPDATE {$table} SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
            $db->sql_query($sql);
        }
    }
    // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
    if ($topic_type == POST_GLOBAL) {
        $sql = 'DELETE FROM ' . TOPICS_TABLE . '
			WHERE topic_moved_id = ' . $data['topic_id'];
        $db->sql_query($sql);
    }
    // Committing the transaction before updating search index
    $db->sql_transaction('commit');
    // Delete draft if post was loaded...
    $draft_id = request_var('draft_loaded', 0);
    if ($draft_id) {
        $sql = 'DELETE FROM ' . DRAFTS_TABLE . "\n\t\t\tWHERE draft_id = {$draft_id}\n\t\t\t\tAND user_id = {$user->data['user_id']}";
        $db->sql_query($sql);
    }
    // Index message contents
    if ($update_search_index && $data['enable_indexing']) {
        // Select the search method and do some additional checks to ensure it can actually be utilised
        $search_type = $config['search_type'];
        if (!class_exists($search_type)) {
            trigger_error('NO_SUCH_SEARCH_MODULE');
        }
        $error = false;
        $search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
        if ($error) {
            trigger_error($error);
        }
        $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $data['forum_id']);
    }
    // Topic Notification, do not change if moderator is changing other users posts...
    if ($user->data['user_id'] == $poster_id) {
        if (!$data['notify_set'] && $data['notify']) {
            $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
				VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
            $db->sql_query($sql);
        } else {
            if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) {
                $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
				WHERE user_id = ' . $user->data['user_id'] . '
					AND topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
        }
    }
    if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') {
        // Mark this topic as posted to
        markread('post', $data['forum_id'], $data['topic_id']);
    }
    // Mark this topic as read
    // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
    markread('topic', $data['forum_id'], $data['topic_id'], time());
    //
    if ($config['load_db_lastread'] && $user->data['is_registered']) {
        $sql = 'SELECT mark_time
			FROM ' . FORUMS_TRACK_TABLE . '
			WHERE user_id = ' . $user->data['user_id'] . '
				AND forum_id = ' . $data['forum_id'];
        $result = $db->sql_query($sql);
        $f_mark_time = (int) $db->sql_fetchfield('mark_time');
        $db->sql_freeresult($result);
    } else {
        if ($config['load_anon_lastread'] || $user->data['is_registered']) {
            $f_mark_time = false;
        }
    }
    if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $user->data['is_registered']) {
        // Update forum info
        $sql = 'SELECT forum_last_post_time
			FROM ' . FORUMS_TABLE . '
			WHERE forum_id = ' . $data['forum_id'];
        $result = $db->sql_query($sql);
        $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
        $db->sql_freeresult($result);
        update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false);
    }
    // If a username was supplied or the poster is a guest, we will use the supplied username.
    // Doing it this way we can use "...post by guest-username..." in notifications when
    // "guest-username" is supplied or ommit the username if it is not.
    $username = $username !== '' || !$user->data['is_registered'] ? $username : $user->data['username'];
    // Send Notifications
    $notification_data = array_merge($data, array('topic_title' => isset($data['topic_title']) ? $data['topic_title'] : $subject, 'post_username' => $username, 'poster_id' => $poster_id, 'post_text' => $data['message'], 'post_time' => $current_time, 'post_subject' => $subject));
    $phpbb_notifications = $phpbb_container->get('notification_manager');
    if ($post_visibility == ITEM_APPROVED) {
        switch ($mode) {
            case 'post':
                $phpbb_notifications->add_notifications(array('notification.type.quote', 'notification.type.topic'), $notification_data);
                break;
            case 'reply':
            case 'quote':
                $phpbb_notifications->add_notifications(array('notification.type.quote', 'notification.type.bookmark', 'notification.type.post'), $notification_data);
                break;
            case 'edit_topic':
            case 'edit_first_post':
            case 'edit':
            case 'edit_last_post':
                $phpbb_notifications->update_notifications(array('notification.type.quote', 'notification.type.bookmark', 'notification.type.topic', 'notification.type.post'), $notification_data);
                break;
        }
    } else {
        if ($post_visibility == ITEM_UNAPPROVED) {
            switch ($mode) {
                case 'post':
                    $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
                    break;
                case 'reply':
                case 'quote':
                    $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
                    break;
                case 'edit_topic':
                case 'edit_first_post':
                case 'edit':
                case 'edit_last_post':
                    // Nothing to do here
                    break;
            }
        } else {
            if ($post_visibility == ITEM_REAPPROVE) {
                switch ($mode) {
                    case 'edit_topic':
                    case 'edit_first_post':
                        $phpbb_notifications->add_notifications('notification.type.topic_in_queue', $notification_data);
                        // Delete the approve_post notification so we can notify the user again,
                        // when his post got reapproved
                        $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
                        break;
                    case 'edit':
                    case 'edit_last_post':
                        $phpbb_notifications->add_notifications('notification.type.post_in_queue', $notification_data);
                        // Delete the approve_post notification so we can notify the user again,
                        // when his post got reapproved
                        $phpbb_notifications->delete_notifications('notification.type.approve_post', $notification_data['post_id']);
                        break;
                    case 'post':
                    case 'reply':
                    case 'quote':
                        // Nothing to do here
                        break;
                }
            } else {
                if ($post_visibility == ITEM_DELETED) {
                    switch ($mode) {
                        case 'post':
                        case 'reply':
                        case 'quote':
                        case 'edit_topic':
                        case 'edit_first_post':
                        case 'edit':
                        case 'edit_last_post':
                            // Nothing to do here
                            break;
                    }
                }
            }
        }
    }
    $params = $add_anchor = '';
    if ($post_visibility == ITEM_APPROVED) {
        $params .= '&amp;t=' . $data['topic_id'];
        if ($mode != 'post') {
            $params .= '&amp;p=' . $data['post_id'];
            $add_anchor = '#p' . $data['post_id'];
        }
    } else {
        if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') {
            $params .= '&amp;t=' . $data['topic_id'];
        }
    }
    $url = !$params ? "{$phpbb_root_path}viewforum.{$phpEx}" : "{$phpbb_root_path}viewtopic.{$phpEx}";
    $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
    /**
     * This event is used for performing actions directly after a post or topic
     * has been submitted. When a new topic is posted, the topic ID is
     * available in the $data array.
     *
     * The only action that can be done by altering data made available to this
     * event is to modify the return URL ($url).
     *
     * @event core.submit_post_end
     * @var	string	mode				Variable containing posting mode value
     * @var	string	subject				Variable containing post subject value
     * @var	string	username			Variable containing post author name
     * @var	int		topic_type			Variable containing topic type value
     * @var	array	poll				Array with the poll data for the post
     * @var	array	data				Array with the data for the post
     * @var	int		post_visibility		Variable containing up to date post visibility
     * @var	bool	update_message		Flag indicating if the post will be updated
     * @var	bool	update_search_index	Flag indicating if the search index will be updated
     * @var	string	url					The "Return to topic" URL
     *
     * @since 3.1.0-a3
     * @change 3.1.0-RC3 Added vars mode, subject, username, topic_type,
     *		poll, update_message, update_search_index
     */
    $vars = array('mode', 'subject', 'username', 'topic_type', 'poll', 'data', 'post_visibility', 'update_message', 'update_search_index', 'url');
    extract($phpbb_dispatcher->trigger_event('core.submit_post_end', compact($vars)));
    return $url;
}
示例#9
0
<?php

/**
*/
if (!defined('IN_src')) {
    exit;
}
// set up caching
$cache = $src_container->get('cache');
// Instantiate some basic classes
$src_dispatcher = $src_container->get('dispatcher');
$request = $src_container->get('request');
$user = $src_container->get('user');
$auth = $src_container->get('auth');
$db = $src_container->get('dbal.conn');
// make sure request_var uses this request instance
request_var('', 0, false, false, $request);
// "dependency injection" for a function
// Grab global variables, re-cache if necessary
$config = $src_container->get('config');
set_config(null, null, null, $config);
set_config_count(null, null, null, $config);
$src_log = $src_container->get('log');
$symfony_request = $src_container->get('symfony_request');
$src_filesystem = $src_container->get('filesystem');
$src_path_helper = $src_container->get('path_helper');
// load extensions
$src_extension_manager = $src_container->get('ext.manager');
$template = $src_container->get('template');
示例#10
0
/**
* Submit PM
*/
function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
{
    global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path;
    // We do not handle erasing pms here
    if ($mode == 'delete') {
        return false;
    }
    $current_time = time();
    // Collect some basic information about which tables and which rows to update/insert
    $sql_data = array();
    $root_level = 0;
    // Recipient Information
    $recipients = $to = $bcc = array();
    if ($mode != 'edit') {
        // Build Recipient List
        // u|g => array($user_id => 'to'|'bcc')
        $_types = array('u', 'g');
        foreach ($_types as $ug_type) {
            if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type])) {
                foreach ($data['address_list'][$ug_type] as $id => $field) {
                    $id = (int) $id;
                    // Do not rely on the address list being "valid"
                    if (!$id || $ug_type == 'u' && $id == ANONYMOUS) {
                        continue;
                    }
                    $field = $field == 'to' ? 'to' : 'bcc';
                    if ($ug_type == 'u') {
                        $recipients[$id] = $field;
                    }
                    ${$field}[] = $ug_type . '_' . $id;
                }
            }
        }
        if (isset($data['address_list']['g']) && sizeof($data['address_list']['g'])) {
            // We need to check the PM status of group members (do they want to receive PM's?)
            // Only check if not a moderator or admin, since they are allowed to override this user setting
            $sql_allow_pm = !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_') ? ' AND u.user_allow_pm = 1' : '';
            $sql = 'SELECT u.user_type, ug.group_id, ug.user_id
				FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
				WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
					AND ug.user_pending = 0
					AND u.user_id = ug.user_id
					AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . $sql_allow_pm;
            $result = $db->sql_query($sql);
            while ($row = $db->sql_fetchrow($result)) {
                // Additionally, do not include the sender if he is in the group he wants to send to. ;)
                if ($row['user_id'] === $user->data['user_id']) {
                    continue;
                }
                $field = $data['address_list']['g'][$row['group_id']] == 'to' ? 'to' : 'bcc';
                $recipients[$row['user_id']] = $field;
            }
            $db->sql_freeresult($result);
        }
        if (!sizeof($recipients)) {
            trigger_error('NO_RECIPIENT');
        }
    }
    $db->sql_transaction('begin');
    $sql = '';
    switch ($mode) {
        case 'reply':
        case 'quote':
            $root_level = $data['reply_from_root_level'] ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
            // Set message_replied switch for this user
            $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
				SET pm_replied = 1
				WHERE user_id = ' . $data['from_user_id'] . '
					AND msg_id = ' . $data['reply_from_msg_id'];
            // no break
        // no break
        case 'forward':
        case 'post':
        case 'quotepost':
            $sql_data = array('root_level' => $root_level, 'author_id' => $data['from_user_id'], 'icon_id' => $data['icon_id'], 'author_ip' => $data['from_user_ip'], 'message_time' => $current_time, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'message_subject' => $subject, 'message_text' => $data['message'], 'message_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'to_address' => implode(':', $to), 'bcc_address' => implode(':', $bcc), 'message_reported' => 0);
            break;
        case 'edit':
            $sql_data = array('icon_id' => $data['icon_id'], 'message_edit_time' => $current_time, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'message_subject' => $subject, 'message_text' => $data['message'], 'message_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid']);
            break;
    }
    if (sizeof($sql_data)) {
        $query = '';
        if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') {
            $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
            $data['msg_id'] = $db->sql_nextid();
        } else {
            if ($mode == 'edit') {
                $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
				SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
				WHERE msg_id = ' . $data['msg_id'];
                $db->sql_query($sql);
            }
        }
    }
    if ($mode != 'edit') {
        if ($sql) {
            $db->sql_query($sql);
        }
        unset($sql);
        $sql_ary = array();
        foreach ($recipients as $user_id => $type) {
            $sql_ary[] = array('msg_id' => (int) $data['msg_id'], 'user_id' => (int) $user_id, 'author_id' => (int) $data['from_user_id'], 'folder_id' => PRIVMSGS_NO_BOX, 'pm_new' => 1, 'pm_unread' => 1, 'pm_forwarded' => $mode == 'forward' ? 1 : 0);
        }
        $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
        $sql = 'UPDATE ' . USERS_TABLE . '
			SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
			WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
        $db->sql_query($sql);
        // Put PM into outbox
        if ($put_in_outbox) {
            $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array('msg_id' => (int) $data['msg_id'], 'user_id' => (int) $data['from_user_id'], 'author_id' => (int) $data['from_user_id'], 'folder_id' => PRIVMSGS_OUTBOX, 'pm_new' => 0, 'pm_unread' => 0, 'pm_forwarded' => $mode == 'forward' ? 1 : 0)));
        }
    }
    // Set user last post time
    if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post') {
        $sql = 'UPDATE ' . USERS_TABLE . "\n\t\t\tSET user_lastpost_time = {$current_time}\n\t\t\tWHERE user_id = " . $data['from_user_id'];
        $db->sql_query($sql);
    }
    // Submit Attachments
    if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) {
        $space_taken = $files_added = 0;
        $orphan_rows = array();
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            $orphan_rows[(int) $attach_row['attach_id']] = array();
        }
        if (sizeof($orphan_rows)) {
            $sql = 'SELECT attach_id, filesize, physical_filename
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
					AND in_message = 1
					AND is_orphan = 1
					AND poster_id = ' . $user->data['user_id'];
            $result = $db->sql_query($sql);
            $orphan_rows = array();
            while ($row = $db->sql_fetchrow($result)) {
                $orphan_rows[$row['attach_id']] = $row;
            }
            $db->sql_freeresult($result);
        }
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) {
                continue;
            }
            if (!$attach_row['is_orphan']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\tSET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'\n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'] . '
						AND is_orphan = 0';
                $db->sql_query($sql);
            } else {
                // insert attachment into db
                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) {
                    continue;
                }
                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
                $files_added++;
                $attach_sql = array('post_msg_id' => $data['msg_id'], 'topic_id' => 0, 'is_orphan' => 0, 'poster_id' => $data['from_user_id'], 'attach_comment' => $attach_row['attach_comment']);
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
					WHERE attach_id = ' . $attach_row['attach_id'] . '
						AND is_orphan = 1
						AND poster_id = ' . $user->data['user_id'];
                $db->sql_query($sql);
            }
        }
        if ($space_taken && $files_added) {
            set_config_count('upload_dir_size', $space_taken, true);
            set_config_count('num_files', $files_added, true);
        }
    }
    // Delete draft if post was loaded...
    $draft_id = request_var('draft_loaded', 0);
    if ($draft_id) {
        $sql = 'DELETE FROM ' . DRAFTS_TABLE . "\n\t\t\tWHERE draft_id = {$draft_id}\n\t\t\t\tAND user_id = " . $data['from_user_id'];
        $db->sql_query($sql);
    }
    $db->sql_transaction('commit');
    // Send Notifications
    if ($mode != 'edit') {
        pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
    }
    return $data['msg_id'];
}
/**
* Submit Post
* @todo Split up and create lightweight, simple API for this.
*/
function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
{
    global $db, $auth, $user, $config, $phpEx, $template, $phpbb_root_path;
    // We do not handle erasing posts here
    if ($mode == 'delete') {
        return false;
    }
    $current_time = time();
    if ($mode == 'post') {
        $post_mode = 'post';
        $update_message = true;
    } else {
        if ($mode != 'edit') {
            $post_mode = 'reply';
            $update_message = true;
        } else {
            if ($mode == 'edit') {
                $post_mode = $data['topic_replies_real'] == 0 ? 'edit_topic' : ($data['topic_first_post_id'] == $data['post_id'] ? 'edit_first_post' : ($data['topic_last_post_id'] == $data['post_id'] ? 'edit_last_post' : 'edit'));
            }
        }
    }
    // First of all make sure the subject and topic title are having the correct length.
    // To achieve this without cutting off between special chars we convert to an array and then count the elements.
    $subject = truncate_string($subject);
    $data['topic_title'] = truncate_string($data['topic_title']);
    // Collect some basic information about which tables and which rows to update/insert
    $sql_data = $topic_row = array();
    $poster_id = $mode == 'edit' ? $data['poster_id'] : (int) $user->data['user_id'];
    // Retrieve some additional information if not present
    if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false)) {
        $sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved
			FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p
			WHERE t.topic_id = p.topic_id
				AND p.post_id = ' . $data['post_id'];
        $result = $db->sql_query($sql);
        $topic_row = $db->sql_fetchrow($result);
        $db->sql_freeresult($result);
        $data['topic_approved'] = $topic_row['topic_approved'];
        $data['post_approved'] = $topic_row['post_approved'];
    }
    // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval
    // The variable name should be $post_approved, because it indicates if the post is approved or not
    $post_approval = 1;
    // Check the permissions for post approval. Moderators are not affected.
    if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) {
        // Post not approved, but in queue
        $post_approval = 0;
    }
    // Mods are able to force approved/unapproved posts. True means the post is approved, false the post is unapproved
    if (isset($data['force_approved_state'])) {
        $post_approval = $data['force_approved_state'] ? 1 : 0;
    }
    // Start the transaction here
    $db->sql_transaction('begin');
    // Collect Information
    switch ($post_mode) {
        case 'post':
        case 'reply':
            $sql_data[POSTS_TABLE]['sql'] = array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'poster_id' => (int) $user->data['user_id'], 'icon_id' => $data['icon_id'], 'poster_ip' => $user->ip, 'post_time' => $current_time, 'post_approved' => $post_approval, 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => !$user->data['is_registered'] ? $username : '', 'post_subject' => $subject, 'post_text' => $data['message'], 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_postcount' => $auth->acl_get('f_postcount', $data['forum_id']) ? 1 : 0, 'post_edit_locked' => $data['post_edit_locked']);
            break;
        case 'edit_first_post':
        case 'edit':
        case 'edit_last_post':
        case 'edit_topic':
            // If edit reason is given always display edit info
            // If editing last post then display no edit info
            // If m_edit permission then display no edit info
            // If normal edit display edit info
            // Display edit info if edit reason given or user is editing his post, which is not the last within the topic.
            if ($data['post_edit_reason'] || !$auth->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post')) {
                $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false);
                $sql_data[POSTS_TABLE]['sql'] = array('post_edit_time' => $current_time, 'post_edit_reason' => $data['post_edit_reason'], 'post_edit_user' => (int) $data['post_edit_user']);
                $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1';
            } else {
                if (!$data['post_edit_reason'] && $mode == 'edit' && $auth->acl_get('m_edit', $data['forum_id'])) {
                    $sql_data[POSTS_TABLE]['sql'] = array('post_edit_reason' => '');
                }
            }
            // If the person editing this post is different to the one having posted then we will add a log entry stating the edit
            // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods
            if ($user->data['user_id'] != $poster_id) {
                $log_subject = $subject ? $subject : $data['topic_title'];
                add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, !empty($username) ? $username : $user->lang['GUEST']);
            }
            if (!isset($sql_data[POSTS_TABLE]['sql'])) {
                $sql_data[POSTS_TABLE]['sql'] = array();
            }
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'poster_id' => $data['poster_id'], 'icon_id' => $data['icon_id'], 'post_approved' => !$post_approval ? 0 : $data['post_approved'], 'enable_bbcode' => $data['enable_bbcode'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'post_username' => $username && $data['poster_id'] == ANONYMOUS ? $username : '', 'post_subject' => $subject, 'post_checksum' => $data['message_md5'], 'post_attachment' => !empty($data['attachment_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'post_edit_locked' => $data['post_edit_locked']));
            if ($update_message) {
                $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message'];
            }
            break;
    }
    $post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved'];
    $topic_row = array();
    // And the topic ladies and gentlemen
    switch ($post_mode) {
        case 'post':
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_poster' => (int) $user->data['user_id'], 'topic_time' => $current_time, 'topic_last_view_time' => $current_time, 'forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => $post_approval, 'topic_title' => $subject, 'topic_first_poster_name' => !$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : ''), 'topic_first_poster_colour' => $user->data['user_colour'], 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : 0);
            if (isset($poll['poll_options']) && !empty($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
                $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array('poll_title' => $poll['poll_title'], 'poll_start' => $poll_start, 'poll_max_options' => $poll['poll_max_options'], 'poll_length' => $poll_length, 'poll_vote_change' => $poll['poll_vote_change']));
            }
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval ? ', user_posts = user_posts + 1' : '');
            if ($topic_type != POST_GLOBAL) {
                if ($post_approval) {
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
                }
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . ($post_approval ? ', forum_topics = forum_topics + 1' : '');
            }
            break;
        case 'reply':
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ',
				topic_replies_real = topic_replies_real + 1,
				topic_bumped = 0,
				topic_bumper = 0' . ($post_approval ? ', topic_replies = topic_replies + 1' : '') . (!empty($data['attachment_data']) || isset($data['topic_attachment']) && $data['topic_attachment'] ? ', topic_attachment = 1' : '');
            $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = {$current_time}" . ($auth->acl_get('f_postcount', $data['forum_id']) && $post_approval ? ', user_posts = user_posts + 1' : '');
            if ($post_approval && $topic_type != POST_GLOBAL) {
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1';
            }
            break;
        case 'edit_topic':
        case 'edit_first_post':
            if (isset($poll['poll_options'])) {
                $poll_start = $poll['poll_start'] || empty($poll['poll_options']) ? $poll['poll_start'] : $current_time;
                $poll_length = $poll['poll_length'] * 86400;
                if ($poll_length < 0) {
                    $poll_start = $poll_start + $poll_length;
                    if ($poll_start < 0) {
                        $poll_start = 0;
                    }
                    $poll_length = 1;
                }
            }
            $sql_data[TOPICS_TABLE]['sql'] = array('forum_id' => $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], 'icon_id' => $data['icon_id'], 'topic_approved' => !$post_approval ? 0 : $data['topic_approved'], 'topic_title' => $subject, 'topic_first_poster_name' => $username, 'topic_type' => $topic_type, 'topic_time_limit' => $topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE ? $data['topic_time_limit'] * 86400 : 0, 'poll_title' => isset($poll['poll_options']) ? $poll['poll_title'] : '', 'poll_start' => isset($poll['poll_options']) ? $poll_start : 0, 'poll_max_options' => isset($poll['poll_options']) ? $poll['poll_max_options'] : 1, 'poll_length' => isset($poll['poll_options']) ? $poll_length : 0, 'poll_vote_change' => isset($poll['poll_vote_change']) ? $poll['poll_vote_change'] : 0, 'topic_last_view_time' => $current_time, 'topic_attachment' => !empty($data['attachment_data']) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0));
            // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved
            if (!$post_approval && $data['topic_approved']) {
                // Do we need to grab some topic informations?
                if (!sizeof($topic_row)) {
                    $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved
						FROM ' . TOPICS_TABLE . '
						WHERE topic_id = ' . $data['topic_id'];
                    $result = $db->sql_query($sql);
                    $topic_row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                }
                // If this is the only post remaining we do not need to decrement topic_replies.
                // Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again.
                // If this is an edited topic or the first post the topic gets completely disapproved later on...
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1';
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1);
                set_config_count('num_topics', -1, true);
                set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * -1, true);
                // Only decrement this post, since this is the one non-approved now
                if ($auth->acl_get('f_postcount', $data['forum_id'])) {
                    $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
                }
            }
            break;
        case 'edit':
        case 'edit_last_post':
            // Correctly set back the topic replies and forum posts... but only if the post was approved before.
            if (!$post_approval && $data['post_approved']) {
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time;
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1';
                set_config_count('num_posts', -1, true);
                if ($auth->acl_get('f_postcount', $data['forum_id'])) {
                    $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1';
                }
            }
            break;
    }
    // Submit new topic
    if ($post_mode == 'post') {
        $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['topic_id'] = $db->sql_nextid();
        $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        unset($sql_data[TOPICS_TABLE]['sql']);
    }
    // Submit new post
    if ($post_mode == 'post' || $post_mode == 'reply') {
        if ($post_mode == 'reply') {
            $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array('topic_id' => $data['topic_id']));
        }
        $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']);
        $db->sql_query($sql);
        $data['post_id'] = $db->sql_nextid();
        if ($post_mode == 'post') {
            $sql_data[TOPICS_TABLE]['sql'] = array('topic_first_post_id' => $data['post_id'], 'topic_last_post_id' => $data['post_id'], 'topic_last_post_time' => $current_time, 'topic_last_poster_id' => (int) $user->data['user_id'], 'topic_last_poster_name' => !$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : ''), 'topic_last_poster_colour' => $user->data['user_colour'], 'topic_last_post_subject' => (string) $subject);
        }
        unset($sql_data[POSTS_TABLE]['sql']);
    }
    $make_global = false;
    // Are we globalising or unglobalising?
    if ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic') {
        if (!sizeof($topic_row)) {
            $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved, topic_last_post_id
				FROM ' . TOPICS_TABLE . '
				WHERE topic_id = ' . $data['topic_id'];
            $result = $db->sql_query($sql);
            $topic_row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
        }
        // globalise/unglobalise?
        if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL || $topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) {
            if (!empty($sql_data[FORUMS_TABLE]['stat']) && implode('', $sql_data[FORUMS_TABLE]['stat'])) {
                $db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET ' . implode(', ', $sql_data[FORUMS_TABLE]['stat']) . ' WHERE forum_id = ' . $data['forum_id']);
            }
            $make_global = true;
            $sql_data[FORUMS_TABLE]['stat'] = array();
        }
        // globalise
        if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) {
            // Decrement topic/post count
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies_real'] + 1);
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real - 1' . ($topic_row['topic_approved'] ? ', forum_topics = forum_topics - 1' : '');
            // Update forum_ids for all posts
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET forum_id = 0
				WHERE topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        } else {
            if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) {
                // Increment topic/post count
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + ' . ($topic_row['topic_replies_real'] + 1);
                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . ($topic_row['topic_approved'] ? ', forum_topics = forum_topics + 1' : '');
                // Update forum_ids for all posts
                $sql = 'UPDATE ' . POSTS_TABLE . '
				SET forum_id = ' . $data['forum_id'] . '
				WHERE topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
        }
    }
    // Update the topics table
    if (isset($sql_data[TOPICS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . TOPICS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . '
			WHERE topic_id = ' . $data['topic_id'];
        $db->sql_query($sql);
    }
    // Update the posts table
    if (isset($sql_data[POSTS_TABLE]['sql'])) {
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . '
			WHERE post_id = ' . $data['post_id'];
        $db->sql_query($sql);
    }
    // Update Poll Tables
    if (isset($poll['poll_options'])) {
        $cur_poll_options = array();
        if ($mode == 'edit') {
            $sql = 'SELECT *
				FROM ' . POLL_OPTIONS_TABLE . '
				WHERE topic_id = ' . $data['topic_id'] . '
				ORDER BY poll_option_id';
            $result = $db->sql_query($sql);
            $cur_poll_options = array();
            while ($row = $db->sql_fetchrow($result)) {
                $cur_poll_options[] = $row;
            }
            $db->sql_freeresult($result);
        }
        $sql_insert_ary = array();
        for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) {
            if (strlen(trim($poll['poll_options'][$i]))) {
                if (empty($cur_poll_options[$i])) {
                    // If we add options we need to put them to the end to be able to preserve votes...
                    $sql_insert_ary[] = array('poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), 'topic_id' => (int) $data['topic_id'], 'poll_option_text' => (string) $poll['poll_options'][$i]);
                } else {
                    if ($poll['poll_options'][$i] != $cur_poll_options[$i]) {
                        $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . "\n\t\t\t\t\t\tSET poll_option_text = '" . $db->sql_escape($poll['poll_options'][$i]) . "'\n\t\t\t\t\t\tWHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . '
							AND topic_id = ' . $data['topic_id'];
                        $db->sql_query($sql);
                    }
                }
            }
        }
        $db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary);
        if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) {
            $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . '
				WHERE poll_option_id > ' . sizeof($poll['poll_options']) . '
					AND topic_id = ' . $data['topic_id'];
            $db->sql_query($sql);
        }
        // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option
        if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) {
            $db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']);
            $db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']);
        }
    }
    // Submit Attachments
    if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) {
        $space_taken = $files_added = 0;
        $orphan_rows = array();
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            $orphan_rows[(int) $attach_row['attach_id']] = array();
        }
        if (sizeof($orphan_rows)) {
            $sql = 'SELECT attach_id, filesize, physical_filename
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
					AND is_orphan = 1
					AND poster_id = ' . $user->data['user_id'];
            $result = $db->sql_query($sql);
            $orphan_rows = array();
            while ($row = $db->sql_fetchrow($result)) {
                $orphan_rows[$row['attach_id']] = $row;
            }
            $db->sql_freeresult($result);
        }
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) {
                continue;
            }
            if (!$attach_row['is_orphan']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\tSET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'\n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'] . '
						AND is_orphan = 0';
                $db->sql_query($sql);
            } else {
                // insert attachment into db
                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) {
                    continue;
                }
                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
                $files_added++;
                $attach_sql = array('post_msg_id' => $data['post_id'], 'topic_id' => $data['topic_id'], 'is_orphan' => 0, 'poster_id' => $poster_id, 'attach_comment' => $attach_row['attach_comment']);
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
					WHERE attach_id = ' . $attach_row['attach_id'] . '
						AND is_orphan = 1
						AND poster_id = ' . $user->data['user_id'];
                $db->sql_query($sql);
            }
        }
        if ($space_taken && $files_added) {
            set_config_count('upload_dir_size', $space_taken, true);
            set_config_count('num_files', $files_added, true);
        }
    }
    // we need to update the last forum information
    // only applicable if the topic is not global and it is approved
    // we also check to make sure we are not dealing with globaling the latest topic (pretty rare but still needs to be checked)
    if ($topic_type != POST_GLOBAL && !$make_global && ($post_approved || !$data['post_approved'])) {
        // the last post makes us update the forum table. This can happen if...
        // We make a new topic
        // We reply to a topic
        // We edit the last post in a topic and this post is the latest in the forum (maybe)
        // We edit the only post in the topic
        // We edit the first post in the topic and all the other posts are not approved
        if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved) {
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($subject) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time;
            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $user->data['user_id'];
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape(!$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : '')) . "'";
            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($user->data['user_colour']) . "'";
        } else {
            if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies']) {
                // this does not _necessarily_ mean that we must update the info again,
                // it just means that we might have to
                $sql = 'SELECT forum_last_post_id, forum_last_post_subject
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . (int) $data['forum_id'];
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // this post is the latest post in the forum, better update
                if ($row['forum_last_post_id'] == $data['post_id']) {
                    // If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows
                    if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) {
                        // the post's subject changed
                        if ($row['forum_last_post_subject'] !== $subject) {
                            $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . $db->sql_escape($subject) . '\'';
                        }
                        // Update the user name if poster is anonymous... just in case an admin changed it
                        if ($data['poster_id'] == ANONYMOUS) {
                            $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($username) . "'";
                        }
                    } else {
                        if ($data['post_approved'] !== $post_approved) {
                            // we need a fresh change of socks, everything has become invalidated
                            $sql = 'SELECT MAX(topic_last_post_id) as last_post_id
						FROM ' . TOPICS_TABLE . '
						WHERE forum_id = ' . (int) $data['forum_id'] . '
							AND topic_approved = 1';
                            $result = $db->sql_query($sql);
                            $row = $db->sql_fetchrow($result);
                            $db->sql_freeresult($result);
                            // any posts left in this forum?
                            if (!empty($row['last_post_id'])) {
                                $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
							FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
							WHERE p.poster_id = u.user_id
								AND p.post_id = ' . (int) $row['last_post_id'];
                                $result = $db->sql_query($sql);
                                $row = $db->sql_fetchrow($result);
                                $db->sql_freeresult($result);
                                // salvation, a post is found! jam it into the forums table
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                            } else {
                                // just our luck, the last topic in the forum has just been turned unapproved...
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''";
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0';
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''";
                                $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''";
                            }
                        }
                    }
                }
            }
        }
    } else {
        if ($make_global) {
            // somebody decided to be a party pooper, we must recalculate the whole shebang (maybe)
            $sql = 'SELECT forum_last_post_id
			FROM ' . FORUMS_TABLE . '
			WHERE forum_id = ' . (int) $data['forum_id'];
            $result = $db->sql_query($sql);
            $forum_row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            // we made a topic global, go get new data
            if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL && $forum_row['forum_last_post_id'] == $topic_row['topic_last_post_id']) {
                // we need a fresh change of socks, everything has become invalidated
                $sql = 'SELECT MAX(topic_last_post_id) as last_post_id
				FROM ' . TOPICS_TABLE . '
				WHERE forum_id = ' . (int) $data['forum_id'] . '
					AND topic_approved = 1';
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // any posts left in this forum?
                if (!empty($row['last_post_id'])) {
                    $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
					FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
					WHERE p.poster_id = u.user_id
						AND p.post_id = ' . (int) $row['last_post_id'];
                    $result = $db->sql_query($sql);
                    $row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                    // salvation, a post is found! jam it into the forums table
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                } else {
                    // just our luck, the last topic in the forum has just been globalized...
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0';
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''";
                }
            } else {
                if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL && $forum_row['forum_last_post_id'] < $topic_row['topic_last_post_id']) {
                    // this post has a higher id, it is newer
                    $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
				WHERE p.poster_id = u.user_id
					AND p.post_id = ' . (int) $topic_row['topic_last_post_id'];
                    $result = $db->sql_query($sql);
                    $row = $db->sql_fetchrow($result);
                    $db->sql_freeresult($result);
                    // salvation, a post is found! jam it into the forums table
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time'];
                    $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id'];
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                    $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
                }
            }
        }
    }
    // topic sync time!
    // simply, we update if it is a reply or the last post is edited
    if ($post_approved) {
        // reply requires the whole thing
        if ($post_mode == 'reply') {
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id'];
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $user->data['user_id'];
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape(!$user->data['is_registered'] && $username ? $username : ($user->data['user_id'] != ANONYMOUS ? $user->data['username'] : '')) . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . ($user->data['user_id'] != ANONYMOUS ? $db->sql_escape($user->data['user_colour']) : '') . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
            $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time;
        } else {
            if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies']) {
                // only the subject can be changed from edit
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($subject) . "'";
                // Maybe not only the subject, but also changing anonymous usernames. ;)
                if ($data['poster_id'] == ANONYMOUS) {
                    $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($username) . "'";
                }
            }
        }
    } else {
        if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || $post_mode == 'edit_first_post' && !$data['topic_replies'])) {
            // like having the rug pulled from under us
            $sql = 'SELECT MAX(post_id) as last_post_id
			FROM ' . POSTS_TABLE . '
			WHERE topic_id = ' . (int) $data['topic_id'] . '
				AND post_approved = 1';
            $result = $db->sql_query($sql);
            $row = $db->sql_fetchrow($result);
            $db->sql_freeresult($result);
            // any posts left in this forum?
            if (!empty($row['last_post_id'])) {
                $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour
				FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
				WHERE p.poster_id = u.user_id
					AND p.post_id = ' . (int) $row['last_post_id'];
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);
                // salvation, a post is found! jam it into the topics table
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id'];
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . $db->sql_escape($row['post_subject']) . "'";
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time'];
                $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id'];
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . $db->sql_escape($row['poster_id'] == ANONYMOUS ? $row['post_username'] : $row['username']) . "'";
                $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . $db->sql_escape($row['user_colour']) . "'";
            }
        }
    }
    // Update total post count, do not consider moderated posts/topics
    if ($post_approval) {
        if ($post_mode == 'post') {
            set_config_count('num_topics', 1, true);
            set_config_count('num_posts', 1, true);
        }
        if ($post_mode == 'reply') {
            set_config_count('num_posts', 1, true);
        }
    }
    // Update forum stats
    $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id);
    foreach ($sql_data as $table => $update_ary) {
        if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) {
            $sql = "UPDATE {$table} SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table];
            $db->sql_query($sql);
        }
    }
    // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement
    if ($make_global) {
        $sql = 'DELETE FROM ' . TOPICS_TABLE . '
			WHERE topic_moved_id = ' . $data['topic_id'];
        $db->sql_query($sql);
    }
    // Committing the transaction before updating search index
    $db->sql_transaction('commit');
    // Delete draft if post was loaded...
    $draft_id = request_var('draft_loaded', 0);
    if ($draft_id) {
        $sql = 'DELETE FROM ' . DRAFTS_TABLE . "\n\t\t\tWHERE draft_id = {$draft_id}\n\t\t\t\tAND user_id = {$user->data['user_id']}";
        $db->sql_query($sql);
    }
    // Index message contents
    if ($update_search_index && $data['enable_indexing']) {
        // Select the search method and do some additional checks to ensure it can actually be utilised
        $search_type = basename($config['search_type']);
        if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) {
            trigger_error('NO_SUCH_SEARCH_MODULE');
        }
        if (!class_exists($search_type)) {
            include "{$phpbb_root_path}includes/search/{$search_type}.{$phpEx}";
        }
        $error = false;
        $search = new $search_type($error);
        if ($error) {
            trigger_error($error);
        }
        $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, $topic_type == POST_GLOBAL ? 0 : $data['forum_id']);
    }
    // Topic Notification, do not change if moderator is changing other users posts...
    if ($user->data['user_id'] == $poster_id) {
        if (!$data['notify_set'] && $data['notify']) {
            $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id)
				VALUES (' . $user->data['user_id'] . ', ' . $data['topic_id'] . ')';
            $db->sql_query($sql);
        } else {
            if (($config['email_enable'] || $config['jab_enable']) && $data['notify_set'] && !$data['notify']) {
                $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . '
				WHERE user_id = ' . $user->data['user_id'] . '
					AND topic_id = ' . $data['topic_id'];
                $db->sql_query($sql);
            }
        }
    }
    if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') {
        // Mark this topic as posted to
        markread('post', $data['forum_id'], $data['topic_id']);
    }
    // Mark this topic as read
    // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message)
    markread('topic', $topic_type == POST_GLOBAL ? 0 : $data['forum_id'], $data['topic_id'], time());
    //
    if ($config['load_db_lastread'] && $user->data['is_registered']) {
        $sql = 'SELECT mark_time
			FROM ' . FORUMS_TRACK_TABLE . '
			WHERE user_id = ' . $user->data['user_id'] . '
				AND forum_id = ' . ($topic_type == POST_GLOBAL ? 0 : $data['forum_id']);
        $result = $db->sql_query($sql);
        $f_mark_time = (int) $db->sql_fetchfield('mark_time');
        $db->sql_freeresult($result);
    } else {
        if ($config['load_anon_lastread'] || $user->data['is_registered']) {
            $f_mark_time = false;
        }
    }
    if ($config['load_db_lastread'] && $user->data['is_registered'] || $config['load_anon_lastread'] || $user->data['is_registered']) {
        // Update forum info
        if ($topic_type == POST_GLOBAL) {
            $sql = 'SELECT MAX(topic_last_post_time) as forum_last_post_time
				FROM ' . TOPICS_TABLE . '
				WHERE forum_id = 0';
        } else {
            $sql = 'SELECT forum_last_post_time
				FROM ' . FORUMS_TABLE . '
				WHERE forum_id = ' . $data['forum_id'];
        }
        $result = $db->sql_query($sql);
        $forum_last_post_time = (int) $db->sql_fetchfield('forum_last_post_time');
        $db->sql_freeresult($result);
        update_forum_tracking_info($topic_type == POST_GLOBAL ? 0 : $data['forum_id'], $forum_last_post_time, $f_mark_time, false);
    }
    // Send Notifications
    if (($mode == 'reply' || $mode == 'quote' || $mode == 'post') && $post_approval) {
        user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']);
    }
    $params = $add_anchor = '';
    if ($post_approval) {
        $params .= '&amp;t=' . $data['topic_id'];
        if ($mode != 'post') {
            $params .= '&amp;p=' . $data['post_id'];
            $add_anchor = '#p' . $data['post_id'];
        }
    } else {
        if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') {
            $params .= '&amp;t=' . $data['topic_id'];
        }
    }
    $url = !$params ? "{$phpbb_root_path}viewforum.{$phpEx}" : "{$phpbb_root_path}viewtopic.{$phpEx}";
    $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor;
    return $url;
}
示例#12
0
 function main($mode, $sub)
 {
     global $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language;
     global $request, $phpbb_admin_path, $phpbb_adm_relative_path, $phpbb_container, $phpbb_config_php_file;
     // We must enable super globals, otherwise creating a new instance of the request class,
     // using the new container with a dbal connection will fail with the following PHP Notice:
     // Object of class phpbb_request_deactivated_super_global could not be converted to int
     $request->enable_super_globals();
     // Create a normal container now
     $phpbb_container_builder = new \phpbb\di\container_builder($phpbb_config_php_file, $phpbb_root_path, $phpEx);
     $phpbb_container_builder->set_dump_container(false);
     $phpbb_container_builder->set_use_extensions(false);
     if (file_exists($phpbb_root_path . 'install/update/new/config')) {
         $phpbb_container_builder->set_config_path($phpbb_root_path . 'install/update/new/config');
     }
     $phpbb_container = $phpbb_container_builder->get_container();
     // Writes into global $cache
     $cache = $phpbb_container->get('cache');
     $this->tpl_name = 'install_update';
     $this->page_title = 'UPDATE_INSTALLATION';
     $this->old_location = $phpbb_root_path . 'install/update/old/';
     $this->new_location = $phpbb_root_path . 'install/update/new/';
     // Init DB
     extract($phpbb_config_php_file->get_all());
     require $phpbb_root_path . 'includes/constants.' . $phpEx;
     // Special options for conflicts/modified files
     define('MERGE_NO_MERGE_NEW', 1);
     define('MERGE_NO_MERGE_MOD', 2);
     define('MERGE_NEW_FILE', 3);
     define('MERGE_MOD_FILE', 4);
     $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
     $db = new $dbms();
     // Connect to DB
     $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false);
     // We do not need this any longer, unset for safety purposes
     unset($dbpasswd);
     // We need to fill the config to let internal functions correctly work
     $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null(), CONFIG_TABLE);
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     // Force template recompile
     $config['load_tplcompile'] = 1;
     // First of all, init the user session
     $user->session_begin();
     $auth->acl($user->data);
     // Overwrite user's language with the selected one.
     // Config needs to be changed to ensure that guests also get the selected language.
     $config_default_lang = $config['default_lang'];
     $config['default_lang'] = $language;
     $user->data['user_lang'] = $language;
     $user->add_lang(array('common', 'acp/common', 'acp/board', 'install', 'posting'));
     // Reset the default_lang
     $config['default_lang'] = $config_default_lang;
     unset($config_default_lang);
     // If we are within the intro page we need to make sure we get up-to-date version info
     if ($sub == 'intro') {
         $cache->destroy('_version_info');
     }
     // Set custom template again. ;)
     $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style');
     $paths = array_filter($paths, 'is_dir');
     $template->set_custom_style(array(array('name' => 'adm', 'ext_path' => 'adm/style/')), $paths);
     $template->assign_vars(array('S_USER_LANG' => $user->lang['USER_LANG'], 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'], 'S_CONTENT_ENCODING' => 'UTF-8', 'S_CONTENT_FLOW_BEGIN' => $user->lang['DIRECTION'] == 'ltr' ? 'left' : 'right', 'S_CONTENT_FLOW_END' => $user->lang['DIRECTION'] == 'ltr' ? 'right' : 'left'));
     // Get current and latest version
     $version_helper = $phpbb_container->get('version_helper');
     try {
         $this->latest_version = $version_helper->get_latest_on_current_branch(true);
     } catch (\RuntimeException $e) {
         $this->latest_version = false;
         $update_info = array();
         include $phpbb_root_path . 'install/update/index.' . $phpEx;
         $info = empty($update_info) || !is_array($update_info) ? false : $update_info;
         if ($info !== false) {
             $this->latest_version = !empty($info['version']['to']) ? trim($info['version']['to']) : false;
         }
     }
     // For the current version we trick a bit. ;)
     $this->current_version = !empty($config['version_update_from']) ? $config['version_update_from'] : $config['version'];
     $up_to_date = version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->latest_version)), '<') ? false : true;
     // Check for a valid update directory, else point the user to the phpbb.com website
     if (!file_exists($phpbb_root_path . 'install/update') || !file_exists($phpbb_root_path . 'install/update/index.' . $phpEx) || !file_exists($this->old_location) || !file_exists($this->new_location)) {
         $template->assign_vars(array('S_ERROR' => true, 'ERROR_MSG' => $up_to_date ? $user->lang['NO_UPDATE_FILES_UP_TO_DATE'] : sprintf($user->lang['NO_UPDATE_FILES_OUTDATED'], $config['version'], $this->current_version, $this->latest_version)));
         return;
     }
     $this->update_info = $this->get_file('update_info');
     // Make sure the update directory holds the correct information
     // Since admins are able to run the update/checks more than once we only check if the current version is lower or equal than the version to which we update to.
     if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '>')) {
         $template->assign_vars(array('S_ERROR' => true, 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $config['version'], $this->update_info['version']['from'], $this->update_info['version']['to'])));
         return;
     }
     // Check if the update files are actually meant to update from the current version
     if ($this->current_version != $this->update_info['version']['from']) {
         $template->assign_vars(array('S_ERROR' => true, 'ERROR_MSG' => sprintf($user->lang['INCOMPATIBLE_UPDATE_FILES'], $this->current_version, $this->update_info['version']['from'], $this->update_info['version']['to'])));
     }
     // Check if the update files stored are for the latest version...
     if (version_compare(strtolower($this->latest_version), strtolower($this->update_info['version']['to']), '>')) {
         $template->assign_vars(array('S_WARNING' => true, 'WARNING_MSG' => sprintf($user->lang['OLD_UPDATE_FILES'], $this->update_info['version']['from'], $this->update_info['version']['to'], $this->latest_version)));
     }
     // We store the "update to" version, because it is not always the latest. ;)
     $this->update_to_version = $this->update_info['version']['to'];
     // Fill DB version
     if (empty($config['dbms_version'])) {
         set_config('dbms_version', $db->sql_server_info(true));
     }
     if ($this->test_update === false) {
         // What about the language file? Got it updated?
         if (in_array('language/' . $language . '/install.' . $phpEx, $this->update_info['files'])) {
             $lang = array();
             include $this->new_location . 'language/' . $language . '/install.' . $phpEx;
             // this is the user's language.. just merge it
             $user->lang = array_merge($user->lang, $lang);
         }
         if ($language != 'en' && in_array('language/en/install.' . $phpEx, $this->update_info['files'])) {
             $lang = array();
             include $this->new_location . 'language/en/install.' . $phpEx;
             // only add new keys to user's language in english
             $new_keys = array_diff(array_keys($lang), array_keys($user->lang));
             foreach ($new_keys as $i => $new_key) {
                 $user->lang[$new_key] = $lang[$new_key];
             }
         }
     }
     // Include renderer and engine
     $this->include_file('includes/diff/diff.' . $phpEx);
     $this->include_file('includes/diff/engine.' . $phpEx);
     $this->include_file('includes/diff/renderer.' . $phpEx);
     // Make sure we stay at the file check if checking the files again
     if ($request->variable('check_again', false, false, \phpbb\request\request_interface::POST)) {
         $sub = $this->p_master->sub = 'file_check';
     }
     switch ($sub) {
         case 'intro':
             $this->page_title = 'UPDATE_INSTALLATION';
             $template->assign_vars(array('S_INTRO' => true, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=version_check")));
             // Make sure the update list is destroyed.
             $cache->destroy('_update_list');
             $cache->destroy('_diff_files');
             $cache->destroy('_expected_files');
             break;
         case 'version_check':
             $this->page_title = 'STAGE_VERSION_CHECK';
             $template->assign_vars(array('S_VERSION_CHECK' => true, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check"), 'S_UP_TO_DATE' => $up_to_date, 'LATEST_VERSION' => $this->latest_version, 'CURRENT_VERSION' => $this->current_version));
             // Print out version the update package updates to
             if ($this->latest_version != $this->update_info['version']['to']) {
                 $template->assign_var('PACKAGE_VERSION', $this->update_info['version']['to']);
             }
             // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
             // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
             // We now try to cope with this by triggering the update process
             if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<')) {
                 $template->assign_vars(array('S_UP_TO_DATE' => false));
             }
             break;
         case 'update_db':
             // Redirect the user to the database update script with some explanations...
             $template->assign_vars(array('S_DB_UPDATE' => true, 'S_DB_UPDATE_FINISHED' => $config['version'] == $this->update_info['version']['to'] ? true : false, 'U_DB_UPDATE' => append_sid($phpbb_root_path . 'install/database_update.' . $phpEx, 'type=1&amp;language=' . $user->data['user_lang']), 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_db"), 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check"), 'L_EVERYTHING_UP_TO_DATE' => $user->lang('EVERYTHING_UP_TO_DATE', append_sid("{$phpbb_root_path}ucp.{$phpEx}", 'mode=login'), append_sid("{$phpbb_root_path}ucp.{$phpEx}", 'mode=login&amp;redirect=' . $phpbb_adm_relative_path . 'index.php%3Fi=send_statistics%26mode=send_statistics'))));
             // Do not display incompatible package note after successful update
             if ($config['version'] == $this->update_info['version']['to']) {
                 $template->assign_var('S_ERROR', false);
             }
             break;
         case 'file_check':
             // retrieve info on what changes should have already been made to the files.
             $expected_files = $cache->get('_expected_files');
             if (!$expected_files) {
                 $expected_files = array();
             }
             // Now make sure the previous file collection is no longer valid...
             $cache->destroy('_diff_files');
             $this->page_title = 'STAGE_FILE_CHECK';
             // Now make sure our update list is correct if the admin refreshes
             $action = request_var('action', '');
             // We are directly within an update. To make sure our update list is correct we check its status.
             $update_list = $request->variable('check_again', false, false, \phpbb\request\request_interface::POST) ? false : $cache->get('_update_list');
             $modified = $update_list !== false ? @filemtime($cache->get_driver()->cache_dir . 'data_update_list.' . $phpEx) : 0;
             // Make sure the list is up-to-date
             if ($update_list !== false) {
                 $get_new_list = false;
                 foreach ($this->update_info['files'] as $file) {
                     if (file_exists($phpbb_root_path . $file) && filemtime($phpbb_root_path . $file) > $modified) {
                         $get_new_list = true;
                         break;
                     }
                 }
             } else {
                 $get_new_list = true;
             }
             if (!$get_new_list && $update_list['status'] != -1) {
                 $get_new_list = true;
             }
             if ($get_new_list) {
                 $this->get_update_structure($update_list, $expected_files);
                 $cache->put('_update_list', $update_list);
                 // Refresh the page if we are still not finished...
                 if ($update_list['status'] != -1) {
                     $refresh_url = append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check");
                     meta_refresh(2, $refresh_url);
                     $template->assign_vars(array('S_IN_PROGRESS' => true, 'S_COLLECTED' => (int) $update_list['status'], 'S_TO_COLLECT' => sizeof($this->update_info['files']), 'L_IN_PROGRESS' => $user->lang['COLLECTING_FILE_DIFFS'], 'L_IN_PROGRESS_EXPLAIN' => sprintf($user->lang['NUMBER_OF_FILES_COLLECTED'], (int) $update_list['status'], sizeof($this->update_info['files']) + sizeof($this->update_info['deleted']))));
                     return;
                 }
             }
             if ($action == 'diff') {
                 $this->show_diff($update_list);
                 return;
             }
             if (sizeof($update_list['no_update'])) {
                 $template->assign_vars(array('S_NO_UPDATE_FILES' => true, 'NO_UPDATE_FILES' => implode(', ', array_map('htmlspecialchars', $update_list['no_update']))));
             }
             $new_expected_files = array();
             // Now assign the list to the template
             foreach ($update_list as $status => $filelist) {
                 if ($status == 'no_update' || !sizeof($filelist) || $status == 'status' || $status == 'status_deleted') {
                     continue;
                 }
                 /*					$template->assign_block_vars('files', array(
                 						'S_STATUS'		=> true,
                 						'STATUS'		=> $status,
                 						'L_STATUS'		=> $user->lang['STATUS_' . strtoupper($status)],
                 						'TITLE'			=> $user->lang['FILES_' . strtoupper($status)],
                 						'EXPLAIN'		=> $user->lang['FILES_' . strtoupper($status) . '_EXPLAIN'],
                 						)
                 					);*/
                 foreach ($filelist as $file_struct) {
                     $s_binary = !empty($this->update_info['binary']) && in_array($file_struct['filename'], $this->update_info['binary']) ? true : false;
                     $filename = htmlspecialchars($file_struct['filename']);
                     if (strrpos($filename, '/') !== false) {
                         $dir_part = substr($filename, 0, strrpos($filename, '/') + 1);
                         $file_part = substr($filename, strrpos($filename, '/') + 1);
                     } else {
                         $dir_part = '';
                         $file_part = $filename;
                     }
                     $diff_url = append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check&amp;action=diff&amp;status={$status}&amp;file=" . urlencode($file_struct['filename']));
                     if (isset($file_struct['as_expected']) && $file_struct['as_expected']) {
                         $new_expected_files[$file_struct['filename']] = $expected_files[$file_struct['filename']];
                     } else {
                         $template->assign_block_vars($status, array('STATUS' => $status, 'FILENAME' => $filename, 'DIR_PART' => $dir_part, 'FILE_PART' => $file_part, 'NUM_CONFLICTS' => isset($file_struct['conflicts']) ? $file_struct['conflicts'] : 0, 'S_CUSTOM' => $file_struct['custom'] ? true : false, 'S_BINARY' => $s_binary, 'CUSTOM_ORIGINAL' => $file_struct['custom'] ? $file_struct['original'] : '', 'U_SHOW_DIFF' => $diff_url, 'L_SHOW_DIFF' => $status != 'up_to_date' ? $user->lang['SHOW_DIFF_' . strtoupper($status)] : '', 'U_VIEW_MOD_FILE' => $diff_url . '&amp;op=' . MERGE_MOD_FILE, 'U_VIEW_NEW_FILE' => $diff_url . '&amp;op=' . MERGE_NEW_FILE, 'U_VIEW_NO_MERGE_MOD' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_MOD, 'U_VIEW_NO_MERGE_NEW' => $diff_url . '&amp;op=' . MERGE_NO_MERGE_NEW));
                     }
                 }
             }
             $cache->put('_expected_files', $new_expected_files);
             $all_up_to_date = true;
             foreach ($update_list as $status => $filelist) {
                 if ($status != 'up_to_date' && $status != 'custom' && $status != 'status' && $status != 'status_deleted' && sizeof($filelist)) {
                     $all_up_to_date = false;
                     break;
                 }
             }
             $template->assign_vars(array('S_FILE_CHECK' => true, 'S_ALL_UP_TO_DATE' => $all_up_to_date, 'S_VERSION_UP_TO_DATE' => $up_to_date, 'S_UP_TO_DATE' => $up_to_date, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check"), 'U_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_files"), 'U_DB_UPDATE_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_db")));
             // Since some people try to update to RC releases, but phpBB.com tells them the last version is the version they currently run
             // we are faced with the updater thinking the database schema is up-to-date; which it is, but should be updated none-the-less
             // We now try to cope with this by triggering the update process
             if (version_compare(str_replace('rc', 'RC', strtolower($this->current_version)), str_replace('rc', 'RC', strtolower($this->update_info['version']['to'])), '<')) {
                 $template->assign_vars(array('S_UP_TO_DATE' => false));
             }
             if ($all_up_to_date) {
                 global $phpbb_container;
                 $phpbb_log = $phpbb_container->get('log');
                 // Add database update to log
                 $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_UPDATE_PHPBB', time(), array($this->current_version, $this->update_to_version));
                 $db->sql_return_on_error(true);
                 $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'");
                 $db->sql_return_on_error(false);
                 $cache->purge();
             }
             break;
         case 'update_files':
             $this->page_title = 'STAGE_UPDATE_FILES';
             $s_hidden_fields = '';
             $params = array();
             $conflicts = request_var('conflict', array('' => 0));
             $modified = request_var('modified', array('' => 0));
             foreach ($conflicts as $filename => $merge_option) {
                 $s_hidden_fields .= '<input type="hidden" name="conflict[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
                 $params[] = 'conflict[' . urlencode($filename) . ']=' . urlencode($merge_option);
             }
             foreach ($modified as $filename => $merge_option) {
                 if (!$merge_option) {
                     continue;
                 }
                 $s_hidden_fields .= '<input type="hidden" name="modified[' . htmlspecialchars($filename) . ']" value="' . $merge_option . '" />';
                 $params[] = 'modified[' . urlencode($filename) . ']=' . urlencode($merge_option);
             }
             $no_update = request_var('no_update', array(0 => ''));
             foreach ($no_update as $index => $filename) {
                 $s_hidden_fields .= '<input type="hidden" name="no_update[]" value="' . htmlspecialchars($filename) . '" />';
                 $params[] = 'no_update[]=' . urlencode($filename);
             }
             // Before the user is choosing his preferred method, let's create the content list...
             $update_list = $cache->get('_update_list');
             if ($update_list === false) {
                 trigger_error($user->lang['NO_UPDATE_INFO'], E_USER_ERROR);
             }
             // Check if the conflicts data is valid
             if (sizeof($conflicts)) {
                 $conflict_filenames = array();
                 foreach ($update_list['conflict'] as $files) {
                     $conflict_filenames[] = $files['filename'];
                 }
                 $new_conflicts = array();
                 foreach ($conflicts as $filename => $diff_method) {
                     if (in_array($filename, $conflict_filenames)) {
                         $new_conflicts[$filename] = $diff_method;
                     }
                 }
                 $conflicts = $new_conflicts;
             }
             // Build list for modifications
             if (sizeof($modified)) {
                 $modified_filenames = array();
                 foreach ($update_list['modified'] as $files) {
                     $modified_filenames[] = $files['filename'];
                 }
                 $new_modified = array();
                 foreach ($modified as $filename => $diff_method) {
                     if (in_array($filename, $modified_filenames)) {
                         $new_modified[$filename] = $diff_method;
                     }
                 }
                 $modified = $new_modified;
             }
             // Check number of conflicting files, they need to be equal. For modified files the number can differ
             if (sizeof($update_list['conflict']) != sizeof($conflicts)) {
                 trigger_error($user->lang['MERGE_SELECT_ERROR'], E_USER_ERROR);
             }
             // Before we do anything, let us diff the files and store the raw file information "somewhere"
             $get_files = false;
             $file_list = $cache->get('_diff_files');
             $expected_files = $cache->get('_expected_files');
             if ($file_list === false || $file_list['status'] != -1) {
                 $get_files = true;
             }
             if ($get_files) {
                 if ($file_list === false) {
                     $file_list = array('status' => 0);
                 }
                 if (!isset($expected_files) || $expected_files === false) {
                     $expected_files = array();
                 }
                 $processed = 0;
                 foreach ($update_list as $status => $files) {
                     if (!is_array($files)) {
                         continue;
                     }
                     foreach ($files as $file_struct) {
                         // Skip this file if the user selected to not update it
                         if (in_array($file_struct['filename'], $no_update)) {
                             $expected_files[$file_struct['filename']] = false;
                             continue;
                         }
                         // Already handled... then skip of course...
                         if (isset($file_list[$file_struct['filename']])) {
                             continue;
                         }
                         // Refresh if we reach 5 diffs...
                         if ($processed >= 5) {
                             $cache->put('_diff_files', $file_list);
                             if ($request->variable('download', false)) {
                                 $params[] = 'download=1';
                             }
                             $redirect_url = append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_files&amp;" . implode('&amp;', $params));
                             meta_refresh(3, $redirect_url);
                             $template->assign_vars(array('S_IN_PROGRESS' => true, 'L_IN_PROGRESS' => $user->lang['MERGING_FILES'], 'L_IN_PROGRESS_EXPLAIN' => $user->lang['MERGING_FILES_EXPLAIN']));
                             return;
                         }
                         if (file_exists($phpbb_root_path . $file_struct['filename'])) {
                             $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
                             if (isset($expected_files[$file_struct['filename']]) && md5($contents) == $expected_files[$file_struct['filename']]) {
                                 continue;
                             }
                         }
                         $original_filename = $file_struct['custom'] ? $file_struct['original'] : $file_struct['filename'];
                         switch ($status) {
                             case 'modified':
                                 $option = isset($modified[$file_struct['filename']]) ? $modified[$file_struct['filename']] : 0;
                                 switch ($option) {
                                     case MERGE_NO_MERGE_NEW:
                                         $contents = file_get_contents($this->new_location . $original_filename);
                                         break;
                                     case MERGE_NO_MERGE_MOD:
                                         $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
                                         break;
                                     default:
                                         $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
                                         $contents = implode("\n", $diff->merged_output());
                                         unset($diff);
                                         break;
                                 }
                                 $expected_files[$file_struct['filename']] = md5($contents);
                                 $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
                                 $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
                                 $file_list['status']++;
                                 $processed++;
                                 break;
                             case 'conflict':
                                 $option = $conflicts[$file_struct['filename']];
                                 $contents = '';
                                 switch ($option) {
                                     case MERGE_NO_MERGE_NEW:
                                         $contents = file_get_contents($this->new_location . $original_filename);
                                         break;
                                     case MERGE_NO_MERGE_MOD:
                                         $contents = file_get_contents($phpbb_root_path . $file_struct['filename']);
                                         break;
                                     default:
                                         $diff = $this->return_diff($this->old_location . $original_filename, $phpbb_root_path . $file_struct['filename'], $this->new_location . $original_filename);
                                         if ($option == MERGE_NEW_FILE) {
                                             $contents = implode("\n", $diff->merged_new_output());
                                         } else {
                                             if ($option == MERGE_MOD_FILE) {
                                                 $contents = implode("\n", $diff->merged_orig_output());
                                             } else {
                                                 unset($diff);
                                                 break 2;
                                             }
                                         }
                                         unset($diff);
                                         break;
                                 }
                                 $expected_files[$file_struct['filename']] = md5($contents);
                                 $file_list[$file_struct['filename']] = '_file_' . md5($file_struct['filename']);
                                 $cache->put($file_list[$file_struct['filename']], base64_encode($contents));
                                 $file_list['status']++;
                                 $processed++;
                                 break;
                         }
                     }
                 }
                 $cache->put('_expected_files', $expected_files);
             }
             $file_list['status'] = -1;
             $cache->put('_diff_files', $file_list);
             if ($request->variable('download', false)) {
                 $this->include_file('includes/functions_compress.' . $phpEx);
                 $use_method = request_var('use_method', '');
                 $methods = array('.tar');
                 $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib');
                 foreach ($available_methods as $type => $module) {
                     if (!@extension_loaded($module)) {
                         continue;
                     }
                     $methods[] = $type;
                 }
                 // Let the user decide in which format he wants to have the pack
                 if (!$use_method) {
                     $this->page_title = 'SELECT_DOWNLOAD_FORMAT';
                     $radio_buttons = '';
                     foreach ($methods as $method) {
                         $radio_buttons .= '<label><input type="radio"' . (!$radio_buttons ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>';
                     }
                     $template->assign_vars(array('S_DOWNLOAD_FILES' => true, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_files"), 'RADIO_BUTTONS' => $radio_buttons, 'S_HIDDEN_FIELDS' => $s_hidden_fields));
                     // To ease the update process create a file location map
                     $update_list = $cache->get('_update_list');
                     $script_path = $config['force_server_vars'] ? $config['script_path'] == '/' ? '/' : $config['script_path'] . '/' : $user->page['root_script_path'];
                     foreach ($update_list as $status => $files) {
                         if ($status == 'up_to_date' || $status == 'no_update' || $status == 'status' || $status == 'status_deleted') {
                             continue;
                         }
                         foreach ($files as $file_struct) {
                             if (in_array($file_struct['filename'], $no_update)) {
                                 continue;
                             }
                             $template->assign_block_vars('location', array('SOURCE' => htmlspecialchars($file_struct['filename']), 'DESTINATION' => $script_path . htmlspecialchars($file_struct['filename'])));
                         }
                     }
                     return;
                 }
                 if (!in_array($use_method, $methods)) {
                     $use_method = '.tar';
                 }
                 $update_mode = 'download';
             } else {
                 $this->include_file('includes/functions_transfer.' . $phpEx);
                 // Choose FTP, if not available use fsock...
                 $method = basename(request_var('method', ''));
                 $submit = isset($_POST['submit']) ? true : false;
                 $test_ftp_connection = request_var('test_connection', '');
                 if (!$method || !class_exists($method)) {
                     $method = 'ftp';
                     $methods = transfer::methods();
                     if (!in_array('ftp', $methods)) {
                         $method = $methods[0];
                     }
                 }
                 $test_connection = false;
                 if ($test_ftp_connection || $submit) {
                     $transfer = new $method(request_var('host', ''), request_var('username', ''), htmlspecialchars_decode($request->untrimmed_variable('password', '')), request_var('root_path', ''), request_var('port', ''), request_var('timeout', ''));
                     $test_connection = $transfer->open_session();
                     // Make sure that the directory is correct by checking for the existence of common.php
                     if ($test_connection === true) {
                         // Check for common.php file
                         if (!$transfer->file_exists($phpbb_root_path, 'common.' . $phpEx)) {
                             $test_connection = 'ERR_WRONG_PATH_TO_PHPBB';
                         }
                     }
                     $transfer->close_session();
                     // Make sure the login details are correct before continuing
                     if ($submit && $test_connection !== true) {
                         $submit = false;
                         $test_ftp_connection = true;
                     }
                 }
                 $s_hidden_fields .= build_hidden_fields(array('method' => $method));
                 if (!$submit) {
                     $this->page_title = 'SELECT_FTP_SETTINGS';
                     if (!class_exists($method)) {
                         trigger_error('Method does not exist.', E_USER_ERROR);
                     }
                     $requested_data = call_user_func(array($method, 'data'));
                     foreach ($requested_data as $data => $default) {
                         $template->assign_block_vars('data', array('DATA' => $data, 'NAME' => $user->lang[strtoupper($method . '_' . $data)], 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], 'DEFAULT' => $request->variable($data, (string) $default)));
                     }
                     $template->assign_vars(array('S_CONNECTION_SUCCESS' => $test_ftp_connection && $test_connection === true ? true : false, 'S_CONNECTION_FAILED' => $test_ftp_connection && $test_connection !== true ? true : false, 'ERROR_MSG' => $test_ftp_connection && $test_connection !== true ? $user->lang[$test_connection] : '', 'S_FTP_UPLOAD' => true, 'UPLOAD_METHOD' => $method, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_files"), 'U_DOWNLOAD_METHOD' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=update_files&amp;download=1"), 'S_HIDDEN_FIELDS' => $s_hidden_fields));
                     return;
                 }
                 $update_mode = 'upload';
             }
             // Now update the installation or download the archive...
             $download_filename = 'update_' . $this->update_info['version']['from'] . '_to_' . $this->update_info['version']['to'];
             $archive_filename = $download_filename . '_' . time() . '_' . unique_id();
             // Now init the connection
             if ($update_mode == 'download') {
                 if (function_exists('phpbb_is_writable') && !phpbb_is_writable($phpbb_root_path . 'store/')) {
                     trigger_error(sprintf('The directory “%s” is not writable.', $phpbb_root_path . 'store/'), E_USER_ERROR);
                 }
                 if ($use_method == '.zip') {
                     $compress = new compress_zip('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method);
                 } else {
                     $compress = new compress_tar('w', $phpbb_root_path . 'store/' . $archive_filename . $use_method, $use_method);
                 }
             } else {
                 $transfer = new $method(request_var('host', ''), request_var('username', ''), htmlspecialchars_decode($request->untrimmed_variable('password', '')), request_var('root_path', ''), request_var('port', ''), request_var('timeout', ''));
                 $transfer->open_session();
             }
             // Ok, go through the update list and do the operations based on their status
             foreach ($update_list as $status => $files) {
                 if (!is_array($files)) {
                     continue;
                 }
                 foreach ($files as $file_struct) {
                     // Skip this file if the user selected to not update it
                     if (in_array($file_struct['filename'], $no_update)) {
                         continue;
                     }
                     $original_filename = $file_struct['custom'] ? $file_struct['original'] : $file_struct['filename'];
                     switch ($status) {
                         case 'new':
                         case 'new_conflict':
                         case 'not_modified':
                             if ($update_mode == 'download') {
                                 $compress->add_custom_file($this->new_location . $original_filename, $file_struct['filename']);
                             } else {
                                 if ($status != 'new') {
                                     $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
                                 }
                                 // New directory too?
                                 $dirname = dirname($file_struct['filename']);
                                 if ($dirname && !file_exists($phpbb_root_path . $dirname)) {
                                     $transfer->make_dir($dirname);
                                 }
                                 $transfer->copy_file($this->new_location . $original_filename, $file_struct['filename']);
                             }
                             break;
                         case 'modified':
                             $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
                             if ($update_mode == 'download') {
                                 $compress->add_data($contents, $file_struct['filename']);
                             } else {
                                 // @todo add option to specify if a backup file should be created?
                                 $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
                                 $transfer->write_file($file_struct['filename'], $contents);
                             }
                             break;
                         case 'conflict':
                             $contents = base64_decode($cache->get($file_list[$file_struct['filename']]));
                             if ($update_mode == 'download') {
                                 $compress->add_data($contents, $file_struct['filename']);
                             } else {
                                 $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
                                 $transfer->write_file($file_struct['filename'], $contents);
                             }
                             break;
                         case 'deleted':
                             if ($update_mode != 'download') {
                                 $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak');
                             }
                             break;
                     }
                 }
             }
             if ($update_mode == 'download') {
                 $compress->close();
                 $compress->download($archive_filename, $download_filename);
                 @unlink($phpbb_root_path . 'store/' . $archive_filename . $use_method);
                 exit;
             } else {
                 $transfer->close_session();
                 $template->assign_vars(array('S_UPLOAD_SUCCESS' => true, 'U_ACTION' => append_sid($this->p_master->module_url, "language={$language}&amp;mode={$mode}&amp;sub=file_check")));
                 return;
             }
             break;
     }
 }
示例#13
0
 /**
  * The function which does the actual work (or dispatches it to the relevant places)
  */
 function convert_data($sub)
 {
     global $template, $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth;
     global $convert, $convert_row, $message_parser, $skip_rows, $language;
     global $request, $phpbb_config_php_file;
     extract($phpbb_config_php_file->get_all());
     require $phpbb_root_path . 'includes/constants.' . $phpEx;
     require $phpbb_root_path . 'includes/functions_convert.' . $phpEx;
     $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms);
     $db = new $dbms();
     $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true);
     unset($dbpasswd);
     // We need to fill the config to let internal functions correctly work
     $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null(), CONFIG_TABLE);
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     // Override a couple of config variables for the duration
     $config['max_quote_depth'] = 0;
     // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
     $config['max_post_chars'] = $config['min_post_chars'] = 0;
     // Set up a user as well. We _should_ have enough of a database here at this point to do this
     // and it helps for any core code we call
     $user->session_begin();
     $user->page = $user->extract_current_page($phpbb_root_path);
     // This is a little bit of a fudge, but it allows the language entries to be available to the
     // core code without us loading them again
     $user->lang =& $lang;
     $this->page_title = $user->lang['STAGE_IN_PROGRESS'];
     $convert->options = array();
     if (isset($config['convert_progress'])) {
         $convert->options = unserialize($config['convert_progress']);
         $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options']));
     }
     // This information should have already been checked once, but do it again for safety
     if (empty($convert->options) || empty($convert->options['tag']) || !isset($convert->options['dbms']) || !isset($convert->options['dbhost']) || !isset($convert->options['dbport']) || !isset($convert->options['dbuser']) || !isset($convert->options['dbpasswd']) || !isset($convert->options['dbname']) || !isset($convert->options['table_prefix'])) {
         $this->p_master->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__);
     }
     // Make some short variables accessible, for easier referencing
     $convert->convertor_tag = basename($convert->options['tag']);
     $convert->src_dbms = $convert->options['dbms'];
     $convert->src_dbhost = $convert->options['dbhost'];
     $convert->src_dbport = $convert->options['dbport'];
     $convert->src_dbuser = $convert->options['dbuser'];
     $convert->src_dbpasswd = $convert->options['dbpasswd'];
     $convert->src_dbname = $convert->options['dbname'];
     $convert->src_table_prefix = $convert->options['table_prefix'];
     // initiate database connection to old db if old and new db differ
     global $src_db, $same_db;
     $src_db = $same_db = null;
     if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser) {
         $dbms = $convert->src_dbms;
         $src_db = new $dbms();
         $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true);
         $same_db = false;
     } else {
         $src_db = $db;
         $same_db = true;
     }
     $convert->mysql_convert = false;
     switch ($src_db->sql_layer) {
         case 'sqlite':
         case 'sqlite3':
             $convert->src_truncate_statement = 'DELETE FROM ';
             break;
             // Thanks MySQL, for silently converting...
         // Thanks MySQL, for silently converting...
         case 'mysql':
         case 'mysql4':
             if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>=')) {
                 $convert->mysql_convert = true;
             }
             $convert->src_truncate_statement = 'TRUNCATE TABLE ';
             break;
         case 'mysqli':
             $convert->mysql_convert = true;
             $convert->src_truncate_statement = 'TRUNCATE TABLE ';
             break;
         default:
             $convert->src_truncate_statement = 'TRUNCATE TABLE ';
             break;
     }
     if ($convert->mysql_convert && !$same_db) {
         $src_db->sql_query("SET NAMES 'binary'");
     }
     switch ($db->get_sql_layer()) {
         case 'sqlite':
         case 'sqlite3':
             $convert->truncate_statement = 'DELETE FROM ';
             break;
         default:
             $convert->truncate_statement = 'TRUNCATE TABLE ';
             break;
     }
     $get_info = false;
     // check security implications of direct inclusion
     if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx)) {
         $this->p_master->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__);
     }
     if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx)) {
         include './convertors/functions_' . $convert->convertor_tag . '.' . $phpEx;
     }
     $get_info = true;
     include './convertors/convert_' . $convert->convertor_tag . '.' . $phpEx;
     // Map some variables...
     $convert->convertor_data = $convertor_data;
     $convert->tables = $tables;
     $convert->config_schema = $config_schema;
     // Now include the real data
     $get_info = false;
     include './convertors/convert_' . $convert->convertor_tag . '.' . $phpEx;
     $convert->convertor_data = $convertor_data;
     $convert->tables = $tables;
     $convert->config_schema = $config_schema;
     $convert->convertor = $convertor;
     // The test_file is a file that should be present in the location of the old board.
     if (!file_exists($convert->options['forum_path'] . '/' . $test_file)) {
         $this->p_master->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__);
     }
     $search_type = $config['search_type'];
     // For conversions we are a bit less strict and set to a search backend we know exist...
     if (!class_exists($search_type)) {
         $search_type = '\\phpbb\\search\\fulltext_native';
         set_config('search_type', $search_type);
     }
     if (!class_exists($search_type)) {
         trigger_error('NO_SUCH_SEARCH_MODULE');
     }
     $error = false;
     $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user);
     if ($error) {
         trigger_error($error);
     }
     include $phpbb_root_path . 'includes/message_parser.' . $phpEx;
     $message_parser = new parse_message();
     $jump = request_var('jump', 0);
     $final_jump = request_var('final_jump', 0);
     $sync_batch = request_var('sync_batch', -1);
     $last_statement = request_var('last', 0);
     // We are running sync...
     if ($sync_batch >= 0) {
         $this->sync_forums($sync_batch);
         return;
     }
     if ($jump) {
         $this->jump($jump, $last_statement);
         return;
     }
     if ($final_jump) {
         $this->final_jump($final_jump);
         return;
     }
     $current_table = request_var('current_table', 0);
     $old_current_table = min(-1, $current_table - 1);
     $skip_rows = request_var('skip_rows', 0);
     if (!$current_table && !$skip_rows) {
         if (!$request->variable('confirm', false)) {
             // If avatars / ranks / smilies folders are specified make sure they are writable
             $bad_folders = array();
             $local_paths = array('avatar_path' => path($config['avatar_path']), 'avatar_gallery_path' => path($config['avatar_gallery_path']), 'icons_path' => path($config['icons_path']), 'ranks_path' => path($config['ranks_path']), 'smilies_path' => path($config['smilies_path']));
             foreach ($local_paths as $folder => $local_path) {
                 if (isset($convert->convertor[$folder])) {
                     if (empty($convert->convertor['test_file'])) {
                         // test_file is mandantory at the moment so this should never be reached, but just in case...
                         $this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);
                     }
                     if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path)) {
                         if (!$local_path) {
                             $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder);
                         } else {
                             $bad_folders[] = $local_path;
                         }
                     }
                 }
             }
             if (sizeof($bad_folders)) {
                 $msg = sizeof($bad_folders) == 1 ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE'];
                 sort($bad_folders);
                 $this->p_master->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true);
                 $template->assign_vars(array('L_SUBMIT' => $user->lang['INSTALL_TEST'], 'U_ACTION' => $this->p_master->module_url . "?mode={$this->mode}&amp;sub=in_progress&amp;tag={$convert->convertor_tag}&amp;language={$language}"));
                 return;
             }
             // Grab all the tables used in convertor
             $missing_tables = $tables_list = $aliases = array();
             foreach ($convert->convertor['schema'] as $schema) {
                 // Skip those not used (because of addons/plugins not detected)
                 if (!$schema['target']) {
                     continue;
                 }
                 foreach ($schema as $key => $val) {
                     // we're dealing with an array like:
                     // array('forum_status',			'forums.forum_status',				'is_item_locked')
                     if (is_int($key) && !empty($val[1])) {
                         $temp_data = $val[1];
                         if (!is_array($temp_data)) {
                             $temp_data = array($temp_data);
                         }
                         foreach ($temp_data as $val) {
                             if (preg_match('/([a-z0-9_]+)\\.([a-z0-9_]+)\\)* ?A?S? ?([a-z0-9_]*?)\\.?([a-z0-9_]*)$/i', $val, $m)) {
                                 $table = $convert->src_table_prefix . $m[1];
                                 $tables_list[$table] = $table;
                                 if (!empty($m[3])) {
                                     $aliases[] = $convert->src_table_prefix . $m[3];
                                 }
                             }
                         }
                     } else {
                         if ($key == 'left_join') {
                             // Convert the value if it wasn't an array already.
                             if (!is_array($val)) {
                                 $val = array($val);
                             }
                             for ($j = 0; $j < sizeof($val); ++$j) {
                                 if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m)) {
                                     $table = $convert->src_table_prefix . $m[1];
                                     $tables_list[$table] = $table;
                                     if (!empty($m[2])) {
                                         $aliases[] = $convert->src_table_prefix . $m[2];
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
             // Remove aliased tables from $tables_list
             foreach ($aliases as $alias) {
                 unset($tables_list[$alias]);
             }
             // Check if the tables that we need exist
             $src_db->sql_return_on_error(true);
             foreach ($tables_list as $table => $null) {
                 $sql = 'SELECT 1 FROM ' . $table;
                 $_result = $src_db->sql_query_limit($sql, 1);
                 if (!$_result) {
                     $missing_tables[] = $table;
                 }
                 $src_db->sql_freeresult($_result);
             }
             $src_db->sql_return_on_error(false);
             // Throw an error if some tables are missing
             // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again
             if (sizeof($missing_tables) == sizeof($tables_list)) {
                 $this->p_master->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
             } else {
                 if (sizeof($missing_tables)) {
                     $this->p_master->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__);
                 }
             }
             $url = $this->save_convert_progress('&amp;confirm=1');
             $msg = $user->lang['PRE_CONVERT_COMPLETE'];
             if ($convert->convertor_data['author_notes']) {
                 $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']);
             }
             $template->assign_vars(array('L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 'L_MESSAGE' => $msg, 'U_ACTION' => $url));
             return;
         }
         // if (!$request->variable('confirm', false)))
         $template->assign_block_vars('checks', array('S_LEGEND' => true, 'LEGEND' => $user->lang['STARTING_CONVERT']));
         // Convert the config table and load the settings of the old board
         if (!empty($convert->config_schema)) {
             restore_config($convert->config_schema);
             // Override a couple of config variables for the duration
             $config['max_quote_depth'] = 0;
             // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues
             $config['max_post_chars'] = $config['min_post_chars'] = 0;
         }
         $template->assign_block_vars('checks', array('TITLE' => $user->lang['CONFIG_CONVERT'], 'RESULT' => $user->lang['DONE']));
         // Now process queries and execute functions that have to be executed prior to the conversion
         if (!empty($convert->convertor['execute_first'])) {
             // @codingStandardsIgnoreStart
             eval($convert->convertor['execute_first']);
             // @codingStandardsIgnoreEnd
         }
         if (!empty($convert->convertor['query_first'])) {
             if (!is_array($convert->convertor['query_first'])) {
                 $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first']));
             } else {
                 if (!is_array($convert->convertor['query_first'][0])) {
                     $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1]));
                 }
             }
             foreach ($convert->convertor['query_first'] as $query_first) {
                 if ($query_first[0] == 'src') {
                     if ($convert->mysql_convert && $same_db) {
                         $src_db->sql_query("SET NAMES 'binary'");
                     }
                     $src_db->sql_query($query_first[1]);
                     if ($convert->mysql_convert && $same_db) {
                         $src_db->sql_query("SET NAMES 'utf8'");
                     }
                 } else {
                     $db->sql_query($query_first[1]);
                 }
             }
         }
         $template->assign_block_vars('checks', array('TITLE' => $user->lang['PREPROCESS_STEP'], 'RESULT' => $user->lang['DONE']));
     }
     // if (!$current_table && !$skip_rows)
     $template->assign_block_vars('checks', array('S_LEGEND' => true, 'LEGEND' => $user->lang['FILLING_TABLES']));
     // This loop takes one target table and processes it
     while ($current_table < sizeof($convert->convertor['schema'])) {
         $schema = $convert->convertor['schema'][$current_table];
         // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this.
         if (empty($schema['target'])) {
             $current_table++;
             continue;
         }
         $template->assign_block_vars('checks', array('TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target'])));
         // This is only the case when we first start working on the tables.
         if (!$skip_rows) {
             // process execute_first and query_first for this table...
             if (!empty($schema['execute_first'])) {
                 // @codingStandardsIgnoreStart
                 eval($schema['execute_first']);
                 // @codingStandardsIgnoreEnd
             }
             if (!empty($schema['query_first'])) {
                 if (!is_array($schema['query_first'])) {
                     $schema['query_first'] = array('target', array($schema['query_first']));
                 } else {
                     if (!is_array($schema['query_first'][0])) {
                         $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1]));
                     }
                 }
                 foreach ($schema['query_first'] as $query_first) {
                     if ($query_first[0] == 'src') {
                         if ($convert->mysql_convert && $same_db) {
                             $src_db->sql_query("SET NAMES 'binary'");
                         }
                         $src_db->sql_query($query_first[1]);
                         if ($convert->mysql_convert && $same_db) {
                             $src_db->sql_query("SET NAMES 'utf8'");
                         }
                     } else {
                         $db->sql_query($query_first[1]);
                     }
                 }
             }
             if (!empty($schema['autoincrement'])) {
                 switch ($db->get_sql_layer()) {
                     case 'postgres':
                         $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
                         break;
                     case 'oracle':
                         $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
                         $row = $db->sql_fetchrow($result);
                         $db->sql_freeresult($result);
                         $largest_id = (int) $row['max_id'];
                         if ($largest_id) {
                             $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
                             $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
                         }
                         break;
                 }
             }
         }
         // Process execute_always for this table
         // This is for code which needs to be executed on every pass of this table if
         // it gets split because of time restrictions
         if (!empty($schema['execute_always'])) {
             // @codingStandardsIgnoreStart
             eval($schema['execute_always']);
             // @codingStandardsIgnoreEnd
         }
         //
         // Set up some variables
         //
         // $waiting_rows	holds rows for multirows insertion (MySQL only)
         // $src_tables		holds unique tables with aliases to select from
         // $src_fields		will quickly refer source fields (or aliases) corresponding to the current index
         // $select_fields	holds the names of the fields to retrieve
         //
         $sql_data = array('source_fields' => array(), 'target_fields' => array(), 'source_tables' => array(), 'select_fields' => array());
         // This statement is building the keys for later insertion.
         $insert_query = $this->build_insert_query($schema, $sql_data, $current_table);
         // If no source table is affected, we skip the table
         if (empty($sql_data['source_tables'])) {
             $skip_rows = 0;
             $current_table++;
             continue;
         }
         $distinct = !empty($schema['distinct']) ? 'DISTINCT ' : '';
         $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']);
         // Where
         $sql .= !empty($schema['where']) ? "\nWHERE (" . $schema['where'] . ')' : '';
         // Group By
         if (!empty($schema['group_by'])) {
             $schema['group_by'] = array($schema['group_by']);
             foreach ($sql_data['select_fields'] as $select) {
                 $alias = strpos(strtolower($select), ' as ');
                 $select = $alias ? substr($select, 0, $alias) : $select;
                 if (!in_array($select, $schema['group_by'])) {
                     $schema['group_by'][] = $select;
                 }
             }
         }
         $sql .= !empty($schema['group_by']) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : '';
         // Having
         $sql .= !empty($schema['having']) ? "\nHAVING " . $schema['having'] : '';
         // Order By
         if (empty($schema['order_by']) && !empty($schema['primary'])) {
             $schema['order_by'] = $schema['primary'];
         }
         $sql .= !empty($schema['order_by']) ? "\nORDER BY " . $schema['order_by'] : '';
         // Counting basically holds the amount of rows processed.
         $counting = -1;
         $batch_time = 0;
         while ($counting === -1 || $counting >= $convert->batch_size && still_on_time()) {
             $old_current_table = $current_table;
             $rows = '';
             $waiting_rows = array();
             if (!empty($batch_time)) {
                 $mtime = explode(' ', microtime());
                 $mtime = $mtime[0] + $mtime[1];
                 $rows = ceil($counting / ($mtime - $batch_time)) . " rows/s ({$counting} rows) | ";
             }
             $template->assign_block_vars('checks', array('TITLE' => "skip_rows = {$skip_rows}", 'RESULT' => $rows . (defined('DEBUG') && function_exists('memory_get_usage') ? ceil(memory_get_usage() / 1024) . ' ' . $user->lang['KIB'] : '')));
             $mtime = explode(' ', microtime());
             $batch_time = $mtime[0] + $mtime[1];
             if ($convert->mysql_convert && $same_db) {
                 $src_db->sql_query("SET NAMES 'binary'");
             }
             // Take skip rows into account and only fetch batch_size amount of rows
             $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows);
             if ($convert->mysql_convert && $same_db) {
                 $src_db->sql_query("SET NAMES 'utf8'");
             }
             // This loop processes each row
             $counting = 0;
             $convert->row = $convert_row = array();
             if (!empty($schema['autoincrement'])) {
                 switch ($db->get_sql_layer()) {
                     case 'mssql':
                     case 'mssql_odbc':
                     case 'mssqlnative':
                         $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON');
                         break;
                 }
             }
             // Now handle the rows until time is over or no more rows to process...
             while ($counting === 0 || still_on_time()) {
                 $convert_row = $src_db->sql_fetchrow($___result);
                 if (!$convert_row) {
                     // move to the next batch or table
                     break;
                 }
                 // With this we are able to always save the last state
                 $convert->row = $convert_row;
                 // Increment the counting variable, it stores the number of rows we have processed
                 $counting++;
                 $insert_values = array();
                 $sql_flag = $this->process_row($schema, $sql_data, $insert_values);
                 if ($sql_flag === true) {
                     switch ($db->get_sql_layer()) {
                         // If MySQL, we'll wait to have num_wait_rows rows to submit at once
                         case 'mysql':
                         case 'mysql4':
                         case 'mysqli':
                             $waiting_rows[] = '(' . implode(', ', $insert_values) . ')';
                             if (sizeof($waiting_rows) >= $convert->num_wait_rows) {
                                 $errored = false;
                                 $db->sql_return_on_error(true);
                                 if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) {
                                     $errored = true;
                                 }
                                 $db->sql_return_on_error(false);
                                 if ($errored) {
                                     $db->sql_return_on_error(true);
                                     // Because it errored out we will try to insert the rows one by one... most of the time this
                                     // is caused by duplicate entries - but we also do not want to miss one...
                                     foreach ($waiting_rows as $waiting_sql) {
                                         if (!$db->sql_query($insert_query . $waiting_sql)) {
                                             $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
                                         }
                                     }
                                     $db->sql_return_on_error(false);
                                 }
                                 $waiting_rows = array();
                             }
                             break;
                         default:
                             $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')';
                             $db->sql_return_on_error(true);
                             if (!$db->sql_query($insert_sql)) {
                                 $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
                             }
                             $db->sql_return_on_error(false);
                             $waiting_rows = array();
                             break;
                     }
                 }
                 $skip_rows++;
             }
             $src_db->sql_freeresult($___result);
             // We might still have some rows waiting
             if (sizeof($waiting_rows)) {
                 $errored = false;
                 $db->sql_return_on_error(true);
                 if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) {
                     $errored = true;
                 }
                 $db->sql_return_on_error(false);
                 if ($errored) {
                     $db->sql_return_on_error(true);
                     // Because it errored out we will try to insert the rows one by one... most of the time this
                     // is caused by duplicate entries - but we also do not want to miss one...
                     foreach ($waiting_rows as $waiting_sql) {
                         $db->sql_query($insert_query . $waiting_sql);
                         $this->p_master->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true);
                     }
                     $db->sql_return_on_error(false);
                 }
                 $waiting_rows = array();
             }
             if (!empty($schema['autoincrement'])) {
                 switch ($db->get_sql_layer()) {
                     case 'mssql':
                     case 'mssql_odbc':
                     case 'mssqlnative':
                         $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF');
                         break;
                     case 'postgres':
                         $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));');
                         break;
                     case 'oracle':
                         $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']);
                         $row = $db->sql_fetchrow($result);
                         $db->sql_freeresult($result);
                         $largest_id = (int) $row['max_id'];
                         if ($largest_id) {
                             $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq');
                             $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1));
                         }
                         break;
                 }
             }
         }
         // When we reach this point, either the current table has been processed or we're running out of time.
         if (still_on_time() && $counting < $convert->batch_size) {
             $skip_rows = 0;
             $current_table++;
         } else {
             /*
             				if (still_on_time() && $counting < $convert->batch_size)
             				{
             					$skip_rows = 0;
             					$current_table++;
             				}*/
             // Looks like we ran out of time.
             $url = $this->save_convert_progress('&amp;current_table=' . $current_table . '&amp;skip_rows=' . $skip_rows);
             $current_table++;
             //				$percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows));
             $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema']));
             $template->assign_vars(array('L_MESSAGE' => $msg, 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], 'U_ACTION' => $url));
             $this->meta_refresh($url);
             return;
         }
     }
     // Process execute_last then we'll be done
     $url = $this->save_convert_progress('&amp;jump=1');
     $template->assign_vars(array('L_SUBMIT' => $user->lang['FINAL_STEP'], 'U_ACTION' => $url));
     $this->meta_refresh($url);
     return;
 }
/**
* Delete Attachments
*
* @param string $mode can be: post|message|topic|attach|user
* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
    global $db, $config, $phpbb_dispatcher;
    // 0 is as bad as an empty array
    if (empty($ids)) {
        return false;
    }
    if (is_array($ids)) {
        $ids = array_unique($ids);
        $ids = array_map('intval', $ids);
    } else {
        $ids = array((int) $ids);
    }
    $sql_where = '';
    switch ($mode) {
        case 'post':
        case 'message':
            $sql_id = 'post_msg_id';
            $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
            break;
        case 'topic':
            $sql_id = 'topic_id';
            break;
        case 'user':
            $sql_id = 'poster_id';
            break;
        case 'attach':
        default:
            $sql_id = 'attach_id';
            $mode = 'attach';
            break;
    }
    $post_ids = $message_ids = $topic_ids = $physical = array();
    /**
     * Perform additional actions before collecting data for attachment(s) deletion
     *
     * @event core.delete_attachments_collect_data_before
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars)));
    // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
    $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
        if ($resync && !$row['is_orphan']) {
            if (!$row['in_message']) {
                $post_ids[] = $row['post_msg_id'];
                $topic_ids[] = $row['topic_id'];
            } else {
                $message_ids[] = $row['post_msg_id'];
            }
        }
        $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
    }
    $db->sql_freeresult($result);
    /**
     * Perform additional actions before attachment(s) deletion
     *
     * @event core.delete_attachments_before
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_before', compact($vars)));
    // Delete attachments
    $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
		WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $db->sql_query($sql);
    $num_deleted = $db->sql_affectedrows();
    /**
     * Perform additional actions after attachment(s) deletion from the database
     *
     * @event core.delete_attachments_from_database_after
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @var	int		num_deleted		The number of deleted attachment(s) from the database
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', 'num_deleted');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars)));
    if (!$num_deleted) {
        return 0;
    }
    // Delete attachments from filesystem
    $space_removed = $files_removed = 0;
    foreach ($physical as $file_ary) {
        if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) {
            // Only non-orphaned files count to the file size
            $space_removed += $file_ary['filesize'];
            $files_removed++;
        }
        if ($file_ary['thumbnail']) {
            phpbb_unlink($file_ary['filename'], 'thumbnail', true);
        }
    }
    /**
     * Perform additional actions after attachment(s) deletion from the filesystem
     *
     * @event core.delete_attachments_from_filesystem_after
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @var	int		num_deleted		The number of deleted attachment(s) from the database
     * @var	int		space_removed	The size of deleted files(s) from the filesystem
     * @var	int		files_removed	The number of deleted file(s) from the filesystem
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', 'num_deleted', 'space_removed', 'files_removed');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars)));
    if ($space_removed || $files_removed) {
        set_config_count('upload_dir_size', $space_removed * -1, true);
        set_config_count('num_files', $files_removed * -1, true);
    }
    // If we do not resync, we do not need to adjust any message, post, topic or user entries
    if (!$resync) {
        return $num_deleted;
    }
    // No more use for the original ids
    unset($ids);
    // Now, we need to resync posts, messages, topics. We go through every one of them
    $post_ids = array_unique($post_ids);
    $message_ids = array_unique($message_ids);
    $topic_ids = array_unique($topic_ids);
    // Update post indicators for posts now no longer having attachments
    if (sizeof($post_ids)) {
        // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table
        $sql = 'SELECT post_msg_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
				AND in_message = 0
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['post_msg_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $post_ids = array_diff($post_ids, $remaining_ids);
        if (sizeof($post_ids)) {
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET post_attachment = 0
				WHERE ' . $db->sql_in_set('post_id', $post_ids);
            $db->sql_query($sql);
        }
    }
    // Update message table if messages are affected
    if (sizeof($message_ids)) {
        // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table
        $sql = 'SELECT post_msg_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . '
				AND in_message = 1
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['post_msg_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $message_ids = array_diff($message_ids, $remaining_ids);
        if (sizeof($message_ids)) {
            $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
				SET message_attachment = 0
				WHERE ' . $db->sql_in_set('msg_id', $message_ids);
            $db->sql_query($sql);
        }
    }
    // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
    if (sizeof($topic_ids)) {
        // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected)
        $sql = 'SELECT topic_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['topic_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $topic_ids = array_diff($topic_ids, $remaining_ids);
        if (sizeof($topic_ids)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
            $db->sql_query($sql);
        }
    }
    return $num_deleted;
}
    function add_cur_topic()
    {
        global $db, $auth, $user, $config, $phpbb_root_path, $phpEx;
        $topic_elm = $this->topic_list[$this->topic_num];
        $forum_name = (string) $topic_elm['forum-name'];
        $forum_data =& $this->forum_ary[$forum_name];
        $forum_id = $forum_data['forum_id'];
        $post_count = $auth->acl_get('f_postcount', $forum_id) ? 1 : 0;
        // Get first post data
        $forum_time = $topic_elm->message[0]['date'];
        $poster_name = (string) $topic_elm->message[0]['by'];
        $poster_data =& $this->poster_ary[$poster_name];
        if ($poster_data === false || !is_numeric($poster_data['user_id'])) {
            $poster_data = array('user_id' => ANONYMOUS, 'username' => '', 'colour' => '');
            $poster_name = '';
        }
        $db->sql_transaction('begin');
        // Create the topic
        $sql_data = array('topic_poster' => $poster_data['user_id'], 'topic_time' => $forum_time, 'topic_last_view_time' => $forum_time, 'topic_last_post_time' => $forum_time, 'forum_id' => $forum_id, 'topic_title' => (string) $topic_elm['title'], 'topic_first_poster_name' => $poster_name, 'topic_first_poster_colour' => $poster_data['colour'], 'topic_type' => POST_NORMAL, 'topic_visibility' => 1);
        $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data);
        $db->sql_query($sql);
        $topic_id = $db->sql_nextid();
        unset($sql_data);
        if (isset($topic_elm['oldtopicno'])) {
            // Create the topic old number
            $sql_data = array('oldpostid' => (int) $topic_elm['oldtopicno'], 'newpostid' => $topic_id);
            $sql = 'INSERT INTO phpbb_posts_convert ' . $db->sql_build_array('INSERT', $sql_data);
            $db->sql_query($sql);
            unset($sql_data);
        }
        // Add the topic posts
        foreach ($topic_elm as $msg_index => $msg_data) {
            $msg_date = $msg_data['date'];
            $poster_name = (string) $msg_data['by'];
            $poster_data =& $this->poster_ary[$poster_name];
            if ($poster_data === false || !is_numeric($poster_data['user_id'])) {
                $poster_data = array('user_id' => ANONYMOUS, 'username' => '', 'colour' => '');
                $poster_name = '';
            }
            $sql_data = array('topic_id' => $topic_id, 'forum_id' => $forum_id, 'poster_id' => $poster_data['user_id'], 'poster_ip' => (string) $msg_data['ip'], 'post_time' => $msg_date, 'enable_bbcode' => $msg_data['bbcode'], 'enable_smilies' => $msg_data['smiley'], 'enable_magic_url' => $msg_data['magic-url'], 'enable_sig' => $msg_data['signature'], 'post_username' => $poster_name, 'post_subject' => (string) $msg_data['title'], 'post_text' => (string) $msg_data[0], 'post_checksum' => md5((string) $msg_data[0]), 'bbcode_bitfield' => (string) $msg_data['bbcode_bitfield'], 'bbcode_uid' => (string) $msg_data['bbcode_uid'], 'post_postcount' => $post_count, 'post_edit_locked' => 0, 'post_visibility' => 1);
            $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data);
            $db->sql_query($sql);
            $msg_id = $db->sql_nextid();
            if ($msg_index == 0) {
                $first_msg_id = $msg_id;
            }
            // Update user data to take into account this post
            if ($poster_data['user_id'] != ANONYMOUS) {
                if ($post_count) {
                    if (isset($poster_data['post'])) {
                        $poster_data['post'] = 1;
                    } else {
                        ++$poster_data['post'];
                    }
                }
                if ($msg_date > $poster_data['lastpost_time']) {
                    $poster_data['lastpost_time'] = $msg_date;
                    $poster_data['time_updated'] = true;
                }
            }
            // If the forum indexing is enable, index this message
            if ($forum_data['enable_indexing'] && !$this->indexing_failed) {
                if (!$this->indexing_initialized) {
                    // Select the search method and do some additional checks to ensure it can actually be utilised
                    $search_type = basename($config['search_type']);
                    if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) {
                        $this->errors[] = $user->lang['NO_SUCH_SEARCH_MODULE'] . ' (' . $phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx . ')';
                        $this->indexing_failed = true;
                    } else {
                        if (!class_exists($search_type)) {
                            include "{$phpbb_root_path}includes/search/{$search_type}.{$phpEx}";
                        }
                        $error = false;
                        $this->search = new $search_type($error);
                        if ($error) {
                            $this->errors[] = $error;
                            $this->indexing_failed = true;
                        } else {
                            $this->indexing_initialized = true;
                        }
                    }
                }
                if ($this->indexing_initialized) {
                    $this->search->index($msg_index == 0 ? 'post' : 'reply', $msg_id, $msg_data[0], $msg_data['title'], $poster_data['user_id'], $forum_id);
                }
            }
        }
        // Store last post data in topic
        $post_count = sizeof($topic_elm);
        $sql_data = array('topic_first_post_id' => $first_msg_id, 'topic_last_post_id' => $msg_id, 'topic_last_post_time' => $msg_date, 'topic_last_view_time' => $msg_date, 'topic_last_poster_id' => $poster_data['user_id'], 'topic_last_poster_name' => $poster_name, 'topic_last_poster_colour' => (string) $poster_data['colour'], 'topic_last_post_subject' => (string) $msg_data['title'], 'topic_posts_approved' => $post_count);
        $sql = 'UPDATE ' . TOPICS_TABLE . '
			SET ' . $db->sql_build_array('UPDATE', $sql_data) . '
			WHERE topic_id = ' . $topic_id;
        $db->sql_query($sql);
        // Update users stat
        $sql_data = array();
        foreach ($this->user_ary as &$user_data) {
            if ($user_data['post'] > 0) {
                $sql_data[] = 'user_posts = user_posts + ' . $user_data['post'];
                $user_data['post'] = 0;
            }
            if ($user_data['time_updated']) {
                $sql_data[] = 'user_lastpost_time = greatest(user_lastpost_time, ' . $user_data['lastpost_time'] . ')';
                $user_data['time_updated'] = false;
            }
            if ($sql_data) {
                $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . implode(', ', $sql_data) . ' WHERE user_id = ' . $user_data['user_id'];
                $db->sql_query($sql);
                $sql_data = array();
            }
        }
        // Update global topic and post count
        set_config_count('num_topics', 1, true);
        set_config_count('num_posts', $post_count, true);
        sync('forum', 'forum_id', array($forum_id), true, true);
        $db->sql_transaction('commit');
    }
示例#16
0
/**
* Flips user_type from active to inactive and vice versa, handles group membership updates
*
* @param string $mode can be flip for flipping from active/inactive, activate or deactivate
*/
function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL)
{
    global $config, $db, $user, $auth, $phpbb_dispatcher;
    $deactivated = $activated = 0;
    $sql_statements = array();
    if (!is_array($user_id_ary)) {
        $user_id_ary = array($user_id_ary);
    }
    if (!sizeof($user_id_ary)) {
        return;
    }
    $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason
		FROM ' . USERS_TABLE . '
		WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        $sql_ary = array();
        if ($row['user_type'] == USER_IGNORE || $row['user_type'] == USER_FOUNDER || $mode == 'activate' && $row['user_type'] != USER_INACTIVE || $mode == 'deactivate' && $row['user_type'] == USER_INACTIVE) {
            continue;
        }
        if ($row['user_type'] == USER_INACTIVE) {
            $activated++;
        } else {
            $deactivated++;
            // Remove the users session key...
            $user->reset_login_keys($row['user_id']);
        }
        $sql_ary += array('user_type' => $row['user_type'] == USER_NORMAL ? USER_INACTIVE : USER_NORMAL, 'user_inactive_time' => $row['user_type'] == USER_NORMAL ? time() : 0, 'user_inactive_reason' => $row['user_type'] == USER_NORMAL ? $reason : 0);
        $sql_statements[$row['user_id']] = $sql_ary;
    }
    $db->sql_freeresult($result);
    /**
     * Check or modify activated/deactivated users data before submitting it to the database
     *
     * @event core.user_active_flip_before
     * @var	string	mode			User type changing mode, can be: flip|activate|deactivate
     * @var	int		reason			Reason for changing user type, can be: INACTIVE_REGISTER|INACTIVE_PROFILE|INACTIVE_MANUAL|INACTIVE_REMIND
     * @var	int		activated		The number of users to be activated
     * @var	int		deactivated		The number of users to be deactivated
     * @var	array	user_id_ary		Array with user ids to change user type
     * @var	array	sql_statements	Array with users data to submit to the database, keys: user ids, values: arrays with user data
     * @since 3.1.4-RC1
     */
    $vars = array('mode', 'reason', 'activated', 'deactivated', 'user_id_ary', 'sql_statements');
    extract($phpbb_dispatcher->trigger_event('core.user_active_flip_before', compact($vars)));
    if (sizeof($sql_statements)) {
        foreach ($sql_statements as $user_id => $sql_ary) {
            $sql = 'UPDATE ' . USERS_TABLE . '
				SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
				WHERE user_id = ' . $user_id;
            $db->sql_query($sql);
        }
        $auth->acl_clear_prefetch(array_keys($sql_statements));
    }
    /**
     * Perform additional actions after the users have been activated/deactivated
     *
     * @event core.user_active_flip_after
     * @var	string	mode			User type changing mode, can be: flip|activate|deactivate
     * @var	int		reason			Reason for changing user type, can be: INACTIVE_REGISTER|INACTIVE_PROFILE|INACTIVE_MANUAL|INACTIVE_REMIND
     * @var	int		activated		The number of users to be activated
     * @var	int		deactivated		The number of users to be deactivated
     * @var	array	user_id_ary		Array with user ids to change user type
     * @var	array	sql_statements	Array with users data to submit to the database, keys: user ids, values: arrays with user data
     * @since 3.1.4-RC1
     */
    $vars = array('mode', 'reason', 'activated', 'deactivated', 'user_id_ary', 'sql_statements');
    extract($phpbb_dispatcher->trigger_event('core.user_active_flip_after', compact($vars)));
    if ($deactivated) {
        set_config_count('num_users', $deactivated * -1, true);
    }
    if ($activated) {
        set_config_count('num_users', $activated, true);
    }
    // Update latest username
    update_last_username();
}
示例#17
0
 /**
  * Sends an email to the board administrator with their password and some useful links
  */
 function email_admin($mode, $sub)
 {
     global $auth, $config, $db, $lang, $template, $user, $phpbb_root_path, $phpbb_admin_path, $phpEx;
     $this->page_title = $lang['STAGE_FINAL'];
     // Obtain any submitted data
     $data = $this->get_submitted_data();
     // We need to fill the config to let internal functions correctly work
     $config = new \phpbb\config\db($db, new \phpbb\cache\driver\null(), CONFIG_TABLE);
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     $user->session_begin();
     $auth->login($data['admin_name'], $data['admin_pass1'], false, true, true);
     // OK, Now that we've reached this point we can be confident that everything
     // is installed and working......I hope :)
     // So it's time to send an email to the administrator confirming the details
     // they entered
     if ($config['email_enable']) {
         include_once $phpbb_root_path . 'includes/functions_messenger.' . $phpEx;
         $messenger = new messenger(false);
         $messenger->template('installed', $data['language']);
         $messenger->to($data['board_email'], $data['admin_name']);
         $messenger->anti_abuse_headers($config, $user);
         $messenger->assign_vars(array('USERNAME' => htmlspecialchars_decode($data['admin_name']), 'PASSWORD' => htmlspecialchars_decode($data['admin_pass1'])));
         $messenger->send(NOTIFY_EMAIL);
     }
     // And finally, add a note to the log
     add_log('admin', 'LOG_INSTALL_INSTALLED', $config['version']);
     $template->assign_vars(array('TITLE' => $lang['INSTALL_CONGRATS'], 'BODY' => sprintf($lang['INSTALL_CONGRATS_EXPLAIN'], $config['version'], append_sid($phpbb_root_path . 'install/index.' . $phpEx, 'mode=convert&amp;language=' . $data['language']), '../docs/README.html'), 'L_SUBMIT' => $lang['INSTALL_LOGIN'], 'U_ACTION' => append_sid($phpbb_admin_path . 'index.' . $phpEx, 'i=send_statistics&amp;mode=send_statistics')));
 }
示例#18
0
文件: mcp_queue.php 项目: html/PI
/**
* Approve Post/Topic
*/
function approve_post($post_id_list, $id, $mode)
{
    global $db, $template, $user, $config;
    global $phpEx, $phpbb_root_path;
    if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) {
        trigger_error('NOT_AUTHORISED');
    }
    $redirect = request_var('redirect', build_url(array('quickmod')));
    $success_msg = '';
    $s_hidden_fields = build_hidden_fields(array('i' => $id, 'mode' => $mode, 'post_id_list' => $post_id_list, 'action' => 'approve', 'redirect' => $redirect));
    $post_info = get_post_data($post_id_list, 'm_approve');
    if (confirm_box(true)) {
        $notify_poster = isset($_REQUEST['notify_poster']) ? true : false;
        // If Topic -> total_topics = total_topics+1, total_posts = total_posts+1, forum_topics = forum_topics+1, forum_posts = forum_posts+1
        // If Post -> total_posts = total_posts+1, forum_posts = forum_posts+1, topic_replies = topic_replies+1
        $total_topics = $total_posts = 0;
        $forum_topics_posts = $topic_approve_sql = $topic_replies_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array();
        $user_posts_sql = $post_approved_list = array();
        $update_forum_information = false;
        foreach ($post_info as $post_id => $post_data) {
            if ($post_data['post_approved']) {
                $post_approved_list[] = $post_id;
                continue;
            }
            $topic_id_list[$post_data['topic_id']] = 1;
            if ($post_data['forum_id']) {
                $forum_id_list[$post_data['forum_id']] = 1;
            }
            // User post update (we do not care about topic or post, since user posts are strictly connected to posts)
            // But we care about forums where post counts get not increased. ;)
            if ($post_data['post_postcount']) {
                $user_posts_sql[$post_data['poster_id']] = empty($user_posts_sql[$post_data['poster_id']]) ? 1 : $user_posts_sql[$post_data['poster_id']] + 1;
            }
            // Topic or Post. ;)
            if ($post_data['topic_first_post_id'] == $post_id) {
                if ($post_data['forum_id']) {
                    if (!isset($forum_topics_posts[$post_data['forum_id']])) {
                        $forum_topics_posts[$post_data['forum_id']] = array('forum_posts' => 0, 'forum_topics' => 0);
                    }
                    $total_topics++;
                    $forum_topics_posts[$post_data['forum_id']]['forum_topics']++;
                }
                $topic_approve_sql[] = $post_data['topic_id'];
                $approve_log[] = array('type' => 'topic', 'post_subject' => $post_data['post_subject'], 'forum_id' => $post_data['forum_id'], 'topic_id' => $post_data['topic_id']);
            } else {
                $approve_log[] = array('type' => 'post', 'post_subject' => $post_data['post_subject'], 'forum_id' => $post_data['forum_id'], 'topic_id' => $post_data['topic_id']);
            }
            if ($post_data['topic_replies_real'] > 0) {
                if (!isset($topic_replies_sql[$post_data['topic_id']])) {
                    $topic_replies_sql[$post_data['topic_id']] = 0;
                }
                $topic_replies_sql[$post_data['topic_id']]++;
            }
            if ($post_data['forum_id']) {
                if (!isset($forum_topics_posts[$post_data['forum_id']])) {
                    $forum_topics_posts[$post_data['forum_id']] = array('forum_posts' => 0, 'forum_topics' => 0);
                }
                $total_posts++;
                $forum_topics_posts[$post_data['forum_id']]['forum_posts']++;
                // Increment by topic_replies if we approve a topic...
                // This works because we do not adjust the topic_replies when re-approving a topic after an edit.
                if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_replies']) {
                    $total_posts += $post_data['topic_replies'];
                    $forum_topics_posts[$post_data['forum_id']]['forum_posts'] += $post_data['topic_replies'];
                }
            }
            $post_approve_sql[] = $post_id;
            // If the post is newer than the last post information stored we need to update the forum information
            if ($post_data['post_time'] >= $post_data['forum_last_post_time']) {
                $update_forum_information = true;
            }
        }
        $post_id_list = array_values(array_diff($post_id_list, $post_approved_list));
        for ($i = 0, $size = sizeof($post_approved_list); $i < $size; $i++) {
            unset($post_info[$post_approved_list[$i]]);
        }
        if (sizeof($topic_approve_sql)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_approved = 1
				WHERE ' . $db->sql_in_set('topic_id', $topic_approve_sql);
            $db->sql_query($sql);
        }
        if (sizeof($post_approve_sql)) {
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET post_approved = 1
				WHERE ' . $db->sql_in_set('post_id', $post_approve_sql);
            $db->sql_query($sql);
        }
        foreach ($approve_log as $log_data) {
            add_log('mod', $log_data['forum_id'], $log_data['topic_id'], $log_data['type'] == 'topic' ? 'LOG_TOPIC_APPROVED' : 'LOG_POST_APPROVED', $log_data['post_subject']);
        }
        if (sizeof($topic_replies_sql)) {
            foreach ($topic_replies_sql as $topic_id => $num_replies) {
                $sql = 'UPDATE ' . TOPICS_TABLE . "\n\t\t\t\t\tSET topic_replies = topic_replies + {$num_replies}\n\t\t\t\t\tWHERE topic_id = {$topic_id}";
                $db->sql_query($sql);
            }
        }
        if (sizeof($forum_topics_posts)) {
            foreach ($forum_topics_posts as $forum_id => $row) {
                $sql = 'UPDATE ' . FORUMS_TABLE . '
					SET ';
                $sql .= $row['forum_topics'] ? "forum_topics = forum_topics + {$row['forum_topics']}" : '';
                $sql .= $row['forum_topics'] && $row['forum_posts'] ? ', ' : '';
                $sql .= $row['forum_posts'] ? "forum_posts = forum_posts + {$row['forum_posts']}" : '';
                $sql .= " WHERE forum_id = {$forum_id}";
                $db->sql_query($sql);
            }
        }
        if (sizeof($user_posts_sql)) {
            // Try to minimize the query count by merging users with the same post count additions
            $user_posts_update = array();
            foreach ($user_posts_sql as $user_id => $user_posts) {
                $user_posts_update[$user_posts][] = $user_id;
            }
            foreach ($user_posts_update as $user_posts => $user_id_ary) {
                $sql = 'UPDATE ' . USERS_TABLE . '
					SET user_posts = user_posts + ' . $user_posts . '
					WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
                $db->sql_query($sql);
            }
        }
        if ($total_topics) {
            set_config_count('num_topics', $total_topics, true);
        }
        if ($total_posts) {
            set_config_count('num_posts', $total_posts, true);
        }
        unset($topic_approve_sql, $topic_replies_sql, $post_approve_sql);
        update_post_information('topic', array_keys($topic_id_list));
        if ($update_forum_information) {
            update_post_information('forum', array_keys($forum_id_list));
        }
        unset($topic_id_list, $forum_id_list);
        $messenger = new messenger();
        // Notify Poster?
        if ($notify_poster) {
            foreach ($post_info as $post_id => $post_data) {
                if ($post_data['poster_id'] == ANONYMOUS) {
                    continue;
                }
                $email_template = $post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id'] ? 'topic_approved' : 'post_approved';
                $messenger->template($email_template, $post_data['user_lang']);
                $messenger->to($post_data['user_email'], $post_data['username']);
                $messenger->im($post_data['user_jabber'], $post_data['username']);
                $messenger->assign_vars(array('USERNAME' => htmlspecialchars_decode($post_data['username']), 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])), 'U_VIEW_TOPIC' => generate_board_url() . "/viewtopic.{$phpEx}?f={$post_data['forum_id']}&t={$post_data['topic_id']}&e=0", 'U_VIEW_POST' => generate_board_url() . "/viewtopic.{$phpEx}?f={$post_data['forum_id']}&t={$post_data['topic_id']}&p={$post_id}&e={$post_id}"));
                $messenger->send($post_data['user_notify_type']);
            }
        }
        $messenger->save_queue();
        // Send out normal user notifications
        $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']);
        foreach ($post_info as $post_id => $post_data) {
            if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) {
                // Forum Notifications
                user_notification('post', $post_data['topic_title'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id);
            } else {
                // Topic Notifications
                user_notification('reply', $post_data['post_subject'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id);
            }
        }
        if (sizeof($post_id_list) == 1) {
            $post_data = $post_info[$post_id_list[0]];
            $post_url = append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", "f={$post_data['forum_id']}&amp;t={$post_data['topic_id']}&amp;p={$post_data['post_id']}") . '#p' . $post_data['post_id'];
        }
        unset($post_info);
        if ($total_topics) {
            $success_msg = $total_topics == 1 ? 'TOPIC_APPROVED_SUCCESS' : 'TOPICS_APPROVED_SUCCESS';
        } else {
            $success_msg = sizeof($post_id_list) + sizeof($post_approved_list) == 1 ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS';
        }
    } else {
        $show_notify = false;
        foreach ($post_info as $post_data) {
            if ($post_data['poster_id'] == ANONYMOUS) {
                continue;
            } else {
                $show_notify = true;
                break;
            }
        }
        $template->assign_vars(array('S_NOTIFY_POSTER' => $show_notify, 'S_APPROVE' => true));
        confirm_box(false, 'APPROVE_POST' . (sizeof($post_id_list) == 1 ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html');
    }
    $redirect = request_var('redirect', "index.{$phpEx}");
    $redirect = reapply_sid($redirect);
    if (!$success_msg) {
        redirect($redirect);
    } else {
        meta_refresh(3, $redirect);
        // If approving one post, also give links back to post...
        $add_message = '';
        if (sizeof($post_id_list) == 1 && !empty($post_url)) {
            $add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>');
        }
        trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"{$redirect}\">", '</a>') . $add_message);
    }
}
 /**
  * Creates a new user with limited permissions
  *
  * @param string $username Also doubles up as the user's password
  * @return int ID of created user
  */
 protected function create_user($username)
 {
     // Required by unique_id
     global $config;
     $config = new \phpbb\config\config(array());
     /*
      * Add required config entries to the config array to prevent
      * set_config() sending an INSERT query for already existing entries,
      * resulting in a SQL error.
      * This is because set_config() first sends an UPDATE query, then checks
      * sql_affectedrows() which can be 0 (e.g. on MySQL) when the new
      * data is already there.
      */
     $config['newest_user_colour'] = '';
     $config['rand_seed'] = '';
     $config['rand_seed_last_update'] = time() + 600;
     // Required by user_add
     global $db, $cache, $phpbb_dispatcher, $phpbb_container;
     $db = $this->get_db();
     if (!function_exists('phpbb_mock_null_cache')) {
         require_once __DIR__ . '/../mock/null_cache.php';
     }
     $cache = new phpbb_mock_null_cache();
     $cache_driver = new \phpbb\cache\driver\null();
     $phpbb_container = new phpbb_mock_container_builder();
     $phpbb_container->set('cache.driver', $cache_driver);
     $phpbb_notifications = new phpbb_mock_notification_manager();
     $phpbb_container->set('notification_manager', $phpbb_notifications);
     if (!function_exists('utf_clean_string')) {
         require_once __DIR__ . '/../../phpBB/includes/utf/utf_tools.php';
     }
     if (!function_exists('user_add')) {
         require_once __DIR__ . '/../../phpBB/includes/functions_user.php';
     }
     set_config(null, null, null, $config);
     set_config_count(null, null, null, $config);
     $phpbb_dispatcher = new phpbb_mock_event_dispatcher();
     $passwords_manager = $this->get_passwords_manager();
     $user_row = array('username' => $username, 'group_id' => 2, 'user_email' => '*****@*****.**', 'user_type' => 0, 'user_lang' => 'en', 'user_timezone' => 'UTC', 'user_dateformat' => 'r', 'user_password' => $passwords_manager->hash($username . $username));
     return user_add($user_row);
 }
示例#20
0
/**
* Delete Attachments
*
* @param string $mode can be: post|message|topic|attach|user
* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
    global $db, $config;
    if (is_array($ids) && sizeof($ids)) {
        $ids = array_unique($ids);
        $ids = array_map('intval', $ids);
    } else {
        $ids = array((int) $ids);
    }
    if (!sizeof($ids)) {
        return false;
    }
    $sql_where = '';
    switch ($mode) {
        case 'post':
        case 'message':
            $sql_id = 'post_msg_id';
            $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
            break;
        case 'topic':
            $sql_id = 'topic_id';
            break;
        case 'user':
            $sql_id = 'poster_id';
            break;
        case 'attach':
        default:
            $sql_id = 'attach_id';
            $mode = 'attach';
            break;
    }
    $post_ids = $message_ids = $topic_ids = $physical = array();
    // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
    $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
        if ($resync && !$row['is_orphan']) {
            if (!$row['in_message']) {
                $post_ids[] = $row['post_msg_id'];
                $topic_ids[] = $row['topic_id'];
            } else {
                $message_ids[] = $row['post_msg_id'];
            }
        }
        $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
    }
    $db->sql_freeresult($result);
    // Delete attachments
    $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
		WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $db->sql_query($sql);
    $num_deleted = $db->sql_affectedrows();
    if (!$num_deleted) {
        return 0;
    }
    // Delete attachments from filesystem
    $space_removed = $files_removed = 0;
    foreach ($physical as $file_ary) {
        if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) {
            // Only non-orphaned files count to the file size
            $space_removed += $file_ary['filesize'];
            $files_removed++;
        }
        if ($file_ary['thumbnail']) {
            phpbb_unlink($file_ary['filename'], 'thumbnail', true);
        }
    }
    if ($space_removed || $files_removed) {
        set_config_count('upload_dir_size', $space_removed * -1, true);
        set_config_count('num_files', $files_removed * -1, true);
    }
    // If we do not resync, we do not need to adjust any message, post, topic or user entries
    if (!$resync) {
        return $num_deleted;
    }
    // No more use for the original ids
    unset($ids);
    // Now, we need to resync posts, messages, topics. We go through every one of them
    $post_ids = array_unique($post_ids);
    $message_ids = array_unique($message_ids);
    $topic_ids = array_unique($topic_ids);
    // Update post indicators for posts now no longer having attachments
    if (sizeof($post_ids)) {
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET post_attachment = 0
			WHERE ' . $db->sql_in_set('post_id', $post_ids);
        $db->sql_query($sql);
    }
    // Update message table if messages are affected
    if (sizeof($message_ids)) {
        $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
			SET message_attachment = 0
			WHERE ' . $db->sql_in_set('msg_id', $message_ids);
        $db->sql_query($sql);
    }
    // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
    if (sizeof($topic_ids)) {
        // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected)
        $sql = 'SELECT topic_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['topic_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $topic_ids = array_diff($topic_ids, $remaining_ids);
        if (sizeof($topic_ids)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
            $db->sql_query($sql);
        }
    }
    return $num_deleted;
}
示例#21
0
    function main($id, $mode)
    {
        global $db, $user, $auth, $template, $cache;
        global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
        $user->add_lang(array('posting', 'viewtopic', 'acp/attachments'));
        $error = $notify = array();
        $submit = isset($_POST['submit']) ? true : false;
        $action = request_var('action', '');
        $form_key = 'acp_attach';
        add_form_key($form_key);
        if ($submit && !check_form_key($form_key)) {
            trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
        }
        switch ($mode) {
            case 'attach':
                $l_title = 'ACP_ATTACHMENT_SETTINGS';
                break;
            case 'extensions':
                $l_title = 'ACP_MANAGE_EXTENSIONS';
                break;
            case 'ext_groups':
                $l_title = 'ACP_EXTENSION_GROUPS';
                break;
            case 'orphan':
                $l_title = 'ACP_ORPHAN_ATTACHMENTS';
                break;
            default:
                trigger_error('NO_MODE', E_USER_ERROR);
                break;
        }
        $this->tpl_name = 'acp_attachments';
        $this->page_title = $l_title;
        $template->assign_vars(array('L_TITLE' => $user->lang[$l_title], 'L_TITLE_EXPLAIN' => $user->lang[$l_title . '_EXPLAIN'], 'U_ACTION' => $this->u_action));
        switch ($mode) {
            case 'attach':
                include_once $phpbb_root_path . 'includes/functions_posting.' . $phpEx;
                $sql = 'SELECT group_name, cat_id
					FROM ' . EXTENSION_GROUPS_TABLE . '
					WHERE cat_id > 0
					ORDER BY cat_id';
                $result = $db->sql_query($sql);
                $s_assigned_groups = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $s_assigned_groups[$row['cat_id']][] = $row['group_name'];
                }
                $db->sql_freeresult($result);
                $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . (!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']';
                $display_vars = array('title' => 'ACP_ATTACHMENT_SETTINGS', 'vars' => array('legend1' => 'ACP_ATTACHMENT_SETTINGS', 'img_max_width' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_max_height' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_link_width' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_link_height' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'upload_path' => array('lang' => 'UPLOAD_DIR', 'validate' => 'wpath', 'type' => 'text:25:100', 'explain' => true), 'display_order' => array('lang' => 'DISPLAY_ORDER', 'validate' => 'bool', 'type' => 'custom', 'method' => 'display_order', 'explain' => true), 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true), 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'check_attachment_content' => array('lang' => 'CHECK_CONTENT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend2' => $l_legend_cat_images, 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), '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', 'type' => 'text:7:15', 'explain' => true, 'append' => ' px'), 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => '&nbsp;&nbsp;<span>[ <a href="' . $this->u_action . '&amp;action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px')));
                $this->new_config = $config;
                $cfg_array = isset($_REQUEST['config']) ? request_var('config', array('' => '')) : $this->new_config;
                $error = array();
                // We validate the complete config if whished
                validate_config_vars($display_vars['vars'], $cfg_array, $error);
                // Do not write values if there is an error
                if (sizeof($error)) {
                    $submit = false;
                }
                // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to...
                foreach ($display_vars['vars'] as $config_name => $null) {
                    if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) {
                        continue;
                    }
                    $this->new_config[$config_name] = $config_value = $cfg_array[$config_name];
                    if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm'))) {
                        $size_var = request_var($config_name, '');
                        $this->new_config[$config_name] = $config_value = $size_var == 'kb' ? round($config_value * 1024) : ($size_var == 'mb' ? round($config_value * 1048576) : $config_value);
                    }
                    if ($submit) {
                        set_config($config_name, $config_value);
                    }
                }
                $this->perform_site_list();
                if ($submit) {
                    add_log('admin', 'LOG_CONFIG_ATTACH');
                    // Check Settings
                    $this->test_upload($error, $this->new_config['upload_path'], false);
                    if (!sizeof($error)) {
                        trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
                    }
                }
                $template->assign_var('S_ATTACHMENT_SETTINGS', true);
                if ($action == 'imgmagick') {
                    $this->new_config['img_imagick'] = $this->search_imagemagick();
                }
                // We strip eventually manual added convert program, we only want the patch
                if ($this->new_config['img_imagick']) {
                    // Change path separator
                    $this->new_config['img_imagick'] = str_replace('\\', '/', $this->new_config['img_imagick']);
                    $this->new_config['img_imagick'] = str_replace(array('convert', '.exe'), array('', ''), $this->new_config['img_imagick']);
                    // Check for trailing slash
                    if (substr($this->new_config['img_imagick'], -1) !== '/') {
                        $this->new_config['img_imagick'] .= '/';
                    }
                }
                $supported_types = get_supported_image_types();
                // Check Thumbnail Support
                if (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) {
                    $this->new_config['img_create_thumbnail'] = 0;
                }
                $template->assign_vars(array('U_SEARCH_IMAGICK' => $this->u_action . '&amp;action=imgmagick', 'S_THUMBNAIL_SUPPORT' => !$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format'])) ? false : true));
                // Secure Download Options - Same procedure as with banning
                $allow_deny = $this->new_config['secure_allow_deny'] ? 'ALLOWED' : 'DISALLOWED';
                $sql = 'SELECT *
					FROM ' . SITELIST_TABLE;
                $result = $db->sql_query($sql);
                $defined_ips = '';
                $ips = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $value = $row['site_ip'] ? $row['site_ip'] : $row['site_hostname'];
                    if ($value) {
                        $defined_ips .= '<option' . ($row['ip_exclude'] ? ' class="sep"' : '') . ' value="' . $row['site_id'] . '">' . $value . '</option>';
                        $ips[$row['site_id']] = $value;
                    }
                }
                $db->sql_freeresult($result);
                $template->assign_vars(array('S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'], 'S_DEFINED_IPS' => $defined_ips != '' ? true : false, 'S_WARNING' => sizeof($error) ? true : false, 'WARNING_MSG' => implode('<br />', $error), 'DEFINED_IPS' => $defined_ips, 'L_SECURE_TITLE' => $user->lang['DEFINE_' . $allow_deny . '_IPS'], 'L_IP_EXCLUDE' => $user->lang['EXCLUDE_FROM_' . $allow_deny . '_IP'], 'L_REMOVE_IPS' => $user->lang['REMOVE_' . $allow_deny . '_IPS']));
                // Output relevant options
                foreach ($display_vars['vars'] as $config_key => $vars) {
                    if (!is_array($vars) && strpos($config_key, 'legend') === false) {
                        continue;
                    }
                    if (strpos($config_key, 'legend') !== false) {
                        $template->assign_block_vars('options', array('S_LEGEND' => true, 'LEGEND' => isset($user->lang[$vars]) ? $user->lang[$vars] : $vars));
                        continue;
                    }
                    $type = explode(':', $vars['type']);
                    $l_explain = '';
                    if ($vars['explain'] && isset($vars['lang_explain'])) {
                        $l_explain = isset($user->lang[$vars['lang_explain']]) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain'];
                    } else {
                        if ($vars['explain']) {
                            $l_explain = isset($user->lang[$vars['lang'] . '_EXPLAIN']) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : '';
                        }
                    }
                    $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars);
                    if (empty($content)) {
                        continue;
                    }
                    $template->assign_block_vars('options', array('KEY' => $config_key, 'TITLE' => $user->lang[$vars['lang']], 'S_EXPLAIN' => $vars['explain'], 'TITLE_EXPLAIN' => $l_explain, 'CONTENT' => $content));
                    unset($display_vars['vars'][$config_key]);
                }
                break;
            case 'extensions':
                if ($submit || isset($_POST['add_extension_check'])) {
                    if ($submit) {
                        // Change Extensions ?
                        $extension_change_list = request_var('extension_change_list', array(0));
                        $group_select_list = request_var('group_select', array(0));
                        // Generate correct Change List
                        $extensions = array();
                        for ($i = 0, $size = sizeof($extension_change_list); $i < $size; $i++) {
                            $extensions[$extension_change_list[$i]]['group_id'] = $group_select_list[$i];
                        }
                        $sql = 'SELECT *
							FROM ' . EXTENSIONS_TABLE . '
							ORDER BY extension_id';
                        $result = $db->sql_query($sql);
                        while ($row = $db->sql_fetchrow($result)) {
                            if ($row['group_id'] != $extensions[$row['extension_id']]['group_id']) {
                                $sql = 'UPDATE ' . EXTENSIONS_TABLE . '
									SET group_id = ' . (int) $extensions[$row['extension_id']]['group_id'] . '
									WHERE extension_id = ' . $row['extension_id'];
                                $db->sql_query($sql);
                                add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']);
                            }
                        }
                        $db->sql_freeresult($result);
                        // Delete Extension?
                        $extension_id_list = request_var('extension_id_list', array(0));
                        if (sizeof($extension_id_list)) {
                            $sql = 'SELECT extension
								FROM ' . EXTENSIONS_TABLE . '
								WHERE ' . $db->sql_in_set('extension_id', $extension_id_list);
                            $result = $db->sql_query($sql);
                            $extension_list = '';
                            while ($row = $db->sql_fetchrow($result)) {
                                $extension_list .= $extension_list == '' ? $row['extension'] : ', ' . $row['extension'];
                            }
                            $db->sql_freeresult($result);
                            $sql = 'DELETE
								FROM ' . EXTENSIONS_TABLE . '
								WHERE ' . $db->sql_in_set('extension_id', $extension_id_list);
                            $db->sql_query($sql);
                            add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list);
                        }
                    }
                    // Add Extension?
                    $add_extension = strtolower(request_var('add_extension', ''));
                    $add_extension_group = request_var('add_group_select', 0);
                    $add = isset($_POST['add_extension_check']) ? true : false;
                    if ($add_extension && $add) {
                        if (!sizeof($error)) {
                            $sql = 'SELECT extension_id
								FROM ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE extension = '" . $db->sql_escape($add_extension) . "'";
                            $result = $db->sql_query($sql);
                            if ($row = $db->sql_fetchrow($result)) {
                                $error[] = sprintf($user->lang['EXTENSION_EXIST'], $add_extension);
                            }
                            $db->sql_freeresult($result);
                            if (!sizeof($error)) {
                                $sql_ary = array('group_id' => $add_extension_group, 'extension' => $add_extension);
                                $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                                add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension);
                            }
                        }
                    }
                    if (!sizeof($error)) {
                        $notify[] = $user->lang['EXTENSIONS_UPDATED'];
                    }
                    $cache->destroy('_extensions');
                }
                $template->assign_vars(array('S_EXTENSIONS' => true, 'ADD_EXTENSION' => isset($add_extension) ? $add_extension : '', 'GROUP_SELECT_OPTIONS' => isset($_POST['add_extension_check']) ? $this->group_select('add_group_select', $add_extension_group, 'extension_group') : $this->group_select('add_group_select', false, 'extension_group')));
                $sql = 'SELECT *
					FROM ' . EXTENSIONS_TABLE . '
					ORDER BY group_id, extension';
                $result = $db->sql_query($sql);
                if ($row = $db->sql_fetchrow($result)) {
                    $old_group_id = $row['group_id'];
                    do {
                        $s_spacer = false;
                        $current_group_id = $row['group_id'];
                        if ($old_group_id != $current_group_id) {
                            $s_spacer = true;
                            $old_group_id = $current_group_id;
                        }
                        $template->assign_block_vars('extensions', array('S_SPACER' => $s_spacer, 'EXTENSION_ID' => $row['extension_id'], 'EXTENSION' => $row['extension'], 'GROUP_OPTIONS' => $this->group_select('group_select[]', $row['group_id'])));
                    } while ($row = $db->sql_fetchrow($result));
                }
                $db->sql_freeresult($result);
                break;
            case 'ext_groups':
                $template->assign_var('S_EXTENSION_GROUPS', true);
                if ($submit) {
                    $action = request_var('action', '');
                    $group_id = request_var('g', 0);
                    if ($action != 'add' && $action != 'edit') {
                        trigger_error('NO_MODE', E_USER_ERROR);
                    }
                    if (!$group_id && $action == 'edit') {
                        trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                    }
                    if ($group_id) {
                        $sql = 'SELECT *
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $result = $db->sql_query($sql);
                        $ext_row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        if (!$ext_row) {
                            trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                        }
                    } else {
                        $ext_row = array();
                    }
                    $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
                    $new_group_name = $action == 'add' ? $group_name : ($ext_row['group_name'] != $group_name ? $group_name : '');
                    if (!$group_name) {
                        $error[] = $user->lang['NO_EXT_GROUP_NAME'];
                    }
                    // Check New Group Name
                    if ($new_group_name) {
                        $sql = 'SELECT group_id
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($new_group_name)) . "'";
                        $result = $db->sql_query($sql);
                        if ($db->sql_fetchrow($result)) {
                            $error[] = sprintf($user->lang['EXTENSION_GROUP_EXIST'], $new_group_name);
                        }
                        $db->sql_freeresult($result);
                    }
                    if (!sizeof($error)) {
                        // Ok, build the update/insert array
                        $upload_icon = request_var('upload_icon', 'no_image');
                        $size_select = request_var('size_select', 'b');
                        $forum_select = request_var('forum_select', false);
                        $allowed_forums = request_var('allowed_forums', array(0));
                        $allow_in_pm = isset($_POST['allow_in_pm']) ? true : false;
                        $max_filesize = request_var('max_filesize', 0);
                        $max_filesize = $size_select == 'kb' ? round($max_filesize * 1024) : ($size_select == 'mb' ? round($max_filesize * 1048576) : $max_filesize);
                        $allow_group = isset($_POST['allow_group']) ? true : false;
                        if ($max_filesize == $config['max_filesize']) {
                            $max_filesize = 0;
                        }
                        if (!sizeof($allowed_forums)) {
                            $forum_select = false;
                        }
                        $group_ary = array('group_name' => $group_name, 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE), 'allow_group' => $allow_group ? 1 : 0, 'upload_icon' => $upload_icon == 'no_image' ? '' : $upload_icon, 'max_filesize' => $max_filesize, 'allowed_forums' => $forum_select ? serialize($allowed_forums) : '', 'allow_in_pm' => $allow_in_pm ? 1 : 0);
                        if ($action == 'add') {
                            $group_ary['download_mode'] = INLINE_LINK;
                        }
                        $sql = $action == 'add' ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET ';
                        $sql .= $db->sql_build_array($action == 'add' ? 'INSERT' : 'UPDATE', $group_ary);
                        $sql .= $action == 'edit' ? " WHERE group_id = {$group_id}" : '';
                        $db->sql_query($sql);
                        if ($action == 'add') {
                            $group_id = $db->sql_nextid();
                        }
                        add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name);
                    }
                    $extension_list = request_var('extensions', array(0));
                    if ($action == 'edit' && sizeof($extension_list)) {
                        $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tSET group_id = 0\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $db->sql_query($sql);
                    }
                    if (sizeof($extension_list)) {
                        $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tSET group_id = {$group_id}\n\t\t\t\t\t\t\tWHERE " . $db->sql_in_set('extension_id', $extension_list);
                        $db->sql_query($sql);
                    }
                    $cache->destroy('_extensions');
                    if (!sizeof($error)) {
                        $notify[] = $user->lang['SUCCESS_EXTENSION_GROUP_' . strtoupper($action)];
                    }
                }
                $cat_lang = array(ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES']);
                $group_id = request_var('g', 0);
                $action = isset($_POST['add']) ? 'add' : $action;
                switch ($action) {
                    case 'delete':
                        if (confirm_box(true)) {
                            $sql = 'SELECT group_name
								FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $result = $db->sql_query($sql);
                            $group_name = (string) $db->sql_fetchfield('group_name');
                            $db->sql_freeresult($result);
                            $sql = 'DELETE
								FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $db->sql_query($sql);
                            // Set corresponding Extensions to a pending Group
                            $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\t\tSET group_id = 0\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $db->sql_query($sql);
                            add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name);
                            $cache->destroy('_extensions');
                            trigger_error($user->lang['EXTENSION_GROUP_DELETED'] . adm_back_link($this->u_action));
                        } else {
                            confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array('i' => $id, 'mode' => $mode, 'group_id' => $group_id, 'action' => 'delete')));
                        }
                        break;
                    case 'edit':
                        if (!$group_id) {
                            trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                        }
                        $sql = 'SELECT *
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $result = $db->sql_query($sql);
                        $ext_group_row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        $forum_ids = !$ext_group_row['allowed_forums'] ? array() : unserialize(trim($ext_group_row['allowed_forums']));
                        // no break;
                    // no break;
                    case 'add':
                        if ($action == 'add') {
                            $ext_group_row = array('group_name' => utf8_normalize_nfc(request_var('group_name', '', true)), 'cat_id' => 0, 'allow_group' => 1, 'allow_in_pm' => 1, 'upload_icon' => '', 'max_filesize' => 0);
                            $forum_ids = array();
                        }
                        $extensions = array();
                        $sql = 'SELECT *
							FROM ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}\n\t\t\t\t\t\t\t\tOR group_id = 0\n\t\t\t\t\t\t\tORDER BY extension";
                        $result = $db->sql_query($sql);
                        $extensions = $db->sql_fetchrowset($result);
                        $db->sql_freeresult($result);
                        if ($ext_group_row['max_filesize'] == 0) {
                            $ext_group_row['max_filesize'] = (int) $config['max_filesize'];
                        }
                        $max_filesize = get_formatted_filesize($ext_group_row['max_filesize'], false, array('mb', 'kb', 'b'));
                        $size_format = $max_filesize['si_identifier'];
                        $ext_group_row['max_filesize'] = $max_filesize['value'];
                        $img_path = $config['upload_icons_path'];
                        $filename_list = '';
                        $no_image_select = false;
                        $imglist = filelist($phpbb_root_path . $img_path);
                        if (!empty($imglist[''])) {
                            $imglist = array_values($imglist);
                            $imglist = $imglist[0];
                            foreach ($imglist as $key => $img) {
                                if (!$ext_group_row['upload_icon']) {
                                    $no_image_select = true;
                                    $selected = '';
                                } else {
                                    $selected = $ext_group_row['upload_icon'] == $img ? ' selected="selected"' : '';
                                }
                                if (strlen($img) > 255) {
                                    continue;
                                }
                                $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>';
                            }
                        }
                        $i = 0;
                        $assigned_extensions = '';
                        foreach ($extensions as $num => $row) {
                            if ($row['group_id'] == $group_id && $group_id) {
                                $assigned_extensions .= $i ? ', ' . $row['extension'] : $row['extension'];
                                $i++;
                            }
                        }
                        $s_extension_options = '';
                        foreach ($extensions as $row) {
                            $s_extension_options .= '<option' . (!$row['group_id'] ? ' class="disabled"' : '') . ' value="' . $row['extension_id'] . '"' . ($row['group_id'] == $group_id && $group_id ? ' selected="selected"' : '') . '>' . $row['extension'] . '</option>';
                        }
                        $template->assign_vars(array('PHPBB_ROOT_PATH' => $phpbb_root_path, 'IMG_PATH' => $img_path, 'ACTION' => $action, 'GROUP_ID' => $group_id, 'GROUP_NAME' => $ext_group_row['group_name'], 'ALLOW_GROUP' => $ext_group_row['allow_group'], 'ALLOW_IN_PM' => $ext_group_row['allow_in_pm'], 'UPLOAD_ICON_SRC' => $phpbb_root_path . $img_path . '/' . $ext_group_row['upload_icon'], 'EXTGROUP_FILESIZE' => $ext_group_row['max_filesize'], 'ASSIGNED_EXTENSIONS' => $assigned_extensions, 'S_CATEGORY_SELECT' => $this->category_select('special_category', $group_id, 'category'), 'S_EXT_GROUP_SIZE_OPTIONS' => size_select_options($size_format), 'S_EXTENSION_OPTIONS' => $s_extension_options, 'S_FILENAME_LIST' => $filename_list, 'S_EDIT_GROUP' => true, 'S_NO_IMAGE' => $no_image_select, 'S_FORUM_IDS' => sizeof($forum_ids) ? true : false, 'U_EXTENSIONS' => append_sid("{$phpbb_admin_path}index.{$phpEx}", "i={$id}&amp;mode=extensions"), 'U_BACK' => $this->u_action, 'L_LEGEND' => $user->lang[strtoupper($action) . '_EXTENSION_GROUP']));
                        $s_forum_id_options = '';
                        /** @todo use in-built function **/
                        $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
							FROM ' . FORUMS_TABLE . '
							ORDER BY left_id ASC';
                        $result = $db->sql_query($sql, 600);
                        $right = $cat_right = $padding_inc = 0;
                        $padding = $forum_list = $holding = '';
                        $padding_store = array('0' => '');
                        while ($row = $db->sql_fetchrow($result)) {
                            if ($row['forum_type'] == FORUM_CAT && $row['left_id'] + 1 == $row['right_id']) {
                                // Non-postable forum with no subforums, don't display
                                continue;
                            }
                            if (!$auth->acl_get('f_list', $row['forum_id'])) {
                                // if the user does not have permissions to list this forum skip
                                continue;
                            }
                            if ($row['left_id'] < $right) {
                                $padding .= '&nbsp; &nbsp;';
                                $padding_store[$row['parent_id']] = $padding;
                            } else {
                                if ($row['left_id'] > $right + 1) {
                                    $padding = empty($padding_store[$row['parent_id']]) ? '' : $padding_store[$row['parent_id']];
                                }
                            }
                            $right = $row['right_id'];
                            $selected = in_array($row['forum_id'], $forum_ids) ? ' selected="selected"' : '';
                            if ($row['left_id'] > $cat_right) {
                                // make sure we don't forget anything
                                $s_forum_id_options .= $holding;
                                $holding = '';
                            }
                            if ($row['right_id'] - $row['left_id'] > 1) {
                                $cat_right = max($cat_right, $row['right_id']);
                                $holding .= '<option value="' . $row['forum_id'] . '"' . ($row['forum_type'] == FORUM_POST ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>';
                            } else {
                                $s_forum_id_options .= $holding . '<option value="' . $row['forum_id'] . '"' . ($row['forum_type'] == FORUM_POST ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>';
                                $holding = '';
                            }
                        }
                        if ($holding) {
                            $s_forum_id_options .= $holding;
                        }
                        $db->sql_freeresult($result);
                        unset($padding_store);
                        $template->assign_vars(array('S_FORUM_ID_OPTIONS' => $s_forum_id_options));
                        break;
                }
                $sql = 'SELECT *
					FROM ' . EXTENSION_GROUPS_TABLE . '
					ORDER BY allow_group DESC, allow_in_pm DESC, group_name';
                $result = $db->sql_query($sql);
                $old_allow_group = $old_allow_pm = 1;
                while ($row = $db->sql_fetchrow($result)) {
                    $s_add_spacer = $old_allow_group != $row['allow_group'] || $old_allow_pm != $row['allow_in_pm'] ? true : false;
                    $template->assign_block_vars('groups', array('S_ADD_SPACER' => $s_add_spacer, 'S_ALLOWED_IN_PM' => $row['allow_in_pm'] ? true : false, 'S_GROUP_ALLOWED' => $row['allow_group'] ? true : false, 'U_EDIT' => $this->u_action . "&amp;action=edit&amp;g={$row['group_id']}", 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;g={$row['group_id']}", 'GROUP_NAME' => $row['group_name'], 'CATEGORY' => $cat_lang[$row['cat_id']]));
                    $old_allow_group = $row['allow_group'];
                    $old_allow_pm = $row['allow_in_pm'];
                }
                $db->sql_freeresult($result);
                break;
            case 'orphan':
                if ($submit) {
                    $delete_files = isset($_POST['delete']) ? array_keys(request_var('delete', array('' => 0))) : array();
                    $add_files = isset($_POST['add']) ? array_keys(request_var('add', array('' => 0))) : array();
                    $post_ids = request_var('post_id', array('' => 0));
                    if (sizeof($delete_files)) {
                        $sql = 'SELECT *
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', $delete_files) . '
								AND is_orphan = 1';
                        $result = $db->sql_query($sql);
                        $delete_files = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            phpbb_unlink($row['physical_filename'], 'file');
                            if ($row['thumbnail']) {
                                phpbb_unlink($row['physical_filename'], 'thumbnail');
                            }
                            $delete_files[$row['attach_id']] = $row['real_filename'];
                        }
                        $db->sql_freeresult($result);
                    }
                    if (sizeof($delete_files)) {
                        $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files));
                        $db->sql_query($sql);
                        add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files));
                        $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files));
                    }
                    $upload_list = array();
                    foreach ($add_files as $attach_id) {
                        if (!isset($delete_files[$attach_id]) && !empty($post_ids[$attach_id])) {
                            $upload_list[$attach_id] = $post_ids[$attach_id];
                        }
                    }
                    unset($add_files);
                    if (sizeof($upload_list)) {
                        $template->assign_var('S_UPLOADING_FILES', true);
                        $sql = 'SELECT forum_id, forum_name
							FROM ' . FORUMS_TABLE;
                        $result = $db->sql_query($sql);
                        $forum_names = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            $forum_names[$row['forum_id']] = $row['forum_name'];
                        }
                        $db->sql_freeresult($result);
                        $sql = 'SELECT forum_id, topic_id, post_id, poster_id
							FROM ' . POSTS_TABLE . '
							WHERE ' . $db->sql_in_set('post_id', $upload_list);
                        $result = $db->sql_query($sql);
                        $post_info = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            $post_info[$row['post_id']] = $row;
                        }
                        $db->sql_freeresult($result);
                        // Select those attachments we want to change...
                        $sql = 'SELECT *
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', array_keys($upload_list)) . '
								AND is_orphan = 1';
                        $result = $db->sql_query($sql);
                        $files_added = $space_taken = 0;
                        while ($row = $db->sql_fetchrow($result)) {
                            $post_row = $post_info[$upload_list[$row['attach_id']]];
                            $template->assign_block_vars('upload', array('FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']), 'S_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']) ? true : false, 'L_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : ''));
                            if (!$auth->acl_get('f_attach', $post_row['forum_id'])) {
                                continue;
                            }
                            // Adjust attachment entry
                            $sql_ary = array('in_message' => 0, 'is_orphan' => 0, 'poster_id' => $post_row['poster_id'], 'post_msg_id' => $post_row['post_id'], 'topic_id' => $post_row['topic_id']);
                            $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
								SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
								WHERE attach_id = ' . $row['attach_id'];
                            $db->sql_query($sql);
                            $sql = 'UPDATE ' . POSTS_TABLE . '
								SET post_attachment = 1
								WHERE post_id = ' . $post_row['post_id'];
                            $db->sql_query($sql);
                            $sql = 'UPDATE ' . TOPICS_TABLE . '
								SET topic_attachment = 1
								WHERE topic_id = ' . $post_row['topic_id'];
                            $db->sql_query($sql);
                            $space_taken += $row['filesize'];
                            $files_added++;
                            add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']);
                        }
                        $db->sql_freeresult($result);
                        if ($files_added) {
                            set_config_count('upload_dir_size', $space_taken, true);
                            set_config_count('num_files', $files_added, true);
                        }
                    }
                }
                $template->assign_vars(array('S_ORPHAN' => true));
                // Just get the files with is_orphan set and older than 3 hours
                $sql = 'SELECT *
					FROM ' . ATTACHMENTS_TABLE . '
					WHERE is_orphan = 1
						AND filetime < ' . (time() - 3 * 60 * 60) . '
					ORDER BY filetime DESC';
                $result = $db->sql_query($sql);
                while ($row = $db->sql_fetchrow($result)) {
                    $template->assign_block_vars('orphan', array('FILESIZE' => get_formatted_filesize($row['filesize']), 'FILETIME' => $user->format_date($row['filetime']), 'REAL_FILENAME' => utf8_basename($row['real_filename']), 'PHYSICAL_FILENAME' => utf8_basename($row['physical_filename']), 'ATTACH_ID' => $row['attach_id'], 'POST_IDS' => !empty($post_ids[$row['attach_id']]) ? $post_ids[$row['attach_id']] : '', 'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&amp;id=' . $row['attach_id'])));
                }
                $db->sql_freeresult($result);
                break;
        }
        if (sizeof($error)) {
            $template->assign_vars(array('S_WARNING' => true, 'WARNING_MSG' => implode('<br />', $error)));
        }
        if (sizeof($notify)) {
            $template->assign_vars(array('S_NOTIFY' => true, 'NOTIFY_MSG' => implode('<br />', $notify)));
        }
    }
示例#22
0
/**
* Split topic
*/
function split_topic($action, $topic_id, $to_forum_id, $subject)
{
    global $db, $template, $user, $phpEx, $phpbb_root_path, $auth, $config;
    $post_id_list = request_var('post_id_list', array(0));
    $forum_id = request_var('forum_id', 0);
    $start = request_var('start', 0);
    if (!sizeof($post_id_list)) {
        $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']);
        return;
    }
    if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_split'))) {
        return;
    }
    $post_id = $post_id_list[0];
    $post_info = get_post_data(array($post_id));
    if (!sizeof($post_info)) {
        $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']);
        return;
    }
    $post_info = $post_info[$post_id];
    $subject = trim($subject);
    // Make some tests
    if (!$subject) {
        $template->assign_var('MESSAGE', $user->lang['EMPTY_SUBJECT']);
        return;
    }
    if ($to_forum_id <= 0) {
        $template->assign_var('MESSAGE', $user->lang['NO_DESTINATION_FORUM']);
        return;
    }
    $forum_info = get_forum_data(array($to_forum_id), 'f_post');
    if (!sizeof($forum_info)) {
        $template->assign_var('MESSAGE', $user->lang['USER_CANNOT_POST']);
        return;
    }
    $forum_info = $forum_info[$to_forum_id];
    if ($forum_info['forum_type'] != FORUM_POST) {
        $template->assign_var('MESSAGE', $user->lang['FORUM_NOT_POSTABLE']);
        return;
    }
    $redirect = request_var('redirect', build_url(array('quickmod')));
    $s_hidden_fields = build_hidden_fields(array('i' => 'main', 'post_id_list' => $post_id_list, 'f' => $forum_id, 'mode' => 'topic_view', 'start' => $start, 'action' => $action, 't' => $topic_id, 'redirect' => $redirect, 'subject' => $subject, 'to_forum_id' => $to_forum_id, 'icon' => request_var('icon', 0)));
    $success_msg = $return_link = '';
    if (confirm_box(true)) {
        if ($action == 'split_beyond') {
            $sort_days = $total = 0;
            $sort_key = $sort_dir = '';
            $sort_by_sql = $sort_order_sql = array();
            mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id);
            $limit_time_sql = $sort_days ? 'AND t.topic_last_post_time >= ' . (time() - $sort_days * 86400) : '';
            if ($sort_order_sql[0] == 'u') {
                $sql = 'SELECT p.post_id, p.forum_id, p.post_approved
					FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u\n\t\t\t\t\tWHERE p.topic_id = {$topic_id}\n\t\t\t\t\t\tAND p.poster_id = u.user_id\n\t\t\t\t\t\t{$limit_time_sql}\n\t\t\t\t\tORDER BY {$sort_order_sql}";
            } else {
                $sql = 'SELECT p.post_id, p.forum_id, p.post_approved
					FROM ' . POSTS_TABLE . " p\n\t\t\t\t\tWHERE p.topic_id = {$topic_id}\n\t\t\t\t\t\t{$limit_time_sql}\n\t\t\t\t\tORDER BY {$sort_order_sql}";
            }
            $result = $db->sql_query_limit($sql, 0, $start);
            $store = false;
            $post_id_list = array();
            while ($row = $db->sql_fetchrow($result)) {
                // If split from selected post (split_beyond), we split the unapproved items too.
                if (!$row['post_approved'] && !$auth->acl_get('m_approve', $row['forum_id'])) {
                    //					continue;
                }
                // Start to store post_ids as soon as we see the first post that was selected
                if ($row['post_id'] == $post_id) {
                    $store = true;
                }
                if ($store) {
                    $post_id_list[] = $row['post_id'];
                }
            }
            $db->sql_freeresult($result);
        }
        if (!sizeof($post_id_list)) {
            trigger_error('NO_POST_SELECTED');
        }
        $icon_id = request_var('icon', 0);
        $sql_ary = array('forum_id' => $to_forum_id, 'topic_title' => $subject, 'icon_id' => $icon_id, 'topic_approved' => 1);
        $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
        $db->sql_query($sql);
        $to_topic_id = $db->sql_nextid();
        move_posts($post_id_list, $to_topic_id);
        $topic_info = get_topic_data(array($topic_id));
        $topic_info = $topic_info[$topic_id];
        add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject);
        add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']);
        // Change topic title of first post
        $sql = 'UPDATE ' . POSTS_TABLE . "\n\t\t\tSET post_subject = '" . $db->sql_escape($subject) . "'\n\t\t\tWHERE post_id = {$post_id_list[0]}";
        $db->sql_query($sql);
        $success_msg = 'TOPIC_SPLIT_SUCCESS';
        // Update forum statistics
        set_config_count('num_topics', 1, true);
        // Link back to both topics
        $return_link = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", 'f=' . $post_info['forum_id'] . '&amp;t=' . $post_info['topic_id']) . '">', '</a>') . '<br /><br />' . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');
    } else {
        confirm_box(false, $action == 'split_all' ? 'SPLIT_TOPIC_ALL' : 'SPLIT_TOPIC_BEYOND', $s_hidden_fields);
    }
    $redirect = request_var('redirect', "index.{$phpEx}");
    $redirect = reapply_sid($redirect);
    if (!$success_msg) {
        return;
    } else {
        meta_refresh(3, append_sid("{$phpbb_root_path}viewtopic.{$phpEx}", "f={$to_forum_id}&amp;t={$to_topic_id}"));
        trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link);
    }
}
示例#23
0
/**
* Fork Topic
*/
function mcp_fork_topic($topic_ids)
{
    global $auth, $user, $db, $template, $config;
    global $phpEx, $phpbb_root_path;
    if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) {
        return;
    }
    $to_forum_id = request_var('to_forum_id', 0);
    $forum_id = request_var('f', 0);
    $redirect = request_var('redirect', build_url(array('action', 'quickmod')));
    $additional_msg = $success_msg = '';
    $s_hidden_fields = build_hidden_fields(array('topic_id_list' => $topic_ids, 'f' => $forum_id, 'action' => 'fork', 'redirect' => $redirect));
    if ($to_forum_id) {
        $forum_data = get_forum_data($to_forum_id, 'f_post');
        if (!sizeof($topic_ids)) {
            $additional_msg = $user->lang['NO_TOPIC_SELECTED'];
        } else {
            if (!sizeof($forum_data)) {
                $additional_msg = $user->lang['FORUM_NOT_EXIST'];
            } else {
                $forum_data = $forum_data[$to_forum_id];
                if ($forum_data['forum_type'] != FORUM_POST) {
                    $additional_msg = $user->lang['FORUM_NOT_POSTABLE'];
                } else {
                    if (!$auth->acl_get('f_post', $to_forum_id)) {
                        $additional_msg = $user->lang['USER_CANNOT_POST'];
                    }
                }
            }
        }
    } else {
        if (isset($_POST['confirm'])) {
            $additional_msg = $user->lang['FORUM_NOT_EXIST'];
        }
    }
    if ($additional_msg) {
        unset($_POST['confirm']);
        unset($_REQUEST['confirm_key']);
    }
    if (confirm_box(true)) {
        $topic_data = get_topic_data($topic_ids, 'f_post');
        $total_posts = 0;
        $new_topic_id_list = array();
        if ($topic_data['enable_indexing']) {
            // Select the search method and do some additional checks to ensure it can actually be utilised
            $search_type = basename($config['search_type']);
            if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) {
                trigger_error('NO_SUCH_SEARCH_MODULE');
            }
            if (!class_exists($search_type)) {
                include "{$phpbb_root_path}includes/search/{$search_type}.{$phpEx}";
            }
            $error = false;
            $search = new $search_type($error);
            $search_mode = 'post';
            if ($error) {
                trigger_error($error);
            }
        } else {
            $search_type = false;
        }
        foreach ($topic_data as $topic_id => $topic_row) {
            $sql_ary = array('forum_id' => (int) $to_forum_id, 'icon_id' => (int) $topic_row['icon_id'], 'topic_attachment' => (int) $topic_row['topic_attachment'], 'topic_approved' => 1, 'topic_reported' => 0, 'topic_title' => (string) $topic_row['topic_title'], 'topic_poster' => (int) $topic_row['topic_poster'], 'topic_time' => (int) $topic_row['topic_time'], 'topic_replies' => (int) $topic_row['topic_replies_real'], 'topic_replies_real' => (int) $topic_row['topic_replies_real'], 'topic_status' => (int) $topic_row['topic_status'], 'topic_type' => (int) $topic_row['topic_type'], 'topic_first_poster_name' => (string) $topic_row['topic_first_poster_name'], 'topic_last_poster_id' => (int) $topic_row['topic_last_poster_id'], 'topic_last_poster_name' => (string) $topic_row['topic_last_poster_name'], 'topic_last_post_time' => (int) $topic_row['topic_last_post_time'], 'topic_last_view_time' => (int) $topic_row['topic_last_view_time'], 'topic_bumped' => (int) $topic_row['topic_bumped'], 'topic_bumper' => (int) $topic_row['topic_bumper'], 'poll_title' => (string) $topic_row['poll_title'], 'poll_start' => (int) $topic_row['poll_start'], 'poll_length' => (int) $topic_row['poll_length'], 'poll_max_options' => (int) $topic_row['poll_max_options'], 'poll_vote_change' => (int) $topic_row['poll_vote_change']);
            $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
            $new_topic_id = $db->sql_nextid();
            $new_topic_id_list[$topic_id] = $new_topic_id;
            if ($topic_row['poll_start']) {
                $poll_rows = array();
                $sql = 'SELECT *
					FROM ' . POLL_OPTIONS_TABLE . "\n\t\t\t\t\tWHERE topic_id = {$topic_id}";
                $result = $db->sql_query($sql);
                while ($row = $db->sql_fetchrow($result)) {
                    $sql_ary = array('poll_option_id' => (int) $row['poll_option_id'], 'topic_id' => (int) $new_topic_id, 'poll_option_text' => (string) $row['poll_option_text'], 'poll_option_total' => 0);
                    $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                }
            }
            $sql = 'SELECT *
				FROM ' . POSTS_TABLE . "\n\t\t\t\tWHERE topic_id = {$topic_id}\n\t\t\t\tORDER BY post_time ASC";
            $result = $db->sql_query($sql);
            $post_rows = array();
            while ($row = $db->sql_fetchrow($result)) {
                $post_rows[] = $row;
            }
            $db->sql_freeresult($result);
            if (!sizeof($post_rows)) {
                continue;
            }
            $total_posts += sizeof($post_rows);
            foreach ($post_rows as $row) {
                $sql_ary = array('topic_id' => (int) $new_topic_id, 'forum_id' => (int) $to_forum_id, 'poster_id' => (int) $row['poster_id'], 'icon_id' => (int) $row['icon_id'], 'poster_ip' => (string) $row['poster_ip'], 'post_time' => (int) $row['post_time'], 'post_approved' => 1, 'post_reported' => 0, 'enable_bbcode' => (int) $row['enable_bbcode'], 'enable_smilies' => (int) $row['enable_smilies'], 'enable_magic_url' => (int) $row['enable_magic_url'], 'enable_sig' => (int) $row['enable_sig'], 'post_username' => (string) $row['post_username'], 'post_subject' => (string) $row['post_subject'], 'post_text' => (string) $row['post_text'], 'post_edit_reason' => (string) $row['post_edit_reason'], 'post_edit_user' => (int) $row['post_edit_user'], 'post_checksum' => (string) $row['post_checksum'], 'post_attachment' => (int) $row['post_attachment'], 'bbcode_bitfield' => $row['bbcode_bitfield'], 'bbcode_uid' => (string) $row['bbcode_uid'], 'post_edit_time' => (int) $row['post_edit_time'], 'post_edit_count' => (int) $row['post_edit_count'], 'post_edit_locked' => (int) $row['post_edit_locked'], 'post_postcount' => 0);
                $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                $new_post_id = $db->sql_nextid();
                // Copy whether the topic is dotted
                markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']);
                if ($search_type) {
                    $search->index($search_mode, $sql_ary['post_id'], $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], $topic_row['topic_type'] == POST_GLOBAL ? 0 : $to_forum_id);
                    $search_mode = 'reply';
                    // After one we index replies
                }
                // Copy Attachments
                if ($row['post_attachment']) {
                    $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . "\n\t\t\t\t\t\tWHERE post_msg_id = {$row['post_id']}\n\t\t\t\t\t\t\tAND topic_id = {$topic_id}\n\t\t\t\t\t\t\tAND in_message = 0";
                    $result = $db->sql_query($sql);
                    $sql_ary = array();
                    while ($attach_row = $db->sql_fetchrow($result)) {
                        $sql_ary[] = array('post_msg_id' => (int) $new_post_id, 'topic_id' => (int) $new_topic_id, 'in_message' => 0, 'is_orphan' => (int) $attach_row['is_orphan'], 'poster_id' => (int) $attach_row['poster_id'], 'physical_filename' => (string) utf8_basename($attach_row['physical_filename']), 'real_filename' => (string) utf8_basename($attach_row['real_filename']), 'download_count' => (int) $attach_row['download_count'], 'attach_comment' => (string) $attach_row['attach_comment'], 'extension' => (string) $attach_row['extension'], 'mimetype' => (string) $attach_row['mimetype'], 'filesize' => (int) $attach_row['filesize'], 'filetime' => (int) $attach_row['filetime'], 'thumbnail' => (int) $attach_row['thumbnail']);
                    }
                    $db->sql_freeresult($result);
                    if (sizeof($sql_ary)) {
                        $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary);
                    }
                }
            }
            $sql = 'SELECT user_id, notify_status
				FROM ' . TOPICS_WATCH_TABLE . '
				WHERE topic_id = ' . $topic_id;
            $result = $db->sql_query($sql);
            $sql_ary = array();
            while ($row = $db->sql_fetchrow($result)) {
                $sql_ary[] = array('topic_id' => (int) $new_topic_id, 'user_id' => (int) $row['user_id'], 'notify_status' => (int) $row['notify_status']);
            }
            $db->sql_freeresult($result);
            if (sizeof($sql_ary)) {
                $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
            }
        }
        // Sync new topics, parent forums and board stats
        sync('topic', 'topic_id', $new_topic_id_list);
        $sync_sql = array();
        $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $total_posts;
        $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . sizeof($new_topic_id_list);
        $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . sizeof($new_topic_id_list);
        foreach ($sync_sql as $forum_id_key => $array) {
            $sql = 'UPDATE ' . FORUMS_TABLE . '
				SET ' . implode(', ', $array) . '
				WHERE forum_id = ' . $forum_id_key;
            $db->sql_query($sql);
        }
        sync('forum', 'forum_id', $to_forum_id);
        set_config_count('num_topics', sizeof($new_topic_id_list), true);
        set_config_count('num_posts', $total_posts, true);
        foreach ($new_topic_id_list as $topic_id => $new_topic_id) {
            add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']);
        }
        $success_msg = sizeof($topic_ids) == 1 ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS';
    } else {
        $template->assign_vars(array('S_FORUM_SELECT' => make_forum_select($to_forum_id, false, false, true, true, true), 'S_CAN_LEAVE_SHADOW' => false, 'ADDITIONAL_MSG' => $additional_msg));
        confirm_box(false, 'FORK_TOPIC' . (sizeof($topic_ids) == 1 ? '' : 'S'), $s_hidden_fields, 'mcp_move.html');
    }
    $redirect = request_var('redirect', "index.{$phpEx}");
    $redirect = reapply_sid($redirect);
    if (!$success_msg) {
        redirect($redirect);
    } else {
        $redirect_url = append_sid("{$phpbb_root_path}viewforum.{$phpEx}", 'f=' . $forum_id);
        meta_refresh(3, $redirect_url);
        $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>');
        if ($forum_id != $to_forum_id) {
            $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid("{$phpbb_root_path}viewforum.{$phpEx}", 'f=' . $to_forum_id) . '">', '</a>');
        }
        trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link);
    }
}