/**
* marks a private message unread when the user clicks the mark pm as unread link
* when viewing the private message.  Takes a single parameter, which is the msg_id of the pm
* being marked as unread
*/
function mark_unread_pm($msg_id)
{
    global $db, $user, $phpbb_root_path, $phpEx;
    // redirect the user to the index if the user is not logged in or if user is a bot
    if ($user->data['user_id'] == ANONYMOUS || $user->data['is_bot']) {
        redirect(append_sid("{$phpbb_root_path}index.{$phpEx}"));
    }
    $user->setup('ucp');
    // find out what folder we are talking about so we can confine our actions to that folder
    $folder_id = request_var('f', PRIVMSGS_INBOX);
    $sql = 'SELECT msg_id
		FROM ' . PRIVMSGS_TO_TABLE . '
		WHERE msg_id = ' . $msg_id . '
			AND user_id = ' . $user->data['user_id'] . '
			AND pm_deleted = 0
			AND folder_id =' . $folder_id;
    $result = $db->sql_query($sql);
    if ($row = $db->sql_fetchrow($result)) {
        // there is a pm in the relevant mailbox that matches that msg_id
        // so go ahead and mark it unread
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
			SET pm_unread = 1
			WHERE msg_id = ' . $msg_id . '
				AND user_id = ' . $user->data['user_id'] . '
				AND pm_deleted = 0
				AND folder_id =' . $folder_id;
        $db->sql_query($sql);
        include $phpbb_root_path . 'includes/functions_privmsgs.' . $phpEx;
        update_pm_counts();
    } else {
        // if we get here, there is no pm in this user's inbox that matches that msg_id
        trigger_error('NO_MESSAGE');
    }
    $db->sql_freeresult($result);
    $meta_info = append_sid("{$phpbb_root_path}ucp.{$phpEx}", 'i=pm&folder=inbox');
    meta_refresh(3, $meta_info);
    $message = $user->lang['PM_MARKED_UNREAD'] . '<br /><br />';
    $message .= '<a href="' . $meta_info . '">' . $user->lang['RETURN_INBOX'] . '</a><br /><br />';
    $message .= sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid("{$phpbb_root_path}index.{$phpEx}") . '">', '</a>');
    trigger_error($message);
}
Ejemplo n.º 2
0
/**
* Place new messages into appropriate folder
*/
function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
{
    global $db, $user, $config;
    if (!$user->data['user_new_privmsg']) {
        return array('not_moved' => 0, 'removed' => 0);
    }
    $user_message_rules = (int) $user->data['user_message_rules'];
    $user_id = (int) $user->data['user_id'];
    $action_ary = $move_into_folder = array();
    $num_removed = 0;
    // Newly processing on-hold messages
    if ($release) {
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
			SET folder_id = ' . PRIVMSGS_NO_BOX . '
			WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "\n\t\t\t\tAND user_id = {$user_id}";
        $db->sql_query($sql);
    }
    // Get those messages not yet placed into any box
    $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
		FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u\n\t\tWHERE t.user_id = {$user_id}\n\t\t\tAND p.author_id = u.user_id\n\t\t\tAND t.folder_id = " . PRIVMSGS_NO_BOX . '
			AND t.msg_id = p.msg_id';
    // Just place into the appropriate arrays if no rules need to be checked
    if (!$user_message_rules) {
        $result = $db->sql_query($retrieve_sql);
        while ($row = $db->sql_fetchrow($result)) {
            $action_ary[$row['msg_id']][] = array('action' => false);
        }
        $db->sql_freeresult($result);
    } else {
        $user_rules = $zebra = $check_rows = array();
        $user_ids = $memberships = array();
        // First of all, grab all rules and retrieve friends/foes
        $sql = 'SELECT *
			FROM ' . PRIVMSGS_RULES_TABLE . "\n\t\t\tWHERE user_id = {$user_id}";
        $result = $db->sql_query($sql);
        $user_rules = $db->sql_fetchrowset($result);
        $db->sql_freeresult($result);
        if (sizeof($user_rules)) {
            $sql = 'SELECT zebra_id, friend, foe
				FROM ' . ZEBRA_TABLE . "\n\t\t\t\tWHERE user_id = {$user_id}";
            $result = $db->sql_query($sql);
            while ($row = $db->sql_fetchrow($result)) {
                $zebra[$row['zebra_id']] = $row;
            }
            $db->sql_freeresult($result);
        }
        // Now build a bare-bone check_row array
        $result = $db->sql_query($retrieve_sql);
        while ($row = $db->sql_fetchrow($result)) {
            $check_rows[] = array_merge($row, array('to' => explode(':', $row['to_address']), 'bcc' => explode(':', $row['bcc_address']), 'friend' => isset($zebra[$row['author_id']]) ? $zebra[$row['author_id']]['friend'] : 0, 'foe' => isset($zebra[$row['author_id']]) ? $zebra[$row['author_id']]['foe'] : 0, 'user_in_group' => array($user->data['group_id']), 'author_in_group' => array()));
            $user_ids[] = $row['user_id'];
        }
        $db->sql_freeresult($result);
        // Retrieve user memberships
        if (sizeof($user_ids)) {
            $sql = 'SELECT *
				FROM ' . USER_GROUP_TABLE . '
				WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
					AND user_pending = 0';
            $result = $db->sql_query($sql);
            while ($row = $db->sql_fetchrow($result)) {
                $memberships[$row['user_id']][] = $row['group_id'];
            }
            $db->sql_freeresult($result);
        }
        // Now place into the appropriate folder
        foreach ($check_rows as $row) {
            // Add membership if set
            if (isset($memberships[$row['author_id']])) {
                $row['author_in_group'] = $memberships[$row['user_id']];
            }
            // Check Rule - this should be very quick since we have all information we need
            $is_match = false;
            foreach ($user_rules as $rule_row) {
                if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false) {
                    $is_match = true;
                    $action_ary[$row['msg_id']][] = $action;
                }
            }
            if (!$is_match) {
                $action_ary[$row['msg_id']][] = array('action' => false);
            }
        }
        unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
    }
    // We place actions into arrays, to save queries.
    $sql = $unread_ids = $delete_ids = $important_ids = array();
    foreach ($action_ary as $msg_id => $msg_ary) {
        // It is allowed to execute actions more than once, except placing messages into folder
        $folder_action = $message_removed = false;
        foreach ($msg_ary as $pos => $rule_ary) {
            if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER) {
                continue;
            }
            switch ($rule_ary['action']) {
                case ACTION_PLACE_INTO_FOLDER:
                    // Folder actions have precedence, so we will remove any other ones
                    $folder_action = true;
                    $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
                    break;
                case ACTION_MARK_AS_READ:
                    if ($rule_ary['pm_unread']) {
                        $unread_ids[] = $msg_id;
                    }
                    break;
                case ACTION_DELETE_MESSAGE:
                    $delete_ids[] = $msg_id;
                    $message_removed = true;
                    break;
                case ACTION_MARK_AS_IMPORTANT:
                    if (!$rule_ary['pm_marked']) {
                        $important_ids[] = $msg_id;
                    }
                    break;
            }
        }
        // We place this here because it could happen that the messages are doubled if a rule marks a message and then moves it into a specific
        // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
        if (!$folder_action && !$message_removed) {
            $move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
        }
    }
    // Do not change the order of processing
    // The number of queries needed to be executed here highly depends on the defined rules and are
    // only gone through if new messages arrive.
    // Delete messages
    if (sizeof($delete_ids)) {
        $num_removed += sizeof($delete_ids);
        delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
    }
    // Set messages to Unread
    if (sizeof($unread_ids)) {
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
			SET pm_unread = 0
			WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "\n\t\t\t\tAND user_id = {$user_id}\n\t\t\t\tAND folder_id = " . PRIVMSGS_NO_BOX;
        $db->sql_query($sql);
    }
    // mark messages as important
    if (sizeof($important_ids)) {
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
			SET pm_marked = 1 - pm_marked
			WHERE folder_id = ' . PRIVMSGS_NO_BOX . "\n\t\t\t\tAND user_id = {$user_id}\n\t\t\t\tAND " . $db->sql_in_set('msg_id', $important_ids);
        $db->sql_query($sql);
    }
    // Move into folder
    $folder = array();
    if (sizeof($move_into_folder)) {
        // Determine Full Folder Action - we need the move to folder id later eventually
        $full_folder_action = $user->data['user_full_folder'] == FULL_FOLDER_NONE ? $config['full_folder_action'] - FULL_FOLDER_NONE * -1 : $user->data['user_full_folder'];
        $sql_folder = array_keys($move_into_folder);
        if ($full_folder_action >= 0) {
            $sql_folder[] = $full_folder_action;
        }
        $sql = 'SELECT folder_id, pm_count
			FROM ' . PRIVMSGS_FOLDER_TABLE . '
			WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "\n\t\t\t\tAND user_id = {$user_id}";
        $result = $db->sql_query($sql);
        while ($row = $db->sql_fetchrow($result)) {
            $folder[(int) $row['folder_id']] = (int) $row['pm_count'];
        }
        $db->sql_freeresult($result);
        unset($sql_folder);
        if (isset($move_into_folder[PRIVMSGS_INBOX])) {
            $sql = 'SELECT COUNT(msg_id) as num_messages
				FROM ' . PRIVMSGS_TO_TABLE . "\n\t\t\t\tWHERE user_id = {$user_id}\n\t\t\t\t\tAND folder_id = " . PRIVMSGS_INBOX;
            $result = $db->sql_query($sql);
            $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
            $db->sql_freeresult($result);
        }
    }
    // Here we have ideally only one folder to move into
    foreach ($move_into_folder as $folder_id => $msg_ary) {
        $dest_folder = $folder_id;
        $full_folder_action = FULL_FOLDER_NONE;
        // Check Message Limit - we calculate with the complete array, most of the time it is one message
        // But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
        if ($user->data['message_limit'] && $folder[$folder_id] && $folder[$folder_id] + sizeof($msg_ary) > $user->data['message_limit']) {
            $full_folder_action = $user->data['user_full_folder'] == FULL_FOLDER_NONE ? $config['full_folder_action'] - FULL_FOLDER_NONE * -1 : $user->data['user_full_folder'];
            // If destination folder itself is full...
            if ($full_folder_action >= 0 && $folder[$full_folder_action] + sizeof($msg_ary) > $user->data['message_limit']) {
                $full_folder_action = $config['full_folder_action'] - FULL_FOLDER_NONE * -1;
            }
            // If Full Folder Action is to move to another folder, we simply adjust the destination folder
            if ($full_folder_action >= 0) {
                $dest_folder = $full_folder_action;
            } else {
                if ($full_folder_action == FULL_FOLDER_DELETE) {
                    // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
                    $sql = 'SELECT msg_id
					FROM ' . PRIVMSGS_TO_TABLE . "\n\t\t\t\t\tWHERE user_id = {$user_id}\n\t\t\t\t\t\tAND folder_id = {$dest_folder}\n\t\t\t\t\tORDER BY msg_id ASC";
                    $result = $db->sql_query_limit($sql, $folder[$dest_folder] + sizeof($msg_ary) - $user->data['message_limit']);
                    $delete_ids = array();
                    while ($row = $db->sql_fetchrow($result)) {
                        $delete_ids[] = $row['msg_id'];
                    }
                    $db->sql_freeresult($result);
                    $num_removed += sizeof($delete_ids);
                    delete_pm($user_id, $delete_ids, $dest_folder);
                }
            }
        }
        //
        if ($full_folder_action == FULL_FOLDER_HOLD) {
            $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
				SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
				WHERE folder_id = ' . PRIVMSGS_NO_BOX . "\n\t\t\t\t\tAND user_id = {$user_id}\n\t\t\t\t\tAND " . $db->sql_in_set('msg_id', $msg_ary);
            $db->sql_query($sql);
        } else {
            $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "\n\t\t\t\tSET folder_id = {$dest_folder}, pm_new = 0\n\t\t\t\tWHERE folder_id = " . PRIVMSGS_NO_BOX . "\n\t\t\t\t\tAND user_id = {$user_id}\n\t\t\t\t\tAND pm_new = 1\n\t\t\t\t\tAND " . $db->sql_in_set('msg_id', $msg_ary);
            $db->sql_query($sql);
            if ($dest_folder != PRIVMSGS_INBOX) {
                $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
					SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "\n\t\t\t\t\tWHERE folder_id = {$dest_folder}\n\t\t\t\t\t\tAND user_id = {$user_id}";
                $db->sql_query($sql);
            }
        }
    }
    if (sizeof($action_ary)) {
        // Move from OUTBOX to SENTBOX
        // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
			SET folder_id = ' . PRIVMSGS_SENTBOX . '
			WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
				AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
        $db->sql_query($sql);
    }
    // Update new/unread count
    update_pm_counts();
    // Now check how many messages got not moved...
    $sql = 'SELECT COUNT(msg_id) as num_messages
		FROM ' . PRIVMSGS_TO_TABLE . "\n\t\tWHERE user_id = {$user_id}\n\t\t\tAND folder_id = " . PRIVMSGS_HOLD_BOX;
    $result = $db->sql_query($sql);
    $num_not_moved = (int) $db->sql_fetchfield('num_messages');
    $db->sql_freeresult($result);
    return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
}