2 namespace wcf\data\user\online
;
3 use wcf\data\page\PageCache
;
4 use wcf\data\spider\Spider
;
5 use wcf\data\user\UserProfile
;
6 use wcf\system\cache\builder\SpiderCacheBuilder
;
7 use wcf\system\event\EventHandler
;
8 use wcf\system\page\handler\IOnlineLocationPageHandler
;
10 use wcf\util\StringUtil
;
11 use wcf\util\UserUtil
;
14 * Represents a user who is online.
17 * @copyright 2001-2019 WoltLab GmbH
18 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
19 * @package WoltLabSuite\Core\Data\User\Online
21 * @property-read integer|null $pageID id of the last visited page
22 * @property-read integer|null $pageObjectID id of the object the last visited page belongs to
23 * @property-read integer|null $parentPageObjectID id of the parent of the object the last visited page belongs to
24 * @property-read string|null $userOnlineMarking HTML code used to print the formatted name of a user group member
26 class UserOnline
extends UserProfile
{
28 * location of the user
31 protected $location = '';
37 protected $spider = null;
40 * Returns the formatted username.
44 public function getFormattedUsername() {
45 $username = StringUtil
::encodeHTML($this->username
);
47 if ($this->userOnlineMarking
&& $this->userOnlineMarking
!= '%s') {
48 $username = str_replace('%s', $username, $this->userOnlineMarking
);
51 if ($this->canViewOnlineStatus
== UserProfile
::ACCESS_NOBODY
) {
52 $username .= WCF
::getLanguage()->get('wcf.user.usersOnline.invisible');
59 * Sets the location of the user. If no location is given, the method tries to
60 * automatically determine the location.
62 * @param string|null $location
63 * @return boolean `true` if the location has been successfully set, otherwise `false`
65 public function setLocation($location = null) {
66 if ($location === null) {
68 $page = PageCache
::getInstance()->getPage($this->pageID
);
70 if ($page->getHandler() !== null && $page->getHandler() instanceof IOnlineLocationPageHandler
) {
71 // refer to page handler
72 /** @noinspection PhpUndefinedMethodInspection */
73 $this->location
= $page->getHandler()->getOnlineLocation($page, $this);
76 else if ($page->isVisible() && $page->isAccessible()) {
77 $title = $page->getTitle();
79 if ($page->pageType
!= 'system') {
80 $this->location
= '<a href="' . StringUtil
::encodeHTML($page->getLink()) . '">' . StringUtil
::encodeHTML($title) . '</a>';
83 $this->location
= StringUtil
::encodeHTML($title);
87 return ($this->location
!= '');
96 $this->location
= $location;
101 * Returns the location of the user.
105 public function getLocation() {
106 return $this->location
;
110 * Returns the ip address.
114 public function getFormattedIPAddress() {
115 if ($address = UserUtil
::convertIPv6To4($this->ipAddress
)) {
119 return $this->ipAddress
;
123 * Tries to retrieve browser name and version.
127 public function getBrowser() {
128 $parameters = ['browser' => '', 'userAgent' => $this->userAgent
];
129 EventHandler
::getInstance()->fireAction($this, 'getBrowser', $parameters);
130 if (!empty($parameters['browser'])) {
131 return $parameters['browser'];
135 if (preg_match('~lunascape[ /]([\d\.]+)~i', $this->userAgent
, $match)) {
136 return 'Lunascape '.$match[1];
140 if (preg_match('~sleipnir/([\d\.]+)~i', $this->userAgent
, $match)) {
141 return 'Sleipnir '.$match[1];
145 if (preg_match('~(?:ucbrowser|uc browser|ucweb)[ /]?([\d\.]+)~i', $this->userAgent
, $match)) {
146 return 'UC Browser '.$match[1];
150 if (preg_match('~(?:baidubrowser|flyflow)[ /]?([\d\.x]+)~i', $this->userAgent
, $match)) {
151 return 'Baidubrowser '.$match[1];
155 if (preg_match('~blackberry.*version/([\d\.]+)~i', $this->userAgent
, $match)) {
156 return 'Blackberry '.$match[1];
160 if (preg_match('~opera/([\d\.]+).*(mobi|mini)~i', $this->userAgent
, $match)) {
161 return 'Opera Mobile '.$match[1];
165 if (preg_match('~opera.*version/([\d\.]+)|opr/([\d\.]+)~i', $this->userAgent
, $match)) {
166 return 'Opera '.(isset($match[2]) ?
$match[2] : $match[1]);
170 if (preg_match('~thunderbird/([\d\.]+)~i', $this->userAgent
, $match)) {
171 return 'Thunderbird '.$match[1];
175 if (preg_match('~icedragon/([\d\.]+)~i', $this->userAgent
, $match)) {
176 return 'IceDragon '.$match[1];
180 if (preg_match('~palemoon/([\d\.]+)~i', $this->userAgent
, $match)) {
181 return 'PaleMoon '.$match[1];
185 if (preg_match('~flock/([\d\.]+)~i', $this->userAgent
, $match)) {
186 return 'Flock '.$match[1];
190 if (preg_match('~iceweasel/([\d\.]+)~i', $this->userAgent
, $match)) {
191 return 'Iceweasel '.$match[1];
195 if (preg_match('~(?:mobile.*firefox|fxios)/([\d\.]+)|fennec/([\d\.]+)~i', $this->userAgent
, $match)) {
196 return 'Firefox Mobile '.(isset($match[2]) ?
$match[2] : $match[1]);
200 if (preg_match('~tapatalk/([\d\.]+)?~i', $this->userAgent
, $match)) {
201 return 'Tapatalk '.(isset($match[1]) ?
$match[1] : 4);
205 if (preg_match('~firefox/([\d\.]+)~i', $this->userAgent
, $match)) {
206 return 'Firefox '.$match[1];
210 if (preg_match('~maxthon[ /]([\d\.]+)~i', $this->userAgent
, $match)) {
211 return 'Maxthon '.$match[1];
215 if (preg_match('~iemobile[ /]([\d\.]+)|MSIE ([\d\.]+).*XBLWP7~i', $this->userAgent
, $match)) {
216 return 'Internet Explorer Mobile '.(isset($match[2]) ?
$match[2] : $match[1]);
220 if (preg_match('~msie ([\d\.]+)|Trident\/\d{1,2}.\d{1,2}; .*rv:([0-9]*)~i', $this->userAgent
, $match)) {
221 return 'Internet Explorer '.(isset($match[2]) ?
$match[2] : $match[1]);
225 if (preg_match('~edge?/([\d\.]+)~i', $this->userAgent
, $match)) {
226 return 'Microsoft Edge '.$match[1];
230 if (preg_match('~edga/([\d\.]+)~i', $this->userAgent
, $match)) {
231 return 'Microsoft Edge Mobile '.$match[1];
235 if (preg_match('~vivaldi/([\d\.]+)~i', $this->userAgent
, $match)) {
236 return 'Vivaldi '.$match[1];
240 if (preg_match('~iron/([\d\.]+)~i', $this->userAgent
, $match)) {
241 return 'Iron '.$match[1];
245 if (preg_match('~coowon/([\d\.]+)~i', $this->userAgent
, $match)) {
246 return 'Coowon '.$match[1];
250 if (preg_match('~(?:coolnovo|chromeplus)/([\d\.]+)~i', $this->userAgent
, $match)) {
251 return 'CoolNovo '.$match[1];
255 if (preg_match('~yabrowser/([\d\.]+)~i', $this->userAgent
, $match)) {
256 return 'Yandex '.$match[1];
260 if (preg_match('~midori/([\d\.]+)~i', $this->userAgent
, $match)) {
261 return 'Midori '.$match[1];
265 if (preg_match('~(?:crios|crmo)/([\d\.]+)|chrome/([\d\.]+).*mobile~i', $this->userAgent
, $match)) {
266 return 'Chrome Mobile '.(isset($match[2]) ?
$match[2] : $match[1]);
270 if (preg_match('~kindle/([\d\.]+)~i', $this->userAgent
, $match)) {
271 return 'Kindle '.$match[1];
275 if (preg_match('~silk/([\d\.]+)~i', $this->userAgent
, $match)) {
276 return 'Silk '.$match[1];
280 if (preg_match('~Android ([\d\.]+).*AppleWebKit~i', $this->userAgent
, $match)) {
281 return 'Android Browser '.$match[1];
285 if (preg_match('~([\d\.]+) Mobile/\w+ safari~i', $this->userAgent
, $match)) {
286 return 'Safari Mobile '.$match[1];
290 if (preg_match('~(?:chromium|chrome)/([\d\.]+)~i', $this->userAgent
, $match)) {
291 return 'Chrome '.$match[1];
295 if (preg_match('~([\d\.]+) safari~i', $this->userAgent
, $match)) {
296 return 'Safari '.$match[1];
299 return $this->userAgent
;
303 * Returns the spider object
307 public function getSpider() {
308 if (!$this->spiderID
) return null;
310 if ($this->spider
=== null) {
311 $spiderList = SpiderCacheBuilder
::getInstance()->getData();
312 $this->spider
= $spiderList[$this->spiderID
];
315 return $this->spider
;