phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_privmsgs.php

History | View | Annotate | Download (57 kB)

1
<?php
2
/**
3
*
4
* @package phpBB3
5
* @copyright (c) 2005 phpBB Group
6
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
7
*
8
*/
9
10
/**
11
*/
12
if (!defined('IN_PHPBB'))
13
{
14
        exit;
15
}
16
17
/*
18
        Ability to simply add own rules by doing three things:
19
                1) Add an appropriate constant
20
                2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required)
21
                3) Implement the rule logic in the check_rule() function
22
                4) Add a new language variable to ucp.php
23
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.
26
*/
27
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
42
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);
47
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);
53
54
/**
55
* Global private message rules
56
* These rules define what to do if a rule is hit
57
*/
58
$global_privmsgs_rules = array(
59
        CHECK_SUBJECT        => array(
60
                RULE_IS_LIKE                => array('check0' => 'message_subject'),
61
                RULE_IS_NOT_LIKE        => array('check0' => 'message_subject'),
62
                RULE_IS                                => array('check0' => 'message_subject'),
63
                RULE_IS_NOT                        => array('check0' => 'message_subject'),
64
                RULE_BEGINS_WITH        => array('check0' => 'message_subject'),
65
                RULE_ENDS_WITH                => array('check0' => 'message_subject'),
66
        ),
67
68
        CHECK_SENDER        => array(
69
                RULE_IS_LIKE                => array('check0' => 'username'),
70
                RULE_IS_NOT_LIKE        => array('check0' => 'username'),
71
                RULE_IS                                => array('check0' => 'username'),
72
                RULE_IS_NOT                        => array('check0' => 'username'),
73
                RULE_BEGINS_WITH        => array('check0' => 'username'),
74
                RULE_ENDS_WITH                => array('check0' => 'username'),
75
                RULE_IS_FRIEND                => array('check0' => 'friend'),
76
                RULE_IS_FOE                        => array('check0' => 'foe'),
77
                RULE_IS_USER                => array('check0' => 'author_id'),
78
                RULE_IS_GROUP                => array('check0' => 'author_in_group'),
79
        ),
80
81
        CHECK_MESSAGE        => array(
82
                RULE_IS_LIKE                => array('check0' => 'message_text'),
83
                RULE_IS_NOT_LIKE        => array('check0' => 'message_text'),
84
                RULE_IS                                => array('check0' => 'message_text'),
85
                RULE_IS_NOT                        => array('check0' => 'message_text'),
86
        ),
87
88
        CHECK_STATUS        => array(
89
                RULE_ANSWERED                => array('check0' => 'pm_replied'),
90
                RULE_FORWARDED                => array('check0' => 'pm_forwarded'),
91
        ),
92
93
        CHECK_TO                => array(
94
                RULE_TO_GROUP                => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group'),
95
                RULE_TO_ME                        => array('check0' => 'to', 'check1' => 'bcc'),
96
        )
97
);
98
99
/**
100
* This is for defining which condition fields to show for which Rule
101
*/
102
$global_rule_conditions = array(
103
        RULE_IS_LIKE                => 'text',
104
        RULE_IS_NOT_LIKE        => 'text',
105
        RULE_IS                                => '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'
111
);
112
113
/**
114
* Get all folder
115
*/
116
function get_folder($user_id, $folder_id = false)
117
{
118
        global $db, $user, $template;
119
        global $phpbb_root_path, $phpEx;
120
121
        $folder = array();
122
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 . '
128
                GROUP BY folder_id';
129
        $result = $db->sql_query($sql);
130
131
        $num_messages = $num_unread = array();
132
        while ($row = $db->sql_fetchrow($result))
133
        {
134
                $num_messages[(int) $row['folder_id']] = $row['num_messages'];
135
                $num_unread[(int) $row['folder_id']] = $row['num_unread'];
136
        }
137
        $db->sql_freeresult($result);
138
139
        // Make sure the default boxes are defined
140
        $available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX);
141
142
        foreach ($available_folder as $default_folder)
143
        {
144
                if (!isset($num_messages[$default_folder]))
145
                {
146
                        $num_messages[$default_folder] = 0;
147
                }
148
149
                if (!isset($num_unread[$default_folder]))
150
                {
151
                        $num_unread[$default_folder] = 0;
152
                }
153
        }
154
155
        // Adjust unread status for outbox
156
        $num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX];
157
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]
162
        );
163
164
        // Custom Folder
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);
169
170
        while ($row = $db->sql_fetchrow($result))
171
        {
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)
176
                );
177
        }
178
        $db->sql_freeresult($result);
179
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]
184
        );
185
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]
190
        );
191
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)
194
        {
195
                $folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox');
196
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'],
202
203
                        'U_FOLDER'                        => ($f_id > 0) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $f_id) : append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $folder_id_name),
204
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)
208
                );
209
        }
210
211
        if ($folder_id !== false && !isset($folder[$folder_id]))
212
        {
213
                trigger_error('UNKNOWN_FOLDER');
214
        }
215
216
        return $folder;
217
}
218
219
/**
220
* Delete Messages From Sentbox
221
* we are doing this here because this saves us a bunch of checks and queries
222
*/
223
function clean_sentbox($num_sentbox_messages)
224
{
225
        global $db, $user, $config;
226
227
        // Check Message Limit
228
        if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit'])
229
        {
230
                // Delete old messages
231
                $sql = 'SELECT t.msg_id
232
                        FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p
233
                        WHERE t.msg_id = p.msg_id
234
                                AND t.user_id = ' . $user->data['user_id'] . '
235
                                AND t.folder_id = ' . PRIVMSGS_SENTBOX . '
236
                        ORDER BY p.message_time ASC';
237
                $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit']));
238
239
                $delete_ids = array();
240
                while ($row = $db->sql_fetchrow($result))
241
                {
242
                        $delete_ids[] = $row['msg_id'];
243
                }
244
                $db->sql_freeresult($result);
245
                delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX);
246
        }
247
}
248
249
/**
250
* Check Rule against Message Information
251
*/
252
function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
253
{
254
        global $user, $config;
255
256
        if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']]))
257
        {
258
                return false;
259
        }
260
261
        $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']];
262
263
        $result = false;
264
265
        $check0 = $message_row[$check_ary['check0']];
266
267
        switch ($rule_row['rule_connection'])
268
        {
269
                case RULE_IS_LIKE:
270
                        $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
271
                break;
272
                
273
                case RULE_IS_NOT_LIKE:
274
                        $result = !preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
275
                break;
276
                
277
                case RULE_IS:
278
                        $result = ($check0 == $rule_row['rule_string']);
279
                break;
280
                
281
                case RULE_IS_NOT:
282
                        $result = ($check0 != $rule_row['rule_string']);
283
                break;
284
                
285
                case RULE_BEGINS_WITH:
286
                        $result = preg_match("/^" . preg_quote($rule_row['rule_string'], '/') . '/i', $check0);
287
                break;
288
                
289
                case RULE_ENDS_WITH:
290
                        $result = preg_match("/" . preg_quote($rule_row['rule_string'], '/') . '$/i', $check0);
291
                break;
292
                
293
                case RULE_IS_FRIEND:
294
                case RULE_IS_FOE:
295
                case RULE_ANSWERED:
296
                case RULE_FORWARDED:
297
                        $result = ($check0 == 1);
298
                break;
299
                
300
                case RULE_IS_USER:
301
                        $result = ($check0 == $rule_row['rule_user_id']);
302
                break;
303
                
304
                case RULE_IS_GROUP:
305
                        $result = in_array($rule_row['rule_group_id'], $check0);
306
                break;
307
                
308
                case RULE_TO_GROUP:
309
                        $result = (in_array('g_' . $message_row[$check_ary['check2']], $check0) || in_array('g_' . $message_row[$check_ary['check2']], $message_row[$check_ary['check1']]));
310
                break;
311
                
312
                case RULE_TO_ME:
313
                        $result = (in_array('u_' . $user_id, $check0) || in_array('u_' . $user_id, $message_row[$check_ary['check1']]));
314
                break;
315
        }
316
317
318
        if (!$result)
319
        {
320
                return false;
321
        }
322
323
        switch ($rule_row['rule_action'])
324
        {
325
                case ACTION_PLACE_INTO_FOLDER:
326
                        return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']);
327
                break;
328
329
                case ACTION_MARK_AS_READ:
330
                case ACTION_MARK_AS_IMPORTANT:
331
                        return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
332
                break;
333
334
                case ACTION_DELETE_MESSAGE:
335
                        global $db, $auth;
336
337
                        // Check for admins/mods - users are not allowed to remove those messages...
338
                        // We do the check here to make sure the data we use is consistent
339
                        $sql = 'SELECT user_id, user_type, user_permissions
340
                                FROM ' . USERS_TABLE . '
341
                                WHERE user_id = ' . (int) $message_row['author_id'];
342
                        $result = $db->sql_query($sql);
343
                        $userdata = $db->sql_fetchrow($result);
344
                        $db->sql_freeresult($result);
345
346
                        $auth2 = new auth();
347
                        $auth2->acl($userdata);
348
349
                        if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
350
                        {
351
                                return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']);
352
                        }
353
354
                        return false;
355
                break;
356
357
                default:
358
                        return false;
359
        }
360
361
        return false;
362
}
363
364
/**
365
* Update user PM count
366
*/
367
function update_pm_counts()
368
{
369
        global $user, $db;
370
371
        // Update unread count
372
        $sql = 'SELECT COUNT(msg_id) as num_messages
373
                FROM ' . PRIVMSGS_TO_TABLE . '
374
                WHERE pm_unread = 1
375
                        AND folder_id <> ' . PRIVMSGS_OUTBOX . '
376
                        AND user_id = ' . $user->data['user_id'];
377
        $result = $db->sql_query($sql);
378
        $user->data['user_unread_privmsg'] = (int) $db->sql_fetchfield('num_messages');
379
        $db->sql_freeresult($result);
380
381
        // Update new pm count
382
        $sql = 'SELECT COUNT(msg_id) as num_messages
383
                FROM ' . PRIVMSGS_TO_TABLE . '
384
                WHERE pm_new = 1
385
                        AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
386
                        AND user_id = ' . $user->data['user_id'];
387
        $result = $db->sql_query($sql);
388
        $user->data['user_new_privmsg'] = (int) $db->sql_fetchfield('num_messages');
389
        $db->sql_freeresult($result);
390
391
        $db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array(
392
                'user_unread_privmsg'        => (int) $user->data['user_unread_privmsg'],
393
                'user_new_privmsg'                => (int) $user->data['user_new_privmsg'],
394
        )) . ' WHERE user_id = ' . $user->data['user_id']);
395
396
        // Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag.
397
        if (!$user->data['user_new_privmsg'])
398
        {
399
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
400
                        SET pm_new = 0
401
                        WHERE pm_new = 1
402
                                AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
403
                                AND user_id = ' . $user->data['user_id'];
404
                $db->sql_query($sql);
405
        }
406
}
407
408
/**
409
* Place new messages into appropriate folder
410
*/
411
function place_pm_into_folder(&$global_privmsgs_rules, $release = false)
412
{
413
        global $db, $user, $config;
414
415
        if (!$user->data['user_new_privmsg'])
416
        {
417
                return array('not_moved' => 0, 'removed' => 0);
418
        }
419
420
        $user_message_rules = (int) $user->data['user_message_rules'];
421
        $user_id = (int) $user->data['user_id'];
422
423
        $action_ary = $move_into_folder = array();
424
        $num_removed = 0;
425
426
        // Newly processing on-hold messages
427
        if ($release)
428
        {
429
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
430
                        SET folder_id = ' . PRIVMSGS_NO_BOX . '
431
                        WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . "
432
                                AND user_id = $user_id";
433
                $db->sql_query($sql);
434
        }
435
436
        // Get those messages not yet placed into any box
437
        $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id
438
                FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u
439
                WHERE t.user_id = $user_id
440
                        AND p.author_id = u.user_id
441
                        AND t.folder_id = " . PRIVMSGS_NO_BOX . '
442
                        AND t.msg_id = p.msg_id';
443
444
        // Just place into the appropriate arrays if no rules need to be checked
445
        if (!$user_message_rules)
446
        {
447
                $result = $db->sql_query($retrieve_sql);
448
449
                while ($row = $db->sql_fetchrow($result))
450
                {
451
                        $action_ary[$row['msg_id']][] = array('action' => false);
452
                }
453
                $db->sql_freeresult($result);
454
        }
455
        else
456
        {
457
                $user_rules = $zebra = $check_rows = array();
458
                $user_ids = $memberships = array();
459
460
                // First of all, grab all rules and retrieve friends/foes
461
                $sql = 'SELECT *
462
                        FROM ' . PRIVMSGS_RULES_TABLE . "
463
                        WHERE user_id = $user_id";
464
                $result = $db->sql_query($sql);
465
                $user_rules = $db->sql_fetchrowset($result);
466
                $db->sql_freeresult($result);
467
468
                if (sizeof($user_rules))
469
                {
470
                        $sql = 'SELECT zebra_id, friend, foe
471
                                FROM ' . ZEBRA_TABLE . "
472
                                WHERE user_id = $user_id";
473
                        $result = $db->sql_query($sql);
474
475
                        while ($row = $db->sql_fetchrow($result))
476
                        {
477
                                $zebra[$row['zebra_id']] = $row;
478
                        }
479
                        $db->sql_freeresult($result);
480
                }
481
482
                // Now build a bare-bone check_row array
483
                $result = $db->sql_query($retrieve_sql);
484
485
                while ($row = $db->sql_fetchrow($result))
486
                {
487
                        $check_rows[] = array_merge($row, array(
488
                                'to'                                => explode(':', $row['to_address']),
489
                                'bcc'                                => explode(':', $row['bcc_address']),
490
                                'friend'                        => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0,
491
                                'foe'                                => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0,
492
                                'user_in_group'                => array($user->data['group_id']),
493
                                'author_in_group'        => array())
494
                        );
495
496
                        $user_ids[] = $row['user_id'];
497
                }
498
                $db->sql_freeresult($result);
499
500
                // Retrieve user memberships
501
                if (sizeof($user_ids))
502
                {
503
                        $sql = 'SELECT *
504
                                FROM ' . USER_GROUP_TABLE . '
505
                                WHERE ' . $db->sql_in_set('user_id', $user_ids) . '
506
                                        AND user_pending = 0';
507
                        $result = $db->sql_query($sql);
508
509
                        while ($row = $db->sql_fetchrow($result))
510
                        {
511
                                $memberships[$row['user_id']][] = $row['group_id'];
512
                        }
513
                        $db->sql_freeresult($result);
514
                }
515
516
                // Now place into the appropriate folder
517
                foreach ($check_rows as $row)
518
                {
519
                        // Add membership if set
520
                        if (isset($memberships[$row['author_id']]))
521
                        {
522
                                $row['author_in_group'] = $memberships[$row['user_id']];
523
                        }
524
525
                        // Check Rule - this should be very quick since we have all information we need
526
                        $is_match = false;
527
                        foreach ($user_rules as $rule_row)
528
                        {
529
                                if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false)
530
                                {
531
                                        $is_match = true;
532
                                        $action_ary[$row['msg_id']][] = $action;
533
                                }
534
                        }
535
536
                        if (!$is_match)
537
                        {
538
                                $action_ary[$row['msg_id']][] = array('action' => false);
539
                        }
540
                }
541
542
                unset($user_rules, $zebra, $check_rows, $user_ids, $memberships);
543
        }
544
545
        // We place actions into arrays, to save queries.
546
        $sql = $unread_ids = $delete_ids = $important_ids = array();
547
548
        foreach ($action_ary as $msg_id => $msg_ary)
549
        {
550
                // It is allowed to execute actions more than once, except placing messages into folder
551
                $folder_action = $message_removed = false;
552
553
                foreach ($msg_ary as $pos => $rule_ary)
554
                {
555
                        if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER)
556
                        {
557
                                continue;
558
                        }
559
560
                        switch ($rule_ary['action'])
561
                        {
562
                                case ACTION_PLACE_INTO_FOLDER:
563
                                        // Folder actions have precedence, so we will remove any other ones
564
                                        $folder_action = true;
565
                                        $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id;
566
                                break;
567
568
                                case ACTION_MARK_AS_READ:
569
                                        if ($rule_ary['pm_unread'])
570
                                        {
571
                                                $unread_ids[] = $msg_id;
572
                                        }
573
                                break;
574
575
                                case ACTION_DELETE_MESSAGE:
576
                                        $delete_ids[] = $msg_id;
577
                                        $message_removed = true;
578
                                break;
579
580
                                case ACTION_MARK_AS_IMPORTANT:
581
                                        if (!$rule_ary['pm_marked'])
582
                                        {
583
                                                $important_ids[] = $msg_id;
584
                                        }
585
                                break;
586
                        }
587
                }
588
589
                // 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
590
                // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder.
591
                if (!$folder_action && !$message_removed)
592
                {
593
                        $move_into_folder[PRIVMSGS_INBOX][] = $msg_id;
594
                }
595
        }
596
597
        // Do not change the order of processing
598
        // The number of queries needed to be executed here highly depends on the defined rules and are
599
        // only gone through if new messages arrive.
600
601
        // Delete messages
602
        if (sizeof($delete_ids))
603
        {
604
                $num_removed += sizeof($delete_ids);
605
                delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX);
606
        }
607
608
        // Set messages to Unread
609
        if (sizeof($unread_ids))
610
        {
611
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
612
                        SET pm_unread = 0
613
                        WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . "
614
                                AND user_id = $user_id
615
                                AND folder_id = " . PRIVMSGS_NO_BOX;
616
                $db->sql_query($sql);
617
        }
618
619
        // mark messages as important
620
        if (sizeof($important_ids))
621
        {
622
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
623
                        SET pm_marked = 1 - pm_marked
624
                        WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
625
                                AND user_id = $user_id
626
                                AND " . $db->sql_in_set('msg_id', $important_ids);
627
                $db->sql_query($sql);
628
        }
629
630
        // Move into folder
631
        $folder = array();
632
633
        if (sizeof($move_into_folder))
634
        {
635
                // Determine Full Folder Action - we need the move to folder id later eventually
636
                $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
637
638
                $sql_folder = array_keys($move_into_folder);
639
                if ($full_folder_action >= 0)
640
                {
641
                        $sql_folder[] = $full_folder_action;
642
                }
643
644
                $sql = 'SELECT folder_id, pm_count
645
                        FROM ' . PRIVMSGS_FOLDER_TABLE . '
646
                        WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . "
647
                                AND user_id = $user_id";
648
                $result = $db->sql_query($sql);
649
650
                while ($row = $db->sql_fetchrow($result))
651
                {
652
                        $folder[(int) $row['folder_id']] = (int) $row['pm_count'];
653
                }
654
                $db->sql_freeresult($result);
655
656
                unset($sql_folder);
657
658
                if (isset($move_into_folder[PRIVMSGS_INBOX]))
659
                {
660
                        $sql = 'SELECT COUNT(msg_id) as num_messages
661
                                FROM ' . PRIVMSGS_TO_TABLE . "
662
                                WHERE user_id = $user_id
663
                                        AND folder_id = " . PRIVMSGS_INBOX;
664
                        $result = $db->sql_query($sql);
665
                        $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages');
666
                        $db->sql_freeresult($result);
667
                }
668
        }
669
670
        // Here we have ideally only one folder to move into
671
        foreach ($move_into_folder as $folder_id => $msg_ary)
672
        {
673
                $dest_folder = $folder_id;
674
                $full_folder_action = FULL_FOLDER_NONE;
675
676
                // Check Message Limit - we calculate with the complete array, most of the time it is one message
677
                // But we are making sure that the other way around works too (more messages in queue than allowed to be stored)
678
                if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit'])
679
                {
680
                        $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder'];
681
682
                        // If destination folder itself is full...
683
                        if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit'])
684
                        {
685
                                $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1));
686
                        }
687
688
                        // If Full Folder Action is to move to another folder, we simply adjust the destination folder
689
                        if ($full_folder_action >= 0)
690
                        {
691
                                $dest_folder = $full_folder_action;
692
                        }
693
                        else if ($full_folder_action == FULL_FOLDER_DELETE)
694
                        {
695
                                // Delete some messages. NOTE: Ordered by msg_id here instead of message_time!
696
                                $sql = 'SELECT msg_id
697
                                        FROM ' . PRIVMSGS_TO_TABLE . "
698
                                        WHERE user_id = $user_id
699
                                                AND folder_id = $dest_folder
700
                                        ORDER BY msg_id ASC";
701
                                $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit']));
702
703
                                $delete_ids = array();
704
                                while ($row = $db->sql_fetchrow($result))
705
                                {
706
                                        $delete_ids[] = $row['msg_id'];
707
                                }
708
                                $db->sql_freeresult($result);
709
710
                                $num_removed += sizeof($delete_ids);
711
                                delete_pm($user_id, $delete_ids, $dest_folder);
712
                        }
713
                }
714
715
                //
716
                if ($full_folder_action == FULL_FOLDER_HOLD)
717
                {
718
                        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
719
                                SET folder_id = ' . PRIVMSGS_HOLD_BOX . '
720
                                WHERE folder_id = ' . PRIVMSGS_NO_BOX . "
721
                                        AND user_id = $user_id
722
                                        AND " . $db->sql_in_set('msg_id', $msg_ary);
723
                        $db->sql_query($sql);
724
                }
725
                else
726
                {
727
                        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
728
                                SET folder_id = $dest_folder, pm_new = 0
729
                                WHERE folder_id = " . PRIVMSGS_NO_BOX . "
730
                                        AND user_id = $user_id
731
                                        AND pm_new = 1
732
                                        AND " . $db->sql_in_set('msg_id', $msg_ary);
733
                        $db->sql_query($sql);
734
735
                        if ($dest_folder != PRIVMSGS_INBOX)
736
                        {
737
                                $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . '
738
                                        SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . "
739
                                        WHERE folder_id = $dest_folder
740
                                                AND user_id = $user_id";
741
                                $db->sql_query($sql);
742
                        }
743
                }
744
        }
745
746
        if (sizeof($action_ary))
747
        {
748
                // Move from OUTBOX to SENTBOX
749
                // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted)
750
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
751
                        SET folder_id = ' . PRIVMSGS_SENTBOX . '
752
                        WHERE folder_id = ' . PRIVMSGS_OUTBOX . '
753
                                AND ' . $db->sql_in_set('msg_id', array_keys($action_ary));
754
                $db->sql_query($sql);
755
        }
756
757
        // Update new/unread count
758
        update_pm_counts();
759
760
        // Now check how many messages got not moved...
761
        $sql = 'SELECT COUNT(msg_id) as num_messages
762
                FROM ' . PRIVMSGS_TO_TABLE . "
763
                WHERE user_id = $user_id
764
                        AND folder_id = " . PRIVMSGS_HOLD_BOX;
765
        $result = $db->sql_query($sql);
766
        $num_not_moved = (int) $db->sql_fetchfield('num_messages');
767
        $db->sql_freeresult($result);
768
769
        return array('not_moved' => $num_not_moved, 'removed' => $num_removed);
770
}
771
772
/**
773
* Move PM from one to another folder
774
*/
775
function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id)
776
{
777
        global $db, $user;
778
        global $phpbb_root_path, $phpEx;
779
780
        $num_moved = 0;
781
782
        if (!is_array($move_msg_ids))
783
        {
784
                $move_msg_ids = array($move_msg_ids);
785
        }
786
787
        if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) &&
788
                !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder)
789
        {
790
                // We have to check the destination folder ;)
791
                if ($dest_folder != PRIVMSGS_INBOX)
792
                {
793
                        $sql = 'SELECT folder_id, folder_name, pm_count
794
                                FROM ' . PRIVMSGS_FOLDER_TABLE . "
795
                                WHERE folder_id = $dest_folder
796
                                        AND user_id = $user_id";
797
                        $result = $db->sql_query($sql);
798
                        $row = $db->sql_fetchrow($result);
799
                        $db->sql_freeresult($result);
800
801
                        if (!$row)
802
                        {
803
                                trigger_error('NOT_AUTHORISED');
804
                        }
805
806
                        if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit)
807
                        {
808
                                $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />';
809
                                $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']);
810
                                trigger_error($message);
811
                        }
812
                }
813
                else
814
                {
815
                        $sql = 'SELECT COUNT(msg_id) as num_messages
816
                                FROM ' . PRIVMSGS_TO_TABLE . '
817
                                WHERE folder_id = ' . PRIVMSGS_INBOX . "
818
                                        AND user_id = $user_id";
819
                        $result = $db->sql_query($sql);
820
                        $num_messages = (int) $db->sql_fetchfield('num_messages');
821
                        $db->sql_freeresult($result);
822
823
                        if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit)
824
                        {
825
                                $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />';
826
                                $message .= sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=inbox') . '">', '</a>', $user->lang['PM_INBOX']);
827
                                trigger_error($message);
828
                        }
829
                }
830
831
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
832
                        SET folder_id = $dest_folder
833
                        WHERE folder_id = $cur_folder_id
834
                                AND user_id = $user_id
835
                                AND " . $db->sql_in_set('msg_id', $move_msg_ids);
836
                $db->sql_query($sql);
837
                $num_moved = $db->sql_affectedrows();
838
839
                // Update pm counts
840
                if ($num_moved)
841
                {
842
                        if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)))
843
                        {
844
                                $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
845
                                        SET pm_count = pm_count - $num_moved
846
                                        WHERE folder_id = $cur_folder_id
847
                                                AND user_id = $user_id";
848
                                $db->sql_query($sql);
849
                        }
850
851
                        if ($dest_folder != PRIVMSGS_INBOX)
852
                        {
853
                                $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
854
                                        SET pm_count = pm_count + $num_moved
855
                                        WHERE folder_id = $dest_folder
856
                                                AND user_id = $user_id";
857
                                $db->sql_query($sql);
858
                        }
859
                }
860
        }
861
        else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)))
862
        {
863
                trigger_error('CANNOT_MOVE_SPECIAL');
864
        }
865
866
        return $num_moved;
867
}
868
869
/**
870
* Update unread message status
871
*/
872
function update_unread_status($unread, $msg_id, $user_id, $folder_id)
873
{
874
        if (!$unread)
875
        {
876
                return;
877
        }
878
879
        global $db, $user;
880
881
        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
882
                SET pm_unread = 0
883
                WHERE msg_id = $msg_id
884
                        AND user_id = $user_id
885
                        AND folder_id = $folder_id";
886
        $db->sql_query($sql);
887
888
        $sql = 'UPDATE ' . USERS_TABLE . "
889
                SET user_unread_privmsg = user_unread_privmsg - 1
890
                WHERE user_id = $user_id";
891
        $db->sql_query($sql);
892
893
        if ($user->data['user_id'] == $user_id)
894
        {
895
                $user->data['user_unread_privmsg']--;
896
897
                // Try to cope with previous wrong conversions...
898
                if ($user->data['user_unread_privmsg'] < 0)
899
                {
900
                        $sql = 'UPDATE ' . USERS_TABLE . "
901
                                SET user_unread_privmsg = 0
902
                                WHERE user_id = $user_id";
903
                        $db->sql_query($sql);
904
905
                        $user->data['user_unread_privmsg'] = 0;
906
                }
907
        }
908
}
909
910
/**
911
* Handle all actions possible with marked messages
912
*/
913
function handle_mark_actions($user_id, $mark_action)
914
{
915
        global $db, $user, $phpbb_root_path, $phpEx;
916
917
        $msg_ids                = request_var('marked_msg_id', array(0));
918
        $cur_folder_id        = request_var('cur_folder_id', PRIVMSGS_NO_BOX);
919
        $confirm                = (isset($_POST['confirm'])) ? true : false;
920
921
        if (!sizeof($msg_ids))
922
        {
923
                return false;
924
        }
925
926
        switch ($mark_action)
927
        {
928
                case 'mark_important':
929
930
                        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . "
931
                                SET pm_marked = 1 - pm_marked
932
                                WHERE folder_id = $cur_folder_id
933
                                        AND user_id = $user_id
934
                                        AND " . $db->sql_in_set('msg_id', $msg_ids);
935
                        $db->sql_query($sql);
936
937
                break;
938
939
                case 'delete_marked':
940
941
                        global $auth;
942
943
                        if (!$auth->acl_get('u_pm_delete'))
944
                        {
945
                                trigger_error('NO_AUTH_DELETE_MESSAGE');
946
                        }
947
948
                        if (confirm_box(true))
949
                        {
950
                                delete_pm($user_id, $msg_ids, $cur_folder_id);
951
952
                                $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED';
953
                                $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&amp;folder=' . $cur_folder_id);
954
955
                                meta_refresh(3, $redirect);
956
                                trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>'));
957
                        }
958
                        else
959
                        {
960
                                $s_hidden_fields = array(
961
                                        'cur_folder_id'        => $cur_folder_id,
962
                                        'mark_option'        => 'delete_marked',
963
                                        'submit_mark'        => true,
964
                                        'marked_msg_id'        => $msg_ids
965
                                );
966
967
                                confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields));
968
                        }
969
970
                break;
971
972
                default:
973
                        return false;
974
        }
975
976
        return true;
977
}
978
979
/**
980
* Delete PM(s)
981
*/
982
function delete_pm($user_id, $msg_ids, $folder_id)
983
{
984
        global $db, $user, $phpbb_root_path, $phpEx;
985
986
        $user_id        = (int) $user_id;
987
        $folder_id        = (int) $folder_id;
988
989
        if (!$user_id)
990
        {
991
                return false;
992
        }
993
994
        if (!is_array($msg_ids))
995
        {
996
                if (!$msg_ids)
997
                {
998
                        return false;
999
                }
1000
                $msg_ids = array($msg_ids);
1001
        }
1002
1003
        if (!sizeof($msg_ids))
1004
        {
1005
                return false;
1006
        }
1007
1008
        // Get PM Information for later deleting
1009
        $sql = 'SELECT msg_id, pm_unread, pm_new
1010
                FROM ' . PRIVMSGS_TO_TABLE . '
1011
                WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . "
1012
                        AND folder_id = $folder_id
1013
                        AND user_id = $user_id";
1014
        $result = $db->sql_query($sql);
1015
1016
        $delete_rows = array();
1017
        $num_unread = $num_new = $num_deleted = 0;
1018
        while ($row = $db->sql_fetchrow($result))
1019
        {
1020
                $num_unread += (int) $row['pm_unread'];
1021
                $num_new += (int) $row['pm_new'];
1022
1023
                $delete_rows[$row['msg_id']] = 1;
1024
        }
1025
        $db->sql_freeresult($result);
1026
        unset($msg_ids);
1027
1028
        if (!sizeof($delete_rows))
1029
        {
1030
                return false;
1031
        }
1032
1033
        $db->sql_transaction('begin');
1034
1035
        // if no one has read the message yet (meaning it is in users outbox)
1036
        // then mark the message as deleted...
1037
        if ($folder_id == PRIVMSGS_OUTBOX)
1038
        {
1039
                // Remove PM from Outbox
1040
                $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
1041
                        WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . '
1042
                                AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1043
                $db->sql_query($sql);
1044
1045
                // Update PM Information for safety
1046
                $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = ''
1047
                        WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows));
1048
                $db->sql_query($sql);
1049
1050
                // Set delete flag for those intended to receive the PM
1051
                // We do not remove the message actually, to retain some basic information (sent time for example)
1052
                $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
1053
                        SET pm_deleted = 1
1054
                        WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1055
                $db->sql_query($sql);
1056
1057
                $num_deleted = $db->sql_affectedrows();
1058
        }
1059
        else
1060
        {
1061
                // Delete private message data
1062
                $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . "
1063
                        WHERE user_id = $user_id
1064
                                AND folder_id = $folder_id
1065
                                AND " . $db->sql_in_set('msg_id', array_keys($delete_rows));
1066
                $db->sql_query($sql);
1067
                $num_deleted = $db->sql_affectedrows();
1068
        }
1069
1070
        // if folder id is user defined folder then decrease pm_count
1071
        if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX)))
1072
        {
1073
                $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . "
1074
                        SET pm_count = pm_count - $num_deleted
1075
                        WHERE folder_id = $folder_id";
1076
                $db->sql_query($sql);
1077
        }
1078
1079
        // Update unread and new status field
1080
        if ($num_unread || $num_new)
1081
        {
1082
                $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : '';
1083
1084
                if ($num_new)
1085
                {
1086
                        $set_sql .= ($set_sql != '') ? ', ' : '';
1087
                        $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new;
1088
                }
1089
1090
                $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id");
1091
1092
                $user->data['user_new_privmsg'] -= $num_new;
1093
                $user->data['user_unread_privmsg'] -= $num_unread;
1094
        }
1095
1096
        // Now we have to check which messages we can delete completely
1097
        $sql = 'SELECT msg_id
1098
                FROM ' . PRIVMSGS_TO_TABLE . '
1099
                WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows));
1100
        $result = $db->sql_query($sql);
1101
1102
        while ($row = $db->sql_fetchrow($result))
1103
        {
1104
                unset($delete_rows[$row['msg_id']]);
1105
        }
1106
        $db->sql_freeresult($result);
1107
1108
        $delete_ids = array_keys($delete_rows);
1109
1110
        if (sizeof($delete_ids))
1111
        {
1112
                // Check if there are any attachments we need to remove
1113
                if (!function_exists('delete_attachments'))
1114
                {
1115
                        include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1116
                }
1117
1118
                delete_attachments('message', $delete_ids, false);
1119
1120
                $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . '
1121
                        WHERE ' . $db->sql_in_set('msg_id', $delete_ids);
1122
                $db->sql_query($sql);
1123
        }
1124
1125
        $db->sql_transaction('commit');
1126
1127
        return true;
1128
}
1129
1130
/**
1131
* Rebuild message header
1132
*/
1133
function rebuild_header($check_ary)
1134
{
1135
        global $db;
1136
1137
        $address = array();
1138
1139
        foreach ($check_ary as $check_type => $address_field)
1140
        {
1141
                // Split Addresses into users and groups
1142
                preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1143
1144
                $u = $g = array();
1145
                foreach ($match[1] as $id => $type)
1146
                {
1147
                        ${$type}[] = (int) $match[2][$id];
1148
                }
1149
1150
                $_types = array('u', 'g');
1151
                foreach ($_types as $type)
1152
                {
1153
                        if (sizeof($$type))
1154
                        {
1155
                                foreach ($$type as $id)
1156
                                {
1157
                                        $address[$type][$id] = $check_type;
1158
                                }
1159
                        }
1160
                }
1161
        }
1162
1163
        return $address;
1164
}
1165
1166
/**
1167
* Print out/assign recipient information
1168
*/
1169
function write_pm_addresses($check_ary, $author_id, $plaintext = false)
1170
{
1171
        global $db, $user, $template, $phpbb_root_path, $phpEx;
1172
1173
        $addresses = array();
1174
1175
        foreach ($check_ary as $check_type => $address_field)
1176
        {
1177
                if (!is_array($address_field))
1178
                {
1179
                        // Split Addresses into users and groups
1180
                        preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match);
1181
1182
                        $u = $g = array();
1183
                        foreach ($match[1] as $id => $type)
1184
                        {
1185
                                ${$type}[] = (int) $match[2][$id];
1186
                        }
1187
                }
1188
                else
1189
                {
1190
                        $u = $address_field['u'];
1191
                        $g = $address_field['g'];
1192
                }
1193
1194
                $address = array();
1195
                if (sizeof($u))
1196
                {
1197
                        $sql = 'SELECT user_id, username, user_colour
1198
                                FROM ' . USERS_TABLE . '
1199
                                WHERE ' . $db->sql_in_set('user_id', $u);
1200
                        $result = $db->sql_query($sql);
1201
1202
                        while ($row = $db->sql_fetchrow($result))
1203
                        {
1204
                                if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1205
                                {
1206
                                        if ($plaintext)
1207
                                        {
1208
                                                $address[] = $row['username'];
1209
                                        }
1210
                                        else
1211
                                        {
1212
                                                $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']);
1213
                                        }
1214
                                }
1215
                        }
1216
                        $db->sql_freeresult($result);
1217
                }
1218
1219
                if (sizeof($g))
1220
                {
1221
                        if ($plaintext)
1222
                        {
1223
                                $sql = 'SELECT group_name, group_type
1224
                                        FROM ' . GROUPS_TABLE . '
1225
                                                WHERE ' . $db->sql_in_set('group_id', $g);
1226
                                $result = $db->sql_query($sql);
1227
1228
                                while ($row = $db->sql_fetchrow($result))
1229
                                {
1230
                                        if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1231
                                        {
1232
                                                $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1233
                                        }
1234
                                }
1235
                                $db->sql_freeresult($result);
1236
                        }
1237
                        else
1238
                        {
1239
                                $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id
1240
                                        FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
1241
                                                WHERE ' . $db->sql_in_set('g.group_id', $g) . '
1242
                                                AND g.group_id = ug.group_id
1243
                                                AND ug.user_pending = 0';
1244
                                $result = $db->sql_query($sql);
1245
1246
                                while ($row = $db->sql_fetchrow($result))
1247
                                {
1248
                                        if (!isset($address['group'][$row['group_id']]))
1249
                                        {
1250
                                                if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id'])
1251
                                                {
1252
                                                        $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'];
1253
                                                        $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']);
1254
                                                }
1255
                                        }
1256
1257
                                        if (isset($address['user'][$row['user_id']]))
1258
                                        {
1259
                                                $address['user'][$row['user_id']]['in_group'] = $row['group_id'];
1260
                                        }
1261
                                }
1262
                                $db->sql_freeresult($result);
1263
                        }
1264
                }
1265
1266
                if (sizeof($address) && !$plaintext)
1267
                {
1268
                        $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true);
1269
1270
                        foreach ($address as $type => $adr_ary)
1271
                        {
1272
                                foreach ($adr_ary as $id => $row)
1273
                                {
1274
                                        $tpl_ary = array(
1275
                                                'IS_GROUP'        => ($type == 'group') ? true : false,
1276
                                                'IS_USER'        => ($type == 'user') ? true : false,
1277
                                                'UG_ID'                => $id,
1278
                                                'NAME'                => $row['name'],
1279
                                                'COLOUR'        => ($row['colour']) ? '#' . $row['colour'] : '',
1280
                                                'TYPE'                => $type,
1281
                                        );
1282
1283
                                        if ($type == 'user')
1284
                                        {
1285
                                                $tpl_ary = array_merge($tpl_ary, array(
1286
                                                        'U_VIEW'                => get_username_string('profile', $id, $row['name'], $row['colour']),
1287
                                                        'NAME_FULL'                => get_username_string('full', $id, $row['name'], $row['colour']),
1288
                                                ));
1289
                                        }
1290
                                        else
1291
                                        {
1292
                                                $tpl_ary = array_merge($tpl_ary, array(
1293
                                                        'U_VIEW'                => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $id),
1294
                                                ));
1295
                                        }
1296
1297
                                        $template->assign_block_vars($check_type . '_recipient', $tpl_ary);
1298
                                }
1299
                        }
1300
                }
1301
1302
                $addresses[$check_type] = $address;
1303
        }
1304
1305
        return $addresses;
1306
}
1307
1308
/**
1309
* Get folder status
1310
*/
1311
function get_folder_status($folder_id, $folder)
1312
{
1313
        global $db, $user, $config;
1314
1315
        if (isset($folder[$folder_id]))
1316
        {
1317
                $folder = $folder[$folder_id];
1318
        }
1319
        else
1320
        {
1321
                return false;
1322
        }
1323
1324
        $return = array(
1325
                'folder_name'        => $folder['folder_name'],
1326
                'cur'                        => $folder['num_messages'],
1327
                'remaining'                => ($user->data['message_limit']) ? $user->data['message_limit'] - $folder['num_messages'] : 0,
1328
                'max'                        => $user->data['message_limit'],
1329
                'percent'                => ($user->data['message_limit']) ? (($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100) : 0,
1330
        );
1331
1332
        $return['message']        = $user->lang('FOLDER_STATUS_MSG', (int) $return['max'], $return['cur'], $return['percent']);
1333
1334
        return $return;
1335
}
1336
1337
//
1338
// COMPOSE MESSAGES
1339
//
1340
1341
/**
1342
* Submit PM
1343
*/
1344
function submit_pm($mode, $subject, &$data, $put_in_outbox = true)
1345
{
1346
        global $db, $auth, $config, $phpEx, $template, $user, $phpbb_root_path;
1347
1348
        // We do not handle erasing pms here
1349
        if ($mode == 'delete')
1350
        {
1351
                return false;
1352
        }
1353
1354
        $current_time = time();
1355
1356
        // Collect some basic information about which tables and which rows to update/insert
1357
        $sql_data = array();
1358
        $root_level = 0;
1359
1360
        // Recipient Information
1361
        $recipients = $to = $bcc = array();
1362
1363
        if ($mode != 'edit')
1364
        {
1365
                // Build Recipient List
1366
                // u|g => array($user_id => 'to'|'bcc')
1367
                $_types = array('u', 'g');
1368
                foreach ($_types as $ug_type)
1369
                {
1370
                        if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type]))
1371
                        {
1372
                                foreach ($data['address_list'][$ug_type] as $id => $field)
1373
                                {
1374
                                        $id = (int) $id;
1375
1376
                                        // Do not rely on the address list being "valid"
1377
                                        if (!$id || ($ug_type == 'u' && $id == ANONYMOUS))
1378
                                        {
1379
                                                continue;
1380
                                        }
1381
1382
                                        $field = ($field == 'to') ? 'to' : 'bcc';
1383
                                        if ($ug_type == 'u')
1384
                                        {
1385
                                                $recipients[$id] = $field;
1386
                                        }
1387
                                        ${$field}[] = $ug_type . '_' . $id;
1388
                                }
1389
                        }
1390
                }
1391
1392
                if (isset($data['address_list']['g']) && sizeof($data['address_list']['g']))
1393
                {
1394
                        // We need to check the PM status of group members (do they want to receive PM's?)
1395
                        // Only check if not a moderator or admin, since they are allowed to override this user setting
1396
                        $sql_allow_pm = (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : '';
1397
1398
                        $sql = 'SELECT u.user_type, ug.group_id, ug.user_id
1399
                                FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug
1400
                                WHERE ' . $db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . '
1401
                                        AND ug.user_pending = 0
1402
                                        AND u.user_id = ug.user_id
1403
                                        AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')' .
1404
                                        $sql_allow_pm;
1405
                        $result = $db->sql_query($sql);
1406
1407
                        while ($row = $db->sql_fetchrow($result))
1408
                        {
1409
                                // Additionally, do not include the sender if he is in the group he wants to send to. ;)
1410
                                if ($row['user_id'] === $user->data['user_id'])
1411
                                {
1412
                                        continue;
1413
                                }
1414
1415
                                $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc';
1416
                                $recipients[$row['user_id']] = $field;
1417
                        }
1418
                        $db->sql_freeresult($result);
1419
                }
1420
1421
                if (!sizeof($recipients))
1422
                {
1423
                        trigger_error('NO_RECIPIENT');
1424
                }
1425
        }
1426
1427
        // First of all make sure the subject are having the correct length.
1428
        $subject = truncate_string($subject);
1429
1430
        $db->sql_transaction('begin');
1431
1432
        $sql = '';
1433
1434
        switch ($mode)
1435
        {
1436
                case 'reply':
1437
                case 'quote':
1438
                        $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id'];
1439
1440
                        // Set message_replied switch for this user
1441
                        $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . '
1442
                                SET pm_replied = 1
1443
                                WHERE user_id = ' . $data['from_user_id'] . '
1444
                                        AND msg_id = ' . $data['reply_from_msg_id'];
1445
1446
                // no break
1447
1448
                case 'forward':
1449
                case 'post':
1450
                case 'quotepost':
1451
                        $sql_data = array(
1452
                                'root_level'                => $root_level,
1453
                                'author_id'                        => $data['from_user_id'],
1454
                                'icon_id'                        => $data['icon_id'],
1455
                                'author_ip'                        => $data['from_user_ip'],
1456
                                'message_time'                => $current_time,
1457
                                'enable_bbcode'                => $data['enable_bbcode'],
1458
                                'enable_smilies'        => $data['enable_smilies'],
1459
                                'enable_magic_url'        => $data['enable_urls'],
1460
                                'enable_sig'                => $data['enable_sig'],
1461
                                'message_subject'        => $subject,
1462
                                'message_text'                => $data['message'],
1463
                                'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1464
                                'bbcode_bitfield'        => $data['bbcode_bitfield'],
1465
                                'bbcode_uid'                => $data['bbcode_uid'],
1466
                                'to_address'                => implode(':', $to),
1467
                                'bcc_address'                => implode(':', $bcc),
1468
                                'message_reported'        => 0,
1469
                        );
1470
                break;
1471
1472
                case 'edit':
1473
                        $sql_data = array(
1474
                                'icon_id'                        => $data['icon_id'],
1475
                                'message_edit_time'        => $current_time,
1476
                                'enable_bbcode'                => $data['enable_bbcode'],
1477
                                'enable_smilies'        => $data['enable_smilies'],
1478
                                'enable_magic_url'        => $data['enable_urls'],
1479
                                'enable_sig'                => $data['enable_sig'],
1480
                                'message_subject'        => $subject,
1481
                                'message_text'                => $data['message'],
1482
                                'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0,
1483
                                'bbcode_bitfield'        => $data['bbcode_bitfield'],
1484
                                'bbcode_uid'                => $data['bbcode_uid']
1485
                        );
1486
                break;
1487
        }
1488
1489
        if (sizeof($sql_data))
1490
        {
1491
                $query = '';
1492
1493
                if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward')
1494
                {
1495
                        $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data));
1496
                        $data['msg_id'] = $db->sql_nextid();
1497
                }
1498
                else if ($mode == 'edit')
1499
                {
1500
                        $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
1501
                                SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . '
1502
                                WHERE msg_id = ' . $data['msg_id'];
1503
                        $db->sql_query($sql);
1504
                }
1505
        }
1506
1507
        if ($mode != 'edit')
1508
        {
1509
                if ($sql)
1510
                {
1511
                        $db->sql_query($sql);
1512
                }
1513
                unset($sql);
1514
1515
                $sql_ary = array();
1516
                foreach ($recipients as $user_id => $type)
1517
                {
1518
                        $sql_ary[] = array(
1519
                                'msg_id'                => (int) $data['msg_id'],
1520
                                'user_id'                => (int) $user_id,
1521
                                'author_id'                => (int) $data['from_user_id'],
1522
                                'folder_id'                => PRIVMSGS_NO_BOX,
1523
                                'pm_new'                => 1,
1524
                                'pm_unread'                => 1,
1525
                                'pm_forwarded'        => ($mode == 'forward') ? 1 : 0
1526
                        );
1527
                }
1528
1529
                $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary);
1530
1531
                $sql = 'UPDATE ' . USERS_TABLE . '
1532
                        SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . '
1533
                        WHERE ' . $db->sql_in_set('user_id', array_keys($recipients));
1534
                $db->sql_query($sql);
1535
1536
                // Put PM into outbox
1537
                if ($put_in_outbox)
1538
                {
1539
                        $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array(
1540
                                'msg_id'                => (int) $data['msg_id'],
1541
                                'user_id'                => (int) $data['from_user_id'],
1542
                                'author_id'                => (int) $data['from_user_id'],
1543
                                'folder_id'                => PRIVMSGS_OUTBOX,
1544
                                'pm_new'                => 0,
1545
                                'pm_unread'                => 0,
1546
                                'pm_forwarded'        => ($mode == 'forward') ? 1 : 0))
1547
                        );
1548
                }
1549
        }
1550
1551
        // Set user last post time
1552
        if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post')
1553
        {
1554
                $sql = 'UPDATE ' . USERS_TABLE . "
1555
                        SET user_lastpost_time = $current_time
1556
                        WHERE user_id = " . $data['from_user_id'];
1557
                $db->sql_query($sql);
1558
        }
1559
1560
        // Submit Attachments
1561
        if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward')))
1562
        {
1563
                $space_taken = $files_added = 0;
1564
                $orphan_rows = array();
1565
1566
                foreach ($data['attachment_data'] as $pos => $attach_row)
1567
                {
1568
                        $orphan_rows[(int) $attach_row['attach_id']] = array();
1569
                }
1570
1571
                if (sizeof($orphan_rows))
1572
                {
1573
                        $sql = 'SELECT attach_id, filesize, physical_filename
1574
                                FROM ' . ATTACHMENTS_TABLE . '
1575
                                WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . '
1576
                                        AND in_message = 1
1577
                                        AND is_orphan = 1
1578
                                        AND poster_id = ' . $user->data['user_id'];
1579
                        $result = $db->sql_query($sql);
1580
1581
                        $orphan_rows = array();
1582
                        while ($row = $db->sql_fetchrow($result))
1583
                        {
1584
                                $orphan_rows[$row['attach_id']] = $row;
1585
                        }
1586
                        $db->sql_freeresult($result);
1587
                }
1588
1589
                foreach ($data['attachment_data'] as $pos => $attach_row)
1590
                {
1591
                        if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']]))
1592
                        {
1593
                                continue;
1594
                        }
1595
1596
                        if (!$attach_row['is_orphan'])
1597
                        {
1598
                                // update entry in db if attachment already stored in db and filespace
1599
                                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
1600
                                        SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "'
1601
                                        WHERE attach_id = " . (int) $attach_row['attach_id'] . '
1602
                                                AND is_orphan = 0';
1603
                                $db->sql_query($sql);
1604
                        }
1605
                        else
1606
                        {
1607
                                // insert attachment into db
1608
                                if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . utf8_basename($orphan_rows[$attach_row['attach_id']]['physical_filename'])))
1609
                                {
1610
                                        continue;
1611
                                }
1612
1613
                                $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize'];
1614
                                $files_added++;
1615
1616
                                $attach_sql = array(
1617
                                        'post_msg_id'                => $data['msg_id'],
1618
                                        'topic_id'                        => 0,
1619
                                        'is_orphan'                        => 0,
1620
                                        'poster_id'                        => $data['from_user_id'],
1621
                                        'attach_comment'        => $attach_row['attach_comment'],
1622
                                );
1623
1624
                                $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . '
1625
                                        WHERE attach_id = ' . $attach_row['attach_id'] . '
1626
                                                AND is_orphan = 1
1627
                                                AND poster_id = ' . $user->data['user_id'];
1628
                                $db->sql_query($sql);
1629
                        }
1630
                }
1631
1632
                if ($space_taken && $files_added)
1633
                {
1634
                        set_config_count('upload_dir_size', $space_taken, true);
1635
                        set_config_count('num_files', $files_added, true);
1636
                }
1637
        }
1638
1639
        // Delete draft if post was loaded...
1640
        $draft_id = request_var('draft_loaded', 0);
1641
        if ($draft_id)
1642
        {
1643
                $sql = 'DELETE FROM ' . DRAFTS_TABLE . "
1644
                        WHERE draft_id = $draft_id
1645
                                AND user_id = " . $data['from_user_id'];
1646
                $db->sql_query($sql);
1647
        }
1648
1649
        $db->sql_transaction('commit');
1650
1651
        // Send Notifications
1652
        if ($mode != 'edit')
1653
        {
1654
                pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message'], $data['msg_id']);
1655
        }
1656
1657
        return $data['msg_id'];
1658
}
1659
1660
/**
1661
* PM Notification
1662
*/
1663
function pm_notification($mode, $author, $recipients, $subject, $message, $msg_id)
1664
{
1665
        global $db, $user, $config, $phpbb_root_path, $phpEx, $auth;
1666
1667
        $subject = censor_text($subject);
1668
1669
        unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
1670
1671
        if (!sizeof($recipients))
1672
        {
1673
                return;
1674
        }
1675
1676
        // Get banned User ID's
1677
        $sql = 'SELECT ban_userid
1678
                FROM ' . BANLIST_TABLE . '
1679
                WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
1680
                        AND ban_exclude = 0';
1681
        $result = $db->sql_query($sql);
1682
1683
        while ($row = $db->sql_fetchrow($result))
1684
        {
1685
                unset($recipients[$row['ban_userid']]);
1686
        }
1687
        $db->sql_freeresult($result);
1688
1689
        if (!sizeof($recipients))
1690
        {
1691
                return;
1692
        }
1693
1694
        $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
1695
                FROM ' . USERS_TABLE . '
1696
                WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
1697
        $result = $db->sql_query($sql);
1698
1699
        $msg_list_ary = array();
1700
        while ($row = $db->sql_fetchrow($result))
1701
        {
1702
                if ($row['user_notify_pm'] == 1 && trim($row['user_email']))
1703
                {
1704
                        $msg_list_ary[] = array(
1705
                                'method'        => $row['user_notify_type'],
1706
                                'email'                => $row['user_email'],
1707
                                'jabber'        => $row['user_jabber'],
1708
                                'name'                => $row['username'],
1709
                                'lang'                => $row['user_lang']
1710
                        );
1711
                }
1712
        }
1713
        $db->sql_freeresult($result);
1714
1715
        if (!sizeof($msg_list_ary))
1716
        {
1717
                return;
1718
        }
1719
1720
        include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
1721
        $messenger = new messenger();
1722
1723
        foreach ($msg_list_ary as $pos => $addr)
1724
        {
1725
                $messenger->template('privmsg_notify', $addr['lang']);
1726
1727
                $messenger->to($addr['email'], $addr['name']);
1728
                $messenger->im($addr['jabber'], $addr['name']);
1729
1730
                $messenger->assign_vars(array(
1731
                        'SUBJECT'                => htmlspecialchars_decode($subject),
1732
                        'AUTHOR_NAME'        => htmlspecialchars_decode($author),
1733
                        'USERNAME'                => htmlspecialchars_decode($addr['name']),
1734
1735
                        'U_INBOX'                        => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox",
1736
                        'U_VIEW_MESSAGE'        => generate_board_url() . "/ucp.$phpEx?i=pm&mode=view&p=$msg_id",
1737
                ));
1738
1739
                $messenger->send($addr['method']);
1740
        }
1741
        unset($msg_list_ary);
1742
1743
        $messenger->save_queue();
1744
1745
        unset($messenger);
1746
}
1747
1748
/**
1749
* Display Message History
1750
*/
1751
function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false)
1752
{
1753
        global $db, $user, $config, $template, $phpbb_root_path, $phpEx, $auth, $bbcode;
1754
1755
        // Select all receipts and the author from the pm we currently view, to only display their pm-history
1756
        $sql = 'SELECT author_id, user_id
1757
                FROM ' . PRIVMSGS_TO_TABLE . "
1758
                WHERE msg_id = $msg_id
1759
                        AND folder_id <> " . PRIVMSGS_HOLD_BOX;
1760
        $result = $db->sql_query($sql);
1761
1762
        $recipients = array();
1763
        while ($row = $db->sql_fetchrow($result))
1764
        {
1765
                $recipients[] = (int) $row['user_id'];
1766
                $recipients[] = (int) $row['author_id'];
1767
        }
1768
        $db->sql_freeresult($result);
1769
        $recipients = array_unique($recipients);
1770
1771
        // Get History Messages (could be newer)
1772
        $sql = 'SELECT t.*, p.*, u.*
1773
                FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u
1774
                WHERE t.msg_id = p.msg_id
1775
                        AND p.author_id = u.user_id
1776
                        AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ')
1777
                        AND ' . $db->sql_in_set('t.author_id', $recipients, false, true) . "
1778
                        AND t.user_id = $user_id";
1779
1780
        // We no longer need those.
1781
        unset($recipients);
1782
1783
        if (!$message_row['root_level'])
1784
        {
1785
                $sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))";
1786
        }
1787
        else
1788
        {
1789
                $sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')';
1790
        }
1791
        $sql .= ' ORDER BY p.message_time DESC';
1792
1793
        $result = $db->sql_query($sql);
1794
        $row = $db->sql_fetchrow($result);
1795
1796
        if (!$row)
1797
        {
1798
                $db->sql_freeresult($result);
1799
                return false;
1800
        }
1801
1802
        $title = $row['message_subject'];
1803
1804
        $rowset = array();
1805
        $bbcode_bitfield = '';
1806
        $folder_url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm') . '&amp;folder=';
1807
1808
        do
1809
        {
1810
                $folder_id = (int) $row['folder_id'];
1811
1812
                $row['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : $user->lang['UNKNOWN_FOLDER'];
1813
1814
                if (isset($rowset[$row['msg_id']]))
1815
                {
1816
                        $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'];
1817
                }
1818
                else
1819
                {
1820
                        $rowset[$row['msg_id']] = $row;
1821
                        $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']);
1822
                }
1823
        }
1824
        while ($row = $db->sql_fetchrow($result));
1825
        $db->sql_freeresult($result);
1826
1827
        if (sizeof($rowset) == 1 && !$in_post_mode)
1828
        {
1829
                return false;
1830
        }
1831
1832
        // Instantiate BBCode class
1833
        if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '')
1834
        {
1835
                if (!class_exists('bbcode'))
1836
                {
1837
                        include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
1838
                }
1839
                $bbcode = new bbcode(base64_encode($bbcode_bitfield));
1840
        }
1841
1842
        $title = censor_text($title);
1843
1844
        $url = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm');
1845
        $next_history_pm = $previous_history_pm = $prev_id = 0;
1846
1847
        // Re-order rowset to be able to get the next/prev message rows...
1848
        $rowset = array_values($rowset);
1849
1850
        for ($i = 0, $size = sizeof($rowset); $i < $size; $i++)
1851
        {
1852
                $row = &$rowset[$i];
1853
                $id = (int) $row['msg_id'];
1854
1855
                $author_id        = $row['author_id'];
1856
                $folder_id        = (int) $row['folder_id'];
1857
1858
                $subject        = $row['message_subject'];
1859
                $message        = $row['message_text'];
1860
1861
                $message = censor_text($message);
1862
1863
                $decoded_message = false;
1864
1865
                if ($in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS)
1866
                {
1867
                        $decoded_message = $message;
1868
                        decode_message($decoded_message, $row['bbcode_uid']);
1869
1870
                        $decoded_message = bbcode_nl2br($decoded_message);
1871
                }
1872
1873
                if ($row['bbcode_bitfield'])
1874
                {
1875
                        $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']);
1876
                }
1877
1878
                $message = bbcode_nl2br($message);
1879
                $message = smiley_text($message, !$row['enable_smilies']);
1880
1881
                $subject = censor_text($subject);
1882
1883
                if ($id == $msg_id)
1884
                {
1885
                        $next_history_pm = (isset($rowset[$i + 1])) ? (int) $rowset[$i + 1]['msg_id'] : 0;
1886
                        $previous_history_pm = $prev_id;
1887
                }
1888
1889
                $template->assign_block_vars('history_row', array(
1890
                        'MESSAGE_AUTHOR_QUOTE'                => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''),
1891
                        'MESSAGE_AUTHOR_FULL'                => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']),
1892
                        'MESSAGE_AUTHOR_COLOUR'                => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']),
1893
                        'MESSAGE_AUTHOR'                        => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']),
1894
                        'U_MESSAGE_AUTHOR'                        => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']),
1895
1896
                        'SUBJECT'                        => $subject,
1897
                        'SENT_DATE'                        => $user->format_date($row['message_time']),
1898
                        'MESSAGE'                        => $message,
1899
                        'FOLDER'                        => implode(', ', $row['folder']),
1900
                        'DECODED_MESSAGE'        => $decoded_message,
1901
1902
                        'S_CURRENT_MSG'                => ($row['msg_id'] == $msg_id),
1903
                        'S_AUTHOR_DELETED'        => ($author_id == ANONYMOUS) ? true : false,
1904
                        'S_IN_POST_MODE'        => $in_post_mode,
1905
1906
                        'MSG_ID'                        => $row['msg_id'],
1907
                        'U_VIEW_MESSAGE'        => "$url&amp;f=$folder_id&amp;p=" . $row['msg_id'],
1908
                        'U_QUOTE'                        => (!$in_post_mode && $auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&amp;mode=compose&amp;action=quote&amp;f=" . $folder_id . "&amp;p=" . $row['msg_id'] : '',
1909
                        'U_POST_REPLY_PM'        => ($author_id != $user->data['user_id'] && $author_id != ANONYMOUS && $auth->acl_get('u_sendpm')) ? "$url&amp;mode=compose&amp;action=reply&amp;f=$folder_id&amp;p=" . $row['msg_id'] : '')
1910
                );
1911
                unset($rowset[$i]);
1912
                $prev_id = $id;
1913
        }
1914
1915
        $template->assign_vars(array(
1916
                'QUOTE_IMG'                        => $user->img('icon_post_quote', $user->lang['REPLY_WITH_QUOTE']),
1917
                'HISTORY_TITLE'                => $title,
1918
1919
                'U_VIEW_NEXT_HISTORY'                => ($next_history_pm) ? "$url&amp;p=" . $next_history_pm : '',
1920
                'U_VIEW_PREVIOUS_HISTORY'        => ($previous_history_pm) ? "$url&amp;p=" . $previous_history_pm : '',
1921
        ));
1922
1923
        return true;
1924
}
1925
1926
/**
1927
* Set correct users max messages in PM folder.
1928
* If several group memberships define different amount of messages, the highest will be chosen.
1929
*/
1930
function set_user_message_limit()
1931
{
1932
        global $user, $db, $config;
1933
1934
        // Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config.
1935
        $sql = 'SELECT MAX(g.group_message_limit) as max_message_limit
1936
                FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug
1937
                WHERE ug.user_id = ' . $user->data['user_id'] . '
1938
                        AND ug.user_pending = 0
1939
                        AND ug.group_id = g.group_id';
1940
        $result = $db->sql_query($sql);
1941
        $message_limit = (int) $db->sql_fetchfield('max_message_limit');
1942
        $db->sql_freeresult($result);
1943
1944
        $user->data['message_limit'] = (!$message_limit) ? $config['pm_max_msgs'] : $message_limit;
1945
}
1946
1947
/**
1948
* Generates an array of coloured recipient names from a list of PMs - (groups & users)
1949
*
1950
* @param        array        $pm_by_id        An array of rows from PRIVMSGS_TABLE, keys are the msg_ids.
1951
*
1952
* @return        array                                2D Array: array(msg_id => array('username or group string', ...), ...)
1953
*                                                                Usernames are generated with {@link get_username_string get_username_string}
1954
*                                                                Groups are coloured and have a link to the membership page
1955
*/
1956
function get_recipient_strings($pm_by_id)
1957
{
1958
        global $db, $phpbb_root_path, $phpEx, $user;
1959
1960
        $address_list = $recipient_list = $address = array();
1961
1962
        $_types = array('u', 'g');
1963
1964
        foreach ($pm_by_id as $message_id => $row)
1965
        {
1966
                $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address']));
1967
1968
                foreach ($_types as $ug_type)
1969
                {
1970
                        if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type]))
1971
                        {
1972
                                foreach ($address[$message_id][$ug_type] as $ug_id => $in_to)
1973
                                {
1974
                                        $recipient_list[$ug_type][$ug_id] = array('name' => $user->lang['NA'], 'colour' => '');
1975
                                }
1976
                        }
1977
                }
1978
        }
1979
1980
        foreach ($_types as $ug_type)
1981
        {
1982
                if (!empty($recipient_list[$ug_type]))
1983
                {
1984
                        if ($ug_type == 'u')
1985
                        {
1986
                                $sql = 'SELECT user_id as id, username as name, user_colour as colour
1987
                                        FROM ' . USERS_TABLE . '
1988
                                        WHERE ';
1989
                        }
1990
                        else
1991
                        {
1992
                                $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type
1993
                                        FROM ' . GROUPS_TABLE . '
1994
                                        WHERE ';
1995
                        }
1996
                        $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type])));
1997
1998
                        $result = $db->sql_query($sql);
1999
2000
                        while ($row = $db->sql_fetchrow($result))
2001
                        {
2002
                                if ($ug_type == 'g')
2003
                                {
2004
                                        $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name'];
2005
                                }
2006
2007
                                $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']);
2008
                        }
2009
                        $db->sql_freeresult($result);
2010
                }
2011
        }
2012
2013
        foreach ($address as $message_id => $adr_ary)
2014
        {
2015
                foreach ($adr_ary as $type => $id_ary)
2016
                {
2017
                        foreach ($id_ary as $ug_id => $_id)
2018
                        {
2019
                                if ($type == 'u')
2020
                                {
2021
                                        $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']);
2022
                                }
2023
                                else
2024
                                {
2025
                                        $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : '';
2026
                                        $link = '<a href="' . append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp;g=' . $ug_id) . '"' . $user_colour . '>';
2027
                                        $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : '');
2028
                                }
2029
                        }
2030
                }
2031
        }
2032
2033
        return $address_list;
2034
}