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