5
* @version $Id: functions_admin.php,v 1.254 2007/11/17 12:14:27 acydburn Exp $
6
* @copyright (c) 2005 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
14
if (!defined('IN_PHPBB'))
20
* Recalculate Binary Tree
21
function recalc_btree($sql_id, $sql_table, $module_class = '')
25
if (!$sql_id || !$sql_table)
30
$sql_where = ($module_class) ? " WHERE module_class = '" . $db->sql_escape($module_class) . "'" : '';
32
// Reset to minimum possible left and right id
33
$sql = "SELECT MIN(left_id) as min_left_id, MIN(right_id) as min_right_id
36
$result = $db->sql_query($sql);
37
$row = $db->sql_fetchrow($result);
38
$db->sql_freeresult($result);
40
$substract = (int) (min($row['min_left_id'], $row['min_right_id']) - 1);
44
$sql = "UPDATE $sql_table
45
SET left_id = left_id - $substract, right_id = right_id - $substract
50
$sql = "SELECT $sql_id, parent_id, left_id, right_id
53
ORDER BY left_id ASC, parent_id ASC, $sql_id ASC";
54
$f_result = $db->sql_query($sql);
56
while ($item_data = $db->sql_fetchrow($f_result))
58
if ($item_data['parent_id'])
60
$sql = "SELECT left_id, right_id
62
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
63
$sql_id = {$item_data['parent_id']}";
64
$result = $db->sql_query($sql);
66
if (!$row = $db->sql_fetchrow($result))
68
$sql = "UPDATE $sql_table SET parent_id = 0 WHERE $sql_id = " . $item_data[$sql_id];
71
$db->sql_freeresult($result);
73
$sql = "UPDATE $sql_table
74
SET left_id = left_id + 2, right_id = right_id + 2
75
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
76
left_id > {$row['right_id']}";
79
$sql = "UPDATE $sql_table
80
SET right_id = right_id + 2
81
$sql_where " . (($sql_where) ? 'AND' : 'WHERE') . "
82
{$row['left_id']} BETWEEN left_id AND right_id";
85
$item_data['left_id'] = $row['right_id'];
86
$item_data['right_id'] = $row['right_id'] + 1;
90
$sql = "SELECT MAX(right_id) AS right_id
93
$result = $db->sql_query($sql);
94
$row = $db->sql_fetchrow($result);
95
$db->sql_freeresult($result);
97
$item_data['left_id'] = $row['right_id'] + 1;
98
$item_data['right_id'] = $row['right_id'] + 2;
101
$sql = "UPDATE $sql_table
102
SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']}
103
WHERE $sql_id = " . $item_data[$sql_id];
104
$db->sql_query($sql);
106
$db->sql_freeresult($f_result);
111
* Simple version of jumpbox, just lists authed forums
113
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)
115
global $db, $user, $auth;
117
$acl = ($ignore_acl) ? '' : (($only_acl_post) ? 'f_post' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel'));
119
// This query is identical to the jumpbox one
120
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
121
FROM ' . FORUMS_TABLE . '
122
ORDER BY left_id ASC';
123
$result = $db->sql_query($sql, 600);
126
$padding_store = array('0' => '');
128
$forum_list = ($return_array) ? array() : '';
130
// Sometimes it could happen that forums will be displayed here not be displayed within the index page
131
// This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions.
132
// If this happens, the padding could be "broken"
134
while ($row = $db->sql_fetchrow($result))
136
if ($row['left_id'] < $right)
138
$padding .= ' ';
139
$padding_store[$row['parent_id']] = $padding;
141
else if ($row['left_id'] > $right + 1)
143
$padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : '';
146
$right = $row['right_id'];
149
if ($acl && !$auth->acl_gets($acl, $row['forum_id']))
152
if ($auth->acl_get('f_list', $row['forum_id']))
163
((is_array($ignore_id) && in_array($row['forum_id'], $ignore_id)) || $row['forum_id'] == $ignore_id)
165
// Non-postable forum with no subforums, don't display
166
($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat)
168
($row['forum_type'] != FORUM_POST && $ignore_nonpost)
176
// Include some more information...
177
$selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? true : false) : (($row['forum_id'] == $select_id) ? true : false);
178
$forum_list[$row['forum_id']] = array_merge(array('padding' => $padding, 'selected' => ($selected && !$disabled), 'disabled' => $disabled), $row);
182
$selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? ' selected="selected"' : '') : (($row['forum_id'] == $select_id) ? ' selected="selected"' : '');
183
$forum_list .= '<option value="' . $row['forum_id'] . '"' . (($disabled) ? ' disabled="disabled" class="disabled-option"' : $selected) . '>' . $padding . $row['forum_name'] . '</option>';
186
$db->sql_freeresult($result);
187
unset($padding_store);
193
* Generate size select options
195
function size_select_options($size_compare)
199
$size_types_text = array($user->lang['BYTES'], $user->lang['KB'], $user->lang['MB']);
200
$size_types = array('b', 'kb', 'mb');
202
$s_size_options = '';
204
for ($i = 0, $size = sizeof($size_types_text); $i < $size; $i++)
206
$selected = ($size_compare == $size_types[$i]) ? ' selected="selected"' : '';
207
$s_size_options .= '<option value="' . $size_types[$i] . '"' . $selected . '>' . $size_types_text[$i] . '</option>';
210
return $s_size_options;
214
* Generate list of groups (option fields without select)
216
* @param int $group_id The default group id to mark as selected
217
* @param array $exclude_ids The group ids to exclude from the list, false (default) if you whish to exclude no id
218
* @param int $manage_founder If set to false (default) all groups are returned, if 0 only those groups returned not being managed by founders only, if 1 only those groups returned managed by founders only.
220
* @return string The list of options.
222
function group_select_options($group_id, $exclude_ids = false, $manage_founder = false)
224
global $db, $user, $config;
226
$exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . $db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : '';
227
$sql_and = (!$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : '';
228
$sql_founder = ($manage_founder !== false) ? (($exclude_sql || $sql_and) ? ' AND ' : ' WHERE ') . 'group_founder_manage = ' . (int) $manage_founder : '';
230
$sql = 'SELECT group_id, group_name, group_type
231
FROM ' . GROUPS_TABLE . "
235
ORDER BY group_type DESC, group_name ASC";
236
$result = $db->sql_query($sql);
238
$s_group_options = '';
239
while ($row = $db->sql_fetchrow($result))
241
$selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : '';
242
$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>';
244
$db->sql_freeresult($result);
246
return $s_group_options;
250
* Obtain authed forums list
252
function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only = false, $no_cache = false)
257
if (!isset($forum_rows))
259
// This query is identical to the jumpbox one
260
$expire_time = ($no_cache) ? 0 : 600;
262
$sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
263
FROM ' . FORUMS_TABLE . '
264
ORDER BY left_id ASC';
265
$result = $db->sql_query($sql, $expire_time);
267
$forum_rows = array();
269
$right = $padding = 0;
270
$padding_store = array('0' => 0);
272
while ($row = $db->sql_fetchrow($result))
274
if ($row['left_id'] < $right)
277
$padding_store[$row['parent_id']] = $padding;
279
else if ($row['left_id'] > $right + 1)
281
// Ok, if the $padding_store for this parent is empty there is something wrong. For now we will skip over it.
282
// @todo digging deep to find out "how" this can happen.
283
$padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding;
286
$right = $row['right_id'];
287
$row['padding'] = $padding;
289
$forum_rows[] = $row;
291
$db->sql_freeresult($result);
292
unset($padding_store);
296
foreach ($forum_rows as $row)
298
if ($postable_only && $row['forum_type'] != FORUM_POST)
303
if ($acl_list == '' || ($acl_list != '' && $auth->acl_gets($acl_list, $row['forum_id'])))
305
$rowset[] = ($id_only) ? $row['forum_id'] : $row;
315
function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $include_forum = true)
322
$condition = 'f1.left_id BETWEEN f2.left_id AND f2.right_id';
326
$condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id';
330
$condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id OR f1.left_id BETWEEN f2.left_id AND f2.right_id';
337
FROM ' . FORUMS_TABLE . ' f1
338
LEFT JOIN ' . FORUMS_TABLE . " f2 ON ($condition)
339
WHERE f1.forum_id = $forum_id
340
ORDER BY f2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC');
341
$result = $db->sql_query($sql);
343
while ($row = $db->sql_fetchrow($result))
345
if (!$include_forum && $row['forum_id'] == $forum_id)
352
$db->sql_freeresult($result);
358
* Get physical file listing
360
function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png')
364
// Remove initial / if present
365
$rootdir = (substr($rootdir, 0, 1) == '/') ? substr($rootdir, 1) : $rootdir;
366
// Add closing / if not present
367
$rootdir = ($rootdir && substr($rootdir, -1) != '/') ? $rootdir . '/' : $rootdir;
369
// Remove initial / if present
370
$dir = (substr($dir, 0, 1) == '/') ? substr($dir, 1) : $dir;
371
// Add closing / if not present
372
$dir = ($dir && substr($dir, -1) != '/') ? $dir . '/' : $dir;
374
if (!is_dir($rootdir . $dir))
379
$dh = @opendir($rootdir . $dir);
386
while (($fname = readdir($dh)) !== false)
388
if (is_file("$rootdir$dir$fname"))
390
if (filesize("$rootdir$dir$fname") && preg_match('#\.' . $type . '$#i', $fname))
392
$matches[$dir][] = $fname;
395
else if ($fname[0] != '.' && is_dir("$rootdir$dir$fname"))
397
$matches += filelist($rootdir, "$dir$fname", $type);
408
function move_topics($topic_ids, $forum_id, $auto_sync = true)
412
if (empty($topic_ids))
417
$forum_ids = array($forum_id);
419
if (!is_array($topic_ids))
421
$topic_ids = array($topic_ids);
424
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
425
WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids) . '
426
AND forum_id = ' . $forum_id;
427
$db->sql_query($sql);
431
$sql = 'SELECT DISTINCT forum_id
432
FROM ' . TOPICS_TABLE . '
433
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
434
$result = $db->sql_query($sql);
436
while ($row = $db->sql_fetchrow($result))
438
$forum_ids[] = $row['forum_id'];
440
$db->sql_freeresult($result);
443
$table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE);
444
foreach ($table_ary as $table)
446
$sql = "UPDATE $table
447
SET forum_id = $forum_id
448
WHERE " . $db->sql_in_set('topic_id', $topic_ids);
449
$db->sql_query($sql);
455
sync('forum', 'forum_id', $forum_ids, true, true);
463
function move_posts($post_ids, $topic_id, $auto_sync = true)
467
if (!is_array($post_ids))
469
$post_ids = array($post_ids);
472
$forum_ids = array();
473
$topic_ids = array($topic_id);
475
$sql = 'SELECT DISTINCT topic_id, forum_id
476
FROM ' . POSTS_TABLE . '
477
WHERE ' . $db->sql_in_set('post_id', $post_ids);
478
$result = $db->sql_query($sql);
480
while ($row = $db->sql_fetchrow($result))
482
$forum_ids[] = $row['forum_id'];
483
$topic_ids[] = $row['topic_id'];
485
$db->sql_freeresult($result);
487
$sql = 'SELECT forum_id
488
FROM ' . TOPICS_TABLE . '
489
WHERE topic_id = ' . $topic_id;
490
$result = $db->sql_query($sql);
491
$forum_row = $db->sql_fetchrow($result);
492
$db->sql_freeresult($result);
496
trigger_error('NO_TOPIC');
499
$sql = 'UPDATE ' . POSTS_TABLE . '
500
SET forum_id = ' . $forum_row['forum_id'] . ", topic_id = $topic_id
501
WHERE " . $db->sql_in_set('post_id', $post_ids);
502
$db->sql_query($sql);
504
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . "
505
SET topic_id = $topic_id, in_message = 0
506
WHERE " . $db->sql_in_set('post_msg_id', $post_ids);
507
$db->sql_query($sql);
511
$forum_ids[] = $forum_row['forum_id'];
513
sync('topic_reported', 'topic_id', $topic_ids);
514
sync('topic_attachment', 'topic_id', $topic_ids);
515
sync('topic', 'topic_id', $topic_ids, true);
516
sync('forum', 'forum_id', $forum_ids, true, true);
519
// Update posted information
520
update_posted_info($topic_ids);
526
function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true)
530
$approved_topics = 0;
531
$forum_ids = $topic_ids = array();
533
if ($where_type === 'range')
535
$where_clause = $where_ids;
539
$where_ids = (is_array($where_ids)) ? array_unique($where_ids) : array($where_ids);
541
if (!sizeof($where_ids))
543
return array('topics' => 0, 'posts' => 0);
546
$where_clause = $db->sql_in_set($where_type, $where_ids);
549
// Making sure that delete_posts does not call delete_topics again...
551
'posts' => ($call_delete_posts) ? delete_posts($where_type, $where_ids, false, true, $post_count_sync, false) : 0,
554
$sql = 'SELECT topic_id, forum_id, topic_approved
555
FROM ' . TOPICS_TABLE . '
556
WHERE ' . $where_clause;
557
$result = $db->sql_query($sql);
559
while ($row = $db->sql_fetchrow($result))
561
$forum_ids[] = $row['forum_id'];
562
$topic_ids[] = $row['topic_id'];
564
if ($row['topic_approved'])
569
$db->sql_freeresult($result);
571
$return['topics'] = sizeof($topic_ids);
573
if (!sizeof($topic_ids))
578
$db->sql_transaction('begin');
580
$table_ary = array(TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE);
582
foreach ($table_ary as $table)
584
$sql = "DELETE FROM $table
585
WHERE " . $db->sql_in_set('topic_id', $topic_ids);
586
$db->sql_query($sql);
590
$moved_topic_ids = array();
592
// update the other forums
593
$sql = 'SELECT topic_id, forum_id
594
FROM ' . TOPICS_TABLE . '
595
WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids);
596
$result = $db->sql_query($sql);
598
while ($row = $db->sql_fetchrow($result))
600
$forum_ids[] = $row['forum_id'];
601
$moved_topic_ids[] = $row['topic_id'];
603
$db->sql_freeresult($result);
605
if (sizeof($moved_topic_ids))
607
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
608
WHERE ' . $db->sql_in_set('topic_id', $moved_topic_ids);
609
$db->sql_query($sql);
612
$db->sql_transaction('commit');
616
sync('forum', 'forum_id', array_unique($forum_ids), true, true);
617
sync('topic_reported', $where_type, $where_ids);
620
if ($approved_topics)
622
set_config('num_topics', $config['num_topics'] - $approved_topics, true);
631
function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true)
633
global $db, $config, $phpbb_root_path, $phpEx;
635
if ($where_type === 'range')
637
$where_clause = $where_ids;
641
if (is_array($where_ids))
643
$where_ids = array_unique($where_ids);
647
$where_ids = array($where_ids);
650
if (!sizeof($where_ids))
655
$where_clause = $db->sql_in_set($where_type, array_map('intval', $where_ids));
659
$post_ids = $topic_ids = $forum_ids = $post_counts = $remove_topics = array();
661
$sql = 'SELECT post_id, poster_id, post_approved, post_postcount, topic_id, forum_id
662
FROM ' . POSTS_TABLE . '
663
WHERE ' . $where_clause;
664
$result = $db->sql_query($sql);
666
while ($row = $db->sql_fetchrow($result))
668
$post_ids[] = $row['post_id'];
669
$poster_ids[] = $row['poster_id'];
670
$topic_ids[] = $row['topic_id'];
671
$forum_ids[] = $row['forum_id'];
673
if ($row['post_postcount'] && $post_count_sync)
675
$post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1;
678
if ($row['post_approved'])
683
$db->sql_freeresult($result);
685
if (!sizeof($post_ids))
690
$db->sql_transaction('begin');
692
$table_ary = array(POSTS_TABLE, REPORTS_TABLE);
694
foreach ($table_ary as $table)
696
$sql = "DELETE FROM $table
697
WHERE " . $db->sql_in_set('post_id', $post_ids);
698
$db->sql_query($sql);
702
// Adjust users post counts
703
if (sizeof($post_counts) && $post_count_sync)
705
foreach ($post_counts as $poster_id => $substract)
707
$sql = 'UPDATE ' . USERS_TABLE . '
709
WHERE user_id = ' . $poster_id . '
710
AND user_posts < ' . $substract;
711
$db->sql_query($sql);
712
$sql = 'UPDATE ' . USERS_TABLE . '
713
SET user_posts = user_posts - ' . $substract . '
714
WHERE user_id = ' . $poster_id . '
715
AND user_posts >= ' . $substract;
716
$db->sql_query($sql);
720
// Remove topics now having no posts?
721
if (sizeof($topic_ids))
723
$sql = 'SELECT topic_id
724
FROM ' . POSTS_TABLE . '
725
WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
727
$result = $db->sql_query($sql);
729
while ($row = $db->sql_fetchrow($result))
731
$remove_topics[] = $row['topic_id'];
733
$db->sql_freeresult($result);
735
// Actually, those not within remove_topics should be removed. ;)
736
$remove_topics = array_diff($topic_ids, $remove_topics);
739
// Remove the message from the search index
740
$search_type = basename($config['search_type']);
742
if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
744
trigger_error('NO_SUCH_SEARCH_MODULE');
747
include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx");
750
$search = new $search_type($error);
754
trigger_error($error);
757
$search->index_remove($post_ids, $poster_ids, $forum_ids);
759
delete_attachments('post', $post_ids, false);
761
$db->sql_transaction('commit');
763
// Resync topics_posted table
766
update_posted_info($topic_ids);
771
sync('topic_reported', 'topic_id', $topic_ids);
772
sync('topic', 'topic_id', $topic_ids, true);
773
sync('forum', 'forum_id', $forum_ids, true, true);
778
set_config('num_posts', $config['num_posts'] - $approved_posts, true);
781
// We actually remove topics now to not be inconsistent (the delete_topics function calls this function too)
782
if (sizeof($remove_topics) && $call_delete_topics)
784
delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false);
787
return sizeof($post_ids);
793
* @param string $mode can be: post|topic|attach|user
794
* @param mixed $ids can be: post_ids, topic_ids, attach_ids, user_ids
795
* @param bool $resync set this to false if you are deleting posts or topics
797
function delete_attachments($mode, $ids, $resync = true)
801
if (is_array($ids) && sizeof($ids))
803
$ids = array_unique($ids);
804
$ids = array_map('intval', $ids);
808
$ids = array((int) $ids);
816
$sql_id = ($mode == 'user') ? 'poster_id' : (($mode == 'post') ? 'post_msg_id' : (($mode == 'topic') ? 'topic_id' : 'attach_id'));
818
$post_ids = $topic_ids = $physical = array();
820
// Collect post and topics ids for later use
821
if ($mode == 'attach' || $mode == 'user' || ($mode == 'topic' && $resync))
823
$sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize
824
FROM ' . ATTACHMENTS_TABLE . '
825
WHERE ' . $db->sql_in_set($sql_id, $ids);
826
$result = $db->sql_query($sql);
828
while ($row = $db->sql_fetchrow($result))
830
$post_ids[] = $row['post_id'];
831
$topic_ids[] = $row['topic_id'];
832
$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
834
$db->sql_freeresult($result);
839
$sql = 'SELECT topic_id, physical_filename, thumbnail, filesize
840
FROM ' . ATTACHMENTS_TABLE . '
841
WHERE ' . $db->sql_in_set('post_msg_id', $ids) . '
843
$result = $db->sql_query($sql);
845
while ($row = $db->sql_fetchrow($result))
847
$topic_ids[] = $row['topic_id'];
848
$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
850
$db->sql_freeresult($result);
853
// Delete attachments
854
$sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
855
WHERE ' . $db->sql_in_set($sql_id, $ids);
856
$db->sql_query($sql);
857
$num_deleted = $db->sql_affectedrows();
864
// Delete attachments from filesystem
865
$space_removed = $files_removed = 0;
866
foreach ($physical as $file_ary)
868
if (phpbb_unlink($file_ary['filename'], 'file', true))
870
$space_removed += $file_ary['filesize'];
874
if ($file_ary['thumbnail'])
876
phpbb_unlink($file_ary['filename'], 'thumbnail', true);
879
set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true);
880
set_config('num_files', $config['num_files'] - $files_removed, true);
882
if ($mode == 'topic' && !$resync)
893
$post_ids = array_unique($post_ids);
894
$topic_ids = array_unique($topic_ids);
896
// Update post indicators
897
if (sizeof($post_ids))
899
if ($mode == 'post' || $mode == 'topic')
901
$sql = 'UPDATE ' . POSTS_TABLE . '
902
SET post_attachment = 0
903
WHERE ' . $db->sql_in_set('post_id', $post_ids);
904
$db->sql_query($sql);
907
if ($mode == 'user' || $mode == 'attach')
909
$remaining = array();
911
$sql = 'SELECT post_msg_id
912
FROM ' . ATTACHMENTS_TABLE . '
913
WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
915
$result = $db->sql_query($sql);
917
while ($row = $db->sql_fetchrow($result))
919
$remaining[] = $row['post_msg_id'];
921
$db->sql_freeresult($result);
923
$unset_ids = array_diff($post_ids, $remaining);
925
if (sizeof($unset_ids))
927
$sql = 'UPDATE ' . POSTS_TABLE . '
928
SET post_attachment = 0
929
WHERE ' . $db->sql_in_set('post_id', $unset_ids);
930
$db->sql_query($sql);
933
$remaining = array();
935
$sql = 'SELECT post_msg_id
936
FROM ' . ATTACHMENTS_TABLE . '
937
WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
939
$result = $db->sql_query($sql);
941
while ($row = $db->sql_fetchrow($result))
943
$remaining[] = $row['post_msg_id'];
945
$db->sql_freeresult($result);
947
$unset_ids = array_diff($post_ids, $remaining);
949
if (sizeof($unset_ids))
951
$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
952
SET message_attachment = 0
953
WHERE ' . $db->sql_in_set('msg_id', $unset_ids);
954
$db->sql_query($sql);
959
if (sizeof($topic_ids))
961
// Update topic indicator
962
if ($mode == 'topic')
964
$sql = 'UPDATE ' . TOPICS_TABLE . '
965
SET topic_attachment = 0
966
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
967
$db->sql_query($sql);
970
if ($mode == 'post' || $mode == 'user' || $mode == 'attach')
972
$remaining = array();
974
$sql = 'SELECT topic_id
975
FROM ' . ATTACHMENTS_TABLE . '
976
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
977
$result = $db->sql_query($sql);
979
while ($row = $db->sql_fetchrow($result))
981
$remaining[] = $row['topic_id'];
983
$db->sql_freeresult($result);
985
$unset_ids = array_diff($topic_ids, $remaining);
987
if (sizeof($unset_ids))
989
$sql = 'UPDATE ' . TOPICS_TABLE . '
990
SET topic_attachment = 0
991
WHERE ' . $db->sql_in_set('topic_id', $unset_ids);
992
$db->sql_query($sql);
1001
* Remove topic shadows
1003
function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true)
1005
$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 : '');
1007
switch ($db->sql_layer)
1012
FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2
1013
WHERE t.topic_moved_id = t2.topic_id
1014
AND t.topic_time < ' . (time() - $max_age)
1016
$db->sql_query($sql);
1020
$sql = 'SELECT t.topic_id
1021
FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2
1022
WHERE t.topic_moved_id = t2.topic_id
1023
AND t.topic_time < ' . (time() - $max_age)
1025
$result = $db->sql_query($sql);
1027
$topic_ids = array();
1028
while ($row = $db->sql_fetchrow($result))
1030
$topic_ids[] = $row['topic_id'];
1032
$db->sql_freeresult($result);
1034
if (sizeof($topic_ids))
1036
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
1037
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
1038
$db->sql_query($sql);
1045
$where_type = ($forum_id) ? 'forum_id' : '';
1046
sync('forum', $where_type, $forum_id, true, true);
1051
* Update/Sync posted information for topics
1053
function update_posted_info(&$topic_ids)
1055
global $db, $config;
1057
if (empty($topic_ids) || !$config['load_db_track'])
1062
// First of all, let us remove any posted information for these topics
1063
$sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . '
1064
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
1065
$db->sql_query($sql);
1067
// Now, let us collect the user/topic combos for rebuilding the information
1068
$sql = 'SELECT poster_id, topic_id
1069
FROM ' . POSTS_TABLE . '
1070
WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
1071
AND poster_id <> ' . ANONYMOUS . '
1072
GROUP BY poster_id, topic_id';
1073
$result = $db->sql_query($sql);
1076
while ($row = $db->sql_fetchrow($result))
1078
// Add as key to make them unique (grouping by) and circumvent empty keys on array_unique
1079
$posted[$row['poster_id']][] = $row['topic_id'];
1081
$db->sql_freeresult($result);
1083
// Now add the information...
1085
foreach ($posted as $user_id => $topic_row)
1087
foreach ($topic_row as $topic_id)
1090
'user_id' => (int) $user_id,
1091
'topic_id' => (int) $topic_id,
1092
'topic_posted' => 1,
1098
$db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
1102
* Delete attached file
1104
function phpbb_unlink($filename, $mode = 'file', $entry_removed = false)
1106
global $db, $phpbb_root_path, $config;
1108
// Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself.
1109
$sql = 'SELECT COUNT(attach_id) AS num_entries
1110
FROM ' . ATTACHMENTS_TABLE . "
1111
WHERE physical_filename = '" . $db->sql_escape(basename($filename)) . "'";
1112
$result = $db->sql_query($sql);
1113
$num_entries = (int) $db->sql_fetchfield('num_entries');
1114
$db->sql_freeresult($result);
1116
// Do not remove file if at least one additional entry with the same name exist.
1117
if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1))
1122
$filename = ($mode == 'thumbnail') ? 'thumb_' . basename($filename) : basename($filename);
1123
return @unlink($phpbb_root_path . $config['upload_path'] . '/' . $filename);
1127
* All-encompasing sync function
1131
* sync('topic', 'topic_id', 123); // resync topic #123
1132
* sync('topic', 'forum_id', array(2, 3)); // resync topics from forum #2 and #3
1133
* sync('topic'); // resync all topics
1134
* sync('topic', 'range', 'topic_id BETWEEN 1 AND 60'); // resync a range of topics/forums (only available for 'topic' and 'forum' modes)
1138
* - forum Resync complete forum
1139
* - topic Resync topics
1140
* - topic_moved Removes topic shadows that would be in the same forum as the topic they link to
1141
* - topic_approved Resyncs the topic_approved flag according to the status of the first post
1142
* - post_reported Resyncs the post_reported flag, relying on actual reports
1143
* - topic_reported Resyncs the topic_reported flag, relying on post_reported flags
1144
* - post_attachement Same as post_reported, but with attachment flags
1145
* - topic_attachement Same as topic_reported, but with attachment flags
1147
function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sync_extra = false)
1151
if (is_array($where_ids))
1153
$where_ids = array_unique($where_ids);
1154
$where_ids = array_map('intval', $where_ids);
1156
else if ($where_type != 'range')
1158
$where_ids = ($where_ids) ? array((int) $where_ids) : array();
1161
if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_approved' || $mode == 'topic_reported' || $mode == 'post_reported')
1166
$where_sql_and = 'WHERE';
1168
else if ($where_type == 'range')
1170
// Only check a range of topics/forums. For instance: 'topic_id BETWEEN 1 AND 60'
1171
$where_sql = 'WHERE (' . $mode[0] . ".$where_ids)";
1172
$where_sql_and = $where_sql . "\n\tAND";
1176
// Do not sync the "global forum"
1177
$where_ids = array_diff($where_ids, array(0));
1179
if (!sizeof($where_ids))
1181
// Empty array with IDs. This means that we don't have any work to do. Just return.
1185
// Limit the topics/forums we are syncing, use specific topic/forum IDs.
1186
// $where_type contains the field for the where clause (forum_id, topic_id)
1187
$where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids);
1188
$where_sql_and = $where_sql . "\n\tAND";
1193
if (!sizeof($where_ids))
1198
// $where_type contains the field for the where clause (forum_id, topic_id)
1199
$where_sql = 'WHERE ' . $db->sql_in_set($mode[0] . '.' . $where_type, $where_ids);
1200
$where_sql_and = $where_sql . "\n\tAND";
1206
switch ($db->sql_layer)
1210
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
1211
USING ' . TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2
1212
WHERE t1.topic_moved_id = t2.topic_id
1213
AND t1.forum_id = t2.forum_id";
1214
$db->sql_query($sql);
1218
$sql = 'SELECT t1.topic_id
1219
FROM ' .TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2
1220
WHERE t1.topic_moved_id = t2.topic_id
1221
AND t1.forum_id = t2.forum_id";
1222
$result = $db->sql_query($sql);
1224
$topic_id_ary = array();
1225
while ($row = $db->sql_fetchrow($result))
1227
$topic_id_ary[] = $row['topic_id'];
1229
$db->sql_freeresult($result);
1231
if (!sizeof($topic_id_ary))
1236
$sql = 'DELETE FROM ' . TOPICS_TABLE . '
1237
WHERE ' . $db->sql_in_set('topic_id', $topic_id_ary);
1238
$db->sql_query($sql);
1244
case 'topic_approved':
1245
switch ($db->sql_layer)
1249
$sql = 'UPDATE ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
1250
SET t.topic_approved = p.post_approved
1251
$where_sql_and t.topic_first_post_id = p.post_id";
1252
$db->sql_query($sql);
1256
$sql = 'SELECT t.topic_id, p.post_approved
1257
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
1258
$where_sql_and p.post_id = t.topic_first_post_id
1259
AND p.post_approved <> t.topic_approved";
1260
$result = $db->sql_query($sql);
1262
$topic_ids = array();
1263
while ($row = $db->sql_fetchrow($result))
1265
$topic_ids[] = $row['topic_id'];
1267
$db->sql_freeresult($result);
1269
if (!sizeof($topic_ids))
1274
$sql = 'UPDATE ' . TOPICS_TABLE . '
1275
SET topic_approved = 1 - topic_approved
1276
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
1277
$db->sql_query($sql);
1282
case 'post_reported':
1283
$post_ids = $post_reported = array();
1285
$sql = 'SELECT p.post_id, p.post_reported
1286
FROM ' . POSTS_TABLE . " p
1288
GROUP BY p.post_id, p.post_reported";
1289
$result = $db->sql_query($sql);
1291
while ($row = $db->sql_fetchrow($result))
1293
$post_ids[$row['post_id']] = $row['post_id'];
1294
if ($row['post_reported'])
1296
$post_reported[$row['post_id']] = 1;
1299
$db->sql_freeresult($result);
1301
$sql = 'SELECT DISTINCT(post_id)
1302
FROM ' . REPORTS_TABLE . '
1303
WHERE ' . $db->sql_in_set('post_id', $post_ids) . '
1304
AND report_closed = 0';
1305
$result = $db->sql_query($sql);
1307
$post_ids = array();
1308
while ($row = $db->sql_fetchrow($result))
1310
if (!isset($post_reported[$row['post_id']]))
1312
$post_ids[] = $row['post_id'];
1316
unset($post_reported[$row['post_id']]);
1319
$db->sql_freeresult($result);
1321
// $post_reported should be empty by now, if it's not it contains
1322
// posts that are falsely flagged as reported
1323
foreach ($post_reported as $post_id => $void)
1325
$post_ids[] = $post_id;
1328
if (sizeof($post_ids))
1330
$sql = 'UPDATE ' . POSTS_TABLE . '
1331
SET post_reported = 1 - post_reported
1332
WHERE ' . $db->sql_in_set('post_id', $post_ids);
1333
$db->sql_query($sql);
1337
case 'topic_reported':
1340
sync('post_reported', $where_type, $where_ids);
1343
$topic_ids = $topic_reported = array();
1345
$sql = 'SELECT DISTINCT(t.topic_id)
1346
FROM ' . POSTS_TABLE . " t
1347
$where_sql_and t.post_reported = 1";
1348
$result = $db->sql_query($sql);
1350
while ($row = $db->sql_fetchrow($result))
1352
$topic_reported[$row['topic_id']] = 1;
1354
$db->sql_freeresult($result);
1356
$sql = 'SELECT t.topic_id, t.topic_reported
1357
FROM ' . TOPICS_TABLE . " t
1359
$result = $db->sql_query($sql);
1361
while ($row = $db->sql_fetchrow($result))
1363
if ($row['topic_reported'] ^ isset($topic_reported[$row['topic_id']]))
1365
$topic_ids[] = $row['topic_id'];
1368
$db->sql_freeresult($result);
1370
if (sizeof($topic_ids))
1372
$sql = 'UPDATE ' . TOPICS_TABLE . '
1373
SET topic_reported = 1 - topic_reported
1374
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
1375
$db->sql_query($sql);
1379
case 'post_attachment':
1380
$post_ids = $post_attachment = array();
1382
$sql = 'SELECT p.post_id, p.post_attachment
1383
FROM ' . POSTS_TABLE . " p
1385
GROUP BY p.post_id, p.post_attachment";
1386
$result = $db->sql_query($sql);
1388
while ($row = $db->sql_fetchrow($result))
1390
$post_ids[$row['post_id']] = $row['post_id'];
1391
if ($row['post_attachment'])
1393
$post_attachment[$row['post_id']] = 1;
1396
$db->sql_freeresult($result);
1398
$sql = 'SELECT DISTINCT(post_msg_id)
1399
FROM ' . ATTACHMENTS_TABLE . '
1400
WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
1401
AND in_message = 0';
1402
$result = $db->sql_query($sql);
1404
$post_ids = array();
1405
while ($row = $db->sql_fetchrow($result))
1407
if (!isset($post_attachment[$row['post_msg_id']]))
1409
$post_ids[] = $row['post_msg_id'];
1413
unset($post_attachment[$row['post_msg_id']]);
1416
$db->sql_freeresult($result);
1418
// $post_attachment should be empty by now, if it's not it contains
1419
// posts that are falsely flagged as having attachments
1420
foreach ($post_attachment as $post_id => $void)
1422
$post_ids[] = $post_id;
1425
if (sizeof($post_ids))
1427
$sql = 'UPDATE ' . POSTS_TABLE . '
1428
SET post_attachment = 1 - post_attachment
1429
WHERE ' . $db->sql_in_set('post_id', $post_ids);
1430
$db->sql_query($sql);
1434
case 'topic_attachment':
1437
sync('post_attachment', $where_type, $where_ids);
1440
$topic_ids = $topic_attachment = array();
1442
$sql = 'SELECT DISTINCT(t.topic_id)
1443
FROM ' . POSTS_TABLE . " t
1444
$where_sql_and t.post_attachment = 1";
1445
$result = $db->sql_query($sql);
1447
while ($row = $db->sql_fetchrow($result))
1449
$topic_attachment[$row['topic_id']] = 1;
1451
$db->sql_freeresult($result);
1453
$sql = 'SELECT t.topic_id, t.topic_attachment
1454
FROM ' . TOPICS_TABLE . " t
1456
$result = $db->sql_query($sql);
1458
while ($row = $db->sql_fetchrow($result))
1460
if ($row['topic_attachment'] ^ isset($topic_attachment[$row['topic_id']]))
1462
$topic_ids[] = $row['topic_id'];
1465
$db->sql_freeresult($result);
1467
if (sizeof($topic_ids))
1469
$sql = 'UPDATE ' . TOPICS_TABLE . '
1470
SET topic_attachment = 1 - topic_attachment
1471
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
1472
$db->sql_query($sql);
1478
// 1: Get the list of all forums
1480
FROM ' . FORUMS_TABLE . " f
1482
$result = $db->sql_query($sql);
1484
$forum_data = $forum_ids = $post_ids = $last_post_id = $post_info = array();
1485
while ($row = $db->sql_fetchrow($result))
1487
if ($row['forum_type'] == FORUM_LINK)
1492
$forum_id = (int) $row['forum_id'];
1493
$forum_ids[$forum_id] = $forum_id;
1495
$forum_data[$forum_id] = $row;
1498
$forum_data[$forum_id]['posts'] = 0;
1499
$forum_data[$forum_id]['topics'] = 0;
1500
$forum_data[$forum_id]['topics_real'] = 0;
1502
$forum_data[$forum_id]['last_post_id'] = 0;
1503
$forum_data[$forum_id]['last_post_subject'] = '';
1504
$forum_data[$forum_id]['last_post_time'] = 0;
1505
$forum_data[$forum_id]['last_poster_id'] = 0;
1506
$forum_data[$forum_id]['last_poster_name'] = '';
1507
$forum_data[$forum_id]['last_poster_colour'] = '';
1509
$db->sql_freeresult($result);
1511
if (!sizeof($forum_ids))
1516
$forum_ids = array_values($forum_ids);
1518
// 2: Get topic counts for each forum (optional)
1521
$sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics
1522
FROM ' . TOPICS_TABLE . '
1523
WHERE ' . $db->sql_in_set('forum_id', $forum_ids) . '
1524
GROUP BY forum_id, topic_approved';
1525
$result = $db->sql_query($sql);
1527
while ($row = $db->sql_fetchrow($result))
1529
$forum_id = (int) $row['forum_id'];
1530
$forum_data[$forum_id]['topics_real'] += $row['forum_topics'];
1532
if ($row['topic_approved'])
1534
$forum_data[$forum_id]['topics'] = $row['forum_topics'];
1537
$db->sql_freeresult($result);
1540
// 3: Get post count for each forum (optional)
1543
if (sizeof($forum_ids) == 1)
1545
$sql = 'SELECT SUM(t.topic_replies + 1) AS forum_posts
1546
FROM ' . TOPICS_TABLE . ' t
1547
WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . '
1548
AND t.topic_approved = 1';
1552
$sql = 'SELECT t.forum_id, SUM(t.topic_replies + 1) AS forum_posts
1553
FROM ' . TOPICS_TABLE . ' t
1554
WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . '
1555
AND t.topic_approved = 1
1556
GROUP BY t.forum_id';
1559
$result = $db->sql_query($sql);
1561
while ($row = $db->sql_fetchrow($result))
1563
$forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id'];
1565
$forum_data[$forum_id]['posts'] = (int) $row['forum_posts'];
1567
$db->sql_freeresult($result);
1570
// 4: Get last_post_id for each forum
1571
if (sizeof($forum_ids) == 1)
1573
$sql = 'SELECT MAX(t.topic_last_post_id) as last_post_id
1574
FROM ' . TOPICS_TABLE . ' t
1575
WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . '
1576
AND t.topic_approved = 1';
1580
$sql = 'SELECT t.forum_id, MAX(t.topic_last_post_id) as last_post_id
1581
FROM ' . TOPICS_TABLE . ' t
1582
WHERE ' . $db->sql_in_set('t.forum_id', $forum_ids) . '
1583
AND t.topic_approved = 1
1584
GROUP BY t.forum_id';
1587
$result = $db->sql_query($sql);
1589
while ($row = $db->sql_fetchrow($result))
1591
$forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id'];
1593
$forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id'];
1595
$post_ids[] = $row['last_post_id'];
1597
$db->sql_freeresult($result);
1599
// 5: Retrieve last_post infos
1600
if (sizeof($post_ids))
1602
$sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour
1603
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
1604
WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '
1605
AND p.poster_id = u.user_id';
1606
$result = $db->sql_query($sql);
1608
while ($row = $db->sql_fetchrow($result))
1610
$post_info[$row['post_id']] = $row;
1612
$db->sql_freeresult($result);
1614
foreach ($forum_data as $forum_id => $data)
1616
if ($data['last_post_id'])
1618
if (isset($post_info[$data['last_post_id']]))
1620
$forum_data[$forum_id]['last_post_subject'] = $post_info[$data['last_post_id']]['post_subject'];
1621
$forum_data[$forum_id]['last_post_time'] = $post_info[$data['last_post_id']]['post_time'];
1622
$forum_data[$forum_id]['last_poster_id'] = $post_info[$data['last_post_id']]['poster_id'];
1623
$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'];
1624
$forum_data[$forum_id]['last_poster_colour'] = $post_info[$data['last_post_id']]['user_colour'];
1628
// For some reason we did not find the post in the db
1629
$forum_data[$forum_id]['last_post_id'] = 0;
1630
$forum_data[$forum_id]['last_post_subject'] = '';
1631
$forum_data[$forum_id]['last_post_time'] = 0;
1632
$forum_data[$forum_id]['last_poster_id'] = 0;
1633
$forum_data[$forum_id]['last_poster_name'] = '';
1634
$forum_data[$forum_id]['last_poster_colour'] = '';
1641
// 6: Now do that thing
1642
$fieldnames = array('last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour');
1646
array_push($fieldnames, 'posts', 'topics', 'topics_real');
1649
foreach ($forum_data as $forum_id => $row)
1653
foreach ($fieldnames as $fieldname)
1655
if ($row['forum_' . $fieldname] != $row[$fieldname])
1657
if (preg_match('#(name|colour|subject)$#', $fieldname))
1659
$sql_ary['forum_' . $fieldname] = (string) $row[$fieldname];
1663
$sql_ary['forum_' . $fieldname] = (int) $row[$fieldname];
1668
if (sizeof($sql_ary))
1670
$sql = 'UPDATE ' . FORUMS_TABLE . '
1671
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
1672
WHERE forum_id = ' . $forum_id;
1673
$db->sql_query($sql);
1679
$topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array();
1681
$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
1682
FROM ' . TOPICS_TABLE . " t
1684
$result = $db->sql_query($sql);
1686
while ($row = $db->sql_fetchrow($result))
1688
if ($row['topic_moved_id'])
1690
$moved_topics[] = $row['topic_id'];
1694
$topic_id = (int) $row['topic_id'];
1695
$topic_data[$topic_id] = $row;
1696
$topic_data[$topic_id]['replies_real'] = -1;
1697
$topic_data[$topic_id]['replies'] = 0;
1698
$topic_data[$topic_id]['first_post_id'] = 0;
1699
$topic_data[$topic_id]['last_post_id'] = 0;
1700
unset($topic_data[$topic_id]['topic_id']);
1702
// This array holds all topic_ids
1703
$delete_topics[$topic_id] = '';
1707
$topic_data[$topic_id]['reported'] = 0;
1708
$topic_data[$topic_id]['attachment'] = 0;
1711
$db->sql_freeresult($result);
1713
// Use "t" as table alias because of the $where_sql clause
1714
// NOTE: 't.post_approved' in the GROUP BY is causing a major slowdown.
1715
$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
1716
FROM ' . POSTS_TABLE . " t
1718
GROUP BY t.topic_id, t.post_approved";
1719
$result = $db->sql_query($sql);
1721
while ($row = $db->sql_fetchrow($result))
1723
$topic_id = (int) $row['topic_id'];
1725
$row['first_post_id'] = (int) $row['first_post_id'];
1726
$row['last_post_id'] = (int) $row['last_post_id'];
1728
if (!isset($topic_data[$topic_id]))
1730
// Hey, these posts come from a topic that does not exist
1731
$delete_posts[$topic_id] = '';
1735
// Unset the corresponding entry in $delete_topics
1736
// When we'll be done, only topics with no posts will remain
1737
unset($delete_topics[$topic_id]);
1739
$topic_data[$topic_id]['replies_real'] += $row['total_posts'];
1740
$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']);
1742
if ($row['post_approved'] || !$topic_data[$topic_id]['last_post_id'])
1744
$topic_data[$topic_id]['replies'] = $row['total_posts'] - 1;
1745
$topic_data[$topic_id]['last_post_id'] = $row['last_post_id'];
1749
$db->sql_freeresult($result);
1751
foreach ($topic_data as $topic_id => $row)
1753
$post_ids[] = $row['first_post_id'];
1754
if ($row['first_post_id'] != $row['last_post_id'])
1756
$post_ids[] = $row['last_post_id'];
1760
// Now we delete empty topics and orphan posts
1761
if (sizeof($delete_posts))
1763
delete_posts('topic_id', array_keys($delete_posts), false);
1764
unset($delete_posts);
1767
if (!sizeof($topic_data))
1769
// If we get there, topic ids were invalid or topics did not contain any posts
1770
delete_topics($where_type, $where_ids, true);
1774
if (sizeof($delete_topics))
1776
$delete_topic_ids = array();
1777
foreach ($delete_topics as $topic_id => $void)
1779
unset($topic_data[$topic_id]);
1780
$delete_topic_ids[] = $topic_id;
1783
delete_topics('topic_id', $delete_topic_ids, false);
1784
unset($delete_topics, $delete_topic_ids);
1787
$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
1788
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
1789
WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '
1790
AND u.user_id = p.poster_id';
1791
$result = $db->sql_query($sql);
1793
$post_ids = array();
1794
while ($row = $db->sql_fetchrow($result))
1796
$topic_id = intval($row['topic_id']);
1798
if ($row['post_id'] == $topic_data[$topic_id]['first_post_id'])
1800
if ($topic_data[$topic_id]['topic_approved'] != $row['post_approved'])
1802
$approved_unapproved_ids[] = $topic_id;
1804
$topic_data[$topic_id]['time'] = $row['post_time'];
1805
$topic_data[$topic_id]['poster'] = $row['poster_id'];
1806
$topic_data[$topic_id]['first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
1807
$topic_data[$topic_id]['first_poster_colour'] = $row['user_colour'];
1810
if ($row['post_id'] == $topic_data[$topic_id]['last_post_id'])
1812
$topic_data[$topic_id]['last_poster_id'] = $row['poster_id'];
1813
$topic_data[$topic_id]['last_post_subject'] = $row['post_subject'];
1814
$topic_data[$topic_id]['last_post_time'] = $row['post_time'];
1815
$topic_data[$topic_id]['last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
1816
$topic_data[$topic_id]['last_poster_colour'] = $row['user_colour'];
1819
$db->sql_freeresult($result);
1821
// Make sure shadow topics do link to existing topics
1822
if (sizeof($moved_topics))
1824
$delete_topics = array();
1826
$sql = 'SELECT t1.topic_id, t1.topic_moved_id
1827
FROM ' . TOPICS_TABLE . ' t1
1828
LEFT JOIN ' . TOPICS_TABLE . ' t2 ON (t2.topic_id = t1.topic_moved_id)
1829
WHERE ' . $db->sql_in_set('t1.topic_id', $moved_topics) . '
1830
AND t2.topic_id IS NULL';
1831
$result = $db->sql_query($sql);
1833
while ($row = $db->sql_fetchrow($result))
1835
$delete_topics[] = $row['topic_id'];
1837
$db->sql_freeresult($result);
1839
if (sizeof($delete_topics))
1841
delete_topics('topic_id', $delete_topics, false);
1843
unset($delete_topics);
1845
// Make sure shadow topics having no last post data being updated (this only rarely happens...)
1846
$sql = 'SELECT topic_id, topic_moved_id, topic_last_post_id, topic_first_post_id
1847
FROM ' . TOPICS_TABLE . '
1848
WHERE ' . $db->sql_in_set('topic_id', $moved_topics) . '
1849
AND topic_last_post_time = 0';
1850
$result = $db->sql_query($sql);
1852
$shadow_topic_data = $post_ids = array();
1853
while ($row = $db->sql_fetchrow($result))
1855
$shadow_topic_data[$row['topic_moved_id']] = $row;
1856
$post_ids[] = $row['topic_last_post_id'];
1857
$post_ids[] = $row['topic_first_post_id'];
1859
$db->sql_freeresult($result);
1861
$sync_shadow_topics = array();
1862
if (sizeof($post_ids))
1864
$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
1865
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
1866
WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . '
1867
AND u.user_id = p.poster_id';
1868
$result = $db->sql_query($sql);
1870
$post_ids = array();
1871
while ($row = $db->sql_fetchrow($result))
1873
$topic_id = (int) $row['topic_id'];
1875
// Ok, there should be a shadow topic. If there isn't, then there's something wrong with the db.
1876
// However, there's not much we can do about it.
1877
if (!empty($shadow_topic_data[$topic_id]))
1879
if ($row['post_id'] == $shadow_topic_data[$topic_id]['topic_first_post_id'])
1881
$orig_topic_id = $shadow_topic_data[$topic_id]['topic_id'];
1883
if (!isset($sync_shadow_topics[$orig_topic_id]))
1885
$sync_shadow_topics[$orig_topic_id] = array();
1888
$sync_shadow_topics[$orig_topic_id]['topic_time'] = $row['post_time'];
1889
$sync_shadow_topics[$orig_topic_id]['topic_poster'] = $row['poster_id'];
1890
$sync_shadow_topics[$orig_topic_id]['topic_first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
1891
$sync_shadow_topics[$orig_topic_id]['topic_first_poster_colour'] = $row['user_colour'];
1894
if ($row['post_id'] == $shadow_topic_data[$topic_id]['topic_last_post_id'])
1896
$orig_topic_id = $shadow_topic_data[$topic_id]['topic_id'];
1898
if (!isset($sync_shadow_topics[$orig_topic_id]))
1900
$sync_shadow_topics[$orig_topic_id] = array();
1903
$sync_shadow_topics[$orig_topic_id]['topic_last_poster_id'] = $row['poster_id'];
1904
$sync_shadow_topics[$orig_topic_id]['topic_last_post_subject'] = $row['post_subject'];
1905
$sync_shadow_topics[$orig_topic_id]['topic_last_post_time'] = $row['post_time'];
1906
$sync_shadow_topics[$orig_topic_id]['topic_last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username'];
1907
$sync_shadow_topics[$orig_topic_id]['topic_last_poster_colour'] = $row['user_colour'];
1911
$db->sql_freeresult($result);
1913
$shadow_topic_data = array();
1915
// Update the information we collected
1916
if (sizeof($sync_shadow_topics))
1918
foreach ($sync_shadow_topics as $sync_topic_id => $sql_ary)
1920
$sql = 'UPDATE ' . TOPICS_TABLE . '
1921
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
1922
WHERE topic_id = ' . $sync_topic_id;
1923
$db->sql_query($sql);
1928
unset($sync_shadow_topics, $shadow_topic_data);
1931
// approved becomes unapproved, and vice-versa
1932
if (sizeof($approved_unapproved_ids))
1934
$sql = 'UPDATE ' . TOPICS_TABLE . '
1935
SET topic_approved = 1 - topic_approved
1936
WHERE ' . $db->sql_in_set('topic_id', $approved_unapproved_ids);
1937
$db->sql_query($sql);
1939
unset($approved_unapproved_ids);
1941
// These are fields that will be synchronised
1942
$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');
1946
// This routine assumes that post_reported values are correct
1947
// if they are not, use sync('post_reported') first
1948
$sql = 'SELECT t.topic_id, p.post_id
1949
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
1950
$where_sql_and p.topic_id = t.topic_id
1951
AND p.post_reported = 1
1952
GROUP BY t.topic_id, p.post_id";
1953
$result = $db->sql_query($sql);
1955
$fieldnames[] = 'reported';
1956
while ($row = $db->sql_fetchrow($result))
1958
$topic_data[intval($row['topic_id'])]['reported'] = 1;
1960
$db->sql_freeresult($result);
1962
// This routine assumes that post_attachment values are correct
1963
// if they are not, use sync('post_attachment') first
1964
$sql = 'SELECT t.topic_id, p.post_id
1965
FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p
1966
$where_sql_and p.topic_id = t.topic_id
1967
AND p.post_attachment = 1
1968
GROUP BY t.topic_id, p.post_id";
1969
$result = $db->sql_query($sql);
1971
$fieldnames[] = 'attachment';
1972
while ($row = $db->sql_fetchrow($result))
1974
$topic_data[intval($row['topic_id'])]['attachment'] = 1;
1976
$db->sql_freeresult($result);
1979
foreach ($topic_data as $topic_id => $row)
1983
foreach ($fieldnames as $fieldname)
1985
if (isset($row[$fieldname]) && isset($row['topic_' . $fieldname]) && $row['topic_' . $fieldname] != $row[$fieldname])
1987
$sql_ary['topic_' . $fieldname] = $row[$fieldname];
1991
if (sizeof($sql_ary))
1993
$sql = 'UPDATE ' . TOPICS_TABLE . '
1994
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
1995
WHERE topic_id = ' . $topic_id;
1996
$db->sql_query($sql);
1998
$resync_forums[$row['forum_id']] = $row['forum_id'];
2003
// if some topics have been resync'ed then resync parent forums
2004
// except when we're only syncing a range, we don't want to sync forums during
2005
// batch processing.
2006
if ($resync_parents && sizeof($resync_forums) && $where_type != 'range')
2008
sync('forum', 'forum_id', array_values($resync_forums), true, true);
2019
function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync = true)
2023
if (!is_array($forum_id))
2025
$forum_id = array($forum_id);
2028
if (!sizeof($forum_id))
2035
if (!($prune_flags & FORUM_FLAG_PRUNE_ANNOUNCE))
2037
$sql_and .= ' AND topic_type <> ' . POST_ANNOUNCE;
2040
if (!($prune_flags & FORUM_FLAG_PRUNE_STICKY))
2042
$sql_and .= ' AND topic_type <> ' . POST_STICKY;
2045
if ($prune_mode == 'posted')
2047
$sql_and .= " AND topic_last_post_time < $prune_date";
2050
if ($prune_mode == 'viewed')
2052
$sql_and .= " AND topic_last_view_time < $prune_date";
2055
$sql = 'SELECT topic_id
2056
FROM ' . TOPICS_TABLE . '
2057
WHERE ' . $db->sql_in_set('forum_id', $forum_id) . "
2060
$result = $db->sql_query($sql);
2062
$topic_list = array();
2063
while ($row = $db->sql_fetchrow($result))
2065
$topic_list[] = $row['topic_id'];
2067
$db->sql_freeresult($result);
2069
if ($prune_flags & FORUM_FLAG_PRUNE_POLL)
2071
$sql = 'SELECT topic_id
2072
FROM ' . TOPICS_TABLE . '
2073
WHERE ' . $db->sql_in_set('forum_id', $forum_id) . "
2075
AND poll_last_vote < $prune_date
2077
$result = $db->sql_query($sql);
2079
while ($row = $db->sql_fetchrow($result))
2081
$topic_list[] = $row['topic_id'];
2083
$db->sql_freeresult($result);
2085
$topic_list = array_unique($topic_list);
2088
return delete_topics('topic_id', $topic_list, $auto_sync, false);
2092
* Function auto_prune(), this function now relies on passed vars
2094
function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq)
2098
$sql = 'SELECT forum_name
2099
FROM ' . FORUMS_TABLE . "
2100
WHERE forum_id = $forum_id";
2101
$result = $db->sql_query($sql, 3600);
2102
$row = $db->sql_fetchrow($result);
2103
$db->sql_freeresult($result);
2107
$prune_date = time() - ($prune_days * 86400);
2108
$next_prune = time() + ($prune_freq * 86400);
2110
prune($forum_id, $prune_mode, $prune_date, $prune_flags, true);
2112
$sql = 'UPDATE ' . FORUMS_TABLE . "
2113
SET prune_next = $next_prune
2114
WHERE forum_id = $forum_id";
2115
$db->sql_query($sql);
2117
add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']);
2124
* remove_comments will strip the sql comment lines out of an uploaded sql file
2125
* specifically for mssql and postgres type files in the install....
2127
function remove_comments(&$output)
2129
$lines = explode("\n", $output);
2132
// try to keep mem. use down
2133
$linecount = sizeof($lines);
2135
$in_comment = false;
2136
for ($i = 0; $i < $linecount; $i++)
2138
if (trim($lines[$i]) == '/*')
2145
$output .= $lines[$i] . "\n";
2148
if (trim($lines[$i]) == '*/')
2150
$in_comment = false;
2159
* Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username
2160
* and group names must be carried through for the moderators table
2162
function cache_moderators()
2164
global $db, $cache, $auth, $phpbb_root_path, $phpEx;
2166
// Remove cached sql results
2167
$cache->destroy('sql', MODERATOR_CACHE_TABLE);
2170
switch ($db->sql_layer)
2174
$db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE);
2178
$db->sql_query('TRUNCATE TABLE ' . MODERATOR_CACHE_TABLE);
2182
// We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting
2183
$hold_ary = $ug_id_ary = $sql_ary = array();
2185
// Grab all users having moderative options...
2186
$hold_ary = $auth->acl_user_raw_data(false, 'm_%', false);
2189
if (sizeof($hold_ary))
2191
// At least one moderative option warrants a display
2192
$ug_id_ary = array_keys($hold_ary);
2194
// Remove users who have group memberships with DENY moderator permissions
2195
$sql = $db->sql_build_query('SELECT', array(
2196
'SELECT' => 'a.forum_id, ug.user_id',
2199
ACL_OPTIONS_TABLE => 'o',
2200
USER_GROUP_TABLE => 'ug',
2201
ACL_GROUPS_TABLE => 'a'
2204
'LEFT_JOIN' => array(
2206
'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'),
2207
'ON' => 'a.auth_role_id = r.role_id'
2211
'WHERE' => '(o.auth_option_id = a.auth_option_id OR o.auth_option_id = r.auth_option_id)
2212
AND ((a.auth_setting = ' . ACL_NEVER . ' AND r.auth_setting IS NULL)
2213
OR r.auth_setting = ' . ACL_NEVER . ')
2214
AND a.group_id = ug.group_id
2215
AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "
2216
AND ug.user_pending = 0
2217
AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char),
2219
$result = $db->sql_query($sql);
2221
while ($row = $db->sql_fetchrow($result))
2223
if (isset($hold_ary[$row['user_id']][$row['forum_id']]))
2225
unset($hold_ary[$row['user_id']][$row['forum_id']]);
2228
$db->sql_freeresult($result);
2230
if (sizeof($hold_ary))
2233
$sql = 'SELECT user_id, username
2234
FROM ' . USERS_TABLE . '
2235
WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary));
2236
$result = $db->sql_query($sql);
2238
$usernames_ary = array();
2239
while ($row = $db->sql_fetchrow($result))
2241
$usernames_ary[$row['user_id']] = $row['username'];
2244
foreach ($hold_ary as $user_id => $forum_id_ary)
2246
// Do not continue if user does not exist
2247
if (!isset($usernames_ary[$user_id]))
2252
foreach ($forum_id_ary as $forum_id => $auth_ary)
2255
'forum_id' => (int) $forum_id,
2256
'user_id' => (int) $user_id,
2257
'username' => (string) $usernames_ary[$user_id],
2266
// Now to the groups...
2267
$hold_ary = $auth->acl_group_raw_data(false, 'm_%', false);
2269
if (sizeof($hold_ary))
2271
$ug_id_ary = array_keys($hold_ary);
2273
// Make sure not hidden or special groups are involved...
2274
$sql = 'SELECT group_name, group_id, group_type
2275
FROM ' . GROUPS_TABLE . '
2276
WHERE ' . $db->sql_in_set('group_id', $ug_id_ary);
2277
$result = $db->sql_query($sql);
2279
$groupnames_ary = array();
2280
while ($row = $db->sql_fetchrow($result))
2282
if ($row['group_type'] == GROUP_HIDDEN || $row['group_type'] == GROUP_SPECIAL)
2284
unset($hold_ary[$row['group_id']]);
2287
$groupnames_ary[$row['group_id']] = $row['group_name'];
2289
$db->sql_freeresult($result);
2291
foreach ($hold_ary as $group_id => $forum_id_ary)
2293
// If there is no group, we do not assign it...
2294
if (!isset($groupnames_ary[$group_id]))
2299
foreach ($forum_id_ary as $forum_id => $auth_ary)
2302
foreach ($auth_ary as $auth_option => $setting)
2304
// Make sure at least one ACL_YES option is set...
2305
if ($setting == ACL_YES)
2318
'forum_id' => (int) $forum_id,
2321
'group_id' => (int) $group_id,
2322
'group_name' => (string) $groupnames_ary[$group_id]
2328
$db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary);
2334
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')
2336
global $db, $user, $auth, $phpEx, $phpbb_root_path, $phpbb_admin_path;
2338
$topic_id_list = $reportee_id_list = $is_auth = $is_mod = array();
2340
$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');
2345
$log_type = LOG_ADMIN;
2350
$log_type = LOG_MOD;
2354
$sql_forum = 'AND l.topic_id = ' . intval($topic_id);
2356
else if (is_array($forum_id))
2358
$sql_forum = 'AND ' . $db->sql_in_set('l.forum_id', array_map('intval', $forum_id));
2362
$sql_forum = ($forum_id) ? 'AND l.forum_id = ' . intval($forum_id) : '';
2367
$log_type = LOG_USERS;
2368
$sql_forum = 'AND l.reportee_id = ' . (int) $user_id;
2372
$log_type = LOG_USERS;
2377
$log_type = LOG_CRITICAL;
2385
$sql = "SELECT l.*, u.username, u.username_clean, u.user_colour
2386
FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u
2387
WHERE l.log_type = $log_type
2388
AND u.user_id = l.user_id
2389
" . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . "
2392
$result = $db->sql_query_limit($sql, $limit, $offset);
2396
while ($row = $db->sql_fetchrow($result))
2398
if ($row['topic_id'])
2400
$topic_id_list[] = $row['topic_id'];
2403
if ($row['reportee_id'])
2405
$reportee_id_list[] = $row['reportee_id'];
2409
'id' => $row['log_id'],
2411
'reportee_id' => $row['reportee_id'],
2412
'reportee_username' => '',
2413
'reportee_username_full'=> '',
2415
'user_id' => $row['user_id'],
2416
'username' => $row['username'],
2417
'username_full' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url),
2419
'ip' => $row['log_ip'],
2420
'time' => $row['log_time'],
2421
'forum_id' => $row['forum_id'],
2422
'topic_id' => $row['topic_id'],
2424
'viewforum' => ($row['forum_id'] && $auth->acl_get('f_read', $row['forum_id'])) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'f=' . $row['forum_id']) : false,
2425
'action' => (isset($user->lang[$row['log_operation']])) ? $user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}',
2428
if (!empty($row['log_data']))
2430
$log_data_ary = unserialize($row['log_data']);
2432
if (isset($user->lang[$row['log_operation']]))
2434
// We supress the warning about inappropriate number of passed parameters here due to possible changes within LOG strings from one version to another.
2435
$log[$i]['action'] = @vsprintf($log[$i]['action'], $log_data_ary);
2437
// If within the admin panel we do not censor text out
2438
if (defined('IN_ADMIN'))
2440
$log[$i]['action'] = bbcode_nl2br($log[$i]['action']);
2444
$log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action']));
2449
$log[$i]['action'] .= '<br />' . implode('', $log_data_ary);
2452
/* Apply make_clickable... has to be seen if it is for good. :/
2453
// Seems to be not for the moment, reconsider later...
2454
$log[$i]['action'] = make_clickable($log[$i]['action']);
2460
$db->sql_freeresult($result);
2462
if (sizeof($topic_id_list))
2464
$topic_id_list = array_unique($topic_id_list);
2466
// This query is not really needed if move_topics() updates the forum_id field,
2467
// although it's also used to determine if the topic still exists in the database
2468
$sql = 'SELECT topic_id, forum_id
2469
FROM ' . TOPICS_TABLE . '
2470
WHERE ' . $db->sql_in_set('topic_id', array_map('intval', $topic_id_list));
2471
$result = $db->sql_query($sql);
2473
$default_forum_id = 0;
2475
while ($row = $db->sql_fetchrow($result))
2477
if (!$row['forum_id'])
2479
if ($auth->acl_getf_global('f_read'))
2481
if (!$default_forum_id)
2483
$sql = 'SELECT forum_id
2484
FROM ' . FORUMS_TABLE . '
2485
WHERE forum_type = ' . FORUM_POST;
2486
$f_result = $db->sql_query_limit($sql, 1);
2487
$default_forum_id = (int) $db->sql_fetchfield('forum_id', false, $f_result);
2488
$db->sql_freeresult($f_result);
2491
$is_auth[$row['topic_id']] = $default_forum_id;
2496
if ($auth->acl_get('f_read', $row['forum_id']))
2498
$is_auth[$row['topic_id']] = $row['forum_id'];
2502
if ($auth->acl_gets('a_', 'm_', $row['forum_id']))
2504
$is_mod[$row['topic_id']] = $row['forum_id'];
2507
$db->sql_freeresult($result);
2509
foreach ($log as $key => $row)
2511
$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;
2512
$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;
2516
if (sizeof($reportee_id_list))
2518
$reportee_id_list = array_unique($reportee_id_list);
2519
$reportee_names_list = array();
2521
$sql = 'SELECT user_id, username, user_colour
2522
FROM ' . USERS_TABLE . '
2523
WHERE ' . $db->sql_in_set('user_id', $reportee_id_list);
2524
$result = $db->sql_query($sql);
2526
while ($row = $db->sql_fetchrow($result))
2528
$reportee_names_list[$row['user_id']] = $row;
2530
$db->sql_freeresult($result);
2532
foreach ($log as $key => $row)
2534
if (!isset($reportee_names_list[$row['reportee_id']]))
2539
$log[$key]['reportee_username'] = $reportee_names_list[$row['reportee_id']]['username'];
2540
$log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_names_list[$row['reportee_id']]['username'], $reportee_names_list[$row['reportee_id']]['user_colour'], false, $profile_url);
2544
$sql = 'SELECT COUNT(l.log_id) AS total_entries
2545
FROM ' . LOG_TABLE . " l
2546
WHERE l.log_type = $log_type
2547
AND l.log_time >= $limit_days
2549
$result = $db->sql_query($sql);
2550
$log_count = (int) $db->sql_fetchfield('total_entries');
2551
$db->sql_freeresult($result);
2557
* Update foes - remove moderators and administrators from foe lists...
2559
function update_foes($group_id = false, $user_id = false)
2563
// update foes for some user
2564
if (is_array($user_id) && sizeof($user_id))
2566
$sql = 'DELETE FROM ' . ZEBRA_TABLE . '
2567
WHERE ' . $db->sql_in_set('zebra_id', $user_id) . '
2569
$db->sql_query($sql);
2573
// update foes for some group
2574
if (is_array($group_id) && sizeof($group_id))
2576
// Grab group settings...
2577
$sql = $db->sql_build_query('SELECT', array(
2578
'SELECT' => 'a.group_id',
2581
ACL_OPTIONS_TABLE => 'ao',
2582
ACL_GROUPS_TABLE => 'a'
2585
'LEFT_JOIN' => array(
2587
'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'),
2588
'ON' => 'a.auth_role_id = r.role_id'
2592
'WHERE' => '(ao.auth_option_id = a.auth_option_id OR ao.auth_option_id = r.auth_option_id)
2593
AND ' . $db->sql_in_set('a.group_id', $group_id) . "
2594
AND ao.auth_option IN ('a_', 'm_')",
2596
'GROUP_BY' => 'a.group_id'
2598
$result = $db->sql_query($sql);
2601
while ($row = $db->sql_fetchrow($result))
2603
$groups[] = (int) $row['group_id'];
2605
$db->sql_freeresult($result);
2607
if (!sizeof($groups))
2612
switch ($db->sql_layer)
2616
$sql = 'DELETE ' . (($db->sql_layer === 'mysqli' || version_compare($db->mysql_version, '4.1', '>=')) ? 'z.*' : ZEBRA_TABLE) . '
2617
FROM ' . ZEBRA_TABLE . ' z, ' . USER_GROUP_TABLE . ' ug
2618
WHERE z.zebra_id = ug.user_id
2620
AND ' . $db->sql_in_set('ug.group_id', $groups);
2621
$db->sql_query($sql);
2625
$sql = 'SELECT user_id
2626
FROM ' . USER_GROUP_TABLE . '
2627
WHERE ' . $db->sql_in_set('group_id', $groups);
2628
$result = $db->sql_query($sql);
2631
while ($row = $db->sql_fetchrow($result))
2633
$users[] = (int) $row['user_id'];
2635
$db->sql_freeresult($result);
2639
$sql = 'DELETE FROM ' . ZEBRA_TABLE . '
2640
WHERE ' . $db->sql_in_set('zebra_id', $users) . '
2642
$db->sql_query($sql);
2650
// update foes for everyone
2652
foreach ($auth->acl_get_list(false, array('a_', 'm_'), false) as $forum_id => $forum_ary)
2654
foreach ($forum_ary as $auth_option => $user_ary)
2656
$perms = array_merge($perms, $user_ary);
2662
$sql = 'DELETE FROM ' . ZEBRA_TABLE . '
2663
WHERE ' . $db->sql_in_set('zebra_id', array_unique($perms)) . '
2665
$db->sql_query($sql);
2671
* Lists inactive users
2673
function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC')
2677
$sql = 'SELECT COUNT(user_id) AS user_count
2678
FROM ' . USERS_TABLE . '
2679
WHERE user_type = ' . USER_INACTIVE .
2680
(($limit_days) ? " AND user_inactive_time >= $limit_days" : '');
2681
$result = $db->sql_query($sql);
2682
$user_count = (int) $db->sql_fetchfield('user_count');
2683
$db->sql_freeresult($result);
2685
if ($offset >= $user_count)
2687
$offset = ($offset - $limit < 0) ? 0 : $offset - $limit;
2690
$sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason
2691
FROM ' . USERS_TABLE . '
2692
WHERE user_type = ' . USER_INACTIVE .
2693
(($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . "
2695
$result = $db->sql_query_limit($sql, $limit, $offset);
2697
while ($row = $db->sql_fetchrow($result))
2699
$row['inactive_reason'] = $user->lang['INACTIVE_REASON_UNKNOWN'];
2700
switch ($row['user_inactive_reason'])
2702
case INACTIVE_REGISTER:
2703
$row['inactive_reason'] = $user->lang['INACTIVE_REASON_REGISTER'];
2706
case INACTIVE_PROFILE:
2707
$row['inactive_reason'] = $user->lang['INACTIVE_REASON_PROFILE'];
2710
case INACTIVE_MANUAL:
2711
$row['inactive_reason'] = $user->lang['INACTIVE_REASON_MANUAL'];
2714
case INACTIVE_REMIND:
2715
$row['inactive_reason'] = $user->lang['INACTIVE_REASON_REMIND'];
2726
* Lists warned users
2728
function view_warned_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_warnings DESC')
2732
$sql = 'SELECT user_id, username, user_colour, user_warnings, user_last_warning
2733
FROM ' . USERS_TABLE . '
2734
WHERE user_warnings > 0
2735
' . (($limit_days) ? "AND user_last_warning >= $limit_days" : '') . "
2737
$result = $db->sql_query_limit($sql, $limit, $offset);
2738
$users = $db->sql_fetchrowset($result);
2739
$db->sql_freeresult($result);
2741
$sql = 'SELECT count(user_id) AS user_count
2742
FROM ' . USERS_TABLE . '
2743
WHERE user_warnings > 0
2744
' . (($limit_days) ? "AND user_last_warning >= $limit_days" : '');
2745
$result = $db->sql_query($sql);
2746
$user_count = (int) $db->sql_fetchfield('user_count');
2747
$db->sql_freeresult($result);
2754
* Currently only mysql and mssql are supported
2756
function get_database_size()
2758
global $db, $user, $table_prefix;
2760
$database_size = false;
2762
// This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0
2763
switch ($db->sql_layer)
2768
$sql = 'SELECT VERSION() AS mysql_version';
2769
$result = $db->sql_query($sql);
2770
$row = $db->sql_fetchrow($result);
2771
$db->sql_freeresult($result);
2775
$version = $row['mysql_version'];
2777
if (preg_match('#(3\.23|[45]\.)#', $version))
2779
$db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`{$db->dbname}`" : $db->dbname;
2781
$sql = 'SHOW TABLE STATUS
2783
$result = $db->sql_query($sql, 7200);
2786
while ($row = $db->sql_fetchrow($result))
2788
if ((isset($row['Type']) && $row['Type'] != 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] == 'MyISAM' || $row['Engine'] == 'InnoDB')))
2790
if ($table_prefix != '')
2792
if (strpos($row['Name'], $table_prefix) !== false)
2794
$database_size += $row['Data_length'] + $row['Index_length'];
2799
$database_size += $row['Data_length'] + $row['Index_length'];
2803
$db->sql_freeresult($result);
2811
// if it on the local machine, we can get lucky
2812
if (file_exists($dbname))
2814
$database_size = filesize($dbname);
2822
if (file_exists($dbhost))
2824
$database_size = filesize($dbhost);
2831
$sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize
2833
$result = $db->sql_query($sql, 7200);
2834
$database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false;
2835
$db->sql_freeresult($result);
2839
$sql = "SELECT proname
2841
WHERE proname = 'pg_database_size'";
2842
$result = $db->sql_query($sql);
2843
$row = $db->sql_fetchrow($result);
2844
$db->sql_freeresult($result);
2846
if ($row['proname'] == 'pg_database_size')
2848
$database = $db->dbname;
2849
if (strpos($database, '.') !== false)
2851
list($database, ) = explode('.', $database);
2856
WHERE datname = '$database'";
2857
$result = $db->sql_query($sql);
2858
$row = $db->sql_fetchrow($result);
2859
$db->sql_freeresult($result);
2863
$sql = 'SELECT pg_database_size(' . $oid . ') as size';
2864
$result = $db->sql_query($sql);
2865
$row = $db->sql_fetchrow($result);
2866
$db->sql_freeresult($result);
2868
$database_size = $row['size'];
2873
$sql = 'SELECT SUM(bytes) as dbsize
2874
FROM user_segments';
2875
$result = $db->sql_query($sql, 7200);
2876
$database_size = ($row = $db->sql_fetchrow($result)) ? $row['dbsize'] : false;
2877
$db->sql_freeresult($result);
2881
if ($database_size !== false)
2883
$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));
2887
$database_size = $user->lang['NOT_AVAILABLE'];
2890
return $database_size;
2894
* Retrieve contents from remotely stored file
2896
function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 10)
2900
if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout))
2902
@fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n");
2903
@fputs($fsock, "HOST: $host\r\n");
2904
@fputs($fsock, "Connection: close\r\n\r\n");
2909
while (!@feof($fsock))
2913
$file_info .= @fread($fsock, 1024);
2917
$line = @fgets($fsock, 1024);
2918
if ($line == "\r\n")
2922
else if (stripos($line, '404 not found') !== false)
2924
$errstr = $user->lang['FILE_NOT_FOUND'] . ': ' . $filename;
2935
$errstr = utf8_convert_message($errstr);
2940
$errstr = $user->lang['FSOCK_DISABLED'];
2950
* Remove all warnings which have now expired from the database
2951
* The duration of a warning can be defined by the administrator
2952
* This only removes the warning and reduces the associated count,
2953
* it does not remove the user note recording the contents of the warning
2955
function tidy_warnings()
2957
global $db, $config;
2959
$expire_date = time() - ($config['warnings_expire_days'] * 86400);
2960
$warning_list = $user_list = array();
2962
$sql = 'SELECT * FROM ' . WARNINGS_TABLE . "
2963
WHERE warning_time < $expire_date";
2964
$result = $db->sql_query($sql);
2966
while ($row = $db->sql_fetchrow($result))
2968
$warning_list[] = $row['warning_id'];
2969
$user_list[$row['user_id']] = isset($user_list[$row['user_id']]) ? ++$user_list[$row['user_id']] : 1;
2971
$db->sql_freeresult($result);
2973
if (sizeof($warning_list))
2975
$db->sql_transaction('begin');
2977
$sql = 'DELETE FROM ' . WARNINGS_TABLE . '
2978
WHERE ' . $db->sql_in_set('warning_id', $warning_list);
2979
$db->sql_query($sql);
2981
foreach ($user_list as $user_id => $value)
2983
$sql = 'UPDATE ' . USERS_TABLE . " SET user_warnings = user_warnings - $value
2984
WHERE user_id = $user_id";
2985
$db->sql_query($sql);
2988
$db->sql_transaction('commit');
2991
set_config('warnings_last_gc', time(), true);
2995
* Tidy database, doing some maintanance tasks
2997
function tidy_database()
3001
set_config('database_last_gc', time(), true);
3005
* Add permission language - this will make sure custom files will be included
3007
function add_permission_language()
3009
global $user, $phpEx;
3011
// First of all, our own file. We need to include it as the first file because it presets all relevant variables.
3012
$user->add_lang('acp/permissions_phpbb');
3014
$files_to_add = array();
3016
// Now search in acp and mods folder for permissions_ files.
3017
foreach (array('acp/', 'mods/') as $path)
3019
$dh = @opendir($user->lang_path . $path);
3023
while (($file = readdir($dh)) !== false)
3025
if ($file !== 'permissions_phpbb.' . $phpEx && strpos($file, 'permissions_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx)
3027
$files_to_add[] = $path . substr($file, 0, -(strlen($phpEx) + 1));
3034
if (!sizeof($files_to_add))
3039
$user->add_lang($files_to_add);
b'\\ No newline at end of file'