Blame Identity/Webenv/phpBB/3.0.4/includes/functions_privmsgs.php

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

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

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

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