5
* @version $Id: functions_privmsgs.php,v 1.85 2007/11/07 10:45:38 acydburn Exp $
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;
119
global $phpbb_root_path, $phpEx;
123
// Get folder information
124
$sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread
125
FROM ' . PRIVMSGS_TO_TABLE . "
126
WHERE user_id = $user_id
127
AND folder_id <> " . PRIVMSGS_NO_BOX . '
129
$result = $db->sql_query($sql);
131
$num_messages = $num_unread = array();
132
while ($row = $db->sql_fetchrow($result))
134
$num_messages[(int) $row['folder_id']] = $row['num_messages'];
135
$num_unread[(int) $row['folder_id']] = $row['num_unread'];
137
$db->sql_freeresult($result);
139
// Make sure the default boxes are defined
140
$available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX);
142
foreach ($available_folder as $default_folder)
144
if (!isset($num_messages[$default_folder]))
146
$num_messages[$default_folder] = 0;
149
if (!isset($num_unread[$default_folder]))
151
$num_unread[$default_folder] = 0;
155
// Adjust unread status for outbox
156
$num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX];
158
$folder[PRIVMSGS_INBOX] = array(
159
'folder_name' => $user->lang['PM_INBOX'],
160
'num_messages' => $num_messages[PRIVMSGS_INBOX],
161
'unread_messages' => $num_unread[PRIVMSGS_INBOX]
165
$sql = 'SELECT folder_id, folder_name, pm_count
166
FROM ' . PRIVMSGS_FOLDER_TABLE . "
167
WHERE user_id = $user_id";
168
$result = $db->sql_query($sql);
170
while ($row = $db->sql_fetchrow($result))
172
$folder[$row['folder_id']] = array(
173
'folder_name' => $row['folder_name'],
174
'num_messages' => $row['pm_count'],
175
'unread_messages' => ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0)
178
$db->sql_freeresult($result);
180
$folder[PRIVMSGS_OUTBOX] = array(
181
'folder_name' => $user->lang['PM_OUTBOX'],
182
'num_messages' => $num_messages[PRIVMSGS_OUTBOX],
183
'unread_messages' => $num_unread[PRIVMSGS_OUTBOX]
186
$folder[PRIVMSGS_SENTBOX] = array(
187
'folder_name' => $user->lang['PM_SENTBOX'],
188
'num_messages' => $num_messages[PRIVMSGS_SENTBOX],
189
'unread_messages' => $num_unread[PRIVMSGS_SENTBOX]
192
// Define Folder Array for template designers (and for making custom folders usable by the template too)
193
foreach ($folder as $f_id => $folder_ary)
195
$folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox');
197
$template->assign_block_vars('folder', array(
198
'FOLDER_ID' => $f_id,
199
'FOLDER_NAME' => $folder_ary['folder_name'],
200
'NUM_MESSAGES' => $folder_ary['num_messages'],
201
'UNREAD_MESSAGES' => $folder_ary['unread_messages'],
203
'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),
205
'S_CUR_FOLDER' => ($f_id === $folder_id) ? true : false,
206
'S_UNREAD_MESSAGES' => ($folder_ary['unread_messages']) ? true : false,
207
'S_CUSTOM_FOLDER' => ($f_id > 0) ? true : false)
215
* Delete Messages From Sentbox
216
* we are doing this here because this saves us a bunch of checks and queries
218
function clean_sentbox($num_sentbox_messages)
220
global $db, $user, $config;
222
// Check Message Limit
223
if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
225
// Delete old messages
226
$sql = 'SELECT t.msg_id
227
FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
228
WHERE t.msg_id = p.msg_id
229
AND t.user_id = ' . $user->data['user_id'] . '
230
AND t.folder_id = ' . PRIVMSGS_SENTBOX . '
231
ORDER BY p.message_time ASC';
232
$result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit']));
234
$delete_ids = array();
235
while ($row = $db->sql_fetchrow($result))
237
$delete_ids[] = $row['msg_id'];
239
$db->sql_freeresult($result);
240
delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX);
245
* Check Rule against Message Information
247
function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
249
global $user, $config;
251
if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
256
$check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
258
// Replace Check Literals
259
$evaluate = $check_ary['function'];
260
$evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate);
262
// Replace Rule Literals
263
$evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate);
267
eval('$result = (' . $evaluate . ') ? true : false;');
274
switch ($rule_row['rule_action'])
276
case ACTION_PLACE_INTO_FOLDER:
277
return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
280
case ACTION_MARK_AS_READ:
281
case ACTION_MARK_AS_IMPORTANT:
282
return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
285
case ACTION_DELETE_MESSAGE:
288
// Check for admins/mods - users are not allowed to remove those messages...
289
// We do the check here to make sure the data we use is consistent
290
$sql = 'SELECT user_id, user_type, user_permissions
291
FROM ' . USERS_TABLE . '
292
WHERE user_id = ' . (int) $message_row['author_id'];
293
$result = $db->sql_query($sql);
294
$userdata = $db->sql_fetchrow($result);
295
$db->sql_freeresult($result);
298
$auth2->acl($userdata);
300
if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
302
return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
316
* Update user PM count
318
function update_pm_counts()
322
// Update unread count
323
$sql = 'SELECT COUNT(msg_id) as num_messages
324
FROM ' . PRIVMSGS_TO_TABLE . '
326
AND folder_id <> ' . PRIVMSGS_OUTBOX . '
327
AND user_id = ' . $user->data['user_id'];
328
$result = $db->sql_query($sql);
329
$user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages');
330
$db->sql_freeresult($result);
332
// Update new pm count
333
$sql = 'SELECT COUNT(msg_id) as num_messages
334
FROM ' . PRIVMSGS_TO_TABLE . '
336
AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
337
AND user_id = ' . $user->data['user_id'];
338
$result = $db->sql_query($sql);
339
$user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages');
340
$db->sql_freeresult($result);
342
$db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
343
'user_unread_privmsg' => (int) $user->data['user_unread_privmsg'],
344
'user_new_privmsg' => (int) $user->data['user_new_privmsg'],
345
)) . ' WHERE user_id = ' . $user->data['user_id']);
347
// Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag.
348
if (!$user->data['user_new_privmsg'])
350
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
353
AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
354
AND user_id = ' . $user->data['user_id'];
355
$db->sql_query($sql);
360
* Place new messages into appropriate folder
362
function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
364
global $db, $user, $config;
366
if (!$user->data['user_new_privmsg'])
368
return array('not_moved' => 0, 'removed' => 0);
371
$user_message_rules = (int) $user->data['user_message_rules'];
372
$user_id = (int) $user->data['user_id'];
374
$action_ary = $move_into_folder = array();
377
// Newly processing on-hold messages
380
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
381
SET folder_id = ' . PRIVMSGS_NO_BOX . '
382
WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "
383
AND user_id = $user_id";
384
$db->sql_query($sql);
387
// Get those messages not yet placed into any box
388
$retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
389
FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
390
WHERE t.user_id = $user_id
391
AND p.author_id = u.user_id
392
AND t.folder_id = " . PRIVMSGS_NO_BOX . '
393
AND t.msg_id = p.msg_id';
395
// Just place into the appropriate arrays if no rules need to be checked
396
if (!$user_message_rules)
398
$result = $db->sql_query($retrieve_sql);
400
while ($row = $db->sql_fetchrow($result))
402
$action_ary[$row['msg_id']][] = array('action' => false);
404
$db->sql_freeresult($result);
408
$user_rules = $zebra = $check_rows = array();
409
$user_ids = $memberships = array();
411
// First of all, grab all rules and retrieve friends/foes
413
FROM ' . PRIVMSGS_RULES_TABLE . "
414
WHERE user_id = $user_id";
415
$result = $db->sql_query($sql);
416
$user_rules = $db->sql_fetchrowset($result);
417
$db->sql_freeresult($result);
419
if (sizeof($user_rules))
421
$sql = 'SELECT zebra_id, friend, foe
422
FROM ' . ZEBRA_TABLE . "
423
WHERE user_id = $user_id";
424
$result = $db->sql_query($sql);
426
while ($row = $db->sql_fetchrow($result))
428
$zebra[$row['zebra_id']] = $row;
430
$db->sql_freeresult($result);
433
// Now build a bare-bone check_row array
434
$result = $db->sql_query($retrieve_sql);
436
while ($row = $db->sql_fetchrow($result))
438
$check_rows[] = array_merge($row, array(
439
'to' => explode(':', $row['to_address']),
440
'bcc' => explode(':', $row['bcc_address']),
441
'friend' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,
442
'foe' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0,
443
'user_in_group' => array($user->data['group_id']),
444
'author_in_group' => array())
447
$user_ids[] = $row['user_id'];
449
$db->sql_freeresult($result);
451
// Retrieve user memberships
452
if (sizeof($user_ids))
455
FROM ' . USER_GROUP_TABLE . '
456
WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
457
AND user_pending = 0';
458
$result = $db->sql_query($sql);
460
while ($row = $db->sql_fetchrow($result))
462
$memberships[$row['user_id']][] = $row['group_id'];
464
$db->sql_freeresult($result);
467
// Now place into the appropriate folder
468
foreach ($check_rows as $row)
470
// Add membership if set
471
if (isset($memberships[$row['author_id']]))
473
$row['author_in_group'] = $memberships[$row['user_id']];
476
// Check Rule - this should be very quick since we have all information we need
478
foreach ($user_rules as $rule_row)
480
if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
483
$action_ary[$row['msg_id']][] = $action;
489
$action_ary[$row['msg_id']][] = array('action' => false);
493
unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
496
// We place actions into arrays, to save queries.
497
$sql = $unread_ids = $delete_ids = $important_ids = array();
499
foreach ($action_ary as $msg_id => $msg_ary)
501
// It is allowed to execute actions more than once, except placing messages into folder
502
$folder_action = $message_removed = false;
504
foreach ($msg_ary as $pos => $rule_ary)
506
if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER)
511
switch ($rule_ary['action'])
513
case ACTION_PLACE_INTO_FOLDER:
514
// Folder actions have precedence, so we will remove any other ones
515
$folder_action = true;
516
$move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
519
case ACTION_MARK_AS_READ:
520
if ($rule_ary['pm_unread'])
522
$unread_ids[] = $msg_id;
526
case ACTION_DELETE_MESSAGE:
527
$delete_ids[] = $msg_id;
528
$message_removed = true;
531
case ACTION_MARK_AS_IMPORTANT:
532
if (!$rule_ary['pm_marked'])
534
$important_ids[] = $msg_id;
540
// 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
541
// folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
542
if (!$folder_action && !$message_removed)
544
$move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
548
// Do not change the order of processing
549
// The number of queries needed to be executed here highly depends on the defined rules and are
550
// only gone through if new messages arrive.
553
if (sizeof($delete_ids))
555
$num_removed += sizeof($delete_ids);
556
delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
559
// Set messages to Unread
560
if (sizeof($unread_ids))
562
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
564
WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
565
AND user_id = $user_id
566
AND folder_id = " . PRIVMSGS_NO_BOX;
567
$db->sql_query($sql);
570
// mark messages as important
571
if (sizeof($important_ids))
573
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
574
SET pm_marked = 1 - pm_marked
575
WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
576
AND user_id = $user_id
577
AND " . $db->sql_in_set('msg_id', $important_ids);
578
$db->sql_query($sql);
584
if (sizeof($move_into_folder))
586
// Determine Full Folder Action - we need the move to folder id later eventually
587
$full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
589
$sql_folder = array_keys($move_into_folder);
590
if ($full_folder_action >= 0)
592
$sql_folder[] = $full_folder_action;
595
$sql = 'SELECT folder_id, pm_count
596
FROM ' . PRIVMSGS_FOLDER_TABLE . '
597
WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
598
AND user_id = $user_id";
599
$result = $db->sql_query($sql);
601
while ($row = $db->sql_fetchrow($result))
603
$folder[(int) $row['folder_id']] = (int) $row['pm_count'];
605
$db->sql_freeresult($result);
609
if (in_array(PRIVMSGS_INBOX, array_keys($move_into_folder)))
611
$sql = 'SELECT COUNT(msg_id) as num_messages
612
FROM ' . PRIVMSGS_TO_TABLE . "
613
WHERE user_id = $user_id
614
AND folder_id = " . PRIVMSGS_INBOX;
615
$result = $db->sql_query($sql);
616
$folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
617
$db->sql_freeresult($result);
621
// Here we have ideally only one folder to move into
622
foreach ($move_into_folder as $folder_id => $msg_ary)
624
$dest_folder = $folder_id;
625
$full_folder_action = FULL_FOLDER_NONE;
627
// Check Message Limit - we calculate with the complete array, most of the time it is one message
628
// But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
629
if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit'])
631
$full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
633
// If destination folder itself is full...
634
if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit'])
636
$full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1));
639
// If Full Folder Action is to move to another folder, we simply adjust the destination folder
640
if ($full_folder_action >= 0)
642
$dest_folder = $full_folder_action;
644
else if ($full_folder_action == FULL_FOLDER_DELETE)
646
// Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
647
$sql = 'SELECT msg_id
648
FROM ' . PRIVMSGS_TO_TABLE . "
649
WHERE user_id = $user_id
650
AND folder_id = $dest_folder
651
ORDER BY msg_id ASC";
652
$result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
654
$delete_ids = array();
655
while ($row = $db->sql_fetchrow($result))
657
$delete_ids[] = $row['msg_id'];
659
$db->sql_freeresult($result);
661
$num_removed += sizeof($delete_ids);
662
delete_pm($user_id, $delete_ids, $dest_folder);
667
if ($full_folder_action == FULL_FOLDER_HOLD)
669
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
670
SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
671
WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
672
AND user_id = $user_id
673
AND " . $db->sql_in_set('msg_id', $msg_ary);
674
$db->sql_query($sql);
678
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
679
SET folder_id = $dest_folder, pm_new = 0
680
WHERE folder_id = " . PRIVMSGS_NO_BOX . "
681
AND user_id = $user_id
683
AND " . $db->sql_in_set('msg_id', $msg_ary);
684
$db->sql_query($sql);
686
if ($dest_folder != PRIVMSGS_INBOX)
688
$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
689
SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
690
WHERE folder_id = $dest_folder
691
AND user_id = $user_id";
692
$db->sql_query($sql);
697
if (sizeof($action_ary))
699
// Move from OUTBOX to SENTBOX
700
// We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
701
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
702
SET folder_id = ' . PRIVMSGS_SENTBOX . '
703
WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
704
AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
705
$db->sql_query($sql);
708
// Update new/unread count
711
// Now check how many messages got not moved...
712
$sql = 'SELECT COUNT(msg_id) as num_messages
713
FROM ' . PRIVMSGS_TO_TABLE . "
714
WHERE user_id = $user_id
715
AND folder_id = " . PRIVMSGS_HOLD_BOX;
716
$result = $db->sql_query($sql);
717
$num_not_moved = (int) $db->sql_fetchfield('num_messages');
718
$db->sql_freeresult($result);
720
return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
724
* Move PM from one to another folder
726
function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
729
global $phpbb_root_path, $phpEx;
733
if (!is_array($move_msg_ids))
735
$move_msg_ids = array($move_msg_ids);
738
if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) &&
739
!in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder)
741
// We have to check the destination folder ;)
742
if ($dest_folder != PRIVMSGS_INBOX)
744
$sql = 'SELECT folder_id, folder_name, pm_count
745
FROM ' . PRIVMSGS_FOLDER_TABLE . "
746
WHERE folder_id = $dest_folder
747
AND user_id = $user_id";
748
$result = $db->sql_query($sql);
749
$row = $db->sql_fetchrow($result);
750
$db->sql_freeresult($result);
754
trigger_error('NOT_AUTHORISED');
757
if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit)
759
$message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />';
760
$message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']);
761
trigger_error($message);
766
$sql = 'SELECT COUNT(msg_id) as num_messages
767
FROM ' . PRIVMSGS_TO_TABLE . '
768
WHERE folder_id = ' . PRIVMSGS_INBOX . "
769
AND user_id = $user_id";
770
$result = $db->sql_query($sql);
771
$num_messages = (int) $db->sql_fetchfield('num_messages');
772
$db->sql_freeresult($result);
774
if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit)
776
$message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />';
777
$message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=inbox') . '">', '</a>', $user->lang['PM_INBOX']);
778
trigger_error($message);
782
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
783
SET folder_id = $dest_folder
784
WHERE folder_id = $cur_folder_id
785
AND user_id = $user_id
786
AND " . $db->sql_in_set('msg_id', $move_msg_ids);
787
$db->sql_query($sql);
788
$num_moved = $db->sql_affectedrows();
793
if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)))
795
$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
796
SET pm_count = pm_count - $num_moved
797
WHERE folder_id = $cur_folder_id
798
AND user_id = $user_id";
799
$db->sql_query($sql);
802
if ($dest_folder != PRIVMSGS_INBOX)
804
$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
805
SET pm_count = pm_count + $num_moved
806
WHERE folder_id = $dest_folder
807
AND user_id = $user_id";
808
$db->sql_query($sql);
812
else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)))
814
trigger_error('CANNOT_MOVE_SPECIAL');
821
* Update unread message status
823
function update_unread_status($unread, $msg_id, $user_id, $folder_id)
832
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
834
WHERE msg_id = $msg_id
835
AND user_id = $user_id
836
AND folder_id = $folder_id";
837
$db->sql_query($sql);
839
$sql = 'UPDATE ' . USERS_TABLE . "
840
SET user_unread_privmsg = user_unread_privmsg - 1
841
WHERE user_id = $user_id";
842
$db->sql_query($sql);
844
if ($user->data['user_id'] == $user_id)
846
$user->data['user_unread_privmsg']--;
848
// Try to cope with previous wrong conversions...
849
if ($user->data['user_unread_privmsg'] < 0)
851
$sql = 'UPDATE ' . USERS_TABLE . "
852
SET user_unread_privmsg = 0
853
WHERE user_id = $user_id";
854
$db->sql_query($sql);
856
$user->data['user_unread_privmsg'] = 0;
862
* Handle all actions possible with marked messages
864
function handle_mark_actions($user_id, $mark_action)
866
global $db, $user, $phpbb_root_path, $phpEx;
868
$msg_ids = request_var('marked_msg_id', array(0));
869
$cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
870
$confirm = (isset($_POST['confirm'])) ? true : false;
872
if (!sizeof($msg_ids))
877
switch ($mark_action)
879
case 'mark_important':
881
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
882
SET pm_marked = 1 - pm_marked
883
WHERE folder_id = $cur_folder_id
884
AND user_id = $user_id
885
AND " . $db->sql_in_set('msg_id', $msg_ids);
886
$db->sql_query($sql);
890
case 'delete_marked':
892
if (confirm_box(true))
894
delete_pm($user_id, $msg_ids, $cur_folder_id);
896
$success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED';
897
$redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id);
899
meta_refresh(3, $redirect);
900
trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>'));
904
$s_hidden_fields = array(
905
'cur_folder_id' => $cur_folder_id,
906
'mark_option' => 'delete_marked',
907
'submit_mark' => true,
908
'marked_msg_id' => $msg_ids
911
confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
926
function delete_pm($user_id, $msg_ids, $folder_id)
930
$user_id = (int) $user_id;
931
$folder_id = (int) $folder_id;
938
if (!is_array($msg_ids))
944
$msg_ids = array($msg_ids);
947
if (!sizeof($msg_ids))
952
// Get PM Information for later deleting
953
$sql = 'SELECT msg_id, pm_unread, pm_new
954
FROM ' . PRIVMSGS_TO_TABLE . '
955
WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
956
AND folder_id = $folder_id
957
AND user_id = $user_id";
958
$result = $db->sql_query($sql);
960
$delete_rows = array();
961
$num_unread = $num_new = $num_deleted = 0;
962
while ($row = $db->sql_fetchrow($result))
964
$num_unread += (int) $row['pm_unread'];
965
$num_new += (int) $row['pm_new'];
967
$delete_rows[$row['msg_id']] = 1;
969
$db->sql_freeresult($result);
972
if (!sizeof($delete_rows))
977
// if no one has read the message yet (meaning it is in users outbox)
978
// then mark the message as deleted...
979
if ($folder_id == PRIVMSGS_OUTBOX)
981
// Remove PM from Outbox
982
$sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
983
WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . '
984
AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
985
$db->sql_query($sql);
987
// Update PM Information for safety
988
$sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = ''
989
WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
990
$db->sql_query($sql);
992
// Set delete flag for those intended to receive the PM
993
// We do not remove the message actually, to retain some basic information (sent time for example)
994
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
996
WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
997
$db->sql_query($sql);
999
$num_deleted = $db->sql_affectedrows();
1003
// Delete private message data
1004
$sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
1005
WHERE user_id = $user_id
1006
AND folder_id = $folder_id
1007
AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
1008
$db->sql_query($sql);
1009
$num_deleted = $db->sql_affectedrows();
1012
// if folder id is user defined folder then decrease pm_count
1013
if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX)))
1015
$sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
1016
SET pm_count = pm_count - $num_deleted
1017
WHERE folder_id = $folder_id";
1018
$db->sql_query($sql);
1021
// Update unread and new status field
1022
if ($num_unread || $num_new)
1024
$set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
1028
$set_sql .= ($set_sql != '') ? ', ' : '';
1029
$set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
1032
$db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
1034
$user->data['user_new_privmsg'] -= $num_new;
1035
$user->data['user_unread_privmsg'] -= $num_unread;
1038
// Now we have to check which messages we can delete completely
1039
$sql = 'SELECT msg_id
1040
FROM ' . PRIVMSGS_TO_TABLE . '
1041
WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1042
$result = $db->sql_query($sql);
1044
while ($row = $db->sql_fetchrow($result))
1046
unset($delete_rows[$row['msg_id']]);
1048
$db->sql_freeresult($result);
1050
$delete_ids = array_keys($delete_rows);
1052
if (sizeof($delete_ids))
1054
$sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
1055
WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
1056
$db->sql_query($sql);
1063
* Rebuild message header
1065
function rebuild_header($check_ary)
1071
foreach ($check_ary as $check_type => $address_field)
1073
// Split Addresses into users and groups
1074
preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1077
foreach ($match[1] as $id => $type)
1079
${$type}[] = (int) $match[2][$id];
1082
$_types = array('u', 'g');
1083
foreach ($_types as $type)
1087
foreach ($$type as $id)
1089
$address[$type][$id] = $check_type;
1099
* Print out/assign recipient information
1101
function write_pm_addresses($check_ary, $author_id, $plaintext = false)
1103
global $db, $user, $template, $phpbb_root_path, $phpEx;
1105
$addresses = array();
1107
foreach ($check_ary as $check_type => $address_field)
1109
if (!is_array($address_field))
1111
// Split Addresses into users and groups
1112
preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1115
foreach ($match[1] as $id => $type)
1117
${$type}[] = (int) $match[2][$id];
1122
$u = $address_field['u'];
1123
$g = $address_field['g'];
1129
$sql = 'SELECT user_id, username, user_colour
1130
FROM ' . USERS_TABLE . '
1131
WHERE ' . $db->sql_in_set('user_id', $u) . '
1132
AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1133
$result = $db->sql_query($sql);
1135
while ($row = $db->sql_fetchrow($result))
1137
if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1141
$address[] = $row['username'];
1145
$address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
1149
$db->sql_freeresult($result);
1156
$sql = 'SELECT group_name, group_type
1157
FROM ' . GROUPS_TABLE . '
1158
WHERE ' . $db->sql_in_set('group_id', $g);
1159
$result = $db->sql_query($sql);
1161
while ($row = $db->sql_fetchrow($result))
1163
if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1165
$address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1168
$db->sql_freeresult($result);
1172
$sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
1173
FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
1174
WHERE ' . $db->sql_in_set('g.group_id', $g) . '
1175
AND g.group_id = ug.group_id
1176
AND ug.user_pending = 0';
1177
$result = $db->sql_query($sql);
1179
while ($row = $db->sql_fetchrow($result))
1181
if (!isset($address['group'][$row['group_id']]))
1183
if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1185
$row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1186
$address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
1190
if (isset($address['user'][$row['user_id']]))
1192
$address['user'][$row['user_id']]['in_group'] = $row['group_id'];
1195
$db->sql_freeresult($result);
1199
if (sizeof($address) && !$plaintext)
1201
$template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
1203
foreach ($address as $type => $adr_ary)
1205
foreach ($adr_ary as $id => $row)
1208
'IS_GROUP' => ($type == 'group') ? true : false,
1209
'IS_USER' => ($type == 'user') ? true : false,
1211
'NAME' => $row['name'],
1212
'COLOUR' => ($row['colour']) ? '#' . $row['colour'] : '',
1216
if ($type == 'user')
1218
$tpl_ary = array_merge($tpl_ary, array(
1219
'U_VIEW' => get_username_string('profile', $id, $row['name'], $row['colour']),
1220
'NAME_FULL' => get_username_string('full', $id, $row['name'], $row['colour']),
1225
$tpl_ary = array_merge($tpl_ary, array(
1226
'U_VIEW' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id),
1230
$template->assign_block_vars($check_type . '_recipient', $tpl_ary);
1235
$addresses[$check_type] = $address;
1244
function get_folder_status($folder_id, $folder)
1246
global $db, $user, $config;
1248
if (isset($folder[$folder_id]))
1250
$folder = $folder[$folder_id];
1258
'folder_name' => $folder['folder_name'],
1259
'cur' => $folder['num_messages'],
1260
'remaining' => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0,
1261
'max' => $user->data['message_limit'],
1262
'percent' => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0,
1265
$return['message'] = sprintf($user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']);
1277
function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
1279
global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path;
1281
// We do not handle erasing pms here
1282
if ($mode == 'delete')
1287
$current_time = time();
1289
// Collect some basic information about which tables and which rows to update/insert
1290
$sql_data = array();
1293
// Recipient Information
1294
$recipients = $to = $bcc = array();
1296
if ($mode != 'edit')
1298
// Build Recipient List
1299
// u|g => array($user_id => 'to'|'bcc')
1300
$_types = array('u', 'g');
1301
foreach ($_types as $ug_type)
1303
if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
1305
foreach ($data['address_list'][$ug_type] as $id => $field)
1309
// Do not rely on the address list being "valid"
1310
if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
1315
$field = ($field == 'to') ? 'to' : 'bcc';
1316
if ($ug_type == 'u')
1318
$recipients[$id] = $field;
1320
${$field}[] = $ug_type . '_' . $id;
1325
if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
1327
$sql = 'SELECT u.user_type, ug.group_id, ug.user_id
1328
FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
1329
WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
1330
AND ug.user_pending = 0
1331
AND u.user_id = ug.user_id
1332
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')';
1333
$result = $db->sql_query($sql);
1335
while ($row = $db->sql_fetchrow($result))
1337
$field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
1338
$recipients[$row['user_id']] = $field;
1340
$db->sql_freeresult($result);
1343
if (!sizeof($recipients))
1345
trigger_error('NO_RECIPIENT');
1349
$db->sql_transaction('begin');
1357
$root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
1359
// Set message_replied switch for this user
1360
$sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
1362
WHERE user_id = ' . $data['from_user_id'] . '
1363
AND msg_id = ' . $data['reply_from_msg_id'];
1371
'root_level' => $root_level,
1372
'author_id' => $data['from_user_id'],
1373
'icon_id' => $data['icon_id'],
1374
'author_ip' => $data['from_user_ip'],
1375
'message_time' => $current_time,
1376
'enable_bbcode' => $data['enable_bbcode'],
1377
'enable_smilies' => $data['enable_smilies'],
1378
'enable_magic_url' => $data['enable_urls'],
1379
'enable_sig' => $data['enable_sig'],
1380
'message_subject' => $subject,
1381
'message_text' => $data['message'],
1382
'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1383
'bbcode_bitfield' => $data['bbcode_bitfield'],
1384
'bbcode_uid' => $data['bbcode_uid'],
1385
'to_address' => implode(':', $to),
1386
'bcc_address' => implode(':', $bcc)
1392
'icon_id' => $data['icon_id'],
1393
'message_edit_time' => $current_time,
1394
'enable_bbcode' => $data['enable_bbcode'],
1395
'enable_smilies' => $data['enable_smilies'],
1396
'enable_magic_url' => $data['enable_urls'],
1397
'enable_sig' => $data['enable_sig'],
1398
'message_subject' => $subject,
1399
'message_text' => $data['message'],
1400
'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1401
'bbcode_bitfield' => $data['bbcode_bitfield'],
1402
'bbcode_uid' => $data['bbcode_uid']
1407
if (sizeof($sql_data))
1411
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
1413
$db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
1414
$data['msg_id'] = $db->sql_nextid();
1416
else if ($mode == 'edit')
1418
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
1419
SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
1420
WHERE msg_id = ' . $data['msg_id'];
1421
$db->sql_query($sql);
1425
if ($mode != 'edit')
1429
$db->sql_query($sql);
1434
foreach ($recipients as $user_id => $type)
1437
'msg_id' => (int) $data['msg_id'],
1438
'user_id' => (int) $user_id,
1439
'author_id' => (int) $data['from_user_id'],
1440
'folder_id' => PRIVMSGS_NO_BOX,
1443
'pm_forwarded' => ($mode == 'forward') ? 1 : 0
1447
$db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
1449
$sql = 'UPDATE ' . USERS_TABLE . '
1450
SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
1451
WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
1452
$db->sql_query($sql);
1454
// Put PM into outbox
1457
$db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1458
'msg_id' => (int) $data['msg_id'],
1459
'user_id' => (int) $data['from_user_id'],
1460
'author_id' => (int) $data['from_user_id'],
1461
'folder_id' => PRIVMSGS_OUTBOX,
1464
'pm_forwarded' => ($mode == 'forward') ? 1 : 0))
1469
// Set user last post time
1470
if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post')
1472
$sql = 'UPDATE ' . USERS_TABLE . "
1473
SET user_lastpost_time = $current_time
1474
WHERE user_id = " . $data['from_user_id'];
1475
$db->sql_query($sql);
1478
// Submit Attachments
1479
if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
1481
$space_taken = $files_added = 0;
1482
$orphan_rows = array();
1484
foreach ($data['attachment_data'] as $pos => $attach_row)
1486
$orphan_rows[(int) $attach_row['attach_id']] = array();
1489
if (sizeof($orphan_rows))
1491
$sql = 'SELECT attach_id, filesize, physical_filename
1492
FROM ' . ATTACHMENTS_TABLE . '
1493
WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
1496
AND poster_id = ' . $user->data['user_id'];
1497
$result = $db->sql_query($sql);
1499
$orphan_rows = array();
1500
while ($row = $db->sql_fetchrow($result))
1502
$orphan_rows[$row['attach_id']] = $row;
1504
$db->sql_freeresult($result);
1507
foreach ($data['attachment_data'] as $pos => $attach_row)
1509
if ($attach_row['is_orphan'] && !in_array($attach_row['attach_id'], array_keys($orphan_rows)))
1514
if (!$attach_row['is_orphan'])
1516
// update entry in db if attachment already stored in db and filespace
1517
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
1518
SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
1519
WHERE attach_id = " . (int) $attach_row['attach_id'] . '
1521
$db->sql_query($sql);
1525
// insert attachment into db
1526
if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
1531
$space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
1534
$attach_sql = array(
1535
'post_msg_id' => $data['msg_id'],
1538
'poster_id' => $data['from_user_id'],
1539
'attach_comment' => $attach_row['attach_comment'],
1542
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
1543
WHERE attach_id = ' . $attach_row['attach_id'] . '
1545
AND poster_id = ' . $user->data['user_id'];
1546
$db->sql_query($sql);
1550
if ($space_taken && $files_added)
1552
set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
1553
set_config('num_files', $config['num_files'] + $files_added, true);
1557
// Delete draft if post was loaded...
1558
$draft_id = request_var('draft_loaded', 0);
1561
$sql = 'DELETE FROM ' . DRAFTS_TABLE . "
1562
WHERE draft_id = $draft_id
1563
AND user_id = " . $data['from_user_id'];
1564
$db->sql_query($sql);
1567
$db->sql_transaction('commit');
1569
// Send Notifications
1570
if ($mode != 'edit')
1572
pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']);
1575
return $data['msg_id'];
1581
function pm_notification($mode, $author, $recipients, $subject, $message)
1583
global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
1585
$subject = censor_text($subject);
1587
unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
1589
if (!sizeof($recipients))
1594
// Get banned User ID's
1595
$sql = 'SELECT ban_userid
1596
FROM ' . BANLIST_TABLE . '
1597
WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
1598
AND ban_exclude = 0';
1599
$result = $db->sql_query($sql);
1601
while ($row = $db->sql_fetchrow($result))
1603
unset($recipients[$row['ban_userid']]);
1605
$db->sql_freeresult($result);
1607
if (!sizeof($recipients))
1612
$sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
1613
FROM ' . USERS_TABLE . '
1614
WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
1615
$result = $db->sql_query($sql);
1617
$msg_list_ary = array();
1618
while ($row = $db->sql_fetchrow($result))
1620
if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
1622
$msg_list_ary[] = array(
1623
'method' => $row['user_notify_type'],
1624
'email' => $row['user_email'],
1625
'jabber' => $row['user_jabber'],
1626
'name' => $row['username'],
1627
'lang' => $row['user_lang']
1631
$db->sql_freeresult($result);
1633
if (!sizeof($msg_list_ary))
1638
include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
1639
$messenger = new messenger();
1641
foreach ($msg_list_ary as $pos => $addr)
1643
$messenger->template('privmsg_notify', $addr['lang']);
1645
$messenger->to($addr['email'], $addr['name']);
1646
$messenger->im($addr['jabber'], $addr['name']);
1648
$messenger->assign_vars(array(
1649
'SUBJECT' => htmlspecialchars_decode($subject),
1650
'AUTHOR_NAME' => htmlspecialchars_decode($author),
1651
'USERNAME' => htmlspecialchars_decode($addr['name']),
1653
'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox")
1656
$messenger->send($addr['method']);
1658
unset($msg_list_ary);
1660
$messenger->save_queue();
1666
* Display Message History
1668
function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
1670
global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode;
1672
// Get History Messages (could be newer)
1673
$sql = 'SELECT t.*, p.*, u.*
1674
FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u
1675
WHERE t.msg_id = p.msg_id
1676
AND p.author_id = u.user_id
1677
AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ")
1678
AND t.user_id = $user_id";
1680
if (!$message_row['root_level'])
1682
$sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
1686
$sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';
1688
$sql .= ' ORDER BY p.message_time DESC';
1690
$result = $db->sql_query($sql);
1691
$row = $db->sql_fetchrow($result);
1695
$db->sql_freeresult($result);
1700
$bbcode_bitfield = '';
1701
$folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&folder=';
1705
$folder_id = (int) $row['folder_id'];
1707
$row['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER'];
1709
if (isset($rowset[$row['msg_id']]))
1711
$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'];
1715
$rowset[$row['msg_id']] = $row;
1716
$bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
1719
while ($row = $db->sql_fetchrow($result));
1720
$db->sql_freeresult($result);
1722
$title = $row['message_subject'];
1724
if (sizeof($rowset) == 1 && !$in_post_mode)
1729
// Instantiate BBCode class
1730
if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '')
1732
if (!class_exists('bbcode'))
1734
include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
1736
$bbcode = new bbcode(base64_encode($bbcode_bitfield));
1739
$title = censor_text($title);
1741
$url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
1742
$next_history_pm = $previous_history_pm = $prev_id = 0;
1744
foreach ($rowset as $id => $row)
1746
$author_id = $row['author_id'];
1747
$folder_id = (int) $row['folder_id'];
1749
$subject = $row['message_subject'];
1750
$message = $row['message_text'];
1752
$message = censor_text($message);
1754
if ($row['bbcode_bitfield'])
1756
$bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
1759
$message = bbcode_nl2br($message);
1760
$message = smiley_text($message, !$row['enable_smilies']);
1762
$subject = censor_text($subject);
1766
$next_history_pm = next($rowset);
1767
$next_history_pm = (sizeof($next_history_pm)) ? (int) $next_history_pm['msg_id'] : 0;
1768
$previous_history_pm = $prev_id;
1771
$template->assign_block_vars('history_row', array(
1772
'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),
1773
'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']),
1774
'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']),
1775
'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']),
1777
'SUBJECT' => $subject,
1778
'SENT_DATE' => $user->format_date($row['message_time']),
1779
'MESSAGE' => $message,
1780
'FOLDER' => implode(', ', $row['folder']),
1782
'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id),
1783
'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false,
1784
'S_IN_POST_MODE' => $in_post_mode,
1786
'MSG_ID' => $row['msg_id'],
1787
'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'],
1788
'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'] : '',
1789
'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'] : '')
1791
unset($rowset[$id]);
1795
$template->assign_vars(array(
1796
'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']),
1797
'HISTORY_TITLE' => $title,
1799
'U_VIEW_NEXT_HISTORY' => ($next_history_pm) ? "$url&p=" . $next_history_pm : '',
1800
'U_VIEW_PREVIOUS_HISTORY' => ($previous_history_pm) ? "$url&p=" . $previous_history_pm : '',
b'\\ No newline at end of file'