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