1<?php
2/**
3 * MyBB 1.8
4 * Copyright 2014 MyBB Group, All Rights Reserved
5 *
6 * Website: http://www.mybb.com
7 * License: http://www.mybb.com/about/license
8 *
9 */
10
11define("IN_MYBB", 1);
12define('THIS_SCRIPT', 'online.php');
13
14$templatelist = "online,online_row,online_row_ip,online_today,online_today_row,online_row_ip_lookup,online_refresh,multipage,multipage_end,multipage_start";
15$templatelist .= ",multipage_jump_page,multipage_nextpage,multipage_page,multipage_page_current,multipage_page_link_current,multipage_prevpage";
16
17require_once "./global.php";
18require_once MYBB_ROOT."inc/functions_post.php";
19require_once MYBB_ROOT."inc/functions_online.php";
20require_once MYBB_ROOT."inc/class_parser.php";
21$parser = new postParser;
22
23// Load global language phrases
24$lang->load("online");
25
26if($mybb->usergroup['canviewonline'] == 0)
27{
28	error_no_permission();
29}
30
31// Make navigation
32add_breadcrumb($lang->nav_online, "online.php");
33
34if($mybb->get_input('action') == "today")
35{
36	add_breadcrumb($lang->nav_onlinetoday);
37
38	$plugins->run_hooks("online_today_start");
39
40	$threshold = TIME_NOW-(60*60*24);
41	$query = $db->simple_select("users", "COUNT(uid) AS users", "lastactive > '{$threshold}'");
42	$todaycount = $db->fetch_field($query, "users");
43
44	$query = $db->simple_select("users", "COUNT(uid) AS users", "lastactive > '{$threshold}' AND invisible = '1'");
45	$invis_count = $db->fetch_field($query, "users");
46
47	if(!$mybb->settings['wolusersperpage'] || (int)$mybb->settings['wolusersperpage'] < 1)
48	{
49		$mybb->settings['wolusersperpage'] = 20;
50	}
51
52	// Add pagination
53	$perpage = $mybb->settings['wolusersperpage'];
54
55	if($mybb->get_input('page', MyBB::INPUT_INT) > 0)
56	{
57		$page = $mybb->get_input('page', MyBB::INPUT_INT);
58		$start = ($page-1) * $perpage;
59		$pages = ceil($todaycount / $perpage);
60		if($page > $pages)
61		{
62			$start = 0;
63			$page = 1;
64		}
65	}
66	else
67	{
68		$start = 0;
69		$page = 1;
70	}
71
72	$query = $db->simple_select("users", "*", "lastactive > '{$threshold}'", array("order_by" => "lastactive", "order_dir" => "desc", "limit" => $perpage, "limit_start" => $start));
73
74	$todayrows = '';
75	while($online = $db->fetch_array($query))
76	{
77		$invisiblemark = '';
78		if($online['invisible'] == 1 && $mybb->usergroup['canbeinvisible'] == 1)
79		{
80			$invisiblemark = "*";
81		}
82
83		if($online['invisible'] != 1 || $mybb->usergroup['canviewwolinvis'] == 1 || $online['uid'] == $mybb->user['uid'])
84		{
85			$username = format_name(htmlspecialchars_uni($online['username']), $online['usergroup'], $online['displaygroup']);
86			$online['profilelink'] = build_profile_link($username, $online['uid']);
87			$onlinetime = my_date('normal', $online['lastactive']);
88
89			eval("\$todayrows .= \"".$templates->get("online_today_row")."\";");
90		}
91	}
92
93	$multipage = multipage($todaycount, $perpage, $page, "online.php?action=today");
94
95	$todaycount = my_number_format($todaycount);
96	$invis_count = my_number_format($invis_count);
97
98	if($todaycount == 1)
99	{
100		$onlinetoday = $lang->member_online_today;
101	}
102	else
103	{
104		$onlinetoday = $lang->sprintf($lang->members_were_online_today, $todaycount);
105	}
106
107	if($invis_count)
108	{
109		$string = $lang->members_online_hidden;
110
111		if($invis_count == 1)
112		{
113			$string = $lang->member_online_hidden;
114		}
115
116		$onlinetoday .= $lang->sprintf($string, $invis_count);
117	}
118
119	$plugins->run_hooks("online_today_end");
120
121	eval("\$today = \"".$templates->get("online_today")."\";");
122	output_page($today);
123}
124else
125{
126	$plugins->run_hooks("online_start");
127
128	// Custom sorting options
129	if($mybb->get_input('sortby') == "username")
130	{
131		$sql = "u.username ASC, s.time DESC";
132		$refresh_string = "?sortby=username";
133	}
134	elseif($mybb->get_input('sortby') == "location")
135	{
136		$sql = "s.location, s.time DESC";
137		$refresh_string = "?sortby=location";
138	}
139	// Otherwise sort by last refresh
140	else
141	{
142		switch($db->type)
143		{
144			case "sqlite":
145			case "pgsql":
146				$sql = "CASE WHEN s.uid > 0 THEN 1 ELSE 0 END DESC, s.time DESC";
147				break;
148			default:
149				$sql = "IF( s.uid >0, 1, 0 ) DESC, s.time DESC";
150				break;
151		}
152		$refresh_string = '';
153	}
154
155	$timesearch = TIME_NOW - $mybb->settings['wolcutoffmins']*60;
156
157	$query = $db->query("
158		SELECT COUNT(*) AS online FROM (
159			SELECT 1
160			FROM " . TABLE_PREFIX . "sessions
161			WHERE time > $timesearch
162			GROUP BY uid, ip
163		) s
164	");
165
166	$online_count = $db->fetch_field($query, "online");
167
168	if(!$mybb->settings['threadsperpage'] || (int)$mybb->settings['threadsperpage'] < 1)
169	{
170		$mybb->settings['threadsperpage'] = 20;
171	}
172
173	// How many pages are there?
174	$perpage = $mybb->settings['threadsperpage'];
175
176	if($mybb->get_input('page', MyBB::INPUT_INT) > 0)
177	{
178		$page = $mybb->get_input('page', MyBB::INPUT_INT);
179		$start = ($page-1) * $perpage;
180		$pages = ceil($online_count / $perpage);
181		if($page > $pages)
182		{
183			$start = 0;
184			$page = 1;
185		}
186	}
187	else
188	{
189		$start = 0;
190		$page = 1;
191	}
192
193	// Assemble page URL
194	$multipage = multipage($online_count, $perpage, $page, "online.php".$refresh_string);
195
196	// Query for active sessions
197	$dbversion = $db->get_version();
198	if(
199		(
200			$db->type == 'mysqli' && (
201				version_compare($dbversion, '10.2.0', '>=') || ( // MariaDB
202					version_compare($dbversion, '10', '<') &&
203					version_compare($dbversion, '8.0.2', '>=')
204				)
205			)
206		) ||
207		($db->type == 'pgsql' && version_compare($dbversion, '8.4.0', '>=')) ||
208		($db->type == 'sqlite' && version_compare($dbversion, '3.25.0', '>='))
209	)
210	{
211		$sql = str_replace('u.username', 's.username', $sql);
212
213		$query = $db->query("
214			SELECT * FROM (
215				SELECT
216					s.sid, s.ip, s.uid, s.time, s.location, u.username, s.nopermission, u.invisible, u.usergroup, u.displaygroup,
217					row_number() OVER (PARTITION BY s.uid, s.ip ORDER BY time DESC) AS row_num
218				FROM
219					".TABLE_PREFIX."sessions s
220					LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid = u.uid)
221				WHERE s.time > $timesearch
222			) s
223			WHERE row_num = 1
224			ORDER BY $sql
225			LIMIT {$start}, {$perpage}
226		");
227	}
228	else
229	{
230		$query = $db->query("
231			SELECT
232				s.sid, s.ip, s.uid, s.time, s.location, u.username, s.nopermission, u.invisible, u.usergroup, u.displaygroup
233			FROM
234				".TABLE_PREFIX."sessions s
235				INNER JOIN (
236					SELECT
237						MIN(s2.sid) AS sid
238					FROM
239						".TABLE_PREFIX."sessions s2
240						LEFT JOIN ".TABLE_PREFIX."sessions s3 ON (s2.sid = s3.sid AND s2.time < s3.time)
241					WHERE s2.time > $timesearch AND s3.sid IS NULL
242					GROUP BY s2.uid, s2.ip
243				) s2 ON (s.sid = s2.sid)
244				LEFT JOIN ".TABLE_PREFIX."users u ON (s.uid = u.uid)
245			ORDER BY $sql
246			LIMIT {$start}, {$perpage}
247		");
248	}
249
250	// Fetch spiders
251	$spiders = $cache->read("spiders");
252
253	while($user = $db->fetch_array($query))
254	{
255		$plugins->run_hooks("online_user");
256
257		// Fetch the WOL activity
258		$user['activity'] = fetch_wol_activity($user['location'], $user['nopermission']);
259
260		$botkey = my_strtolower(str_replace("bot=", '', $user['sid']));
261
262		// Have a registered user
263		if($user['uid'] > 0)
264		{
265			if(empty($users[$user['uid']]) || $users[$user['uid']]['time'] < $user['time'])
266			{
267				$users[$user['uid']] = $user;
268			}
269		}
270		// Otherwise this session is a bot
271		else if(my_strpos($user['sid'], "bot=") !== false && $spiders[$botkey])
272		{
273			$user['bot'] = $spiders[$botkey]['name'];
274			$user['usergroup'] = $spiders[$botkey]['usergroup'];
275			$guests[] = $user;
276		}
277		// Or a guest
278		else
279		{
280			$guests[] = $user;
281		}
282	}
283
284	// Now we build the actual online rows - we do this separately because we need to query all of the specific activity and location information
285	$online_rows = '';
286	if(isset($users) && is_array($users))
287	{
288		reset($users);
289		foreach($users as $user)
290		{
291			$online_rows .= build_wol_row($user);
292		}
293	}
294	if(isset($guests) && is_array($guests))
295	{
296		reset($guests);
297		foreach($guests as $user)
298		{
299			$online_rows .= build_wol_row($user);
300		}
301	}
302
303	// Fetch the most online information
304	$most_online = $cache->read("mostonline");
305	$record_count = $most_online['numusers'];
306	$record_date = my_date('relative', $most_online['time']);
307
308	// Set automatic refreshing if enabled
309	if($mybb->settings['refreshwol'] > 0)
310	{
311		$refresh_time = $mybb->settings['refreshwol'] * 60;
312		eval("\$refresh = \"".$templates->get("online_refresh")."\";");
313	}
314
315	$plugins->run_hooks("online_end");
316
317	eval("\$online = \"".$templates->get("online")."\";");
318	output_page($online);
319}
320