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: ?>