[ Index ] |
PHP Cross Reference of phpBB 3.0 Beta 3 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package phpBB3 5 * @version $Id: functions_privmsgs.php,v 1.57 2006/11/03 21:04:09 acydburn Exp $ 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 appropiate 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 informations 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 return $folder; 212 } 213 214 /** 215 * Delete Messages From Sentbox 216 * we are doing this here because this saves us a bunch of checks and queries 217 */ 218 function clean_sentbox($num_sentbox_messages) 219 { 220 global $db, $user, $config; 221 222 // Check Message Limit 223 if ($user->data['message_limit'] && $num_sentbox_messages > $user->data['message_limit']) 224 { 225 // Delete old messages 226 $sql = 'SELECT t.msg_id 227 FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p 228 WHERE t.msg_id = p.msg_id 229 AND t.user_id = ' . $user->data['user_id'] . ' 230 AND t.folder_id = ' . PRIVMSGS_SENTBOX . ' 231 ORDER BY p.message_time ASC'; 232 $result = $db->sql_query_limit($sql, ($num_sentbox_messages - $user->data['message_limit'])); 233 234 $delete_ids = array(); 235 while ($row = $db->sql_fetchrow($result)) 236 { 237 $delete_ids[] = $row['msg_id']; 238 } 239 $db->sql_freeresult($result); 240 delete_pm($user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX); 241 } 242 } 243 244 /** 245 * Check Rule against Message Informations 246 */ 247 function check_rule(&$rules, &$rule_row, &$message_row, $user_id) 248 { 249 global $user, $config; 250 251 if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']])) 252 { 253 return false; 254 } 255 256 $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']]; 257 258 // Replace Check Literals 259 $evaluate = $check_ary['function']; 260 $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate); 261 262 // Replace Rule Literals 263 $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate); 264 265 // Evil Statement 266 $result = false; 267 eval('$result = (' . $evaluate . ') ? true : false;'); 268 269 if (!$result) 270 { 271 return false; 272 } 273 274 switch ($rule_row['rule_action']) 275 { 276 case ACTION_PLACE_INTO_FOLDER: 277 return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']); 278 break; 279 280 case ACTION_MARK_AS_READ: 281 case ACTION_MARK_AS_IMPORTANT: 282 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); 283 break; 284 285 case ACTION_DELETE_MESSAGE: 286 global $db, $auth; 287 288 // Check for admins/mods - users are not allowed to remove those messages... 289 // We do the check here to make sure the data we use is consistent 290 $sql = 'SELECT user_id, user_type, user_permissions 291 FROM ' . USERS_TABLE . ' 292 WHERE user_id = ' . (int) $message_row['author_id']; 293 $result = $db->sql_query($sql); 294 $userdata = $db->sql_fetchrow($result); 295 $db->sql_freeresult($result); 296 297 $auth2 = new auth(); 298 $auth2->acl($userdata); 299 300 if (!$auth2->acl_get('a_') && !$auth->acl_get('m_') && !$auth2->acl_getf_global('m_')) 301 { 302 return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); 303 } 304 305 return false; 306 break; 307 308 default: 309 return false; 310 } 311 312 return false; 313 } 314 315 /** 316 * Place new messages into appropiate folder 317 */ 318 function place_pm_into_folder(&$global_privmsgs_rules, $release = false) 319 { 320 global $db, $user, $config; 321 322 if (!$user->data['user_new_privmsg']) 323 { 324 return 0; 325 } 326 327 $user_new_privmsg = (int) $user->data['user_new_privmsg']; 328 $user_message_rules = (int) $user->data['user_message_rules']; 329 $user_id = (int) $user->data['user_id']; 330 331 $action_ary = $move_into_folder = array(); 332 333 if ($release) 334 { 335 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 336 SET folder_id = ' . PRIVMSGS_NO_BOX . ' 337 WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . " 338 AND user_id = $user_id"; 339 $db->sql_query($sql); 340 } 341 342 // Get those messages not yet placed into any box 343 $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id 344 FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u 345 WHERE t.user_id = $user_id 346 AND p.author_id = u.user_id 347 AND t.folder_id = " . PRIVMSGS_NO_BOX . ' 348 AND t.msg_id = p.msg_id'; 349 350 // Just place into the appropiate arrays if no rules need to be checked 351 if (!$user_message_rules) 352 { 353 $result = $db->sql_query($retrieve_sql); 354 355 while ($row = $db->sql_fetchrow($result)) 356 { 357 $action_ary[$row['msg_id']][] = array('action' => false); 358 $move_into_folder[PRIVMSGS_INBOX][] = $row['msg_id']; 359 } 360 $db->sql_freeresult($result); 361 } 362 else 363 { 364 $user_rules = $zebra = $check_rows = array(); 365 $user_ids = $memberships = array(); 366 367 // First of all, grab all rules and retrieve friends/foes 368 $sql = 'SELECT * 369 FROM ' . PRIVMSGS_RULES_TABLE . " 370 WHERE user_id = $user_id"; 371 $result = $db->sql_query($sql); 372 $user_rules = $db->sql_fetchrowset($result); 373 $db->sql_freeresult($result); 374 375 if (sizeof($user_rules)) 376 { 377 $sql = 'SELECT zebra_id, friend, foe 378 FROM ' . ZEBRA_TABLE . " 379 WHERE user_id = $user_id"; 380 $result = $db->sql_query($sql); 381 382 while ($row = $db->sql_fetchrow($result)) 383 { 384 $zebra[$row['zebra_id']] = $row; 385 } 386 $db->sql_freeresult($result); 387 } 388 389 // Now build a bare-bone check_row array 390 $result = $db->sql_query($retrieve_sql); 391 392 while ($row = $db->sql_fetchrow($result)) 393 { 394 $check_rows[] = array_merge($row, array( 395 'to' => explode(':', $row['to_address']), 396 'bcc' => explode(':', $row['bcc_address']), 397 'friend' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0, 398 'foe' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0, 399 'user_in_group' => array($user->data['group_id']), 400 'author_in_group' => array()) 401 ); 402 403 $user_ids[] = $row['user_id']; 404 } 405 $db->sql_freeresult($result); 406 407 // Retrieve user memberships 408 if (sizeof($user_ids)) 409 { 410 $sql = 'SELECT * 411 FROM ' . USER_GROUP_TABLE . ' 412 WHERE ' . $db->sql_in_set('user_id', $user_ids) . ' 413 AND user_pending = 0'; 414 $result = $db->sql_query($sql); 415 416 while ($row = $db->sql_fetchrow($result)) 417 { 418 $memberships[$row['user_id']][] = $row['group_id']; 419 } 420 $db->sql_freeresult($result); 421 } 422 423 // Now place into the appropiate folder 424 foreach ($check_rows as $row) 425 { 426 // Add membership if set 427 if (isset($memberships[$row['author_id']])) 428 { 429 $row['author_in_group'] = $memberships[$row['user_id']]; 430 } 431 432 // Check Rule - this should be very quick since we have all informations we need 433 $is_match = false; 434 foreach ($user_rules as $rule_row) 435 { 436 if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false) 437 { 438 $is_match = true; 439 $action_ary[$row['msg_id']][] = $action; 440 } 441 } 442 443 if (!$is_match) 444 { 445 $action_ary[$row['msg_id']][] = array('action' => false); 446 $move_into_folder[PRIVMSGS_INBOX][] = $row['msg_id']; 447 } 448 } 449 450 unset($user_rules, $zebra, $check_rows, $user_ids, $memberships); 451 } 452 453 // We place actions into arrays, to save queries. 454 $num_new = $num_unread = 0; 455 $sql = $unread_ids = $delete_ids = $important_ids = array(); 456 457 foreach ($action_ary as $msg_id => $msg_ary) 458 { 459 // It is allowed to execute actions more than once, except placing messages into folder 460 $folder_action = false; 461 462 foreach ($msg_ary as $pos => $rule_ary) 463 { 464 if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER) 465 { 466 continue; 467 } 468 469 switch ($rule_ary['action']) 470 { 471 case ACTION_PLACE_INTO_FOLDER: 472 // Folder actions have precedence, so we will remove any other ones 473 $folder_action = true; 474 $_folder_id = (int) $rule_ary['folder_id']; 475 $move_into_folder = array(); 476 $move_into_folder[$_folder_id][] = $msg_id; 477 $num_new++; 478 break; 479 480 case ACTION_MARK_AS_READ: 481 if ($rule_ary['pm_unread']) 482 { 483 $unread_ids[] = $msg_id; 484 } 485 486 if (!$folder_action) 487 { 488 $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; 489 } 490 break; 491 492 case ACTION_DELETE_MESSAGE: 493 $delete_ids[] = $msg_id; 494 break; 495 496 case ACTION_MARK_AS_IMPORTANT: 497 if (!$rule_ary['pm_marked']) 498 { 499 $important_ids[] = $msg_id; 500 } 501 502 if (!$folder_action) 503 { 504 $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; 505 } 506 break; 507 } 508 } 509 } 510 511 // $num_new += sizeof(array_unique($delete_ids)); 512 // $num_unread += sizeof(array_unique($delete_ids)); 513 $num_unread += sizeof(array_unique($unread_ids)); 514 515 // Do not change the order of processing 516 // The number of queries needed to be executed here highly depends on the defined rules and are 517 // only gone through if new messages arrive. 518 $num_not_moved = 0; 519 520 // Delete messages 521 if (sizeof($delete_ids)) 522 { 523 delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX); 524 } 525 526 // Set messages to Unread 527 if (sizeof($unread_ids)) 528 { 529 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 530 SET pm_unread = 0 531 WHERE ' . $db->sql_in_set('msg_id', $unread_ids) . " 532 AND user_id = $user_id 533 AND folder_id = " . PRIVMSGS_NO_BOX; 534 $db->sql_query($sql); 535 } 536 537 // mark messages as important 538 if (sizeof($important_ids)) 539 { 540 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 541 SET pm_marked = !pm_marked 542 WHERE folder_id = ' . PRIVMSGS_NO_BOX . " 543 AND user_id = $user_id 544 AND " . $db->sql_in_set('msg_id', $important_ids); 545 $db->sql_query($sql); 546 } 547 548 // Move into folder 549 $folder = array(); 550 551 if (sizeof($move_into_folder)) 552 { 553 // Determine Full Folder Action - we need the move to folder id later eventually 554 $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; 555 556 $sql_folder = array_keys($move_into_folder); 557 if ($full_folder_action >= 0) 558 { 559 $sql_folder[] = $full_folder_action; 560 } 561 562 $sql = 'SELECT folder_id, pm_count 563 FROM ' . PRIVMSGS_FOLDER_TABLE . ' 564 WHERE ' . $db->sql_in_set('folder_id', $sql_folder) . " 565 AND user_id = $user_id"; 566 $result = $db->sql_query($sql); 567 568 while ($row = $db->sql_fetchrow($result)) 569 { 570 $folder[(int) $row['folder_id']] = (int) $row['pm_count']; 571 } 572 $db->sql_freeresult($result); 573 574 unset($sql_folder); 575 576 if (in_array(PRIVMSGS_INBOX, array_keys($move_into_folder))) 577 { 578 $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages 579 FROM ' . PRIVMSGS_TO_TABLE . " 580 WHERE user_id = $user_id 581 AND folder_id = " . PRIVMSGS_INBOX . " 582 GROUP BY folder_id"; 583 $result = $db->sql_query_limit($sql, 1); 584 $folder[PRIVMSGS_INBOX] = (int) $db->sql_fetchfield('num_messages'); 585 $db->sql_freeresult($result); 586 } 587 } 588 589 // Here we have ideally only one folder to move into 590 foreach ($move_into_folder as $folder_id => $msg_ary) 591 { 592 $dest_folder = $folder_id; 593 $full_folder_action = FULL_FOLDER_NONE; 594 595 // Check Message Limit - we calculate with the complete array, most of the time it is one message 596 // But we are making sure that the other way around works too (more messages in queue than allowed to be stored) 597 if ($user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > $user->data['message_limit']) 598 { 599 $full_folder_action = ($user->data['user_full_folder'] == FULL_FOLDER_NONE) ? ($config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : $user->data['user_full_folder']; 600 601 // If destination folder itself is full... 602 if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > $user->data['message_limit']) 603 { 604 $full_folder_action = $config['full_folder_action'] - (FULL_FOLDER_NONE*(-1)); 605 } 606 607 // If Full Folder Action is to move to another folder, we simply adjust the destination folder 608 if ($full_folder_action >= 0) 609 { 610 $dest_folder = $full_folder_action; 611 } 612 else if ($full_folder_action == FULL_FOLDER_DELETE) 613 { 614 // Delete some messages. NOTE: Ordered by msg_id here instead of message_time! 615 $sql = 'SELECT msg_id 616 FROM ' . PRIVMSGS_TO_TABLE . " 617 WHERE user_id = $user_id 618 AND folder_id = $dest_folder 619 ORDER BY msg_id ASC"; 620 $result = $db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - $user->data['message_limit'])); 621 622 $delete_ids = array(); 623 while ($row = $db->sql_fetchrow($result)) 624 { 625 $delete_ids[] = $row['msg_id']; 626 } 627 $db->sql_freeresult($result); 628 629 delete_pm($user_id, $delete_ids, $dest_folder); 630 } 631 } 632 633 // 634 if ($full_folder_action == FULL_FOLDER_HOLD) 635 { 636 $num_not_moved += sizeof($msg_ary); 637 638 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 639 SET folder_id = ' . PRIVMSGS_HOLD_BOX . ' 640 WHERE folder_id = ' . PRIVMSGS_NO_BOX . " 641 AND user_id = $user_id 642 AND " . $db->sql_in_set('msg_id', $msg_ary); 643 $db->sql_query($sql); 644 } 645 else 646 { 647 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 648 SET folder_id = $dest_folder, pm_new = 0 649 WHERE folder_id = " . PRIVMSGS_NO_BOX . " 650 AND user_id = $user_id 651 AND pm_new = 1 652 AND " . $db->sql_in_set('msg_id', $msg_ary); 653 $db->sql_query($sql); 654 655 if ($dest_folder != PRIVMSGS_INBOX) 656 { 657 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' 658 SET pm_count = pm_count + ' . (int) $db->sql_affectedrows() . " 659 WHERE folder_id = $dest_folder 660 AND user_id = $user_id"; 661 $db->sql_query($sql); 662 } 663 else 664 { 665 $num_new += $db->sql_affectedrows(); 666 } 667 } 668 } 669 670 if (sizeof($action_ary)) 671 { 672 // Move from OUTBOX to SENTBOX 673 // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted) 674 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 675 SET folder_id = ' . PRIVMSGS_SENTBOX . ' 676 WHERE folder_id = ' . PRIVMSGS_OUTBOX . ' 677 AND ' . $db->sql_in_set('msg_id', array_keys($action_ary)); 678 $db->sql_query($sql); 679 } 680 681 // Update unread and new status field 682 if ($num_unread || $num_new) 683 { 684 $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : ''; 685 if ($num_new) 686 { 687 $set_sql .= ($set_sql != '') ? ', ' : ''; 688 $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new; 689 } 690 691 $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id"); 692 693 $user->data['user_new_privmsg'] -= $num_new; 694 $user->data['user_unread_privmsg'] -= $num_unread; 695 } 696 697 return $num_not_moved; 698 } 699 700 /** 701 * Move PM from one to another folder 702 */ 703 function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id) 704 { 705 global $db, $user; 706 global $phpbb_root_path, $phpEx; 707 708 $num_moved = 0; 709 710 if (!is_array($move_msg_ids)) 711 { 712 $move_msg_ids = array($move_msg_ids); 713 } 714 715 if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && 716 !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && $cur_folder_id != $dest_folder) 717 { 718 // We have to check the destination folder ;) 719 if ($dest_folder != PRIVMSGS_INBOX) 720 { 721 $sql = 'SELECT folder_id, folder_name, pm_count 722 FROM ' . PRIVMSGS_FOLDER_TABLE . " 723 WHERE folder_id = $dest_folder 724 AND user_id = $user_id"; 725 $result = $db->sql_query($sql); 726 $row = $db->sql_fetchrow($result); 727 $db->sql_freeresult($result); 728 729 if (!$row) 730 { 731 trigger_error('NOT_AUTHORIZED'); 732 } 733 734 if ($row['pm_count'] + sizeof($move_msg_ids) > $message_limit) 735 { 736 $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />'; 737 $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']); 738 trigger_error($message); 739 } 740 } 741 else 742 { 743 $sql = 'SELECT COUNT(msg_id) as num_messages 744 FROM ' . PRIVMSGS_TO_TABLE . ' 745 WHERE folder_id = ' . PRIVMSGS_INBOX . " 746 AND user_id = $user_id"; 747 $result = $db->sql_query($sql); 748 $num_messages = (int) $db->sql_fetchfield('num_messages'); 749 $db->sql_freeresult($result); 750 751 if ($num_messages + sizeof($move_msg_ids) > $message_limit) 752 { 753 $message = sprintf($user->lang['NOT_ENOUGH_SPACE_FOLDER'], $user->lang['PM_INBOX']) . '<br /><br />'; 754 $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']); 755 trigger_error($message); 756 } 757 } 758 759 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 760 SET folder_id = $dest_folder 761 WHERE folder_id = $cur_folder_id 762 AND user_id = $user_id 763 AND " . $db->sql_in_set('msg_id', $move_msg_ids); 764 $db->sql_query($sql); 765 $num_moved = $db->sql_affectedrows(); 766 767 // Update pm counts 768 if ($num_moved) 769 { 770 if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX))) 771 { 772 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 773 SET pm_count = pm_count - $num_moved 774 WHERE folder_id = $cur_folder_id 775 AND user_id = $user_id"; 776 $db->sql_query($sql); 777 } 778 779 if ($dest_folder != PRIVMSGS_INBOX) 780 { 781 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 782 SET pm_count = pm_count + $num_moved 783 WHERE folder_id = $dest_folder 784 AND user_id = $user_id"; 785 $db->sql_query($sql); 786 } 787 } 788 } 789 790 return $num_moved; 791 } 792 793 /** 794 * Update unread message status 795 */ 796 function update_unread_status($unread, $msg_id, $user_id, $folder_id) 797 { 798 if (!$unread) 799 { 800 return; 801 } 802 803 global $db, $user; 804 805 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 806 SET pm_unread = 0 807 WHERE msg_id = $msg_id 808 AND user_id = $user_id 809 AND folder_id = $folder_id"; 810 $db->sql_query($sql); 811 812 $sql = 'UPDATE ' . USERS_TABLE . " 813 SET user_unread_privmsg = user_unread_privmsg - 1 814 WHERE user_id = $user_id"; 815 $db->sql_query($sql); 816 817 if ($user->data['user_id'] == $user_id) 818 { 819 $user->data['user_unread_privmsg']--; 820 } 821 } 822 823 /** 824 * Handle all actions possible with marked messages 825 */ 826 function handle_mark_actions($user_id, $mark_action) 827 { 828 global $db, $user, $_POST, $phpbb_root_path, $phpEx; 829 830 $msg_ids = (isset($_POST['marked_msg_id'])) ? array_map('intval', $_POST['marked_msg_id']) : array(); 831 $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); 832 $confirm = (isset($_POST['confirm'])) ? true : false; 833 834 if (!sizeof($msg_ids)) 835 { 836 return false; 837 } 838 839 switch ($mark_action) 840 { 841 case 'mark_important': 842 843 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " 844 SET pm_marked = !pm_marked 845 WHERE folder_id = $cur_folder_id 846 AND user_id = $user_id 847 AND " . $db->sql_in_set('msg_id', $msg_ids); 848 $db->sql_query($sql); 849 850 break; 851 852 case 'delete_marked': 853 854 if (confirm_box(true)) 855 { 856 delete_pm($user_id, $msg_ids, $cur_folder_id); 857 858 $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED'; 859 $redirect = append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&folder=' . $cur_folder_id); 860 861 meta_refresh(3, $redirect); 862 trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>')); 863 } 864 else 865 { 866 $s_hidden_fields = array( 867 'cur_folder_id' => $cur_folder_id, 868 'mark_option' => 'delete_marked', 869 'submit_mark' => true, 870 'marked_msg_id' => $msg_ids 871 ); 872 873 confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields)); 874 } 875 876 break; 877 878 default: 879 return false; 880 } 881 882 return true; 883 } 884 885 /** 886 * Delete PM(s) 887 */ 888 function delete_pm($user_id, $msg_ids, $folder_id) 889 { 890 global $db, $user; 891 892 $user_id = (int) $user_id; 893 $folder_id = (int) $folder_id; 894 895 if (!$user_id) 896 { 897 return false; 898 } 899 900 if (!is_array($msg_ids)) 901 { 902 if (!$msg_ids) 903 { 904 return false; 905 } 906 $msg_ids = array($msg_ids); 907 } 908 909 if (!sizeof($msg_ids)) 910 { 911 return false; 912 } 913 914 // Get PM Informations for later deleting 915 $sql = 'SELECT msg_id, pm_unread, pm_new 916 FROM ' . PRIVMSGS_TO_TABLE . ' 917 WHERE ' . $db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . " 918 AND folder_id = $folder_id 919 AND user_id = $user_id"; 920 $result = $db->sql_query($sql); 921 922 $delete_rows = array(); 923 $num_unread = $num_new = $num_deleted = 0; 924 while ($row = $db->sql_fetchrow($result)) 925 { 926 $num_unread += (int) $row['pm_unread']; 927 $num_new += (int) $row['pm_new']; 928 929 $delete_rows[$row['msg_id']] = 1; 930 } 931 $db->sql_freeresult($result); 932 unset($msg_ids); 933 934 if (!sizeof($delete_rows)) 935 { 936 return false; 937 } 938 939 // if no one has read the message yet (meaning it is in users outbox) 940 // then mark the message as deleted... 941 if ($folder_id == PRIVMSGS_OUTBOX) 942 { 943 // Remove PM from Outbox 944 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " 945 WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . ' 946 AND ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 947 $db->sql_query($sql); 948 949 // Update PM Information for safety 950 $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = '' 951 WHERE " . $db->sql_in_set('msg_id', array_keys($delete_rows)); 952 $db->sql_query($sql); 953 954 // Set delete flag for those intended to receive the PM 955 // We do not remove the message actually, to retain some basic informations (sent time for example) 956 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 957 SET pm_deleted = 1 958 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 959 $db->sql_query($sql); 960 961 $num_deleted = $db->sql_affectedrows(); 962 } 963 else 964 { 965 // Delete Private Message Informations 966 $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " 967 WHERE user_id = $user_id 968 AND folder_id = $folder_id 969 AND " . $db->sql_in_set('msg_id', array_keys($delete_rows)); 970 $db->sql_query($sql); 971 $num_deleted = $db->sql_affectedrows(); 972 } 973 974 // if folder id is user defined folder then decrease pm_count 975 if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX))) 976 { 977 $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " 978 SET pm_count = pm_count - $num_deleted 979 WHERE folder_id = $folder_id"; 980 $db->sql_query($sql); 981 } 982 983 // Update unread and new status field 984 if ($num_unread || $num_new) 985 { 986 $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : ''; 987 988 if ($num_new) 989 { 990 $set_sql .= ($set_sql != '') ? ', ' : ''; 991 $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new; 992 } 993 994 $db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id"); 995 996 $user->data['user_new_privmsg'] -= $num_new; 997 $user->data['user_unread_privmsg'] -= $num_unread; 998 } 999 1000 // Now we have to check which messages we can delete completely 1001 $sql = 'SELECT msg_id 1002 FROM ' . PRIVMSGS_TO_TABLE . ' 1003 WHERE ' . $db->sql_in_set('msg_id', array_keys($delete_rows)); 1004 $result = $db->sql_query($sql); 1005 1006 while ($row = $db->sql_fetchrow($result)) 1007 { 1008 unset($delete_rows[$row['msg_id']]); 1009 } 1010 $db->sql_freeresult($result); 1011 1012 $delete_ids = array_keys($delete_rows); 1013 1014 if (sizeof($delete_ids)) 1015 { 1016 $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' 1017 WHERE ' . $db->sql_in_set('msg_id', $delete_ids); 1018 $db->sql_query($sql); 1019 } 1020 1021 return true; 1022 } 1023 1024 /** 1025 * Rebuild message header 1026 */ 1027 function rebuild_header($check_ary) 1028 { 1029 global $db; 1030 1031 $address = array(); 1032 1033 foreach ($check_ary as $check_type => $address_field) 1034 { 1035 // Split Addresses into users and groups 1036 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); 1037 1038 $u = $g = array(); 1039 foreach ($match[1] as $id => $type) 1040 { 1041 ${$type}[] = (int) $match[2][$id]; 1042 } 1043 1044 $_types = array('u', 'g'); 1045 foreach ($_types as $type) 1046 { 1047 if (sizeof($$type)) 1048 { 1049 foreach ($$type as $id) 1050 { 1051 $address[$type][$id] = $check_type; 1052 } 1053 } 1054 } 1055 } 1056 1057 return $address; 1058 } 1059 1060 /** 1061 * Print out/assign recipient informations 1062 */ 1063 function write_pm_addresses($check_ary, $author_id, $plaintext = false) 1064 { 1065 global $db, $user, $template, $phpbb_root_path, $phpEx; 1066 1067 $addresses = array(); 1068 1069 foreach ($check_ary as $check_type => $address_field) 1070 { 1071 if (!is_array($address_field)) 1072 { 1073 // Split Addresses into users and groups 1074 preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); 1075 1076 $u = $g = array(); 1077 foreach ($match[1] as $id => $type) 1078 { 1079 ${$type}[] = (int) $match[2][$id]; 1080 } 1081 } 1082 else 1083 { 1084 $u = $address_field['u']; 1085 $g = $address_field['g']; 1086 } 1087 1088 $address = array(); 1089 if (sizeof($u)) 1090 { 1091 $sql = 'SELECT user_id, username, user_colour 1092 FROM ' . USERS_TABLE . ' 1093 WHERE ' . $db->sql_in_set('user_id', $u) . ' 1094 AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; 1095 $result = $db->sql_query($sql); 1096 1097 while ($row = $db->sql_fetchrow($result)) 1098 { 1099 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1100 { 1101 if ($plaintext) 1102 { 1103 $address[] = $row['username']; 1104 } 1105 else 1106 { 1107 $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']); 1108 } 1109 } 1110 } 1111 $db->sql_freeresult($result); 1112 } 1113 1114 if (sizeof($g)) 1115 { 1116 if ($plaintext) 1117 { 1118 $sql = 'SELECT group_name, group_type 1119 FROM ' . GROUPS_TABLE . ' 1120 WHERE ' . $db->sql_in_set('group_id', $g); 1121 $result = $db->sql_query($sql); 1122 1123 while ($row = $db->sql_fetchrow($result)) 1124 { 1125 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1126 { 1127 $address[] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; 1128 } 1129 } 1130 $db->sql_freeresult($result); 1131 } 1132 else 1133 { 1134 $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id 1135 FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug 1136 WHERE ' . $db->sql_in_set('g.group_id', $g) . ' 1137 AND g.group_id = ug.group_id 1138 AND ug.user_pending = 0'; 1139 $result = $db->sql_query($sql); 1140 1141 while ($row = $db->sql_fetchrow($result)) 1142 { 1143 if (!isset($address['group'][$row['group_id']])) 1144 { 1145 if ($check_type == 'to' || $author_id == $user->data['user_id'] || $row['user_id'] == $user->data['user_id']) 1146 { 1147 $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; 1148 $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']); 1149 } 1150 } 1151 1152 if (isset($address['user'][$row['user_id']])) 1153 { 1154 $address['user'][$row['user_id']]['in_group'] = $row['group_id']; 1155 } 1156 } 1157 $db->sql_freeresult($result); 1158 } 1159 } 1160 1161 if (sizeof($address) && !$plaintext) 1162 { 1163 $template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true); 1164 1165 foreach ($address as $type => $adr_ary) 1166 { 1167 foreach ($adr_ary as $id => $row) 1168 { 1169 $template->assign_block_vars($check_type . '_recipient', array( 1170 'NAME' => $row['name'], 1171 'IS_GROUP' => ($type == 'group'), 1172 'IS_USER' => ($type == 'user'), 1173 'COLOUR' => ($row['colour']) ? $row['colour'] : '', 1174 'UG_ID' => $id, 1175 'U_VIEW' => ($type == 'user') ? (($id != ANONYMOUS) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile&u=' . $id) : '') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&g=' . $id), 1176 'TYPE' => $type) 1177 ); 1178 } 1179 } 1180 } 1181 1182 $addresses[$check_type] = $address; 1183 } 1184 1185 return $addresses; 1186 } 1187 1188 /** 1189 * Get folder status 1190 */ 1191 function get_folder_status($folder_id, $folder) 1192 { 1193 global $db, $user, $config; 1194 1195 if (isset($folder[$folder_id])) 1196 { 1197 $folder = $folder[$folder_id]; 1198 } 1199 else 1200 { 1201 return false; 1202 } 1203 1204 $return = array( 1205 'folder_name' => $folder['folder_name'], 1206 'cur' => $folder['num_messages'], 1207 'remaining' => $user->data['message_limit'] - $folder['num_messages'], 1208 'max' => $user->data['message_limit'], 1209 'percent' => ($user->data['message_limit'] > 0) ? round(($folder['num_messages'] / $user->data['message_limit']) * 100) : 100, 1210 ); 1211 1212 $return['message'] = sprintf($user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']); 1213 1214 return $return; 1215 } 1216 1217 // 1218 // COMPOSE MESSAGES 1219 // 1220 1221 /** 1222 * Submit PM 1223 */ 1224 function submit_pm($mode, $subject, &$data, $update_message, $put_in_outbox = true) 1225 { 1226 global $db, $auth, $config, $phpEx, $template, $user; 1227 1228 // We do not handle erasing pms here 1229 if ($mode == 'delete') 1230 { 1231 return false; 1232 } 1233 1234 $current_time = time(); 1235 1236 // Collect some basic informations about which tables and which rows to update/insert 1237 $sql_data = array(); 1238 $root_level = 0; 1239 1240 // Recipient Informations 1241 $recipients = $to = $bcc = array(); 1242 1243 if ($mode != 'edit') 1244 { 1245 // Build Recipient List 1246 // u|g => array($user_id => 'to'|'bcc') 1247 $_types = array('u', 'g'); 1248 foreach ($_types as $ug_type) 1249 { 1250 if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type])) 1251 { 1252 foreach ($data['address_list'][$ug_type] as $id => $field) 1253 { 1254 $id = (int) $id; 1255 1256 // Do not rely on the address list being "valid" 1257 if (!$id || ($ug_type == 'u' && $id == ANONYMOUS)) 1258 { 1259 continue; 1260 } 1261 1262 $field = ($field == 'to') ? 'to' : 'bcc'; 1263 if ($ug_type == 'u') 1264 { 1265 $recipients[$id] = $field; 1266 } 1267 ${$field}[] = $ug_type . '_' . $id; 1268 } 1269 } 1270 } 1271 1272 if (isset($data['address_list']['g']) && sizeof($data['address_list']['g'])) 1273 { 1274 $sql = 'SELECT group_id, user_id 1275 FROM ' . USER_GROUP_TABLE . ' 1276 WHERE ' . $db->sql_in_set('group_id', array_keys($data['address_list']['g'])) . ' 1277 AND user_pending = 0'; 1278 $result = $db->sql_query($sql); 1279 1280 while ($row = $db->sql_fetchrow($result)) 1281 { 1282 $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; 1283 $recipients[$row['user_id']] = $field; 1284 } 1285 $db->sql_freeresult($result); 1286 } 1287 1288 if (!sizeof($recipients)) 1289 { 1290 trigger_error('NO_RECIPIENT'); 1291 } 1292 } 1293 1294 $sql = ''; 1295 1296 switch ($mode) 1297 { 1298 case 'reply': 1299 case 'quote': 1300 $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id']; 1301 1302 // Set message_replied switch for this user 1303 $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' 1304 SET pm_replied = 1 1305 WHERE user_id = ' . $data['from_user_id'] . ' 1306 AND msg_id = ' . $data['reply_from_msg_id']; 1307 1308 // no break 1309 1310 case 'forward': 1311 case 'post': 1312 case 'quotepost': 1313 $sql_data = array( 1314 'root_level' => $root_level, 1315 'author_id' => $data['from_user_id'], 1316 'icon_id' => $data['icon_id'], 1317 'author_ip' => $data['from_user_ip'], 1318 'message_time' => $current_time, 1319 'enable_bbcode' => $data['enable_bbcode'], 1320 'enable_smilies' => $data['enable_smilies'], 1321 'enable_magic_url' => $data['enable_urls'], 1322 'enable_sig' => $data['enable_sig'], 1323 'message_subject' => $subject, 1324 'message_text' => $data['message'], 1325 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, 1326 'bbcode_bitfield' => $data['bbcode_bitfield'], 1327 'bbcode_uid' => $data['bbcode_uid'], 1328 'to_address' => implode(':', $to), 1329 'bcc_address' => implode(':', $bcc) 1330 ); 1331 break; 1332 1333 case 'edit': 1334 $sql_data = array( 1335 'icon_id' => $data['icon_id'], 1336 'message_edit_time' => $current_time, 1337 'enable_bbcode' => $data['enable_bbcode'], 1338 'enable_smilies' => $data['enable_smilies'], 1339 'enable_magic_url' => $data['enable_urls'], 1340 'enable_sig' => $data['enable_sig'], 1341 'message_subject' => $subject, 1342 'message_text' => $data['message'], 1343 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, 1344 'bbcode_bitfield' => $data['bbcode_bitfield'], 1345 'bbcode_uid' => $data['bbcode_uid'] 1346 ); 1347 break; 1348 } 1349 1350 if (sizeof($sql_data)) 1351 { 1352 $query = ''; 1353 1354 if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') 1355 { 1356 $db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_data)); 1357 $data['msg_id'] = $db->sql_nextid(); 1358 } 1359 else if ($mode == 'edit') 1360 { 1361 $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 1362 SET message_edit_count = message_edit_count + 1, ' . $db->sql_build_array('UPDATE', $sql_data) . ' 1363 WHERE msg_id = ' . $data['msg_id']; 1364 $db->sql_query($sql); 1365 } 1366 } 1367 1368 if ($mode != 'edit') 1369 { 1370 $db->sql_transaction('begin'); 1371 1372 if ($sql) 1373 { 1374 $db->sql_query($sql); 1375 } 1376 unset($sql); 1377 1378 $sql_ary = array(); 1379 foreach ($recipients as $user_id => $type) 1380 { 1381 $sql_ary[] = array( 1382 'msg_id' => (int) $data['msg_id'], 1383 'user_id' => (int) $user_id, 1384 'author_id' => (int) $data['from_user_id'], 1385 'folder_id' => PRIVMSGS_NO_BOX, 1386 'pm_new' => 1, 1387 'pm_unread' => 1, 1388 'pm_forwarded' => ($mode == 'forward') ? 1 : 0 1389 ); 1390 } 1391 1392 $db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary); 1393 1394 $sql = 'UPDATE ' . USERS_TABLE . ' 1395 SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . ' 1396 WHERE ' . $db->sql_in_set('user_id', array_keys($recipients)); 1397 $db->sql_query($sql); 1398 1399 // Put PM into outbox 1400 if ($put_in_outbox) 1401 { 1402 $db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . $db->sql_build_array('INSERT', array( 1403 'msg_id' => (int) $data['msg_id'], 1404 'user_id' => (int) $data['from_user_id'], 1405 'author_id' => (int) $data['from_user_id'], 1406 'folder_id' => PRIVMSGS_OUTBOX, 1407 'pm_new' => 0, 1408 'pm_unread' => 0, 1409 'pm_forwarded' => ($mode == 'forward') ? 1 : 0)) 1410 ); 1411 } 1412 1413 $db->sql_transaction('commit'); 1414 } 1415 1416 // Set user last post time 1417 if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post') 1418 { 1419 $sql = 'UPDATE ' . USERS_TABLE . " 1420 SET user_lastpost_time = $current_time 1421 WHERE user_id = " . $data['from_user_id']; 1422 $db->sql_query($sql); 1423 } 1424 1425 $db->sql_transaction('begin'); 1426 1427 // Submit Attachments 1428 if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) 1429 { 1430 $space_taken = $files_added = 0; 1431 $orphan_rows = array(); 1432 1433 foreach ($data['attachment_data'] as $pos => $attach_row) 1434 { 1435 $orphan_rows[(int) $attach_row['attach_id']] = array(); 1436 } 1437 1438 if (sizeof($orphan_rows)) 1439 { 1440 $sql = 'SELECT attach_id, filesize, physical_filename 1441 FROM ' . ATTACHMENTS_TABLE . ' 1442 WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' 1443 AND in_message = 1 1444 AND is_orphan = 1 1445 AND poster_id = ' . $user->data['user_id']; 1446 $result = $db->sql_query($sql); 1447 1448 $orphan_rows = array(); 1449 while ($row = $db->sql_fetchrow($result)) 1450 { 1451 $orphan_rows[$row['attach_id']] = $row; 1452 } 1453 $db->sql_freeresult($result); 1454 } 1455 1456 foreach ($data['attachment_data'] as $pos => $attach_row) 1457 { 1458 if ($attach_row['is_orphan'] && !in_array($attach_row['attach_id'], array_keys($orphan_rows))) 1459 { 1460 continue; 1461 } 1462 1463 if (!$attach_row['is_orphan']) 1464 { 1465 // update entry in db if attachment already stored in db and filespace 1466 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " 1467 SET attach_comment = '" . $db->sql_escape($attach_row['attach_comment']) . "' 1468 WHERE attach_id = " . (int) $attach_row['attach_id'] . ' 1469 AND is_orphan = 0'; 1470 $db->sql_query($sql); 1471 } 1472 else 1473 { 1474 // insert attachment into db 1475 if (!@file_exists($phpbb_root_path . $config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) 1476 { 1477 continue; 1478 } 1479 1480 $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; 1481 $files_added++; 1482 1483 $attach_sql = array( 1484 'post_msg_id' => $data['msg_id'], 1485 'topic_id' => 0, 1486 'is_orphan' => 0, 1487 'poster_id' => $data['from_user_id'], 1488 'attach_comment' => $attach_row['attach_comment'], 1489 ); 1490 1491 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $attach_sql) . ' 1492 WHERE attach_id = ' . $attach_row['attach_id'] . ' 1493 AND is_orphan = 1 1494 AND poster_id = ' . $user->data['user_id']; 1495 $db->sql_query($sql); 1496 } 1497 } 1498 1499 if ($space_taken && $files_added) 1500 { 1501 set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true); 1502 set_config('num_files', $config['num_files'] + $files_added, true); 1503 } 1504 } 1505 1506 $db->sql_transaction('commit'); 1507 1508 // Delete draft if post was loaded... 1509 $draft_id = request_var('draft_loaded', 0); 1510 if ($draft_id) 1511 { 1512 $sql = 'DELETE FROM ' . DRAFTS_TABLE . " 1513 WHERE draft_id = $draft_id 1514 AND user_id = " . $data['from_user_id']; 1515 $db->sql_query($sql); 1516 } 1517 1518 // Send Notifications 1519 if ($mode != 'edit') 1520 { 1521 pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']); 1522 } 1523 1524 return $data['msg_id']; 1525 } 1526 1527 /** 1528 * PM Notification 1529 */ 1530 function pm_notification($mode, $author, $recipients, $subject, $message) 1531 { 1532 global $db, $user, $config, $phpbb_root_path, $phpEx, $auth; 1533 1534 $subject = censor_text($subject); 1535 1536 unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]); 1537 1538 if (!sizeof($recipients)) 1539 { 1540 return; 1541 } 1542 1543 // Get banned User ID's 1544 $sql = 'SELECT ban_userid 1545 FROM ' . BANLIST_TABLE . ' 1546 WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . ' 1547 AND ban_exclude = 0'; 1548 $result = $db->sql_query($sql); 1549 1550 while ($row = $db->sql_fetchrow($result)) 1551 { 1552 unset($recipients[$row['ban_userid']]); 1553 } 1554 $db->sql_freeresult($result); 1555 1556 if (!sizeof($recipients)) 1557 { 1558 return; 1559 } 1560 1561 $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber 1562 FROM ' . USERS_TABLE . ' 1563 WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients))); 1564 $result = $db->sql_query($sql); 1565 1566 $msg_list_ary = array(); 1567 while ($row = $db->sql_fetchrow($result)) 1568 { 1569 if ($row['user_notify_pm'] == 1 && trim($row['user_email'])) 1570 { 1571 $msg_list_ary[] = array( 1572 'method' => $row['user_notify_type'], 1573 'email' => $row['user_email'], 1574 'jabber' => $row['user_jabber'], 1575 'name' => $row['username'], 1576 'lang' => $row['user_lang'] 1577 ); 1578 } 1579 } 1580 $db->sql_freeresult($result); 1581 1582 if (!sizeof($msg_list_ary)) 1583 { 1584 return; 1585 } 1586 1587 include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); 1588 $messenger = new messenger(); 1589 1590 foreach ($msg_list_ary as $pos => $addr) 1591 { 1592 $messenger->template('privmsg_notify', $addr['lang']); 1593 1594 $messenger->replyto($config['board_email']); 1595 $messenger->to($addr['email'], $addr['name']); 1596 $messenger->im($addr['jabber'], $addr['name']); 1597 1598 $messenger->assign_vars(array( 1599 'SUBJECT' => htmlspecialchars_decode($subject), 1600 'AUTHOR_NAME' => htmlspecialchars_decode($author), 1601 'USERNAME' => htmlspecialchars_decode($addr['name']), 1602 1603 'U_INBOX' => generate_board_url() . "/ucp.$phpEx?i=pm&folder=inbox") 1604 ); 1605 1606 $messenger->send($addr['method']); 1607 $messenger->reset(); 1608 } 1609 unset($msg_list_ary); 1610 1611 $messenger->save_queue(); 1612 1613 unset($messenger); 1614 } 1615 1616 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Nov 22 00:35:05 2006 | Cross-referenced by PHPXref 0.6 |