1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547:
<?php
if (!defined('SMF'))
die('No direct access...');
function writeLog($force = false)
{
global $user_info, $user_settings, $context, $modSettings, $settings, $topic, $board, $smcFunc, $sourcedir, $cache_enable;
if (!empty($settings['display_who_viewing']) && ($topic || $board))
{
$force = true;
if ($topic)
{
if (isset($_SESSION['last_topic_id']) && $_SESSION['last_topic_id'] == $topic)
$force = false;
$_SESSION['last_topic_id'] = $topic;
}
}
if (!empty($user_info['possibly_robot']) && !empty($modSettings['spider_mode']) && $modSettings['spider_mode'] > 1)
{
require_once($sourcedir . '/ManageSearchEngines.php');
logSpider();
}
if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= (time() - 8) && !$force)
return;
if (!empty($modSettings['who_enabled']))
{
$encoded_get = truncate_array($_GET) + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']);
if (!isset($context['session_var']))
$context['session_var'] = $_SESSION['session_var'];
unset($encoded_get['sesc'], $encoded_get[$context['session_var']]);
$encoded_get = $smcFunc['json_encode']($encoded_get);
}
else
$encoded_get = '';
$session_id = $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id();
$do_delete = cache_get_data('log_online-update', 30) < time() - 30;
if (!empty($_SESSION['log_time']) && $_SESSION['log_time'] >= time() - $modSettings['lastActive'] * 20)
{
if ($do_delete)
{
$smcFunc['db_query']('delete_log_online_interval', '
DELETE FROM {db_prefix}log_online
WHERE log_time < {int:log_time}
AND session != {string:session}',
array(
'log_time' => time() - $modSettings['lastActive'] * 60,
'session' => $session_id,
)
);
cache_put_data('log_online-update', time(), 30);
}
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_online
SET log_time = {int:log_time}, ip = {inet:ip}, url = {string:url}
WHERE session = {string:session}',
array(
'log_time' => time(),
'ip' => $user_info['ip'],
'url' => $encoded_get,
'session' => $session_id,
)
);
if ($smcFunc['db_affected_rows']() == 0)
$_SESSION['log_time'] = 0;
}
else
$_SESSION['log_time'] = 0;
if (empty($_SESSION['log_time']))
{
if ($do_delete || !empty($user_info['id']))
$smcFunc['db_query']('', '
DELETE FROM {db_prefix}log_online
WHERE ' . ($do_delete ? 'log_time < {int:log_time}' : '') . ($do_delete && !empty($user_info['id']) ? ' OR ' : '') . (empty($user_info['id']) ? '' : 'id_member = {int:current_member}'),
array(
'current_member' => $user_info['id'],
'log_time' => time() - $modSettings['lastActive'] * 60,
)
);
$smcFunc['db_insert']($do_delete ? 'ignore' : 'replace',
'{db_prefix}log_online',
array('session' => 'string', 'id_member' => 'int', 'id_spider' => 'int', 'log_time' => 'int', 'ip' => 'inet', 'url' => 'string'),
array($session_id, $user_info['id'], empty($_SESSION['id_robot']) ? 0 : $_SESSION['id_robot'], time(), $user_info['ip'], $encoded_get),
array('session')
);
}
$_SESSION['log_time'] = time();
if (empty($_SESSION['timeOnlineUpdated']))
$_SESSION['timeOnlineUpdated'] = time();
if (SMF != 'SSI' && !empty($user_info['last_login']) && $user_info['last_login'] < time() - 60 && (!isset($_REQUEST['action']) || !in_array($_REQUEST['action'], array('.xml', 'login2', 'logintfa'))))
{
if (time() - $_SESSION['timeOnlineUpdated'] > 60 * 15)
$_SESSION['timeOnlineUpdated'] = time();
$user_settings['total_time_logged_in'] += time() - $_SESSION['timeOnlineUpdated'];
updateMemberData($user_info['id'], array('last_login' => time(), 'member_ip' => $user_info['ip'], 'member_ip2' => $_SERVER['BAN_CHECK_IP'], 'total_time_logged_in' => $user_settings['total_time_logged_in']));
if (!empty($cache_enable) && $cache_enable >= 2)
cache_put_data('user_settings-' . $user_info['id'], $user_settings, 60);
$user_info['total_time_logged_in'] += time() - $_SESSION['timeOnlineUpdated'];
$_SESSION['timeOnlineUpdated'] = time();
}
}
function logLastDatabaseError()
{
global $boarddir, $cachedir;
$last_db_error_change = @filemtime($cachedir . '/db_last_error.php');
$file = $cachedir . '/db_last_error.php';
$dberror_backup_fail = !@is_writable($cachedir . '/db_last_error_bak.php') || !@copy($file, $cachedir . '/db_last_error_bak.php');
$dberror_backup_fail = !$dberror_backup_fail ? (!file_exists($cachedir . '/db_last_error_bak.php') || filesize($cachedir . '/db_last_error_bak.php') === 0) : $dberror_backup_fail;
clearstatcache();
if (filemtime($cachedir . '/db_last_error.php') === $last_db_error_change)
{
$write_db_change = '<' . '?' . "php\n" . '$db_last_error = ' . time() . ';' . "\n" . '?' . '>';
$written_bytes = file_put_contents($cachedir . '/db_last_error.php', $write_db_change, LOCK_EX);
if ($written_bytes !== strlen($write_db_change) && !$dberror_backup_fail)
{
@copy($cachedir . '/db_last_error_bak.php', $cachedir . '/db_last_error.php');
}
else
{
@touch($boarddir . '/' . 'Settings.php');
return true;
}
}
return false;
}
function displayDebug()
{
global $context, $scripturl, $boarddir, $sourcedir, $cachedir, $settings, $modSettings;
global $db_cache, $db_count, $cache_misses, $cache_count_misses, $db_show_debug, $cache_count, $cache_hits, $smcFunc, $txt, $cache_enable;
if (!isset($db_show_debug) || $db_show_debug !== true || (isset($_GET['action']) && $_GET['action'] == 'viewquery'))
return;
if (empty($_SESSION['view_queries']))
$_SESSION['view_queries'] = 0;
if (empty($context['debug']['language_files']))
$context['debug']['language_files'] = array();
if (empty($context['debug']['sheets']))
$context['debug']['sheets'] = array();
$files = get_included_files();
$total_size = 0;
for ($i = 0, $n = count($files); $i < $n; $i++)
{
if (file_exists($files[$i]))
$total_size += filesize($files[$i]);
$files[$i] = strtr($files[$i], array($boarddir => '.', $sourcedir => '(Sources)', $cachedir => '(Cache)', $settings['actual_theme_dir'] => '(Current Theme)'));
}
$warnings = 0;
if (!empty($db_cache))
{
foreach ($db_cache as $q => $query_data)
{
if (!empty($query_data['w']))
$warnings += count($query_data['w']);
}
$_SESSION['debug'] = &$db_cache;
}
$temp = ob_get_contents();
ob_clean();
echo preg_replace('~</body>\s*</html>~', '', $temp), '
<div class="smalltext" style="text-align: left; margin: 1ex;">
', $txt['debug_browser'], $context['browser_body_id'], ' <em>(', implode('</em>, <em>', array_reverse(array_keys($context['browser'], true))), ')</em><br>
', $txt['debug_templates'], count($context['debug']['templates']), ': <em>', implode('</em>, <em>', $context['debug']['templates']), '</em>.<br>
', $txt['debug_subtemplates'], count($context['debug']['sub_templates']), ': <em>', implode('</em>, <em>', $context['debug']['sub_templates']), '</em>.<br>
', $txt['debug_language_files'], count($context['debug']['language_files']), ': <em>', implode('</em>, <em>', $context['debug']['language_files']), '</em>.<br>
', $txt['debug_stylesheets'], count($context['debug']['sheets']), ': <em>', implode('</em>, <em>', $context['debug']['sheets']), '</em>.<br>
', $txt['debug_hooks'], empty($context['debug']['hooks']) ? 0 : count($context['debug']['hooks']) . ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_hooks\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_hooks" style="display: none;"><em>' . implode('</em>, <em>', $context['debug']['hooks']), '</em></span>)', '<br>
', (isset($context['debug']['instances']) ? ($txt['debug_instances'] . (empty($context['debug']['instances']) ? 0 : count($context['debug']['instances'])) . ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_instances\').style.display = \'inline\'; this.style.display = \'none\'; return false;">' . $txt['debug_show'] . '</a><span id="debug_instances" style="display: none;"><em>' . implode('</em>, <em>', array_keys($context['debug']['instances'])) . '</em></span>)' . '<br>') : ''), '
', $txt['debug_files_included'], count($files), ' - ', round($total_size / 1024), $txt['debug_kb'], ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_include_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_include_info" style="display: none;"><em>', implode('</em>, <em>', $files), '</em></span>)<br>';
if (function_exists('memory_get_peak_usage'))
echo $txt['debug_memory_use'], ceil(memory_get_peak_usage() / 1024), $txt['debug_kb'], '<br>';
if (isset($_SESSION['token']))
echo $txt['debug_tokens'] . '<em>' . implode(',</em> <em>', array_keys($_SESSION['token'])), '</em>.<br>';
if (!empty($cache_enable) && !empty($cache_hits))
{
$missed_entries = array();
$entries = array();
$total_t = 0;
$total_s = 0;
foreach ($cache_hits as $cache_hit)
{
$entries[] = $cache_hit['d'] . ' ' . $cache_hit['k'] . ': ' . sprintf($txt['debug_cache_seconds_bytes'], comma_format($cache_hit['t'], 5), $cache_hit['s']);
$total_t += $cache_hit['t'];
$total_s += $cache_hit['s'];
}
if (!isset($cache_misses))
$cache_misses = array();
foreach ($cache_misses as $missed)
$missed_entries[] = $missed['d'] . ' ' . $missed['k'];
echo '
', $txt['debug_cache_hits'], $cache_count, ': ', sprintf($txt['debug_cache_seconds_bytes_total'], comma_format($total_t, 5), comma_format($total_s)), ' (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_cache_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_cache_info" style="display: none;"><em>', implode('</em>, <em>', $entries), '</em></span>)<br>
', $txt['debug_cache_misses'], $cache_count_misses, ': (<a href="javascript:void(0);" onclick="document.getElementById(\'debug_cache_misses_info\').style.display = \'inline\'; this.style.display = \'none\'; return false;">', $txt['debug_show'], '</a><span id="debug_cache_misses_info" style="display: none;"><em>', implode('</em>, <em>', $missed_entries), '</em></span>)<br>';
}
echo '
<a href="', $scripturl, '?action=viewquery" target="_blank" rel="noopener">', $warnings == 0 ? sprintf($txt['debug_queries_used'], (int) $db_count) : sprintf($txt['debug_queries_used_and_warnings'], (int) $db_count, $warnings), '</a><br>
<br>';
if ($_SESSION['view_queries'] == 1 && !empty($db_cache))
foreach ($db_cache as $q => $query_data)
{
$is_select = strpos(trim($query_data['q']), 'SELECT') === 0 || preg_match('~^INSERT(?: IGNORE)? INTO \w+(?:\s+\([^)]+\))?\s+SELECT .+$~s', trim($query_data['q'])) != 0;
if ($is_select)
{
foreach (array('log_topics_unread', 'topics_posted_in', 'tmp_log_search_topics', 'tmp_log_search_messages') as $tmp)
if (strpos(trim($query_data['q']), $tmp) !== false)
{
$is_select = false;
break;
}
}
elseif (preg_match('~^CREATE TEMPORARY TABLE .+?SELECT .+$~s', trim($query_data['q'])) != 0)
$is_select = true;
if (isset($query_data['f']))
$query_data['f'] = preg_replace('~^' . preg_quote($boarddir, '~') . '~', '...', $query_data['f']);
echo '
<strong>', $is_select ? '<a href="' . $scripturl . '?action=viewquery;qq=' . ($q + 1) . '#qq' . $q . '" target="_blank" rel="noopener" style="text-decoration: none;">' : '', nl2br(str_replace("\t", ' ', $smcFunc['htmlspecialchars'](ltrim($query_data['q'], "\n\r")))) . ($is_select ? '</a></strong>' : '</strong>') . '<br>
';
if (!empty($query_data['f']) && !empty($query_data['l']))
echo sprintf($txt['debug_query_in_line'], $query_data['f'], $query_data['l']);
if (isset($query_data['s'], $query_data['t']) && isset($txt['debug_query_which_took_at']))
echo sprintf($txt['debug_query_which_took_at'], round($query_data['t'], 8), round($query_data['s'], 8)) . '<br>';
elseif (isset($query_data['t']))
echo sprintf($txt['debug_query_which_took'], round($query_data['t'], 8)) . '<br>';
echo '
<br>';
}
echo '
<a href="' . $scripturl . '?action=viewquery;sa=hide">', $txt['debug_' . (empty($_SESSION['view_queries']) ? 'show' : 'hide') . '_queries'], '</a>
</div></body></html>';
}
function trackStats($stats = array())
{
global $modSettings, $smcFunc;
static $cache_stats = array();
if (empty($modSettings['trackStats']))
return false;
if (!empty($stats))
return $cache_stats = array_merge($cache_stats, $stats);
elseif (empty($cache_stats))
return false;
$setStringUpdate = '';
$insert_keys = array();
$date = strftime('%Y-%m-%d', forum_time(false));
$update_parameters = array(
'current_date' => $date,
);
foreach ($cache_stats as $field => $change)
{
$setStringUpdate .= '
' . $field . ' = ' . ($change === '+' ? $field . ' + 1' : '{int:' . $field . '}') . ',';
if ($change === '+')
$cache_stats[$field] = 1;
else
$update_parameters[$field] = $change;
$insert_keys[$field] = 'int';
}
$smcFunc['db_query']('', '
UPDATE {db_prefix}log_activity
SET' . substr($setStringUpdate, 0, -1) . '
WHERE date = {date:current_date}',
$update_parameters
);
if ($smcFunc['db_affected_rows']() == 0)
{
$smcFunc['db_insert']('ignore',
'{db_prefix}log_activity',
array_merge($insert_keys, array('date' => 'date')),
array_merge($cache_stats, array($date)),
array('date')
);
}
$cache_stats = array();
return true;
}
function logAction($action, $extra = array(), $log_type = 'moderate')
{
return logActions(array(array(
'action' => $action,
'log_type' => $log_type,
'extra' => $extra,
)));
}
function logActions($logs)
{
global $modSettings, $user_info, $smcFunc, $sourcedir;
$inserts = array();
$log_types = array(
'moderate' => 1,
'user' => 2,
'admin' => 3,
);
if (empty($modSettings['modlog_enabled']))
unset ($log_types['moderate']);
if (empty($modSettings['userlog_enabled']))
unset ($log_types['user']);
if (empty($modSettings['adminlog_enabled']))
unset ($log_types['admin']);
call_integration_hook('integrate_log_types', array(&$log_types));
foreach ($logs as $log)
{
if (!isset($log_types[$log['log_type']]))
return false;
if (!is_array($log['extra']))
trigger_error('logActions(): data is not an array with action \'' . $log['action'] . '\'', E_USER_NOTICE);
if (isset($log['extra']['topic']))
{
if (!is_numeric($log['extra']['topic']))
trigger_error('logActions(): data\'s topic is not a number', E_USER_NOTICE);
$topic_id = empty($log['extra']['topic']) ? 0 : (int) $log['extra']['topic'];
unset($log['extra']['topic']);
}
else
$topic_id = 0;
if (isset($log['extra']['message']))
{
if (!is_numeric($log['extra']['message']))
trigger_error('logActions(): data\'s message is not a number', E_USER_NOTICE);
$msg_id = empty($log['extra']['message']) ? 0 : (int) $log['extra']['message'];
unset($log['extra']['message']);
}
else
$msg_id = 0;
if (in_array($log['action'], array('move', 'remove', 'split', 'merge')))
{
$request = $smcFunc['db_query']('', '
SELECT id_report
FROM {db_prefix}log_reported
WHERE {raw:column_name} = {int:reported}
LIMIT 1',
array(
'column_name' => !empty($msg_id) ? 'id_msg' : 'id_topic',
'reported' => !empty($msg_id) ? $msg_id : $topic_id,
)
);
if ($smcFunc['db_num_rows']($request) > 0)
{
require_once($sourcedir . '/ModerationCenter.php');
require_once($sourcedir . '/Subs-ReportedContent.php');
updateSettings(array('last_mod_report_action' => time()));
recountOpenReports('posts');
}
$smcFunc['db_free_result']($request);
}
if (isset($log['extra']['member']) && !is_numeric($log['extra']['member']))
trigger_error('logActions(): data\'s member is not a number', E_USER_NOTICE);
if (isset($log['extra']['board']))
{
if (!is_numeric($log['extra']['board']))
trigger_error('logActions(): data\'s board is not a number', E_USER_NOTICE);
$board_id = empty($log['extra']['board']) ? 0 : (int) $log['extra']['board'];
unset($log['extra']['board']);
}
else
$board_id = 0;
if (isset($log['extra']['board_to']))
{
if (!is_numeric($log['extra']['board_to']))
trigger_error('logActions(): data\'s board_to is not a number', E_USER_NOTICE);
if (empty($board_id))
{
$board_id = empty($log['extra']['board_to']) ? 0 : (int) $log['extra']['board_to'];
unset($log['extra']['board_to']);
}
}
if (isset($log['extra']['member_affected']))
$memID = $log['extra']['member_affected'];
else
$memID = $user_info['id'];
if (isset($user_info['ip']))
$memIP = $user_info['ip'];
else
$memIP = 'null';
$inserts[] = array(
time(), $log_types[$log['log_type']], $memID, $memIP, $log['action'],
$board_id, $topic_id, $msg_id, $smcFunc['json_encode']($log['extra']),
);
}
$id_action = $smcFunc['db_insert']('',
'{db_prefix}log_actions',
array(
'log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'inet', 'action' => 'string',
'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534',
),
$inserts,
array('id_action'),
1
);
return $id_action;
}
?>