Issues (1061)

Sources/ManageSearchEngines.php (1 issue)

Labels
Severity
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 2020 Simple Machines and individual contributors
11
 * @license https://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 RC2
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
Are you sure the usage of EditSpider() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

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.

Loading history...
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
		$ips = array();
397
		// Check the IP range is valid.
398
		$ip_sets = explode(',', $_POST['spider_ip']);
399
		foreach ($ip_sets as $set)
400
		{
401
			$test = ip2range(trim($set));
402
			if (!empty($test))
403
				$ips[] = $set;
404
		}
405
		$ips = implode(',', $ips);
406
407
		// Goes in as it is...
408
		if ($context['id_spider'])
409
			$smcFunc['db_query']('', '
410
				UPDATE {db_prefix}spiders
411
				SET spider_name = {string:spider_name}, user_agent = {string:spider_agent},
412
					ip_info = {string:ip_info}
413
				WHERE id_spider = {int:current_spider}',
414
				array(
415
					'current_spider' => $context['id_spider'],
416
					'spider_name' => $_POST['spider_name'],
417
					'spider_agent' => $_POST['spider_agent'],
418
					'ip_info' => $ips,
419
				)
420
			);
421
		else
422
			$smcFunc['db_insert']('insert',
423
				'{db_prefix}spiders',
424
				array(
425
					'spider_name' => 'string', 'user_agent' => 'string', 'ip_info' => 'string',
426
				),
427
				array(
428
					$_POST['spider_name'], $_POST['spider_agent'], $ips,
429
				),
430
				array('id_spider')
431
			);
432
433
		cache_put_data('spider_search', null);
434
		recacheSpiderNames();
435
436
		redirectexit('action=admin;area=sengines;sa=spiders');
437
	}
438
439
	// The default is new.
440
	$context['spider'] = array(
441
		'id' => 0,
442
		'name' => '',
443
		'agent' => '',
444
		'ip_info' => '',
445
	);
446
447
	// An edit?
448
	if ($context['id_spider'])
449
	{
450
		$request = $smcFunc['db_query']('', '
451
			SELECT id_spider, spider_name, user_agent, ip_info
452
			FROM {db_prefix}spiders
453
			WHERE id_spider = {int:current_spider}',
454
			array(
455
				'current_spider' => $context['id_spider'],
456
			)
457
		);
458
		if ($row = $smcFunc['db_fetch_assoc']($request))
459
			$context['spider'] = array(
460
				'id' => $row['id_spider'],
461
				'name' => $row['spider_name'],
462
				'agent' => $row['user_agent'],
463
				'ip_info' => $row['ip_info'],
464
			);
465
		$smcFunc['db_free_result']($request);
466
	}
467
468
	createToken('admin-ses');
469
}
470
471
/**
472
 * Do we think the current user is a spider?
473
 *
474
 * @todo Should this not be... you know... in a different file?
475
 * @return int The ID of the spider if it's known or 0 if it isn't known/isn't a spider
476
 */
477
function SpiderCheck()
478
{
479
	global $modSettings, $smcFunc;
480
481
	if (isset($_SESSION['id_robot']))
482
		unset($_SESSION['id_robot']);
483
	$_SESSION['robot_check'] = time();
484
485
	// We cache the spider data for ten minutes if we can.
486
	if (($spider_data = cache_get_data('spider_search', 600)) === null)
487
	{
488
		$request = $smcFunc['db_query']('', '
489
			SELECT id_spider, user_agent, ip_info
490
			FROM {db_prefix}spiders
491
			ORDER BY LENGTH(user_agent) DESC',
492
			array(
493
			)
494
		);
495
		$spider_data = array();
496
		while ($row = $smcFunc['db_fetch_assoc']($request))
497
			$spider_data[] = $row;
498
		$smcFunc['db_free_result']($request);
499
500
		cache_put_data('spider_search', $spider_data, 600);
501
	}
502
503
	if (empty($spider_data))
504
		return false;
505
506
	// Only do these bits once.
507
	$ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
508
509
	foreach ($spider_data as $spider)
510
	{
511
		// User agent is easy.
512
		if (!empty($spider['user_agent']) && strpos($ci_user_agent, strtolower($spider['user_agent'])) !== false)
513
			$_SESSION['id_robot'] = $spider['id_spider'];
514
		// IP stuff is harder.
515
		elseif ($_SERVER['REMOTE_ADDR'])
516
		{
517
			$ips = explode(',', $spider['ip_info']);
518
			foreach ($ips as $ip)
519
			{
520
				if ($ip === '')
521
					continue;
522
523
				$ip = ip2range($ip);
524
				if (!empty($ip))
525
				{
526
					if (inet_ptod($ip['low']) <= inet_ptod($_SERVER['REMOTE_ADDR']) && inet_ptod($ip['high']) >= inet_ptod($_SERVER['REMOTE_ADDR']))
527
						$_SESSION['id_robot'] = $spider['id_spider'];
528
				}
529
			}
530
		}
531
532
		if (isset($_SESSION['id_robot']))
533
			break;
534
	}
535
536
	// If this is low server tracking then log the spider here as opposed to the main logging function.
537
	if (!empty($modSettings['spider_mode']) && $modSettings['spider_mode'] == 1 && !empty($_SESSION['id_robot']))
538
		logSpider();
539
540
	return !empty($_SESSION['id_robot']) ? $_SESSION['id_robot'] : 0;
541
}
542
543
/**
544
 * Log the spider presence online.
545
 *
546
 * @todo Different file?
547
 */
548
function logSpider()
549
{
550
	global $smcFunc, $modSettings, $context;
551
552
	if (empty($modSettings['spider_mode']) || empty($_SESSION['id_robot']))
553
		return;
554
555
	// Attempt to update today's entry.
556
	if ($modSettings['spider_mode'] == 1)
557
	{
558
		$date = strftime('%Y-%m-%d', forum_time(false));
559
		$smcFunc['db_query']('', '
560
			UPDATE {db_prefix}log_spider_stats
561
			SET last_seen = {int:current_time}, page_hits = page_hits + 1
562
			WHERE id_spider = {int:current_spider}
563
				AND stat_date = {date:current_date}',
564
			array(
565
				'current_date' => $date,
566
				'current_time' => time(),
567
				'current_spider' => $_SESSION['id_robot'],
568
			)
569
		);
570
571
		// Nothing updated?
572
		if ($smcFunc['db_affected_rows']() == 0)
573
		{
574
			$smcFunc['db_insert']('ignore',
575
				'{db_prefix}log_spider_stats',
576
				array(
577
					'id_spider' => 'int', 'last_seen' => 'int', 'stat_date' => 'date', 'page_hits' => 'int',
578
				),
579
				array(
580
					$_SESSION['id_robot'], time(), $date, 1,
581
				),
582
				array('id_spider', 'stat_date')
583
			);
584
		}
585
	}
586
	// If we're tracking better stats than track, better stats - we sort out the today thing later.
587
	else
588
	{
589
		if ($modSettings['spider_mode'] > 2)
590
		{
591
			$url = $_GET + array('USER_AGENT' => $_SERVER['HTTP_USER_AGENT']);
592
			unset($url['sesc'], $url[$context['session_var']]);
593
			$url = $smcFunc['json_encode']($url);
594
		}
595
		else
596
			$url = '';
597
598
		$smcFunc['db_insert']('insert',
599
			'{db_prefix}log_spider_hits',
600
			array('id_spider' => 'int', 'log_time' => 'int', 'url' => 'string'),
601
			array($_SESSION['id_robot'], time(), $url),
602
			array()
603
		);
604
	}
605
}
606
607
/**
608
 * This function takes any unprocessed hits and turns them into stats.
609
 */
610
function consolidateSpiderStats()
611
{
612
	global $smcFunc;
613
614
	$request = $smcFunc['db_query']('', '
615
		SELECT id_spider, MAX(log_time) AS last_seen, COUNT(*) AS num_hits
616
		FROM {db_prefix}log_spider_hits
617
		WHERE processed = {int:not_processed}
618
		GROUP BY id_spider, MONTH(log_time), DAYOFMONTH(log_time)',
619
		array(
620
			'not_processed' => 0,
621
		)
622
	);
623
	$spider_hits = array();
624
	while ($row = $smcFunc['db_fetch_assoc']($request))
625
		$spider_hits[] = $row;
626
	$smcFunc['db_free_result']($request);
627
628
	if (empty($spider_hits))
629
		return;
630
631
	// Attempt to update the master data.
632
	$stat_inserts = array();
633
	foreach ($spider_hits as $stat)
634
	{
635
		// We assume the max date is within the right day.
636
		$date = strftime('%Y-%m-%d', $stat['last_seen']);
637
		$smcFunc['db_query']('', '
638
			UPDATE {db_prefix}log_spider_stats
639
			SET page_hits = page_hits + {int:hits},
640
				last_seen = CASE WHEN last_seen > {int:last_seen} THEN last_seen ELSE {int:last_seen} END
641
			WHERE id_spider = {int:current_spider}
642
				AND stat_date = {date:last_seen_date}',
643
			array(
644
				'last_seen_date' => $date,
645
				'last_seen' => $stat['last_seen'],
646
				'current_spider' => $stat['id_spider'],
647
				'hits' => $stat['num_hits'],
648
			)
649
		);
650
		if ($smcFunc['db_affected_rows']() == 0)
651
			$stat_inserts[] = array($date, $stat['id_spider'], $stat['num_hits'], $stat['last_seen']);
652
	}
653
654
	// New stats?
655
	if (!empty($stat_inserts))
656
		$smcFunc['db_insert']('ignore',
657
			'{db_prefix}log_spider_stats',
658
			array('stat_date' => 'date', 'id_spider' => 'int', 'page_hits' => 'int', 'last_seen' => 'int'),
659
			$stat_inserts,
660
			array('stat_date', 'id_spider')
661
		);
662
663
	// All processed.
664
	$smcFunc['db_query']('', '
665
		UPDATE {db_prefix}log_spider_hits
666
		SET processed = {int:is_processed}
667
		WHERE processed = {int:not_processed}',
668
		array(
669
			'is_processed' => 1,
670
			'not_processed' => 0,
671
		)
672
	);
673
}
674
675
/**
676
 * See what spiders have been up to.
677
 */
678
function SpiderLogs()
679
{
680
	global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings;
681
682
	// Load the template and language just incase.
683
	loadLanguage('Search');
684
	loadTemplate('ManageSearch');
685
686
	// Did they want to delete some entries?
687
	if ((!empty($_POST['delete_entries']) && isset($_POST['older'])) || !empty($_POST['removeAll']))
688
	{
689
		checkSession();
690
		validateToken('admin-sl');
691
692
		if (!empty($_POST['delete_entries']) && isset($_POST['older']))
693
		{
694
			$deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60);
695
696
			// Delete the entires.
697
			$smcFunc['db_query']('', '
698
				DELETE FROM {db_prefix}log_spider_hits
699
				WHERE log_time < {int:delete_period}',
700
				array(
701
					'delete_period' => $deleteTime,
702
				)
703
			);
704
		}
705
		else
706
		{
707
			// Deleting all of them
708
			$smcFunc['db_query']('', '
709
				TRUNCATE TABLE {db_prefix}log_spider_hits',
710
				array()
711
			);
712
		}
713
	}
714
715
	$listOptions = array(
716
		'id' => 'spider_logs',
717
		'items_per_page' => $modSettings['defaultMaxListItems'],
718
		'title' => $txt['spider_logs'],
719
		'no_items_label' => $txt['spider_logs_empty'],
720
		'base_href' => $context['admin_area'] == 'sengines' ? $scripturl . '?action=admin;area=sengines;sa=logs' : $scripturl . '?action=admin;area=logs;sa=spiderlog',
721
		'default_sort_col' => 'log_time',
722
		'get_items' => array(
723
			'function' => 'list_getSpiderLogs',
724
		),
725
		'get_count' => array(
726
			'function' => 'list_getNumSpiderLogs',
727
		),
728
		'columns' => array(
729
			'name' => array(
730
				'header' => array(
731
					'value' => $txt['spider'],
732
				),
733
				'data' => array(
734
					'db' => 'spider_name',
735
				),
736
				'sort' => array(
737
					'default' => 's.spider_name',
738
					'reverse' => 's.spider_name DESC',
739
				),
740
			),
741
			'log_time' => array(
742
				'header' => array(
743
					'value' => $txt['spider_time'],
744
				),
745
				'data' => array(
746
					'function' => function($rowData)
747
					{
748
						return timeformat($rowData['log_time']);
749
					},
750
				),
751
				'sort' => array(
752
					'default' => 'sl.id_hit DESC',
753
					'reverse' => 'sl.id_hit',
754
				),
755
			),
756
			'viewing' => array(
757
				'header' => array(
758
					'value' => $txt['spider_viewing'],
759
				),
760
				'data' => array(
761
					'db' => 'url',
762
				),
763
			),
764
		),
765
		'form' => array(
766
			'token' => 'admin-sl',
767
			'href' => $scripturl . '?action=admin;area=sengines;sa=logs',
768
		),
769
		'additional_rows' => array(
770
			array(
771
				'position' => 'after_title',
772
				'value' => $txt['spider_logs_info'],
773
			),
774
			array(
775
				'position' => 'below_table_data',
776
				'value' => '<input type="submit" name="removeAll" value="' . $txt['spider_log_empty_log'] . '" data-confirm="' . $txt['spider_log_empty_log_confirm'] . '" class="button you_sure">',
777
			),
778
		),
779
	);
780
781
	createToken('admin-sl');
782
783
	require_once($sourcedir . '/Subs-List.php');
784
	createList($listOptions);
785
786
	// Now determine the actions of the URLs.
787
	if (!empty($context['spider_logs']['rows']))
788
	{
789
		$urls = array();
790
791
		// Grab the current /url.
792
		foreach ($context['spider_logs']['rows'] as $k => $row)
793
		{
794
			// Feature disabled?
795
			if (empty($row['data']['viewing']['value']) && isset($modSettings['spider_mode']) && $modSettings['spider_mode'] < 3)
796
				$context['spider_logs']['rows'][$k]['viewing']['value'] = '<em>' . $txt['spider_disabled'] . '</em>';
797
			else
798
				$urls[$k] = array($row['data']['viewing']['value'], -1);
799
		}
800
801
		// Now stick in the new URLs.
802
		require_once($sourcedir . '/Who.php');
803
		$urls = determineActions($urls, 'whospider_');
804
		foreach ($urls as $k => $new_url)
805
		{
806
			$context['spider_logs']['rows'][$k]['data']['viewing']['value'] = $new_url;
807
		}
808
	}
809
810
	$context['page_title'] = $txt['spider_logs'];
811
	$context['sub_template'] = 'show_spider_logs';
812
	$context['default_list'] = 'spider_logs';
813
}
814
815
/**
816
 * Callback function for createList()
817
 *
818
 * @param int $start The item to start with (for pagination purposes)
819
 * @param int $items_per_page How many items to show per page
820
 * @param string $sort A string indicating how to sort the results
821
 * @return array An array of spider log data
822
 */
823
function list_getSpiderLogs($start, $items_per_page, $sort)
824
{
825
	global $smcFunc;
826
827
	$request = $smcFunc['db_query']('', '
828
		SELECT sl.id_spider, sl.url, sl.log_time, s.spider_name
829
		FROM {db_prefix}log_spider_hits AS sl
830
			INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = sl.id_spider)
831
		ORDER BY {raw:sort}
832
		LIMIT {int:start}, {int:items}',
833
		array(
834
			'sort' => $sort,
835
			'start' => $start,
836
			'items' => $items_per_page,
837
		)
838
	);
839
	$spider_logs = array();
840
	while ($row = $smcFunc['db_fetch_assoc']($request))
841
		$spider_logs[] = $row;
842
	$smcFunc['db_free_result']($request);
843
844
	return $spider_logs;
845
}
846
847
/**
848
 * Callback function for createList()
849
 *
850
 * @return int The number of spider log entries
851
 */
852
function list_getNumSpiderLogs()
853
{
854
	global $smcFunc;
855
856
	$request = $smcFunc['db_query']('', '
857
		SELECT COUNT(*) AS num_logs
858
		FROM {db_prefix}log_spider_hits',
859
		array(
860
		)
861
	);
862
	list ($numLogs) = $smcFunc['db_fetch_row']($request);
863
	$smcFunc['db_free_result']($request);
864
865
	return $numLogs;
866
}
867
868
/**
869
 * Show the spider statistics.
870
 */
871
function SpiderStats()
872
{
873
	global $context, $txt, $sourcedir, $scripturl, $smcFunc, $modSettings;
874
875
	// Force an update of the stats every 60 seconds.
876
	if (!isset($_SESSION['spider_stat']) || $_SESSION['spider_stat'] < time() - 60)
877
	{
878
		consolidateSpiderStats();
879
		$_SESSION['spider_stat'] = time();
880
	}
881
882
	// Are we cleaning up some old stats?
883
	if (!empty($_POST['delete_entries']) && isset($_POST['older']))
884
	{
885
		checkSession();
886
		validateToken('admin-ss');
887
888
		$deleteTime = time() - (((int) $_POST['older']) * 24 * 60 * 60);
889
890
		// Delete the entires.
891
		$smcFunc['db_query']('', '
892
			DELETE FROM {db_prefix}log_spider_stats
893
			WHERE last_seen < {int:delete_period}',
894
			array(
895
				'delete_period' => $deleteTime,
896
			)
897
		);
898
	}
899
900
	// Get the earliest and latest dates.
901
	$request = $smcFunc['db_query']('', '
902
		SELECT MIN(stat_date) AS first_date, MAX(stat_date) AS last_date
903
		FROM {db_prefix}log_spider_stats',
904
		array(
905
		)
906
	);
907
908
	list ($min_date, $max_date) = $smcFunc['db_fetch_row']($request);
909
	$smcFunc['db_free_result']($request);
910
911
	$min_year = (int) substr($min_date, 0, 4);
912
	$max_year = (int) substr($max_date, 0, 4);
913
	$min_month = (int) substr($min_date, 5, 2);
914
	$max_month = (int) substr($max_date, 5, 2);
915
916
	// Prepare the dates for the drop down.
917
	$date_choices = array();
918
	for ($y = $min_year; $y <= $max_year; $y++)
919
		for ($m = 1; $m <= 12; $m++)
920
		{
921
			// This doesn't count?
922
			if ($y == $min_year && $m < $min_month)
923
				continue;
924
			if ($y == $max_year && $m > $max_month)
925
				break;
926
927
			$date_choices[$y . $m] = $txt['months_short'][$m] . ' ' . $y;
928
		}
929
930
	// What are we currently viewing?
931
	$current_date = isset($_REQUEST['new_date']) && isset($date_choices[$_REQUEST['new_date']]) ? $_REQUEST['new_date'] : $max_date;
932
933
	// Prepare the HTML.
934
	$date_select = '
935
		' . $txt['spider_stats_select_month'] . ':
936
		<select name="new_date" onchange="document.spider_stat_list.submit();">';
937
938
	if (empty($date_choices))
939
		$date_select .= '
940
			<option></option>';
941
	else
942
		foreach ($date_choices as $id => $text)
943
			$date_select .= '
944
			<option value="' . $id . '"' . ($current_date == $id ? ' selected' : '') . '>' . $text . '</option>';
945
946
	$date_select .= '
947
		</select>
948
		<noscript>
949
			<input type="submit" name="go" value="' . $txt['go'] . '" class="button">
950
		</noscript>';
951
952
	// If we manually jumped to a date work out the offset.
953
	if (isset($_REQUEST['new_date']))
954
	{
955
		$date_query = sprintf('%04d-%02d-01', substr($current_date, 0, 4), substr($current_date, 4));
956
957
		$request = $smcFunc['db_query']('', '
958
			SELECT COUNT(*) AS offset
959
			FROM {db_prefix}log_spider_stats
960
			WHERE stat_date < {date:date_being_viewed}',
961
			array(
962
				'date_being_viewed' => $date_query,
963
			)
964
		);
965
		list ($_REQUEST['start']) = $smcFunc['db_fetch_row']($request);
966
		$smcFunc['db_free_result']($request);
967
	}
968
969
	$listOptions = array(
970
		'id' => 'spider_stat_list',
971
		'title' => $txt['spider'] . ' ' . $txt['spider_stats'],
972
		'items_per_page' => $modSettings['defaultMaxListItems'],
973
		'base_href' => $scripturl . '?action=admin;area=sengines;sa=stats',
974
		'default_sort_col' => 'stat_date',
975
		'get_items' => array(
976
			'function' => 'list_getSpiderStats',
977
		),
978
		'get_count' => array(
979
			'function' => 'list_getNumSpiderStats',
980
		),
981
		'no_items_label' => $txt['spider_stats_no_entries'],
982
		'columns' => array(
983
			'stat_date' => array(
984
				'header' => array(
985
					'value' => $txt['date'],
986
				),
987
				'data' => array(
988
					'db' => 'stat_date',
989
				),
990
				'sort' => array(
991
					'default' => 'stat_date',
992
					'reverse' => 'stat_date DESC',
993
				),
994
			),
995
			'name' => array(
996
				'header' => array(
997
					'value' => $txt['spider_name'],
998
				),
999
				'data' => array(
1000
					'db' => 'spider_name',
1001
				),
1002
				'sort' => array(
1003
					'default' => 's.spider_name',
1004
					'reverse' => 's.spider_name DESC',
1005
				),
1006
			),
1007
			'page_hits' => array(
1008
				'header' => array(
1009
					'value' => $txt['spider_stats_page_hits'],
1010
				),
1011
				'data' => array(
1012
					'db' => 'page_hits',
1013
				),
1014
				'sort' => array(
1015
					'default' => 'ss.page_hits',
1016
					'reverse' => 'ss.page_hits DESC',
1017
				),
1018
			),
1019
		),
1020
		'form' => array(
1021
			'href' => $scripturl . '?action=admin;area=sengines;sa=stats',
1022
			'name' => 'spider_stat_list',
1023
		),
1024
		'additional_rows' => array(
1025
			array(
1026
				'position' => 'below_table_data',
1027
				'value' => $date_select,
1028
				'style' => 'text-align: right;',
1029
			),
1030
		),
1031
	);
1032
1033
	createToken('admin-ss');
1034
1035
	require_once($sourcedir . '/Subs-List.php');
1036
	createList($listOptions);
1037
1038
	$context['sub_template'] = 'show_spider_stats';
1039
	$context['default_list'] = 'spider_stat_list';
1040
}
1041
1042
/**
1043
 * Callback function for createList()
1044
 * Get a list of spider stats from the log_spider table
1045
 *
1046
 * @param int $start The item to start with (for pagination purposes)
1047
 * @param int $items_per_page The number of items to show per page
1048
 * @param string $sort A string indicating how to sort the results
1049
 * @return array An array of spider statistics info
1050
 */
1051
function list_getSpiderStats($start, $items_per_page, $sort)
1052
{
1053
	global $smcFunc;
1054
1055
	$request = $smcFunc['db_query']('', '
1056
		SELECT ss.id_spider, ss.stat_date, ss.page_hits, s.spider_name
1057
		FROM {db_prefix}log_spider_stats AS ss
1058
			INNER JOIN {db_prefix}spiders AS s ON (s.id_spider = ss.id_spider)
1059
		ORDER BY {raw:sort}
1060
		LIMIT {int:start}, {int:items}',
1061
		array(
1062
			'sort' => $sort,
1063
			'start' => $start,
1064
			'items' => $items_per_page,
1065
		)
1066
	);
1067
	$spider_stats = array();
1068
	while ($row = $smcFunc['db_fetch_assoc']($request))
1069
		$spider_stats[] = $row;
1070
	$smcFunc['db_free_result']($request);
1071
1072
	return $spider_stats;
1073
}
1074
1075
/**
1076
 * Callback function for createList()
1077
 * Get the number of spider stat rows from the log spider stats table
1078
 *
1079
 * @return int The number of rows in the log_spider_stats table
1080
 */
1081
function list_getNumSpiderStats()
1082
{
1083
	global $smcFunc;
1084
1085
	$request = $smcFunc['db_query']('', '
1086
		SELECT COUNT(*) AS num_stats
1087
		FROM {db_prefix}log_spider_stats',
1088
		array(
1089
		)
1090
	);
1091
	list ($numStats) = $smcFunc['db_fetch_row']($request);
1092
	$smcFunc['db_free_result']($request);
1093
1094
	return $numStats;
1095
}
1096
1097
/**
1098
 * Recache spider names?
1099
 */
1100
function recacheSpiderNames()
1101
{
1102
	global $smcFunc;
1103
1104
	$request = $smcFunc['db_query']('', '
1105
		SELECT id_spider, spider_name
1106
		FROM {db_prefix}spiders',
1107
		array()
1108
	);
1109
	$spiders = array();
1110
	while ($row = $smcFunc['db_fetch_assoc']($request))
1111
		$spiders[$row['id_spider']] = $row['spider_name'];
1112
	$smcFunc['db_free_result']($request);
1113
1114
	updateSettings(array('spider_name_cache' => $smcFunc['json_encode']($spiders)));
1115
}
1116
1117
?>