<?php
/**
* eXtreme Message Board
* XMB 1.9.11
*
* Developed And Maintained By The XMB Group
* Copyright (c) 2001-2011, The XMB Group
* http://www.xmbforum.com
*
* Sponsored By iEntry, Inc.
* http://www.ientry.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
**/
define('X_SCRIPT', 'tools.php');
require 'header.php';
require ROOT.'include/admin.inc.php';
loadtemplates('error_nologinsession');
eval('$css = "'.template('css').'";');
nav('<a href="cp.php">'.$lang['textcp'].'</a>');
eval('echo ("'.template('header').'");');
echo '<script language="JavaScript" type="text/javascript" src="./js/admin.js"></script>';
if (!X_ADMIN) {
eval('echo "'.template('error_nologinsession').'";');
end_time();
eval('echo "'.template('footer').'";');
exit();
}
$auditaction = $_SERVER['REQUEST_URI'];
$aapos = strpos($auditaction, "?");
if ($aapos !== false) {
$auditaction = substr($auditaction, $aapos + 1);
}
$auditaction = addslashes("$onlineip|#|$auditaction");
audit($xmbuser, $auditaction, 0, 0);
displayAdminPanel();
$action = postedVar('action', '', FALSE, FALSE, FALSE, 'g');
switch($action) {
case 'fixftotals':
// Update all forums using as few queries as possible.
$sql = "UPDATE ".X_PREFIX."forums AS f "
. " LEFT JOIN (SELECT fid, COUNT(tid) AS tcount FROM ".X_PREFIX."threads GROUP BY fid) AS query2 ON f.fid=query2.fid "
. " LEFT JOIN (SELECT fid, COUNT(pid) AS pcount FROM ".X_PREFIX."posts GROUP BY fid) AS query3 ON f.fid=query3.fid "
. "SET f.threads = IFNULL(query2.tcount, 0), f.posts = IFNULL(query3.pcount, 0) "
. "WHERE f.type = 'sub'";
$db->query($sql);
$sql = "UPDATE ".X_PREFIX."forums AS f "
. " LEFT JOIN (SELECT fup, SUM(threads) AS tcount, SUM(posts) AS pcount FROM ".X_PREFIX."forums GROUP BY fup) AS query2 ON f.fid=query2.fup "
. " LEFT JOIN (SELECT fid, COUNT(tid) AS tcount FROM ".X_PREFIX."threads GROUP BY fid) AS query3 ON f.fid=query3.fid "
. " LEFT JOIN (SELECT fid, COUNT(pid) AS pcount FROM ".X_PREFIX."posts GROUP BY fid) AS query4 ON f.fid=query4.fid "
. "SET f.threads = IFNULL(query2.tcount, 0) + IFNULL(query3.tcount, 0), "
. " f.posts = IFNULL(query2.pcount, 0) + IFNULL(query4.pcount, 0) "
. "WHERE f.type = 'forum'";
$db->query($sql);
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_forumtotal'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit;
break;
case 'fixttotals':
// Update all threads using as few queries as possible.
$sql = "UPDATE ".X_PREFIX."threads AS t "
. " INNER JOIN (SELECT tid, COUNT(pid) as pcount FROM ".X_PREFIX."posts GROUP BY tid) AS query2 USING (tid) "
. "SET t.replies = query2.pcount - 1";
$db->query($sql);
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_threadtotal'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit;
break;
case 'fixmposts':
// Update all members using as few queries as possible.
$sql = "UPDATE ".X_PREFIX."members AS m "
. " LEFT JOIN (SELECT author, COUNT(pid) as pcount FROM ".X_PREFIX."posts GROUP BY author) AS query2 ON m.username = query2.author "
. "SET m.postnum = IFNULL(query2.pcount, 0)";
$db->query($sql);
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_mempost'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit;
break;
case 'fixlastposts':
if (postedVar('scope', '', FALSE, FALSE, FALSE, 'g') == 'forumsonly') {
// Update all forums using as few queries as possible
$sql = 'SELECT f.fid, f.fup, f.type, f.lastpost, p.author, p.dateline, p.pid, log.username, log.date '
. 'FROM '.X_PREFIX.'forums AS f '
. 'LEFT JOIN ( '
. ' SELECT pid, p3.fid, author, dateline FROM '.X_PREFIX.'posts AS p3 '
. ' INNER JOIN ( '
. ' SELECT p2.fid, MAX(pid) AS lastpid '
. ' FROM '.X_PREFIX.'posts AS p2 '
. ' INNER JOIN ( '
. ' SELECT fid, MAX(dateline) AS lastdate '
. ' FROM '.X_PREFIX.'posts '
. ' GROUP BY fid '
. ' ) AS query3 ON p2.fid=query3.fid AND p2.dateline=query3.lastdate '
. ' GROUP BY p2.fid '
. ' ) AS query2 ON p3.pid=query2.lastpid '
. ') AS p ON f.fid=p.fid '
. 'LEFT JOIN ( /* Self-join order is critical with no unique key available */ '
. ' SELECT log2.fid, log2.date, log2.username '
. ' FROM '.X_PREFIX.'logs AS log2 '
. ' INNER JOIN ( '
. ' SELECT fid, MAX(`date`) AS lastdate '
. ' FROM '.X_PREFIX.'logs '
. ' WHERE `action` = "bump" '
. ' GROUP BY fid '
. ' ) AS query4 ON log2.fid=query4.fid AND log2.date=query4.lastdate '
. ') AS log ON f.fid=log.fid '
. 'WHERE f.type="forum" OR f.type="sub"';
$q = $db->query($sql);
// Structure results to accommodate a nested loop strategy.
$forums_array = array();
$subs_array = array();
while ($row = $db->fetch_array($q)) {
if ($row['type'] == 'forum') {
$forums_array[] = $row;
} else {
$subs_array[] = $row;
}
}
$db->free_result($q);
// Loop through all forums
foreach($forums_array as $loner) {
$lastpost = array();
// Loop through all sub-forums
foreach($subs_array as $sub) {
if ($sub['fup'] == $loner['fid']) {
if ($sub['pid'] !== NULL) {
if ($sub['date'] !== NULL) {
if ($sub['date'] > $sub['dateline']) {
$sub['dateline'] = $sub['date'];
$sub['author'] = $sub['username'];
}
}
$lastpost[] = $sub;
$lp = $sub['dateline'].'|'.$sub['author'].'|'.$sub['pid'];
} else {
$lp = '';
}
if ($sub['lastpost'] != $lp) {
$db->escape_fast($lp);
$db->query("UPDATE ".X_PREFIX."forums SET lastpost='$lp' WHERE fid={$sub['fid']}");
}
}
}
if ($loner['pid'] !== NULL) {
if ($loner['date'] !== NULL) {
if ($loner['date'] > $loner['dateline']) {
$loner['dateline'] = $loner['date'];
$loner['author'] = $loner['username'];
}
}
$lastpost[] = $loner;
}
if (count($lastpost) == 0) {
$lastpost = '';
} else {
$top = 0;
$mkey = -1;
foreach($lastpost as $key => $v) {
if ($v['dateline'] > $top) {
$mkey = $key;
$top = $v['dateline'];
}
}
$lastpost = $lastpost[$mkey]['dateline'].'|'.$lastpost[$mkey]['author'].'|'.$lastpost[$mkey]['pid'];
}
$db->escape_fast($lastpost);
$db->query("UPDATE ".X_PREFIX."forums SET lastpost='$lastpost' WHERE fid='{$loner['fid']}'");
}
} else { // Update all threads using as few queries as possible
$newsql = 'SELECT t.tid, t.lastpost, t.closed, p.author, p.dateline, p.pid, log.username, log.date '
. 'FROM '.X_PREFIX.'threads AS t '
. 'LEFT JOIN '.X_PREFIX.'posts AS p ON t.tid=p.tid '
. 'INNER JOIN ( '
. ' SELECT p2.tid, MAX(pid) AS lastpid '
. ' FROM '.X_PREFIX.'posts AS p2 '
. ' INNER JOIN ( '
. ' SELECT tid, MAX(dateline) AS lastdate '
. ' FROM '.X_PREFIX.'posts '
. ' GROUP BY tid '
. ' ) AS query3 ON p2.tid=query3.tid AND p2.dateline=query3.lastdate '
. ' GROUP BY p2.tid '
. ') AS query2 ON p.pid=query2.lastpid '
. 'LEFT JOIN ( /* Self-join order is critical with no unique key available */ '
. ' SELECT log2.tid, log2.date, log2.username '
. ' FROM '.X_PREFIX.'logs AS log2 '
. ' INNER JOIN ( '
. ' SELECT tid, MAX(`date`) AS lastdate '
. ' FROM '.X_PREFIX.'logs '
. ' WHERE `action` = "bump" '
. ' GROUP BY tid '
. ' ) AS query4 ON log2.tid=query4.tid AND log2.date=query4.lastdate '
. ') AS log ON t.tid=log.tid';
$lpquery = $db->query($newsql);
while($thread = $db->fetch_array($lpquery)) {
if (!is_null($thread['pid'])) {
if ($thread['dateline'] == '0' And substr($thread['closed'], 0, 6) == 'moved|') {
// Handle situation where versions before 1.9.11 set posts.dateline=0 when redirecting threads.
$newtid = intval(substr($thread['closed'], 6));
$lastdate = $db->result($db->query("SELECT MAX(dateline) AS lastdate FROM ".X_PREFIX."posts WHERE tid=$newtid"), 0);
if (is_null($lastdate)) {
// Redirector is orphaned. Set dateline to some non-zero value.
$db->query("UPDATE ".X_PREFIX."posts SET dateline=1 WHERE tid={$thread['tid']} AND dateline = 0");
} else {
$thread['dateline'] = $lastdate;
$db->query("UPDATE ".X_PREFIX."posts SET dateline=$lastdate WHERE tid={$thread['tid']} AND dateline = 0");
}
}
$lp = $thread['dateline'].'|'.$thread['author'].'|'.$thread['pid'];
if (!is_null($thread['date'])) {
if ($thread['date'] > $thread['dateline']) {
$lp = $thread['date'].'|'.$thread['username'].'|'.$thread['pid'];
}
}
} else {
$lp = '';
}
if ($thread['lastpost'] != $lp) {
$db->escape_fast($lp);
$db->query("UPDATE ".X_PREFIX."threads SET lastpost='$lp' WHERE tid={$thread['tid']}");
}
}
$db->free_result($lpquery);
}
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_lastpost'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit;
break;
case 'fixorphanedthreads':
if (noSubmit('orphsubmit')) {
echo '<form action="tools.php?action=fixorphanedthreads" method="post">';
echo '<tr bgcolor="'.$altbg1.'" class="ctrtablerow"><td><input type="text" name="export_fid" size="4"/> '.$lang['export_fid_expl'].'</td></tr>';
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td><input class="submit" type="submit" name="orphsubmit" value="'.$lang['textsubmitchanges'].'" /></td></tr>';
echo '</form>';
} else {
$export_fid = formInt('export_fid');
$export_forum = getForum($export_fid);
if ($export_forum['type'] != 'forum' And $export_forum['type'] != 'sub') {
error($lang['export_fid_not_there'], false, '</table></table><br />');
}
$q = $db->query("SELECT fid FROM ".X_PREFIX."forums WHERE type='forum' OR type='sub'");
while($f = $db->fetch_array($q)) {
$fids[] = $f['fid'];
}
$db->free_result($q);
$fq = "fid != '";
$fids = implode("' AND fid != '", $fids);
$fq .= $fids;
$fq .= "'";
$q = $db->query("SELECT tid FROM ".X_PREFIX."threads WHERE $fq");
$i = 0;
while($t = $db->fetch_array($q)) {
$db->query("UPDATE ".X_PREFIX."threads SET fid='$export_fid' WHERE tid='$t[tid]'");
$db->query("UPDATE ".X_PREFIX."posts SET fid='$export_fid' WHERE tid='$t[tid]'");
$i++;
}
$db->free_result($q);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo $i.$lang['o_threads_found'].'</td></tr>';
}
break;
case 'fixorphanedposts':
if (noSubmit('orphpostsubmit')) {
echo '<form action="tools.php?action=fixorphanedposts" method="post">';
echo '<tr bgcolor="'.$altbg1.'" class="ctrtablerow"><td><input type="text" name="export_tid" size="4"/> '.$lang['export_tid_expl'].'</td></tr>';
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td><input class="submit" type="submit" name="orphpostsubmit" value="'.$lang['textsubmitchanges'].'" /></td></tr>';
echo '</form>';
} else {
// Validate Input
$export_tid = formInt('export_tid');
$query = $db->query("SELECT fid FROM ".X_PREFIX."threads WHERE tid=$export_tid");
if ($db->num_rows($query) != 1) {
error($lang['export_tid_not_there'], false, '</table></table><br />');
}
$row = $db->fetch_array($query);
$export_fid = $row['fid'];
$db->free_result($query);
// Fix Invalid FIDs
$db->query("UPDATE ".X_PREFIX."posts AS p INNER JOIN ".X_PREFIX."threads AS t USING (tid) "
. "SET p.fid = t.fid "
. "WHERE p.fid != t.fid");
$i = $db->affected_rows();
// Fix Invalid TIDs
$db->query("UPDATE ".X_PREFIX."posts AS p LEFT JOIN ".X_PREFIX."threads AS t USING (tid) "
. "SET p.fid = $export_fid, p.tid = $export_tid "
. "WHERE t.tid IS NULL");
$i += $db->affected_rows();
updatethreadcount($export_tid);
updateforumcount($export_fid);
$forum = getForum($export_fid);
if ($forum['type'] == 'sub') {
updateforumcount($forum['fup']);
}
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo $i.$lang['o_posts_found'].'</td></tr>';
}
break;
case 'fixorphanedattachments':
if (noSubmit('orphattachsubmit')) {
echo '<form action="tools.php?action=fixorphanedattachments" method="post">';
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo '<input type="submit" name="orphattachsubmit" value="'.$lang['o_attach_submit'].'" /></td></tr>';
echo '</form>';
} else {
require('include/attach-admin.inc.php');
$i = deleteOrphans();
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo $i.$lang['o_attachments_found'].'</td></tr>';
}
break;
case 'fixorphanedpolls':
if (noSubmit('orphpollsubmit')) {
echo '<form action="tools.php?action=fixorphanedpolls" method="post">';
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo '<input type="submit" name="orphpollsubmit" value="'.$lang['o_poll_submit'].'" /></td></tr>';
echo '</form>';
} else {
$q = $db->query("SELECT topic_id "
. "FROM ".X_PREFIX."vote_desc AS v "
. "LEFT JOIN ".X_PREFIX."threads AS t ON t.tid=v.topic_id "
. "WHERE t.tid IS NULL");
$i = $db->num_rows($q);
if ($i > 0) {
$tids = array();
while($row = $db->fetch_array($q)) {
$tids[] = $row['topic_id'];
}
$tids = implode(', ', $tids);
// Important: Do not alias tables in multi-table delete queries as long as MySQL 4.0 is supported.
$db->query("DELETE FROM ".X_PREFIX."vote_desc, ".X_PREFIX."vote_results, ".X_PREFIX."vote_voters "
. "USING ".X_PREFIX."vote_desc "
. "LEFT JOIN ".X_PREFIX."vote_results ON ".X_PREFIX."vote_results.vote_id = ".X_PREFIX."vote_desc.vote_id "
. "LEFT JOIN ".X_PREFIX."vote_voters ON ".X_PREFIX."vote_voters.vote_id = ".X_PREFIX."vote_desc.vote_id "
. "WHERE ".X_PREFIX."vote_desc.topic_id IN ($tids)");
}
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>';
echo $i.$lang['o_polls_found'].'</td></tr>';
}
break;
case 'updatemoods':
$db->query("UPDATE ".X_PREFIX."members SET mood='$lang[nomoodtext]' WHERE mood=''");
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_mood'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit;
break;
case 'u2udump':
if (noSubmit('yessubmit')) {
?>
<tr bgcolor="<?php echo $altbg2; ?>" class="ctrtablerow"><td><?php echo $lang['u2udump_confirm']; ?><br />
<form action="tools.php?action=u2udump" method="post">
<input type="hidden" name="token" value="<?php echo nonce_create('truncateu2us'); ?>" />
<input type="submit" name="yessubmit" value="<?php echo $lang['textyes']; ?>" /> -
<input type="submit" name="yessubmit" value="<?php echo $lang['textno']; ?>" />
</form></td></tr>
<?php
} else if ($lang['textyes'] == $yessubmit) {
request_secure('truncateu2us', '', X_NONCE_AYS_EXP, FALSE);
$db->query("TRUNCATE ".X_PREFIX."u2u");
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_u2u'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit();
} else {
redirect($full_url.'cp.php', 0);
}
break;
case 'whosonlinedump':
if (noSubmit('yessubmit')) {
?>
<tr bgcolor="<?php echo $altbg2; ?>" class="ctrtablerow"><td><?php echo $lang['whoodump_confirm']; ?><br />
<form action="tools.php?action=whosonlinedump" method="post">
<input type="hidden" name="token" value="<?php echo nonce_create('truncatewhos'); ?>" />
<input type="submit" name="yessubmit" value="<?php echo $lang['textyes']; ?>" /> -
<input type="submit" name="yessubmit" value="<?php echo $lang['textno']; ?>" />
</form></td></tr>
<?php
} else if ($lang['textyes'] == $yessubmit) {
request_secure('truncatewhos', '', X_NONCE_AYS_EXP, FALSE);
$db->query("TRUNCATE ".X_PREFIX."whosonline");
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_whosonline'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit();
} else {
redirect($full_url.'cp.php', 0);
}
break;
case 'logsdump':
if (!X_SADMIN) {
error($lang['superadminonly'], false, '</td></tr></table></td></tr></table><br />');
}
if (noSubmit('yessubmit')) {
?>
<tr bgcolor="<?php echo $altbg2; ?>" class="ctrtablerow"><td><?php echo $lang['logsdump_confirm']; ?><br />
<form action="tools.php?action=logsdump" method="post">
<input type="hidden" name="token" value="<?php echo nonce_create('deletecplogs'); ?>" />
<input type="submit" name="yessubmit" value="<?php echo $lang['textyes']; ?>" /> -
<input type="submit" name="yessubmit" value="<?php echo $lang['textno']; ?>" />
</form></td></tr>
<?php
} else if ($lang['textyes'] == $yessubmit) {
request_secure('deletecplogs', '', X_NONCE_AYS_EXP, FALSE);
$db->query("DELETE FROM ".X_PREFIX."logs WHERE fid=0");
nav($lang['tools']);
echo '<tr bgcolor="'.$altbg2.'" class="ctrtablerow"><td>'.$lang['tool_completed'].' - '.$lang['tool_logs'].'</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
exit();
} else {
redirect($full_url.'cp.php', 0);
}
break;
case 'repairtables':
$start = TRUE;
@set_time_limit(180);
foreach($tables as $val) {
dump_query($db->query('REPAIR TABLE `'.X_PREFIX.$val.'`'), $start);
$start = FALSE;
}
break;
case 'optimizetables':
$start = TRUE;
@set_time_limit(180);
foreach($tables as $val) {
dump_query($db->query('OPTIMIZE TABLE `'.X_PREFIX.$val.'`'), $start);
$start = FALSE;
}
break;
case 'analyzetables':
$start = TRUE;
@set_time_limit(180);
foreach($tables as $val) {
dump_query($db->query('ANALYZE TABLE `'.X_PREFIX.$val.'`'), $start);
$start = FALSE;
}
break;
case 'checktables':
$start = TRUE;
@set_time_limit(180);
foreach($tables as $val) {
dump_query($db->query('CHECK TABLE `'.X_PREFIX.$val.'`'), $start);
$start = FALSE;
}
break;
}
echo '</td></tr></table></table>';
end_time();
eval('echo "'.template('footer').'";');
?>