1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This file contains all the screens that relate to search engines. |
||
5 | * |
||
6 | * Simple Machines Forum (SMF) |
||
7 | * |
||
8 | * @package SMF |
||
9 | * @author Simple Machines https://www.simplemachines.org |
||
10 | * @copyright 2022 Simple Machines and individual contributors |
||
11 | * @license https://www.simplemachines.org/about/smf/license.php BSD |
||
12 | * |
||
13 | * @version 2.1.2 |
||
14 | */ |
||
15 | |||
16 | if (!defined('SMF')) |
||
17 | die('No direct access...'); |
||
18 | |||
19 | /** |
||
20 | * Entry point for this section. |
||
21 | */ |
||
22 | function SearchEngines() |
||
23 | { |
||
24 | global $context, $txt, $modSettings; |
||
25 | |||
26 | isAllowedTo('admin_forum'); |
||
27 | |||
28 | loadLanguage('Search'); |
||
29 | loadTemplate('ManageSearch'); |
||
30 | |||
31 | if (!empty($modSettings['spider_mode'])) |
||
32 | { |
||
33 | $subActions = array( |
||
34 | 'editspiders' => 'EditSpider', |
||
35 | 'logs' => 'SpiderLogs', |
||
36 | 'settings' => 'ManageSearchEngineSettings', |
||
37 | 'spiders' => 'ViewSpiders', |
||
38 | 'stats' => 'SpiderStats', |
||
39 | ); |
||
40 | $default = 'stats'; |
||
41 | } |
||
42 | else |
||
43 | { |
||
44 | $subActions = array( |
||
45 | 'settings' => 'ManageSearchEngineSettings', |
||
46 | ); |
||
47 | $default = 'settings'; |
||
48 | } |
||
49 | |||
50 | // Ensure we have a valid subaction. |
||
51 | $context['sub_action'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : $default; |
||
52 | |||
53 | $context['page_title'] = $txt['search_engines']; |
||
54 | |||
55 | // Some more tab data. |
||
56 | $context[$context['admin_menu_name']]['tab_data'] = array( |
||
57 | 'title' => $txt['search_engines'], |
||
58 | 'description' => $txt['search_engines_description'], |
||
59 | ); |
||
60 | |||
61 | call_integration_hook('integrate_manage_search_engines', array(&$subActions)); |
||
62 | |||
63 | // Call the function! |
||
64 | call_helper($subActions[$context['sub_action']]); |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * This is really just the settings page. |
||
69 | * |
||
70 | * @param bool $return_config Whether to return the config_vars array (used for admin search) |
||
71 | * @return void|array Returns nothing or returns the $config_vars array if $return_config is true |
||
72 | */ |
||
73 | function ManageSearchEngineSettings($return_config = false) |
||
74 | { |
||
75 | global $context, $txt, $scripturl, $sourcedir, $smcFunc; |
||
76 | |||
77 | $config_vars = array( |
||
78 | // How much detail? |
||
79 | array('select', 'spider_mode', 'subtext' => $txt['spider_mode_note'], array($txt['spider_mode_off'], $txt['spider_mode_standard'], $txt['spider_mode_high'], $txt['spider_mode_vhigh']), 'onchange' => 'disableFields();'), |
||
80 | 'spider_group' => array('select', 'spider_group', 'subtext' => $txt['spider_group_note'], array($txt['spider_group_none'], $txt['membergroups_members'])), |
||
81 | 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'])), |
||
82 | ); |
||
83 | |||
84 | // Set up a message. |
||
85 | $context['settings_message'] = sprintf($txt['spider_settings_desc'], $scripturl . '?action=admin;area=logs;sa=settings;' . $context['session_var'] . '=' . $context['session_id']); |
||
86 | |||
87 | // Do some javascript. |
||
88 | $javascript_function = ' |
||
89 | function disableFields() |
||
90 | { |
||
91 | disabledState = document.getElementById(\'spider_mode\').value == 0;'; |
||
92 | |||
93 | foreach ($config_vars as $variable) |
||
94 | if ($variable[1] != 'spider_mode') |
||
95 | $javascript_function .= ' |
||
96 | if (document.getElementById(\'' . $variable[1] . '\')) |
||
97 | document.getElementById(\'' . $variable[1] . '\').disabled = disabledState;'; |
||
98 | |||
99 | $javascript_function .= ' |
||
100 | } |
||
101 | disableFields();'; |
||
102 | |||
103 | call_integration_hook('integrate_modify_search_engine_settings', array(&$config_vars)); |
||
104 | |||
105 | if ($return_config) |
||
106 | return $config_vars; |
||
107 | |||
108 | // We need to load the groups for the spider group thingy. |
||
109 | $request = $smcFunc['db_query']('', ' |
||
110 | SELECT id_group, group_name |
||
111 | FROM {db_prefix}membergroups |
||
112 | WHERE id_group != {int:admin_group} |
||
113 | AND id_group != {int:moderator_group}', |
||
114 | array( |
||
115 | 'admin_group' => 1, |
||
116 | 'moderator_group' => 3, |
||
117 | ) |
||
118 | ); |
||
119 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
120 | $config_vars['spider_group'][2][$row['id_group']] = $row['group_name']; |
||
121 | $smcFunc['db_free_result']($request); |
||
122 | |||
123 | // Make sure it's valid - note that regular members are given id_group = 1 which is reversed in Load.php - no admins here! |
||
124 | if (isset($_POST['spider_group']) && !isset($config_vars['spider_group'][2][$_POST['spider_group']])) |
||
125 | $_POST['spider_group'] = 0; |
||
126 | |||
127 | // We'll want this for our easy save. |
||
128 | require_once($sourcedir . '/ManageServer.php'); |
||
129 | |||
130 | // Setup the template. |
||
131 | $context['page_title'] = $txt['settings']; |
||
132 | $context['sub_template'] = 'show_settings'; |
||
133 | |||
134 | // Are we saving them - are we?? |
||
135 | if (isset($_GET['save'])) |
||
136 | { |
||
137 | checkSession(); |
||
138 | |||
139 | call_integration_hook('integrate_save_search_engine_settings'); |
||
140 | saveDBSettings($config_vars); |
||
141 | recacheSpiderNames(); |
||
142 | $_SESSION['adm-save'] = true; |
||
143 | redirectexit('action=admin;area=sengines;sa=settings'); |
||
144 | } |
||
145 | |||
146 | // Final settings... |
||
147 | $context['post_url'] = $scripturl . '?action=admin;area=sengines;save;sa=settings'; |
||
148 | $context['settings_title'] = $txt['settings']; |
||
149 | addInlineJavaScript($javascript_function, true); |
||
150 | |||
151 | // Prepare the settings... |
||
152 | prepareDBSettingContext($config_vars); |
||
153 | } |
||
154 | |||
155 | /** |
||
156 | * View a list of all the spiders we know about. |
||
157 | */ |
||
158 | function ViewSpiders() |
||
159 | { |
||
160 | global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings; |
||
161 | |||
162 | if (!isset($_SESSION['spider_stat']) || $_SESSION['spider_stat'] < time() - 60) |
||
163 | { |
||
164 | consolidateSpiderStats(); |
||
165 | $_SESSION['spider_stat'] = time(); |
||
166 | } |
||
167 | |||
168 | // Are we adding a new one? |
||
169 | if (!empty($_POST['addSpider'])) |
||
170 | return EditSpider(); |
||
0 ignored issues
–
show
|
|||
171 | // User pressed the 'remove selection button'. |
||
172 | elseif (!empty($_POST['removeSpiders']) && !empty($_POST['remove']) && is_array($_POST['remove'])) |
||
173 | { |
||
174 | checkSession(); |
||
175 | validateToken('admin-ser'); |
||
176 | |||
177 | // Make sure every entry is a proper integer. |
||
178 | foreach ($_POST['remove'] as $index => $spider_id) |
||
179 | $_POST['remove'][(int) $index] = (int) $spider_id; |
||
180 | |||
181 | // Delete them all! |
||
182 | $smcFunc['db_query']('', ' |
||
183 | DELETE FROM {db_prefix}spiders |
||
184 | WHERE id_spider IN ({array_int:remove_list})', |
||
185 | array( |
||
186 | 'remove_list' => $_POST['remove'], |
||
187 | ) |
||
188 | ); |
||
189 | $smcFunc['db_query']('', ' |
||
190 | DELETE FROM {db_prefix}log_spider_hits |
||
191 | WHERE id_spider IN ({array_int:remove_list})', |
||
192 | array( |
||
193 | 'remove_list' => $_POST['remove'], |
||
194 | ) |
||
195 | ); |
||
196 | $smcFunc['db_query']('', ' |
||
197 | DELETE FROM {db_prefix}log_spider_stats |
||
198 | WHERE id_spider IN ({array_int:remove_list})', |
||
199 | array( |
||
200 | 'remove_list' => $_POST['remove'], |
||
201 | ) |
||
202 | ); |
||
203 | |||
204 | cache_put_data('spider_search', null, 300); |
||
205 | recacheSpiderNames(); |
||
206 | } |
||
207 | |||
208 | // Get the last seens. |
||
209 | $request = $smcFunc['db_query']('', ' |
||
210 | SELECT id_spider, MAX(last_seen) AS last_seen_time |
||
211 | FROM {db_prefix}log_spider_stats |
||
212 | GROUP BY id_spider', |
||
213 | array( |
||
214 | ) |
||
215 | ); |
||
216 | |||
217 | $context['spider_last_seen'] = array(); |
||
218 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
219 | $context['spider_last_seen'][$row['id_spider']] = $row['last_seen_time']; |
||
220 | $smcFunc['db_free_result']($request); |
||
221 | |||
222 | createToken('admin-ser'); |
||
223 | $listOptions = array( |
||
224 | 'id' => 'spider_list', |
||
225 | 'title' => $txt['spiders'], |
||
226 | 'items_per_page' => $modSettings['defaultMaxListItems'], |
||
227 | 'base_href' => $scripturl . '?action=admin;area=sengines;sa=spiders', |
||
228 | 'default_sort_col' => 'name', |
||
229 | 'get_items' => array( |
||
230 | 'function' => 'list_getSpiders', |
||
231 | ), |
||
232 | 'get_count' => array( |
||
233 | 'function' => 'list_getNumSpiders', |
||
234 | ), |
||
235 | 'no_items_label' => $txt['spiders_no_entries'], |
||
236 | 'columns' => array( |
||
237 | 'name' => array( |
||
238 | 'header' => array( |
||
239 | 'value' => $txt['spider_name'], |
||
240 | ), |
||
241 | 'data' => array( |
||
242 | 'function' => function($rowData) use ($smcFunc, $scripturl) |
||
243 | { |
||
244 | return sprintf('<a href="%1$s?action=admin;area=sengines;sa=editspiders;sid=%2$d">%3$s</a>', $scripturl, $rowData['id_spider'], $smcFunc['htmlspecialchars']($rowData['spider_name'])); |
||
245 | }, |
||
246 | ), |
||
247 | 'sort' => array( |
||
248 | 'default' => 'spider_name DESC', |
||
249 | 'reverse' => 'spider_name', |
||
250 | ), |
||
251 | ), |
||
252 | 'last_seen' => array( |
||
253 | 'header' => array( |
||
254 | 'value' => $txt['spider_last_seen'], |
||
255 | ), |
||
256 | 'data' => array( |
||
257 | 'function' => function($rowData) use ($context, $txt) |
||
258 | { |
||
259 | return isset($context['spider_last_seen'][$rowData['id_spider']]) ? timeformat($context['spider_last_seen'][$rowData['id_spider']]) : $txt['spider_last_never']; |
||
260 | }, |
||
261 | ), |
||
262 | ), |
||
263 | 'user_agent' => array( |
||
264 | 'header' => array( |
||
265 | 'value' => $txt['spider_agent'], |
||
266 | ), |
||
267 | 'data' => array( |
||
268 | 'db_htmlsafe' => 'user_agent', |
||
269 | ), |
||
270 | 'sort' => array( |
||
271 | 'default' => 'user_agent', |
||
272 | 'reverse' => 'user_agent DESC', |
||
273 | ), |
||
274 | ), |
||
275 | 'ip_info' => array( |
||
276 | 'header' => array( |
||
277 | 'value' => $txt['spider_ip_info'], |
||
278 | ), |
||
279 | 'data' => array( |
||
280 | 'db_htmlsafe' => 'ip_info', |
||
281 | 'class' => 'smalltext', |
||
282 | ), |
||
283 | 'sort' => array( |
||
284 | 'default' => 'ip_info', |
||
285 | 'reverse' => 'ip_info DESC', |
||
286 | ), |
||
287 | ), |
||
288 | 'check' => array( |
||
289 | 'header' => array( |
||
290 | 'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">', |
||
291 | 'class' => 'centercol', |
||
292 | ), |
||
293 | 'data' => array( |
||
294 | 'sprintf' => array( |
||
295 | 'format' => '<input type="checkbox" name="remove[]" value="%1$d">', |
||
296 | 'params' => array( |
||
297 | 'id_spider' => false, |
||
298 | ), |
||
299 | ), |
||
300 | 'class' => 'centercol', |
||
301 | ), |
||
302 | ), |
||
303 | ), |
||
304 | 'form' => array( |
||
305 | 'href' => $scripturl . '?action=admin;area=sengines;sa=spiders', |
||
306 | 'token' => 'admin-ser', |
||
307 | ), |
||
308 | 'additional_rows' => array( |
||
309 | array( |
||
310 | 'position' => 'bottom_of_list', |
||
311 | 'value' => ' |
||
312 | <input type="submit" name="removeSpiders" value="' . $txt['spiders_remove_selected'] . '" data-confirm="' . $txt['spider_remove_selected_confirm'] . '" class="button you_sure"> |
||
313 | <input type="submit" name="addSpider" value="' . $txt['spiders_add'] . '" class="button"> |
||
314 | ', |
||
315 | ), |
||
316 | ), |
||
317 | ); |
||
318 | |||
319 | require_once($sourcedir . '/Subs-List.php'); |
||
320 | createList($listOptions); |
||
321 | |||
322 | $context['sub_template'] = 'show_list'; |
||
323 | $context['default_list'] = 'spider_list'; |
||
324 | } |
||
325 | |||
326 | /** |
||
327 | * Callback function for createList() |
||
328 | * |
||
329 | * @param int $start The item to start with (for pagination purposes) |
||
330 | * @param int $items_per_page The number of items to show per page |
||
331 | * @param string $sort A string indicating how to sort the results |
||
332 | * @return array An array of information about known spiders |
||
333 | */ |
||
334 | function list_getSpiders($start, $items_per_page, $sort) |
||
335 | { |
||
336 | global $smcFunc; |
||
337 | |||
338 | $request = $smcFunc['db_query']('', ' |
||
339 | SELECT id_spider, spider_name, user_agent, ip_info |
||
340 | FROM {db_prefix}spiders |
||
341 | ORDER BY {raw:sort} |
||
342 | LIMIT {int:start}, {int:items}', |
||
343 | array( |
||
344 | 'sort' => $sort, |
||
345 | 'start' => $start, |
||
346 | 'items' => $items_per_page, |
||
347 | ) |
||
348 | ); |
||
349 | $spiders = array(); |
||
350 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
351 | $spiders[$row['id_spider']] = $row; |
||
352 | $smcFunc['db_free_result']($request); |
||
353 | |||
354 | return $spiders; |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * Callback function for createList() |
||
359 | * |
||
360 | * @return int The number of known spiders |
||
361 | */ |
||
362 | function list_getNumSpiders() |
||
363 | { |
||
364 | global $smcFunc; |
||
365 | |||
366 | $request = $smcFunc['db_query']('', ' |
||
367 | SELECT COUNT(*) AS num_spiders |
||
368 | FROM {db_prefix}spiders', |
||
369 | array( |
||
370 | ) |
||
371 | ); |
||
372 | list ($numSpiders) = $smcFunc['db_fetch_row']($request); |
||
373 | $smcFunc['db_free_result']($request); |
||
374 | |||
375 | return $numSpiders; |
||
376 | } |
||
377 | |||
378 | /** |
||
379 | * Here we can add, and edit, spider info! |
||
380 | */ |
||
381 | function EditSpider() |
||
382 | { |
||
383 | global $context, $smcFunc, $txt; |
||
384 | |||
385 | // Some standard stuff. |
||
386 | $context['id_spider'] = !empty($_GET['sid']) ? (int) $_GET['sid'] : 0; |
||
387 | $context['page_title'] = $context['id_spider'] ? $txt['spiders_edit'] : $txt['spiders_add']; |
||
388 | $context['sub_template'] = 'spider_edit'; |
||
389 | |||
390 | // Are we saving? |
||
391 | if (!empty($_POST['save'])) |
||
392 | { |
||
393 | checkSession(); |
||
394 | validateToken('admin-ses'); |
||
395 | |||
396 | foreach (array('spider_name', 'spider_agent') as $key) |
||
397 | $_POST[$key] = trim($smcFunc['normalize']($_POST[$key])); |
||
398 | |||
399 | $ips = array(); |
||
400 | // Check the IP range is valid. |
||
401 | $ip_sets = explode(',', $_POST['spider_ip']); |
||
402 | foreach ($ip_sets as $set) |
||
403 | { |
||
404 | $test = ip2range(trim($set)); |
||
405 | if (!empty($test)) |
||
406 | $ips[] = $set; |
||
407 | } |
||
408 | $ips = implode(',', $ips); |
||
409 | |||
410 | // Goes in as it is... |
||
411 | if ($context['id_spider']) |
||
412 | $smcFunc['db_query']('', ' |
||
413 | UPDATE {db_prefix}spiders |
||
414 | SET spider_name = {string:spider_name}, user_agent = {string:spider_agent}, |
||
415 | ip_info = {string:ip_info} |
||
416 | WHERE id_spider = {int:current_spider}', |
||
417 | array( |
||
418 | 'current_spider' => $context['id_spider'], |
||
419 | 'spider_name' => $_POST['spider_name'], |
||
420 | 'spider_agent' => $_POST['spider_agent'], |
||
421 | 'ip_info' => $ips, |
||
422 | ) |
||
423 | ); |
||
424 | else |
||
425 | $smcFunc['db_insert']('insert', |
||
426 | '{db_prefix}spiders', |
||
427 | array( |
||
428 | 'spider_name' => 'string', 'user_agent' => 'string', 'ip_info' => 'string', |
||
429 | ), |
||
430 | array( |
||
431 | $_POST['spider_name'], $_POST['spider_agent'], $ips, |
||
432 | ), |
||
433 | array('id_spider') |
||
434 | ); |
||
435 | |||
436 | cache_put_data('spider_search', null); |
||
437 | recacheSpiderNames(); |
||
438 | |||
439 | redirectexit('action=admin;area=sengines;sa=spiders'); |
||
440 | } |
||
441 | |||
442 | // The default is new. |
||
443 | $context['spider'] = array( |
||
444 | 'id' => 0, |
||
445 | 'name' => '', |
||
446 | 'agent' => '', |
||
447 | 'ip_info' => '', |
||
448 | ); |
||
449 | |||
450 | // An edit? |
||
451 | if ($context['id_spider']) |
||
452 | { |
||
453 | $request = $smcFunc['db_query']('', ' |
||
454 | SELECT id_spider, spider_name, user_agent, ip_info |
||
455 | FROM {db_prefix}spiders |
||
456 | WHERE id_spider = {int:current_spider}', |
||
457 | array( |
||
458 | 'current_spider' => $context['id_spider'], |
||
459 | ) |
||
460 | ); |
||
461 | if ($row = $smcFunc['db_fetch_assoc']($request)) |
||
462 | $context['spider'] = array( |
||
463 | 'id' => $row['id_spider'], |
||
464 | 'name' => $row['spider_name'], |
||
465 | 'agent' => $row['user_agent'], |
||
466 | 'ip_info' => $row['ip_info'], |
||
467 | ); |
||
468 | $smcFunc['db_free_result']($request); |
||
469 | } |
||
470 | |||
471 | createToken('admin-ses'); |
||
472 | } |
||
473 | |||
474 | /** |
||
475 | * Do we think the current user is a spider? |
||
476 | * |
||
477 | * @todo Should this not be... you know... in a different file? |
||
478 | * @return int The ID of the spider if it's known or 0 if it isn't known/isn't a spider |
||
479 | */ |
||
480 | function SpiderCheck() |
||
481 | { |
||
482 | global $modSettings, $smcFunc; |
||
483 | |||
484 | if (isset($_SESSION['id_robot'])) |
||
485 | unset($_SESSION['id_robot']); |
||
486 | $_SESSION['robot_check'] = time(); |
||
487 | |||
488 | // We cache the spider data for ten minutes if we can. |
||
489 | if (($spider_data = cache_get_data('spider_search', 600)) === null) |
||
490 | { |
||
491 | $request = $smcFunc['db_query']('', ' |
||
492 | SELECT id_spider, user_agent, ip_info |
||
493 | FROM {db_prefix}spiders |
||
494 | ORDER BY LENGTH(user_agent) DESC', |
||
495 | array( |
||
496 | ) |
||
497 | ); |
||
498 | $spider_data = array(); |
||
499 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
500 | $spider_data[] = $row; |
||
501 | $smcFunc['db_free_result']($request); |
||
502 | |||
503 | cache_put_data('spider_search', $spider_data, 600); |
||
504 | } |
||
505 | |||
506 | if (empty($spider_data)) |
||
507 | return false; |
||
508 | |||
509 | // Only do these bits once. |
||
510 | $ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']); |
||
511 | |||
512 | foreach ($spider_data as $spider) |
||
513 | { |
||
514 | // User agent is easy. |
||
515 | if (!empty($spider['user_agent']) && strpos($ci_user_agent, strtolower($spider['user_agent'])) !== false) |
||
516 | $_SESSION['id_robot'] = $spider['id_spider']; |
||
517 | // IP stuff is harder. |
||
518 | elseif ($_SERVER['REMOTE_ADDR']) |
||
519 | { |
||
520 | $ips = explode(',', $spider['ip_info']); |
||
521 | foreach ($ips as $ip) |
||
522 | { |
||
523 | if ($ip === '') |
||
524 | continue; |
||
525 | |||
526 | $ip = ip2range($ip); |
||
527 | if (!empty($ip)) |
||
528 | { |
||
529 | if (inet_ptod($ip['low']) <= inet_ptod($_SERVER['REMOTE_ADDR']) && inet_ptod($ip['high']) >= inet_ptod($_SERVER['REMOTE_ADDR'])) |
||
530 | $_SESSION['id_robot'] = $spider['id_spider']; |
||
531 | } |
||
532 | } |
||
533 | } |
||
534 | |||
535 | if (isset($_SESSION['id_robot'])) |
||
536 | break; |
||
537 | } |
||
538 | |||
539 | // If this is low server tracking then log the spider here as opposed to the main logging function. |
||
540 | if (!empty($modSettings['spider_mode']) && $modSettings['spider_mode'] == 1 && !empty($_SESSION['id_robot'])) |
||
541 | logSpider(); |
||
542 | |||
543 | return !empty($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0; |
||
544 | } |
||
545 | |||
546 | /** |
||
547 | * Log the spider presence online. |
||
548 | * |
||
549 | * @todo Different file? |
||
550 | */ |
||
551 | function logSpider() |
||
552 | { |
||
553 | global $smcFunc, $modSettings, $context; |
||
554 | |||
555 | if (empty($modSettings['spider_mode']) || empty($_SESSION['id_robot'])) |
||
556 | return; |
||
557 | |||
558 | // Attempt to update today's entry. |
||
559 | if ($modSettings['spider_mode'] == 1) |
||
560 | { |
||
561 | $date = smf_strftime('%Y-%m-%d', time()); |
||
562 | $smcFunc['db_query']('', ' |
||
563 | UPDATE {db_prefix}log_spider_stats |
||
564 | SET last_seen = {int:current_time}, page_hits = page_hits + 1 |
||
565 | WHERE id_spider = {int:current_spider} |
||
566 | AND stat_date = {date:current_date}', |
||
567 | array( |
||
568 | 'current_date' => $date, |
||
569 | 'current_time' => time(), |
||
570 | 'current_spider' => $_SESSION['id_robot'], |
||
571 | ) |
||
572 | ); |
||
573 | |||
574 | // Nothing updated? |
||
575 | if ($smcFunc['db_affected_rows']() == 0) |
||
576 | { |
||
577 | $smcFunc['db_insert']('ignore', |
||
578 | '{db_prefix}log_spider_stats', |
||
579 | array( |
||
580 | 'id_spider' => 'int', 'last_seen' => 'int', 'stat_date' => 'date', 'page_hits' => 'int', |
||
581 | ), |
||
582 | array( |
||
583 | $_SESSION['id_robot'], time(), $date, 1, |
||
584 | ), |
||
585 | array('id_spider', 'stat_date') |
||
586 | ); |
||
587 | } |
||
588 | } |
||
589 | // If we're tracking better stats than track, better stats - we sort out the today thing later. |
||
590 | else |
||
591 | { |
||
592 | if ($modSettings['spider_mode'] > 2) |
||
593 | { |
||
594 | $url = $_GET + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']); |
||
595 | unset($url['sesc'], $url[$context['session_var']]); |
||
596 | $url = $smcFunc['json_encode']($url); |
||
597 | } |
||
598 | else |
||
599 | $url = ''; |
||
600 | |||
601 | $smcFunc['db_insert']('insert', |
||
602 | '{db_prefix}log_spider_hits', |
||
603 | array('id_spider' => 'int', 'log_time' => 'int', 'url' => 'string'), |
||
604 | array($_SESSION['id_robot'], time(), $url), |
||
605 | array() |
||
606 | ); |
||
607 | } |
||
608 | } |
||
609 | |||
610 | /** |
||
611 | * This function takes any unprocessed hits and turns them into stats. |
||
612 | */ |
||
613 | function consolidateSpiderStats() |
||
614 | { |
||
615 | global $smcFunc; |
||
616 | |||
617 | $request = $smcFunc['db_query']('', ' |
||
618 | SELECT id_spider, MAX(log_time) AS last_seen, COUNT(*) AS num_hits |
||
619 | FROM {db_prefix}log_spider_hits |
||
620 | WHERE processed = {int:not_processed} |
||
621 | GROUP BY id_spider, MONTH(log_time), DAYOFMONTH(log_time)', |
||
622 | array( |
||
623 | 'not_processed' => 0, |
||
624 | ) |
||
625 | ); |
||
626 | $spider_hits = array(); |
||
627 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
628 | $spider_hits[] = $row; |
||
629 | $smcFunc['db_free_result']($request); |
||
630 | |||
631 | if (empty($spider_hits)) |
||
632 | return; |
||
633 | |||
634 | // Attempt to update the master data. |
||
635 | $stat_inserts = array(); |
||
636 | foreach ($spider_hits as $stat) |
||
637 | { |
||
638 | // We assume the max date is within the right day. |
||
639 | $date = smf_strftime('%Y-%m-%d', $stat['last_seen']); |
||
640 | $smcFunc['db_query']('', ' |
||
641 | UPDATE {db_prefix}log_spider_stats |
||
642 | SET page_hits = page_hits + {int:hits}, |
||
643 | last_seen = CASE WHEN last_seen > {int:last_seen} THEN last_seen ELSE {int:last_seen} END |
||
644 | WHERE id_spider = {int:current_spider} |
||
645 | AND stat_date = {date:last_seen_date}', |
||
646 | array( |
||
647 | 'last_seen_date' => $date, |
||
648 | 'last_seen' => $stat['last_seen'], |
||
649 | 'current_spider' => $stat['id_spider'], |
||
650 | 'hits' => $stat['num_hits'], |
||
651 | ) |
||
652 | ); |
||
653 | if ($smcFunc['db_affected_rows']() == 0) |
||
654 | $stat_inserts[] = array($date, $stat['id_spider'], $stat['num_hits'], $stat['last_seen']); |
||
655 | } |
||
656 | |||
657 | // New stats? |
||
658 | if (!empty($stat_inserts)) |
||
659 | $smcFunc['db_insert']('ignore', |
||
660 | '{db_prefix}log_spider_stats', |
||
661 | array('stat_date' => 'date', 'id_spider' => 'int', 'page_hits' => 'int', 'last_seen' => 'int'), |
||
662 | $stat_inserts, |
||
663 | array('stat_date', 'id_spider') |
||
664 | ); |
||
665 | |||
666 | // All processed. |
||
667 | $smcFunc['db_query']('', ' |
||
668 | UPDATE {db_prefix}log_spider_hits |
||
669 | SET processed = {int:is_processed} |
||
670 | WHERE processed = {int:not_processed}', |
||
671 | array( |
||
672 | 'is_processed' => 1, |
||
673 | 'not_processed' => 0, |
||
674 | ) |
||
675 | ); |
||
676 | } |
||
677 | |||
678 | /** |
||
679 | * See what spiders have been up to. |
||
680 | */ |
||
681 | function SpiderLogs() |
||
682 | { |
||
683 | global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings; |
||
684 | |||
685 | // Load the template and language just incase. |
||
686 | loadLanguage('Search'); |
||
687 | loadTemplate('ManageSearch'); |
||
688 | |||
689 | // Did they want to delete some entries? |
||
690 | if ((!empty($_POST['delete_entries']) && isset($_POST['older'])) || !empty($_POST['removeAll'])) |
||
691 | { |
||
692 | checkSession(); |
||
693 | validateToken('admin-sl'); |
||
694 | |||
695 | if (!empty($_POST['delete_entries']) && isset($_POST['older'])) |
||
696 | { |
||
697 | $deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60); |
||
698 | |||
699 | // Delete the entires. |
||
700 | $smcFunc['db_query']('', ' |
||
701 | DELETE FROM {db_prefix}log_spider_hits |
||
702 | WHERE log_time < {int:delete_period}', |
||
703 | array( |
||
704 | 'delete_period' => $deleteTime, |
||
705 | ) |
||
706 | ); |
||
707 | } |
||
708 | else |
||
709 | { |
||
710 | // Deleting all of them |
||
711 | $smcFunc['db_query']('', ' |
||
712 | TRUNCATE TABLE {db_prefix}log_spider_hits', |
||
713 | array() |
||
714 | ); |
||
715 | } |
||
716 | } |
||
717 | |||
718 | $listOptions = array( |
||
719 | 'id' => 'spider_logs', |
||
720 | 'items_per_page' => $modSettings['defaultMaxListItems'], |
||
721 | 'title' => $txt['spider_logs'], |
||
722 | 'no_items_label' => $txt['spider_logs_empty'], |
||
723 | 'base_href' => $context['admin_area'] == 'sengines' ? $scripturl . '?action=admin;area=sengines;sa=logs' : $scripturl . '?action=admin;area=logs;sa=spiderlog', |
||
724 | 'default_sort_col' => 'log_time', |
||
725 | 'get_items' => array( |
||
726 | 'function' => 'list_getSpiderLogs', |
||
727 | ), |
||
728 | 'get_count' => array( |
||
729 | 'function' => 'list_getNumSpiderLogs', |
||
730 | ), |
||
731 | 'columns' => array( |
||
732 | 'name' => array( |
||
733 | 'header' => array( |
||
734 | 'value' => $txt['spider'], |
||
735 | ), |
||
736 | 'data' => array( |
||
737 | 'db' => 'spider_name', |
||
738 | ), |
||
739 | 'sort' => array( |
||
740 | 'default' => 's.spider_name', |
||
741 | 'reverse' => 's.spider_name DESC', |
||
742 | ), |
||
743 | ), |
||
744 | 'log_time' => array( |
||
745 | 'header' => array( |
||
746 | 'value' => $txt['spider_time'], |
||
747 | ), |
||
748 | 'data' => array( |
||
749 | 'function' => function($rowData) |
||
750 | { |
||
751 | return timeformat($rowData['log_time']); |
||
752 | }, |
||
753 | ), |
||
754 | 'sort' => array( |
||
755 | 'default' => 'sl.id_hit DESC', |
||
756 | 'reverse' => 'sl.id_hit', |
||
757 | ), |
||
758 | ), |
||
759 | 'viewing' => array( |
||
760 | 'header' => array( |
||
761 | 'value' => $txt['spider_viewing'], |
||
762 | ), |
||
763 | 'data' => array( |
||
764 | 'db' => 'url', |
||
765 | ), |
||
766 | ), |
||
767 | ), |
||
768 | 'form' => array( |
||
769 | 'token' => 'admin-sl', |
||
770 | 'href' => $scripturl . '?action=admin;area=sengines;sa=logs', |
||
771 | ), |
||
772 | 'additional_rows' => array( |
||
773 | array( |
||
774 | 'position' => 'after_title', |
||
775 | 'value' => $txt['spider_logs_info'], |
||
776 | ), |
||
777 | array( |
||
778 | 'position' => 'below_table_data', |
||
779 | 'value' => '<input type="submit" name="removeAll" value="' . $txt['spider_log_empty_log'] . '" data-confirm="' . $txt['spider_log_empty_log_confirm'] . '" class="button you_sure">', |
||
780 | ), |
||
781 | ), |
||
782 | ); |
||
783 | |||
784 | createToken('admin-sl'); |
||
785 | |||
786 | require_once($sourcedir . '/Subs-List.php'); |
||
787 | createList($listOptions); |
||
788 | |||
789 | // Now determine the actions of the URLs. |
||
790 | if (!empty($context['spider_logs']['rows'])) |
||
791 | { |
||
792 | $urls = array(); |
||
793 | |||
794 | // Grab the current /url. |
||
795 | foreach ($context['spider_logs']['rows'] as $k => $row) |
||
796 | { |
||
797 | // Feature disabled? |
||
798 | if (empty($row['data']['viewing']['value']) && isset($modSettings['spider_mode']) && $modSettings['spider_mode'] < 3) |
||
799 | $context['spider_logs']['rows'][$k]['viewing']['value'] = '<em>' . $txt['spider_disabled'] . '</em>'; |
||
800 | else |
||
801 | $urls[$k] = array($row['data']['viewing']['value'], -1); |
||
802 | } |
||
803 | |||
804 | // Now stick in the new URLs. |
||
805 | require_once($sourcedir . '/Who.php'); |
||
806 | $urls = determineActions($urls, 'whospider_'); |
||
807 | foreach ($urls as $k => $new_url) |
||
808 | { |
||
809 | if (is_array($new_url)) |
||
810 | { |
||
811 | $context['spider_logs']['rows'][$k]['data']['viewing']['value'] = $txt[$new_url['label']]; |
||
812 | $context['spider_logs']['rows'][$k]['data']['viewing']['class'] = $new_url['class']; |
||
813 | } else |
||
814 | $context['spider_logs']['rows'][$k]['data']['viewing']['value'] = $new_url; |
||
815 | } |
||
816 | } |
||
817 | |||
818 | $context['page_title'] = $txt['spider_logs']; |
||
819 | $context['sub_template'] = 'show_spider_logs'; |
||
820 | $context['default_list'] = 'spider_logs'; |
||
821 | } |
||
822 | |||
823 | /** |
||
824 | * Callback function for createList() |
||
825 | * |
||
826 | * @param int $start The item to start with (for pagination purposes) |
||
827 | * @param int $items_per_page How many items to show per page |
||
828 | * @param string $sort A string indicating how to sort the results |
||
829 | * @return array An array of spider log data |
||
830 | */ |
||
831 | function list_getSpiderLogs($start, $items_per_page, $sort) |
||
832 | { |
||
833 | global $smcFunc; |
||
834 | |||
835 | $request = $smcFunc['db_query']('', ' |
||
836 | SELECT sl.id_spider, sl.url, sl.log_time, s.spider_name |
||
837 | FROM {db_prefix}log_spider_hits AS sl |
||
838 | INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = sl.id_spider) |
||
839 | ORDER BY {raw:sort} |
||
840 | LIMIT {int:start}, {int:items}', |
||
841 | array( |
||
842 | 'sort' => $sort, |
||
843 | 'start' => $start, |
||
844 | 'items' => $items_per_page, |
||
845 | ) |
||
846 | ); |
||
847 | $spider_logs = array(); |
||
848 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
849 | $spider_logs[] = $row; |
||
850 | $smcFunc['db_free_result']($request); |
||
851 | |||
852 | return $spider_logs; |
||
853 | } |
||
854 | |||
855 | /** |
||
856 | * Callback function for createList() |
||
857 | * |
||
858 | * @return int The number of spider log entries |
||
859 | */ |
||
860 | function list_getNumSpiderLogs() |
||
861 | { |
||
862 | global $smcFunc; |
||
863 | |||
864 | $request = $smcFunc['db_query']('', ' |
||
865 | SELECT COUNT(*) AS num_logs |
||
866 | FROM {db_prefix}log_spider_hits', |
||
867 | array( |
||
868 | ) |
||
869 | ); |
||
870 | list ($numLogs) = $smcFunc['db_fetch_row']($request); |
||
871 | $smcFunc['db_free_result']($request); |
||
872 | |||
873 | return $numLogs; |
||
874 | } |
||
875 | |||
876 | /** |
||
877 | * Show the spider statistics. |
||
878 | */ |
||
879 | function SpiderStats() |
||
880 | { |
||
881 | global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings; |
||
882 | |||
883 | // Force an update of the stats every 60 seconds. |
||
884 | if (!isset($_SESSION['spider_stat']) || $_SESSION['spider_stat'] < time() - 60) |
||
885 | { |
||
886 | consolidateSpiderStats(); |
||
887 | $_SESSION['spider_stat'] = time(); |
||
888 | } |
||
889 | |||
890 | // Are we cleaning up some old stats? |
||
891 | if (!empty($_POST['delete_entries']) && isset($_POST['older'])) |
||
892 | { |
||
893 | checkSession(); |
||
894 | validateToken('admin-ss'); |
||
895 | |||
896 | $deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60); |
||
897 | |||
898 | // Delete the entires. |
||
899 | $smcFunc['db_query']('', ' |
||
900 | DELETE FROM {db_prefix}log_spider_stats |
||
901 | WHERE last_seen < {int:delete_period}', |
||
902 | array( |
||
903 | 'delete_period' => $deleteTime, |
||
904 | ) |
||
905 | ); |
||
906 | } |
||
907 | |||
908 | // Get the earliest and latest dates. |
||
909 | $request = $smcFunc['db_query']('', ' |
||
910 | SELECT MIN(stat_date) AS first_date, MAX(stat_date) AS last_date |
||
911 | FROM {db_prefix}log_spider_stats', |
||
912 | array( |
||
913 | ) |
||
914 | ); |
||
915 | |||
916 | list ($min_date, $max_date) = $smcFunc['db_fetch_row']($request); |
||
917 | $smcFunc['db_free_result']($request); |
||
918 | |||
919 | $min_year = (int) substr($min_date, 0, 4); |
||
920 | $max_year = (int) substr($max_date, 0, 4); |
||
921 | $min_month = (int) substr($min_date, 5, 2); |
||
922 | $max_month = (int) substr($max_date, 5, 2); |
||
923 | |||
924 | // Prepare the dates for the drop down. |
||
925 | $date_choices = array(); |
||
926 | for ($y = $min_year; $y <= $max_year; $y++) |
||
927 | for ($m = 1; $m <= 12; $m++) |
||
928 | { |
||
929 | // This doesn't count? |
||
930 | if ($y == $min_year && $m < $min_month) |
||
931 | continue; |
||
932 | if ($y == $max_year && $m > $max_month) |
||
933 | break; |
||
934 | |||
935 | $date_choices[$y . $m] = $txt['months_short'][$m] . ' ' . $y; |
||
936 | } |
||
937 | |||
938 | // What are we currently viewing? |
||
939 | $current_date = isset($_REQUEST['new_date']) && isset($date_choices[$_REQUEST['new_date']]) ? $_REQUEST['new_date'] : $max_date; |
||
940 | |||
941 | // Prepare the HTML. |
||
942 | if (!empty($date_choices)) |
||
943 | { |
||
944 | $date_select = ' |
||
945 | ' . $txt['spider_stats_select_month'] . ': |
||
946 | <select name="new_date" onchange="document.spider_stat_list.submit();">'; |
||
947 | |||
948 | foreach ($date_choices as $id => $text) |
||
949 | $date_select .= ' |
||
950 | <option value="' . $id . '"' . ($current_date == $id ? ' selected' : '') . '>' . $text . '</option>'; |
||
951 | |||
952 | $date_select .= ' |
||
953 | </select> |
||
954 | <noscript> |
||
955 | <input type="submit" name="go" value="' . $txt['go'] . '" class="button"> |
||
956 | </noscript>'; |
||
957 | } |
||
958 | |||
959 | // If we manually jumped to a date work out the offset. |
||
960 | if (isset($_REQUEST['new_date'])) |
||
961 | { |
||
962 | $date_query = sprintf('%04d-%02d-01', substr($current_date, 0, 4), substr($current_date, 4)); |
||
963 | |||
964 | $request = $smcFunc['db_query']('', ' |
||
965 | SELECT COUNT(*) AS offset |
||
966 | FROM {db_prefix}log_spider_stats |
||
967 | WHERE stat_date < {date:date_being_viewed}', |
||
968 | array( |
||
969 | 'date_being_viewed' => $date_query, |
||
970 | ) |
||
971 | ); |
||
972 | list ($_REQUEST['start']) = $smcFunc['db_fetch_row']($request); |
||
973 | $smcFunc['db_free_result']($request); |
||
974 | } |
||
975 | |||
976 | $listOptions = array( |
||
977 | 'id' => 'spider_stat_list', |
||
978 | 'title' => $txt['spider_stats'], |
||
979 | 'items_per_page' => $modSettings['defaultMaxListItems'], |
||
980 | 'base_href' => $scripturl . '?action=admin;area=sengines;sa=stats', |
||
981 | 'default_sort_col' => 'stat_date', |
||
982 | 'get_items' => array( |
||
983 | 'function' => 'list_getSpiderStats', |
||
984 | ), |
||
985 | 'get_count' => array( |
||
986 | 'function' => 'list_getNumSpiderStats', |
||
987 | ), |
||
988 | 'no_items_label' => $txt['spider_stats_no_entries'], |
||
989 | 'columns' => array( |
||
990 | 'stat_date' => array( |
||
991 | 'header' => array( |
||
992 | 'value' => $txt['date'], |
||
993 | ), |
||
994 | 'data' => array( |
||
995 | 'db' => 'stat_date', |
||
996 | ), |
||
997 | 'sort' => array( |
||
998 | 'default' => 'stat_date', |
||
999 | 'reverse' => 'stat_date DESC', |
||
1000 | ), |
||
1001 | ), |
||
1002 | 'name' => array( |
||
1003 | 'header' => array( |
||
1004 | 'value' => $txt['spider_name'], |
||
1005 | ), |
||
1006 | 'data' => array( |
||
1007 | 'db' => 'spider_name', |
||
1008 | ), |
||
1009 | 'sort' => array( |
||
1010 | 'default' => 's.spider_name', |
||
1011 | 'reverse' => 's.spider_name DESC', |
||
1012 | ), |
||
1013 | ), |
||
1014 | 'page_hits' => array( |
||
1015 | 'header' => array( |
||
1016 | 'value' => $txt['spider_stats_page_hits'], |
||
1017 | ), |
||
1018 | 'data' => array( |
||
1019 | 'db' => 'page_hits', |
||
1020 | ), |
||
1021 | 'sort' => array( |
||
1022 | 'default' => 'ss.page_hits', |
||
1023 | 'reverse' => 'ss.page_hits DESC', |
||
1024 | ), |
||
1025 | ), |
||
1026 | ), |
||
1027 | 'form' => array( |
||
1028 | 'href' => $scripturl . '?action=admin;area=sengines;sa=stats', |
||
1029 | 'name' => 'spider_stat_list', |
||
1030 | ), |
||
1031 | 'additional_rows' => empty($date_select) ? array() : array( |
||
1032 | array( |
||
1033 | 'position' => 'below_table_data', |
||
1034 | 'value' => $date_select, |
||
1035 | 'style' => 'text-align: right;', |
||
1036 | ), |
||
1037 | ), |
||
1038 | ); |
||
1039 | |||
1040 | createToken('admin-ss'); |
||
1041 | |||
1042 | require_once($sourcedir . '/Subs-List.php'); |
||
1043 | createList($listOptions); |
||
1044 | |||
1045 | $context['sub_template'] = 'show_spider_stats'; |
||
1046 | $context['default_list'] = 'spider_stat_list'; |
||
1047 | } |
||
1048 | |||
1049 | /** |
||
1050 | * Callback function for createList() |
||
1051 | * Get a list of spider stats from the log_spider table |
||
1052 | * |
||
1053 | * @param int $start The item to start with (for pagination purposes) |
||
1054 | * @param int $items_per_page The number of items to show per page |
||
1055 | * @param string $sort A string indicating how to sort the results |
||
1056 | * @return array An array of spider statistics info |
||
1057 | */ |
||
1058 | function list_getSpiderStats($start, $items_per_page, $sort) |
||
1059 | { |
||
1060 | global $smcFunc; |
||
1061 | |||
1062 | $request = $smcFunc['db_query']('', ' |
||
1063 | SELECT ss.id_spider, ss.stat_date, ss.page_hits, s.spider_name |
||
1064 | FROM {db_prefix}log_spider_stats AS ss |
||
1065 | INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = ss.id_spider) |
||
1066 | ORDER BY {raw:sort} |
||
1067 | LIMIT {int:start}, {int:items}', |
||
1068 | array( |
||
1069 | 'sort' => $sort, |
||
1070 | 'start' => $start, |
||
1071 | 'items' => $items_per_page, |
||
1072 | ) |
||
1073 | ); |
||
1074 | $spider_stats = array(); |
||
1075 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1076 | $spider_stats[] = $row; |
||
1077 | $smcFunc['db_free_result']($request); |
||
1078 | |||
1079 | return $spider_stats; |
||
1080 | } |
||
1081 | |||
1082 | /** |
||
1083 | * Callback function for createList() |
||
1084 | * Get the number of spider stat rows from the log spider stats table |
||
1085 | * |
||
1086 | * @return int The number of rows in the log_spider_stats table |
||
1087 | */ |
||
1088 | function list_getNumSpiderStats() |
||
1089 | { |
||
1090 | global $smcFunc; |
||
1091 | |||
1092 | $request = $smcFunc['db_query']('', ' |
||
1093 | SELECT COUNT(*) AS num_stats |
||
1094 | FROM {db_prefix}log_spider_stats', |
||
1095 | array( |
||
1096 | ) |
||
1097 | ); |
||
1098 | list ($numStats) = $smcFunc['db_fetch_row']($request); |
||
1099 | $smcFunc['db_free_result']($request); |
||
1100 | |||
1101 | return $numStats; |
||
1102 | } |
||
1103 | |||
1104 | /** |
||
1105 | * Recache spider names? |
||
1106 | */ |
||
1107 | function recacheSpiderNames() |
||
1108 | { |
||
1109 | global $smcFunc; |
||
1110 | |||
1111 | $request = $smcFunc['db_query']('', ' |
||
1112 | SELECT id_spider, spider_name |
||
1113 | FROM {db_prefix}spiders', |
||
1114 | array() |
||
1115 | ); |
||
1116 | $spiders = array(); |
||
1117 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
1118 | $spiders[$row['id_spider']] = $row['spider_name']; |
||
1119 | $smcFunc['db_free_result']($request); |
||
1120 | |||
1121 | updateSettings(array('spider_name_cache' => $smcFunc['json_encode']($spiders))); |
||
1122 | } |
||
1123 | |||
1124 | ?> |
This check looks for function or method calls that always return null and whose return value is used.
The method
getObject()
can return nothing but null, so it makes no sense to use the return value.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.