[ Index ] |
PHP Cross Reference of phpBB 3.0 Beta 3 |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * 4 * @package acp 5 * @version $Id: functions_admin.php,v 1.186 2006/11/03 23:09:15 davidmj Exp $ 6 * @copyright (c) 2005 phpBB Group 7 * @license http://opensource.org/licenses/gpl-license.php GNU Public License 8 * 9 */ 10 11 /** 12 * Recalculate Binary Tree 13 function recalc_btree($sql_id, $sql_table, $module_class = '') 14 { 15 global $db; 16 17 if (!$sql_id || !$sql_table) 18 { 19 return; 20 } 21 22 $sql_where = ($module_class) ? " WHERE module_class = '" . $db->sql_escape($module_class) . "'" : ''; 23 24 // Reset to minimum possible left and right id 25 $sql = "SELECT MIN(left_id) as min_left_id, MIN(right_id) as min_right_id 26 FROM $sql_table 27 $sql_where"; 28 $result = $db->sql_query($sql); 29 $row = $db->sql_fetchrow($result); 30 $db->sql_freeresult($result); 31 32 $substract = (int) (min($row['min_left_id'], $row['min_right_id']) - 1); 33 34 if ($substract > 0) 35 { 36 $sql = "UPDATE $sql_table 37 SET left_id = left_id - $substract, right_id = right_id - $substract 38 $sql_where"; 39 $db->sql_query($sql); 40 } 41 42 $sql = "SELECT $sql_id, parent_id, left_id, right_id 43 FROM $sql_table 44 $sql_where 45 ORDER BY left_id ASC, parent_id ASC, $sql_id ASC"; 46 $f_result = $db->sql_query($sql); 47 48 while ($item_data = $db->sql_fetchrow($f_result)) 49 { 50 if ($item_data['parent_id']) 51 { 52 $sql = "SELECT left_id, right_id 53 FROM $sql_table 54 $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " 55 $sql_id = {$item_data['parent_id']}"; 56 $result = $db->sql_query($sql); 57 58 if (!$row = $db->sql_fetchrow($result)) 59 { 60 $sql = "UPDATE $sql_table SET parent_id = 0 WHERE $sql_id = " . $item_data[$sql_id]; 61 $db->sql_query($sql); 62 } 63 $db->sql_freeresult($result); 64 65 $sql = "UPDATE $sql_table 66 SET left_id = left_id + 2, right_id = right_id + 2 67 $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " 68 left_id > {$row['right_id']}"; 69 $db->sql_query($sql); 70 71 $sql = "UPDATE $sql_table 72 SET right_id = right_id + 2 73 $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " 74 {$row['left_id']} BETWEEN left_id AND right_id"; 75 $db->sql_query($sql); 76 77 $item_data['left_id'] = $row['right_id']; 78 $item_data['right_id'] = $row['right_id'] + 1; 79 } 80 else 81 { 82 $sql = "SELECT MAX(right_id) AS right_id 83 FROM $sql_table 84 $sql_where"; 85 $result = $db->sql_query($sql); 86 $row = $db->sql_fetchrow($result); 87 $db->sql_freeresult($result); 88 89 $item_data['left_id'] = $row['right_id'] + 1; 90 $item_data['right_id'] = $row['right_id'] + 2; 91 } 92 93 $sql = "UPDATE $sql_table 94 SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']} 95 WHERE $sql_id = " . $item_data[$sql_id]; 96 $db->sql_query($sql); 97 } 98 $db->sql_freeresult($f_result); 99 } 100 */ 101 102 /** 103 * Simple version of jumpbox, just lists authed forums 104 */ 105 function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false) 106 { 107 global $db, $user, $auth; 108 109 $acl = ($ignore_acl) ? '' : (($only_acl_post) ? 'f_post' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel')); 110 111 // This query is identical to the jumpbox one 112 $sql = 'SELECT forum_id, parent_id, forum_name, forum_type, forum_status, left_id, right_id 113 FROM ' . FORUMS_TABLE . ' 114 ORDER BY left_id ASC'; 115 $result = $db->sql_query($sql); 116 117 $right = $iteration = 0; 118 $padding_store = array('0' => ''); 119 $padding = ''; 120 $forum_list = ($return_array) ? array() : ''; 121 122 // Sometimes it could happen that forums will be displayed here not be displayed within the index page 123 // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions. 124 // If this happens, the padding could be "broken" 125 126 while ($row = $db->sql_fetchrow($result)) 127 { 128 if ($row['left_id'] < $right) 129 { 130 $padding .= ' '; 131 $padding_store[$row['parent_id']] = $padding; 132 } 133 else if ($row['left_id'] > $right + 1) 134 { 135 $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : ''; 136 } 137 138 $right = $row['right_id']; 139 140 if ($acl && !$auth->acl_gets($acl, $row['forum_id'])) 141 { 142 continue; 143 } 144 145 if ((is_array($ignore_id) && in_array($row['forum_id'], $ignore_id)) || $row['forum_id'] == $ignore_id) 146 { 147 continue; 148 } 149 150 if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) 151 { 152 // Non-postable forum with no subforums, don't display 153 continue; 154 } 155 156 if ($row['forum_type'] != FORUM_POST && $ignore_nonpost) 157 { 158 continue; 159 } 160 161 if ($return_array) 162 { 163 // Include some more informations... 164 $selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? true : false) : (($row['forum_id'] == $select_id) ? true : false); 165 $forum_list[$row['forum_id']] = array_merge(array('padding' => $padding, 'selected' => $selected), $row); 166 } 167 else 168 { 169 $selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? ' selected="selected"' : '') : (($row['forum_id'] == $select_id) ? ' selected="selected"' : ''); 170 $forum_list .= '<option value="' . $row['forum_id'] . '"' . $selected . '>' . $padding . $row['forum_name'] . '</option>'; 171 } 172 173 $iteration++; 174 } 175 $db->sql_freeresult($result); 176 unset($padding_store); 177 178 return $forum_list; 179 } 180 181 /** 182 * Generate size select options 183 */ 184 function size_select_options($size_compare) 185 { 186 global $user; 187 188 $size_types_text = array($user->lang['BYTES'], $user->lang['KB'], $user->lang['MB']); 189 $size_types = array('b', 'kb', 'mb'); 190 191 $s_size_options = ''; 192 193 for ($i = 0, $size = sizeof($size_types_text); $i < $size; $i++) 194 { 195 $selected = ($size_compare == $size_types[$i]) ? ' selected="selected"' : ''; 196 $s_size_options .= '<option value="' . $size_types[$i] . '"' . $selected . '>' . $size_types_text[$i] . '</option>'; 197 } 198 199 return $s_size_options; 200 } 201 202 /** 203 * Generate list of groups 204 */ 205 function group_select_options($group_id, $exclude_ids = false) 206 { 207 global $db, $user, $config; 208 209 $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; 210 $sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; 211 212 $sql = 'SELECT group_id, group_name, group_type 213 FROM ' . GROUPS_TABLE . " 214 $exclude_sql 215 $sql_and 216 ORDER BY group_type DESC, group_name ASC"; 217 $result = $db->sql_query($sql); 218 219 $s_group_options = ''; 220 while ($row = $db->sql_fetchrow($result)) 221 { 222 $selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : ''; 223 $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; 224 } 225 $db->sql_freeresult($result); 226 227 return $s_group_options; 228 } 229 230 /** 231 * Obtain authed forums list 232 */ 233 function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only = false, $no_cache = false) 234 { 235 global $db, $auth; 236 static $forum_rows; 237 238 if (!isset($forum_rows)) 239 { 240 // This query is identical to the jumpbox one 241 $expire_time = ($no_cache) ? 0 : 120; 242 243 $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id 244 FROM ' . FORUMS_TABLE . ' 245 ORDER BY left_id ASC'; 246 $result = $db->sql_query($sql, $expire_time); 247 248 $forum_rows = array(); 249 while ($row = $db->sql_fetchrow($result)) 250 { 251 $forum_rows[] = $row; 252 } 253 $db->sql_freeresult($result); 254 } 255 256 $rowset = array(); 257 foreach ($forum_rows as $row) 258 { 259 if ($postable_only && $row['forum_type'] != FORUM_POST) 260 { 261 continue; 262 } 263 264 if ($acl_list == '' || ($acl_list != '' && $auth->acl_gets($acl_list, $row['forum_id']))) 265 { 266 $rowset[] = ($id_only) ? $row['forum_id'] : $row; 267 } 268 } 269 270 return $rowset; 271 } 272 273 /** 274 * Get forum branch 275 */ 276 function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $include_forum = true) 277 { 278 global $db; 279 280 switch ($type) 281 { 282 case 'parents': 283 $condition = 'f1.left_id BETWEEN f2.left_id AND f2.right_id'; 284 break; 285 286 case 'children': 287 $condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id'; 288 break; 289 290 default: 291 $condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id OR f1.left_id BETWEEN f2.left_id AND f2.right_id'; 292 break; 293 } 294 295 $rows = array(); 296 297 $sql = 'SELECT f2.* 298 FROM ' . FORUMS_TABLE . ' f1 299 LEFT JOIN ' . FORUMS_TABLE . " f2 ON ($condition) 300 WHERE f1.forum_id = $forum_id 301 ORDER BY f2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); 302 $result = $db->sql_query($sql); 303 304 while ($row = $db->sql_fetchrow($result)) 305 { 306 if (!$include_forum && $row['forum_id'] == $forum_id) 307 { 308 continue; 309 } 310 311 $rows[] = $row; 312 } 313 $db->sql_freeresult($result); 314 315 return $rows; 316 } 317 318 /** 319 * Get physical file listing 320 */ 321 function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png') 322 { 323 $matches = array(); 324 325 // Remove initial / if present 326 $rootdir = (substr($rootdir, 0, 1) == '/') ? substr($rootdir, 1) : $rootdir; 327 // Add closing / if not present 328 $rootdir = ($rootdir && substr($rootdir, -1) != '/') ? $rootdir . '/' : $rootdir; 329 330 // Remove initial / if present 331 $dir = (substr($dir, 0, 1) == '/') ? substr($dir, 1) : $dir; 332 // Add closing / if not present 333 $dir = ($dir && substr($dir, -1) != '/') ? $dir . '/' : $dir; 334 335 if (!is_dir($rootdir . $dir)) 336 { 337 return false; 338 } 339 340 $dh = opendir($rootdir . $dir); 341 while (($fname = readdir($dh)) !== false) 342 { 343 if (is_file("$rootdir$dir$fname")) 344 { 345 if (filesize("$rootdir$dir$fname") && preg_match('#\.' . $type . '$#i', $fname)) 346 { 347 $matches[$dir][] = $fname; 348 } 349 } 350 else if ($fname[0] != '.' && is_dir("$rootdir$dir$fname")) 351 { 352 $matches += filelist($rootdir, "$dir$fname", $type); 353 } 354 } 355 closedir($dh); 356 357 return $matches; 358 } 359 360 /** 361 * Move topic(s) 362 */ 363 function move_topics($topic_ids, $forum_id, $auto_sync = true) 364 { 365 global $db; 366 367 if (empty($topic_ids)) 368 { 369 return; 370 } 371 372 $forum_ids = array($forum_id); 373 374 if (!is_array($topic_ids)) 375 { 376 $topic_ids = array($topic_ids); 377 } 378 379 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 380 WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids) . ' 381 AND forum_id = ' . $forum_id; 382 $db->sql_query($sql); 383 384 if ($auto_sync) 385 { 386 $sql = 'SELECT DISTINCT forum_id 387 FROM ' . TOPICS_TABLE . ' 388 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 389 $result = $db->sql_query($sql); 390 391 while ($row = $db->sql_fetchrow($result)) 392 { 393 $forum_ids[] = $row['forum_id']; 394 } 395 $db->sql_freeresult($result); 396 } 397 398 $table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); 399 foreach ($table_ary as $table) 400 { 401 $sql = "UPDATE $table 402 SET forum_id = $forum_id 403 WHERE " . $db->sql_in_set('topic_id', $topic_ids); 404 $db->sql_query($sql); 405 } 406 unset($table_ary); 407 408 if ($auto_sync) 409 { 410 sync('forum', 'forum_id', $forum_ids, true); 411 unset($forum_ids); 412 } 413 } 414 415 /** 416 * Move post(s) 417 */ 418 function move_posts($post_ids, $topic_id, $auto_sync = true) 419 { 420 global $db; 421 422 if (!is_array($post_ids)) 423 { 424 $post_ids = array($post_ids); 425 } 426 427 $forum_ids = array(); 428 $topic_ids = array($topic_id); 429 430 $sql = 'SELECT DISTINCT topic_id, forum_id 431 FROM ' . POSTS_TABLE . ' 432 WHERE ' . $db->sql_in_set('post_id', $post_ids); 433 $result = $db->sql_query($sql); 434 435 while ($row = $db->sql_fetchrow($result)) 436 { 437 $forum_ids[] = $row['forum_id']; 438 $topic_ids[] = $row['topic_id']; 439 } 440 $db->sql_freeresult($result); 441 442 $sql = 'SELECT forum_id 443 FROM ' . TOPICS_TABLE . ' 444 WHERE topic_id = ' . $topic_id; 445 $result = $db->sql_query($sql); 446 $forum_row = $db->sql_fetchrow($result); 447 $db->sql_freeresult($result); 448 449 if (!$forum_row) 450 { 451 trigger_error('NO_TOPIC'); 452 } 453 454 $sql = 'UPDATE ' . POSTS_TABLE . ' 455 SET forum_id = ' . $forum_row['forum_id'] . ", topic_id = $topic_id 456 WHERE " . $db->sql_in_set('post_id', $post_ids); 457 $db->sql_query($sql); 458 459 $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " 460 SET topic_id = $topic_id, in_message = 0 461 WHERE " . $db->sql_in_set('post_msg_id', $post_ids); 462 $db->sql_query($sql); 463 464 if ($auto_sync) 465 { 466 $forum_ids[] = $forum_row['forum_id']; 467 468 sync('topic_reported', 'topic_id', $topic_ids); 469 sync('topic_attachment', 'topic_id', $topic_ids); 470 sync('topic', 'topic_id', $topic_ids, true); 471 sync('forum', 'forum_id', $forum_ids, true); 472 } 473 474 // Update posted informations 475 update_posted_info($topic_ids); 476 } 477 478 /** 479 * Remove topic(s) 480 */ 481 function delete_topics($where_type, $where_ids, $auto_sync = true) 482 { 483 global $db, $config; 484 485 $forum_ids = $topic_ids = array(); 486 487 if (is_array($where_ids)) 488 { 489 $where_ids = array_unique($where_ids); 490 } 491 else 492 { 493 $where_ids = array($where_ids); 494 } 495 496 if (!sizeof($where_ids)) 497 { 498 return array('topics' => 0, 'posts' => 0); 499 } 500 501 $return = array( 502 'posts' => delete_posts($where_type, $where_ids, false, true) 503 ); 504 505 $sql = 'SELECT topic_id, forum_id 506 FROM ' . TOPICS_TABLE . ' 507 WHERE ' . $db->sql_in_set($where_type, $where_ids); 508 $result = $db->sql_query($sql); 509 510 while ($row = $db->sql_fetchrow($result)) 511 { 512 $forum_ids[] = $row['forum_id']; 513 $topic_ids[] = $row['topic_id']; 514 } 515 $db->sql_freeresult($result); 516 517 $return['topics'] = sizeof($topic_ids); 518 519 if (!sizeof($topic_ids)) 520 { 521 return $return; 522 } 523 524 $db->sql_transaction('begin'); 525 526 $table_ary = array(TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); 527 528 foreach ($table_ary as $table) 529 { 530 $sql = "DELETE FROM $table 531 WHERE " . $db->sql_in_set('topic_id', $topic_ids); 532 $db->sql_query($sql); 533 } 534 unset($table_ary); 535 536 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 537 WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids); 538 $db->sql_query($sql); 539 540 $db->sql_transaction('commit'); 541 542 if ($auto_sync) 543 { 544 sync('forum', 'forum_id', $forum_ids, true); 545 sync('topic_reported', $where_type, $where_ids); 546 } 547 548 set_config('num_topics', $config['num_topics'] - sizeof($return['topics']), true); 549 550 return $return; 551 } 552 553 /** 554 * Remove post(s) 555 */ 556 function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true) 557 { 558 global $db, $config, $phpbb_root_path, $phpEx; 559 560 if (is_array($where_ids)) 561 { 562 $where_ids = array_unique($where_ids); 563 } 564 else 565 { 566 $where_ids = array($where_ids); 567 } 568 569 if (!sizeof($where_ids)) 570 { 571 return false; 572 } 573 574 $post_ids = $topic_ids = $forum_ids = $post_counts = array(); 575 576 $sql = 'SELECT post_id, poster_id, post_postcount, topic_id, forum_id 577 FROM ' . POSTS_TABLE . ' 578 WHERE ' . $db->sql_in_set($where_type, array_map('intval', $where_ids)); 579 $result = $db->sql_query($sql); 580 581 while ($row = $db->sql_fetchrow($result)) 582 { 583 $post_ids[] = $row['post_id']; 584 $poster_ids[] = $row['poster_id']; 585 $topic_ids[] = $row['topic_id']; 586 $forum_ids[] = $row['forum_id']; 587 588 if ($row['post_postcount']) 589 { 590 $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; 591 } 592 } 593 $db->sql_freeresult($result); 594 595 if (!sizeof($post_ids)) 596 { 597 return false; 598 } 599 600 $db->sql_transaction('begin'); 601 602 $table_ary = array(POSTS_TABLE, REPORTS_TABLE); 603 604 foreach ($table_ary as $table) 605 { 606 $sql = "DELETE FROM $table 607 WHERE " . $db->sql_in_set('post_id', $post_ids); 608 $db->sql_query($sql); 609 } 610 unset($table_ary); 611 612 // Adjust users post counts 613 if (sizeof($post_counts)) 614 { 615 foreach ($post_counts as $poster_id => $substract) 616 { 617 $sql = 'UPDATE ' . USERS_TABLE . ' 618 SET user_posts = user_posts - ' . $substract . ' 619 WHERE user_id = ' . $poster_id; 620 $db->sql_query($sql); 621 } 622 } 623 624 // Remove the message from the search index 625 $search_type = basename($config['search_type']); 626 627 if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) 628 { 629 trigger_error('NO_SUCH_SEARCH_MODULE'); 630 } 631 632 include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx"); 633 634 $error = false; 635 $search = new $search_type($error); 636 637 if ($error) 638 { 639 trigger_error($error); 640 } 641 642 $search->index_remove($post_ids, $poster_ids, $forum_ids); 643 644 delete_attachments('post', $post_ids, false); 645 646 $db->sql_transaction('commit'); 647 648 // Resync topics_posted table 649 if ($posted_sync) 650 { 651 update_posted_info($topic_ids); 652 } 653 654 if ($auto_sync) 655 { 656 sync('topic_reported', 'topic_id', $topic_ids); 657 sync('topic', 'topic_id', $topic_ids, true); 658 sync('forum', 'forum_id', $forum_ids, true); 659 } 660 661 set_config('num_posts', $config['num_posts'] - sizeof($post_ids), true); 662 663 return sizeof($post_ids); 664 } 665 666 /** 667 * Delete Attachments 668 * 669 * @param string $mode can be: post|topic|attach|user 670 * @param mixed $ids can be: post_ids, topic_ids, attach_ids, user_ids 671 * @param bool $resync set this to false if you are deleting posts or topics 672 */ 673 function delete_attachments($mode, $ids, $resync = true) 674 { 675 global $db, $config; 676 677 if (is_array($ids)) 678 { 679 $ids = array_unique($ids); 680 $ids = array_map('intval', $ids); 681 } 682 else 683 { 684 $ids = array((int) $ids); 685 } 686 687 if (!sizeof($ids)) 688 { 689 return false; 690 } 691 692 $sql_id = ($mode == 'user') ? 'poster_id' : (($mode == 'post') ? 'post_msg_id' : (($mode == 'topic') ? 'topic_id' : 'attach_id')); 693 694 $post_ids = $topic_ids = $physical = array(); 695 696 // Collect post and topics ids for later use 697 if ($mode == 'attach' || $mode == 'user' || ($mode == 'topic' && $resync)) 698 { 699 $sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize 700 FROM ' . ATTACHMENTS_TABLE . ' 701 WHERE ' . $db->sql_in_set($sql_id, $ids); 702 $result = $db->sql_query($sql); 703 704 while ($row = $db->sql_fetchrow($result)) 705 { 706 $post_ids[] = $row['post_id']; 707 $topic_ids[] = $row['topic_id']; 708 $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']); 709 } 710 $db->sql_freeresult($result); 711 } 712 713 if ($mode == 'post') 714 { 715 $sql = 'SELECT topic_id, physical_filename, thumbnail, filesize 716 FROM ' . ATTACHMENTS_TABLE . ' 717 WHERE ' . $db->sql_in_set('post_msg_id', $ids) . ' 718 AND in_message = 0'; 719 $result = $db->sql_query($sql); 720 721 while ($row = $db->sql_fetchrow($result)) 722 { 723 $topic_ids[] = $row['topic_id']; 724 $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']); 725 } 726 $db->sql_freeresult($result); 727 } 728 729 // Delete attachments 730 $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' 731 WHERE ' . $db->sql_in_set($sql_id, $ids); 732 $db->sql_query($sql); 733 $num_deleted = $db->sql_affectedrows(); 734 735 if (!$num_deleted) 736 { 737 return 0; 738 } 739 740 // Delete attachments from filesystem 741 $space_removed = $files_removed = 0; 742 foreach ($physical as $file_ary) 743 { 744 if (phpbb_unlink($file_ary['filename'], 'file')) 745 { 746 $space_removed += $file_ary['filesize']; 747 $files_removed++; 748 } 749 750 if ($file_ary['thumbnail']) 751 { 752 phpbb_unlink($file_ary['filename'], 'thumbnail'); 753 } 754 } 755 set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true); 756 set_config('num_files', $config['num_files'] - $files_removed, true); 757 758 if ($mode == 'topic' && !$resync) 759 { 760 return $num_deleted; 761 } 762 763 if ($mode == 'post') 764 { 765 $post_ids = $ids; 766 } 767 unset($ids); 768 769 $post_ids = array_unique($post_ids); 770 $topic_ids = array_unique($topic_ids); 771 772 // Update post indicators 773 if (sizeof($post_ids)) 774 { 775 if ($mode == 'post' || $mode == 'topic') 776 { 777 $sql = 'UPDATE ' . POSTS_TABLE . ' 778 SET post_attachment = 0 779 WHERE ' . $db->sql_in_set('post_id', $post_ids); 780 $db->sql_query($sql); 781 } 782 783 if ($mode == 'user' || $mode == 'attach') 784 { 785 $remaining = array(); 786 787 $sql = 'SELECT post_msg_id 788 FROM ' . ATTACHMENTS_TABLE . ' 789 WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' 790 AND in_message = 0'; 791 $result = $db->sql_query($sql); 792 793 while ($row = $db->sql_fetchrow($result)) 794 { 795 $remaining[] = $row['post_msg_id']; 796 } 797 $db->sql_freeresult($result); 798 799 $unset_ids = array_diff($post_ids, $remaining); 800 801 if (sizeof($unset_ids)) 802 { 803 $sql = 'UPDATE ' . POSTS_TABLE . ' 804 SET post_attachment = 0 805 WHERE ' . $db->sql_in_set('post_id', $unset_ids); 806 $db->sql_query($sql); 807 } 808 809 $remaining = array(); 810 811 $sql = 'SELECT post_msg_id 812 FROM ' . ATTACHMENTS_TABLE . ' 813 WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' 814 AND in_message = 1'; 815 $result = $db->sql_query($sql); 816 817 while ($row = $db->sql_fetchrow($result)) 818 { 819 $remaining[] = $row['post_msg_id']; 820 } 821 $db->sql_freeresult($result); 822 823 $unset_ids = array_diff($post_ids, $remaining); 824 825 if (sizeof($unset_ids)) 826 { 827 $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' 828 SET message_attachment = 0 829 WHERE ' . $db->sql_in_set('msg_id', $unset_ids); 830 $db->sql_query($sql); 831 } 832 } 833 } 834 835 if (sizeof($topic_ids)) 836 { 837 // Update topic indicator 838 if ($mode == 'topic') 839 { 840 $sql = 'UPDATE ' . TOPICS_TABLE . ' 841 SET topic_attachment = 0 842 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 843 $db->sql_query($sql); 844 } 845 846 if ($mode == 'post' || $mode == 'user' || $mode == 'attach') 847 { 848 $remaining = array(); 849 850 $sql = 'SELECT topic_id 851 FROM ' . ATTACHMENTS_TABLE . ' 852 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 853 $result = $db->sql_query($sql); 854 855 while ($row = $db->sql_fetchrow($result)) 856 { 857 $remaining[] = $row['topic_id']; 858 } 859 $db->sql_freeresult($result); 860 861 $unset_ids = array_diff($topic_ids, $remaining); 862 863 if (sizeof($unset_ids)) 864 { 865 $sql = 'UPDATE ' . TOPICS_TABLE . ' 866 SET topic_attachment = 0 867 WHERE ' . $db->sql_in_set('topic_id', $unset_ids); 868 $db->sql_query($sql); 869 } 870 } 871 } 872 873 return $num_deleted; 874 } 875 876 /** 877 * Remove topic shadows 878 */ 879 function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) 880 { 881 $where = (is_array($forum_id)) ? 'AND ' . $db->sql_in_set('t.forum_id', array_map('intval', $forum_id)) : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : ''); 882 883 switch ($db->sql_layer) 884 { 885 case 'mysql4': 886 case 'mysqli': 887 $sql = 'DELETE t.* 888 FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2 889 WHERE t.topic_moved_id = t2.topic_id 890 AND t.topic_time < ' . (time() - $max_age) 891 . $where; 892 $db->sql_query($sql); 893 break; 894 895 default: 896 $sql = 'SELECT t.topic_id 897 FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2 898 WHERE t.topic_moved_id = t2.topic_id 899 AND t.topic_time < ' . (time() - $max_age) 900 . $where; 901 $result = $db->sql_query($sql); 902 903 $topic_ids = array(); 904 while ($row = $db->sql_fetchrow($result)) 905 { 906 $topic_ids[] = $row['topic_id']; 907 } 908 $db->sql_freeresult($result); 909 910 if (sizeof($topic_ids)) 911 { 912 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 913 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 914 $db->sql_query($sql); 915 } 916 break; 917 } 918 919 if ($auto_sync) 920 { 921 $where_type = ($forum_id) ? 'forum_id' : ''; 922 sync('forum', $where_type, $forum_id, true); 923 } 924 } 925 926 /** 927 * Update/Sync posted informations for topics 928 */ 929 function update_posted_info(&$topic_ids) 930 { 931 global $db, $config; 932 933 if (empty($topic_ids) || !$config['load_db_track']) 934 { 935 return; 936 } 937 938 // First of all, let us remove any posted information for these topics 939 $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' 940 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 941 $db->sql_query($sql); 942 943 // Now, let us collect the user/topic combos for rebuilding the information 944 $sql = 'SELECT poster_id, topic_id 945 FROM ' . POSTS_TABLE . ' 946 WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' 947 AND poster_id <> ' . ANONYMOUS . ' 948 GROUP BY poster_id, topic_id'; 949 $result = $db->sql_query($sql); 950 951 $posted = array(); 952 while ($row = $db->sql_fetchrow($result)) 953 { 954 // Add as key to make them unique (grouping by) and circumvent empty keys on array_unique 955 $posted[$row['poster_id']][] = $row['topic_id']; 956 } 957 $db->sql_freeresult($result); 958 959 // Now add the information... 960 $sql_ary = array(); 961 foreach ($posted as $user_id => $topic_row) 962 { 963 foreach ($topic_row as $topic_id) 964 { 965 $sql_ary[] = array( 966 'user_id' => $user_id, 967 'topic_id' => $topic_id, 968 'topic_posted' => 1, 969 ); 970 } 971 } 972 unset($posted); 973 974 $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); 975 } 976 977 /** 978 * Delete File 979 */ 980 function phpbb_unlink($filename, $mode = 'file') 981 { 982 global $config, $user, $phpbb_root_path; 983 984 $filename = ($mode == 'thumbnail') ? $phpbb_root_path . $config['upload_path'] . '/thumb_' . basename($filename) : $phpbb_root_path . $config['upload_path'] . '/' . basename($filename); 985 return @unlink($filename); 986 } 987 988 /** 989 * All-encompasing sync function 990 * 991 * Exaples: 992 * <code> 993 * sync('topic', 'topic_id', 123); // resync topic #123 994 * sync('topic', 'forum_id', array(2, 3)); // resync topics from forum #2 and #3 995 * sync('topic'); // resync all topics 996 * sync('topic', 'range', 'topic_id BETWEEN 1 AND 60'); // resync a range of topics/forums (only available for 'topic' and 'forum' modes) 997 * </code> 998 * 999 * Modes: 1000 * - forum Resync complete forum 1001 * - topic Resync topics 1002 * - topic_moved Removes topic shadows that would be in the same forum as the topic they link to 1003 * - topic_approved Resyncs the topic_approved flag according to the status of the first post 1004 * - post_reported Resyncs the post_reported flag, relying on actual reports 1005 * - topic_reported Resyncs the topic_reported flag, relying on post_reported flags 1006 * - post_attachement Same as post_reported, but with attachment flags 1007 * - topic_attachement Same as topic_reported, but with attachment flags 1008 */ 1009 function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sync_extra = false) 1010 { 1011 global $db; 1012 1013 if (is_array($where_ids)) 1014 { 1015 $where_ids = array_unique($where_ids); 1016 $where_ids = array_map('intval', $where_ids); 1017 } 1018 else if ($where_type != 'range') 1019 { 1020 $where_ids = ($where_ids) ? array((int) $where_ids) : array(); 1021 } 1022 1023 if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_approved') 1024 { 1025 if (!$where_type) 1026 { 1027 $where_sql = ''; 1028 $where_sql_and = 'WHERE'; 1029 } 1030 else if ($where_type == 'range') 1031 { 1032 // Only check a range of topics/forums. For instance: 'topic_id BETWEEN 1 AND 60' 1033 $where_sql = 'WHERE (' . $mode[0] . ".$where_ids)"; 1034 $where_sql_and = $where_sql . "\n\tAND"; 1035 } 1036 else 1037 { 1038 // Do not sync the "global forum" 1039 $where_ids = array_diff($where_ids, array(0)); 1040 1041 if (!sizeof($where_ids)) 1042 { 1043 // Empty array with IDs. This means that we don't have any work to do. Just return. 1044 return; 1045 } 1046 1047 // Limit the topics/forums we are syncing, use specific topic/forum IDs. 1048 // $where_type contains the field for the where clause (forum_id, topic_id) 1049 $where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids); 1050 $where_sql_and = $where_sql . "\n\tAND"; 1051 } 1052 } 1053 else 1054 { 1055 if (!sizeof($where_ids)) 1056 { 1057 return; 1058 } 1059 1060 // $where_type contains the field for the where clause (forum_id, topic_id) 1061 $where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids); 1062 $where_sql_and = $where_sql . "\n\tAND"; 1063 } 1064 1065 switch ($mode) 1066 { 1067 case 'topic_moved': 1068 switch ($db->sql_layer) 1069 { 1070 case 'mysql4': 1071 case 'mysqli': 1072 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 1073 USING ' . TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2 1074 WHERE t1.topic_moved_id = t2.topic_id 1075 AND t1.forum_id = t2.forum_id"; 1076 $db->sql_query($sql); 1077 break; 1078 1079 default: 1080 $sql = 'SELECT t1.topic_id 1081 FROM ' .TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2 1082 WHERE t1.topic_moved_id = t2.topic_id 1083 AND t1.forum_id = t2.forum_id"; 1084 $result = $db->sql_query($sql); 1085 1086 $topic_id_ary = array(); 1087 while ($row = $db->sql_fetchrow($result)) 1088 { 1089 $topic_id_ary[] = $row['topic_id']; 1090 } 1091 $db->sql_freeresult($result); 1092 1093 if (!sizeof($topic_id_ary)) 1094 { 1095 return; 1096 } 1097 1098 $sql = 'DELETE FROM ' . TOPICS_TABLE . ' 1099 WHERE ' . $db->sql_in_set('topic_id', $topic_id_ary); 1100 $db->sql_query($sql); 1101 1102 break; 1103 } 1104 break; 1105 1106 case 'topic_approved': 1107 switch ($db->sql_layer) 1108 { 1109 case 'mysql4': 1110 case 'mysqli': 1111 $sql = 'UPDATE ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p 1112 SET t.topic_approved = p.post_approved 1113 $where_sql_and t.topic_first_post_id = p.post_id"; 1114 $db->sql_query($sql); 1115 break; 1116 1117 default: 1118 $sql = 'SELECT t.topic_id, p.post_approved 1119 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p 1120 $where_sql_and p.post_id = t.topic_first_post_id 1121 AND p.post_approved <> t.topic_approved"; 1122 $result = $db->sql_query($sql); 1123 1124 $topic_ids = array(); 1125 while ($row = $db->sql_fetchrow($result)) 1126 { 1127 $topic_ids[] = $row['topic_id']; 1128 } 1129 $db->sql_freeresult($result); 1130 1131 if (!sizeof($topic_ids)) 1132 { 1133 return; 1134 } 1135 1136 $sql = 'UPDATE ' . TOPICS_TABLE . ' 1137 SET topic_approved = 1 - topic_approved 1138 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 1139 $db->sql_query($sql); 1140 break; 1141 } 1142 break; 1143 1144 case 'post_reported': 1145 $post_ids = $post_reported = array(); 1146 1147 $sql = 'SELECT p.post_id, p.post_reported 1148 FROM ' . POSTS_TABLE . " p 1149 $where_sql 1150 GROUP BY p.post_id, p.post_reported"; 1151 $result = $db->sql_query($sql); 1152 1153 while ($row = $db->sql_fetchrow($result)) 1154 { 1155 $post_ids[$row['post_id']] = $row['post_id']; 1156 if ($row['post_reported']) 1157 { 1158 $post_reported[$row['post_id']] = 1; 1159 } 1160 } 1161 $db->sql_freeresult($result); 1162 1163 $sql = 'SELECT DISTINCT(post_id) 1164 FROM ' . REPORTS_TABLE . ' 1165 WHERE ' . $db->sql_in_set('post_id', $post_ids) . ' 1166 AND report_closed = 0'; 1167 $result = $db->sql_query($sql); 1168 1169 $post_ids = array(); 1170 while ($row = $db->sql_fetchrow($result)) 1171 { 1172 if (!isset($post_reported[$row['post_id']])) 1173 { 1174 $post_ids[] = $row['post_id']; 1175 } 1176 else 1177 { 1178 unset($post_reported[$row['post_id']]); 1179 } 1180 } 1181 $db->sql_freeresult($result); 1182 1183 // $post_reported should be empty by now, if it's not it contains 1184 // posts that are falsely flagged as reported 1185 foreach ($post_reported as $post_id => $void) 1186 { 1187 $post_ids[] = $post_id; 1188 } 1189 1190 if (sizeof($post_ids)) 1191 { 1192 $sql = 'UPDATE ' . POSTS_TABLE . ' 1193 SET post_reported = 1 - post_reported 1194 WHERE ' . $db->sql_in_set('post_id', $post_ids); 1195 $db->sql_query($sql); 1196 } 1197 break; 1198 1199 case 'topic_reported': 1200 if ($sync_extra) 1201 { 1202 sync('post_reported', $where_type, $where_ids); 1203 } 1204 1205 $topic_ids = $topic_reported = array(); 1206 1207 $sql = 'SELECT DISTINCT(t.topic_id) 1208 FROM ' . POSTS_TABLE . " t 1209 $where_sql_and t.post_reported = 1"; 1210 $result = $db->sql_query($sql); 1211 1212 while ($row = $db->sql_fetchrow($result)) 1213 { 1214 $topic_reported[$row['topic_id']] = 1; 1215 } 1216 $db->sql_freeresult($result); 1217 1218 $sql = 'SELECT t.topic_id, t.topic_reported 1219 FROM ' . TOPICS_TABLE . " t 1220 $where_sql"; 1221 $result = $db->sql_query($sql); 1222 1223 while ($row = $db->sql_fetchrow($result)) 1224 { 1225 if ($row['topic_reported'] ^ isset($topic_reported[$row['topic_id']])) 1226 { 1227 $topic_ids[] = $row['topic_id']; 1228 } 1229 } 1230 $db->sql_freeresult($result); 1231 1232 if (sizeof($topic_ids)) 1233 { 1234 $sql = 'UPDATE ' . TOPICS_TABLE . ' 1235 SET topic_reported = 1 - topic_reported 1236 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 1237 $db->sql_query($sql); 1238 } 1239 break; 1240 1241 case 'post_attachment': 1242 $post_ids = $post_attachment = array(); 1243 1244 $sql = 'SELECT p.post_id, p.post_attachment 1245 FROM ' . POSTS_TABLE . " p 1246 $where_sql 1247 GROUP BY p.post_id, p.post_attachment"; 1248 $result = $db->sql_query($sql); 1249 1250 while ($row = $db->sql_fetchrow($result)) 1251 { 1252 $post_ids[$row['post_id']] = $row['post_id']; 1253 if ($row['post_attachment']) 1254 { 1255 $post_attachment[$row['post_id']] = 1; 1256 } 1257 } 1258 $db->sql_freeresult($result); 1259 1260 $sql = 'SELECT DISTINCT(post_msg_id) 1261 FROM ' . ATTACHMENTS_TABLE . ' 1262 WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . ' 1263 AND in_message = 0'; 1264 $result = $db->sql_query($sql); 1265 1266 $post_ids = array(); 1267 while ($row = $db->sql_fetchrow($result)) 1268 { 1269 if (!isset($post_attachment[$row['post_id']])) 1270 { 1271 $post_ids[] = $row['post_id']; 1272 } 1273 else 1274 { 1275 unset($post_attachment[$row['post_id']]); 1276 } 1277 } 1278 $db->sql_freeresult($result); 1279 1280 // $post_attachment should be empty by now, if it's not it contains 1281 // posts that are falsely flagged as having attachments 1282 foreach ($post_attachment as $post_id => $void) 1283 { 1284 $post_ids[] = $post_id; 1285 } 1286 1287 if (sizeof($post_ids)) 1288 { 1289 $sql = 'UPDATE ' . POSTS_TABLE . ' 1290 SET post_attachment = 1 - post_attachment 1291 WHERE ' . $db->sql_in_set('post_id', $post_ids); 1292 $db->sql_query($sql); 1293 } 1294 break; 1295 1296 case 'topic_attachment': 1297 if ($sync_extra) 1298 { 1299 sync('post_attachment', $where_type, $where_ids); 1300 } 1301 1302 $topic_ids = $topic_attachment = array(); 1303 1304 $sql = 'SELECT DISTINCT(t.topic_id) 1305 FROM ' . POSTS_TABLE . " t 1306 $where_sql_and t.post_attachment = 1"; 1307 $result = $db->sql_query($sql); 1308 1309 while ($row = $db->sql_fetchrow($result)) 1310 { 1311 $topic_attachment[$row['topic_id']] = 1; 1312 } 1313 $db->sql_freeresult($result); 1314 1315 $sql = 'SELECT t.topic_id, t.topic_attachment 1316 FROM ' . TOPICS_TABLE . " t 1317 $where_sql"; 1318 $result = $db->sql_query($sql); 1319 1320 while ($row = $db->sql_fetchrow($result)) 1321 { 1322 if ($row['topic_attachment'] ^ isset($topic_attachment[$row['topic_id']])) 1323 { 1324 $topic_ids[] = $row['topic_id']; 1325 } 1326 } 1327 $db->sql_freeresult($result); 1328 1329 if (sizeof($topic_ids)) 1330 { 1331 $sql = 'UPDATE ' . TOPICS_TABLE . ' 1332 SET topic_attachment = 1 - topic_attachment 1333 WHERE ' . $db->sql_in_set('topic_id', $topic_ids); 1334 $db->sql_query($sql); 1335 } 1336 break; 1337 1338 case 'forum': 1339 1340 // 1: Get the list of all forums 1341 $sql = 'SELECT f.* 1342 FROM ' . FORUMS_TABLE . " f 1343 $where_sql"; 1344 $result = $db->sql_query($sql); 1345 1346 $forum_data = $forum_ids = $post_ids = $last_post_id = $post_info = array(); 1347 while ($row = $db->sql_fetchrow($result)) 1348 { 1349 if ($row['forum_type'] == FORUM_LINK) 1350 { 1351 continue; 1352 } 1353 1354 $forum_id = (int) $row['forum_id']; 1355 $forum_ids[$forum_id] = $forum_id; 1356 1357 $forum_data[$forum_id] = $row; 1358 $forum_data[$forum_id]['posts'] = 0; 1359 $forum_data[$forum_id]['topics'] = 0; 1360 $forum_data[$forum_id]['topics_real'] = 0; 1361 $forum_data[$forum_id]['last_post_id'] = 0; 1362 $forum_data[$forum_id]['last_post_subject'] = ''; 1363 $forum_data[$forum_id]['last_post_time'] = 0; 1364 $forum_data[$forum_id]['last_poster_id'] = 0; 1365 $forum_data[$forum_id]['last_poster_name'] = ''; 1366 $forum_data[$forum_id]['last_poster_colour'] = ''; 1367 } 1368 $db->sql_freeresult($result); 1369 1370 if (!sizeof($forum_ids)) 1371 { 1372 break; 1373 } 1374 1375 $forum_ids = array_values($forum_ids); 1376 1377 // 2: Get topic counts for each forum 1378 $sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics 1379 FROM ' . TOPICS_TABLE . ' 1380 WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' 1381 GROUP BY forum_id, topic_approved'; 1382 $result = $db->sql_query($sql); 1383 1384 while ($row = $db->sql_fetchrow($result)) 1385 { 1386 $forum_id = (int) $row['forum_id']; 1387 $forum_data[$forum_id]['topics_real'] += $row['forum_topics']; 1388 1389 if ($row['topic_approved']) 1390 { 1391 $forum_data[$forum_id]['topics'] = $row['forum_topics']; 1392 } 1393 } 1394 $db->sql_freeresult($result); 1395 1396 // 3: Get post count and last_post_id for each forum 1397 if (sizeof($forum_ids) == 1) 1398 { 1399 $sql = 'SELECT COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id 1400 FROM ' . POSTS_TABLE . ' 1401 WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' 1402 AND post_approved = 1'; 1403 } 1404 else 1405 { 1406 $sql = 'SELECT forum_id, COUNT(post_id) AS forum_posts, MAX(post_id) AS last_post_id 1407 FROM ' . POSTS_TABLE . ' 1408 WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . ' 1409 AND post_approved = 1 1410 GROUP BY forum_id'; 1411 } 1412 1413 $result = $db->sql_query($sql); 1414 1415 while ($row = $db->sql_fetchrow($result)) 1416 { 1417 $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; 1418 1419 $forum_data[$forum_id]['posts'] = (int) $row['forum_posts']; 1420 $forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id']; 1421 1422 $post_ids[] = $row['last_post_id']; 1423 } 1424 $db->sql_freeresult($result); 1425 1426 // 4: Retrieve last_post infos 1427 if (sizeof($post_ids)) 1428 { 1429 $sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour 1430 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u 1431 WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' 1432 AND p.poster_id = u.user_id'; 1433 $result = $db->sql_query($sql); 1434 1435 while ($row = $db->sql_fetchrow($result)) 1436 { 1437 $post_info[$row['post_id']] = $row; 1438 } 1439 $db->sql_freeresult($result); 1440 1441 foreach ($forum_data as $forum_id => $data) 1442 { 1443 if ($data['last_post_id']) 1444 { 1445 if (isset($post_info[$data['last_post_id']])) 1446 { 1447 $forum_data[$forum_id]['last_post_subject'] = $post_info[$data['last_post_id']]['post_subject']; 1448 $forum_data[$forum_id]['last_post_time'] = $post_info[$data['last_post_id']]['post_time']; 1449 $forum_data[$forum_id]['last_poster_id'] = $post_info[$data['last_post_id']]['poster_id']; 1450 $forum_data[$forum_id]['last_poster_name'] = ($post_info[$data['last_post_id']]['poster_id'] != ANONYMOUS) ? $post_info[$data['last_post_id']]['username'] : $post_info[$data['last_post_id']]['post_username']; 1451 $forum_data[$forum_id]['last_poster_colour'] = $post_info[$data['last_post_id']]['user_colour']; 1452 } 1453 else 1454 { 1455 // For some reason we did not find the post in the db 1456 $forum_data[$forum_id]['last_post_id'] = 0; 1457 $forum_data[$forum_id]['last_post_subject'] = ''; 1458 $forum_data[$forum_id]['last_post_time'] = 0; 1459 $forum_data[$forum_id]['last_poster_id'] = 0; 1460 $forum_data[$forum_id]['last_poster_name'] = ''; 1461 $forum_data[$forum_id]['last_poster_colour'] = ''; 1462 } 1463 } 1464 } 1465 unset($post_info); 1466 } 1467 1468 // 5: Now do that thing 1469 $fieldnames = array('posts', 'topics', 'topics_real', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); 1470 1471 foreach ($forum_data as $forum_id => $row) 1472 { 1473 $sql_ary = array(); 1474 1475 foreach ($fieldnames as $fieldname) 1476 { 1477 if ($row['forum_' . $fieldname] != $row[$fieldname]) 1478 { 1479 if (preg_match('#(name|colour|subject)$#', $fieldname)) 1480 { 1481 $sql_ary['forum_' . $fieldname] = (string) $row[$fieldname]; 1482 } 1483 else 1484 { 1485 $sql_ary['forum_' . $fieldname] = (int) $row[$fieldname]; 1486 } 1487 } 1488 } 1489 1490 if (sizeof($sql_ary)) 1491 { 1492 $sql = 'UPDATE ' . FORUMS_TABLE . ' 1493 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 1494 WHERE forum_id = ' . $forum_id; 1495 $db->sql_query($sql); 1496 } 1497 } 1498 break; 1499 1500 case 'topic': 1501 $topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array(); 1502 1503 $sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time 1504 FROM ' . TOPICS_TABLE . " t 1505 $where_sql"; 1506 $result = $db->sql_query($sql); 1507 1508 while ($row = $db->sql_fetchrow($result)) 1509 { 1510 if ($row['topic_moved_id']) 1511 { 1512 $moved_topics[] = $row['topic_id']; 1513 continue; 1514 } 1515 1516 $topic_id = (int) $row['topic_id']; 1517 $topic_data[$topic_id] = $row; 1518 $topic_data[$topic_id]['replies_real'] = -1; 1519 $topic_data[$topic_id]['replies'] = 0; 1520 $topic_data[$topic_id]['first_post_id'] = 0; 1521 $topic_data[$topic_id]['last_post_id'] = 0; 1522 unset($topic_data[$topic_id]['topic_id']); 1523 1524 // This array holds all topic_ids 1525 $delete_topics[$topic_id] = ''; 1526 1527 if ($sync_extra) 1528 { 1529 $topic_data[$topic_id]['reported'] = 0; 1530 $topic_data[$topic_id]['attachment'] = 0; 1531 } 1532 } 1533 $db->sql_freeresult($result); 1534 1535 // Use "t" as table alias because of the $where_sql clause 1536 // NOTE: 't.post_approved' in the GROUP BY is causing a major slowdown. 1537 $sql = 'SELECT t.topic_id, t.post_approved, COUNT(t.post_id) AS total_posts, MIN(t.post_id) AS first_post_id, MAX(t.post_id) AS last_post_id 1538 FROM ' . POSTS_TABLE . " t 1539 $where_sql 1540 GROUP BY t.topic_id, t.post_approved"; 1541 $result = $db->sql_query($sql); 1542 1543 while ($row = $db->sql_fetchrow($result)) 1544 { 1545 $topic_id = (int) $row['topic_id']; 1546 1547 $row['first_post_id'] = (int) $row['first_post_id']; 1548 $row['last_post_id'] = (int) $row['last_post_id']; 1549 1550 if (!isset($topic_data[$topic_id])) 1551 { 1552 // Hey, these posts come from a topic that does not exist 1553 $delete_posts[$topic_id] = ''; 1554 } 1555 else 1556 { 1557 // Unset the corresponding entry in $delete_topics 1558 // When we'll be done, only topics with no posts will remain 1559 unset($delete_topics[$topic_id]); 1560 1561 $topic_data[$topic_id]['replies_real'] += $row['total_posts']; 1562 $topic_data[$topic_id]['first_post_id'] = (!$topic_data[$topic_id]['first_post_id']) ? $row['first_post_id'] : min($topic_data[$topic_id]['first_post_id'], $row['first_post_id']); 1563 1564 if ($row['post_approved'] || !$topic_data[$topic_id]['last_post_id']) 1565 { 1566 $topic_data[$topic_id]['replies'] = $row['total_posts'] - 1; 1567 $topic_data[$topic_id]['last_post_id'] = $row['last_post_id']; 1568 } 1569 } 1570 } 1571 $db->sql_freeresult($result); 1572 1573 foreach ($topic_data as $topic_id => $row) 1574 { 1575 $post_ids[] = $row['first_post_id']; 1576 if ($row['first_post_id'] != $row['last_post_id']) 1577 { 1578 $post_ids[] = $row['last_post_id']; 1579 } 1580 } 1581 1582 // Now we delete empty topics and orphan posts 1583 if (sizeof($delete_posts)) 1584 { 1585 delete_posts('topic_id', array_keys($delete_posts), false); 1586 unset($delete_posts); 1587 } 1588 1589 if (!sizeof($topic_data)) 1590 { 1591 // If we get there, topic ids were invalid or topics did not contain any posts 1592 delete_topics($where_type, $where_ids, true); 1593 return; 1594 } 1595 1596 if (sizeof($delete_topics)) 1597 { 1598 $delete_topic_ids = array(); 1599 foreach ($delete_topics as $topic_id => $void) 1600 { 1601 unset($topic_data[$topic_id]); 1602 $delete_topic_ids[] = $topic_id; 1603 } 1604 1605 delete_topics('topic_id', $delete_topic_ids, false); 1606 unset($delete_topics, $delete_topic_ids); 1607 } 1608 1609 // Make sure shadow topics do link to existing topics 1610 if (sizeof($moved_topics)) 1611 { 1612 $delete_topics = array(); 1613 1614 $sql = 'SELECT t1.topic_id, t1.topic_moved_id 1615 FROM ' . TOPICS_TABLE . ' t1 1616 LEFT JOIN ' . TOPICS_TABLE . ' t2 ON (t2.topic_id = t1.topic_moved_id) 1617 WHERE ' . $db->sql_in_set('t1.topic_id', $moved_topics) . ' 1618 AND t2.topic_id IS NULL'; 1619 $result = $db->sql_query($sql); 1620 1621 while ($row = $db->sql_fetchrow($result)) 1622 { 1623 $delete_topics[] = $row['topic_id']; 1624 } 1625 $db->sql_freeresult($result); 1626 1627 if (sizeof($delete_topics)) 1628 { 1629 delete_topics('topic_id', $delete_topics, false); 1630 } 1631 unset($delete_topics); 1632 } 1633 1634 $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour 1635 FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u 1636 WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' 1637 AND u.user_id = p.poster_id'; 1638 $result = $db->sql_query($sql); 1639 1640 $post_ids = array(); 1641 while ($row = $db->sql_fetchrow($result)) 1642 { 1643 $topic_id = intval($row['topic_id']); 1644 1645 if ($row['post_id'] == $topic_data[$topic_id]['first_post_id']) 1646 { 1647 if ($topic_data[$topic_id]['topic_approved'] != $row['post_approved']) 1648 { 1649 $approved_unapproved_ids[] = $topic_id; 1650 } 1651 $topic_data[$topic_id]['time'] = $row['post_time']; 1652 $topic_data[$topic_id]['poster'] = $row['poster_id']; 1653 $topic_data[$topic_id]['first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; 1654 $topic_data[$topic_id]['first_poster_colour'] = $row['user_colour']; 1655 } 1656 1657 if ($row['post_id'] == $topic_data[$topic_id]['last_post_id']) 1658 { 1659 $topic_data[$topic_id]['last_poster_id'] = $row['poster_id']; 1660 $topic_data[$topic_id]['last_post_subject'] = $row['post_subject']; 1661 $topic_data[$topic_id]['last_post_time'] = $row['post_time']; 1662 $topic_data[$topic_id]['last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; 1663 $topic_data[$topic_id]['last_poster_colour'] = $row['user_colour']; 1664 } 1665 } 1666 $db->sql_freeresult($result); 1667 1668 // approved becomes unapproved, and vice-versa 1669 if (sizeof($approved_unapproved_ids)) 1670 { 1671 $sql = 'UPDATE ' . TOPICS_TABLE . ' 1672 SET topic_approved = 1 - topic_approved 1673 WHERE ' . $db->sql_in_set('topic_id', $approved_unapproved_ids); 1674 $db->sql_query($sql); 1675 } 1676 unset($approved_unapproved_ids); 1677 1678 // These are fields that will be synchronised 1679 $fieldnames = array('time', 'replies', 'replies_real', 'poster', 'first_post_id', 'first_poster_name', 'first_poster_colour', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); 1680 1681 if ($sync_extra) 1682 { 1683 // This routine assumes that post_reported values are correct 1684 // if they are not, use sync('post_reported') first 1685 $sql = 'SELECT t.topic_id, p.post_id 1686 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p 1687 $where_sql_and p.topic_id = t.topic_id 1688 AND p.post_reported = 1 1689 GROUP BY t.topic_id, p.post_id"; 1690 $result = $db->sql_query($sql); 1691 1692 $fieldnames[] = 'reported'; 1693 while ($row = $db->sql_fetchrow($result)) 1694 { 1695 $topic_data[intval($row['topic_id'])]['reported'] = 1; 1696 } 1697 $db->sql_freeresult($result); 1698 1699 // This routine assumes that post_attachment values are correct 1700 // if they are not, use sync('post_attachment') first 1701 $sql = 'SELECT t.topic_id, p.post_id 1702 FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p 1703 $where_sql_and p.topic_id = t.topic_id 1704 AND p.post_attachment = 1 1705 GROUP BY t.topic_id, p.post_id"; 1706 $result = $db->sql_query($sql); 1707 1708 $fieldnames[] = 'attachment'; 1709 while ($row = $db->sql_fetchrow($result)) 1710 { 1711 $topic_data[intval($row['topic_id'])]['attachment'] = 1; 1712 } 1713 $db->sql_freeresult($result); 1714 } 1715 1716 foreach ($topic_data as $topic_id => $row) 1717 { 1718 $sql_ary = array(); 1719 1720 foreach ($fieldnames as $fieldname) 1721 { 1722 if (isset($row[$fieldname]) && isset($row['topic_' . $fieldname]) && $row['topic_' . $fieldname] != $row[$fieldname]) 1723 { 1724 $sql_ary['topic_' . $fieldname] = $row[$fieldname]; 1725 } 1726 } 1727 1728 if (sizeof($sql_ary)) 1729 { 1730 $sql = 'UPDATE ' . TOPICS_TABLE . ' 1731 SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' 1732 WHERE topic_id = ' . $topic_id; 1733 $db->sql_query($sql); 1734 1735 $resync_forums[$row['forum_id']] = $row['forum_id']; 1736 } 1737 } 1738 unset($topic_data); 1739 1740 // if some topics have been resync'ed then resync parent forums 1741 // except when we're only syncing a range, we don't want to sync forums during 1742 // batch processing. 1743 if ($resync_parents && sizeof($resync_forums) && $where_type != 'range') 1744 { 1745 sync('forum', 'forum_id', array_values($resync_forums), true); 1746 } 1747 break; 1748 } 1749 1750 return; 1751 } 1752 1753 /** 1754 * Prune function 1755 */ 1756 function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync = true) 1757 { 1758 global $db; 1759 1760 if (!is_array($forum_id)) 1761 { 1762 $forum_id = array($forum_id); 1763 } 1764 1765 if (!sizeof($forum_id)) 1766 { 1767 return; 1768 } 1769 1770 $sql_and = ''; 1771 1772 if (!($prune_flags & FORUM_FLAG_PRUNE_ANNOUNCE)) 1773 { 1774 $sql_and .= ' AND topic_type <> ' . POST_ANNOUNCE; 1775 } 1776 1777 if (!($prune_flags & FORUM_FLAG_PRUNE_STICKY)) 1778 { 1779 $sql_and .= ' AND topic_type <> ' . POST_STICKY; 1780 } 1781 1782 if ($prune_mode == 'posted') 1783 { 1784 $sql_and .= " AND topic_last_post_time < $prune_date"; 1785 } 1786 1787 if ($prune_mode == 'viewed') 1788 { 1789 $sql_and .= " AND topic_last_view_time < $prune_date"; 1790 } 1791 1792 $sql = 'SELECT topic_id 1793 FROM ' . TOPICS_TABLE . ' 1794 WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " 1795 AND poll_start = 0 1796 $sql_and"; 1797 $result = $db->sql_query($sql); 1798 1799 $topic_list = array(); 1800 while ($row = $db->sql_fetchrow($result)) 1801 { 1802 $topic_list[] = $row['topic_id']; 1803 } 1804 $db->sql_freeresult($result); 1805 1806 if ($prune_flags & FORUM_FLAG_PRUNE_POLL) 1807 { 1808 $sql = 'SELECT topic_id 1809 FROM ' . TOPICS_TABLE . ' 1810 WHERE ' . $db->sql_in_set('forum_id', $forum_id) . " 1811 AND poll_start > 0 1812 AND poll_last_vote < $prune_date 1813 $sql_and"; 1814 $result = $db->sql_query($sql); 1815 1816 while ($row = $db->sql_fetchrow($result)) 1817 { 1818 $topic_list[] = $row['topic_id']; 1819 } 1820 $db->sql_freeresult($result); 1821 1822 $topic_list = array_unique($topic_list); 1823 } 1824 1825 return delete_topics('topic_id', $topic_list, $auto_sync); 1826 } 1827 1828 /** 1829 * Function auto_prune(), this function now relies on passed vars 1830 */ 1831 function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq) 1832 { 1833 global $db; 1834 1835 $sql = 'SELECT forum_name 1836 FROM ' . FORUMS_TABLE . " 1837 WHERE forum_id = $forum_id"; 1838 $result = $db->sql_query($sql, 3600); 1839 $row = $db->sql_fetchrow($result); 1840 $db->sql_freeresult($result); 1841 1842 if ($row) 1843 { 1844 $prune_date = time() - ($prune_days * 86400); 1845 $next_prune = time() + ($prune_freq * 86400); 1846 1847 prune($forum_id, $prune_mode, $prune_date, $prune_flags, true); 1848 1849 $sql = 'UPDATE ' . FORUMS_TABLE . " 1850 SET prune_next = $next_prune 1851 WHERE forum_id = $forum_id"; 1852 $db->sql_query($sql); 1853 1854 add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']); 1855 } 1856 1857 return; 1858 } 1859 1860 /** 1861 * remove_comments will strip the sql comment lines out of an uploaded sql file 1862 * specifically for mssql and postgres type files in the install.... 1863 */ 1864 function remove_comments(&$output) 1865 { 1866 $lines = explode("\n", $output); 1867 $output = ''; 1868 1869 // try to keep mem. use down 1870 $linecount = sizeof($lines); 1871 1872 $in_comment = false; 1873 for ($i = 0; $i < $linecount; $i++) 1874 { 1875 if (trim($lines[$i]) == '/*') 1876 { 1877 $in_comment = true; 1878 } 1879 1880 if (!$in_comment) 1881 { 1882 $output .= $lines[$i] . "\n"; 1883 } 1884 1885 if (trim($lines[$i]) == '*/') 1886 { 1887 $in_comment = false; 1888 } 1889 } 1890 1891 unset($lines); 1892 return $output; 1893 } 1894 1895 /** 1896 * remove_remarks will strip the sql comment lines out of an uploaded sql file 1897 */ 1898 function remove_remarks(&$sql) 1899 { 1900 $sql = preg_replace('/\n{2,}/', "\n", preg_replace('/^#.*$/m', "\n", $sql)); 1901 } 1902 1903 /** 1904 * split_sql_file will split an uploaded sql file into single sql statements. 1905 * Note: expects trim() to have already been run on $sql. 1906 */ 1907 function split_sql_file($sql, $delimiter) 1908 { 1909 $sql = str_replace("\r" , '', $sql); 1910 $data = preg_split('/' . preg_quote($delimiter, '/') . '$/m', $sql); 1911 1912 foreach ($data as $key => $value) 1913 { 1914 $data[$key] = trim($value); 1915 } 1916 1917 // The empty case 1918 $end_data = end($data); 1919 1920 if (empty($end_data)) 1921 { 1922 unset($data[key($data)]); 1923 } 1924 1925 return $data; 1926 } 1927 1928 /** 1929 * Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username 1930 * and group names must be carried through for the moderators table 1931 * 1932 * @todo let the admin define if he wants to display moderators (forum-based) - display_on_index already present and checked for... 1933 */ 1934 function cache_moderators() 1935 { 1936 global $db, $cache, $auth, $phpbb_root_path, $phpEx; 1937 1938 // Remove cached sql results 1939 $cache->destroy('sql', MODERATOR_CACHE_TABLE); 1940 1941 // Clear table 1942 $db->sql_query((($db->sql_layer != 'sqlite') ? 'TRUNCATE TABLE ' : 'DELETE FROM ') . MODERATOR_CACHE_TABLE); 1943 1944 // We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting 1945 $hold_ary = $ug_id_ary = $sql_ary = array(); 1946 1947 // Grab all users having moderative options... 1948 $hold_ary = $auth->acl_user_raw_data(false, 'm_%', false); 1949 1950 // Add users? 1951 if (sizeof($hold_ary)) 1952 { 1953 // At least one moderative option warrants a display 1954 $ug_id_ary = array_keys($hold_ary); 1955 1956 // Remove users who have group memberships with DENY moderator permissions 1957 $sql = $db->sql_build_query('SELECT', array( 1958 'SELECT' => 'a.forum_id, ug.user_id', 1959 1960 'FROM' => array( 1961 ACL_OPTIONS_TABLE => 'o', 1962 USER_GROUP_TABLE => 'ug', 1963 ACL_GROUPS_TABLE => 'a' 1964 ), 1965 1966 'LEFT_JOIN' => array( 1967 array( 1968 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), 1969 'ON' => 'a.auth_role_id = r.role_id' 1970 ) 1971 ), 1972 1973 'WHERE' => '(o.auth_option_id = a.auth_option_id OR o.auth_option_id = r.auth_option_id) 1974 AND ((a.auth_setting = ' . ACL_NEVER . ' AND r.auth_setting IS NULL) 1975 OR r.auth_setting = ' . ACL_NEVER . ') 1976 AND a.group_id = ug.group_id 1977 AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . " 1978 AND ug.user_pending = 0 1979 AND o.auth_option LIKE 'm\_%'" . 1980 (($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : ''), 1981 )); 1982 $result = $db->sql_query($sql); 1983 1984 while ($row = $db->sql_fetchrow($result)) 1985 { 1986 if (isset($hold_ary[$row['user_id']][$row['forum_id']])) 1987 { 1988 unset($hold_ary[$row['user_id']][$row['forum_id']]); 1989 } 1990 } 1991 $db->sql_freeresult($result); 1992 1993 if (sizeof($hold_ary)) 1994 { 1995 // Get usernames... 1996 $sql = 'SELECT user_id, username 1997 FROM ' . USERS_TABLE . ' 1998 WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)); 1999 $result = $db->sql_query($sql); 2000 2001 $usernames_ary = array(); 2002 while ($row = $db->sql_fetchrow($result)) 2003 { 2004 $usernames_ary[$row['user_id']] = $row['username']; 2005 } 2006 2007 foreach ($hold_ary as $user_id => $forum_id_ary) 2008 { 2009 // Do not continue if user does not exist 2010 if (!isset($usernames_ary[$user_id])) 2011 { 2012 continue; 2013 } 2014 2015 foreach ($forum_id_ary as $forum_id => $auth_ary) 2016 { 2017 $sql_ary[] = array( 2018 'forum_id' => $forum_id, 2019 'user_id' => $user_id, 2020 'username' => $usernames_ary[$user_id], 2021 'group_id' => 0, 2022 'group_name' => '' 2023 ); 2024 } 2025 } 2026 } 2027 } 2028 2029 // Now to the groups... 2030 $hold_ary = $auth->acl_group_raw_data(false, 'm_%', false); 2031 2032 if (sizeof($hold_ary)) 2033 { 2034 $ug_id_ary = array_keys($hold_ary); 2035 2036 // Make sure not hidden or special groups are involved... 2037 $sql = 'SELECT group_name, group_id, group_type 2038 FROM ' . GROUPS_TABLE . ' 2039 WHERE ' . $db->sql_in_set('group_id', $ug_id_ary); 2040 $result = $db->sql_query($sql); 2041 2042 $groupnames_ary = array(); 2043 while ($row = $db->sql_fetchrow($result)) 2044 { 2045 if ($row['group_type'] == GROUP_HIDDEN || $row['group_type'] == GROUP_SPECIAL) 2046 { 2047 unset($hold_ary[$row['group_id']]); 2048 } 2049 2050 $groupnames_ary[$row['group_id']] = $row['group_name']; 2051 } 2052 $db->sql_freeresult($result); 2053 2054 foreach ($hold_ary as $group_id => $forum_id_ary) 2055 { 2056 // If there is no group, we do not assign it... 2057 if (!isset($groupnames_ary[$group_id])) 2058 { 2059 continue; 2060 } 2061 2062 foreach ($forum_id_ary as $forum_id => $auth_ary) 2063 { 2064 $flag = false; 2065 foreach ($auth_ary as $auth_option => $setting) 2066 { 2067 // Make sure at least one ACL_YES option is set... 2068 if ($setting == ACL_YES) 2069 { 2070 $flag = true; 2071 break; 2072 } 2073 } 2074 2075 if (!$flag) 2076 { 2077 continue; 2078 } 2079 2080 $sql_ary[] = array( 2081 'forum_id' => $forum_id, 2082 'user_id' => 0, 2083 'username' => '', 2084 'group_id' => $group_id, 2085 'group_name' => $groupnames_ary[$group_id] 2086 ); 2087 } 2088 } 2089 } 2090 2091 $db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary); 2092 } 2093 2094 /** 2095 * View log 2096 */ 2097 function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC') 2098 { 2099 global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path; 2100 2101 $topic_id_list = $reportee_id_list = $is_auth = $is_mod = array(); 2102 2103 $profile_url = (defined('IN_ADMIN')) ? append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview') : append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=viewprofile'); 2104 2105 switch ($mode) 2106 { 2107 case 'admin': 2108 $log_type = LOG_ADMIN; 2109 $sql_forum = ''; 2110 break; 2111 2112 case 'mod': 2113 $log_type = LOG_MOD; 2114 2115 if ($topic_id) 2116 { 2117 $sql_forum = 'AND l.topic_id = ' . intval($topic_id); 2118 } 2119 else if (is_array($forum_id)) 2120 { 2121 $sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); 2122 } 2123 else 2124 { 2125 $sql_forum = ($forum_id) ? 'AND l.forum_id = ' . intval($forum_id) : ''; 2126 } 2127 break; 2128 2129 case 'user': 2130 $log_type = LOG_USERS; 2131 $sql_forum = 'AND l.reportee_id = ' . intval($user_id); 2132 break; 2133 2134 case 'users': 2135 $log_type = LOG_USERS; 2136 $sql_forum = ''; 2137 break; 2138 2139 case 'critical': 2140 $log_type = LOG_CRITICAL; 2141 $sql_forum = ''; 2142 break; 2143 2144 default: 2145 return; 2146 } 2147 2148 $sql = "SELECT l.*, u.username 2149 FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u 2150 WHERE l.log_type = $log_type 2151 AND u.user_id = l.user_id 2152 " . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . " 2153 $sql_forum 2154 ORDER BY $sort_by"; 2155 $result = $db->sql_query_limit($sql, $limit, $offset); 2156 2157 $i = 0; 2158 $log = array(); 2159 while ($row = $db->sql_fetchrow($result)) 2160 { 2161 if ($row['topic_id']) 2162 { 2163 $topic_id_list[] = $row['topic_id']; 2164 } 2165 2166 if ($row['reportee_id']) 2167 { 2168 $reportee_id_list[] = $row['reportee_id']; 2169 } 2170 2171 $log[$i] = array( 2172 'id' => $row['log_id'], 2173 'reportee_id' => $row['reportee_id'], 2174 'reportee_username' => '', 2175 'user_id' => $row['user_id'], 2176 'username' => '<a href="' . $profile_url . '&u=' . $row['user_id'] . '">' . $row['username'] . '</a>', 2177 'ip' => $row['log_ip'], 2178 'time' => $row['log_time'], 2179 'forum_id' => $row['forum_id'], 2180 'topic_id' => $row['topic_id'], 2181 2182 'viewforum' => ($row['forum_id'] && $auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : false, 2183 'action' => (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', 2184 ); 2185 2186 if (!empty($row['log_data'])) 2187 { 2188 $log_data_ary = unserialize($row['log_data']); 2189 2190 if (isset($user->lang[$row['log_operation']])) 2191 { 2192 $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); 2193 $log[$i]['action'] = str_replace("\n", '<br />', censor_text($log[$i]['action'])); 2194 } 2195 else 2196 { 2197 $log[$i]['action'] .= '<br />' . implode('', $log_data_ary); 2198 } 2199 } 2200 2201 $i++; 2202 } 2203 $db->sql_freeresult($result); 2204 2205 if (sizeof($topic_id_list)) 2206 { 2207 $topic_id_list = array_unique($topic_id_list); 2208 2209 // This query is not really needed if move_topics() updates the forum_id field, 2210 // although it's also used to determine if the topic still exists in the database 2211 $sql = 'SELECT topic_id, forum_id 2212 FROM ' . TOPICS_TABLE . ' 2213 WHERE ' . $db->sql_in_set('topic_id', array_map('intval', $topic_id_list)); 2214 $result = $db->sql_query($sql); 2215 2216 $default_forum_id = 0; 2217 2218 while ($row = $db->sql_fetchrow($result)) 2219 { 2220 if (!$row['forum_id']) 2221 { 2222 if ($auth->acl_getf_global('f_read')) 2223 { 2224 if (!$default_forum_id) 2225 { 2226 $sql = 'SELECT forum_id 2227 FROM ' . FORUMS_TABLE . ' 2228 WHERE forum_type = ' . FORUM_POST; 2229 $f_result = $db->sql_query_limit($sql, 1); 2230 $default_forum_id = (int) $db->sql_fetchfield('forum_id', false, $f_result); 2231 $db->sql_freeresult($f_result); 2232 } 2233 2234 $is_auth[$row['topic_id']] = $default_forum_id; 2235 } 2236 } 2237 else 2238 { 2239 if ($auth->acl_get('f_read', $row['forum_id'])) 2240 { 2241 $is_auth[$row['topic_id']] = $row['forum_id']; 2242 } 2243 } 2244 2245 if ($auth->acl_gets('a_', 'm_', $row['forum_id'])) 2246 { 2247 $is_mod[$row['topic_id']] = $row['forum_id']; 2248 } 2249 } 2250 $db->sql_freeresult($result); 2251 2252 foreach ($log as $key => $row) 2253 { 2254 $log[$key]['viewtopic'] = (isset($is_auth[$row['topic_id']])) ? append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $is_auth[$row['topic_id']] . '&t=' . $row['topic_id']) : false; 2255 $log[$key]['viewlogs'] = (isset($is_mod[$row['topic_id']])) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $user->session_id) : false; 2256 } 2257 } 2258 2259 if ($reportee_id_list) 2260 { 2261 $reportee_id_list = array_unique($reportee_id_list); 2262 $reportee_names_list = array(); 2263 2264 if (!function_exists('user_get_id_name')) 2265 { 2266 include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); 2267 } 2268 2269 user_get_id_name($reportee_id_list, $reportee_names_list); 2270 2271 foreach ($log as $key => $row) 2272 { 2273 $log[$key]['reportee_username'] = (isset($reportee_names_list[$row['reportee_id']])) ? '<a href="' . $profile_url . '&u=' . $row['reportee_id'] . '">' . $reportee_names_list[$row['reportee_id']] . '</a>' : false; 2274 } 2275 } 2276 2277 $sql = 'SELECT COUNT(l.log_id) AS total_entries 2278 FROM ' . LOG_TABLE . " l 2279 WHERE l.log_type = $log_type 2280 AND l.log_time >= $limit_days 2281 $sql_forum"; 2282 $result = $db->sql_query($sql); 2283 $log_count = (int) $db->sql_fetchfield('total_entries'); 2284 $db->sql_freeresult($result); 2285 2286 return; 2287 } 2288 2289 /** 2290 * Update foes - remove moderators and administrators from foe lists... 2291 */ 2292 function update_foes() 2293 { 2294 global $db, $auth; 2295 2296 $perms = array(); 2297 foreach ($auth->acl_get_list(false, array('a_', 'm_'), false) as $forum_id => $forum_ary) 2298 { 2299 foreach ($forum_ary as $auth_option => $user_ary) 2300 { 2301 $perms = array_merge($perms, $user_ary); 2302 } 2303 } 2304 2305 if (sizeof($perms)) 2306 { 2307 $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' 2308 WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . ' 2309 AND foe = 1'; 2310 $db->sql_query($sql); 2311 } 2312 unset($perms); 2313 } 2314 2315 /** 2316 * Lists inactive users 2317 */ 2318 function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC') 2319 { 2320 global $db, $user; 2321 2322 $sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason 2323 FROM ' . USERS_TABLE . ' 2324 WHERE user_type = ' . USER_INACTIVE . 2325 (($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . " 2326 ORDER BY $sort_by"; 2327 $result = $db->sql_query_limit($sql, $limit, $offset); 2328 2329 while ($row = $db->sql_fetchrow($result)) 2330 { 2331 $row['inactive_reason'] = $user->lang['INACTIVE_REASON_UNKNOWN']; 2332 switch ($row['user_inactive_reason']) 2333 { 2334 case INACTIVE_REGISTER: 2335 $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REGISTER']; 2336 break; 2337 2338 case INACTIVE_PROFILE: 2339 $row['inactive_reason'] = $user->lang['INACTIVE_REASON_PROFILE']; 2340 break; 2341 2342 case INACTIVE_MANUAL: 2343 $row['inactive_reason'] = $user->lang['INACTIVE_REASON_MANUAL']; 2344 break; 2345 2346 case INACTIVE_REMIND: 2347 $row['inactive_reason'] = $user->lang['INACTIVE_REASON_REMIND']; 2348 break; 2349 } 2350 2351 $users[] = $row; 2352 } 2353 2354 $sql = 'SELECT COUNT(user_id) AS user_count 2355 FROM ' . USERS_TABLE . ' 2356 WHERE user_type = ' . USER_INACTIVE . 2357 (($limit_days) ? " AND user_inactive_time >= $limit_days" : ''); 2358 $result = $db->sql_query($sql); 2359 $user_count = (int) $db->sql_fetchfield('user_count'); 2360 $db->sql_freeresult($result); 2361 2362 return; 2363 } 2364 2365 /** 2366 * Lists warned users 2367 */ 2368 function view_warned_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_warnings DESC') 2369 { 2370 global $db; 2371 2372 $sql = 'SELECT user_id, username, user_warnings, user_last_warning 2373 FROM ' . USERS_TABLE . ' 2374 WHERE user_warnings > 0 2375 ' . (($limit_days) ? "AND user_last_warning >= $limit_days" : '') . " 2376 ORDER BY $sort_by"; 2377 $result = $db->sql_query_limit($sql, $limit, $offset); 2378 $users = $db->sql_fetchrowset($result); 2379 $db->sql_freeresult($result); 2380 2381 $sql = 'SELECT count(user_id) AS user_count 2382 FROM ' . USERS_TABLE . ' 2383 WHERE user_warnings > 0 2384 ' . (($limit_days) ? "AND user_last_warning >= $limit_days" : ''); 2385 $result = $db->sql_query($sql); 2386 $user_count = (int) $db->sql_fetchfield('user_count'); 2387 $db->sql_freeresult($result); 2388 2389 return; 2390 } 2391 2392 /** 2393 * Get database size 2394 * Currently only mysql and mssql are supported 2395 */ 2396 function get_database_size() 2397 { 2398 global $db, $user, $table_prefix; 2399 2400 $database_size = false; 2401 2402 // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 2403 switch ($db->sql_layer) 2404 { 2405 case 'mysql': 2406 case 'mysql4': 2407 case 'mysqli': 2408 2409 $sql = 'SELECT VERSION() AS mysql_version'; 2410 $result = $db->sql_query($sql); 2411 $row = $db->sql_fetchrow($result); 2412 $db->sql_freeresult($result); 2413 2414 if ($row) 2415 { 2416 $version = $row['mysql_version']; 2417 2418 if (preg_match('#(3\.23|[45]\.)#', $version)) 2419 { 2420 $db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->dbname}`" : $db->dbname; 2421 2422 $sql = 'SHOW TABLE STATUS 2423 FROM ' . $db_name; 2424 $result = $db->sql_query($sql); 2425 2426 $database_size = 0; 2427 while ($row = $db->sql_fetchrow($result)) 2428 { 2429 if ((isset($row['Type']) && $row['Type'] != 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] == 'MyISAM' || $row['Engine'] == 'InnoDB'))) 2430 { 2431 if ($table_prefix != '') 2432 { 2433 if (strpos($row['Name'], $table_prefix) !== false) 2434 { 2435 $database_size += $row['Data_length'] + $row['Index_length']; 2436 } 2437 } 2438 else 2439 { 2440 $database_size += $row['Data_length'] + $row['Index_length']; 2441 } 2442 } 2443 } 2444 $db->sql_freeresult($result); 2445 } 2446 } 2447 2448 break; 2449 2450 case 'mssql': 2451 case 'mssql_odbc': 2452 2453 $sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize 2454 FROM sysfiles'; 2455 $result = $db->sql_query($sql); 2456 $database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false; 2457 $db->sql_freeresult($result); 2458 2459 break; 2460 2461 case 'postgres': 2462 2463 $sql = "SELECT proname 2464 FROM pg_proc 2465 WHERE proname = 'pg_database_size'"; 2466 $result = $db->sql_query($sql); 2467 $row = $db->sql_fetchrow($result); 2468 $db->sql_freeresult($result); 2469 2470 if ($row['proname'] == 'pg_database_size') 2471 { 2472 $sql = "SELECT oid 2473 FROM pg_database 2474 WHERE datname = '" . $db->dbname . "'"; 2475 $result = $db->sql_query($sql); 2476 $row = $db->sql_fetchrow($result); 2477 $db->sql_freeresult($result); 2478 2479 $oid = $row['oid']; 2480 2481 $sql = 'SELECT pg_database_size(' . $oid . ') as size'; 2482 $result = $db->sql_query($sql); 2483 $row = $db->sql_fetchrow($result); 2484 $db->sql_freeresult($result); 2485 2486 $database_size = $row['size']; 2487 } 2488 2489 break; 2490 } 2491 2492 if ($database_size !== false) 2493 { 2494 $database_size = ($database_size >= 1048576) ? sprintf('%.2f ' . $user->lang['MB'], ($database_size / 1048576)) : (($database_size >= 1024) ? sprintf('%.2f ' . $user->lang['KB'], ($database_size / 1024)) : sprintf('%.2f ' . $user->lang['BYTES'], $database_size)); 2495 } 2496 else 2497 { 2498 $database_size = $user->lang['NOT_AVAILABLE']; 2499 } 2500 2501 return $database_size; 2502 } 2503 2504 /** 2505 * Retrieve contents from remotely stored file 2506 */ 2507 function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 10) 2508 { 2509 global $user; 2510 2511 if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) 2512 { 2513 @fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n"); 2514 @fputs($fsock, "HOST: $host\r\n"); 2515 @fputs($fsock, "Connection: close\r\n\r\n"); 2516 2517 $file_info = ''; 2518 $get_info = false; 2519 2520 while (!@feof($fsock)) 2521 { 2522 if ($get_info) 2523 { 2524 $file_info .= @fread($fsock, 1024); 2525 } 2526 else 2527 { 2528 $line = @fgets($fsock, 1024); 2529 if ($line == "\r\n") 2530 { 2531 $get_info = true; 2532 } 2533 else if (strpos($line, '404 Not Found') !== false) 2534 { 2535 $errstr = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename; 2536 return false; 2537 } 2538 } 2539 } 2540 @fclose($fsock); 2541 } 2542 else 2543 { 2544 if ($errstr) 2545 { 2546 return false; 2547 } 2548 else 2549 { 2550 $errstr = 'fsock disabled'; 2551 return false; 2552 } 2553 } 2554 2555 return $file_info; 2556 } 2557 2558 /** 2559 * Tidy Warnings 2560 * Remove all warnings which have now expired from the database 2561 * The duration of a warning can be defined by the administrator 2562 * This only removes the warning and reduces the assosciated count, 2563 * it does not remove the user note recording the contents of the warning 2564 */ 2565 function tidy_warnings() 2566 { 2567 global $db, $config; 2568 2569 $expire_date = time() - ($config['warnings_expire_days'] * 86400); 2570 $warning_list = $user_list = array(); 2571 2572 $sql = 'SELECT * FROM ' . WARNINGS_TABLE . " 2573 WHERE warning_time < $expire_date"; 2574 $result = $db->sql_query($sql); 2575 2576 while ($row = $db->sql_fetchrow($result)) 2577 { 2578 $warning_list[] = $row['warning_id']; 2579 $user_list[$row['user_id']] = isset($user_list[$row['user_id']]) ? $user_list[$row['user_id']]++ : 1; 2580 } 2581 $db->sql_freeresult($result); 2582 2583 if (sizeof($warning_list)) 2584 { 2585 $db->sql_transaction('begin'); 2586 2587 $sql = 'DELETE FROM ' . WARNINGS_TABLE . ' 2588 WHERE ' . $db->sql_in_set('warning_id', $warning_list); 2589 $db->sql_query($sql); 2590 2591 foreach ($user_list as $user_id => $value) 2592 { 2593 $sql = 'UPDATE ' . USERS_TABLE . " SET user_warnings = user_warnings - $value 2594 WHERE user_id = $user_id"; 2595 $db->sql_query($sql); 2596 } 2597 2598 $db->sql_transaction('commit'); 2599 } 2600 2601 set_config('warnings_last_gc', time(), true); 2602 } 2603 2604 /** 2605 * Tidy database, doing some maintanance tasks 2606 */ 2607 function tidy_database() 2608 { 2609 global $db; 2610 2611 set_config('database_last_gc', time(), true); 2612 } 2613 2614 /** 2615 * Add permission language - this will make sure custom files will be included 2616 */ 2617 function add_permission_language() 2618 { 2619 global $user, $phpEx; 2620 2621 // First of all, our own file. 2622 $user->add_lang('acp/permissions_phpbb'); 2623 2624 $files_to_add = array(); 2625 2626 // Now search in acp and mods folder for permissions_ files. 2627 foreach (array('acp/', 'mods/') as $path) 2628 { 2629 $dh = opendir($user->lang_path . $path); 2630 2631 if ($dh !== false) 2632 { 2633 while (($file = readdir($dh)) !== false) 2634 { 2635 if (strpos($file, 'permissions_') === 0 && strpos($file, 'permissions_phpbb') === false && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx) 2636 { 2637 $files_to_add[] = $path . substr($file, 0, -(strlen($phpEx) + 1)); 2638 } 2639 } 2640 closedir($dh); 2641 } 2642 } 2643 2644 if (!sizeof($files_to_add)) 2645 { 2646 return false; 2647 } 2648 2649 $user->add_lang($files_to_add); 2650 return true; 2651 } 2652 2653 ?>
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 |