6 * @copyright (c) 2005 phpBB Group
7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
13 if (!defined('IN_PHPBB'))
19 Ability to simply add own rules by doing three things:
20 1) Add an appropriate constant
21 2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required)
22 3) Add a new language variable to ucp.php
24 The user is then able to select the new rule. It will be checked against and handled as specified.
25 To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified.
28 define('RULE_IS_LIKE', 1); // Is Like
29 define('RULE_IS_NOT_LIKE', 2); // Is Not Like
30 define('RULE_IS', 3); // Is
31 define('RULE_IS_NOT', 4); // Is Not
32 define('RULE_BEGINS_WITH', 5); // Begins with
33 define('RULE_ENDS_WITH', 6); // Ends with
34 define('RULE_IS_FRIEND', 7); // Is Friend
35 define('RULE_IS_FOE', 8); // Is Foe
36 define('RULE_IS_USER', 9); // Is User
37 define('RULE_IS_GROUP', 10); // Is In Usergroup
38 define('RULE_ANSWERED', 11); // Answered
39 define('RULE_FORWARDED', 12); // Forwarded
40 define('RULE_TO_GROUP', 14); // Usergroup
41 define('RULE_TO_ME', 15); // Me
43 define('ACTION_PLACE_INTO_FOLDER', 1);
44 define('ACTION_MARK_AS_READ', 2);
45 define('ACTION_MARK_AS_IMPORTANT', 3);
46 define('ACTION_DELETE_MESSAGE', 4);
48 define('CHECK_SUBJECT', 1);
49 define('CHECK_SENDER', 2);
50 define('CHECK_MESSAGE', 3);
51 define('CHECK_STATUS', 4);
52 define('CHECK_TO', 5);
55 * Global private message rules
56 * These rules define what to do if a rule is hit
58 $global_privmsgs_rules = array(
59 CHECK_SUBJECT
=> array(
60 RULE_IS_LIKE
=> array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
61 RULE_IS_NOT_LIKE
=> array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
62 RULE_IS
=> array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'),
63 RULE_IS_NOT
=> array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'),
64 RULE_BEGINS_WITH
=> array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
65 RULE_ENDS_WITH
=> array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
68 CHECK_SENDER
=> array(
69 RULE_IS_LIKE
=> array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
70 RULE_IS_NOT_LIKE
=> array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
71 RULE_IS
=> array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'),
72 RULE_IS_NOT
=> array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'),
73 RULE_BEGINS_WITH
=> array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
74 RULE_ENDS_WITH
=> array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'),
75 RULE_IS_FRIEND
=> array('check0' => 'friend', 'function' => '{CHECK0} == 1'),
76 RULE_IS_FOE
=> array('check0' => 'foe', 'function' => '{CHECK0} == 1'),
77 RULE_IS_USER
=> array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'),
78 RULE_IS_GROUP
=> array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'),
81 CHECK_MESSAGE
=> array(
82 RULE_IS_LIKE
=> array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'),
83 RULE_IS_NOT_LIKE
=> array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'),
84 RULE_IS
=> array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'),
85 RULE_IS_NOT
=> array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'),
88 CHECK_STATUS
=> array(
89 RULE_ANSWERED
=> array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'),
90 RULE_FORWARDED
=> array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'),
94 RULE_TO_GROUP
=> array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'),
95 RULE_TO_ME
=> array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'),
100 * This is for defining which condition fields to show for which Rule
102 $global_rule_conditions = array(
103 RULE_IS_LIKE
=> 'text',
104 RULE_IS_NOT_LIKE
=> 'text',
106 RULE_IS_NOT
=> 'text',
107 RULE_BEGINS_WITH
=> 'text',
108 RULE_ENDS_WITH
=> 'text',
109 RULE_IS_USER
=> 'user',
110 RULE_IS_GROUP
=> 'group'
116 function get_folder($user_id, $folder_id = false)
118 global $db, $user, $template;
122 // Get folder information
123 $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread
124 FROM ' . PRIVMSGS_TO_TABLE
. "
125 WHERE user_id = $user_id
126 AND folder_id <> " . PRIVMSGS_NO_BOX
. '
128 $result = $db->sql_query($sql);
130 $num_messages = $num_unread = array();
131 while ($row = $db->sql_fetchrow($result))
133 $num_messages[(int) $row['folder_id']] = $row['num_messages'];
134 $num_unread[(int) $row['folder_id']] = $row['num_unread'];
136 $db->sql_freeresult($result);
138 // Make sure the default boxes are defined
139 $available_folder = array(PRIVMSGS_INBOX
, PRIVMSGS_OUTBOX
, PRIVMSGS_SENTBOX
);
141 foreach ($available_folder as $default_folder)
143 if (!isset($num_messages[$default_folder]))
145 $num_messages[$default_folder] = 0;
148 if (!isset($num_unread[$default_folder]))
150 $num_unread[$default_folder] = 0;
154 // Adjust unread status for outbox
155 $num_unread[PRIVMSGS_OUTBOX
] = $num_messages[PRIVMSGS_OUTBOX
];
157 $folder[PRIVMSGS_INBOX
] = array(
158 'folder_name' => $user->lang
['PM_INBOX'],
159 'num_messages' => $num_messages[PRIVMSGS_INBOX
],
160 'unread_messages' => $num_unread[PRIVMSGS_INBOX
]
164 $sql = 'SELECT folder_id, folder_name, pm_count
165 FROM ' . PRIVMSGS_FOLDER_TABLE
. "
166 WHERE user_id = $user_id";
167 $result = $db->sql_query($sql);
169 while ($row = $db->sql_fetchrow($result))
171 $folder[$row['folder_id']] = array(
172 'folder_name' => $row['folder_name'],
173 'num_messages' => $row['pm_count'],
174 'unread_messages' => ((isset($num_unread[$row['folder_id']])) ?
$num_unread[$row['folder_id']] : 0)
177 $db->sql_freeresult($result);
179 $folder[PRIVMSGS_OUTBOX
] = array(
180 'folder_name' => $user->lang
['PM_OUTBOX'],
181 'num_messages' => $num_messages[PRIVMSGS_OUTBOX
],
182 'unread_messages' => $num_unread[PRIVMSGS_OUTBOX
]
185 $folder[PRIVMSGS_SENTBOX
] = array(
186 'folder_name' => $user->lang
['PM_SENTBOX'],
187 'num_messages' => $num_messages[PRIVMSGS_SENTBOX
],
188 'unread_messages' => $num_unread[PRIVMSGS_SENTBOX
]
191 // Define Folder Array for template designers (and for making custom folders usable by the template too)
192 foreach ($folder as $f_id => $folder_ary)
194 $folder_id_name = ($f_id == PRIVMSGS_INBOX
) ?
'inbox' : (($f_id == PRIVMSGS_OUTBOX
) ?
'outbox' : 'sentbox');
196 $template->assign_block_vars('folder', array(
197 'FOLDER_ID' => $f_id,
198 'FOLDER_NAME' => $folder_ary['folder_name'],
199 'NUM_MESSAGES' => $folder_ary['num_messages'],
200 'UNREAD_MESSAGES' => $folder_ary['unread_messages'],
202 'U_FOLDER' => ($f_id > 0) ?
append_sid('ucp', 'i=pm&folder=' . $f_id) : append_sid('ucp', 'i=pm&folder=' . $folder_id_name),
204 'S_CUR_FOLDER' => ($f_id === $folder_id) ?
true : false,
205 'S_UNREAD_MESSAGES' => ($folder_ary['unread_messages']) ?
true : false,
206 'S_CUSTOM_FOLDER' => ($f_id > 0) ?
true : false)
210 if ($folder_id !== false && !isset($folder[$folder_id]))
212 trigger_error('UNKNOWN_FOLDER');
219 * Delete Messages From Sentbox
220 * we are doing this here because this saves us a bunch of checks and queries
222 function clean_sentbox($num_sentbox_messages)
226 // Check Message Limit
227 if ($user->data
['message_limit'] && $num_sentbox_messages > $user->data
['message_limit'])
229 // Delete old messages
230 $sql = 'SELECT t.msg_id
231 FROM ' . PRIVMSGS_TO_TABLE
. ' t, ' . PRIVMSGS_TABLE
. ' p
232 WHERE t.msg_id = p.msg_id
233 AND t.user_id = ' . $user->data
['user_id'] . '
234 AND t.folder_id = ' . PRIVMSGS_SENTBOX
. '
235 ORDER BY p.message_time ASC';
236 $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data
['message_limit']));
238 $delete_ids = array();
239 while ($row = $db->sql_fetchrow($result))
241 $delete_ids[] = $row['msg_id'];
243 $db->sql_freeresult($result);
244 delete_pm($user->data
['user_id'], $delete_ids, PRIVMSGS_SENTBOX
);
249 * Check Rule against Message Information
251 function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
255 if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
260 $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
262 // Replace Check Literals
263 $evaluate = $check_ary['function'];
264 $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate);
266 // Replace Rule Literals
267 $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate);
271 eval('$result = (' . $evaluate . ') ? true : false;');
278 switch ($rule_row['rule_action'])
280 case ACTION_PLACE_INTO_FOLDER
:
281 return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
284 case ACTION_MARK_AS_READ
:
285 case ACTION_MARK_AS_IMPORTANT
:
286 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
289 case ACTION_DELETE_MESSAGE
:
292 // Check for admins/mods - users are not allowed to remove those messages...
293 // We do the check here to make sure the data we use is consistent
294 $sql = 'SELECT user_id, user_type, user_permissions
295 FROM ' . USERS_TABLE
. '
296 WHERE user_id = ' . (int) $message_row['author_id'];
297 $result = $db->sql_query($sql);
298 $userdata = $db->sql_fetchrow($result);
299 $db->sql_freeresult($result);
302 $auth2->acl($userdata);
304 if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
306 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
320 * Update user PM count
322 function update_pm_counts()
326 // Update unread count
327 $sql = 'SELECT COUNT(msg_id) as num_messages
328 FROM ' . PRIVMSGS_TO_TABLE
. '
330 AND folder_id <> ' . PRIVMSGS_OUTBOX
. '
331 AND user_id = ' . $user->data
['user_id'];
332 $result = $db->sql_query($sql);
333 $user->data
['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages');
334 $db->sql_freeresult($result);
336 // Update new pm count
337 $sql = 'SELECT COUNT(msg_id) as num_messages
338 FROM ' . PRIVMSGS_TO_TABLE
. '
340 AND folder_id IN (' . PRIVMSGS_NO_BOX
. ', ' . PRIVMSGS_HOLD_BOX
. ')
341 AND user_id = ' . $user->data
['user_id'];
342 $result = $db->sql_query($sql);
343 $user->data
['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages');
344 $db->sql_freeresult($result);
346 $db->sql_query('UPDATE ' . USERS_TABLE
. ' SET ' . $db->sql_build_array('UPDATE', array(
347 'user_unread_privmsg' => (int) $user->data
['user_unread_privmsg'],
348 'user_new_privmsg' => (int) $user->data
['user_new_privmsg'],
349 )) . ' WHERE user_id = ' . $user->data
['user_id']);
351 // Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag.
352 if (!$user->data
['user_new_privmsg'])
354 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
357 AND folder_id NOT IN (' . PRIVMSGS_NO_BOX
. ', ' . PRIVMSGS_HOLD_BOX
. ')
358 AND user_id = ' . $user->data
['user_id'];
359 $db->sql_query($sql);
364 * Place new messages into appropriate folder
366 function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
370 if (!$user->data
['user_new_privmsg'])
372 return array('not_moved' => 0, 'removed' => 0);
375 $user_message_rules = (int) $user->data
['user_message_rules'];
376 $user_id = (int) $user->data
['user_id'];
378 $action_ary = $move_into_folder = array();
381 // Newly processing on-hold messages
384 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
385 SET folder_id = ' . PRIVMSGS_NO_BOX
. '
386 WHERE folder_id = ' . PRIVMSGS_HOLD_BOX
. "
387 AND user_id = $user_id";
388 $db->sql_query($sql);
391 // Get those messages not yet placed into any box
392 $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
393 FROM ' . PRIVMSGS_TO_TABLE
. ' t, ' . PRIVMSGS_TABLE
. ' p, ' . USERS_TABLE
. " u
394 WHERE t.user_id = $user_id
395 AND p.author_id = u.user_id
396 AND t.folder_id = " . PRIVMSGS_NO_BOX
. '
397 AND t.msg_id = p.msg_id';
399 // Just place into the appropriate arrays if no rules need to be checked
400 if (!$user_message_rules)
402 $result = $db->sql_query($retrieve_sql);
404 while ($row = $db->sql_fetchrow($result))
406 $action_ary[$row['msg_id']][] = array('action' => false);
408 $db->sql_freeresult($result);
412 $user_rules = $zebra = $check_rows = array();
413 $user_ids = $memberships = array();
415 // First of all, grab all rules and retrieve friends/foes
417 FROM ' . PRIVMSGS_RULES_TABLE
. "
418 WHERE user_id = $user_id";
419 $result = $db->sql_query($sql);
420 $user_rules = $db->sql_fetchrowset($result);
421 $db->sql_freeresult($result);
423 if (sizeof($user_rules))
425 $sql = 'SELECT zebra_id, friend, foe
426 FROM ' . ZEBRA_TABLE
. "
427 WHERE user_id = $user_id";
428 $result = $db->sql_query($sql);
430 while ($row = $db->sql_fetchrow($result))
432 $zebra[$row['zebra_id']] = $row;
434 $db->sql_freeresult($result);
437 // Now build a bare-bone check_row array
438 $result = $db->sql_query($retrieve_sql);
440 while ($row = $db->sql_fetchrow($result))
442 $check_rows[] = array_merge($row, array(
443 'to' => explode(':', $row['to_address']),
444 'bcc' => explode(':', $row['bcc_address']),
445 'friend' => (isset($zebra[$row['author_id']])) ?
$zebra[$row['author_id']]['friend'] : 0,
446 'foe' => (isset($zebra[$row['author_id']])) ?
$zebra[$row['author_id']]['foe'] : 0,
447 'user_in_group' => array($user->data
['group_id']),
448 'author_in_group' => array())
451 $user_ids[] = $row['user_id'];
453 $db->sql_freeresult($result);
455 // Retrieve user memberships
456 if (sizeof($user_ids))
459 FROM ' . USER_GROUP_TABLE
. '
460 WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
461 AND user_pending = 0';
462 $result = $db->sql_query($sql);
464 while ($row = $db->sql_fetchrow($result))
466 $memberships[$row['user_id']][] = $row['group_id'];
468 $db->sql_freeresult($result);
471 // Now place into the appropriate folder
472 foreach ($check_rows as $row)
474 // Add membership if set
475 if (isset($memberships[$row['author_id']]))
477 $row['author_in_group'] = $memberships[$row['user_id']];
480 // Check Rule - this should be very quick since we have all information we need
482 foreach ($user_rules as $rule_row)
484 if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
487 $action_ary[$row['msg_id']][] = $action;
493 $action_ary[$row['msg_id']][] = array('action' => false);
497 unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
500 // We place actions into arrays, to save queries.
501 $sql = $unread_ids = $delete_ids = $important_ids = array();
503 foreach ($action_ary as $msg_id => $msg_ary)
505 // It is allowed to execute actions more than once, except placing messages into folder
506 $folder_action = $message_removed = false;
508 foreach ($msg_ary as $pos => $rule_ary)
510 if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER
)
515 switch ($rule_ary['action'])
517 case ACTION_PLACE_INTO_FOLDER
:
518 // Folder actions have precedence, so we will remove any other ones
519 $folder_action = true;
520 $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
523 case ACTION_MARK_AS_READ
:
524 if ($rule_ary['pm_unread'])
526 $unread_ids[] = $msg_id;
530 case ACTION_DELETE_MESSAGE
:
531 $delete_ids[] = $msg_id;
532 $message_removed = true;
535 case ACTION_MARK_AS_IMPORTANT
:
536 if (!$rule_ary['pm_marked'])
538 $important_ids[] = $msg_id;
544 // 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
545 // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
546 if (!$folder_action && !$message_removed)
548 $move_into_folder[PRIVMSGS_INBOX
][] = $msg_id;
552 // Do not change the order of processing
553 // The number of queries needed to be executed here highly depends on the defined rules and are
554 // only gone through if new messages arrive.
557 if (sizeof($delete_ids))
559 $num_removed +
= sizeof($delete_ids);
560 delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX
);
563 // Set messages to Unread
564 if (sizeof($unread_ids))
566 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
568 WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
569 AND user_id = $user_id
570 AND folder_id = " . PRIVMSGS_NO_BOX
;
571 $db->sql_query($sql);
574 // mark messages as important
575 if (sizeof($important_ids))
577 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
578 SET pm_marked = 1 - pm_marked
579 WHERE folder_id = ' . PRIVMSGS_NO_BOX
. "
580 AND user_id = $user_id
581 AND " . $db->sql_in_set('msg_id', $important_ids);
582 $db->sql_query($sql);
588 if (sizeof($move_into_folder))
590 // Determine Full Folder Action - we need the move to folder id later eventually
591 $full_folder_action = ($user->data
['user_full_folder'] == FULL_FOLDER_NONE
) ?
(phpbb
::$config['full_folder_action'] - (FULL_FOLDER_NONE
*(-1))) : $user->data
['user_full_folder'];
593 $sql_folder = array_keys($move_into_folder);
594 if ($full_folder_action >= 0)
596 $sql_folder[] = $full_folder_action;
599 $sql = 'SELECT folder_id, pm_count
600 FROM ' . PRIVMSGS_FOLDER_TABLE
. '
601 WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
602 AND user_id = $user_id";
603 $result = $db->sql_query($sql);
605 while ($row = $db->sql_fetchrow($result))
607 $folder[(int) $row['folder_id']] = (int) $row['pm_count'];
609 $db->sql_freeresult($result);
613 if (isset($move_into_folder[PRIVMSGS_INBOX
]))
615 $sql = 'SELECT COUNT(msg_id) as num_messages
616 FROM ' . PRIVMSGS_TO_TABLE
. "
617 WHERE user_id = $user_id
618 AND folder_id = " . PRIVMSGS_INBOX
;
619 $result = $db->sql_query($sql);
620 $folder[PRIVMSGS_INBOX
] = (int) $db->sql_fetchfield('num_messages');
621 $db->sql_freeresult($result);
625 // Here we have ideally only one folder to move into
626 foreach ($move_into_folder as $folder_id => $msg_ary)
628 $dest_folder = $folder_id;
629 $full_folder_action = FULL_FOLDER_NONE
;
631 // Check Message Limit - we calculate with the complete array, most of the time it is one message
632 // But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
633 if ($user->data
['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] +
sizeof($msg_ary)) > $user->data
['message_limit'])
635 $full_folder_action = ($user->data
['user_full_folder'] == FULL_FOLDER_NONE
) ?
(phpbb
::$config['full_folder_action'] - (FULL_FOLDER_NONE
*(-1))) : $user->data
['user_full_folder'];
637 // If destination folder itself is full...
638 if ($full_folder_action >= 0 && ($folder[$full_folder_action] +
sizeof($msg_ary)) > $user->data
['message_limit'])
640 $full_folder_action = phpbb
::$config['full_folder_action'] - (FULL_FOLDER_NONE
*(-1));
643 // If Full Folder Action is to move to another folder, we simply adjust the destination folder
644 if ($full_folder_action >= 0)
646 $dest_folder = $full_folder_action;
648 else if ($full_folder_action == FULL_FOLDER_DELETE
)
650 // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
651 $sql = 'SELECT msg_id
652 FROM ' . PRIVMSGS_TO_TABLE
. "
653 WHERE user_id = $user_id
654 AND folder_id = $dest_folder
655 ORDER BY msg_id ASC";
656 $result = $db->sql_query_limit($sql, (($folder[$dest_folder] +
sizeof($msg_ary)) - $user->data
['message_limit']));
658 $delete_ids = array();
659 while ($row = $db->sql_fetchrow($result))
661 $delete_ids[] = $row['msg_id'];
663 $db->sql_freeresult($result);
665 $num_removed +
= sizeof($delete_ids);
666 delete_pm($user_id, $delete_ids, $dest_folder);
671 if ($full_folder_action == FULL_FOLDER_HOLD
)
673 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
674 SET folder_id = ' . PRIVMSGS_HOLD_BOX
. '
675 WHERE folder_id = ' . PRIVMSGS_NO_BOX
. "
676 AND user_id = $user_id
677 AND " . $db->sql_in_set('msg_id', $msg_ary);
678 $db->sql_query($sql);
682 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. "
683 SET folder_id = $dest_folder, pm_new = 0
684 WHERE folder_id = " . PRIVMSGS_NO_BOX
. "
685 AND user_id = $user_id
687 AND " . $db->sql_in_set('msg_id', $msg_ary);
688 $db->sql_query($sql);
690 if ($dest_folder != PRIVMSGS_INBOX
)
692 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE
. '
693 SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
694 WHERE folder_id = $dest_folder
695 AND user_id = $user_id";
696 $db->sql_query($sql);
701 if (sizeof($action_ary))
703 // Move from OUTBOX to SENTBOX
704 // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
705 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
706 SET folder_id = ' . PRIVMSGS_SENTBOX
. '
707 WHERE folder_id = ' . PRIVMSGS_OUTBOX
. '
708 AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
709 $db->sql_query($sql);
712 // Update new/unread count
715 // Now check how many messages got not moved...
716 $sql = 'SELECT COUNT(msg_id) as num_messages
717 FROM ' . PRIVMSGS_TO_TABLE
. "
718 WHERE user_id = $user_id
719 AND folder_id = " . PRIVMSGS_HOLD_BOX
;
720 $result = $db->sql_query($sql);
721 $num_not_moved = (int) $db->sql_fetchfield('num_messages');
722 $db->sql_freeresult($result);
724 return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
728 * Move PM from one to another folder
730 function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
736 if (!is_array($move_msg_ids))
738 $move_msg_ids = array($move_msg_ids);
741 if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX
, PRIVMSGS_OUTBOX
, PRIVMSGS_SENTBOX
)) &&
742 !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX
, PRIVMSGS_OUTBOX
)) && $cur_folder_id != $dest_folder)
744 // We have to check the destination folder ;)
745 if ($dest_folder != PRIVMSGS_INBOX
)
747 $sql = 'SELECT folder_id, folder_name, pm_count
748 FROM ' . PRIVMSGS_FOLDER_TABLE
. "
749 WHERE folder_id = $dest_folder
750 AND user_id = $user_id";
751 $result = $db->sql_query($sql);
752 $row = $db->sql_fetchrow($result);
753 $db->sql_freeresult($result);
757 trigger_error('NOT_AUTHORISED');
760 if ($message_limit && $row['pm_count'] +
sizeof($move_msg_ids) > $message_limit)
762 $message = sprintf($user->lang
['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />';
763 $message .= sprintf($user->lang
['CLICK_RETURN_FOLDER'], '<a href="' . append_sid('ucp', 'i=pm&folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']);
764 trigger_error($message);
769 $sql = 'SELECT COUNT(msg_id) as num_messages
770 FROM ' . PRIVMSGS_TO_TABLE
. '
771 WHERE folder_id = ' . PRIVMSGS_INBOX
. "
772 AND user_id = $user_id";
773 $result = $db->sql_query($sql);
774 $num_messages = (int) $db->sql_fetchfield('num_messages');
775 $db->sql_freeresult($result);
777 if ($message_limit && $num_messages +
sizeof($move_msg_ids) > $message_limit)
779 $message = sprintf($user->lang
['NOT_ENOUGH_SPACE_FOLDER'], $user->lang
['PM_INBOX']) . '<br /><br />';
780 $message .= sprintf($user->lang
['CLICK_RETURN_FOLDER'], '<a href="' . append_sid('ucp', 'i=pm&folder=inbox') . '">', '</a>', $user->lang
['PM_INBOX']);
781 trigger_error($message);
785 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. "
786 SET folder_id = $dest_folder
787 WHERE folder_id = $cur_folder_id
788 AND user_id = $user_id
789 AND " . $db->sql_in_set('msg_id', $move_msg_ids);
790 $db->sql_query($sql);
791 $num_moved = $db->sql_affectedrows();
796 if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX
, PRIVMSGS_OUTBOX
, PRIVMSGS_SENTBOX
)))
798 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE
. "
799 SET pm_count = pm_count - $num_moved
800 WHERE folder_id = $cur_folder_id
801 AND user_id = $user_id";
802 $db->sql_query($sql);
805 if ($dest_folder != PRIVMSGS_INBOX
)
807 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE
. "
808 SET pm_count = pm_count + $num_moved
809 WHERE folder_id = $dest_folder
810 AND user_id = $user_id";
811 $db->sql_query($sql);
815 else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX
, PRIVMSGS_OUTBOX
)))
817 trigger_error('CANNOT_MOVE_SPECIAL');
824 * Update unread message status
826 function update_unread_status($unread, $msg_id, $user_id, $folder_id)
835 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. "
837 WHERE msg_id = $msg_id
838 AND user_id = $user_id
839 AND folder_id = $folder_id";
840 $db->sql_query($sql);
842 $sql = 'UPDATE ' . USERS_TABLE
. "
843 SET user_unread_privmsg = user_unread_privmsg - 1
844 WHERE user_id = $user_id";
845 $db->sql_query($sql);
847 if ($user->data
['user_id'] == $user_id)
849 $user->data
['user_unread_privmsg']--;
851 // Try to cope with previous wrong conversions...
852 if ($user->data
['user_unread_privmsg'] < 0)
854 $sql = 'UPDATE ' . USERS_TABLE
. "
855 SET user_unread_privmsg = 0
856 WHERE user_id = $user_id";
857 $db->sql_query($sql);
859 $user->data
['user_unread_privmsg'] = 0;
865 * Handle all actions possible with marked messages
867 function handle_mark_actions($user_id, $mark_action)
871 $msg_ids = request_var('marked_msg_id', array(0));
872 $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX
);
873 $confirm = phpbb_request
::is_set_post('confirm');
875 if (!sizeof($msg_ids))
880 switch ($mark_action)
882 case 'mark_important':
884 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. "
885 SET pm_marked = 1 - pm_marked
886 WHERE folder_id = $cur_folder_id
887 AND user_id = $user_id
888 AND " . $db->sql_in_set('msg_id', $msg_ids);
889 $db->sql_query($sql);
893 case 'delete_marked':
895 if (confirm_box(true))
897 delete_pm($user_id, $msg_ids, $cur_folder_id);
899 $success_msg = (sizeof($msg_ids) == 1) ?
'MESSAGE_DELETED' : 'MESSAGES_DELETED';
900 $redirect = append_sid('ucp', 'i=pm&folder=' . $cur_folder_id);
902 meta_refresh(3, $redirect);
903 trigger_error($user->lang
[$success_msg] . '<br /><br />' . sprintf($user->lang
['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>'));
907 $s_hidden_fields = array(
908 'cur_folder_id' => $cur_folder_id,
909 'mark_option' => 'delete_marked',
910 'submit_mark' => true,
911 'marked_msg_id' => $msg_ids
914 confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
929 function delete_pm($user_id, $msg_ids, $folder_id)
933 $user_id = (int) $user_id;
934 $folder_id = (int) $folder_id;
941 if (!is_array($msg_ids))
947 $msg_ids = array($msg_ids);
950 if (!sizeof($msg_ids))
955 // Get PM Information for later deleting
956 $sql = 'SELECT msg_id, pm_unread, pm_new
957 FROM ' . PRIVMSGS_TO_TABLE
. '
958 WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
959 AND folder_id = $folder_id
960 AND user_id = $user_id";
961 $result = $db->sql_query($sql);
963 $delete_rows = array();
964 $num_unread = $num_new = $num_deleted = 0;
965 while ($row = $db->sql_fetchrow($result))
967 $num_unread +
= (int) $row['pm_unread'];
968 $num_new +
= (int) $row['pm_new'];
970 $delete_rows[$row['msg_id']] = 1;
972 $db->sql_freeresult($result);
975 if (!sizeof($delete_rows))
980 $db->sql_transaction('begin');
982 // if no one has read the message yet (meaning it is in users outbox)
983 // then mark the message as deleted...
984 if ($folder_id == PRIVMSGS_OUTBOX
)
986 // Remove PM from Outbox
987 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE
. "
988 WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX
. '
989 AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
990 $db->sql_query($sql);
992 // Update PM Information for safety
993 $sql = 'UPDATE ' . PRIVMSGS_TABLE
. " SET message_text = ''
994 WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
995 $db->sql_query($sql);
997 // Set delete flag for those intended to receive the PM
998 // We do not remove the message actually, to retain some basic information (sent time for example)
999 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
1001 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1002 $db->sql_query($sql);
1004 $num_deleted = $db->sql_affectedrows();
1008 // Delete private message data
1009 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE
. "
1010 WHERE user_id = $user_id
1011 AND folder_id = $folder_id
1012 AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
1013 $db->sql_query($sql);
1014 $num_deleted = $db->sql_affectedrows();
1017 // if folder id is user defined folder then decrease pm_count
1018 if (!in_array($folder_id, array(PRIVMSGS_INBOX
, PRIVMSGS_OUTBOX
, PRIVMSGS_SENTBOX
, PRIVMSGS_NO_BOX
)))
1020 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE
. "
1021 SET pm_count = pm_count - $num_deleted
1022 WHERE folder_id = $folder_id";
1023 $db->sql_query($sql);
1026 // Update unread and new status field
1027 if ($num_unread ||
$num_new)
1029 $set_sql = ($num_unread) ?
'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
1033 $set_sql .= ($set_sql != '') ?
', ' : '';
1034 $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
1037 $db->sql_query('UPDATE ' . USERS_TABLE
. " SET $set_sql WHERE user_id = $user_id");
1039 $user->data
['user_new_privmsg'] -= $num_new;
1040 $user->data
['user_unread_privmsg'] -= $num_unread;
1043 // Now we have to check which messages we can delete completely
1044 $sql = 'SELECT msg_id
1045 FROM ' . PRIVMSGS_TO_TABLE
. '
1046 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1047 $result = $db->sql_query($sql);
1049 while ($row = $db->sql_fetchrow($result))
1051 unset($delete_rows[$row['msg_id']]);
1053 $db->sql_freeresult($result);
1055 $delete_ids = array_keys($delete_rows);
1057 if (sizeof($delete_ids))
1059 // Check if there are any attachments we need to remove
1060 if (!function_exists('delete_attachments'))
1062 include(PHPBB_ROOT_PATH
. 'includes/functions_admin.' . PHP_EXT
);
1065 delete_attachments('message', $delete_ids, false);
1067 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE
. '
1068 WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
1069 $db->sql_query($sql);
1072 $db->sql_transaction('commit');
1078 * Rebuild message header
1080 function rebuild_header($check_ary)
1086 foreach ($check_ary as $check_type => $address_field)
1088 // Split Addresses into users and groups
1089 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1092 foreach ($match[1] as $id => $type)
1094 $
{$type}[] = (int) $match[2][$id];
1097 $_types = array('u', 'g');
1098 foreach ($_types as $type)
1102 foreach ($
$type as $id)
1104 $address[$type][$id] = $check_type;
1114 * Print out/assign recipient information
1116 function write_pm_addresses($check_ary, $author_id, $plaintext = false)
1118 global $db, $user, $template;
1120 $addresses = array();
1122 foreach ($check_ary as $check_type => $address_field)
1124 if (!is_array($address_field))
1126 // Split Addresses into users and groups
1127 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1130 foreach ($match[1] as $id => $type)
1132 $
{$type}[] = (int) $match[2][$id];
1137 $u = $address_field['u'];
1138 $g = $address_field['g'];
1144 $sql = 'SELECT user_id, username, user_colour
1145 FROM ' . USERS_TABLE
. '
1146 WHERE ' . $db->sql_in_set('user_id', $u) . '
1147 AND user_type IN (' . phpbb
::USER_NORMAL
. ', ' . phpbb
::USER_FOUNDER
. ')';
1148 $result = $db->sql_query($sql);
1150 while ($row = $db->sql_fetchrow($result))
1152 if ($check_type == 'to' ||
$author_id == $user->data
['user_id'] ||
$row['user_id'] == $user->data
['user_id'])
1156 $address[] = $row['username'];
1160 $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
1164 $db->sql_freeresult($result);
1171 $sql = 'SELECT group_name, group_type
1172 FROM ' . GROUPS_TABLE
. '
1173 WHERE ' . $db->sql_in_set('group_id', $g);
1174 $result = $db->sql_query($sql);
1176 while ($row = $db->sql_fetchrow($result))
1178 if ($check_type == 'to' ||
$author_id == $user->data
['user_id'] ||
$row['user_id'] == $user->data
['user_id'])
1180 $address[] = ($row['group_type'] == GROUP_SPECIAL
) ?
$user->lang
['G_' . $row['group_name']] : $row['group_name'];
1183 $db->sql_freeresult($result);
1187 $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
1188 FROM ' . GROUPS_TABLE
. ' g, ' . USER_GROUP_TABLE
. ' ug
1189 WHERE ' . $db->sql_in_set('g.group_id', $g) . '
1190 AND g.group_id = ug.group_id
1191 AND ug.user_pending = 0';
1192 $result = $db->sql_query($sql);
1194 while ($row = $db->sql_fetchrow($result))
1196 if (!isset($address['group'][$row['group_id']]))
1198 if ($check_type == 'to' ||
$author_id == $user->data
['user_id'] ||
$row['user_id'] == $user->data
['user_id'])
1200 $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL
) ?
$user->lang
['G_' . $row['group_name']] : $row['group_name'];
1201 $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
1205 if (isset($address['user'][$row['user_id']]))
1207 $address['user'][$row['user_id']]['in_group'] = $row['group_id'];
1210 $db->sql_freeresult($result);
1214 if (sizeof($address) && !$plaintext)
1216 $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
1218 foreach ($address as $type => $adr_ary)
1220 foreach ($adr_ary as $id => $row)
1223 'IS_GROUP' => ($type == 'group') ?
true : false,
1224 'IS_USER' => ($type == 'user') ?
true : false,
1226 'NAME' => $row['name'],
1227 'COLOUR' => ($row['colour']) ?
'#' . $row['colour'] : '',
1231 if ($type == 'user')
1233 $tpl_ary = array_merge($tpl_ary, array(
1234 'U_VIEW' => get_username_string('profile', $id, $row['name'], $row['colour']),
1235 'NAME_FULL' => get_username_string('full', $id, $row['name'], $row['colour']),
1240 $tpl_ary = array_merge($tpl_ary, array(
1241 'U_VIEW' => append_sid('memberlist', 'mode=group&g=' . $id),
1245 $template->assign_block_vars($check_type . '_recipient', $tpl_ary);
1250 $addresses[$check_type] = $address;
1259 function get_folder_status($folder_id, $folder)
1263 if (isset($folder[$folder_id]))
1265 $folder = $folder[$folder_id];
1273 'folder_name' => $folder['folder_name'],
1274 'cur' => $folder['num_messages'],
1275 'remaining' => ($user->data
['message_limit']) ?
$user->data
['message_limit'] - $folder['num_messages'] : 0,
1276 'max' => $user->data
['message_limit'],
1277 'percent' => ($user->data
['message_limit']) ?
(($user->data
['message_limit'] > 0) ?
round(($folder['num_messages'] / $user->data
['message_limit']) * 100) : 100) : 0,
1280 $return['message'] = sprintf($user->lang
['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']);
1292 function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
1294 global $db, $auth, $template, $user;
1296 // We do not handle erasing pms here
1297 if ($mode == 'delete')
1302 $current_time = time();
1304 // Collect some basic information about which tables and which rows to update/insert
1305 $sql_data = array();
1308 // Recipient Information
1309 $recipients = $to = $bcc = array();
1311 if ($mode != 'edit')
1313 // Build Recipient List
1314 // u|g => array($user_id => 'to'|'bcc')
1315 $_types = array('u', 'g');
1316 foreach ($_types as $ug_type)
1318 if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
1320 foreach ($data['address_list'][$ug_type] as $id => $field)
1324 // Do not rely on the address list being "valid"
1325 if (!$id ||
($ug_type == 'u' && $id == ANONYMOUS
))
1330 $field = ($field == 'to') ?
'to' : 'bcc';
1331 if ($ug_type == 'u')
1333 $recipients[$id] = $field;
1335 $
{$field}[] = $ug_type . '_' . $id;
1340 if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
1342 // We need to check the PM status of group members (do they want to receive PM's?)
1343 // Only check if not a moderator or admin, since they are allowed to override this user setting
1344 $sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ?
' AND u.user_allow_pm = 1' : '';
1346 $sql = 'SELECT u.user_type, ug.group_id, ug.user_id
1347 FROM ' . USERS_TABLE
. ' u, ' . USER_GROUP_TABLE
. ' ug
1348 WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
1349 AND ug.user_pending = 0
1350 AND u.user_id = ug.user_id
1351 AND u.user_type IN (' . phpbb
::USER_NORMAL
. ', ' . phpbb
::USER_FOUNDER
. ')' .
1353 $result = $db->sql_query($sql);
1355 while ($row = $db->sql_fetchrow($result))
1357 $field = ($data['address_list']['g'][$row['group_id']] == 'to') ?
'to' : 'bcc';
1358 $recipients[$row['user_id']] = $field;
1360 $db->sql_freeresult($result);
1363 if (!sizeof($recipients))
1365 trigger_error('NO_RECIPIENT');
1369 $db->sql_transaction('begin');
1377 $root_level = ($data['reply_from_root_level']) ?
$data['reply_from_root_level'] : $data['reply_from_msg_id'];
1379 // Set message_replied switch for this user
1380 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE
. '
1382 WHERE user_id = ' . $data['from_user_id'] . '
1383 AND msg_id = ' . $data['reply_from_msg_id'];
1391 'root_level' => $root_level,
1392 'author_id' => $data['from_user_id'],
1393 'icon_id' => $data['icon_id'],
1394 'author_ip' => $data['from_user_ip'],
1395 'message_time' => $current_time,
1396 'enable_bbcode' => $data['enable_bbcode'],
1397 'enable_smilies' => $data['enable_smilies'],
1398 'enable_magic_url' => $data['enable_urls'],
1399 'enable_sig' => $data['enable_sig'],
1400 'message_subject' => $subject,
1401 'message_text' => $data['message'],
1402 'message_attachment'=> (!empty($data['attachment_data'])) ?
1 : 0,
1403 'bbcode_bitfield' => $data['bbcode_bitfield'],
1404 'bbcode_uid' => $data['bbcode_uid'],
1405 'to_address' => implode(':', $to),
1406 'bcc_address' => implode(':', $bcc)
1412 'icon_id' => $data['icon_id'],
1413 'message_edit_time' => $current_time,
1414 'enable_bbcode' => $data['enable_bbcode'],
1415 'enable_smilies' => $data['enable_smilies'],
1416 'enable_magic_url' => $data['enable_urls'],
1417 'enable_sig' => $data['enable_sig'],
1418 'message_subject' => $subject,
1419 'message_text' => $data['message'],
1420 'message_attachment'=> (!empty($data['attachment_data'])) ?
1 : 0,
1421 'bbcode_bitfield' => $data['bbcode_bitfield'],
1422 'bbcode_uid' => $data['bbcode_uid']
1427 if (sizeof($sql_data))
1431 if ($mode == 'post' ||
$mode == 'reply' ||
$mode == 'quote' ||
$mode == 'quotepost' ||
$mode == 'forward')
1433 $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE
. ' ' . $db->sql_build_array('INSERT', $sql_data));
1434 $data['msg_id'] = $db->sql_nextid();
1436 else if ($mode == 'edit')
1438 $sql = 'UPDATE ' . PRIVMSGS_TABLE
. '
1439 SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
1440 WHERE msg_id = ' . $data['msg_id'];
1441 $db->sql_query($sql);
1445 if ($mode != 'edit')
1449 $db->sql_query($sql);
1454 foreach ($recipients as $user_id => $type)
1457 'msg_id' => (int) $data['msg_id'],
1458 'user_id' => (int) $user_id,
1459 'author_id' => (int) $data['from_user_id'],
1460 'folder_id' => PRIVMSGS_NO_BOX
,
1463 'pm_forwarded' => ($mode == 'forward') ?
1 : 0
1467 $db->sql_multi_insert(PRIVMSGS_TO_TABLE
, $sql_ary);
1469 $sql = 'UPDATE ' . USERS_TABLE
. '
1470 SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
1471 WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
1472 $db->sql_query($sql);
1474 // Put PM into outbox
1477 $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE
. ' ' . $db->sql_build_array('INSERT', array(
1478 'msg_id' => (int) $data['msg_id'],
1479 'user_id' => (int) $data['from_user_id'],
1480 'author_id' => (int) $data['from_user_id'],
1481 'folder_id' => PRIVMSGS_OUTBOX
,
1484 'pm_forwarded' => ($mode == 'forward') ?
1 : 0))
1489 // Set user last post time
1490 if ($mode == 'reply' ||
$mode == 'quote' ||
$mode == 'quotepost' ||
$mode == 'forward' ||
$mode == 'post')
1492 $sql = 'UPDATE ' . USERS_TABLE
. "
1493 SET user_lastpost_time = $current_time
1494 WHERE user_id = " . $data['from_user_id'];
1495 $db->sql_query($sql);
1498 // Submit Attachments
1499 if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
1501 $space_taken = $files_added = 0;
1502 $orphan_rows = array();
1504 foreach ($data['attachment_data'] as $pos => $attach_row)
1506 $orphan_rows[(int) $attach_row['attach_id']] = array();
1509 if (sizeof($orphan_rows))
1511 $sql = 'SELECT attach_id, filesize, physical_filename
1512 FROM ' . ATTACHMENTS_TABLE
. '
1513 WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
1516 AND poster_id = ' . $user->data
['user_id'];
1517 $result = $db->sql_query($sql);
1519 $orphan_rows = array();
1520 while ($row = $db->sql_fetchrow($result))
1522 $orphan_rows[$row['attach_id']] = $row;
1524 $db->sql_freeresult($result);
1527 foreach ($data['attachment_data'] as $pos => $attach_row)
1529 if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
1534 if (!$attach_row['is_orphan'])
1536 // update entry in db if attachment already stored in db and filespace
1537 $sql = 'UPDATE ' . ATTACHMENTS_TABLE
. "
1538 SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
1539 WHERE attach_id = " . (int) $attach_row['attach_id'] . '
1541 $db->sql_query($sql);
1545 // insert attachment into db
1546 if (!@file_exists
(PHPBB_ROOT_PATH
. phpbb
::$config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
1551 $space_taken +
= $orphan_rows[$attach_row['attach_id']]['filesize'];
1554 $attach_sql = array(
1555 'post_msg_id' => $data['msg_id'],
1558 'poster_id' => $data['from_user_id'],
1559 'attach_comment' => $attach_row['attach_comment'],
1562 $sql = 'UPDATE ' . ATTACHMENTS_TABLE
. ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
1563 WHERE attach_id = ' . $attach_row['attach_id'] . '
1565 AND poster_id = ' . $user->data
['user_id'];
1566 $db->sql_query($sql);
1570 if ($space_taken && $files_added)
1572 set_config('upload_dir_size', phpbb
::$config['upload_dir_size'] +
$space_taken, true);
1573 set_config('num_files', phpbb
::$config['num_files'] +
$files_added, true);
1577 // Delete draft if post was loaded...
1578 $draft_id = request_var('draft_loaded', 0);
1581 $sql = 'DELETE FROM ' . DRAFTS_TABLE
. "
1582 WHERE draft_id = $draft_id
1583 AND user_id = " . $data['from_user_id'];
1584 $db->sql_query($sql);
1587 $db->sql_transaction('commit');
1589 // Send Notifications
1590 if ($mode != 'edit')
1592 pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
1595 return $data['msg_id'];
1601 function pm_notification($mode, $author, $recipients, $subject, $message)
1603 global $db, $user, $auth;
1605 $subject = censor_text($subject);
1607 unset($recipients[ANONYMOUS
], $recipients[$user->data
['user_id']]);
1609 if (!sizeof($recipients))
1614 // Get banned User ID's
1615 $sql = 'SELECT ban_userid
1616 FROM ' . BANLIST_TABLE
. '
1617 WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
1618 AND ban_exclude = 0';
1619 $result = $db->sql_query($sql);
1621 while ($row = $db->sql_fetchrow($result))
1623 unset($recipients[$row['ban_userid']]);
1625 $db->sql_freeresult($result);
1627 if (!sizeof($recipients))
1632 $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
1633 FROM ' . USERS_TABLE
. '
1634 WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
1635 $result = $db->sql_query($sql);
1637 $msg_list_ary = array();
1638 while ($row = $db->sql_fetchrow($result))
1640 if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
1642 $msg_list_ary[] = array(
1643 'method' => $row['user_notify_type'],
1644 'email' => $row['user_email'],
1645 'jabber' => $row['user_jabber'],
1646 'name' => $row['username'],
1647 'lang' => $row['user_lang']
1651 $db->sql_freeresult($result);
1653 if (!sizeof($msg_list_ary))
1658 include_once(PHPBB_ROOT_PATH
. 'includes/functions_messenger.' . PHP_EXT
);
1659 $messenger = new messenger();
1661 foreach ($msg_list_ary as $pos => $addr)
1663 $messenger->template('privmsg_notify', $addr['lang']);
1665 $messenger->to($addr['email'], $addr['name']);
1666 $messenger->im($addr['jabber'], $addr['name']);
1668 $messenger->assign_vars(array(
1669 'SUBJECT' => htmlspecialchars_decode($subject),
1670 'AUTHOR_NAME' => htmlspecialchars_decode($author),
1671 'USERNAME' => htmlspecialchars_decode($addr['name']),
1673 'U_INBOX' => generate_board_url() . '/ucp.' . PHP_EXT
. '?i=pm&folder=inbox')
1676 $messenger->send($addr['method']);
1678 unset($msg_list_ary);
1680 $messenger->save_queue();
1686 * Display Message History
1688 function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
1690 global $db, $user, $template, $auth, $bbcode;
1692 // Get History Messages (could be newer)
1693 $sql = 'SELECT t.*, p.*, u.*
1694 FROM ' . PRIVMSGS_TABLE
. ' p, ' . PRIVMSGS_TO_TABLE
. ' t, ' . USERS_TABLE
. ' u
1695 WHERE t.msg_id = p.msg_id
1696 AND p.author_id = u.user_id
1697 AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX
. ', ' . PRIVMSGS_HOLD_BOX
. ")
1698 AND t.user_id = $user_id";
1700 if (!$message_row['root_level'])
1702 $sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
1706 $sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';
1708 $sql .= ' ORDER BY p.message_time DESC';
1710 $result = $db->sql_query($sql);
1711 $row = $db->sql_fetchrow($result);
1715 $db->sql_freeresult($result);
1720 $bbcode_bitfield = '';
1721 $folder_url = append_sid('ucp', 'i=pm') . '&folder=';
1725 $folder_id = (int) $row['folder_id'];
1727 $row['folder'][] = (isset($folder[$folder_id])) ?
'<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang
['UNKNOWN_FOLDER'];
1729 if (isset($rowset[$row['msg_id']]))
1731 $rowset[$row['msg_id']]['folder'][] = (isset($folder[$folder_id])) ?
'<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang
['UNKNOWN_FOLDER'];
1735 $rowset[$row['msg_id']] = $row;
1736 $bbcode_bitfield = $bbcode_bitfield |
base64_decode($row['bbcode_bitfield']);
1739 while ($row = $db->sql_fetchrow($result));
1740 $db->sql_freeresult($result);
1742 $title = $row['message_subject'];
1744 if (sizeof($rowset) == 1 && !$in_post_mode)
1749 // Instantiate BBCode class
1750 if ((empty($bbcode) ||
$bbcode === false) && $bbcode_bitfield !== '')
1752 if (!class_exists('bbcode'))
1754 include(PHPBB_ROOT_PATH
. 'includes/bbcode.' . PHP_EXT
);
1756 $bbcode = new bbcode(base64_encode($bbcode_bitfield));
1759 $title = censor_text($title);
1761 $url = append_sid('ucp', 'i=pm');
1762 $next_history_pm = $previous_history_pm = $prev_id = 0;
1764 foreach ($rowset as $id => $row)
1766 $author_id = $row['author_id'];
1767 $folder_id = (int) $row['folder_id'];
1769 $subject = $row['message_subject'];
1770 $message = $row['message_text'];
1772 $message = censor_text($message);
1774 $decoded_message = false;
1776 if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS
&& $author_id != $user->data
['user_id'])
1778 $decoded_message = $message;
1779 decode_message($decoded_message, $row['bbcode_uid']);
1781 $decoded_message = bbcode_nl2br($decoded_message);
1784 if ($row['bbcode_bitfield'])
1786 $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
1789 $message = bbcode_nl2br($message);
1790 $message = smiley_text($message, !$row['enable_smilies']);
1792 $subject = censor_text($subject);
1796 $next_history_pm = next($rowset);
1797 $next_history_pm = (sizeof($next_history_pm)) ?
(int) $next_history_pm['msg_id'] : 0;
1798 $previous_history_pm = $prev_id;
1801 $template->assign_block_vars('history_row', array(
1802 'MESSAGE_AUTHOR_QUOTE' => (($decoded_message) ?
addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''),
1803 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),
1804 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']),
1805 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']),
1806 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']),
1808 'SUBJECT' => $subject,
1809 'SENT_DATE' => $user->format_date($row['message_time']),
1810 'MESSAGE' => $message,
1811 'FOLDER' => implode(', ', $row['folder']),
1812 'DECODED_MESSAGE' => $decoded_message,
1814 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id),
1815 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS
) ?
true : false,
1816 'S_IN_POST_MODE' => $in_post_mode,
1818 'MSG_ID' => $row['msg_id'],
1819 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'],
1820 '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'] : '',
1821 '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'] : '')
1823 unset($rowset[$id]);
1827 $template->assign_vars(array(
1828 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang
['REPLY_WITH_QUOTE']),
1829 'HISTORY_TITLE' => $title,
1831 'U_VIEW_NEXT_HISTORY' => ($next_history_pm) ?
"$url&p=" . $next_history_pm : '',
1832 'U_VIEW_PREVIOUS_HISTORY' => ($previous_history_pm) ?
"$url&p=" . $previous_history_pm : '',
1839 * Set correct users max messages in PM folder.
1840 * If several group memberships define different amount of messages, the highest will be chosen.
1842 function set_user_message_limit()
1846 // Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config.
1847 $sql = 'SELECT MAX(g.group_message_limit) as max_message_limit
1848 FROM ' . GROUPS_TABLE
. ' g, ' . USER_GROUP_TABLE
. ' ug
1849 WHERE ug.user_id = ' . $user->data
['user_id'] . '
1850 AND ug.user_pending = 0
1851 AND ug.group_id = g.group_id';
1852 $result = $db->sql_query($sql);
1853 $message_limit = (int) $db->sql_fetchfield('max_message_limit');
1854 $db->sql_freeresult($result);
1856 $user->data
['message_limit'] = (!$message_limit) ? phpbb
::$config['pm_max_msgs'] : $message_limit;