function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = true)
{
    global $_CLASS, $config;
    // We do not handle erasing posts here
    if ($mode == 'delete') {
        return;
    }
    // Collect some basic informations about which tables and which rows to update/insert
    $sql_data = array();
    $root_level = 0;
    // Recipient Informations
    $recipients = $to = $bcc = array();
    if ($mode != 'edit') {
        // Build Recipient List
        // u|g => array($user_id => 'to'|'bcc')
        foreach (array('u', 'g') as $ug_type) {
            if (!empty($data['address_list'][$ug_type])) {
                foreach ($data['address_list'][$ug_type] as $id => $field) {
                    $field = $field == 'to' ? 'to' : 'bcc';
                    if ($ug_type == 'u') {
                        $recipients[$id] = $field;
                    }
                    ${$field}[] = $ug_type . '_' . (int) $id;
                }
            }
        }
        if (!empty($data['address_list']['g'])) {
            $sql = 'SELECT group_id, user_id
				FROM ' . USER_GROUP_TABLE . '
				WHERE group_id IN (' . implode(', ', array_keys($data['address_list']['g'])) . ')
					AND user_pending = 0';
            $result = $_CLASS['core_db']->query($sql);
            while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                $field = $data['address_list']['g'][$row['group_id']] == 'to' ? 'to' : 'bcc';
                $recipients[$row['user_id']] = $field;
            }
            $_CLASS['core_db']->free_result($result);
        }
        $recipients = array_unique($recipients);
        unset($recipients[ANONYMOUS]);
        if (empty($recipients)) {
            trigger_error('NO_RECIPIENT');
        }
    }
    $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 ' . FORUMS_PRIVMSGS_TO_TABLE . '
				SET replied = 1
				WHERE user_id = ' . $_CLASS['core_user']->data['user_id'] . '
					AND msg_id = ' . $data['reply_from_msg_id'];
        case 'forward':
        case 'post':
            $sql_data = array('root_level' => $root_level, 'author_id' => (int) $_CLASS['core_user']->data['user_id'], 'icon_id' => $data['icon_id'], 'author_ip' => $_CLASS['core_user']->ip, 'message_time' => $_CLASS['core_user']->time, 'enable_bbcode' => $data['enable_bbcode'], 'enable_html' => $data['enable_html'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'message_subject' => $subject, 'message_text' => $data['message'], 'message_checksum' => $data['message_md5'], 'message_attachment' => isset($data['filename_data']['physical_filename']) && !empty($data['filename_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'to_address' => implode(':', $to), 'bcc_address' => implode(':', $bcc));
            break;
        case 'edit':
            $sql_data = array('icon_id' => $data['icon_id'], 'message_edit_time' => $_CLASS['core_user']->time, 'enable_bbcode' => $data['enable_bbcode'], 'enable_html' => $data['enable_html'], 'enable_smilies' => $data['enable_smilies'], 'enable_magic_url' => $data['enable_urls'], 'enable_sig' => $data['enable_sig'], 'message_subject' => $subject, 'message_text' => $data['message'], 'message_checksum' => $data['message_md5'], 'message_attachment' => isset($data['filename_data']['physical_filename']) && !empty($data['filename_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid']);
            break;
    }
    $_CLASS['core_db']->transaction();
    if (!empty($sql_data)) {
        if ($mode === 'post' || $mode === 'reply' || $mode === 'quote' || $mode === 'forward') {
            $_CLASS['core_db']->query('INSERT INTO ' . FORUMS_PRIVMSGS_TABLE . ' ' . $_CLASS['core_db']->sql_build_array('INSERT', $sql_data));
            $data['msg_id'] = $_CLASS['core_db']->insert_id(FORUMS_PRIVMSGS_TABLE, 'msg_id');
        } elseif ($mode === 'edit') {
            $sql = 'UPDATE ' . FORUMS_PRIVMSGS_TABLE . ' 
				SET message_edit_count = message_edit_count + 1, ' . $_CLASS['core_db']->sql_build_array('UPDATE', $sql_data) . ' 
				WHERE msg_id = ' . $data['msg_id'];
            $_CLASS['core_db']->query($sql);
        }
    }
    if ($mode !== 'edit') {
        if ($sql) {
            $_CLASS['core_db']->query($sql);
        }
        foreach ($recipients as $user_id => $type) {
            $_CLASS['core_db']->query('INSERT INTO ' . FORUMS_PRIVMSGS_TO_TABLE . ' ' . $_CLASS['core_db']->sql_build_array('INSERT', array('msg_id' => $data['msg_id'], 'user_id' => $user_id, 'author_id' => $_CLASS['core_user']->data['user_id'], 'folder_id' => PRIVMSGS_NO_BOX, 'msg_new' => 1, 'unread' => 1, 'forwarded' => $mode == 'forward' ? 1 : 0)));
        }
        $sql = 'UPDATE ' . USERS_TABLE . ' 
			SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1
			WHERE user_id IN (' . implode(', ', array_keys($recipients)) . ')';
        $_CLASS['core_db']->query($sql);
        // Put PM into outbox
        if ($put_in_outbox) {
            $_CLASS['core_db']->query('INSERT INTO ' . FORUMS_PRIVMSGS_TO_TABLE . ' ' . $_CLASS['core_db']->sql_build_array('INSERT', array('msg_id' => (int) $data['msg_id'], 'user_id' => (int) $_CLASS['core_user']->data['user_id'], 'author_id' => (int) $_CLASS['core_user']->data['user_id'], 'folder_id' => PRIVMSGS_OUTBOX, 'msg_new' => 0, 'unread' => 0, 'forwarded' => $mode == 'forward' ? 1 : 0)));
        }
    }
    // Set user last post time
    if ($mode == 'reply' || $mode == 'quote' || $mode == 'forward' || $mode == 'post') {
        $sql = 'UPDATE ' . USERS_TABLE . "\n\t\t\tSET user_last_post_time = {$_CLASS['core_user']->time}\n\t\t\tWHERE user_id = " . $_CLASS['core_user']->data['user_id'];
        $_CLASS['core_db']->query($sql);
    }
    // Submit Attachments
    if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit', 'forward'))) {
        $space_taken = $files_added = 0;
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['attach_id']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . FORUMS_ATTACHMENTS_TABLE . " \n\t\t\t\t\tSET comment = '" . $_CLASS['core_db']->sql_escape($attach_row['comment']) . "' \n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'];
                $_CLASS['core_db']->query($sql);
            } else {
                // insert attachment into db
                $attach_sql = array('post_msg_id' => $data['msg_id'], 'download_count' => 0, 'topic_id' => 0, 'in_message' => 1, 'poster_id' => $_CLASS['core_user']->data['user_id'], 'physical_filename' => basename($attach_row['physical_filename']), 'real_filename' => basename($attach_row['real_filename']), 'comment' => $attach_row['comment'], 'extension' => $attach_row['extension'], 'mimetype' => $attach_row['mimetype'], 'filesize' => $attach_row['filesize'], 'filetime' => $attach_row['filetime'], 'thumbnail' => $attach_row['thumbnail']);
                $_CLASS['core_db']->query('INSERT INTO ' . FORUMS_ATTACHMENTS_TABLE . ' ' . $_CLASS['core_db']->sql_build_array('INSERT', $attach_sql));
                $space_taken += $attach_row['filesize'];
                $files_added++;
            }
        }
        if (!empty($data['attachment_data'])) {
            $sql = 'UPDATE ' . FORUMS_PRIVMSGS_TABLE . '
				SET message_attachment = 1
				WHERE msg_id = ' . $data['msg_id'];
            $_CLASS['core_db']->query($sql);
        }
        if ($space_taken && $files_added) {
            set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
            set_config('num_files', $config['num_files'] + $files_added, true);
        }
    }
    $_CLASS['core_db']->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 = " . $_CLASS['core_user']->data['user_id'];
        $_CLASS['core_db']->query($sql);
    }
    // Send Notifications
    if ($mode !== 'edit') {
        //unset($recipients[$_CLASS['core_user']->data['user_id']]);
        pm_notification($mode, $_CLASS['core_user']->data['username'], $recipients, $subject, $data['message']);
    }
    return $data['msg_id'];
}
Example #2
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)) {
                $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));
            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'] . '/' . 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('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
            set_config('num_files', $config['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'];
}
Example #3
0
/**
* Submit PM
*/
function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = true)
{
    global $db, $auth, $config, $phpEx, $template, $user;
    // We do not handle erasing pms here
    if ($mode == 'delete') {
        return false;
    }
    $current_time = time();
    // Collect some basic informations about which tables and which rows to update/insert
    $sql_data = array();
    $root_level = 0;
    // Recipient Informations
    $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) {
                        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'])) {
            $sql = 'SELECT group_id, user_id
				FROM ' . USER_GROUP_TABLE . '
				WHERE group_id IN (' . implode(', ', array_keys($data['address_list']['g'])) . ')
					AND user_pending = 0';
            $result = $db->sql_query($sql);
            while ($row = $db->sql_fetchrow($result)) {
                $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');
        }
    }
    $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 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_encoding' => $user->lang['ENCODING'], 'message_attachment' => isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid'], 'to_address' => implode(':', $to), 'bcc_address' => implode(':', $bcc));
            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_encoding' => $user->lang['ENCODING'], 'message_attachment' => isset($data['filename_data']['physical_filename']) && sizeof($data['filename_data']) ? 1 : 0, 'bbcode_bitfield' => $data['bbcode_bitfield'], 'bbcode_uid' => $data['bbcode_uid']);
            break;
    }
    if (sizeof($sql_data)) {
        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') {
        $db->sql_transaction('begin');
        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, 'new' => 1, 'unread' => 1, 'forwarded' => $mode == 'forward' ? 1 : 0);
        }
        if (sizeof($sql_ary)) {
            switch (SQL_LAYER) {
                case 'mysql':
                case 'mysql4':
                case 'mysqli':
                    $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('MULTI_INSERT', $sql_ary));
                    break;
                default:
                    foreach ($sql_ary as $ary) {
                        $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', $ary));
                    }
                    break;
            }
        }
        $sql = 'UPDATE ' . USERS_TABLE . ' 
			SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
			WHERE user_id IN (' . implode(', ', 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, 'new' => 0, 'unread' => 0, 'forwarded' => $mode == 'forward' ? 1 : 0)));
        }
        $db->sql_transaction('commit');
    }
    // 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);
    }
    $db->sql_transaction('begin');
    // 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;
        foreach ($data['attachment_data'] as $pos => $attach_row) {
            if ($attach_row['attach_id']) {
                // update entry in db if attachment already stored in db and filespace
                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " \n\t\t\t\t\tSET comment = '" . $db->sql_escape($attach_row['comment']) . "' \n\t\t\t\t\tWHERE attach_id = " . (int) $attach_row['attach_id'];
                $db->sql_query($sql);
            } else {
                // insert attachment into db
                $attach_sql = array('post_msg_id' => $data['msg_id'], 'topic_id' => 0, 'in_message' => 1, 'poster_id' => $data['from_user_id'], 'physical_filename' => basename($attach_row['physical_filename']), 'real_filename' => basename($attach_row['real_filename']), 'comment' => $attach_row['comment'], 'extension' => $attach_row['extension'], 'mimetype' => $attach_row['mimetype'], 'filesize' => $attach_row['filesize'], 'filetime' => $attach_row['filetime'], 'thumbnail' => $attach_row['thumbnail']);
                $sql = 'INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $attach_sql);
                $db->sql_query($sql);
                $space_taken += $attach_row['filesize'];
                $files_added++;
            }
        }
        if (sizeof($data['attachment_data'])) {
            $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
				SET message_attachment = 1
				WHERE msg_id = ' . $data['msg_id'];
            $db->sql_query($sql);
        }
        if ($space_taken && $files_added) {
            set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
            set_config('num_files', $config['num_files'] + $files_added, true);
        }
    }
    $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 = " . $data['from_user_id'];
        $db->sql_query($sql);
    }
    // Send Notifications
    if ($mode != 'edit') {
        pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
    }
    return $data['msg_id'];
}