Blame Extras/phpBB/3.0.4/includes/functions_privmsgs.php

4c79b5
4c79b5
/**
4c79b5
*
4c79b5
* @package phpBB3
4c79b5
* @version $Id: functions_privmsgs.php 8993 2008-10-10 17:38:17Z toonarmy $
4c79b5
* @copyright (c) 2005 phpBB Group
4c79b5
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
4c79b5
*
4c79b5
*/
4c79b5
4c79b5
/**
4c79b5
*/
4c79b5
if (!defined('IN_PHPBB'))
4c79b5
{
4c79b5
	exit;
4c79b5
}
4c79b5
4c79b5
/*
4c79b5
	Ability to simply add own rules by doing three things:
4c79b5
		1) Add an appropriate constant
4c79b5
		2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required)
4c79b5
		3) Add a new language variable to ucp.php
4c79b5
4c79b5
		The user is then able to select the new rule. It will be checked against and handled as specified.
4c79b5
		To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified.
4c79b5
*/
4c79b5
4c79b5
define('RULE_IS_LIKE', 1);		// Is Like
4c79b5
define('RULE_IS_NOT_LIKE', 2);	// Is Not Like
4c79b5
define('RULE_IS', 3);			// Is
4c79b5
define('RULE_IS_NOT', 4);		// Is Not
4c79b5
define('RULE_BEGINS_WITH', 5);	// Begins with
4c79b5
define('RULE_ENDS_WITH', 6);	// Ends with
4c79b5
define('RULE_IS_FRIEND', 7);	// Is Friend
4c79b5
define('RULE_IS_FOE', 8);		// Is Foe
4c79b5
define('RULE_IS_USER', 9);		// Is User
4c79b5
define('RULE_IS_GROUP', 10);	// Is In Usergroup
4c79b5
define('RULE_ANSWERED', 11);	// Answered
4c79b5
define('RULE_FORWARDED', 12);	// Forwarded
4c79b5
define('RULE_TO_GROUP', 14);	// Usergroup
4c79b5
define('RULE_TO_ME', 15);		// Me
4c79b5
4c79b5
define('ACTION_PLACE_INTO_FOLDER', 1);
4c79b5
define('ACTION_MARK_AS_READ', 2);
4c79b5
define('ACTION_MARK_AS_IMPORTANT', 3);
4c79b5
define('ACTION_DELETE_MESSAGE', 4);
4c79b5
4c79b5
define('CHECK_SUBJECT', 1);
4c79b5
define('CHECK_SENDER', 2);
4c79b5
define('CHECK_MESSAGE', 3);
4c79b5
define('CHECK_STATUS', 4);
4c79b5
define('CHECK_TO', 5);
4c79b5
4c79b5
/**
4c79b5
* Global private message rules
4c79b5
* These rules define what to do if a rule is hit
4c79b5
*/
4c79b5
$global_privmsgs_rules = array(
4c79b5
	CHECK_SUBJECT	=> array(
4c79b5
		RULE_IS_LIKE		=> array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
4c79b5
		RULE_IS_NOT_LIKE	=> array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
4c79b5
		RULE_IS				=> array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'),
4c79b5
		RULE_IS_NOT			=> array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'),
4c79b5
		RULE_BEGINS_WITH	=> array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
4c79b5
		RULE_ENDS_WITH		=> array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
4c79b5
	),
4c79b5
4c79b5
	CHECK_SENDER	=> array(
4c79b5
		RULE_IS_LIKE		=> array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
4c79b5
		RULE_IS_NOT_LIKE	=> array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
4c79b5
		RULE_IS				=> array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'),
4c79b5
		RULE_IS_NOT			=> array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'),
4c79b5
		RULE_BEGINS_WITH	=> array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
4c79b5
		RULE_ENDS_WITH		=> array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
4c79b5
		RULE_IS_FRIEND		=> array('check0' => 'friend', 'function' => '{CHECK0} == 1'),
4c79b5
		RULE_IS_FOE			=> array('check0' => 'foe', 'function' => '{CHECK0} == 1'),
4c79b5
		RULE_IS_USER		=> array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'),
4c79b5
		RULE_IS_GROUP		=> array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'),
4c79b5
	),
4c79b5
4c79b5
	CHECK_MESSAGE	=> array(
4c79b5
		RULE_IS_LIKE		=> array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
4c79b5
		RULE_IS_NOT_LIKE	=> array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
4c79b5
		RULE_IS				=> array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'),
4c79b5
		RULE_IS_NOT			=> array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'),
4c79b5
	),
4c79b5
4c79b5
	CHECK_STATUS	=> array(
4c79b5
		RULE_ANSWERED		=> array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'),
4c79b5
		RULE_FORWARDED		=> array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'),
4c79b5
	),
4c79b5
4c79b5
	CHECK_TO		=> array(
4c79b5
		RULE_TO_GROUP		=> array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'),
4c79b5
		RULE_TO_ME			=> array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'),
4c79b5
	)
4c79b5
);
4c79b5
4c79b5
/**
4c79b5
* This is for defining which condition fields to show for which Rule
4c79b5
*/
4c79b5
$global_rule_conditions = array(
4c79b5
	RULE_IS_LIKE		=> 'text',
4c79b5
	RULE_IS_NOT_LIKE	=> 'text',
4c79b5
	RULE_IS				=> 'text',
4c79b5
	RULE_IS_NOT			=> 'text',
4c79b5
	RULE_BEGINS_WITH	=> 'text',
4c79b5
	RULE_ENDS_WITH		=> 'text',
4c79b5
	RULE_IS_USER		=> 'user',
4c79b5
	RULE_IS_GROUP		=> 'group'
4c79b5
);
4c79b5
4c79b5
/**
4c79b5
* Get all folder
4c79b5
*/
4c79b5
function get_folder($user_id, $folder_id = false)
4c79b5
{
4c79b5
	global $db, $user, $template;
4c79b5
	global $phpbb_root_path, $phpEx;
4c79b5
4c79b5
	$folder = array();
4c79b5
4c79b5
	// Get folder information
4c79b5
	$sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
		WHERE user_id = $user_id
4c79b5
			AND folder_id <> " . PRIVMSGS_NO_BOX . '
4c79b5
		GROUP BY folder_id';
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	$num_messages = $num_unread = array();
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		$num_messages[(int) $row['folder_id']] = $row['num_messages'];
4c79b5
		$num_unread[(int) $row['folder_id']] = $row['num_unread'];
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	// Make sure the default boxes are defined
4c79b5
	$available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX);
4c79b5
4c79b5
	foreach ($available_folder as $default_folder)
4c79b5
	{
4c79b5
		if (!isset($num_messages[$default_folder]))
4c79b5
		{
4c79b5
			$num_messages[$default_folder] = 0;
4c79b5
		}
4c79b5
4c79b5
		if (!isset($num_unread[$default_folder]))
4c79b5
		{
4c79b5
			$num_unread[$default_folder] = 0;
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	// Adjust unread status for outbox
4c79b5
	$num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX];
4c79b5
4c79b5
	$folder[PRIVMSGS_INBOX] = array(
4c79b5
		'folder_name'		=> $user->lang['PM_INBOX'],
4c79b5
		'num_messages'		=> $num_messages[PRIVMSGS_INBOX],
4c79b5
		'unread_messages'	=> $num_unread[PRIVMSGS_INBOX]
4c79b5
	);
4c79b5
4c79b5
	// Custom Folder
4c79b5
	$sql = 'SELECT folder_id, folder_name, pm_count
4c79b5
		FROM ' . PRIVMSGS_FOLDER_TABLE . "
4c79b5
			WHERE user_id = $user_id";
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		$folder[$row['folder_id']] = array(
4c79b5
			'folder_name'		=> $row['folder_name'],
4c79b5
			'num_messages'		=> $row['pm_count'],
4c79b5
			'unread_messages'	=> ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0)
4c79b5
		);
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	$folder[PRIVMSGS_OUTBOX] = array(
4c79b5
		'folder_name'		=> $user->lang['PM_OUTBOX'],
4c79b5
		'num_messages'		=> $num_messages[PRIVMSGS_OUTBOX],
4c79b5
		'unread_messages'	=> $num_unread[PRIVMSGS_OUTBOX]
4c79b5
	);
4c79b5
4c79b5
	$folder[PRIVMSGS_SENTBOX] = array(
4c79b5
		'folder_name'		=> $user->lang['PM_SENTBOX'],
4c79b5
		'num_messages'		=> $num_messages[PRIVMSGS_SENTBOX],
4c79b5
		'unread_messages'	=> $num_unread[PRIVMSGS_SENTBOX]
4c79b5
	);
4c79b5
4c79b5
	// Define Folder Array for template designers (and for making custom folders usable by the template too)
4c79b5
	foreach ($folder as $f_id => $folder_ary)
4c79b5
	{
4c79b5
		$folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox');
4c79b5
4c79b5
		$template->assign_block_vars('folder', array(
4c79b5
			'FOLDER_ID'			=> $f_id,
4c79b5
			'FOLDER_NAME'		=> $folder_ary['folder_name'],
4c79b5
			'NUM_MESSAGES'		=> $folder_ary['num_messages'],
4c79b5
			'UNREAD_MESSAGES'	=> $folder_ary['unread_messages'],
4c79b5
4c79b5
			'U_FOLDER'			=> ($f_id > 0) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $folder_id_name),
4c79b5
4c79b5
			'S_CUR_FOLDER'		=> ($f_id === $folder_id) ? true : false,
4c79b5
			'S_UNREAD_MESSAGES'	=> ($folder_ary['unread_messages']) ? true : false,
4c79b5
			'S_CUSTOM_FOLDER'	=> ($f_id > 0) ? true : false)
4c79b5
		);
4c79b5
	}
4c79b5
4c79b5
	if ($folder_id !== false && !isset($folder[$folder_id]))
4c79b5
	{
4c79b5
		trigger_error('UNKNOWN_FOLDER');
4c79b5
	}
4c79b5
4c79b5
	return $folder;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Delete Messages From Sentbox
4c79b5
* we are doing this here because this saves us a bunch of checks and queries
4c79b5
*/
4c79b5
function clean_sentbox($num_sentbox_messages)
4c79b5
{
4c79b5
	global $db, $user, $config;
4c79b5
4c79b5
	// Check Message Limit
4c79b5
	if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
4c79b5
	{
4c79b5
		// Delete old messages
4c79b5
		$sql = 'SELECT t.msg_id
4c79b5
			FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
4c79b5
			WHERE t.msg_id = p.msg_id
4c79b5
				AND t.user_id = ' . $user->data['user_id'] . '
4c79b5
				AND t.folder_id = ' . PRIVMSGS_SENTBOX . '
4c79b5
			ORDER BY p.message_time ASC';
4c79b5
		$result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit']));
4c79b5
4c79b5
		$delete_ids = array();
4c79b5
		while ($row = $db->sql_fetchrow($result))
4c79b5
		{
4c79b5
			$delete_ids[] = $row['msg_id'];
4c79b5
		}
4c79b5
		$db->sql_freeresult($result);
4c79b5
		delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX);
4c79b5
	}
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Check Rule against Message Information
4c79b5
*/
4c79b5
function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
4c79b5
{
4c79b5
	global $user, $config;
4c79b5
4c79b5
	if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	$check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
4c79b5
4c79b5
	// Replace Check Literals
4c79b5
	$evaluate = $check_ary['function'];
4c79b5
	$evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate);
4c79b5
4c79b5
	// Replace Rule Literals
4c79b5
	$evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate);
4c79b5
4c79b5
	// Evil Statement
4c79b5
	$result = false;
4c79b5
	eval('$result = (' . $evaluate . ') ? true : false;');
4c79b5
4c79b5
	if (!$result)
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	switch ($rule_row['rule_action'])
4c79b5
	{
4c79b5
		case ACTION_PLACE_INTO_FOLDER:
4c79b5
			return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
4c79b5
		break;
4c79b5
4c79b5
		case ACTION_MARK_AS_READ:
4c79b5
		case ACTION_MARK_AS_IMPORTANT:
4c79b5
			return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
4c79b5
		break;
4c79b5
4c79b5
		case ACTION_DELETE_MESSAGE:
4c79b5
			global $db, $auth;
4c79b5
4c79b5
			// Check for admins/mods - users are not allowed to remove those messages...
4c79b5
			// We do the check here to make sure the data we use is consistent
4c79b5
			$sql = 'SELECT user_id, user_type, user_permissions
4c79b5
				FROM ' . USERS_TABLE . '
4c79b5
				WHERE user_id = ' . (int) $message_row['author_id'];
4c79b5
			$result = $db->sql_query($sql);
4c79b5
			$userdata = $db->sql_fetchrow($result);
4c79b5
			$db->sql_freeresult($result);
4c79b5
4c79b5
			$auth2 = new auth();
4c79b5
			$auth2->acl($userdata);
4c79b5
4c79b5
			if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
4c79b5
			{
4c79b5
				return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
4c79b5
			}
4c79b5
4c79b5
			return false;
4c79b5
		break;
4c79b5
4c79b5
		default:
4c79b5
			return false;
4c79b5
	}
4c79b5
4c79b5
	return false;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Update user PM count
4c79b5
*/
4c79b5
function update_pm_counts()
4c79b5
{
4c79b5
	global $user, $db;
4c79b5
4c79b5
	// Update unread count
4c79b5
	$sql = 'SELECT COUNT(msg_id) as num_messages
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . '
4c79b5
		WHERE pm_unread = 1
4c79b5
			AND folder_id <> ' . PRIVMSGS_OUTBOX . '
4c79b5
			AND user_id = ' . $user->data['user_id'];
4c79b5
	$result = $db->sql_query($sql);
4c79b5
	$user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages');
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	// Update new pm count
4c79b5
	$sql = 'SELECT COUNT(msg_id) as num_messages
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . '
4c79b5
		WHERE pm_new = 1
4c79b5
			AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
4c79b5
			AND user_id = ' . $user->data['user_id'];
4c79b5
	$result = $db->sql_query($sql);
4c79b5
	$user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages');
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	$db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
4c79b5
		'user_unread_privmsg'	=> (int) $user->data['user_unread_privmsg'],
4c79b5
		'user_new_privmsg'		=> (int) $user->data['user_new_privmsg'],
4c79b5
	)) . ' WHERE user_id = ' . $user->data['user_id']);
4c79b5
4c79b5
	// Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag.
4c79b5
	if (!$user->data['user_new_privmsg'])
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET pm_new = 0
4c79b5
			WHERE pm_new = 1
4c79b5
				AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
4c79b5
				AND user_id = ' . $user->data['user_id'];
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Place new messages into appropriate folder
4c79b5
*/
4c79b5
function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
4c79b5
{
4c79b5
	global $db, $user, $config;
4c79b5
4c79b5
	if (!$user->data['user_new_privmsg'])
4c79b5
	{
4c79b5
		return array('not_moved' => 0, 'removed' => 0);
4c79b5
	}
4c79b5
4c79b5
	$user_message_rules = (int) $user->data['user_message_rules'];
4c79b5
	$user_id = (int) $user->data['user_id'];
4c79b5
4c79b5
	$action_ary = $move_into_folder = array();
4c79b5
	$num_removed = 0;
4c79b5
4c79b5
	// Newly processing on-hold messages
4c79b5
	if ($release)
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET folder_id = ' . PRIVMSGS_NO_BOX . '
4c79b5
			WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "
4c79b5
				AND user_id = $user_id";
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// Get those messages not yet placed into any box
4c79b5
	$retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
4c79b5
		WHERE t.user_id = $user_id
4c79b5
			AND p.author_id = u.user_id
4c79b5
			AND t.folder_id = " . PRIVMSGS_NO_BOX . '
4c79b5
			AND t.msg_id = p.msg_id';
4c79b5
4c79b5
	// Just place into the appropriate arrays if no rules need to be checked
4c79b5
	if (!$user_message_rules)
4c79b5
	{
4c79b5
		$result = $db->sql_query($retrieve_sql);
4c79b5
4c79b5
		while ($row = $db->sql_fetchrow($result))
4c79b5
		{
4c79b5
			$action_ary[$row['msg_id']][] = array('action' => false);
4c79b5
		}
4c79b5
		$db->sql_freeresult($result);
4c79b5
	}
4c79b5
	else
4c79b5
	{
4c79b5
		$user_rules = $zebra = $check_rows = array();
4c79b5
		$user_ids = $memberships = array();
4c79b5
4c79b5
		// First of all, grab all rules and retrieve friends/foes
4c79b5
		$sql = 'SELECT *
4c79b5
			FROM ' . PRIVMSGS_RULES_TABLE . "
4c79b5
			WHERE user_id = $user_id";
4c79b5
		$result = $db->sql_query($sql);
4c79b5
		$user_rules = $db->sql_fetchrowset($result);
4c79b5
		$db->sql_freeresult($result);
4c79b5
4c79b5
		if (sizeof($user_rules))
4c79b5
		{
4c79b5
			$sql = 'SELECT zebra_id, friend, foe
4c79b5
				FROM ' . ZEBRA_TABLE . "
4c79b5
				WHERE user_id = $user_id";
4c79b5
			$result = $db->sql_query($sql);
4c79b5
4c79b5
			while ($row = $db->sql_fetchrow($result))
4c79b5
			{
4c79b5
				$zebra[$row['zebra_id']] = $row;
4c79b5
			}
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
4c79b5
		// Now build a bare-bone check_row array
4c79b5
		$result = $db->sql_query($retrieve_sql);
4c79b5
4c79b5
		while ($row = $db->sql_fetchrow($result))
4c79b5
		{
4c79b5
			$check_rows[] = array_merge($row, array(
4c79b5
				'to'				=> explode(':', $row['to_address']),
4c79b5
				'bcc'				=> explode(':', $row['bcc_address']),
4c79b5
				'friend'			=> (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,
4c79b5
				'foe'				=> (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0,
4c79b5
				'user_in_group'		=> array($user->data['group_id']),
4c79b5
				'author_in_group'	=> array())
4c79b5
			);
4c79b5
4c79b5
			$user_ids[] = $row['user_id'];
4c79b5
		}
4c79b5
		$db->sql_freeresult($result);
4c79b5
4c79b5
		// Retrieve user memberships
4c79b5
		if (sizeof($user_ids))
4c79b5
		{
4c79b5
			$sql = 'SELECT *
4c79b5
				FROM ' . USER_GROUP_TABLE . '
4c79b5
				WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
4c79b5
					AND user_pending = 0';
4c79b5
			$result = $db->sql_query($sql);
4c79b5
4c79b5
			while ($row = $db->sql_fetchrow($result))
4c79b5
			{
4c79b5
				$memberships[$row['user_id']][] = $row['group_id'];
4c79b5
			}
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
4c79b5
		// Now place into the appropriate folder
4c79b5
		foreach ($check_rows as $row)
4c79b5
		{
4c79b5
			// Add membership if set
4c79b5
			if (isset($memberships[$row['author_id']]))
4c79b5
			{
4c79b5
				$row['author_in_group'] = $memberships[$row['user_id']];
4c79b5
			}
4c79b5
4c79b5
			// Check Rule - this should be very quick since we have all information we need
4c79b5
			$is_match = false;
4c79b5
			foreach ($user_rules as $rule_row)
4c79b5
			{
4c79b5
				if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
4c79b5
				{
4c79b5
					$is_match = true;
4c79b5
					$action_ary[$row['msg_id']][] = $action;
4c79b5
				}
4c79b5
			}
4c79b5
4c79b5
			if (!$is_match)
4c79b5
			{
4c79b5
				$action_ary[$row['msg_id']][] = array('action' => false);
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
4c79b5
	}
4c79b5
4c79b5
	// We place actions into arrays, to save queries.
4c79b5
	$sql = $unread_ids = $delete_ids = $important_ids = array();
4c79b5
4c79b5
	foreach ($action_ary as $msg_id => $msg_ary)
4c79b5
	{
4c79b5
		// It is allowed to execute actions more than once, except placing messages into folder
4c79b5
		$folder_action = $message_removed = false;
4c79b5
4c79b5
		foreach ($msg_ary as $pos => $rule_ary)
4c79b5
		{
4c79b5
			if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER)
4c79b5
			{
4c79b5
				continue;
4c79b5
			}
4c79b5
4c79b5
			switch ($rule_ary['action'])
4c79b5
			{
4c79b5
				case ACTION_PLACE_INTO_FOLDER:
4c79b5
					// Folder actions have precedence, so we will remove any other ones
4c79b5
					$folder_action = true;
4c79b5
					$move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
4c79b5
				break;
4c79b5
4c79b5
				case ACTION_MARK_AS_READ:
4c79b5
					if ($rule_ary['pm_unread'])
4c79b5
					{
4c79b5
						$unread_ids[] = $msg_id;
4c79b5
					}
4c79b5
				break;
4c79b5
4c79b5
				case ACTION_DELETE_MESSAGE:
4c79b5
					$delete_ids[] = $msg_id;
4c79b5
					$message_removed = true;
4c79b5
				break;
4c79b5
4c79b5
				case ACTION_MARK_AS_IMPORTANT:
4c79b5
					if (!$rule_ary['pm_marked'])
4c79b5
					{
4c79b5
						$important_ids[] = $msg_id;
4c79b5
					}
4c79b5
				break;
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		// 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
4c79b5
		// folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
4c79b5
		if (!$folder_action && !$message_removed)
4c79b5
		{
4c79b5
			$move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	// Do not change the order of processing
4c79b5
	// The number of queries needed to be executed here highly depends on the defined rules and are
4c79b5
	// only gone through if new messages arrive.
4c79b5
4c79b5
	// Delete messages
4c79b5
	if (sizeof($delete_ids))
4c79b5
	{
4c79b5
		$num_removed += sizeof($delete_ids);
4c79b5
		delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
4c79b5
	}
4c79b5
4c79b5
	// Set messages to Unread
4c79b5
	if (sizeof($unread_ids))
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET pm_unread = 0
4c79b5
			WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
4c79b5
				AND user_id = $user_id
4c79b5
				AND folder_id = " . PRIVMSGS_NO_BOX;
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// mark messages as important
4c79b5
	if (sizeof($important_ids))
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET pm_marked = 1 - pm_marked
4c79b5
			WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
4c79b5
				AND user_id = $user_id
4c79b5
				AND " . $db->sql_in_set('msg_id', $important_ids);
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// Move into folder
4c79b5
	$folder = array();
4c79b5
4c79b5
	if (sizeof($move_into_folder))
4c79b5
	{
4c79b5
		// Determine Full Folder Action - we need the move to folder id later eventually
4c79b5
		$full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
4c79b5
4c79b5
		$sql_folder = array_keys($move_into_folder);
4c79b5
		if ($full_folder_action >= 0)
4c79b5
		{
4c79b5
			$sql_folder[] = $full_folder_action;
4c79b5
		}
4c79b5
4c79b5
		$sql = 'SELECT folder_id, pm_count
4c79b5
			FROM ' . PRIVMSGS_FOLDER_TABLE . '
4c79b5
			WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
4c79b5
				AND user_id = $user_id";
4c79b5
		$result = $db->sql_query($sql);
4c79b5
4c79b5
		while ($row = $db->sql_fetchrow($result))
4c79b5
		{
4c79b5
			$folder[(int) $row['folder_id']] = (int) $row['pm_count'];
4c79b5
		}
4c79b5
		$db->sql_freeresult($result);
4c79b5
4c79b5
		unset($sql_folder);
4c79b5
4c79b5
		if (isset($move_into_folder[PRIVMSGS_INBOX]))
4c79b5
		{
4c79b5
			$sql = 'SELECT COUNT(msg_id) as num_messages
4c79b5
				FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
				WHERE user_id = $user_id
4c79b5
					AND folder_id = " . PRIVMSGS_INBOX;
4c79b5
			$result = $db->sql_query($sql);
4c79b5
			$folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	// Here we have ideally only one folder to move into
4c79b5
	foreach ($move_into_folder as $folder_id => $msg_ary)
4c79b5
	{
4c79b5
		$dest_folder = $folder_id;
4c79b5
		$full_folder_action = FULL_FOLDER_NONE;
4c79b5
4c79b5
		// Check Message Limit - we calculate with the complete array, most of the time it is one message
4c79b5
		// But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
4c79b5
		if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit'])
4c79b5
		{
4c79b5
			$full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
4c79b5
4c79b5
			// If destination folder itself is full...
4c79b5
			if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit'])
4c79b5
			{
4c79b5
				$full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1));
4c79b5
			}
4c79b5
4c79b5
			// If Full Folder Action is to move to another folder, we simply adjust the destination folder
4c79b5
			if ($full_folder_action >= 0)
4c79b5
			{
4c79b5
				$dest_folder = $full_folder_action;
4c79b5
			}
4c79b5
			else if ($full_folder_action == FULL_FOLDER_DELETE)
4c79b5
			{
4c79b5
				// Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
4c79b5
				$sql = 'SELECT msg_id
4c79b5
					FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
					WHERE user_id = $user_id
4c79b5
						AND folder_id = $dest_folder
4c79b5
					ORDER BY msg_id ASC";
4c79b5
				$result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
4c79b5
4c79b5
				$delete_ids = array();
4c79b5
				while ($row = $db->sql_fetchrow($result))
4c79b5
				{
4c79b5
					$delete_ids[] = $row['msg_id'];
4c79b5
				}
4c79b5
				$db->sql_freeresult($result);
4c79b5
4c79b5
				$num_removed += sizeof($delete_ids);
4c79b5
				delete_pm($user_id, $delete_ids, $dest_folder);
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		//
4c79b5
		if ($full_folder_action == FULL_FOLDER_HOLD)
4c79b5
		{
4c79b5
			$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
				SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
4c79b5
				WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
4c79b5
					AND user_id = $user_id
4c79b5
					AND " . $db->sql_in_set('msg_id', $msg_ary);
4c79b5
			$db->sql_query($sql);
4c79b5
		}
4c79b5
		else
4c79b5
		{
4c79b5
			$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
4c79b5
				SET folder_id = $dest_folder, pm_new = 0
4c79b5
				WHERE folder_id = " . PRIVMSGS_NO_BOX . "
4c79b5
					AND user_id = $user_id
4c79b5
					AND pm_new = 1
4c79b5
					AND " . $db->sql_in_set('msg_id', $msg_ary);
4c79b5
			$db->sql_query($sql);
4c79b5
4c79b5
			if ($dest_folder != PRIVMSGS_INBOX)
4c79b5
			{
4c79b5
				$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
4c79b5
					SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
4c79b5
					WHERE folder_id = $dest_folder
4c79b5
						AND user_id = $user_id";
4c79b5
				$db->sql_query($sql);
4c79b5
			}
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	if (sizeof($action_ary))
4c79b5
	{
4c79b5
		// Move from OUTBOX to SENTBOX
4c79b5
		// We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET folder_id = ' . PRIVMSGS_SENTBOX . '
4c79b5
			WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
4c79b5
				AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// Update new/unread count
4c79b5
	update_pm_counts();
4c79b5
4c79b5
	// Now check how many messages got not moved...
4c79b5
	$sql = 'SELECT COUNT(msg_id) as num_messages
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
		WHERE user_id = $user_id
4c79b5
			AND folder_id = " . PRIVMSGS_HOLD_BOX;
4c79b5
	$result = $db->sql_query($sql);
4c79b5
	$num_not_moved = (int) $db->sql_fetchfield('num_messages');
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Move PM from one to another folder
4c79b5
*/
4c79b5
function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
4c79b5
{
4c79b5
	global $db, $user;
4c79b5
	global $phpbb_root_path, $phpEx;
4c79b5
4c79b5
	$num_moved = 0;
4c79b5
4c79b5
	if (!is_array($move_msg_ids))
4c79b5
	{
4c79b5
		$move_msg_ids = array($move_msg_ids);
4c79b5
	}
4c79b5
4c79b5
	if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) &&
4c79b5
		!in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder)
4c79b5
	{
4c79b5
		// We have to check the destination folder ;)
4c79b5
		if ($dest_folder != PRIVMSGS_INBOX)
4c79b5
		{
4c79b5
			$sql = 'SELECT folder_id, folder_name, pm_count
4c79b5
				FROM ' . PRIVMSGS_FOLDER_TABLE . "
4c79b5
				WHERE folder_id = $dest_folder
4c79b5
					AND user_id = $user_id";
4c79b5
			$result = $db->sql_query($sql);
4c79b5
			$row = $db->sql_fetchrow($result);
4c79b5
			$db->sql_freeresult($result);
4c79b5
4c79b5
			if (!$row)
4c79b5
			{
4c79b5
				trigger_error('NOT_AUTHORISED');
4c79b5
			}
4c79b5
4c79b5
			if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit)
4c79b5
			{
4c79b5
				$message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '

';
4c79b5
				$message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '', '', $row['folder_name']);
4c79b5
				trigger_error($message);
4c79b5
			}
4c79b5
		}
4c79b5
		else
4c79b5
		{
4c79b5
			$sql = 'SELECT COUNT(msg_id) as num_messages
4c79b5
				FROM ' . PRIVMSGS_TO_TABLE . '
4c79b5
				WHERE folder_id = ' . PRIVMSGS_INBOX . "
4c79b5
					AND user_id = $user_id";
4c79b5
			$result = $db->sql_query($sql);
4c79b5
			$num_messages = (int) $db->sql_fetchfield('num_messages');
4c79b5
			$db->sql_freeresult($result);
4c79b5
4c79b5
			if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit)
4c79b5
			{
4c79b5
				$message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '

';
4c79b5
				$message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '', '', $user->lang['PM_INBOX']);
4c79b5
				trigger_error($message);
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
4c79b5
			SET folder_id = $dest_folder
4c79b5
			WHERE folder_id = $cur_folder_id
4c79b5
				AND user_id = $user_id
4c79b5
				AND " . $db->sql_in_set('msg_id', $move_msg_ids);
4c79b5
		$db->sql_query($sql);
4c79b5
		$num_moved = $db->sql_affectedrows();
4c79b5
4c79b5
		// Update pm counts
4c79b5
		if ($num_moved)
4c79b5
		{
4c79b5
			if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)))
4c79b5
			{
4c79b5
				$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
4c79b5
					SET pm_count = pm_count - $num_moved
4c79b5
					WHERE folder_id = $cur_folder_id
4c79b5
						AND user_id = $user_id";
4c79b5
				$db->sql_query($sql);
4c79b5
			}
4c79b5
4c79b5
			if ($dest_folder != PRIVMSGS_INBOX)
4c79b5
			{
4c79b5
				$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
4c79b5
					SET pm_count = pm_count + $num_moved
4c79b5
					WHERE folder_id = $dest_folder
4c79b5
						AND user_id = $user_id";
4c79b5
				$db->sql_query($sql);
4c79b5
			}
4c79b5
		}
4c79b5
	}
4c79b5
	else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)))
4c79b5
	{
4c79b5
		trigger_error('CANNOT_MOVE_SPECIAL');
4c79b5
	}
4c79b5
4c79b5
	return $num_moved;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Update unread message status
4c79b5
*/
4c79b5
function update_unread_status($unread, $msg_id, $user_id, $folder_id)
4c79b5
{
4c79b5
	if (!$unread)
4c79b5
	{
4c79b5
		return;
4c79b5
	}
4c79b5
4c79b5
	global $db, $user;
4c79b5
4c79b5
	$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
4c79b5
		SET pm_unread = 0
4c79b5
		WHERE msg_id = $msg_id
4c79b5
			AND user_id = $user_id
4c79b5
			AND folder_id = $folder_id";
4c79b5
	$db->sql_query($sql);
4c79b5
4c79b5
	$sql = 'UPDATE ' . USERS_TABLE . "
4c79b5
		SET user_unread_privmsg = user_unread_privmsg - 1
4c79b5
		WHERE user_id = $user_id";
4c79b5
	$db->sql_query($sql);
4c79b5
4c79b5
	if ($user->data['user_id'] == $user_id)
4c79b5
	{
4c79b5
		$user->data['user_unread_privmsg']--;
4c79b5
4c79b5
		// Try to cope with previous wrong conversions...
4c79b5
		if ($user->data['user_unread_privmsg'] < 0)
4c79b5
		{
4c79b5
			$sql = 'UPDATE ' . USERS_TABLE . "
4c79b5
				SET user_unread_privmsg = 0
4c79b5
				WHERE user_id = $user_id";
4c79b5
			$db->sql_query($sql);
4c79b5
4c79b5
			$user->data['user_unread_privmsg'] = 0;
4c79b5
		}
4c79b5
	}
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Handle all actions possible with marked messages
4c79b5
*/
4c79b5
function handle_mark_actions($user_id, $mark_action)
4c79b5
{
4c79b5
	global $db, $user, $phpbb_root_path, $phpEx;
4c79b5
4c79b5
	$msg_ids		= request_var('marked_msg_id', array(0));
4c79b5
	$cur_folder_id	= request_var('cur_folder_id', PRIVMSGS_NO_BOX);
4c79b5
	$confirm		= (isset($_POST['confirm'])) ? true : false;
4c79b5
4c79b5
	if (!sizeof($msg_ids))
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	switch ($mark_action)
4c79b5
	{
4c79b5
		case 'mark_important':
4c79b5
4c79b5
			$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
4c79b5
				SET pm_marked = 1 - pm_marked
4c79b5
				WHERE folder_id = $cur_folder_id
4c79b5
					AND user_id = $user_id
4c79b5
					AND " . $db->sql_in_set('msg_id', $msg_ids);
4c79b5
			$db->sql_query($sql);
4c79b5
4c79b5
		break;
4c79b5
4c79b5
		case 'delete_marked':
4c79b5
4c79b5
			if (confirm_box(true))
4c79b5
			{
4c79b5
				delete_pm($user_id, $msg_ids, $cur_folder_id);
4c79b5
4c79b5
				$success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED';
4c79b5
				$redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id);
4c79b5
4c79b5
				meta_refresh(3, $redirect);
4c79b5
				trigger_error($user->lang[$success_msg] . '

' . sprintf($user->lang['RETURN_FOLDER'], '', ''));
4c79b5
			}
4c79b5
			else
4c79b5
			{
4c79b5
				$s_hidden_fields = array(
4c79b5
					'cur_folder_id'	=> $cur_folder_id,
4c79b5
					'mark_option'	=> 'delete_marked',
4c79b5
					'submit_mark'	=> true,
4c79b5
					'marked_msg_id'	=> $msg_ids
4c79b5
				);
4c79b5
4c79b5
				confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
4c79b5
			}
4c79b5
4c79b5
		break;
4c79b5
4c79b5
		default:
4c79b5
			return false;
4c79b5
	}
4c79b5
4c79b5
	return true;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Delete PM(s)
4c79b5
*/
4c79b5
function delete_pm($user_id, $msg_ids, $folder_id)
4c79b5
{
4c79b5
	global $db, $user, $phpbb_root_path, $phpEx;
4c79b5
4c79b5
	$user_id	= (int) $user_id;
4c79b5
	$folder_id	= (int) $folder_id;
4c79b5
4c79b5
	if (!$user_id)
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	if (!is_array($msg_ids))
4c79b5
	{
4c79b5
		if (!$msg_ids)
4c79b5
		{
4c79b5
			return false;
4c79b5
		}
4c79b5
		$msg_ids = array($msg_ids);
4c79b5
	}
4c79b5
4c79b5
	if (!sizeof($msg_ids))
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	// Get PM Information for later deleting
4c79b5
	$sql = 'SELECT msg_id, pm_unread, pm_new
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . '
4c79b5
		WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
4c79b5
			AND folder_id = $folder_id
4c79b5
			AND user_id = $user_id";
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	$delete_rows = array();
4c79b5
	$num_unread = $num_new = $num_deleted = 0;
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		$num_unread += (int) $row['pm_unread'];
4c79b5
		$num_new += (int) $row['pm_new'];
4c79b5
4c79b5
		$delete_rows[$row['msg_id']] = 1;
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
	unset($msg_ids);
4c79b5
4c79b5
	if (!sizeof($delete_rows))
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	$db->sql_transaction('begin');
4c79b5
4c79b5
	// if no one has read the message yet (meaning it is in users outbox)
4c79b5
	// then mark the message as deleted...
4c79b5
	if ($folder_id == PRIVMSGS_OUTBOX)
4c79b5
	{
4c79b5
		// Remove PM from Outbox
4c79b5
		$sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
			WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . '
4c79b5
				AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
4c79b5
		$db->sql_query($sql);
4c79b5
4c79b5
		// Update PM Information for safety
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = ''
4c79b5
			WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
4c79b5
		$db->sql_query($sql);
4c79b5
4c79b5
		// Set delete flag for those intended to receive the PM
4c79b5
		// We do not remove the message actually, to retain some basic information (sent time for example)
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
			SET pm_deleted = 1
4c79b5
			WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
4c79b5
		$db->sql_query($sql);
4c79b5
4c79b5
		$num_deleted = $db->sql_affectedrows();
4c79b5
	}
4c79b5
	else
4c79b5
	{
4c79b5
		// Delete private message data
4c79b5
		$sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
4c79b5
			WHERE user_id = $user_id
4c79b5
				AND folder_id = $folder_id
4c79b5
				AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
4c79b5
		$db->sql_query($sql);
4c79b5
		$num_deleted = $db->sql_affectedrows();
4c79b5
	}
4c79b5
4c79b5
	// if folder id is user defined folder then decrease pm_count
4c79b5
	if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX)))
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
4c79b5
			SET pm_count = pm_count - $num_deleted
4c79b5
			WHERE folder_id = $folder_id";
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// Update unread and new status field
4c79b5
	if ($num_unread || $num_new)
4c79b5
	{
4c79b5
		$set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
4c79b5
4c79b5
		if ($num_new)
4c79b5
		{
4c79b5
			$set_sql .= ($set_sql != '') ? ', ' : '';
4c79b5
			$set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
4c79b5
		}
4c79b5
4c79b5
		$db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
4c79b5
4c79b5
		$user->data['user_new_privmsg'] -= $num_new;
4c79b5
		$user->data['user_unread_privmsg'] -= $num_unread;
4c79b5
	}
4c79b5
4c79b5
	// Now we have to check which messages we can delete completely
4c79b5
	$sql = 'SELECT msg_id
4c79b5
		FROM ' . PRIVMSGS_TO_TABLE . '
4c79b5
		WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		unset($delete_rows[$row['msg_id']]);
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	$delete_ids = array_keys($delete_rows);
4c79b5
4c79b5
	if (sizeof($delete_ids))
4c79b5
	{
4c79b5
		// Check if there are any attachments we need to remove
4c79b5
		if (!function_exists('delete_attachments'))
4c79b5
		{
4c79b5
			include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
4c79b5
		}
4c79b5
4c79b5
		delete_attachments('message', $delete_ids, false);
4c79b5
4c79b5
		$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
4c79b5
			WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	$db->sql_transaction('commit');
4c79b5
4c79b5
	return true;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Rebuild message header
4c79b5
*/
4c79b5
function rebuild_header($check_ary)
4c79b5
{
4c79b5
	global $db;
4c79b5
4c79b5
	$address = array();
4c79b5
4c79b5
	foreach ($check_ary as $check_type => $address_field)
4c79b5
	{
4c79b5
		// Split Addresses into users and groups
4c79b5
		preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
4c79b5
4c79b5
		$u = $g = array();
4c79b5
		foreach ($match[1] as $id => $type)
4c79b5
		{
4c79b5
			${$type}[] = (int) $match[2][$id];
4c79b5
		}
4c79b5
4c79b5
		$_types = array('u', 'g');
4c79b5
		foreach ($_types as $type)
4c79b5
		{
4c79b5
			if (sizeof($$type))
4c79b5
			{
4c79b5
				foreach ($$type as $id)
4c79b5
				{
4c79b5
					$address[$type][$id] = $check_type;
4c79b5
				}
4c79b5
			}
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	return $address;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Print out/assign recipient information
4c79b5
*/
4c79b5
function write_pm_addresses($check_ary, $author_id, $plaintext = false)
4c79b5
{
4c79b5
	global $db, $user, $template, $phpbb_root_path, $phpEx;
4c79b5
4c79b5
	$addresses = array();
4c79b5
4c79b5
	foreach ($check_ary as $check_type => $address_field)
4c79b5
	{
4c79b5
		if (!is_array($address_field))
4c79b5
		{
4c79b5
			// Split Addresses into users and groups
4c79b5
			preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
4c79b5
4c79b5
			$u = $g = array();
4c79b5
			foreach ($match[1] as $id => $type)
4c79b5
			{
4c79b5
				${$type}[] = (int) $match[2][$id];
4c79b5
			}
4c79b5
		}
4c79b5
		else
4c79b5
		{
4c79b5
			$u = $address_field['u'];
4c79b5
			$g = $address_field['g'];
4c79b5
		}
4c79b5
4c79b5
		$address = array();
4c79b5
		if (sizeof($u))
4c79b5
		{
4c79b5
			$sql = 'SELECT user_id, username, user_colour
4c79b5
				FROM ' . USERS_TABLE . '
4c79b5
				WHERE ' . $db->sql_in_set('user_id', $u) . '
4c79b5
					AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
4c79b5
			$result = $db->sql_query($sql);
4c79b5
4c79b5
			while ($row = $db->sql_fetchrow($result))
4c79b5
			{
4c79b5
				if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
4c79b5
				{
4c79b5
					if ($plaintext)
4c79b5
					{
4c79b5
						$address[] = $row['username'];
4c79b5
					}
4c79b5
					else
4c79b5
					{
4c79b5
						$address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
4c79b5
					}
4c79b5
				}
4c79b5
			}
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
4c79b5
		if (sizeof($g))
4c79b5
		{
4c79b5
			if ($plaintext)
4c79b5
			{
4c79b5
				$sql = 'SELECT group_name, group_type
4c79b5
					FROM ' . GROUPS_TABLE . '
4c79b5
						WHERE ' . $db->sql_in_set('group_id', $g);
4c79b5
				$result = $db->sql_query($sql);
4c79b5
4c79b5
				while ($row = $db->sql_fetchrow($result))
4c79b5
				{
4c79b5
					if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
4c79b5
					{
4c79b5
						$address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
4c79b5
					}
4c79b5
				}
4c79b5
				$db->sql_freeresult($result);
4c79b5
			}
4c79b5
			else
4c79b5
			{
4c79b5
				$sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
4c79b5
					FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
4c79b5
						WHERE ' . $db->sql_in_set('g.group_id', $g) . '
4c79b5
						AND g.group_id = ug.group_id
4c79b5
						AND ug.user_pending = 0';
4c79b5
				$result = $db->sql_query($sql);
4c79b5
4c79b5
				while ($row = $db->sql_fetchrow($result))
4c79b5
				{
4c79b5
					if (!isset($address['group'][$row['group_id']]))
4c79b5
					{
4c79b5
						if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
4c79b5
						{
4c79b5
							$row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
4c79b5
							$address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
4c79b5
						}
4c79b5
					}
4c79b5
4c79b5
					if (isset($address['user'][$row['user_id']]))
4c79b5
					{
4c79b5
						$address['user'][$row['user_id']]['in_group'] = $row['group_id'];
4c79b5
					}
4c79b5
				}
4c79b5
				$db->sql_freeresult($result);
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		if (sizeof($address) && !$plaintext)
4c79b5
		{
4c79b5
			$template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
4c79b5
4c79b5
			foreach ($address as $type => $adr_ary)
4c79b5
			{
4c79b5
				foreach ($adr_ary as $id => $row)
4c79b5
				{
4c79b5
					$tpl_ary = array(
4c79b5
						'IS_GROUP'	=> ($type == 'group') ? true : false,
4c79b5
						'IS_USER'	=> ($type == 'user') ? true : false,
4c79b5
						'UG_ID'		=> $id,
4c79b5
						'NAME'		=> $row['name'],
4c79b5
						'COLOUR'	=> ($row['colour']) ? '#' . $row['colour'] : '',
4c79b5
						'TYPE'		=> $type,
4c79b5
					);
4c79b5
4c79b5
					if ($type == 'user')
4c79b5
					{
4c79b5
						$tpl_ary = array_merge($tpl_ary, array(
4c79b5
							'U_VIEW'		=> get_username_string('profile', $id, $row['name'], $row['colour']),
4c79b5
							'NAME_FULL'		=> get_username_string('full', $id, $row['name'], $row['colour']),
4c79b5
						));
4c79b5
					}
4c79b5
					else
4c79b5
					{
4c79b5
						$tpl_ary = array_merge($tpl_ary, array(
4c79b5
							'U_VIEW'		=> append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id),
4c79b5
						));
4c79b5
					}
4c79b5
4c79b5
					$template->assign_block_vars($check_type . '_recipient', $tpl_ary);
4c79b5
				}
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		$addresses[$check_type] = $address;
4c79b5
	}
4c79b5
4c79b5
	return $addresses;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Get folder status
4c79b5
*/
4c79b5
function get_folder_status($folder_id, $folder)
4c79b5
{
4c79b5
	global $db, $user, $config;
4c79b5
4c79b5
	if (isset($folder[$folder_id]))
4c79b5
	{
4c79b5
		$folder = $folder[$folder_id];
4c79b5
	}
4c79b5
	else
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	$return = array(
4c79b5
		'folder_name'	=> $folder['folder_name'],
4c79b5
		'cur'			=> $folder['num_messages'],
4c79b5
		'remaining'		=> ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0,
4c79b5
		'max'			=> $user->data['message_limit'],
4c79b5
		'percent'		=> ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0,
4c79b5
	);
4c79b5
4c79b5
	$return['message']	= sprintf($user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']);
4c79b5
4c79b5
	return $return;
4c79b5
}
4c79b5
4c79b5
//
4c79b5
// COMPOSE MESSAGES
4c79b5
//
4c79b5
4c79b5
/**
4c79b5
* Submit PM
4c79b5
*/
4c79b5
function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
4c79b5
{
4c79b5
	global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path;
4c79b5
4c79b5
	// We do not handle erasing pms here
4c79b5
	if ($mode == 'delete')
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	$current_time = time();
4c79b5
4c79b5
	// Collect some basic information about which tables and which rows to update/insert
4c79b5
	$sql_data = array();
4c79b5
	$root_level = 0;
4c79b5
4c79b5
	// Recipient Information
4c79b5
	$recipients = $to = $bcc = array();
4c79b5
4c79b5
	if ($mode != 'edit')
4c79b5
	{
4c79b5
		// Build Recipient List
4c79b5
		// u|g => array($user_id => 'to'|'bcc')
4c79b5
		$_types = array('u', 'g');
4c79b5
		foreach ($_types as $ug_type)
4c79b5
		{
4c79b5
			if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
4c79b5
			{
4c79b5
				foreach ($data['address_list'][$ug_type] as $id => $field)
4c79b5
				{
4c79b5
					$id = (int) $id;
4c79b5
4c79b5
					// Do not rely on the address list being "valid"
4c79b5
					if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
4c79b5
					{
4c79b5
						continue;
4c79b5
					}
4c79b5
4c79b5
					$field = ($field == 'to') ? 'to' : 'bcc';
4c79b5
					if ($ug_type == 'u')
4c79b5
					{
4c79b5
						$recipients[$id] = $field;
4c79b5
					}
4c79b5
					${$field}[] = $ug_type . '_' . $id;
4c79b5
				}
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
4c79b5
		{
4c79b5
			// We need to check the PM status of group members (do they want to receive PM's?)
4c79b5
			// Only check if not a moderator or admin, since they are allowed to override this user setting
4c79b5
			$sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : '';
4c79b5
4c79b5
			$sql = 'SELECT u.user_type, ug.group_id, ug.user_id
4c79b5
				FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
4c79b5
				WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
4c79b5
					AND ug.user_pending = 0
4c79b5
					AND u.user_id = ug.user_id
4c79b5
					AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' . 
4c79b5
					$sql_allow_pm;
4c79b5
			$result = $db->sql_query($sql);
4c79b5
4c79b5
			while ($row = $db->sql_fetchrow($result))
4c79b5
			{
4c79b5
				$field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
4c79b5
				$recipients[$row['user_id']] = $field;
4c79b5
			}
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
4c79b5
		if (!sizeof($recipients))
4c79b5
		{
4c79b5
			trigger_error('NO_RECIPIENT');
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	$db->sql_transaction('begin');
4c79b5
4c79b5
	$sql = '';
4c79b5
4c79b5
	switch ($mode)
4c79b5
	{
4c79b5
		case 'reply':
4c79b5
		case 'quote':
4c79b5
			$root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
4c79b5
4c79b5
			// Set message_replied switch for this user
4c79b5
			$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
4c79b5
				SET pm_replied = 1
4c79b5
				WHERE user_id = ' . $data['from_user_id'] . '
4c79b5
					AND msg_id = ' . $data['reply_from_msg_id'];
4c79b5
4c79b5
		// no break
4c79b5
4c79b5
		case 'forward':
4c79b5
		case 'post':
4c79b5
		case 'quotepost':
4c79b5
			$sql_data = array(
4c79b5
				'root_level'		=> $root_level,
4c79b5
				'author_id'			=> $data['from_user_id'],
4c79b5
				'icon_id'			=> $data['icon_id'],
4c79b5
				'author_ip'			=> $data['from_user_ip'],
4c79b5
				'message_time'		=> $current_time,
4c79b5
				'enable_bbcode'		=> $data['enable_bbcode'],
4c79b5
				'enable_smilies'	=> $data['enable_smilies'],
4c79b5
				'enable_magic_url'	=> $data['enable_urls'],
4c79b5
				'enable_sig'		=> $data['enable_sig'],
4c79b5
				'message_subject'	=> $subject,
4c79b5
				'message_text'		=> $data['message'],
4c79b5
				'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
4c79b5
				'bbcode_bitfield'	=> $data['bbcode_bitfield'],
4c79b5
				'bbcode_uid'		=> $data['bbcode_uid'],
4c79b5
				'to_address'		=> implode(':', $to),
4c79b5
				'bcc_address'		=> implode(':', $bcc)
4c79b5
			);
4c79b5
		break;
4c79b5
4c79b5
		case 'edit':
4c79b5
			$sql_data = array(
4c79b5
				'icon_id'			=> $data['icon_id'],
4c79b5
				'message_edit_time'	=> $current_time,
4c79b5
				'enable_bbcode'		=> $data['enable_bbcode'],
4c79b5
				'enable_smilies'	=> $data['enable_smilies'],
4c79b5
				'enable_magic_url'	=> $data['enable_urls'],
4c79b5
				'enable_sig'		=> $data['enable_sig'],
4c79b5
				'message_subject'	=> $subject,
4c79b5
				'message_text'		=> $data['message'],
4c79b5
				'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
4c79b5
				'bbcode_bitfield'	=> $data['bbcode_bitfield'],
4c79b5
				'bbcode_uid'		=> $data['bbcode_uid']
4c79b5
			);
4c79b5
		break;
4c79b5
	}
4c79b5
4c79b5
	if (sizeof($sql_data))
4c79b5
	{
4c79b5
		$query = '';
4c79b5
4c79b5
		if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
4c79b5
		{
4c79b5
			$db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
4c79b5
			$data['msg_id'] = $db->sql_nextid();
4c79b5
		}
4c79b5
		else if ($mode == 'edit')
4c79b5
		{
4c79b5
			$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
4c79b5
				SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
4c79b5
				WHERE msg_id = ' . $data['msg_id'];
4c79b5
			$db->sql_query($sql);
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	if ($mode != 'edit')
4c79b5
	{
4c79b5
		if ($sql)
4c79b5
		{
4c79b5
			$db->sql_query($sql);
4c79b5
		}
4c79b5
		unset($sql);
4c79b5
4c79b5
		$sql_ary = array();
4c79b5
		foreach ($recipients as $user_id => $type)
4c79b5
		{
4c79b5
			$sql_ary[] = array(
4c79b5
				'msg_id'		=> (int) $data['msg_id'],
4c79b5
				'user_id'		=> (int) $user_id,
4c79b5
				'author_id'		=> (int) $data['from_user_id'],
4c79b5
				'folder_id'		=> PRIVMSGS_NO_BOX,
4c79b5
				'pm_new'		=> 1,
4c79b5
				'pm_unread'		=> 1,
4c79b5
				'pm_forwarded'	=> ($mode == 'forward') ? 1 : 0
4c79b5
			);
4c79b5
		}
4c79b5
4c79b5
		$db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
4c79b5
4c79b5
		$sql = 'UPDATE ' . USERS_TABLE . '
4c79b5
			SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
4c79b5
			WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
4c79b5
		$db->sql_query($sql);
4c79b5
4c79b5
		// Put PM into outbox
4c79b5
		if ($put_in_outbox)
4c79b5
		{
4c79b5
			$db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
4c79b5
				'msg_id'		=> (int) $data['msg_id'],
4c79b5
				'user_id'		=> (int) $data['from_user_id'],
4c79b5
				'author_id'		=> (int) $data['from_user_id'],
4c79b5
				'folder_id'		=> PRIVMSGS_OUTBOX,
4c79b5
				'pm_new'		=> 0,
4c79b5
				'pm_unread'		=> 0,
4c79b5
				'pm_forwarded'	=> ($mode == 'forward') ? 1 : 0))
4c79b5
			);
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	// Set user last post time
4c79b5
	if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post')
4c79b5
	{
4c79b5
		$sql = 'UPDATE ' . USERS_TABLE . "
4c79b5
			SET user_lastpost_time = $current_time
4c79b5
			WHERE user_id = " . $data['from_user_id'];
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	// Submit Attachments
4c79b5
	if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
4c79b5
	{
4c79b5
		$space_taken = $files_added = 0;
4c79b5
		$orphan_rows = array();
4c79b5
4c79b5
		foreach ($data['attachment_data'] as $pos => $attach_row)
4c79b5
		{
4c79b5
			$orphan_rows[(int) $attach_row['attach_id']] = array();
4c79b5
		}
4c79b5
4c79b5
		if (sizeof($orphan_rows))
4c79b5
		{
4c79b5
			$sql = 'SELECT attach_id, filesize, physical_filename
4c79b5
				FROM ' . ATTACHMENTS_TABLE . '
4c79b5
				WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
4c79b5
					AND in_message = 1
4c79b5
					AND is_orphan = 1
4c79b5
					AND poster_id = ' . $user->data['user_id'];
4c79b5
			$result = $db->sql_query($sql);
4c79b5
4c79b5
			$orphan_rows = array();
4c79b5
			while ($row = $db->sql_fetchrow($result))
4c79b5
			{
4c79b5
				$orphan_rows[$row['attach_id']] = $row;
4c79b5
			}
4c79b5
			$db->sql_freeresult($result);
4c79b5
		}
4c79b5
4c79b5
		foreach ($data['attachment_data'] as $pos => $attach_row)
4c79b5
		{
4c79b5
			if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
4c79b5
			{
4c79b5
				continue;
4c79b5
			}
4c79b5
4c79b5
			if (!$attach_row['is_orphan'])
4c79b5
			{
4c79b5
				// update entry in db if attachment already stored in db and filespace
4c79b5
				$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
4c79b5
					SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
4c79b5
					WHERE attach_id = " . (int) $attach_row['attach_id'] . '
4c79b5
						AND is_orphan = 0';
4c79b5
				$db->sql_query($sql);
4c79b5
			}
4c79b5
			else
4c79b5
			{
4c79b5
				// insert attachment into db
4c79b5
				if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
4c79b5
				{
4c79b5
					continue;
4c79b5
				}
4c79b5
4c79b5
				$space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
4c79b5
				$files_added++;
4c79b5
4c79b5
				$attach_sql = array(
4c79b5
					'post_msg_id'		=> $data['msg_id'],
4c79b5
					'topic_id'			=> 0,
4c79b5
					'is_orphan'			=> 0,
4c79b5
					'poster_id'			=> $data['from_user_id'],
4c79b5
					'attach_comment'	=> $attach_row['attach_comment'],
4c79b5
				);
4c79b5
4c79b5
				$sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
4c79b5
					WHERE attach_id = ' . $attach_row['attach_id'] . '
4c79b5
						AND is_orphan = 1
4c79b5
						AND poster_id = ' . $user->data['user_id'];
4c79b5
				$db->sql_query($sql);
4c79b5
			}
4c79b5
		}
4c79b5
4c79b5
		if ($space_taken && $files_added)
4c79b5
		{
4c79b5
			set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
4c79b5
			set_config('num_files', $config['num_files'] + $files_added, true);
4c79b5
		}
4c79b5
	}
4c79b5
4c79b5
	// Delete draft if post was loaded...
4c79b5
	$draft_id = request_var('draft_loaded', 0);
4c79b5
	if ($draft_id)
4c79b5
	{
4c79b5
		$sql = 'DELETE FROM ' . DRAFTS_TABLE . "
4c79b5
			WHERE draft_id = $draft_id
4c79b5
				AND user_id = " . $data['from_user_id'];
4c79b5
		$db->sql_query($sql);
4c79b5
	}
4c79b5
4c79b5
	$db->sql_transaction('commit');
4c79b5
4c79b5
	// Send Notifications
4c79b5
	if ($mode != 'edit')
4c79b5
	{
4c79b5
		pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
4c79b5
	}
4c79b5
4c79b5
	return $data['msg_id'];
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* PM Notification
4c79b5
*/
4c79b5
function pm_notification($mode, $author, $recipients, $subject, $message)
4c79b5
{
4c79b5
	global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
4c79b5
4c79b5
	$subject = censor_text($subject);
4c79b5
4c79b5
	unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
4c79b5
4c79b5
	if (!sizeof($recipients))
4c79b5
	{
4c79b5
		return;
4c79b5
	}
4c79b5
4c79b5
	// Get banned User ID's
4c79b5
	$sql = 'SELECT ban_userid
4c79b5
		FROM ' . BANLIST_TABLE . '
4c79b5
		WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
4c79b5
			AND ban_exclude = 0';
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		unset($recipients[$row['ban_userid']]);
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	if (!sizeof($recipients))
4c79b5
	{
4c79b5
		return;
4c79b5
	}
4c79b5
4c79b5
	$sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
4c79b5
		FROM ' . USERS_TABLE . '
4c79b5
		WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
4c79b5
	$result = $db->sql_query($sql);
4c79b5
4c79b5
	$msg_list_ary = array();
4c79b5
	while ($row = $db->sql_fetchrow($result))
4c79b5
	{
4c79b5
		if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
4c79b5
		{
4c79b5
			$msg_list_ary[] = array(
4c79b5
				'method'	=> $row['user_notify_type'],
4c79b5
				'email'		=> $row['user_email'],
4c79b5
				'jabber'	=> $row['user_jabber'],
4c79b5
				'name'		=> $row['username'],
4c79b5
				'lang'		=> $row['user_lang']
4c79b5
			);
4c79b5
		}
4c79b5
	}
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	if (!sizeof($msg_list_ary))
4c79b5
	{
4c79b5
		return;
4c79b5
	}
4c79b5
4c79b5
	include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
4c79b5
	$messenger = new messenger();
4c79b5
4c79b5
	foreach ($msg_list_ary as $pos => $addr)
4c79b5
	{
4c79b5
		$messenger->template('privmsg_notify', $addr['lang']);
4c79b5
4c79b5
		$messenger->to($addr['email'], $addr['name']);
4c79b5
		$messenger->im($addr['jabber'], $addr['name']);
4c79b5
4c79b5
		$messenger->assign_vars(array(
4c79b5
			'SUBJECT'		=> htmlspecialchars_decode($subject),
4c79b5
			'AUTHOR_NAME'	=> htmlspecialchars_decode($author),
4c79b5
			'USERNAME'		=> htmlspecialchars_decode($addr['name']),
4c79b5
4c79b5
			'U_INBOX'		=> generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox")
4c79b5
		);
4c79b5
4c79b5
		$messenger->send($addr['method']);
4c79b5
	}
4c79b5
	unset($msg_list_ary);
4c79b5
4c79b5
	$messenger->save_queue();
4c79b5
4c79b5
	unset($messenger);
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Display Message History
4c79b5
*/
4c79b5
function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
4c79b5
{
4c79b5
	global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode;
4c79b5
4c79b5
	// Get History Messages (could be newer)
4c79b5
	$sql = 'SELECT t.*, p.*, u.*
4c79b5
		FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u
4c79b5
		WHERE t.msg_id = p.msg_id
4c79b5
			AND p.author_id = u.user_id
4c79b5
			AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ")
4c79b5
			AND t.user_id = $user_id";
4c79b5
4c79b5
	if (!$message_row['root_level'])
4c79b5
	{
4c79b5
		$sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
4c79b5
	}
4c79b5
	else
4c79b5
	{
4c79b5
		$sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';
4c79b5
	}
4c79b5
	$sql .= ' ORDER BY p.message_time DESC';
4c79b5
4c79b5
	$result = $db->sql_query($sql);
4c79b5
	$row = $db->sql_fetchrow($result);
4c79b5
4c79b5
	if (!$row)
4c79b5
	{
4c79b5
		$db->sql_freeresult($result);
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	$rowset = array();
4c79b5
	$bbcode_bitfield = '';
4c79b5
	$folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder=';
4c79b5
4c79b5
	do
4c79b5
	{
4c79b5
		$folder_id = (int) $row['folder_id'];
4c79b5
4c79b5
		$row['folder'][] = (isset($folder[$folder_id])) ? '' . $folder[$folder_id]['folder_name'] . '' : $user->lang['UNKNOWN_FOLDER'];
4c79b5
4c79b5
		if (isset($rowset[$row['msg_id']]))
4c79b5
		{
4c79b5
			$rowset[$row['msg_id']]['folder'][] = (isset($folder[$folder_id])) ? '' . $folder[$folder_id]['folder_name'] . '' : $user->lang['UNKNOWN_FOLDER'];
4c79b5
		}
4c79b5
		else
4c79b5
		{
4c79b5
			$rowset[$row['msg_id']] = $row;
4c79b5
			$bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
4c79b5
		}
4c79b5
	}
4c79b5
	while ($row = $db->sql_fetchrow($result));
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	$title = $row['message_subject'];
4c79b5
4c79b5
	if (sizeof($rowset) == 1 && !$in_post_mode)
4c79b5
	{
4c79b5
		return false;
4c79b5
	}
4c79b5
4c79b5
	// Instantiate BBCode class
4c79b5
	if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '')
4c79b5
	{
4c79b5
		if (!class_exists('bbcode'))
4c79b5
		{
4c79b5
			include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
4c79b5
		}
4c79b5
		$bbcode = new bbcode(base64_encode($bbcode_bitfield));
4c79b5
	}
4c79b5
4c79b5
	$title = censor_text($title);
4c79b5
4c79b5
	$url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
4c79b5
	$next_history_pm = $previous_history_pm = $prev_id = 0;
4c79b5
4c79b5
	foreach ($rowset as $id => $row)
4c79b5
	{
4c79b5
		$author_id	= $row['author_id'];
4c79b5
		$folder_id	= (int) $row['folder_id'];
4c79b5
4c79b5
		$subject	= $row['message_subject'];
4c79b5
		$message	= $row['message_text'];
4c79b5
4c79b5
		$message = censor_text($message);
4c79b5
4c79b5
		$decoded_message = false;
4c79b5
4c79b5
		if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id'])
4c79b5
		{
4c79b5
			$decoded_message = $message;
4c79b5
			decode_message($decoded_message, $row['bbcode_uid']);
4c79b5
4c79b5
			$decoded_message = bbcode_nl2br($decoded_message);
4c79b5
		}
4c79b5
4c79b5
		if ($row['bbcode_bitfield'])
4c79b5
		{
4c79b5
			$bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
4c79b5
		}
4c79b5
4c79b5
		$message = bbcode_nl2br($message);
4c79b5
		$message = smiley_text($message, !$row['enable_smilies']);
4c79b5
4c79b5
		$subject = censor_text($subject);
4c79b5
4c79b5
		if ($id == $msg_id)
4c79b5
		{
4c79b5
			$next_history_pm = next($rowset);
4c79b5
			$next_history_pm = (sizeof($next_history_pm)) ? (int) $next_history_pm['msg_id'] : 0;
4c79b5
			$previous_history_pm = $prev_id;
4c79b5
		}
4c79b5
4c79b5
		$template->assign_block_vars('history_row', array(
4c79b5
			'MESSAGE_AUTHOR_QUOTE'		=> (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''),
4c79b5
			'MESSAGE_AUTHOR_FULL'		=> get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),
4c79b5
			'MESSAGE_AUTHOR_COLOUR'		=> get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']),
4c79b5
			'MESSAGE_AUTHOR'			=> get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']),
4c79b5
			'U_MESSAGE_AUTHOR'			=> get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']),
4c79b5
4c79b5
			'SUBJECT'			=> $subject,
4c79b5
			'SENT_DATE'			=> $user->format_date($row['message_time']),
4c79b5
			'MESSAGE'			=> $message,
4c79b5
			'FOLDER'			=> implode(', ', $row['folder']),
4c79b5
			'DECODED_MESSAGE'	=> $decoded_message,
4c79b5
4c79b5
			'S_CURRENT_MSG'		=> ($row['msg_id'] == $msg_id),
4c79b5
			'S_AUTHOR_DELETED'	=> ($author_id == ANONYMOUS) ? true : false,
4c79b5
			'S_IN_POST_MODE'	=> $in_post_mode,
4c79b5
4c79b5
			'MSG_ID'			=> $row['msg_id'],
4c79b5
			'U_VIEW_MESSAGE'	=> "$url&f=$folder_id&p=" . $row['msg_id'],
4c79b5
			'U_QUOTE'			=> (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != $user->data['user_id']) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '',
4c79b5
			'U_POST_REPLY_PM'	=> ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '')
4c79b5
		);
4c79b5
		unset($rowset[$id]);
4c79b5
		$prev_id = $id;
4c79b5
	}
4c79b5
4c79b5
	$template->assign_vars(array(
4c79b5
		'QUOTE_IMG'			=> $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']),
4c79b5
		'HISTORY_TITLE'		=> $title,
4c79b5
4c79b5
		'U_VIEW_NEXT_HISTORY'		=> ($next_history_pm) ? "$url&p=" . $next_history_pm : '',
4c79b5
		'U_VIEW_PREVIOUS_HISTORY'	=> ($previous_history_pm) ? "$url&p=" . $previous_history_pm : '',
4c79b5
	));
4c79b5
4c79b5
	return true;
4c79b5
}
4c79b5
4c79b5
/**
4c79b5
* Set correct users max messages in PM folder.
4c79b5
* If several group memberships define different amount of messages, the highest will be chosen.
4c79b5
*/
4c79b5
function set_user_message_limit()
4c79b5
{
4c79b5
	global $user, $db, $config;
4c79b5
4c79b5
	// Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config.
4c79b5
	$sql = 'SELECT MAX(g.group_message_limit) as max_message_limit
4c79b5
		FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
4c79b5
		WHERE ug.user_id = ' . $user->data['user_id'] . '
4c79b5
			AND ug.user_pending = 0
4c79b5
			AND ug.group_id = g.group_id';
4c79b5
	$result = $db->sql_query($sql);
4c79b5
	$message_limit = (int) $db->sql_fetchfield('max_message_limit');
4c79b5
	$db->sql_freeresult($result);
4c79b5
4c79b5
	$user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
4c79b5
}
4c79b5
4c79b5
?>