Chris@76: 'EditSpider', Chris@76: 'logs' => 'SpiderLogs', Chris@76: 'settings' => 'ManageSearchEngineSettings', Chris@76: 'spiders' => 'ViewSpiders', Chris@76: 'stats' => 'SpiderStats', Chris@76: ); Chris@76: Chris@76: // Ensure we have a valid subaction. Chris@76: $context['sub_action'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'stats'; Chris@76: Chris@76: $context['page_title'] = $txt['search_engines']; Chris@76: Chris@76: // Some more tab data. Chris@76: $context[$context['admin_menu_name']]['tab_data'] = array( Chris@76: 'title' => $txt['search_engines'], Chris@76: 'description' => $txt['search_engines_description'], Chris@76: ); Chris@76: Chris@76: // Call the function! Chris@76: $subActions[$context['sub_action']](); Chris@76: } Chris@76: Chris@76: // This is really just the settings page. Chris@76: function ManageSearchEngineSettings($return_config = false) Chris@76: { Chris@76: global $context, $txt, $modSettings, $scripturl, $sourcedir, $smcFunc; Chris@76: Chris@76: $config_vars = array( Chris@76: // How much detail? Chris@76: array('select', 'spider_mode', array($txt['spider_mode_off'], $txt['spider_mode_standard'], $txt['spider_mode_high'], $txt['spider_mode_vhigh']), 'onchange' => 'disableFields();'), Chris@76: 'spider_group' => array('select', 'spider_group', array($txt['spider_group_none'], $txt['membergroups_members'])), Chris@76: array('select', 'show_spider_online', array($txt['show_spider_online_no'], $txt['show_spider_online_summary'], $txt['show_spider_online_detail'], $txt['show_spider_online_detail_admin'])), Chris@76: ); Chris@76: Chris@76: // Set up a message. Chris@76: $context['settings_message'] = '' . sprintf($txt['spider_settings_desc'], $scripturl . '?action=admin;area=logs;sa=pruning;' . $context['session_var'] . '=' . $context['session_id']) . ''; Chris@76: Chris@76: // Do some javascript. Chris@76: $javascript_function = ' Chris@76: function disableFields() Chris@76: { Chris@76: disabledState = document.getElementById(\'spider_mode\').value == 0;'; Chris@76: Chris@76: foreach ($config_vars as $variable) Chris@76: if ($variable[1] != 'spider_mode') Chris@76: $javascript_function .= ' Chris@76: if (document.getElementById(\'' . $variable[1] . '\')) Chris@76: document.getElementById(\'' . $variable[1] . '\').disabled = disabledState;'; Chris@76: Chris@76: $javascript_function .= ' Chris@76: } Chris@76: disableFields();'; Chris@76: Chris@76: if ($return_config) Chris@76: return $config_vars; Chris@76: Chris@76: // We need to load the groups for the spider group thingy. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_group, group_name Chris@76: FROM {db_prefix}membergroups Chris@76: WHERE id_group != {int:admin_group} Chris@76: AND id_group != {int:moderator_group}', Chris@76: array( Chris@76: 'admin_group' => 1, Chris@76: 'moderator_group' => 3, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $config_vars['spider_group'][2][$row['id_group']] = $row['group_name']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Make sure it's valid - note that regular members are given id_group = 1 which is reversed in Load.php - no admins here! Chris@76: if (isset($_POST['spider_group']) && !isset($config_vars['spider_group'][2][$_POST['spider_group']])) Chris@76: $_POST['spider_group'] = 0; Chris@76: Chris@76: // We'll want this for our easy save. Chris@76: require_once($sourcedir . '/ManageServer.php'); Chris@76: Chris@76: // Setup the template. Chris@76: $context['page_title'] = $txt['settings']; Chris@76: $context['sub_template'] = 'show_settings'; Chris@76: Chris@76: // Are we saving them - are we?? Chris@76: if (isset($_GET['save'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: saveDBSettings($config_vars); Chris@76: recacheSpiderNames(); Chris@76: redirectexit('action=admin;area=sengines;sa=settings'); Chris@76: } Chris@76: Chris@76: // Final settings... Chris@76: $context['post_url'] = $scripturl . '?action=admin;area=sengines;save;sa=settings'; Chris@76: $context['settings_title'] = $txt['settings']; Chris@76: $context['settings_insert_below'] = ' Chris@76: '; Chris@76: Chris@76: // Prepare the settings... Chris@76: prepareDBSettingContext($config_vars); Chris@76: } Chris@76: Chris@76: // View a list of all the spiders we know about. Chris@76: function ViewSpiders() Chris@76: { Chris@76: global $context, $txt, $sourcedir, $scripturl, $smcFunc; Chris@76: Chris@76: if (!isset($_SESSION['spider_stat']) || $_SESSION['spider_stat'] < time() - 60) Chris@76: { Chris@76: consolidateSpiderStats(); Chris@76: $_SESSION['spider_stat'] = time(); Chris@76: } Chris@76: Chris@76: // Are we adding a new one? Chris@76: if (!empty($_POST['addSpider'])) Chris@76: return EditSpider(); Chris@76: // User pressed the 'remove selection button'. Chris@76: elseif (!empty($_POST['removeSpiders']) && !empty($_POST['remove']) && is_array($_POST['remove'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // Make sure every entry is a proper integer. Chris@76: foreach ($_POST['remove'] as $index => $spider_id) Chris@76: $_POST['remove'][(int) $index] = (int) $spider_id; Chris@76: Chris@76: // Delete them all! Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}spiders Chris@76: WHERE id_spider IN ({array_int:remove_list})', Chris@76: array( Chris@76: 'remove_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_spider_hits Chris@76: WHERE id_spider IN ({array_int:remove_list})', Chris@76: array( Chris@76: 'remove_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_spider_stats Chris@76: WHERE id_spider IN ({array_int:remove_list})', Chris@76: array( Chris@76: 'remove_list' => $_POST['remove'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: cache_put_data('spider_search', null, 300); Chris@76: recacheSpiderNames(); Chris@76: } Chris@76: Chris@76: // Get the last seens. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_spider, MAX(last_seen) AS last_seen_time Chris@76: FROM {db_prefix}log_spider_stats Chris@76: GROUP BY id_spider', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: $context['spider_last_seen'] = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $context['spider_last_seen'][$row['id_spider']] = $row['last_seen_time']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'spider_list', Chris@76: 'items_per_page' => 20, Chris@76: 'base_href' => $scripturl . '?action=admin;area=sengines;sa=spiders', Chris@76: 'default_sort_col' => 'name', Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getSpiders', Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumSpiders', Chris@76: ), Chris@76: 'no_items_label' => $txt['spiders_no_entries'], Chris@76: 'columns' => array( Chris@76: 'name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_name'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $scripturl; Chris@76: Chris@76: return sprintf(\'%3$s\', $scripturl, $rowData[\'id_spider\'], htmlspecialchars($rowData[\'spider_name\'])); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'spider_name', Chris@76: 'reverse' => 'spider_name DESC', Chris@76: ), Chris@76: ), Chris@76: 'last_seen' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_last_seen'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $context, $txt; Chris@76: Chris@76: return isset($context[\'spider_last_seen\'][$rowData[\'id_spider\']]) ? timeformat($context[\'spider_last_seen\'][$rowData[\'id_spider\']]) : $txt[\'spider_last_never\']; Chris@76: '), Chris@76: ), Chris@76: ), Chris@76: 'user_agent' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_agent'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db_htmlsafe' => 'user_agent', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'user_agent', Chris@76: 'reverse' => 'user_agent DESC', Chris@76: ), Chris@76: ), Chris@76: 'ip_info' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_ip_info'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db_htmlsafe' => 'ip_info', Chris@76: 'class' => 'smalltext', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'ip_info', Chris@76: 'reverse' => 'ip_info DESC', Chris@76: ), Chris@76: ), Chris@76: 'check' => array( Chris@76: 'header' => array( Chris@76: 'value' => '', Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '', Chris@76: 'params' => array( Chris@76: 'id_spider' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=sengines;sa=spiders', Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => ' Chris@76: Chris@76: Chris@76: ', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: $context['sub_template'] = 'show_list'; Chris@76: $context['default_list'] = 'spider_list'; Chris@76: } Chris@76: Chris@76: function list_getSpiders($start, $items_per_page, $sort) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_spider, spider_name, user_agent, ip_info Chris@76: FROM {db_prefix}spiders Chris@76: ORDER BY ' . $sort . ' Chris@76: LIMIT ' . $start . ', ' . $items_per_page, Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $spiders = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spiders[$row['id_spider']] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $spiders; Chris@76: } Chris@76: Chris@76: function list_getNumSpiders() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS num_spiders Chris@76: FROM {db_prefix}spiders', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($numSpiders) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $numSpiders; Chris@76: } Chris@76: Chris@76: // Here we can add, and edit, spider info! Chris@76: function EditSpider() Chris@76: { Chris@76: global $context, $smcFunc, $txt; Chris@76: Chris@76: // Some standard stuff. Chris@76: $context['id_spider'] = !empty($_GET['sid']) ? (int) $_GET['sid'] : 0; Chris@76: $context['page_title'] = $context['id_spider'] ? $txt['spiders_edit'] : $txt['spiders_add']; Chris@76: $context['sub_template'] = 'spider_edit'; Chris@76: Chris@76: // Are we saving? Chris@76: if (!empty($_POST['save'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: $ips = array(); Chris@76: // Check the IP range is valid. Chris@76: $ip_sets = explode(',', $_POST['spider_ip']); Chris@76: foreach ($ip_sets as $set) Chris@76: { Chris@76: $test = ip2range(trim($set)); Chris@76: if (!empty($test)) Chris@76: $ips[] = $set; Chris@76: } Chris@76: $ips = implode(',', $ips); Chris@76: Chris@76: // Goes in as it is... Chris@76: if ($context['id_spider']) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}spiders Chris@76: SET spider_name = {string:spider_name}, user_agent = {string:spider_agent}, Chris@76: ip_info = {string:ip_info} Chris@76: WHERE id_spider = {int:current_spider}', Chris@76: array( Chris@76: 'current_spider' => $context['id_spider'], Chris@76: 'spider_name' => $_POST['spider_name'], Chris@76: 'spider_agent' => $_POST['spider_agent'], Chris@76: 'ip_info' => $ips, Chris@76: ) Chris@76: ); Chris@76: else Chris@76: $smcFunc['db_insert']('insert', Chris@76: '{db_prefix}spiders', Chris@76: array( Chris@76: 'spider_name' => 'string', 'user_agent' => 'string', 'ip_info' => 'string', Chris@76: ), Chris@76: array( Chris@76: $_POST['spider_name'], $_POST['spider_agent'], $ips, Chris@76: ), Chris@76: array('id_spider') Chris@76: ); Chris@76: Chris@76: // Order by user agent length. Chris@76: sortSpiderTable(); Chris@76: Chris@76: cache_put_data('spider_search', null, 300); Chris@76: recacheSpiderNames(); Chris@76: Chris@76: redirectexit('action=admin;area=sengines;sa=spiders'); Chris@76: } Chris@76: Chris@76: // The default is new. Chris@76: $context['spider'] = array( Chris@76: 'id' => 0, Chris@76: 'name' => '', Chris@76: 'agent' => '', Chris@76: 'ip_info' => '', Chris@76: ); Chris@76: Chris@76: // An edit? Chris@76: if ($context['id_spider']) Chris@76: { Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_spider, spider_name, user_agent, ip_info Chris@76: FROM {db_prefix}spiders Chris@76: WHERE id_spider = {int:current_spider}', Chris@76: array( Chris@76: 'current_spider' => $context['id_spider'], Chris@76: ) Chris@76: ); Chris@76: if ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $context['spider'] = array( Chris@76: 'id' => $row['id_spider'], Chris@76: 'name' => $row['spider_name'], Chris@76: 'agent' => $row['user_agent'], Chris@76: 'ip_info' => $row['ip_info'], Chris@76: ); Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: } Chris@76: Chris@76: //!!! Should this not be... you know... in a different file? Chris@76: // Do we think the current user is a spider? Chris@76: function SpiderCheck() Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: if (isset($_SESSION['id_robot'])) Chris@76: unset($_SESSION['id_robot']); Chris@76: $_SESSION['robot_check'] = time(); Chris@76: Chris@76: // We cache the spider data for five minutes if we can. Chris@76: if (!empty($modSettings['cache_enable'])) Chris@76: $spider_data = cache_get_data('spider_search', 300); Chris@76: Chris@76: if (!isset($spider_data) || $spider_data === NULL) Chris@76: { Chris@76: $request = $smcFunc['db_query']('spider_check', ' Chris@76: SELECT id_spider, user_agent, ip_info Chris@76: FROM {db_prefix}spiders', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $spider_data = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spider_data[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (!empty($modSettings['cache_enable'])) Chris@76: cache_put_data('spider_search', $spider_data, 300); Chris@76: } Chris@76: Chris@76: if (empty($spider_data)) Chris@76: return false; Chris@76: Chris@76: // Only do these bits once. Chris@76: $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']); Chris@76: preg_match('/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/', $_SERVER['REMOTE_ADDR'], $ip_parts); Chris@76: Chris@76: foreach ($spider_data as $spider) Chris@76: { Chris@76: // User agent is easy. Chris@76: if (!empty($spider['user_agent']) && strpos($ci_user_agent, strtolower($spider['user_agent'])) !== false) Chris@76: $_SESSION['id_robot'] = $spider['id_spider']; Chris@76: // IP stuff is harder. Chris@76: elseif (!empty($ip_parts)) Chris@76: { Chris@76: $ips = explode(',', $spider['ip_info']); Chris@76: foreach ($ips as $ip) Chris@76: { Chris@76: $ip = ip2range($ip); Chris@76: if (!empty($ip)) Chris@76: { Chris@76: foreach ($ip as $key => $value) Chris@76: { Chris@76: if ($value['low'] > $ip_parts[$key + 1] || $value['high'] < $ip_parts[$key + 1]) Chris@76: break; Chris@76: elseif ($key == 3) Chris@76: $_SESSION['id_robot'] = $spider['id_spider']; Chris@76: } Chris@76: } Chris@76: } Chris@76: } Chris@76: Chris@76: if (isset($_SESSION['id_robot'])) Chris@76: break; Chris@76: } Chris@76: Chris@76: // If this is low server tracking then log the spider here as oppossed to the main logging function. Chris@76: if (!empty($modSettings['spider_mode']) && $modSettings['spider_mode'] == 1 && !empty($_SESSION['id_robot'])) Chris@76: logSpider(); Chris@76: Chris@76: return !empty($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0; Chris@76: } Chris@76: Chris@76: // Log the spider presence online. Chris@76: //!!! Different file? Chris@76: function logSpider() Chris@76: { Chris@76: global $smcFunc, $modSettings, $context; Chris@76: Chris@76: if (empty($modSettings['spider_mode']) || empty($_SESSION['id_robot'])) Chris@76: return; Chris@76: Chris@76: // Attempt to update today's entry. Chris@76: if ($modSettings['spider_mode'] == 1) Chris@76: { Chris@76: $date = strftime('%Y-%m-%d', forum_time(false)); Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_spider_stats Chris@76: SET last_seen = {int:current_time}, page_hits = page_hits + 1 Chris@76: WHERE id_spider = {int:current_spider} Chris@76: AND stat_date = {date:current_date}', Chris@76: array( Chris@76: 'current_date' => $date, Chris@76: 'current_time' => time(), Chris@76: 'current_spider' => $_SESSION['id_robot'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Nothing updated? Chris@76: if ($smcFunc['db_affected_rows']() == 0) Chris@76: { Chris@76: $smcFunc['db_insert']('ignore', Chris@76: '{db_prefix}log_spider_stats', Chris@76: array( Chris@76: 'id_spider' => 'int', 'last_seen' => 'int', 'stat_date' => 'date', 'page_hits' => 'int', Chris@76: ), Chris@76: array( Chris@76: $_SESSION['id_robot'], time(), $date, 1, Chris@76: ), Chris@76: array('id_spider', 'stat_date') Chris@76: ); Chris@76: } Chris@76: } Chris@76: // If we're tracking better stats than track, better stats - we sort out the today thing later. Chris@76: else Chris@76: { Chris@76: if ($modSettings['spider_mode'] > 2) Chris@76: { Chris@76: $url = $_GET + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']); Chris@76: unset($url['sesc'], $url[$context['session_var']]); Chris@76: $url = serialize($url); Chris@76: } Chris@76: else Chris@76: $url = ''; Chris@76: Chris@76: $smcFunc['db_insert']('insert', Chris@76: '{db_prefix}log_spider_hits', Chris@76: array('id_spider' => 'int', 'log_time' => 'int', 'url' => 'string'), Chris@76: array($_SESSION['id_robot'], time(), $url), Chris@76: array() Chris@76: ); Chris@76: } Chris@76: } Chris@76: Chris@76: // This function takes any unprocessed hits and turns them into stats. Chris@76: function consolidateSpiderStats() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('consolidate_spider_stats', ' Chris@76: SELECT id_spider, MAX(log_time) AS last_seen, COUNT(*) AS num_hits Chris@76: FROM {db_prefix}log_spider_hits Chris@76: WHERE processed = {int:not_processed} Chris@76: GROUP BY id_spider, MONTH(log_time), DAYOFMONTH(log_time)', Chris@76: array( Chris@76: 'not_processed' => 0, Chris@76: ) Chris@76: ); Chris@76: $spider_hits = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spider_hits[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (empty($spider_hits)) Chris@76: return; Chris@76: Chris@76: // Attempt to update the master data. Chris@76: $stat_inserts = array(); Chris@76: foreach ($spider_hits as $stat) Chris@76: { Chris@76: // We assume the max date is within the right day. Chris@76: $date = strftime('%Y-%m-%d', $stat['last_seen']); Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_spider_stats Chris@76: SET page_hits = page_hits + ' . $stat['num_hits'] . ', Chris@76: last_seen = CASE WHEN last_seen > {int:last_seen} THEN last_seen ELSE {int:last_seen} END Chris@76: WHERE id_spider = {int:current_spider} Chris@76: AND stat_date = {date:last_seen_date}', Chris@76: array( Chris@76: 'last_seen_date' => $date, Chris@76: 'last_seen' => $stat['last_seen'], Chris@76: 'current_spider' => $stat['id_spider'], Chris@76: ) Chris@76: ); Chris@76: if ($smcFunc['db_affected_rows']() == 0) Chris@76: $stat_inserts[] = array($date, $stat['id_spider'], $stat['num_hits'], $stat['last_seen']); Chris@76: } Chris@76: Chris@76: // New stats? Chris@76: if (!empty($stat_inserts)) Chris@76: $smcFunc['db_insert']('ignore', Chris@76: '{db_prefix}log_spider_stats', Chris@76: array('stat_date' => 'date', 'id_spider' => 'int', 'page_hits' => 'int', 'last_seen' => 'int'), Chris@76: $stat_inserts, Chris@76: array('stat_date', 'id_spider') Chris@76: ); Chris@76: Chris@76: // All processed. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}log_spider_hits Chris@76: SET processed = {int:is_processed} Chris@76: WHERE processed = {int:not_processed}', Chris@76: array( Chris@76: 'is_processed' => 1, Chris@76: 'not_processed' => 0, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: // See what spiders have been up to. Chris@76: function SpiderLogs() Chris@76: { Chris@76: global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings; Chris@76: Chris@76: // Load the template and language just incase. Chris@76: loadLanguage('Search'); Chris@76: loadTemplate('ManageSearch'); Chris@76: Chris@76: // Did they want to delete some entries? Chris@76: if (!empty($_POST['delete_entries']) && isset($_POST['older'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: $deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60); Chris@76: Chris@76: // Delete the entires. Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}log_spider_hits Chris@76: WHERE log_time < {int:delete_period}', Chris@76: array( Chris@76: 'delete_period' => $deleteTime, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'spider_logs', Chris@76: 'items_per_page' => 20, Chris@76: 'title' => $txt['spider_logs'], Chris@76: 'no_items_label' => $txt['spider_logs_empty'], Chris@76: 'base_href' => $context['admin_area'] == 'sengines' ? $scripturl . '?action=admin;area=sengines;sa=logs' : $scripturl . '?action=admin;area=logs;sa=spiderlog', Chris@76: 'default_sort_col' => 'log_time', Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getSpiderLogs', Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumSpiderLogs', Chris@76: ), Chris@76: 'columns' => array( Chris@76: 'name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'spider_name', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 's.spider_name', Chris@76: 'reverse' => 's.spider_name DESC', Chris@76: ), Chris@76: ), Chris@76: 'log_time' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_time'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: return timeformat($rowData[\'log_time\']); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'sl.id_hit DESC', Chris@76: 'reverse' => 'sl.id_hit', Chris@76: ), Chris@76: ), Chris@76: 'viewing' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_viewing'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'url', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'after_title', Chris@76: 'value' => $txt['spider_logs_info'], Chris@76: 'class' => 'smalltext', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: // Now determine the actions of the URLs. Chris@76: if (!empty($context['spider_logs']['rows'])) Chris@76: { Chris@76: $urls = array(); Chris@76: // Grab the current /url. Chris@76: foreach ($context['spider_logs']['rows'] as $k => $row) Chris@76: { Chris@76: // Feature disabled? Chris@76: if (empty($row['viewing']['value']) && isset($modSettings['spider_mode']) && $modSettings['spider_mode'] < 3) Chris@76: $context['spider_logs']['rows'][$k]['viewing']['value'] = '' . $txt['spider_disabled'] . ''; Chris@76: else Chris@76: $urls[$k] = array($row['viewing']['value'], -1); Chris@76: } Chris@76: Chris@76: // Now stick in the new URLs. Chris@76: require_once($sourcedir . '/Who.php'); Chris@76: $urls = determineActions($urls, 'whospider_'); Chris@76: foreach ($urls as $k => $new_url) Chris@76: { Chris@76: $context['spider_logs']['rows'][$k]['viewing']['value'] = $new_url; Chris@76: } Chris@76: } Chris@76: Chris@76: $context['page_title'] = $txt['spider_logs']; Chris@76: $context['sub_template'] = 'show_spider_logs'; Chris@76: $context['default_list'] = 'spider_logs'; Chris@76: } Chris@76: Chris@76: function list_getSpiderLogs($start, $items_per_page, $sort) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT sl.id_spider, sl.url, sl.log_time, s.spider_name Chris@76: FROM {db_prefix}log_spider_hits AS sl Chris@76: INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = sl.id_spider) Chris@76: ORDER BY ' . $sort . ' Chris@76: LIMIT ' . $start . ', ' . $items_per_page, Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $spider_logs = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spider_logs[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $spider_logs; Chris@76: } Chris@76: Chris@76: function list_getNumSpiderLogs() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS num_logs Chris@76: FROM {db_prefix}log_spider_hits', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($numLogs) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $numLogs; Chris@76: } Chris@76: Chris@76: // Show the spider statistics. Chris@76: function SpiderStats() Chris@76: { Chris@76: global $context, $txt, $sourcedir, $scripturl, $smcFunc; Chris@76: Chris@76: // Force an update of the stats every 60 seconds. Chris@76: if (!isset($_SESSION['spider_stat']) || $_SESSION['spider_stat'] < time() - 60) Chris@76: { Chris@76: consolidateSpiderStats(); Chris@76: $_SESSION['spider_stat'] = time(); Chris@76: } Chris@76: Chris@76: // Get the earliest and latest dates. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT MIN(stat_date) AS first_date, MAX(stat_date) AS last_date Chris@76: FROM {db_prefix}log_spider_stats', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: list ($min_date, $max_date) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $min_year = (int) substr($min_date, 0, 4); Chris@76: $max_year = (int) substr($max_date, 0, 4); Chris@76: $min_month = (int) substr($min_date, 5, 2); Chris@76: $max_month = (int) substr($max_date, 5, 2); Chris@76: Chris@76: // Prepare the dates for the drop down. Chris@76: $date_choices = array(); Chris@76: for ($y = $min_year; $y <= $max_year; $y++) Chris@76: for ($m = 1; $m <= 12; $m++) Chris@76: { Chris@76: // This doesn't count? Chris@76: if ($y == $min_year && $m < $min_month) Chris@76: continue; Chris@76: if ($y == $max_year && $m > $max_month) Chris@76: break; Chris@76: Chris@76: $date_choices[$y . $m] = $txt['months_short'][$m] . ' ' . $y; Chris@76: } Chris@76: Chris@76: // What are we currently viewing? Chris@76: $current_date = isset($_REQUEST['new_date']) && isset($date_choices[$_REQUEST['new_date']]) ? $_REQUEST['new_date'] : $max_date; Chris@76: Chris@76: // Prepare the HTML. Chris@76: $date_select = ' Chris@76: ' . $txt['spider_stats_select_month'] . ': Chris@76: Chris@76: '; Chris@76: Chris@76: // If we manually jumped to a date work out the offset. Chris@76: if (isset($_REQUEST['new_date'])) Chris@76: { Chris@76: $date_query = sprintf('%04d-%02d-01', substr($current_date, 0, 4), substr($current_date, 4)); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS offset Chris@76: FROM {db_prefix}log_spider_stats Chris@76: WHERE stat_date < {date:date_being_viewed}', Chris@76: array( Chris@76: 'date_being_viewed' => $date_query, Chris@76: ) Chris@76: ); Chris@76: list ($_REQUEST['start']) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'spider_stat_list', Chris@76: 'items_per_page' => 20, Chris@76: 'base_href' => $scripturl . '?action=admin;area=sengines;sa=stats', Chris@76: 'default_sort_col' => 'stat_date', Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getSpiderStats', Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumSpiderStats', Chris@76: ), Chris@76: 'no_items_label' => $txt['spider_stats_no_entries'], Chris@76: 'columns' => array( Chris@76: 'stat_date' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['date'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'stat_date', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'stat_date', Chris@76: 'reverse' => 'stat_date DESC', Chris@76: ), Chris@76: ), Chris@76: 'name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_name'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'spider_name', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 's.spider_name', Chris@76: 'reverse' => 's.spider_name DESC', Chris@76: ), Chris@76: ), Chris@76: 'page_hits' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['spider_stats_page_hits'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'page_hits', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'ss.page_hits', Chris@76: 'reverse' => 'ss.page_hits DESC', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=sengines;sa=stats', Chris@76: 'name' => 'spider_stat_list', Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => $date_select, Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: $context['sub_template'] = 'show_list'; Chris@76: $context['default_list'] = 'spider_stat_list'; Chris@76: } Chris@76: Chris@76: function list_getSpiderStats($start, $items_per_page, $sort) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT ss.id_spider, ss.stat_date, ss.page_hits, s.spider_name Chris@76: FROM {db_prefix}log_spider_stats AS ss Chris@76: INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = ss.id_spider) Chris@76: ORDER BY ' . $sort . ' Chris@76: LIMIT ' . $start . ', ' . $items_per_page, Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $spider_stats = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spider_stats[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $spider_stats; Chris@76: } Chris@76: Chris@76: function list_getNumSpiderStats() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS num_stats Chris@76: FROM {db_prefix}log_spider_stats', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($numStats) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $numStats; Chris@76: } Chris@76: Chris@76: // Recache spider names? Chris@76: function recacheSpiderNames() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_spider, spider_name Chris@76: FROM {db_prefix}spiders', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: $spiders = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $spiders[$row['id_spider']] = $row['spider_name']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: updateSettings(array('spider_name_cache' => serialize($spiders))); Chris@76: } Chris@76: Chris@76: // Sort the search engine table by user agent name to avoid misidentification of engine. Chris@76: function sortSpiderTable() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: db_extend('packages'); Chris@76: Chris@76: // Add a sorting column. Chris@76: $smcFunc['db_add_column']('{db_prefix}spiders', array('name' => 'temp_order', 'size' => 8, 'type' => 'mediumint', 'null' => false)); Chris@76: Chris@76: // Set the contents of this column. Chris@76: $smcFunc['db_query']('set_spider_order', ' Chris@76: UPDATE {db_prefix}spiders Chris@76: SET temp_order = LENGTH(user_agent)', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Order the table by this column. Chris@76: $smcFunc['db_query']('alter_table_spiders', ' Chris@76: ALTER TABLE {db_prefix}spiders Chris@76: ORDER BY temp_order DESC', Chris@76: array( Chris@76: 'db_error_skip' => true, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Remove the sorting column. Chris@76: $smcFunc['db_remove_column']('{db_prefix}spiders', 'temp_order'); Chris@76: } Chris@76: Chris@76: ?>