Repository: Wolfcast/BrowserDetection Branch: master Commit: f863a6165368 Files: 25 Total size: 881.9 KB Directory structure: gitextract_l63mtl3o/ ├── LICENSE.LGPL-3.0-only.md ├── LICENSE.MIT.md ├── LICENSE.md ├── README.md ├── composer.json ├── docs/ │ ├── classes/ │ │ └── Wolfcast-BrowserDetection.html │ ├── css/ │ │ ├── base.css │ │ ├── normalize.css │ │ └── template.css │ ├── files/ │ │ ├── BrowserDetection.php.txt │ │ └── browserdetection.html │ ├── graphs/ │ │ └── classes.html │ ├── index.html │ ├── indices/ │ │ └── files.html │ ├── js/ │ │ ├── search.js │ │ ├── searchIndex.js │ │ └── template.js │ ├── namespaces/ │ │ ├── default.html │ │ └── wolfcast.html │ ├── packages/ │ │ ├── BrowserDetection.html │ │ └── default.html │ └── reports/ │ ├── deprecated.html │ ├── errors.html │ └── markers.html └── lib/ └── BrowserDetection.php ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE.LGPL-3.0-only.md ================================================ GNU LESSER GENERAL PUBLIC LICENSE ================================= **Version 3, 29 June 2007** Copyright (C) 2007 [Free Software Foundation, Inc.](http://fsf.org/) Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. -------------------------- As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. ----------------------------------------- You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. ------------------------------- If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: 1. under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or 2. under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. ---------------------------------------------------------------- The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: 1. Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. 2. Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. ------------------ You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: 1. Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. 2. Accompany the Combined Work with a copy of the GNU GPL and this license document. 3. For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. 4. Do one of the following: * Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. * Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. 5. Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. ---------------------- You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: 1. Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. 2. Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. ------------------------------------------------------------- The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. ================================================ FILE: LICENSE.MIT.md ================================================ Copyright 2010 Wolfcast Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: LICENSE.md ================================================ This program is free software; you can redistribute it and/or modify it under the terms of EITHER the [MIT License](LICENSE.MIT.md) (SPDX short identifier: [MIT](https://spdx.org/licenses/MIT.html)) OR the [GNU Lesser General Public License Version 3](LICENSE.LGPL-3.0-only.md) (SPDX short identifier: [LGPL-3.0-only](https://spdx.org/licenses/GPL-3.0-only.html)). ================================================ FILE: README.md ================================================ BrowserDetection ================ The [Wolfcast](https://wolfcast.com/) BrowserDetection PHP class facilitates the identification of the user's environment such as Web browser, version, platform family, platform version or if it's a mobile device or not. This class will try to detect what the user is using from the `HTTP_USER_AGENT` string sent by the Web browser. A good way to use the class would be to gather user statistics or to report the browser and version used for informational purposes. A bad way to use the class would be to serve content based on the browser and version used. **Sites that rely on the user-agent string should be updated to modern techniques, such as feature detection, adaptive layout, and other modern practices.** Always keep in mind that `HTTP_USER_AGENT` can be easily spoofed by the user. Features -------- The [Wolfcast](https://wolfcast.com/) BrowserDetection PHP class is the most accurate detection class. **It has been tested with 14000+ different user agent strings and it have a 99.95% accuracy ratio!** Natively detects the following browsers: * Android * BlackBerry * BlackBerry Tablet OS * Chrome * Edge * Firebird * Firefox * GNU IceCat * GNU IceWeasel * iCab * Internet Explorer * Internet Explorer Mobile * Konqueror * Lynx * Mozilla * MSN TV * Netscape * Nokia Browser * Opera * Opera Mini * Opera Mobile * Phoenix * Safari * Samsung Internet * UC Browser You can also easily add custom rules to support other browsers not natively supported! Natively detects the following robots: * Bingbot * Googlebot * MSNBot * W3C Validator * Yahoo! Multimedia * Yahoo! Slurp You can also easily add custom rules to support other robots not natively supported! Natively detects the following platforms: * Android * BlackBerry * Chrome OS * FreeBSD * iOS * Linux * Macintosh * NetBSD * Nokia * OpenBSD * OpenSolaris * Symbian * Windows * Windows CE * Windows Phone You can also easily add custom rules to support other platforms not natively supported! Requirements ------------ Requires PHP 5.3 or newer (tested with PHP 8.4.5, 7.4.33 and 5.6.40). Demo and full documentation --------------------------- You can try the [live demo](https://wolfcast.com/open-source/browser-detection/tutorial.php) of the class and you can read the [documentation](https://wolfcast.com/open-source/browser-detection/doc/classes/Wolfcast-BrowserDetection.html). Installation ------------ You can add this library as a local, per-project dependency to your project using [Composer](https://getcomposer.org/) ([Packagist link](https://packagist.org/packages/wolfcast/browser-detection)): composer require wolfcast/browser-detection You can also manually install this library by adding `BrowserDetection.php` (found in the `lib` directory) to your project and then `require_once` the library where needed. Usage ----- ``` require_once('BrowserDetection.php'); $browser = new Wolfcast\BrowserDetection(); if ($browser->getName() == Wolfcast\BrowserDetection::BROWSER_FIREFOX && $browser->compareVersions($browser->getVersion(), '5.0') >= 0) { echo 'You are using FireFox version 5 or greater.'; } ``` History ------- Correctly identifying what Web browser your users are using is an incredibly complex task. If you ever tried to implement something like this you quickly saw how this can become a code mess. Only a few libraries exist and they often get deprecated and becomes abandonware. This is why we created our own detection engine. We didn't start from scratch. The class is a heavily updated version of Chris Schuld's Browser class version 1.9 (which was unmaintained for a couple of years). Chris' class was based on the original work from Gary White. License ------- SPDX-License-Identifier: MIT OR LGPL-3.0-only ================================================ FILE: composer.json ================================================ { "name": "wolfcast/browser-detection", "type": "library", "description": "The Wolfcast BrowserDetection PHP class facilitates the identification of the user's environment such as Web browser, version, platform family, platform version or if it's a mobile device or not.", "keywords": ["browser","detection","version","environment","platform","mobile"], "homepage": "https://github.com/Wolfcast/BrowserDetection", "license": "LGPL-3.0-or-later", "authors": [ { "name": "Alexandre Valiquette", "homepage": "https://wolfcast.com/", "role": "Lead developer" } ], "require": { "php": ">=5.3.0" }, "autoload": { "classmap": [ "lib/BrowserDetection.php" ] } } ================================================ FILE: docs/classes/Wolfcast-BrowserDetection.html ================================================ Wolfcast BrowserDetection Documentation

Wolfcast BrowserDetection Documentation

BrowserDetection
in package

The BrowserDetection class facilitates the identification of the user's environment such as Web browser, version, platform and device type.

Typical usage:

$browser = new Wolfcast\BrowserDetection();
if ($browser->getName() == Wolfcast\BrowserDetection::BROWSER_FIREFOX &&
    $browser->compareVersions($browser->getVersion(), '5.0') >= 0) {
    echo 'You are using FireFox version 5 or greater.';
}

The class is a rewrite of Chris Schuld's Browser class version 1.9 which is mostly unmaintained since August 20th, 2010. Chris' class was based on the original work from Gary White.

Updates:

2025-03-23: Version 2.9.9

  • Added macOS Sequoia detection for browsers that still correctly report the macOS version.

2024-04-21: Version 2.9.8

  • Added macOS Sonoma and macOS Ventura detection. Note that all the majors Web browsers have reported macOS Catalina since 2021 for any macOS 11+ versions. See the documentation of macVerToStr() for more details.
  • Improved the library documentation when detecting Windows version names since Windows 11 is always reported as Windows 10. See windowsNTVerToStr() for more details.
  • Updated HTML documentation of the library to the latest version of phpDocumentor.

2022-09-20: Version 2.9.7

  • Changed licensing to dual licensing: MIT or LGPL-3.0-only. This has no impact on existing users. You can continue under the previous license or switch to MIT.

2022-05-01: Version 2.9.6

  • Added support for Chrome OS.
  • Added support for macOS Monterey and macOS Big Sur.
  • Now correctly detects AArch64 as 64-bit.
  • Added support for PHP 8.
  • Tested with latest Web Browsers and platforms.

2020-02-02: Version 2.9.5

  • WARNING! Breaking change: complete rework of robots detection. Now robot name and version is detected in addition of browser name and version. Use getRobotName() and getRobotVersion() when isRobot() is true.
  • WARNING! Breaking change: due to robots detection rework the following methods signatures has changed (isRobot parameter removed): addCustomBrowserDetection(), checkSimpleBrowserUA(), checkBrowserUAWithVersion().
  • Added possibility to support new robots with addCustomRobotDetection().
  • Added support for the new Microsoft Edge based on Chromium.
  • Added version names for Android 10 and later (Google no longer use candy names for new versions).
  • Added macOS Catalina detection.
  • Added Windows Server 2019 detection (Windows Server 2016 can be no longer detected due to the fact that they both use the same version number and that the build is not included in the user agent).

2019-03-27: Version 2.9.3

  • Fixed Edge detection on Android.
  • Added Android Q detection.
  • Now filtering superglobals.

2019-02-28: Version 2.9.2

  • Fixed Opera detection.

2018-08-23: Version 2.9.1

  • Fixed Chrome detection under iOS.
  • Added Android Pie detection.
  • Added macOS Mojave detection.

2018-07-15: Version 2.9.0

  • WARNING! Breaking change: new Wolfcast namespace. Use new Wolfcast\BrowserDetection().
  • iPad, iPhone and iPod are all under iOS now.
  • Added Android Oreo detection.
  • Added macOS High Sierra detection.
  • Added UC Browser detection.
  • Improved regular expressions (even less false positives).
  • Removed AOL detection.
  • Removed the following Web browsers detection: Amaya, Galeon, NetPositive, OmniWeb, Vivaldi detection (use addCustomBrowserDetection()).
  • Removed the following legacy platforms detection: BeOS, OS/2, SunOS (use addCustomPlatformDetection()).

2016-11-28: Version 2.5.1

  • Better detection of 64-bit platforms.

2016-08-19: Version 2.5.0

  • Platform version and platform version name are now supported for Mac.
  • Fixed platform version name for Android.

2016-08-02: Version 2.4.0

  • Platform version and platform version name are now supported for Android.
  • Added support for the Samsung Internet browser.
  • Added support for the Vivaldi browser.
  • Better support for legacy Windows versions.

2016-02-11: Version 2.3.0

  • WARNING! Breaking change: public method getBrowser() is renamed to getName().
  • WARNING! Breaking change: changed the compareVersions() return values to be more in line with other libraries.
  • You can now get the exact platform version (name or version numbers) on which the browser is run on with getPlatformVersion(). Only working with Windows operating systems at the moment.
  • You can now determine if the browser is executed from a 64-bit platform with is64bitPlatform().
  • Better detection of mobile platform for Googlebot.

2016-01-04: Version 2.2.0

  • Added support for Microsoft Edge.

2014-12-30: Version 2.1.2

  • Better detection of Opera.

2014-07-11: Version 2.1.1

  • Better detection of mobile devices and platforms.

2014-06-04: Version 2.1.0

  • Added support for IE 11+.

2013-05-27: Version 2.0.0 which is (almost) a complete rewrite based on Chris Schuld's Browser class version 1.9 plus changes below.

  • Added support for Opera Mobile
  • Added support for the Windows Phone (formerly Windows Mobile) platform
  • Added support for BlackBerry Tablet OS and BlackBerry 10
  • Added support for the Symbian platform
  • Added support for Bingbot
  • Added support for the Yahoo! Multimedia crawler
  • Removed iPhone/iPad/iPod browsers since there are not browsers but platforms - test them with getPlatform()
  • Removed support for Shiretoko (Firefox 3.5 alpha/beta) and MSN Browser
  • Merged Nokia and Nokia S60
  • Updated some deprecated browser names
  • Many public methods are now protected
  • Documentation updated

2010-07-04:

  • Added detection of IE compatibility view - test with getIECompatibilityView()
  • Added support for all (deprecated) Netscape versions
  • Added support for Safari < 3.0
  • Better Firefox version parsing
  • Better Opera version parsing
  • Better Mozilla detection
Tags
version
2.9.9
last-modified

March 23, 2025

author

Alexandre Valiquette, Chris Schuld, Gary White

copyright

Copyright (c) 2025, Wolfcast

license

https://spdx.org/licenses/GPL-3.0-only.html

license

https://spdx.org/licenses/MIT.html

link
https://wolfcast.com/
link
https://wolfcast.com/open-source/browser-detection/tutorial.php
link
https://chrisschuld.com/

Table of Contents

Constants

BROWSER_ANDROID  = 'Android'
BROWSER_BLACKBERRY  = 'BlackBerry'
BROWSER_CHROME  = 'Chrome'
BROWSER_EDGE  = 'Edge'
BROWSER_FIREBIRD  = 'Firebird'
BROWSER_FIREFOX  = 'Firefox'
BROWSER_ICAB  = 'iCab'
BROWSER_ICECAT  = 'GNU IceCat'
BROWSER_ICEWEASEL  = 'GNU IceWeasel'
BROWSER_IE  = 'Internet Explorer'
BROWSER_IE_MOBILE  = 'Internet Explorer Mobile'
BROWSER_KONQUEROR  = 'Konqueror'
BROWSER_LYNX  = 'Lynx'
BROWSER_MOZILLA  = 'Mozilla'
BROWSER_MSNTV  = 'MSN TV'
BROWSER_NETSCAPE  = 'Netscape'
BROWSER_NOKIA  = 'Nokia Browser'
BROWSER_OPERA  = 'Opera'
BROWSER_OPERA_MINI  = 'Opera Mini'
BROWSER_OPERA_MOBILE  = 'Opera Mobile'
BROWSER_PHOENIX  = 'Phoenix'
BROWSER_SAFARI  = 'Safari'
BROWSER_SAMSUNG  = 'Samsung Internet'
BROWSER_TABLET_OS  = 'BlackBerry Tablet OS'
BROWSER_UC  = 'UC Browser'
BROWSER_UNKNOWN  = 'unknown'
PLATFORM_ANDROID  = 'Android'
PLATFORM_BLACKBERRY  = 'BlackBerry'
PLATFORM_CHROME_OS  = 'Chrome OS'
PLATFORM_FREEBSD  = 'FreeBSD'
PLATFORM_IOS  = 'iOS'
PLATFORM_LINUX  = 'Linux'
PLATFORM_MACINTOSH  = 'Macintosh'
PLATFORM_NETBSD  = 'NetBSD'
PLATFORM_NOKIA  = 'Nokia'
PLATFORM_OPENBSD  = 'OpenBSD'
PLATFORM_OPENSOLARIS  = 'OpenSolaris'
PLATFORM_SYMBIAN  = 'Symbian'
PLATFORM_UNKNOWN  = 'unknown'
PLATFORM_VERSION_UNKNOWN  = 'unknown'
PLATFORM_WINDOWS  = 'Windows'
PLATFORM_WINDOWS_CE  = 'Windows CE'
PLATFORM_WINDOWS_PHONE  = 'Windows Phone'
ROBOT_BINGBOT  = 'Bingbot'
ROBOT_GOOGLEBOT  = 'Googlebot'
ROBOT_MSNBOT  = 'MSNBot'
ROBOT_SLURP  = 'Yahoo! Slurp'
ROBOT_UNKNOWN  = ''
ROBOT_VERSION_UNKNOWN  = ''
ROBOT_W3CVALIDATOR  = 'W3C Validator'
ROBOT_YAHOO_MM  = 'Yahoo! Multimedia'
VERSION_UNKNOWN  = 'unknown'
Version unknown constant.

Properties

$_agent  : string
$_browserName  : string
$_compatibilityViewName  : string
$_compatibilityViewVer  : string
$_customBrowserDetection  : array<string|int, mixed>
$_customPlatformDetection  : array<string|int, mixed>
$_customRobotDetection  : array<string|int, mixed>
$_is64bit  : bool
$_isMobile  : bool
$_isRobot  : bool
$_platform  : string
$_platformVersion  : string
$_robotName  : string
$_robotVersion  : string
$_version  : string

Methods

__construct()  : mixed
BrowserDetection class constructor.
__toString()  : string
Determine how the class will react when it is treated like a string.
addCustomBrowserDetection()  : bool
Dynamically add support for a new Web browser.
addCustomPlatformDetection()  : bool
Dynamically add support for a new platform.
addCustomRobotDetection()  : bool
Dynamically add support for a new robot.
compareVersions()  : int
Compare two version number strings.
getIECompatibilityView()  : mixed
Get the name and version of the browser emulated in the compatibility view mode (if any). Since Internet Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE.
getLibVersion()  : string
Return the BrowserDetection class version.
getName()  : string
Get the name of the browser. All of the return values are class constants. You can compare them like this: $myBrowserInstance->getName() == BrowserDetection::BROWSER_FIREFOX.
getPlatform()  : string
Get the name of the platform family on which the browser is run on (such as Windows, Apple, etc.). All of the return values are class constants. You can compare them like this: $myBrowserInstance->getPlatform() == BrowserDetection::PLATFORM_ANDROID.
getPlatformVersion()  : string
Get the platform version on which the browser is run on. It can be returned as a string number like 'NT 6.3' or as a name like 'Windows 8.1'. When returning version string numbers for Windows NT OS families the number is prefixed by 'NT ' to differentiate from older Windows 3.x & 9x release. At the moment only the Windows and Android operating systems are supported.
getRobotName()  : string
Get the name of the robot. All of the return values are class constants. You can compare them like this: $myBrowserInstance->getRobotName() == BrowserDetection::ROBOT_GOOGLEBOT.
getRobotVersion()  : string
Get the version of the robot.
getUserAgent()  : string
Get the user agent value used by the class to determine the browser details.
getVersion()  : string
Get the version of the browser.
is64bitPlatform()  : bool
Determine if the browser is executed from a 64-bit platform. Keep in mind that not all platforms/browsers report this and the result may not always be accurate.
isChromeFrame()  : bool
Determine if the browser runs Google Chrome Frame (it's a plug-in designed for Internet Explorer 6+ based on the open-source Chromium project - it's like a Chrome browser within IE).
isInIECompatibilityView()  : bool
Determine if the browser is in compatibility view or not. Since Internet Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE.
isMobile()  : bool
Determine if the browser is from a mobile device or not.
isRobot()  : bool
Determine if the browser is a robot (Googlebot, Bingbot, Yahoo! Slurp...) or not.
removeCustomBrowserDetection()  : bool
Remove support for a previously added Web browser.
removeCustomPlatformDetection()  : bool
Remove support for a previously added platform.
removeCustomRobotDetection()  : bool
Remove support for a previously added robot.
setUserAgent()  : mixed
Set the user agent to use with the class.
androidVerToStr()  : string
Convert the Android version numbers to the operating system name. For instance '1.6' returns 'Donut'.
checkBrowser()  : bool
Determine what is the browser used by the user.
checkBrowserAndroid()  : bool
Determine if the browser is the Android browser (based on the WebKit layout engine and coupled with Chrome's JavaScript engine) or not.
checkBrowserBlackBerry()  : bool
Determine if the browser is the BlackBerry browser or not.
checkBrowserChrome()  : bool
Determine if the browser is Chrome or not.
checkBrowserCustom()  : bool
Determine if the browser is among the custom browser rules or not. Rules are checked in the order they were added.
checkBrowserEdge()  : bool
Determine if the browser is Edge or not.
checkBrowserFirebird()  : bool
Determine if the browser is Firebird or not. Firebird was the name of Firefox from version 0.6 to 0.7.1.
checkBrowserFirefox()  : bool
Determine if the browser is Firefox or not.
checkBrowserIcab()  : bool
Determine if the browser is iCab or not.
checkBrowserIceCat()  : bool
Determine if the browser is GNU IceCat (formerly known as GNU IceWeasel) or not.
checkBrowserIceWeasel()  : bool
Determine if the browser is GNU IceWeasel (now know as GNU IceCat) or not.
checkBrowserInternetExplorer()  : bool
Determine if the browser is Internet Explorer or not.
checkBrowserKonqueror()  : bool
Determine if the browser is Konqueror or not.
checkBrowserLynx()  : bool
Determine if the browser is Lynx or not. It is the oldest web browser currently in general use and development.
checkBrowserMozilla()  : bool
Determine if the browser is Mozilla or not.
checkBrowserMsnTv()  : bool
Determine if the browser is MSN TV (formerly WebTV) or not.
checkBrowserNetscape()  : bool
Determine if the browser is Netscape or not. Official support for this browser ended on March 1st, 2008.
checkBrowserNokia()  : bool
Determine if the browser is a Nokia browser or not.
checkBrowserOpera()  : bool
Determine if the browser is Opera or not.
checkBrowserPhoenix()  : bool
Determine if the browser is Phoenix or not. Phoenix was the name of Firefox from version 0.1 to 0.5.
checkBrowserSafari()  : bool
Determine if the browser is Safari or not.
checkBrowserSamsung()  : bool
Determine if the browser is the Samsung Internet browser or not.
checkBrowserUAWithVersion()  : bool
Test the user agent for a specific browser that use a "Version" string (like Safari and Opera). The user agent should look like: "Version/1.0 Browser name/123.456" or "Browser name/123.456 Version/1.0".
checkBrowserUC()  : bool
Determine if the browser is UC Browser or not.
checkPlatform()  : mixed
Determine the user's platform.
checkPlatformCustom()  : bool
Determine if the platform is among the custom platform rules or not. Rules are checked in the order they were added.
checkPlatformVersion()  : mixed
Determine the user's platform version.
checkRobot()  : mixed
Determine if it's a robot crawling the page and find it's name and version.
checkRobotBingbot()  : bool
Determine if the robot is the Bingbot crawler or not.
checkRobotCustom()  : bool
Determine if the robot is among the custom robot rules or not. Rules are checked in the order they were added.
checkRobotGooglebot()  : bool
Determine if the robot is the Googlebot crawler or not.
checkRobotMsnBot()  : bool
Determine if the robot is the MSNBot crawler or not. In October 2010 it was replaced by the Bingbot robot.
checkRobotSlurp()  : bool
Determine if the robot is the Yahoo! Slurp crawler or not.
checkRobotW3CValidator()  : bool
Determine if the robot is the W3C Validator or not.
checkRobotYahooMultimedia()  : bool
Determine if the robot is the Yahoo! multimedia crawler or not.
checkSimpleBrowserUA()  : bool
Test the user agent for a specific browser where the browser name is immediately followed by the version number.
checkSimpleRobot()  : bool
Test the user agent for a specific robot where the robot name is immediately followed by the version number.
cleanVersion()  : string
Clean a version string from unwanted characters.
containString()  : bool
Find if one or more substring is contained in a string.
detect()  : mixed
Detect the user environment from the details in the user agent string.
findAndGetVersion()  : bool
Test the user agent for a specific browser and extract it's version.
iOSVerToStr()  : string
Convert the iOS version numbers to the operating system name. For instance '2.0' returns 'iPhone OS 2.0'.
macVerToStr()  : string
Convert the macOS version numbers to the operating system name. For instance '10.7' returns 'Mac OS X Lion'.
parseInt()  : int
Get the integer value of a string variable.
reset()  : mixed
Reset all the properties of the class.
safariBuildToSafariVer()  : string
Convert a Safari build number to a Safari version number.
set64bit()  : mixed
Set if the browser is executed from a 64-bit platform.
setBrowser()  : mixed
Set the name of the browser.
setMobile()  : mixed
Set the browser to be from a mobile device or not.
setPlatform()  : mixed
Set the platform on which the browser is on.
setPlatformVersion()  : mixed
Set the platform version on which the browser is on.
setRobot()  : mixed
Set the browser to be a robot (crawler) or not.
setRobotName()  : mixed
Set the name of the robot.
setRobotVersion()  : mixed
Set the version of the robot.
setVersion()  : mixed
Set the version of the browser.
webKitBuildToSafariVer()  : string
Convert a WebKit build number to a Safari version number.
windowsNTVerToStr()  : string
Convert the Windows NT family version numbers to the operating system name. For instance '5.1' returns 'Windows XP'.
windowsVerToStr()  : string
Convert the Windows 3.x & 9x family version numbers to the operating system name. For instance '4.10.1998' returns 'Windows 98'.
wordPos()  : mixed
Find the position of the first occurrence of a word in a string.

Constants

BROWSER_IE_MOBILE

public mixed BROWSER_IE_MOBILE = 'Internet Explorer Mobile'

BROWSER_OPERA_MOBILE

public mixed BROWSER_OPERA_MOBILE = 'Opera Mobile'

BROWSER_TABLET_OS

public mixed BROWSER_TABLET_OS = 'BlackBerry Tablet OS'

PLATFORM_VERSION_UNKNOWN

public mixed PLATFORM_VERSION_UNKNOWN = 'unknown'

PLATFORM_WINDOWS_PHONE

public mixed PLATFORM_WINDOWS_PHONE = 'Windows Phone'

VERSION_UNKNOWN

Version unknown constant.

public mixed VERSION_UNKNOWN = 'unknown'

Properties

$_compatibilityViewName

private string $_compatibilityViewName = ''
Tags
access

private

$_compatibilityViewVer

private string $_compatibilityViewVer = ''
Tags
access

private

$_customBrowserDetection

private array<string|int, mixed> $_customBrowserDetection = array()
Tags
access

private

$_customPlatformDetection

private array<string|int, mixed> $_customPlatformDetection = array()
Tags
access

private

$_customRobotDetection

private array<string|int, mixed> $_customRobotDetection = array()
Tags
access

private

$_platformVersion

private string $_platformVersion = ''
Tags
access

private

Methods

__construct()

BrowserDetection class constructor.

public __construct([string $useragent = '' ]) : mixed
Parameters
$useragent : string = ''

(optional) The user agent to work with. Leave empty for the current user agent (contained in $_SERVER['HTTP_USER_AGENT']).

__toString()

Determine how the class will react when it is treated like a string.

public __toString() : string
Return values
string

Returns an HTML formatted string with a summary of the browser informations.

addCustomBrowserDetection()

Dynamically add support for a new Web browser.

public addCustomBrowserDetection(string $browserName[, mixed $uaNameToLookFor = '' ][, bool $isMobile = false ][, string $separator = '/' ][, bool $uaNameFindWords = true ]) : bool
Parameters
$browserName : string

The Web browser name (used for display).

$uaNameToLookFor : mixed = ''

(optional) The string (or array of strings) representing the browser name to find in the user agent. If omitted, $browserName will be used.

$isMobile : bool = false

(optional) Determines if the browser is from a mobile device.

$separator : string = '/'

(optional) The separator string used to split the browser name and the version number in the user agent.

$uaNameFindWords : bool = true

(optional) Determines if the browser name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the browser name can be found anywhere in the user agent string.

Tags
see
removeCustomBrowserDetection()
Return values
bool

Returns true if the custom rule has been added, false otherwise.

addCustomPlatformDetection()

Dynamically add support for a new platform.

public addCustomPlatformDetection(string $platformName[, mixed $platformNameToLookFor = '' ][, bool $isMobile = false ][, bool $uaNameFindWords = true ]) : bool
Parameters
$platformName : string

The platform name (used for display).

$platformNameToLookFor : mixed = ''

(optional) The string (or array of strings) representing the platform name to find in the user agent. If omitted, $platformName will be used.

$isMobile : bool = false

(optional) Determines if the platform is from a mobile device.

$uaNameFindWords : bool = true

(optional) Determines if the platform name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar".

Tags
see
removeCustomPlatformDetection()
Return values
bool

Returns true if the custom rule has been added, false otherwise.

addCustomRobotDetection()

Dynamically add support for a new robot.

public addCustomRobotDetection(string $robotName[, mixed $uaNameToLookFor = '' ][, bool $isMobile = false ][, string $separator = '/' ][, bool $uaNameFindWords = true ]) : bool
Parameters
$robotName : string

The robot name (used for display).

$uaNameToLookFor : mixed = ''

(optional) The string (or array of strings) representing the robot name to find in the user agent. If omitted, $robotName will be used.

$isMobile : bool = false

(optional) Determines if the robot should be considered as mobile or not.

$separator : string = '/'

(optional) The separator string used to split the robot name and the version number in the user agent.

$uaNameFindWords : bool = true

(optional) Determines if the robot name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the robot name can be found anywhere in the user agent string.

Tags
see
removeCustomRobotDetection()
Return values
bool

Returns true if the custom rule has been added, false otherwise.

compareVersions()

Compare two version number strings.

public compareVersions(string $sourceVer, string $compareVer) : int
Parameters
$sourceVer : string

The source version number.

$compareVer : string

The version number to compare with the source version number.

Return values
int

Returns -1 if $sourceVer < $compareVer, 0 if $sourceVer == $compareVer or 1 if $sourceVer > $compareVer.

getIECompatibilityView()

Get the name and version of the browser emulated in the compatibility view mode (if any). Since Internet Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE.

public getIECompatibilityView([bool $asArray = false ]) : mixed
Parameters
$asArray : bool = false

(optional) Determines if the return value must be an array (true) or a string (false).

Return values
mixed

If a string was requested, the function returns the name and version of the browser emulated in the compatibility view mode or an empty string if the browser is not in compatibility view mode. If an array was requested, an array with the keys 'browser' and 'version' is returned.

getLibVersion()

Return the BrowserDetection class version.

public getLibVersion() : string
Return values
string

Returns the version as a sting with the #.#.# format.

getName()

Get the name of the browser. All of the return values are class constants. You can compare them like this: $myBrowserInstance->getName() == BrowserDetection::BROWSER_FIREFOX.

public getName() : string
Return values
string

Returns the name of the browser or BrowserDetection::BROWSER_UNKNOWN if unknown.

getPlatform()

Get the name of the platform family on which the browser is run on (such as Windows, Apple, etc.). All of the return values are class constants. You can compare them like this: $myBrowserInstance->getPlatform() == BrowserDetection::PLATFORM_ANDROID.

public getPlatform() : string
Return values
string

Returns the name of the platform or BrowserDetection::PLATFORM_UNKNOWN if unknown.

getPlatformVersion()

Get the platform version on which the browser is run on. It can be returned as a string number like 'NT 6.3' or as a name like 'Windows 8.1'. When returning version string numbers for Windows NT OS families the number is prefixed by 'NT ' to differentiate from older Windows 3.x & 9x release. At the moment only the Windows and Android operating systems are supported.

public getPlatformVersion([bool $returnVersionNumbers = false ][, bool $returnServerFlavor = false ]) : string
Parameters
$returnVersionNumbers : bool = false

(optional) Determines if the return value must be versions numbers as a string (true) or the version name (false).

$returnServerFlavor : bool = false

(optional) Since some Windows NT versions have the same values, this flag determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use version 6.3. This parameter is only useful when testing for Windows.

Return values
string

Returns the version name/version numbers of the platform or the constant PLATFORM_VERSION_UNKNOWN if unknown.

getRobotName()

Get the name of the robot. All of the return values are class constants. You can compare them like this: $myBrowserInstance->getRobotName() == BrowserDetection::ROBOT_GOOGLEBOT.

public getRobotName() : string
Return values
string

Returns the name of the robot or BrowserDetection::ROBOT_UNKNOWN if unknown.

getRobotVersion()

Get the version of the robot.

public getRobotVersion() : string
Return values
string

Returns the version of the robot or BrowserDetection::ROBOT_VERSION_UNKNOWN if unknown.

getUserAgent()

Get the user agent value used by the class to determine the browser details.

public getUserAgent() : string
Return values
string

The user agent string.

getVersion()

Get the version of the browser.

public getVersion() : string
Return values
string

Returns the version of the browser or BrowserDetection::VERSION_UNKNOWN if unknown.

is64bitPlatform()

Determine if the browser is executed from a 64-bit platform. Keep in mind that not all platforms/browsers report this and the result may not always be accurate.

public is64bitPlatform() : bool
Return values
bool

Returns true if the browser is executed from a 64-bit platform.

isChromeFrame()

Determine if the browser runs Google Chrome Frame (it's a plug-in designed for Internet Explorer 6+ based on the open-source Chromium project - it's like a Chrome browser within IE).

public isChromeFrame() : bool
Return values
bool

Returns true if the browser is using Google Chrome Frame, false otherwise.

isInIECompatibilityView()

Determine if the browser is in compatibility view or not. Since Internet Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE.

public isInIECompatibilityView() : bool
Return values
bool

Returns true if the browser is in compatibility view, false otherwise.

isMobile()

Determine if the browser is from a mobile device or not.

public isMobile() : bool
Return values
bool

Returns true if the browser is from a mobile device, false otherwise.

isRobot()

Determine if the browser is a robot (Googlebot, Bingbot, Yahoo! Slurp...) or not.

public isRobot() : bool
Return values
bool

Returns true if the browser is a robot, false otherwise.

removeCustomBrowserDetection()

Remove support for a previously added Web browser.

public removeCustomBrowserDetection(string $browserName) : bool
Parameters
$browserName : string

The Web browser name as used when added.

Tags
see
addCustomBrowserDetection()
Return values
bool

Returns true if the custom rule has been found and removed, false otherwise.

removeCustomPlatformDetection()

Remove support for a previously added platform.

public removeCustomPlatformDetection(string $platformName) : bool
Parameters
$platformName : string

The platform name as used when added.

Tags
see
addCustomPlatformDetection()
Return values
bool

Returns true if the custom rule has been found and removed, false otherwise.

removeCustomRobotDetection()

Remove support for a previously added robot.

public removeCustomRobotDetection(string $robotName) : bool
Parameters
$robotName : string

The robot name as used when added.

Tags
see
addCustomRobotDetection()
Return values
bool

Returns true if the custom rule has been found and removed, false otherwise.

setUserAgent()

Set the user agent to use with the class.

public setUserAgent([string $agentString = '' ]) : mixed
Parameters
$agentString : string = ''

(optional) The value of the user agent. If an empty string is sent (default), $_SERVER['HTTP_USER_AGENT'] will be used.

androidVerToStr()

Convert the Android version numbers to the operating system name. For instance '1.6' returns 'Donut'.

protected androidVerToStr(string $androidVer) : string
Parameters
$androidVer : string

The Android version numbers as a string.

Tags
access

protected

Return values
string

The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version numbers.

checkBrowser()

Determine what is the browser used by the user.

protected checkBrowser() : bool
Tags
access

protected

Return values
bool

Returns true if the browser has been identified, false otherwise.

checkBrowserAndroid()

Determine if the browser is the Android browser (based on the WebKit layout engine and coupled with Chrome's JavaScript engine) or not.

protected checkBrowserAndroid() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is the Android browser, false otherwise.

checkBrowserChrome()

Determine if the browser is Chrome or not.

protected checkBrowserChrome() : bool
Tags
access

protected

link
https://www.google.com/chrome/
Return values
bool

Returns true if the browser is Chrome, false otherwise.

checkBrowserCustom()

Determine if the browser is among the custom browser rules or not. Rules are checked in the order they were added.

protected checkBrowserCustom() : bool
Tags
access

protected

Return values
bool

Returns true if we found the browser we were looking for in the custom rules, false otherwise.

checkBrowserEdge()

Determine if the browser is Edge or not.

protected checkBrowserEdge() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is Edge, false otherwise.

checkBrowserFirebird()

Determine if the browser is Firebird or not. Firebird was the name of Firefox from version 0.6 to 0.7.1.

protected checkBrowserFirebird() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is Firebird, false otherwise.

checkBrowserIcab()

Determine if the browser is iCab or not.

protected checkBrowserIcab() : bool
Tags
access

protected

link
http://www.icab.de/
Return values
bool

Returns true if the browser is iCab, false otherwise.

checkBrowserIceCat()

Determine if the browser is GNU IceCat (formerly known as GNU IceWeasel) or not.

protected checkBrowserIceCat() : bool
Tags
access

protected

link
https://www.gnu.org/software/gnuzilla/
Return values
bool

Returns true if the browser is GNU IceCat, false otherwise.

checkBrowserIceWeasel()

Determine if the browser is GNU IceWeasel (now know as GNU IceCat) or not.

protected checkBrowserIceWeasel() : bool
Tags
access

protected

see
checkBrowserIceCat()
Return values
bool

Returns true if the browser is GNU IceWeasel, false otherwise.

checkBrowserKonqueror()

Determine if the browser is Konqueror or not.

protected checkBrowserKonqueror() : bool
Tags
access

protected

link
https://www.konqueror.org/
Return values
bool

Returns true if the browser is Konqueror, false otherwise.

checkBrowserLynx()

Determine if the browser is Lynx or not. It is the oldest web browser currently in general use and development.

protected checkBrowserLynx() : bool

It is a text-based only Web browser.

Tags
access

protected

link
https://en.wikipedia.org/wiki/Lynx_(web_browser)
Return values
bool

Returns true if the browser is Lynx, false otherwise.

checkBrowserMozilla()

Determine if the browser is Mozilla or not.

protected checkBrowserMozilla() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is Mozilla, false otherwise.

checkBrowserNetscape()

Determine if the browser is Netscape or not. Official support for this browser ended on March 1st, 2008.

protected checkBrowserNetscape() : bool
Tags
access

protected

link
https://en.wikipedia.org/wiki/Netscape
Return values
bool

Returns true if the browser is Netscape, false otherwise.

checkBrowserPhoenix()

Determine if the browser is Phoenix or not. Phoenix was the name of Firefox from version 0.1 to 0.5.

protected checkBrowserPhoenix() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is Phoenix, false otherwise.

checkBrowserSamsung()

Determine if the browser is the Samsung Internet browser or not.

protected checkBrowserSamsung() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is the the Samsung Internet browser, false otherwise.

checkBrowserUAWithVersion()

Test the user agent for a specific browser that use a "Version" string (like Safari and Opera). The user agent should look like: "Version/1.0 Browser name/123.456" or "Browser name/123.456 Version/1.0".

protected checkBrowserUAWithVersion(mixed $uaNameToLookFor, string $userAgent, string $browserName[, bool $isMobile = false ][, bool $findWords = true ]) : bool
Parameters
$uaNameToLookFor : mixed

The string (or array of strings) representing the browser name to find in the user agent.

$userAgent : string

The user agent string to work with.

$browserName : string

The literal browser name. Always use a class constant!

$isMobile : bool = false

(optional) Determines if the browser is from a mobile device.

$findWords : bool = true

(optional) Determines if the needle should match a word to be found. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be found anywhere in the haystack.

Tags
access

protected

Return values
bool

Returns true if we found the browser we were looking for, false otherwise.

checkBrowserUC()

Determine if the browser is UC Browser or not.

protected checkBrowserUC() : bool
Tags
access

protected

Return values
bool

Returns true if the browser is UC Browser, false otherwise.

checkPlatform()

Determine the user's platform.

protected checkPlatform() : mixed
Tags
access

protected

checkPlatformCustom()

Determine if the platform is among the custom platform rules or not. Rules are checked in the order they were added.

protected checkPlatformCustom() : bool
Tags
access

protected

Return values
bool

Returns true if we found the platform we were looking for in the custom rules, false otherwise.

checkPlatformVersion()

Determine the user's platform version.

protected checkPlatformVersion() : mixed
Tags
access

protected

checkRobot()

Determine if it's a robot crawling the page and find it's name and version.

protected checkRobot() : mixed
Tags
access

protected

checkRobotCustom()

Determine if the robot is among the custom robot rules or not. Rules are checked in the order they were added.

protected checkRobotCustom() : bool
Tags
access

protected

Return values
bool

Returns true if we found the robot we were looking for in the custom rules, false otherwise.

checkRobotGooglebot()

Determine if the robot is the Googlebot crawler or not.

protected checkRobotGooglebot() : bool
Tags
access

protected

Return values
bool

Returns true if the robot is Googlebot, false otherwise.

checkRobotMsnBot()

Determine if the robot is the MSNBot crawler or not. In October 2010 it was replaced by the Bingbot robot.

protected checkRobotMsnBot() : bool
Tags
access

protected

see
checkRobotBingbot()
Return values
bool

Returns true if the robot is MSNBot, false otherwise.

checkRobotSlurp()

Determine if the robot is the Yahoo! Slurp crawler or not.

protected checkRobotSlurp() : bool
Tags
access

protected

Return values
bool

Returns true if the robot is Yahoo! Slurp, false otherwise.

checkRobotW3CValidator()

Determine if the robot is the W3C Validator or not.

protected checkRobotW3CValidator() : bool
Tags
access

protected

link
https://validator.w3.org/
Return values
bool

Returns true if the robot is the W3C Validator, false otherwise.

checkRobotYahooMultimedia()

Determine if the robot is the Yahoo! multimedia crawler or not.

protected checkRobotYahooMultimedia() : bool
Tags
access

protected

Return values
bool

Returns true if the robot is the Yahoo! multimedia crawler, false otherwise.

checkSimpleBrowserUA()

Test the user agent for a specific browser where the browser name is immediately followed by the version number.

protected checkSimpleBrowserUA(mixed $uaNameToLookFor, string $userAgent, string $browserName[, bool $isMobile = false ][, string $separator = '/' ][, bool $uaNameFindWords = true ]) : bool

The user agent should look like: "Browser name/1.0" or "Browser 1.0;".

Parameters
$uaNameToLookFor : mixed

The string (or array of strings) representing the browser name to find in the user agent.

$userAgent : string

The user agent string to work with.

$browserName : string

The literal browser name. Always use a class constant!

$isMobile : bool = false

(optional) Determines if the browser is from a mobile device.

$separator : string = '/'

(optional) The separator string used to split the browser name and the version number in the user agent.

$uaNameFindWords : bool = true

(optional) Determines if the browser name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the browser name can be found anywhere in the user agent string.

Tags
access

protected

Return values
bool

Returns true if we found the browser we were looking for, false otherwise.

checkSimpleRobot()

Test the user agent for a specific robot where the robot name is immediately followed by the version number.

protected checkSimpleRobot(mixed $uaNameToLookFor, string $userAgent, string $robotName[, string $separator = '/' ][, bool $uaNameFindWords = true ]) : bool

The user agent should look like: "Robot name/1.0" or "Robot 1.0;".

Parameters
$uaNameToLookFor : mixed

The string (or array of strings) representing the robot name to find in the user agent.

$userAgent : string

The user agent string to work with.

$robotName : string

The literal robot name. Always use a class constant!

$separator : string = '/'

(optional) The separator string used to split the robot name and the version number in the user agent.

$uaNameFindWords : bool = true

(optional) Determines if the robot name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the robot name can be found anywhere in the user agent string.

Tags
access

protected

Return values
bool

Returns true if we found the robot we were looking for, false otherwise.

cleanVersion()

Clean a version string from unwanted characters.

protected cleanVersion(string $version[, mixed $toRemove = NULL ]) : string
Parameters
$version : string

The version string to clean.

$toRemove : mixed = NULL

(optional) String or array of strings representing additional string(s) to remove.

Tags
access

protected

Return values
string

Returns the cleaned version number string.

containString()

Find if one or more substring is contained in a string.

protected containString(string $haystack, mixed $needle[, bool $insensitive = true ][, bool $findWords = true ][, int &$foundPos = NULL ]) : bool
Parameters
$haystack : string

The string to search in.

$needle : mixed

The string to search for. Can be a string or an array of strings if multiples values are to be searched.

$insensitive : bool = true

(optional) Determines if we do a case-sensitive search (false) or a case-insensitive one (true).

$findWords : bool = true

(optional) Determines if the needle should match a word to be found. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be found anywhere in the haystack.

$foundPos : int = NULL

(optional) Integer buffer that will contain the position of the needle (if found and if a non NULL variable has been passed).

Tags
access

protected

Return values
bool

Returns true if the needle (or one of the needles) has been found in the haystack, false otherwise.

detect()

Detect the user environment from the details in the user agent string.

protected detect() : mixed
Tags
access

protected

findAndGetVersion()

Test the user agent for a specific browser and extract it's version.

protected findAndGetVersion(type $uaNameToLookFor, type $userAgent, type &$version[, type $separator = '/' ][, type $uaNameFindWords = true ]) : bool
Parameters
$uaNameToLookFor : type

The string (or array of strings) representing the browser name to find in the user agent.

$userAgent : type

The user agent string to work with.

$version : type

String buffer that will contain the version found (if any).

$separator : type = '/'

(optional) The separator string used to split the browser name and the version number in the user agent.

$uaNameFindWords : type = true

(optional) Determines if the browser name to find should match a word instead of a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the browser name can be found anywhere in the user agent string.

Tags
access

protected

Return values
bool

Returns true if we found the browser we were looking for, false otherwise.

iOSVerToStr()

Convert the iOS version numbers to the operating system name. For instance '2.0' returns 'iPhone OS 2.0'.

protected iOSVerToStr(string $iOSVer) : string
Parameters
$iOSVer : string

The iOS version numbers as a string.

Tags
access

protected

Return values
string

The operating system name.

macVerToStr()

Convert the macOS version numbers to the operating system name. For instance '10.7' returns 'Mac OS X Lion'.

protected macVerToStr(string $macVer) : string

Firefox, Safari and Chromium development teams have discovered a long tail of websites broken when reporting "Mac OS X 11" in the user agent string. In order to slightly improve user privacy as well as Web compatibility, they all capped the reported macOS version to 10.15 (Catalina) in the user agent string.

Firefox reported macOS version is capped at 10.15 since Firefox 87 (March 23, 2021). This change has been also backported in Firefox 78.9.0esr (March 23, 2021).

Safari reported macOS version is capped at 10.15.7 since Safari 14.1 (April 26, 2021).

Chromium reported macOS version is capped at 10.15.7 since Chromium 91.0.4437.0 (May 25, 2021).

See below links for more details.

Parameters
$macVer : string

The macOS version numbers as a string.

Tags
access

protected

link
https://bugzilla.mozilla.org/show_bug.cgi?id=1679929
link
https://github.com/WebKit/WebKit/commit/94d3ce0900c31c929798e91ea86dcfe604251a9e
link
https://github.com/WebKit/WebKit/commit/a46b2c6dd07fab463f1b2353c5d5b2ff43000f58
link
https://chromiumdash.appspot.com/commit/a632542e79f2589e1b3f470827c7d03092be0afb
Return values
string

The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version numbers.

parseInt()

Get the integer value of a string variable.

protected parseInt(string $intStr) : int
Parameters
$intStr : string

The scalar value being converted to an integer.

Tags
access

protected

Return values
int

The integer value of $intStr on success, or 0 on failure.

reset()

Reset all the properties of the class.

protected reset() : mixed
Tags
access

protected

set64bit()

Set if the browser is executed from a 64-bit platform.

protected set64bit(bool $is64bit) : mixed
Parameters
$is64bit : bool

Value that tells if the browser is executed from a 64-bit platform.

Tags
access

protected

setBrowser()

Set the name of the browser.

protected setBrowser(string $browserName) : mixed
Parameters
$browserName : string

The name of the browser.

Tags
access

protected

setMobile()

Set the browser to be from a mobile device or not.

protected setMobile([bool $isMobile = true ]) : mixed
Parameters
$isMobile : bool = true

(optional) Value that tells if the browser is on a mobile device or not.

Tags
access

protected

setPlatform()

Set the platform on which the browser is on.

protected setPlatform(string $platform) : mixed
Parameters
$platform : string

The name of the platform.

Tags
access

protected

setPlatformVersion()

Set the platform version on which the browser is on.

protected setPlatformVersion(string $platformVer) : mixed
Parameters
$platformVer : string

The version numbers of the platform.

Tags
access

protected

setRobot()

Set the browser to be a robot (crawler) or not.

protected setRobot([bool $isRobot = true ]) : mixed
Parameters
$isRobot : bool = true

(optional) Value that tells if the browser is a robot or not.

Tags
access

protected

setRobotName()

Set the name of the robot.

protected setRobotName(string $robotName) : mixed
Parameters
$robotName : string

The name of the robot.

Tags
access

protected

setRobotVersion()

Set the version of the robot.

protected setRobotVersion(string $robotVersion) : mixed
Parameters
$robotVersion : string

The version of the robot.

Tags
access

protected

setVersion()

Set the version of the browser.

protected setVersion(string $version) : mixed
Parameters
$version : string

The version of the browser.

Tags
access

protected

windowsNTVerToStr()

Convert the Windows NT family version numbers to the operating system name. For instance '5.1' returns 'Windows XP'.

protected windowsNTVerToStr(string $winVer[, bool $returnServerFlavor = false ]) : string

Windows 10 and Windows 11 share the same major version number (10). Windows 11 starts with build 22000 (version 10.0.22000) but the build is not included in the UA.

Windows Server 2022, 2019 & 2016 have also the same version number (10). Again, only the build can differentiate these versions.

Parameters
$winVer : string

The Windows NT family version numbers as a string.

$returnServerFlavor : bool = false

(optional) Since some Windows NT versions have the same values, this flag determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use version 6.3.

Tags
access

protected

Return values
string

The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version numbers.

windowsVerToStr()

Convert the Windows 3.x & 9x family version numbers to the operating system name. For instance '4.10.1998' returns 'Windows 98'.

protected windowsVerToStr(string $winVer) : string
Parameters
$winVer : string

The Windows 3.x or 9x family version numbers as a string.

Tags
access

protected

Return values
string

The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version numbers.

wordPos()

Find the position of the first occurrence of a word in a string.

protected wordPos(string $haystack, string $needle[, bool $insensitive = true ][, int $offset = 0 ][, string &$foundString = NULL ]) : mixed
Parameters
$haystack : string

The string to search in.

$needle : string

The string to search for.

$insensitive : bool = true

(optional) Determines if we do a case-sensitive search (false) or a case-insensitive one (true).

$offset : int = 0

If specified, search will start this number of characters counted from the beginning of the string. If the offset is negative, the search will start this number of characters counted from the end of the string.

$foundString : string = NULL

String buffer that will contain the exact matching needle found. Set to NULL when return value of the function is false.

Tags
access

protected

Return values
mixed

Returns the position of the needle (int) if found, false otherwise. Warning this function may return Boolean false, but may also return a non-Boolean value which evaluates to false.


        
On this page

Search results

    ================================================ FILE: docs/css/base.css ================================================ :root { /* Typography */ --font-primary: 'Open Sans', Helvetica, Arial, sans-serif; --font-secondary: 'Open Sans', Helvetica, Arial, sans-serif; --font-monospace: 'Source Code Pro', monospace; --line-height--primary: 1.6; --letter-spacing--primary: .05rem; --text-base-size: 1em; --text-scale-ratio: 1.2; --text-xxs: calc(var(--text-base-size) / var(--text-scale-ratio) / var(--text-scale-ratio) / var(--text-scale-ratio)); --text-xs: calc(var(--text-base-size) / var(--text-scale-ratio) / var(--text-scale-ratio)); --text-sm: calc(var(--text-base-size) / var(--text-scale-ratio)); --text-md: var(--text-base-size); --text-lg: calc(var(--text-base-size) * var(--text-scale-ratio)); --text-xl: calc(var(--text-base-size) * var(--text-scale-ratio) * var(--text-scale-ratio)); --text-xxl: calc(var(--text-base-size) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio)); --text-xxxl: calc(var(--text-base-size) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio)); --text-xxxxl: calc(var(--text-base-size) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio)); --text-xxxxxl: calc(var(--text-base-size) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio) * var(--text-scale-ratio)); --color-hue-red: 4; --color-hue-pink: 340; --color-hue-purple: 291; --color-hue-deep-purple: 262; --color-hue-indigo: 231; --color-hue-blue: 207; --color-hue-light-blue: 199; --color-hue-cyan: 187; --color-hue-teal: 174; --color-hue-green: 122; --color-hue-phpdocumentor-green: 96; --color-hue-light-green: 88; --color-hue-lime: 66; --color-hue-yellow: 54; --color-hue-amber: 45; --color-hue-orange: 36; --color-hue-deep-orange: 14; --color-hue-brown: 16; /* Colors */ --primary-color-hue: var(--color-hue-phpdocumentor-green, --color-hue-phpdocumentor-green); --primary-color-saturation: 57%; --primary-color: hsl(var(--primary-color-hue), var(--primary-color-saturation), 60%); --primary-color-darken: hsl(var(--primary-color-hue), var(--primary-color-saturation), 40%); --primary-color-darker: hsl(var(--primary-color-hue), var(--primary-color-saturation), 25%); --primary-color-darkest: hsl(var(--primary-color-hue), var(--primary-color-saturation), 10%); --primary-color-lighten: hsl(var(--primary-color-hue), calc(var(--primary-color-saturation) - 20%), 85%); --primary-color-lighter: hsl(var(--primary-color-hue), calc(var(--primary-color-saturation) - 45%), 97.5%); --dark-gray: #d1d1d1; --light-gray: #f0f0f0; --text-color: var(--primary-color-darkest); --header-height: var(--spacing-xxxxl); --header-bg-color: var(--primary-color); --code-background-color: var(--primary-color-lighter); --code-border-color: --primary-color-lighten; --button-border-color: var(--primary-color-darken); --button-color: transparent; --button-color-primary: var(--primary-color); --button-text-color: #555; --button-text-color-primary: white; --popover-background-color: rgba(255, 255, 255, 0.75); --link-color-primary: var(--primary-color-darker); --link-hover-color-primary: var(--primary-color-darkest); --form-field-border-color: var(--dark-gray); --form-field-color: #fff; --admonition-success-color: var(--primary-color); --admonition-border-color: silver; --table-separator-color: var(--primary-color-lighten); --title-text-color: var(--primary-color); --sidebar-border-color: var(--primary-color-lighten); /* Grid */ --container-width: 75%; /* Spacing */ --spacing-base-size: 1rem; --spacing-scale-ratio: 1.5; --spacing-xxxs: calc(var(--spacing-base-size) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio)); --spacing-xxs: calc(var(--spacing-base-size) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio)); --spacing-xs: calc(var(--spacing-base-size) / var(--spacing-scale-ratio) / var(--spacing-scale-ratio)); --spacing-sm: calc(var(--spacing-base-size) / var(--spacing-scale-ratio)); --spacing-md: var(--spacing-base-size); --spacing-lg: calc(var(--spacing-base-size) * var(--spacing-scale-ratio)); --spacing-xl: calc(var(--spacing-base-size) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio)); --spacing-xxl: calc(var(--spacing-base-size) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio)); --spacing-xxxl: calc(var(--spacing-base-size) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio)); --spacing-xxxxl: calc(var(--spacing-base-size) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio) * var(--spacing-scale-ratio)); --border-radius-base-size: 3px; } /* Base Styles -------------------------------------------------- */ body { background-color: #fff; color: var(--text-color); font-family: var(--font-primary); font-size: var(--text-md); letter-spacing: var(--letter-spacing--primary); line-height: var(--line-height--primary); width: 100%; } .phpdocumentor h1, .phpdocumentor h2, .phpdocumentor h3, .phpdocumentor h4, .phpdocumentor h5, .phpdocumentor h6 { margin-bottom: var(--spacing-lg); margin-top: var(--spacing-lg); font-weight: 600; } .phpdocumentor h1 { font-size: var(--text-xxxxl); letter-spacing: var(--letter-spacing--primary); line-height: 1.2; margin-top: 0; } .phpdocumentor h2 { font-size: var(--text-xxxl); letter-spacing: var(--letter-spacing--primary); line-height: 1.25; } .phpdocumentor h3 { font-size: var(--text-xxl); letter-spacing: var(--letter-spacing--primary); line-height: 1.3; } .phpdocumentor h4 { font-size: var(--text-xl); letter-spacing: calc(var(--letter-spacing--primary) / 2); line-height: 1.35; margin-bottom: var(--spacing-md); } .phpdocumentor h5 { font-size: var(--text-lg); letter-spacing: calc(var(--letter-spacing--primary) / 4); line-height: 1.5; margin-bottom: var(--spacing-md); margin-top: var(--spacing-md); } .phpdocumentor h6 { font-size: var(--text-md); letter-spacing: 0; line-height: var(--line-height--primary); margin-bottom: var(--spacing-md); margin-top: var(--spacing-md); } .phpdocumentor h1 .headerlink, .phpdocumentor h2 .headerlink, .phpdocumentor h3 .headerlink, .phpdocumentor h4 .headerlink, .phpdocumentor h5 .headerlink, .phpdocumentor h6 .headerlink { display: none; } @media (min-width: 550px) { .phpdocumentor h1 .headerlink, .phpdocumentor h2 .headerlink, .phpdocumentor h3 .headerlink, .phpdocumentor h4 .headerlink, .phpdocumentor h5 .headerlink, .phpdocumentor h6 .headerlink { display: inline; transition: all .3s ease-in-out; opacity: 0; text-decoration: none; color: silver; font-size: 80%; } .phpdocumentor h1:hover .headerlink, .phpdocumentor h2:hover .headerlink, .phpdocumentor h3:hover .headerlink, .phpdocumentor h4:hover .headerlink, .phpdocumentor h5:hover .headerlink, .phpdocumentor h6:hover .headerlink { opacity: 1; } } .phpdocumentor p { margin-top: 0; margin-bottom: var(--spacing-md); } .phpdocumentor figure { margin-bottom: var(--spacing-md); } .phpdocumentor figcaption { text-align: center; font-style: italic; font-size: 80%; } .phpdocumentor-uml-diagram svg { max-width: 100%; height: auto !important; } .phpdocumentor-line { border-top: 1px solid #E1E1E1; border-width: 0; margin-bottom: var(--spacing-xxl); margin-top: var(--spacing-xxl); } .phpdocumentor-section { box-sizing: border-box; margin: 0 auto; max-width: var(--container-width); padding: 0 var(--spacing-sm); position: relative; width: 100%; } @media (min-width: 550px) { .phpdocumentor-section { padding: 0 var(--spacing-lg); } } @media (min-width: 1200px) { .phpdocumentor-section { padding: 0; width: 95%; } } .phpdocumentor-column { box-sizing: border-box; float: left; width: 100%; } @media (min-width: 550px) { .phpdocumentor-column { margin-left: 4%; } .phpdocumentor-column:first-child { margin-left: 0; } .-one.phpdocumentor-column { width: 4.66666666667%; } .-two.phpdocumentor-column { width: 13.3333333333%; } .-three.phpdocumentor-column { width: 22%; } .-four.phpdocumentor-column { width: 30.6666666667%; } .-five.phpdocumentor-column { width: 39.3333333333%; } .-six.phpdocumentor-column { width: 48%; } .-seven.phpdocumentor-column { width: 56.6666666667%; } .-eight.phpdocumentor-column { width: 65.3333333333%; } .-nine.phpdocumentor-column { width: 74.0%; } .-ten.phpdocumentor-column { width: 82.6666666667%; } .-eleven.phpdocumentor-column { width: 91.3333333333%; } .-twelve.phpdocumentor-column { margin-left: 0; width: 100%; } .-one-third.phpdocumentor-column { width: 30.6666666667%; } .-two-thirds.phpdocumentor-column { width: 65.3333333333%; } .-one-half.phpdocumentor-column { width: 48%; } /* Offsets */ .-offset-by-one.phpdocumentor-column { margin-left: 8.66666666667%; } .-offset-by-two.phpdocumentor-column { margin-left: 17.3333333333%; } .-offset-by-three.phpdocumentor-column { margin-left: 26%; } .-offset-by-four.phpdocumentor-column { margin-left: 34.6666666667%; } .-offset-by-five.phpdocumentor-column { margin-left: 43.3333333333%; } .-offset-by-six.phpdocumentor-column { margin-left: 52%; } .-offset-by-seven.phpdocumentor-column { margin-left: 60.6666666667%; } .-offset-by-eight.phpdocumentor-column { margin-left: 69.3333333333%; } .-offset-by-nine.phpdocumentor-column { margin-left: 78.0%; } .-offset-by-ten.phpdocumentor-column { margin-left: 86.6666666667%; } .-offset-by-eleven.phpdocumentor-column { margin-left: 95.3333333333%; } .-offset-by-one-third.phpdocumentor-column { margin-left: 34.6666666667%; } .-offset-by-two-thirds.phpdocumentor-column { margin-left: 69.3333333333%; } .-offset-by-one-half.phpdocumentor-column { margin-left: 52%; } } .phpdocumentor a { color: var(--link-color-primary); } .phpdocumentor a:hover { color: var(--link-hover-color-primary); } .phpdocumentor-button { background-color: var(--button-color); border: 1px solid var(--button-border-color); border-radius: var(--border-radius-base-size); box-sizing: border-box; color: var(--button-text-color); cursor: pointer; display: inline-block; font-size: var(--text-sm); font-weight: 600; height: 38px; letter-spacing: .1rem; line-height: 38px; padding: 0 var(--spacing-xxl); text-align: center; text-decoration: none; text-transform: uppercase; white-space: nowrap; margin-bottom: var(--spacing-md); } .phpdocumentor-button .-wide { width: 100%; } .phpdocumentor-button:hover, .phpdocumentor-button:focus { border-color: #888; color: #333; outline: 0; } .phpdocumentor-button.-primary { background-color: var(--button-color-primary); border-color: var(--button-color-primary); color: var(--button-text-color-primary); } .phpdocumentor-button.-primary:hover, .phpdocumentor-button.-primary:focus { background-color: var(--link-color-primary); border-color: var(--link-color-primary); color: var(--button-text-color-primary); } .phpdocumentor form { margin-bottom: var(--spacing-md); } .phpdocumentor-field { background-color: var(--form-field-color); border: 1px solid var(--form-field-border-color); border-radius: var(--border-radius-base-size); box-shadow: none; box-sizing: border-box; height: 38px; padding: var(--spacing-xxxs) var(--spacing-xxs); /* The 6px vertically centers text on FF, ignored by Webkit */ margin-bottom: var(--spacing-md); } /* Removes awkward default styles on some inputs for iOS */ input[type="email"], input[type="number"], input[type="search"], input[type="text"], input[type="tel"], input[type="url"], input[type="password"], textarea { -moz-appearance: none; -webkit-appearance: none; appearance: none; } .phpdocumentor-textarea { min-height: 65px; padding-bottom: var(--spacing-xxxs); padding-top: var(--spacing-xxxs); } .phpdocumentor-field:focus { border: 1px solid var(--button-color-primary); outline: 0; } label.phpdocumentor-label { display: block; margin-bottom: var(--spacing-xs); } .phpdocumentor-fieldset { border-width: 0; padding: 0; } input[type="checkbox"].phpdocumentor-field, input[type="radio"].phpdocumentor-field { display: inline; } .phpdocumentor-column ul, div.phpdocumentor-list > ul, ul.phpdocumentor-list { list-style: circle; } .phpdocumentor-column ol, div.phpdocumentor-list > ol, ol.phpdocumentor-list { list-style: decimal; } .phpdocumentor-column ul, div.phpdocumentor-list > ul, ol.phpdocumentor-list, ul.phpdocumentor-list { margin-top: 0; padding-left: var(--spacing-lg); margin-bottom: var(--spacing-sm); } .phpdocumentor-column ul.-clean, div.phpdocumentor-list > ul.-clean, ul.phpdocumentor-list.-clean { list-style: none; padding-left: 0; } dl { margin-bottom: var(--spacing-md); } .phpdocumentor-column ul ul, div.phpdocumentor-list > ul ul, ul.phpdocumentor-list ul.phpdocumentor-list, ul.phpdocumentor-list ol.phpdocumentor-list, ol.phpdocumentor-list ol.phpdocumentor-list, ol.phpdocumentor-list ul.phpdocumentor-list { font-size: var(--text-sm); margin: 0 0 0 calc(var(--spacing-xs) * 2); } .phpdocumentor-column ul li, .phpdocumentor-list li { padding-bottom: var(--spacing-xs); } .phpdocumentor dl dt { margin-bottom: var(--spacing-xs); } .phpdocumentor dl dd { margin-bottom: var(--spacing-md); } .phpdocumentor pre { margin-bottom: var(--spacing-md); } .phpdocumentor-code { font-family: var(--font-monospace); background: var(--code-background-color); border: 1px solid var(--code-border-color); border-radius: var(--border-radius-base-size); font-size: var(--text-sm); padding: var(--spacing-sm) var(--spacing-md); width: 100%; box-sizing: border-box; } .phpdocumentor-code.-dark { background: var(--primary-color-darkest); color: var(--light-gray); box-shadow: 0 2px 3px var(--dark-gray); } pre > .phpdocumentor-code { display: block; white-space: pre; } .phpdocumentor blockquote { border-left: 4px solid var(--primary-color-darken); margin: var(--spacing-md) 0; padding: var(--spacing-xs) var(--spacing-sm); color: var(--primary-color-darker); font-style: italic; } .phpdocumentor blockquote p:last-of-type { margin-bottom: 0; } .phpdocumentor table { margin-bottom: var(--spacing-md); } th.phpdocumentor-heading, td.phpdocumentor-cell { border-bottom: 1px solid var(--table-separator-color); padding: var(--spacing-sm) var(--spacing-md); text-align: left; } th.phpdocumentor-heading:first-child, td.phpdocumentor-cell:first-child { padding-left: 0; } th.phpdocumentor-heading:last-child, td.phpdocumentor-cell:last-child { padding-right: 0; } .phpdocumentor-label-line { display: flex; flex-direction: row; gap: 1rem } .phpdocumentor-label { background: #f6f6f6; border-radius: .25rem; font-size: 80%; display: inline-block; overflow: hidden } /* It would be better if the phpdocumentor-element class were to become a flex element with a gap, but for #3337 that is too big a fix and needs to be done in a new design iteration. */ .phpdocumentor-signature + .phpdocumentor-label-line .phpdocumentor-label { margin-top: var(--spacing-sm); } .phpdocumentor-label span { display: inline-block; padding: .125rem .5rem; } .phpdocumentor-label--success span:last-of-type { background: #abe1ab; } .phpdocumentor-header { display: flex; flex-direction: row; align-items: stretch; flex-wrap: wrap; justify-content: space-between; height: auto; padding: var(--spacing-md) var(--spacing-md); } .phpdocumentor-header__menu-button { position: absolute; top: -100%; left: -100%; } .phpdocumentor-header__menu-icon { font-size: 2rem; color: var(--primary-color); } .phpdocumentor-header__menu-button:checked ~ .phpdocumentor-topnav { max-height: 250px; padding-top: var(--spacing-md); } @media (min-width: 1000px) { .phpdocumentor-header { flex-direction: row; padding: var(--spacing-lg) var(--spacing-lg); min-height: var(--header-height); } .phpdocumentor-header__menu-icon { display: none; } } @media (min-width: 1000px) { .phpdocumentor-header { padding-top: 0; padding-bottom: 0; } } @media (min-width: 1200px) { .phpdocumentor-header { padding: 0; } } .phpdocumentor-title { box-sizing: border-box; color: var(--title-text-color); font-size: var(--text-xxl); letter-spacing: .05rem; font-weight: normal; width: auto; margin: 0; display: flex; align-items: center; } .phpdocumentor-title.-without-divider { border: none; } .phpdocumentor-title__link { transition: all .3s ease-out; display: flex; color: var(--title-text-color); text-decoration: none; font-weight: normal; white-space: nowrap; transform: scale(.75); transform-origin: left; } .phpdocumentor-title__link:hover { transform: perspective(15rem) translateX(.5rem); font-weight: 600; } @media (min-width: 1000px) { .phpdocumentor-title { width: 22%; } .phpdocumentor-title__link { transform-origin: left; } } @media (min-width: 1000px) { .phpdocumentor-title__link { transform: scale(.85); } } @media (min-width: 1200px) { .phpdocumentor-title__link { transform: scale(1); } } .phpdocumentor-topnav { display: flex; align-items: center; margin: 0; max-height: 0; overflow: hidden; transition: max-height 0.2s ease-out; flex-basis: 100%; } .phpdocumentor-topnav__menu { text-align: right; list-style: none; margin: 0; padding: 0; flex: 1; display: flex; flex-flow: row wrap; justify-content: center; } .phpdocumentor-topnav__menu-item { margin: 0; width: 100%; display: inline-block; text-align: center; padding: var(--spacing-sm) 0 } .phpdocumentor-topnav__menu-item.-social { width: auto; padding: var(--spacing-sm) } .phpdocumentor-topnav__menu-item a { display: inline-block; color: var(--text-color); text-decoration: none; font-size: var(--text-lg); transition: all .3s ease-out; border-bottom: 1px dotted transparent; line-height: 1; } .phpdocumentor-topnav__menu-item a:hover { transform: perspective(15rem) translateY(.1rem); border-bottom: 1px dotted var(--text-color); } @media (min-width: 1000px) { .phpdocumentor-topnav { max-height: none; overflow: visible; flex-basis: auto; } .phpdocumentor-topnav__menu { display: flex; flex-flow: row wrap; justify-content: flex-end; } .phpdocumentor-topnav__menu-item, .phpdocumentor-topnav__menu-item.-social { width: auto; display: inline; text-align: right; padding: 0 0 0 var(--spacing-md) } } .phpdocumentor-sidebar { margin: 0; overflow: hidden; max-height: 0; } .phpdocumentor .phpdocumentor-sidebar .phpdocumentor-list { padding: var(--spacing-xs) var(--spacing-md); list-style: none; margin: 0; } .phpdocumentor .phpdocumentor-sidebar li { white-space: nowrap; text-overflow: ellipsis; overflow: hidden; padding: 0 0 var(--spacing-xxxs) var(--spacing-md); } .phpdocumentor .phpdocumentor-sidebar abbr, .phpdocumentor .phpdocumentor-sidebar a { text-decoration: none; border-bottom: none; color: var(--text-color); font-size: var(--text-md); padding-left: 0; transition: padding-left .4s ease-out; } .phpdocumentor .phpdocumentor-sidebar a:hover, .phpdocumentor .phpdocumentor-sidebar a.-active { padding-left: 5px; font-weight: 600; } .phpdocumentor .phpdocumentor-sidebar__category > * { border-left: 1px solid var(--primary-color-lighten); } .phpdocumentor .phpdocumentor-sidebar__category { margin-bottom: var(--spacing-lg); } .phpdocumentor .phpdocumentor-sidebar__category-header { font-size: var(--text-md); margin-top: 0; margin-bottom: var(--spacing-xs); color: var(--link-color-primary); font-weight: 600; border-left: 0; } .phpdocumentor .phpdocumentor-sidebar__root-package, .phpdocumentor .phpdocumentor-sidebar__root-namespace { font-size: var(--text-md); margin: 0; padding-top: var(--spacing-xs); padding-left: var(--spacing-md); color: var(--text-color); font-weight: normal; } @media (min-width: 550px) { .phpdocumentor-sidebar { border-right: var(--sidebar-border-color) solid 1px; } } .phpdocumentor-sidebar__menu-button { position: absolute; top: -100%; left: -100%; } .phpdocumentor-sidebar__menu-icon { font-size: var(--text-md); font-weight: 600; background: var(--primary-color); color: white; margin: 0 0 var(--spacing-lg); display: block; padding: var(--spacing-sm); text-align: center; border-radius: 3px; text-transform: uppercase; letter-spacing: .15rem; } .phpdocumentor-sidebar__menu-button:checked ~ .phpdocumentor-sidebar { max-height: 100%; padding-top: var(--spacing-md); } @media (min-width: 550px) { .phpdocumentor-sidebar { overflow: visible; max-height: 100%; } .phpdocumentor-sidebar__menu-icon { display: none; } } .phpdocumentor-admonition { border: 1px solid var(--admonition-border-color); border-radius: var(--border-radius-base-size); border-color: var(--primary-color-lighten); background-color: var(--primary-color-lighter); padding: var(--spacing-lg); margin: var(--spacing-lg) 0; display: flex; flex-direction: row; align-items: flex-start; } .phpdocumentor-admonition p:last-of-type { margin-bottom: 0; } .phpdocumentor-admonition--success, .phpdocumentor-admonition.-success { border-color: var(--admonition-success-color); } .phpdocumentor-admonition__icon { margin-right: var(--spacing-md); color: var(--primary-color); max-width: 3rem; } .phpdocumentor ul.phpdocumentor-breadcrumbs { font-size: var(--text-md); list-style: none; margin: 0; padding: 0; } .phpdocumentor ul.phpdocumentor-breadcrumbs a { color: var(--text-color); text-decoration: none; } .phpdocumentor ul.phpdocumentor-breadcrumbs > li { display: inline-block; margin: 0; } .phpdocumentor ul.phpdocumentor-breadcrumbs > li + li:before { color: var(--dark-gray); content: "\\\A0"; padding: 0; } .phpdocumentor .phpdocumentor-back-to-top { position: fixed; bottom: 2rem; font-size: 2.5rem; opacity: .25; transition: all .3s ease-in-out; right: 2rem; } .phpdocumentor .phpdocumentor-back-to-top:hover { color: var(--link-color-primary); opacity: 1; } .phpdocumentor-search { position: relative; display: none; /** disable by default for non-js flow */ opacity: .3; /** white-out default for loading indication */ transition: opacity .3s, background .3s; margin: var(--spacing-sm) 0; flex: 1; min-width: 100%; } .phpdocumentor-search label { display: flex; align-items: center; flex: 1; } .phpdocumentor-search__icon { color: var(--primary-color); margin-right: var(--spacing-sm); width: 1rem; height: 1rem; } .phpdocumentor-search--enabled { display: flex; } .phpdocumentor-search--active { opacity: 1; } .phpdocumentor-search input:disabled { background-color: lightgray; } .phpdocumentor-search__field:focus, .phpdocumentor-search__field { margin-bottom: 0; border: 0; border-bottom: 2px solid var(--primary-color); padding: 0; border-radius: 0; flex: 1; } @media (min-width: 1000px) { .phpdocumentor-search { min-width: auto; max-width: 20rem; margin: 0 0 0 auto; } } .phpdocumentor-search-results { backdrop-filter: blur(5px); background: var(--popover-background-color); position: fixed; top: 0; left: 0; right: 0; bottom: 0; padding: 0; opacity: 1; pointer-events: all; transition: opacity .3s, background .3s; } .phpdocumentor-search-results--hidden { background: transparent; backdrop-filter: blur(0); opacity: 0; pointer-events: none; } .phpdocumentor-search-results__dialog { width: 100%; background: white; max-height: 100%; display: flex; flex-direction: column; } .phpdocumentor-search-results__body { overflow: auto; } .phpdocumentor-search-results__header { padding: var(--spacing-lg); display: flex; justify-content: space-between; background: var(--primary-color-darken); color: white; align-items: center; } .phpdocumentor-search-results__close { font-size: var(--text-xl); background: none; border: none; padding: 0; margin: 0; } .phpdocumentor .phpdocumentor-search-results__title { font-size: var(--text-xl); margin-bottom: 0; } .phpdocumentor-search-results__entries { list-style: none; padding: 0 var(--spacing-lg); margin: 0; } .phpdocumentor-search-results__entry { border-bottom: 1px solid var(--table-separator-color); padding: var(--spacing-sm) 0; text-align: left; } .phpdocumentor-search-results__entry a { display: block; } .phpdocumentor-search-results__entry small { margin-top: var(--spacing-xs); margin-bottom: var(--spacing-md); color: var(--primary-color-darker); display: block; word-break: break-word; } .phpdocumentor-search-results__entry h3 { font-size: var(--text-lg); margin: 0; } @media (min-width: 550px) { .phpdocumentor-search-results { padding: 0 var(--spacing-lg); } .phpdocumentor-search-results__entry h3 { font-size: var(--text-xxl); } .phpdocumentor-search-results__dialog { margin: var(--spacing-xl) auto; max-width: 40rem; background: white; border: 1px solid silver; box-shadow: 0 2px 5px silver; max-height: 40rem; border-radius: 3px; } } .phpdocumentor-modal { position: fixed; width: 100vw; height: 100vh; opacity: 0; visibility: hidden; transition: all 0.3s ease; top: 0; left: 0; display: flex; align-items: center; justify-content: center; z-index: 1; } .phpdocumentor-modal__open { visibility: visible; opacity: 1; transition-delay: 0s; } .phpdocumentor-modal-bg { position: absolute; background: gray; opacity: 50%; width: 100%; height: 100%; } .phpdocumentor-modal-container { border-radius: 1em; background: #fff; position: relative; padding: 2em; box-sizing: border-box; max-width:100vw; } .phpdocumentor-modal__close { position: absolute; right: 0.75em; top: 0.75em; outline: none; appearance: none; color: var(--primary-color); background: none; border: 0px; font-weight: bold; cursor: pointer; } .phpdocumentor-on-this-page__sidebar { display: none; } .phpdocumentor-on-this-page__title { display: block; font-weight: bold; margin-bottom: var(--spacing-sm); color: var(--link-color-primary); } @media (min-width: 1000px) { .phpdocumentor-on-this-page__sidebar { display: block; position: relative; } .phpdocumentor-on-this-page__content::-webkit-scrollbar, [scrollbars]::-webkit-scrollbar { height: 8px; width: 8px; } .phpdocumentor-on-this-page__content::-webkit-scrollbar-corner, [scrollbars]::-webkit-scrollbar-corner { background: 0; } .phpdocumentor-on-this-page__content::-webkit-scrollbar-thumb, [scrollbars]::-webkit-scrollbar-thumb { background: rgba(128,134,139,0.26); border-radius: 8px; } .phpdocumentor-on-this-page__content { position: sticky; height: calc(100vh - var(--header-height)); overflow-y: auto; border-left: 1px solid var(--sidebar-border-color); padding-left: var(--spacing-lg); font-size: 90%; top: -1px; /* Needed for the javascript to make the .-stuck trick work */ flex: 0 1 auto; width: 15vw; } .phpdocumentor-on-this-page__content.-stuck { height: 100vh; } .phpdocumentor-on-this-page__content li { word-break: break-all; line-height: normal; } .phpdocumentor-on-this-page__content li.-deprecated { text-decoration: line-through; } } /* Used for screen readers and such */ .visually-hidden { display: none; } .float-right { float: right; } .float-left { float: left; } ================================================ FILE: docs/css/normalize.css ================================================ /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ /** * 1. Set default font family to sans-serif. * 2. Prevent iOS text size adjust after orientation change, without disabling * user zoom. */ html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } /** * Remove default margin. */ body { margin: 0; } /* HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined for any HTML5 element in IE 8/9. * Correct `block` display not defined for `details` or `summary` in IE 10/11 * and Firefox. * Correct `block` display not defined for `main` in IE 11. */ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary { display: block; } /** * 1. Correct `inline-block` display not defined in IE 8/9. * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. */ audio, canvas, progress, video { display: inline-block; /* 1 */ vertical-align: baseline; /* 2 */ } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address `[hidden]` styling not present in IE 8/9/10. * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. */ [hidden], template { display: none !important; } /* Links ========================================================================== */ /** * Remove the gray background color from active links in IE 10. */ a { background-color: transparent; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a:active, a:hover { outline: 0; } /* Text-level semantics ========================================================================== */ /** * Address styling not present in IE 8/9/10/11, Safari, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. */ b, strong { font-weight: bold; } /** * Address styling not present in Safari and Chrome. */ dfn { font-style: italic; } /** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari, and Chrome. */ h1 { font-size: 2em; margin: 0.67em 0; } /** * Address styling not present in IE 8/9. */ mark { background: #ff0; color: #000; } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } /* Embedded content ========================================================================== */ /** * Remove border when inside `a` element in IE 8/9/10. */ img { border: 0; } /** * Correct overflow not hidden in IE 9/10/11. */ svg:not(:root) { overflow: hidden; } /* Grouping content ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari. */ figure { margin: 1em 40px; } /** * Address differences between Firefox and other browsers. */ hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } /** * Contain overflow in all browsers. */ pre { overflow: auto; } /** * Address odd `em`-unit font size rendering in all browsers. */ code, kbd, pre, samp { font-family: var(--font-monospace); font-size: 1em; } /* Forms ========================================================================== */ /** * Known limitation: by default, Chrome and Safari on OS X allow very limited * styling of `select`, unless a `border` property is set. */ /** * 1. Correct color not being inherited. * Known issue: affects color of disabled elements. * 2. Correct font properties not being inherited. * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. */ button, input, optgroup, select, textarea { color: inherit; /* 1 */ font: inherit; /* 2 */ margin: 0; /* 3 */ } /** * Address `overflow` set to `hidden` in IE 8/9/10/11. */ button { overflow: visible; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. * Correct `select` style inheritance in Firefox. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ button, html input[type="button"], /* 1 */ input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ input { line-height: normal; } /** * It's recommended that you don't attempt to style these elements. * Firefox's implementation doesn't respect box-sizing, padding, or width. * * 1. Address box sizing set to `content-box` in IE 8/9/10. * 2. Remove excess padding in IE 8/9/10. */ input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * Fix the cursor style for Chrome's increment/decrement buttons. For certain * `font-size` values of the `input`, it causes the cursor style of the * decrement button to change from `default` to `text`. */ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Address `appearance` set to `searchfield` in Safari and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } /** * Remove inner padding and search cancel button in Safari and Chrome on OS X. * Safari (but not Chrome) clips the cancel button when the search input has * padding (and `textfield` appearance). */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9/10/11. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ } /** * Remove default vertical scrollbar in IE 8/9/10/11. */ textarea { overflow: auto; } /** * Don't inherit the `font-weight` (applied by a rule above). * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. */ optgroup { font-weight: bold; } /* Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } td, th { padding: 0; } ================================================ FILE: docs/css/template.css ================================================ .phpdocumentor-content { position: relative; display: flex; gap: var(--spacing-md); } .phpdocumentor-content > section:first-of-type { width: 75%; flex: 1 1 auto; } @media (min-width: 1900px) { .phpdocumentor-content > section:first-of-type { width: 100%; flex: 1 1 auto; } } .phpdocumentor .phpdocumentor-content__title { margin-top: 0; } .phpdocumentor-summary { font-style: italic; } .phpdocumentor-description { margin-bottom: var(--spacing-md); } .phpdocumentor-element { position: relative; } .phpdocumentor-element .phpdocumentor-element { border: 1px solid var(--primary-color-lighten); margin-bottom: var(--spacing-md); padding: var(--spacing-xs); border-radius: 5px; } .phpdocumentor-element.-deprecated .phpdocumentor-element__name { text-decoration: line-through; } @media (min-width: 550px) { .phpdocumentor-element .phpdocumentor-element { margin-bottom: var(--spacing-lg); padding: var(--spacing-md); } } .phpdocumentor-element__modifier { font-size: var(--text-xxs); padding: calc(var(--spacing-base-size) / 4) calc(var(--spacing-base-size) / 2); color: var(--text-color); background-color: var(--light-gray); border-radius: 3px; text-transform: uppercase; } .phpdocumentor .phpdocumentor-elements__header { margin-top: var(--spacing-xxl); margin-bottom: var(--spacing-lg); } .phpdocumentor .phpdocumentor-element__name { line-height: 1; margin-top: 0; font-weight: 300; font-size: var(--text-lg); word-break: break-all; margin-bottom: var(--spacing-sm); } @media (min-width: 550px) { .phpdocumentor .phpdocumentor-element__name { font-size: var(--text-xl); margin-bottom: var(--spacing-xs); } } @media (min-width: 1200px) { .phpdocumentor .phpdocumentor-element__name { margin-bottom: var(--spacing-md); } } .phpdocumentor-element__package, .phpdocumentor-element__extends, .phpdocumentor-element__implements { display: block; font-size: var(--text-xxs); font-weight: normal; opacity: .7; } .phpdocumentor-element__package .phpdocumentor-breadcrumbs { display: inline; } .phpdocumentor .phpdocumentor-signature { display: block; font-size: var(--text-sm); border: 1px solid #f0f0f0; } .phpdocumentor .phpdocumentor-signature.-deprecated .phpdocumentor-signature__name { text-decoration: line-through; } @media (min-width: 550px) { .phpdocumentor .phpdocumentor-signature { margin-left: calc(var(--spacing-xl) * -1); width: calc(100% + var(--spacing-xl)); } } .phpdocumentor-table-of-contents { } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry { margin-bottom: var(--spacing-xxs); margin-left: 2rem; display: flex; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry > a { flex: 0 1 auto; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry > a.-deprecated { text-decoration: line-through; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry > span { flex: 1; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry:after { content: ''; height: 12px; width: 12px; left: 16px; position: absolute; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-private:after { background: url('data:image/svg+xml;utf8,') no-repeat; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-protected:after { left: 13px; background: url('data:image/svg+xml;utf8,') no-repeat; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry:before { width: 1.25rem; height: 1.25rem; line-height: 1.25rem; background: transparent url('data:image/svg+xml;utf8,') no-repeat center center; content: ''; position: absolute; left: 0; border-radius: 50%; font-weight: 600; color: white; text-align: center; font-size: .75rem; margin-top: .2rem; } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-method:before { content: 'M'; color: ''; background-image: url('data:image/svg+xml;utf8,'); } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-function:before { content: 'M'; color: ' 96'; background-image: url('data:image/svg+xml;utf8,'); } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-property:before { content: 'P' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-constant:before { content: 'C'; background-color: transparent; background-image: url('data:image/svg+xml;utf8,'); } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-class:before { content: 'C' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-interface:before { content: 'I' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-trait:before { content: 'T' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-namespace:before { content: 'N' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-package:before { content: 'P' } .phpdocumentor-table-of-contents .phpdocumentor-table-of-contents__entry.-enum:before { content: 'E' } .phpdocumentor-table-of-contents dd { font-style: italic; margin-left: 2rem; } .phpdocumentor-element-found-in { display: none; } @media (min-width: 550px) { .phpdocumentor-element-found-in { display: block; font-size: var(--text-sm); color: gray; margin-bottom: 1rem; } } @media (min-width: 1200px) { .phpdocumentor-element-found-in { position: absolute; top: var(--spacing-sm); right: var(--spacing-sm); font-size: var(--text-sm); margin-bottom: 0; } } .phpdocumentor-element-found-in .phpdocumentor-element-found-in__source { flex: 0 1 auto; display: inline-flex; } .phpdocumentor-element-found-in .phpdocumentor-element-found-in__source:after { width: 1.25rem; height: 1.25rem; line-height: 1.25rem; background: transparent url('data:image/svg+xml;utf8,') no-repeat center center; content: ''; left: 0; border-radius: 50%; font-weight: 600; text-align: center; font-size: .75rem; margin-top: .2rem; } .phpdocumentor-class-graph { width: 100%; height: 600px; border:1px solid black; overflow: hidden } .phpdocumentor-class-graph__graph { width: 100%; } .phpdocumentor-tag-list__definition { display: flex; } .phpdocumentor-tag-link { margin-right: var(--spacing-sm); } .phpdocumentor-uml-diagram svg { cursor: zoom-in; } ================================================ FILE: docs/files/BrowserDetection.php.txt ================================================ getName() == Wolfcast\BrowserDetection::BROWSER_FIREFOX && * $browser->compareVersions($browser->getVersion(), '5.0') >= 0) { * echo 'You are using FireFox version 5 or greater.'; * } * ``` * * The class is a rewrite of Chris Schuld's Browser class version 1.9 which is mostly unmaintained since August 20th, * 2010. Chris' class was based on the original work from Gary White. * * Updates: * * 2025-03-23: Version 2.9.9 * + Added macOS Sequoia detection for browsers that still correctly report the macOS version. * * 2024-04-21: Version 2.9.8 * + Added macOS Sonoma and macOS Ventura detection. Note that all the majors Web browsers have reported macOS Catalina * since 2021 for any macOS 11+ versions. See the documentation of macVerToStr() for more details. * + Improved the library documentation when detecting Windows version names since Windows 11 is always reported as * Windows 10. See windowsNTVerToStr() for more details. * + Updated HTML documentation of the library to the latest version of phpDocumentor. * * 2022-09-20: Version 2.9.7 * + Changed licensing to dual licensing: MIT or LGPL-3.0-only. This has no impact on existing users. You can continue * under the previous license or switch to MIT. * * 2022-05-01: Version 2.9.6 * + Added support for Chrome OS. * + Added support for macOS Monterey and macOS Big Sur. * + Now correctly detects AArch64 as 64-bit. * + Added support for PHP 8. * + Tested with latest Web Browsers and platforms. * * 2020-02-02: Version 2.9.5 * + WARNING! Breaking change: complete rework of robots detection. Now robot name and version is detected in addition * of browser name and version. Use getRobotName() and getRobotVersion() when isRobot() is true. * + WARNING! Breaking change: due to robots detection rework the following methods signatures has changed (isRobot * parameter removed): addCustomBrowserDetection(), checkSimpleBrowserUA(), checkBrowserUAWithVersion(). * + Added possibility to support new robots with addCustomRobotDetection(). * + Added support for the new Microsoft Edge based on Chromium. * + Added version names for Android 10 and later (Google no longer use candy names for new versions). * + Added macOS Catalina detection. * + Added Windows Server 2019 detection (Windows Server 2016 can be no longer detected due to the fact that they both * use the same version number and that the build is not included in the user agent). * * 2019-03-27: Version 2.9.3 * + Fixed Edge detection on Android. * + Added Android Q detection. * + Now filtering superglobals. * * 2019-02-28: Version 2.9.2 * + Fixed Opera detection. * * 2018-08-23: Version 2.9.1 * + Fixed Chrome detection under iOS. * + Added Android Pie detection. * + Added macOS Mojave detection. * * 2018-07-15: Version 2.9.0 * + WARNING! Breaking change: new Wolfcast namespace. Use new Wolfcast\BrowserDetection(). * + iPad, iPhone and iPod are all under iOS now. * + Added Android Oreo detection. * + Added macOS High Sierra detection. * + Added UC Browser detection. * + Improved regular expressions (even less false positives). * + Removed AOL detection. * + Removed the following Web browsers detection: Amaya, Galeon, NetPositive, OmniWeb, Vivaldi detection (use * addCustomBrowserDetection()). * + Removed the following legacy platforms detection: BeOS, OS/2, SunOS (use addCustomPlatformDetection()). * * 2016-11-28: Version 2.5.1 * + Better detection of 64-bit platforms. * * 2016-08-19: Version 2.5.0 * + Platform version and platform version name are now supported for Mac. * + Fixed platform version name for Android. * * 2016-08-02: Version 2.4.0 * + Platform version and platform version name are now supported for Android. * + Added support for the Samsung Internet browser. * + Added support for the Vivaldi browser. * + Better support for legacy Windows versions. * * 2016-02-11: Version 2.3.0 * + WARNING! Breaking change: public method getBrowser() is renamed to getName(). * + WARNING! Breaking change: changed the compareVersions() return values to be more in line with other libraries. * + You can now get the exact platform version (name or version numbers) on which the browser is run on with * getPlatformVersion(). Only working with Windows operating systems at the moment. * + You can now determine if the browser is executed from a 64-bit platform with is64bitPlatform(). * + Better detection of mobile platform for Googlebot. * * 2016-01-04: Version 2.2.0 * + Added support for Microsoft Edge. * * 2014-12-30: Version 2.1.2 * + Better detection of Opera. * * 2014-07-11: Version 2.1.1 * + Better detection of mobile devices and platforms. * * 2014-06-04: Version 2.1.0 * + Added support for IE 11+. * * 2013-05-27: Version 2.0.0 which is (almost) a complete rewrite based on Chris Schuld's Browser class version 1.9 plus * changes below. * + Added support for Opera Mobile * + Added support for the Windows Phone (formerly Windows Mobile) platform * + Added support for BlackBerry Tablet OS and BlackBerry 10 * + Added support for the Symbian platform * + Added support for Bingbot * + Added support for the Yahoo! Multimedia crawler * + Removed iPhone/iPad/iPod browsers since there are not browsers but platforms - test them with getPlatform() * + Removed support for Shiretoko (Firefox 3.5 alpha/beta) and MSN Browser * + Merged Nokia and Nokia S60 * + Updated some deprecated browser names * + Many public methods are now protected * + Documentation updated * * 2010-07-04: * + Added detection of IE compatibility view - test with getIECompatibilityView() * + Added support for all (deprecated) Netscape versions * + Added support for Safari < 3.0 * + Better Firefox version parsing * + Better Opera version parsing * + Better Mozilla detection * * @package BrowserDetection * @version 2.9.9 * @last-modified March 23, 2025 * @author Alexandre Valiquette, Chris Schuld, Gary White * @copyright Copyright (c) 2025, Wolfcast * @license https://spdx.org/licenses/GPL-3.0-only.html * @license https://spdx.org/licenses/MIT.html * @link https://wolfcast.com/ * @link https://wolfcast.com/open-source/browser-detection/tutorial.php * @link https://chrisschuld.com/ */ class BrowserDetection { /**#@+ * Constant for the name of the Web browser. */ const BROWSER_ANDROID = 'Android'; const BROWSER_BLACKBERRY = 'BlackBerry'; const BROWSER_CHROME = 'Chrome'; const BROWSER_EDGE = 'Edge'; const BROWSER_FIREBIRD = 'Firebird'; const BROWSER_FIREFOX = 'Firefox'; const BROWSER_ICAB = 'iCab'; const BROWSER_ICECAT = 'GNU IceCat'; const BROWSER_ICEWEASEL = 'GNU IceWeasel'; const BROWSER_IE = 'Internet Explorer'; const BROWSER_IE_MOBILE = 'Internet Explorer Mobile'; const BROWSER_KONQUEROR = 'Konqueror'; const BROWSER_LYNX = 'Lynx'; const BROWSER_MOZILLA = 'Mozilla'; const BROWSER_MSNTV = 'MSN TV'; const BROWSER_NETSCAPE = 'Netscape'; const BROWSER_NOKIA = 'Nokia Browser'; const BROWSER_OPERA = 'Opera'; const BROWSER_OPERA_MINI = 'Opera Mini'; const BROWSER_OPERA_MOBILE = 'Opera Mobile'; const BROWSER_PHOENIX = 'Phoenix'; const BROWSER_SAFARI = 'Safari'; const BROWSER_SAMSUNG = 'Samsung Internet'; const BROWSER_TABLET_OS = 'BlackBerry Tablet OS'; const BROWSER_UC = 'UC Browser'; const BROWSER_UNKNOWN = 'unknown'; /**#@-*/ /**#@+ * Constant for the name of the platform on which the Web browser runs. */ const PLATFORM_ANDROID = 'Android'; const PLATFORM_BLACKBERRY = 'BlackBerry'; const PLATFORM_CHROME_OS = 'Chrome OS'; const PLATFORM_FREEBSD = 'FreeBSD'; const PLATFORM_IOS = 'iOS'; const PLATFORM_LINUX = 'Linux'; const PLATFORM_MACINTOSH = 'Macintosh'; const PLATFORM_NETBSD = 'NetBSD'; const PLATFORM_NOKIA = 'Nokia'; const PLATFORM_OPENBSD = 'OpenBSD'; const PLATFORM_OPENSOLARIS = 'OpenSolaris'; const PLATFORM_SYMBIAN = 'Symbian'; const PLATFORM_UNKNOWN = 'unknown'; const PLATFORM_VERSION_UNKNOWN = 'unknown'; const PLATFORM_WINDOWS = 'Windows'; const PLATFORM_WINDOWS_CE = 'Windows CE'; const PLATFORM_WINDOWS_PHONE = 'Windows Phone'; /**#@-*/ /**#@+ * Constant for the name of the robot. */ const ROBOT_BINGBOT = 'Bingbot'; const ROBOT_GOOGLEBOT = 'Googlebot'; const ROBOT_MSNBOT = 'MSNBot'; const ROBOT_SLURP = 'Yahoo! Slurp'; const ROBOT_UNKNOWN = ''; const ROBOT_VERSION_UNKNOWN = ''; const ROBOT_W3CVALIDATOR = 'W3C Validator'; const ROBOT_YAHOO_MM = 'Yahoo! Multimedia'; /**#@-*/ /** * Version unknown constant. */ const VERSION_UNKNOWN = 'unknown'; /** * @var string * @access private */ private $_agent = ''; /** * @var string * @access private */ private $_browserName = ''; /** * @var string * @access private */ private $_compatibilityViewName = ''; /** * @var string * @access private */ private $_compatibilityViewVer = ''; /** * @var array * @access private */ private $_customBrowserDetection = array(); /** * @var array * @access private */ private $_customPlatformDetection = array(); /** * @var array * @access private */ private $_customRobotDetection = array(); /** * @var boolean * @access private */ private $_is64bit = false; /** * @var boolean * @access private */ private $_isMobile = false; /** * @var boolean * @access private */ private $_isRobot = false; /** * @var string * @access private */ private $_platform = ''; /** * @var string * @access private */ private $_platformVersion = ''; /** * @var string * @access private */ private $_robotName = ''; /** * @var string * @access private */ private $_robotVersion = ''; /** * @var string * @access private */ private $_version = ''; //--- MAGIC METHODS ------------------------------------------------------------------------------------------------ /** * BrowserDetection class constructor. * @param string $useragent (optional) The user agent to work with. Leave empty for the current user agent * (contained in $_SERVER['HTTP_USER_AGENT']). */ public function __construct($useragent = '') { $this->setUserAgent($useragent); } /** * Determine how the class will react when it is treated like a string. * @return string Returns an HTML formatted string with a summary of the browser informations. */ public function __toString() { $result = ''; $values = array(); $values[] = array('label' => 'User agent', 'value' => $this->getUserAgent()); $values[] = array('label' => 'Browser name', 'value' => $this->getName()); $values[] = array('label' => 'Browser version', 'value' => $this->getVersion()); $values[] = array('label' => 'Platform family', 'value' => $this->getPlatform()); $values[] = array('label' => 'Platform version', 'value' => $this->getPlatformVersion(true)); $values[] = array('label' => 'Platform version name', 'value' => $this->getPlatformVersion()); $values[] = array('label' => 'Platform is 64-bit', 'value' => $this->is64bitPlatform() ? 'true' : 'false'); $values[] = array('label' => 'Is mobile', 'value' => $this->isMobile() ? 'true' : 'false'); $values[] = array('label' => 'Is robot', 'value' => $this->isRobot() ? 'true' : 'false'); $values[] = array('label' => 'Robot name', 'value' => $this->isRobot() ? ($this->getRobotName() != self::ROBOT_UNKNOWN ? $this->getRobotName() : 'Unknown') : 'Not applicable'); $values[] = array('label' => 'Robot version', 'value' => $this->isRobot() ? ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN ? $this->getRobotVersion() : 'Unknown') : 'Not applicable'); $values[] = array('label' => 'IE is in compatibility view', 'value' => $this->isInIECompatibilityView() ? 'true' : 'false'); $values[] = array('label' => 'Emulated IE version', 'value' => $this->isInIECompatibilityView() ? $this->getIECompatibilityView() : 'Not applicable'); $values[] = array('label' => 'Is Chrome Frame', 'value' => $this->isChromeFrame() ? 'true' : 'false'); foreach ($values as $currVal) { $result .= '' . htmlspecialchars($currVal['label'], ENT_NOQUOTES) . ': ' . $currVal['value'] . '
    ' . PHP_EOL; } return $result; } //--- PUBLIC MEMBERS ----------------------------------------------------------------------------------------------- /** * Dynamically add support for a new Web browser. * @param string $browserName The Web browser name (used for display). * @param mixed $uaNameToLookFor (optional) The string (or array of strings) representing the browser name to find * in the user agent. If omitted, $browserName will be used. * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param string $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @see removeCustomBrowserDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomBrowserDetection($browserName, $uaNameToLookFor = '', $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($browserName == '') { return false; } if (array_key_exists($browserName, $this->_customBrowserDetection)) { unset($this->_customBrowserDetection[$browserName]); } if ($uaNameToLookFor == '') { $uaNameToLookFor = $browserName; } $this->_customBrowserDetection[$browserName] = array('uaNameToLookFor' => $uaNameToLookFor, 'isMobile' => $isMobile == true, 'separator' => $separator, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Dynamically add support for a new platform. * @param string $platformName The platform name (used for display). * @param mixed $platformNameToLookFor (optional) The string (or array of strings) representing the platform name to * find in the user agent. If omitted, $platformName will be used. * @param boolean $isMobile (optional) Determines if the platform is from a mobile device. * @param boolean $uaNameFindWords (optional) Determines if the platform name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * @see removeCustomPlatformDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomPlatformDetection($platformName, $platformNameToLookFor = '', $isMobile = false, $uaNameFindWords = true) { if ($platformName == '') { return false; } if (array_key_exists($platformName, $this->_customPlatformDetection)) { unset($this->_customPlatformDetection[$platformName]); } if ($platformNameToLookFor == '') { $platformNameToLookFor = $platformName; } $this->_customPlatformDetection[$platformName] = array('platformNameToLookFor' => $platformNameToLookFor, 'isMobile' => $isMobile == true, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Dynamically add support for a new robot. * @param string $robotName The robot name (used for display). * @param mixed $uaNameToLookFor (optional) The string (or array of strings) representing the robot name to find * in the user agent. If omitted, $robotName will be used. * @param boolean $isMobile (optional) Determines if the robot should be considered as mobile or not. * @param string $separator (optional) The separator string used to split the robot name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the robot name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the robot name can be found anywhere in the user agent string. * @see removeCustomRobotDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomRobotDetection($robotName, $uaNameToLookFor = '', $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($robotName == '') { return false; } if (array_key_exists($robotName, $this->_customRobotDetection)) { unset($this->_customRobotDetection[$robotName]); } if ($uaNameToLookFor == '') { $uaNameToLookFor = $robotName; } $this->_customRobotDetection[$robotName] = array('uaNameToLookFor' => $uaNameToLookFor, 'isMobile' => $isMobile == true, 'separator' => $separator, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Compare two version number strings. * @param string $sourceVer The source version number. * @param string $compareVer The version number to compare with the source version number. * @return int Returns -1 if $sourceVer < $compareVer, 0 if $sourceVer == $compareVer or 1 if $sourceVer > * $compareVer. */ public function compareVersions($sourceVer, $compareVer) { $sourceVer = explode('.', $sourceVer); foreach ($sourceVer as $k => $v) { $sourceVer[$k] = $this->parseInt($v); } $compareVer = explode('.', $compareVer); foreach ($compareVer as $k => $v) { $compareVer[$k] = $this->parseInt($v); } if (count($sourceVer) != count($compareVer)) { if (count($sourceVer) > count($compareVer)) { for ($i = count($compareVer); $i < count($sourceVer); $i++) { $compareVer[$i] = 0; } } else { for ($i = count($sourceVer); $i < count($compareVer); $i++) { $sourceVer[$i] = 0; } } } foreach ($sourceVer as $i => $srcVerPart) { if ($srcVerPart > $compareVer[$i]) { return 1; } else { if ($srcVerPart < $compareVer[$i]) { return -1; } } } return 0; } /** * Get the name and version of the browser emulated in the compatibility view mode (if any). Since Internet * Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially * IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those * older versions of IE. * @param boolean $asArray (optional) Determines if the return value must be an array (true) or a string (false). * @return mixed If a string was requested, the function returns the name and version of the browser emulated in * the compatibility view mode or an empty string if the browser is not in compatibility view mode. If an array was * requested, an array with the keys 'browser' and 'version' is returned. */ public function getIECompatibilityView($asArray = false) { if ($asArray) { return array('browser' => $this->_compatibilityViewName, 'version' => $this->_compatibilityViewVer); } else { return trim($this->_compatibilityViewName . ' ' . $this->_compatibilityViewVer); } } /** * Return the BrowserDetection class version. * @return string Returns the version as a sting with the #.#.# format. */ public function getLibVersion() { return '2.9.9'; } /** * Get the name of the browser. All of the return values are class constants. You can compare them like this: * $myBrowserInstance->getName() == BrowserDetection::BROWSER_FIREFOX. * @return string Returns the name of the browser or BrowserDetection::BROWSER_UNKNOWN if unknown. */ public function getName() { return $this->_browserName; } /** * Get the name of the platform family on which the browser is run on (such as Windows, Apple, etc.). All of * the return values are class constants. You can compare them like this: * $myBrowserInstance->getPlatform() == BrowserDetection::PLATFORM_ANDROID. * @return string Returns the name of the platform or BrowserDetection::PLATFORM_UNKNOWN if unknown. */ public function getPlatform() { return $this->_platform; } /** * Get the platform version on which the browser is run on. It can be returned as a string number like 'NT 6.3' or * as a name like 'Windows 8.1'. When returning version string numbers for Windows NT OS families the number is * prefixed by 'NT ' to differentiate from older Windows 3.x & 9x release. At the moment only the Windows and * Android operating systems are supported. * @param boolean $returnVersionNumbers (optional) Determines if the return value must be versions numbers as a * string (true) or the version name (false). * @param boolean $returnServerFlavor (optional) Since some Windows NT versions have the same values, this flag * determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use * version 6.3. This parameter is only useful when testing for Windows. * @return string Returns the version name/version numbers of the platform or the constant PLATFORM_VERSION_UNKNOWN * if unknown. */ public function getPlatformVersion($returnVersionNumbers = false, $returnServerFlavor = false) { if ($this->_platformVersion == self::PLATFORM_VERSION_UNKNOWN || $this->_platformVersion == '') { return self::PLATFORM_VERSION_UNKNOWN; } if ($returnVersionNumbers) { return $this->_platformVersion; } else { switch ($this->getPlatform()) { case self::PLATFORM_WINDOWS: if (substr($this->_platformVersion, 0, 3) == 'NT ') { return $this->windowsNTVerToStr(substr($this->_platformVersion, 3), $returnServerFlavor); } else { return $this->windowsVerToStr($this->_platformVersion); } break; case self::PLATFORM_MACINTOSH: return $this->macVerToStr($this->_platformVersion); case self::PLATFORM_ANDROID: return $this->androidVerToStr($this->_platformVersion); case self::PLATFORM_IOS: return $this->iOSVerToStr($this->_platformVersion); default: return self::PLATFORM_VERSION_UNKNOWN; } } } /** * Get the name of the robot. All of the return values are class constants. You can compare them like this: * $myBrowserInstance->getRobotName() == BrowserDetection::ROBOT_GOOGLEBOT. * @return string Returns the name of the robot or BrowserDetection::ROBOT_UNKNOWN if unknown. */ public function getRobotName() { return $this->_robotName; } /** * Get the version of the robot. * @return string Returns the version of the robot or BrowserDetection::ROBOT_VERSION_UNKNOWN if unknown. */ public function getRobotVersion() { return $this->_robotVersion; } /** * Get the user agent value used by the class to determine the browser details. * @return string The user agent string. */ public function getUserAgent() { return $this->_agent; } /** * Get the version of the browser. * @return string Returns the version of the browser or BrowserDetection::VERSION_UNKNOWN if unknown. */ public function getVersion() { return $this->_version; } /** * Determine if the browser is executed from a 64-bit platform. Keep in mind that not all platforms/browsers report * this and the result may not always be accurate. * @return boolean Returns true if the browser is executed from a 64-bit platform. */ public function is64bitPlatform() { return $this->_is64bit; } /** * Determine if the browser runs Google Chrome Frame (it's a plug-in designed for Internet Explorer 6+ based on the * open-source Chromium project - it's like a Chrome browser within IE). * @return boolean Returns true if the browser is using Google Chrome Frame, false otherwise. */ public function isChromeFrame() { return $this->containString($this->_agent, 'chromeframe'); } /** * Determine if the browser is in compatibility view or not. Since Internet Explorer 8, IE can be put in * compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in * IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE. * @return boolean Returns true if the browser is in compatibility view, false otherwise. */ public function isInIECompatibilityView() { return ($this->_compatibilityViewName != '') || ($this->_compatibilityViewVer != ''); } /** * Determine if the browser is from a mobile device or not. * @return boolean Returns true if the browser is from a mobile device, false otherwise. */ public function isMobile() { return $this->_isMobile; } /** * Determine if the browser is a robot (Googlebot, Bingbot, Yahoo! Slurp...) or not. * @return boolean Returns true if the browser is a robot, false otherwise. */ public function isRobot() { return $this->_isRobot; } /** * Remove support for a previously added Web browser. * @param string $browserName The Web browser name as used when added. * @see addCustomBrowserDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomBrowserDetection($browserName) { if (array_key_exists($browserName, $this->_customBrowserDetection)) { unset($this->_customBrowserDetection[$browserName]); return true; } return false; } /** * Remove support for a previously added platform. * @param string $platformName The platform name as used when added. * @see addCustomPlatformDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomPlatformDetection($platformName) { if (array_key_exists($platformName, $this->_customPlatformDetection)) { unset($this->_customPlatformDetection[$platformName]); return true; } return false; } /** * Remove support for a previously added robot. * @param string $robotName The robot name as used when added. * @see addCustomRobotDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomRobotDetection($robotName) { if (array_key_exists($robotName, $this->_customRobotDetection)) { unset($this->_customRobotDetection[$robotName]); return true; } return false; } /** * Set the user agent to use with the class. * @param string $agentString (optional) The value of the user agent. If an empty string is sent (default), * $_SERVER['HTTP_USER_AGENT'] will be used. */ public function setUserAgent($agentString = '') { if (!is_string($agentString) || trim($agentString) == '') { //https://bugs.php.net/bug.php?id=49184 if (filter_has_var(INPUT_SERVER, 'HTTP_USER_AGENT')) { $agentString = filter_input(INPUT_SERVER, 'HTTP_USER_AGENT', FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); } else if (array_key_exists('HTTP_USER_AGENT', $_SERVER) && is_string($_SERVER['HTTP_USER_AGENT'])) { $agentString = filter_var($_SERVER['HTTP_USER_AGENT'], FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); } else { $agentString = ''; } if ($agentString === false || $agentString === NULL) { //filter_input or filter_var failed $agentString = ''; } } $this->reset(); $this->_agent = $agentString; $this->detect(); } //--- PROTECTED MEMBERS -------------------------------------------------------------------------------------------- /** * Convert the Android version numbers to the operating system name. For instance '1.6' returns 'Donut'. * @access protected * @param string $androidVer The Android version numbers as a string. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function androidVerToStr($androidVer) { //https://en.wikipedia.org/wiki/Android_version_history if ($this->compareVersions($androidVer, '10') >= 0) { $majorVer = strstr($androidVer, '.', true); if ($majorVer == '') { $majorVer = $androidVer; } return self::BROWSER_ANDROID . ' ' . $majorVer; } else if ($this->compareVersions($androidVer, '9') >= 0 && $this->compareVersions($androidVer, '10') < 0) { return 'Pie'; } else if ($this->compareVersions($androidVer, '8') >= 0 && $this->compareVersions($androidVer, '9') < 0) { return 'Oreo'; } else if ($this->compareVersions($androidVer, '7') >= 0 && $this->compareVersions($androidVer, '8') < 0) { return 'Nougat'; } else if ($this->compareVersions($androidVer, '6') >= 0 && $this->compareVersions($androidVer, '7') < 0) { return 'Marshmallow'; } else if ($this->compareVersions($androidVer, '5') >= 0 && $this->compareVersions($androidVer, '5.2') < 0) { return 'Lollipop'; } else if ($this->compareVersions($androidVer, '4.4') >= 0 && $this->compareVersions($androidVer, '4.5') < 0) { return 'KitKat'; } else if ($this->compareVersions($androidVer, '4.1') >= 0 && $this->compareVersions($androidVer, '4.4') < 0) { return 'Jelly Bean'; } else if ($this->compareVersions($androidVer, '4') >= 0 && $this->compareVersions($androidVer, '4.1') < 0) { return 'Ice Cream Sandwich'; } else if ($this->compareVersions($androidVer, '3') >= 0 && $this->compareVersions($androidVer, '3.3') < 0) { return 'Honeycomb'; } else if ($this->compareVersions($androidVer, '2.3') >= 0 && $this->compareVersions($androidVer, '2.4') < 0) { return 'Gingerbread'; } else if ($this->compareVersions($androidVer, '2.2') >= 0 && $this->compareVersions($androidVer, '2.3') < 0) { return 'Froyo'; } else if ($this->compareVersions($androidVer, '2') >= 0 && $this->compareVersions($androidVer, '2.2') < 0) { return 'Eclair'; } else if ($this->compareVersions($androidVer, '1.6') == 0) { return 'Donut'; } else if ($this->compareVersions($androidVer, '1.5') == 0) { return 'Cupcake'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Unknown/unnamed Android version } } /** * Determine if the browser is the Android browser (based on the WebKit layout engine and coupled with Chrome's * JavaScript engine) or not. * @access protected * @return boolean Returns true if the browser is the Android browser, false otherwise. */ protected function checkBrowserAndroid() { //Android don't use the standard "Android/1.0", it uses "Android 1.0;" instead return $this->checkSimpleBrowserUA('Android', $this->_agent, self::BROWSER_ANDROID, true); } /** * Determine if the browser is the BlackBerry browser or not. * @access protected * @link https://web.archive.org/web/20170328000854/http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/How-to-detect-the-BlackBerry-Browser/ta-p/559862 * @return boolean Returns true if the browser is the BlackBerry browser, false otherwise. */ protected function checkBrowserBlackBerry() { $found = false; //Tablet OS check if ($this->checkSimpleBrowserUA('RIM Tablet OS', $this->_agent, self::BROWSER_TABLET_OS, true)) { return true; } //Version 6, 7 & 10 check (versions 8 & 9 does not exists) if ($this->checkBrowserUAWithVersion(array('BlackBerry', 'BB10'), $this->_agent, self::BROWSER_BLACKBERRY, true)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { $found = true; } else { return true; } } //Version 4.2 to 5.0 check if ($this->checkSimpleBrowserUA('BlackBerry', $this->_agent, self::BROWSER_BLACKBERRY, true, '/', false)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { $found = true; } else { return true; } } return $found; } /** * Determine if the browser is Chrome or not. * @access protected * @link https://www.google.com/chrome/ * @return boolean Returns true if the browser is Chrome, false otherwise. */ protected function checkBrowserChrome() { return $this->checkSimpleBrowserUA(array('Chrome', 'CriOS'), $this->_agent, self::BROWSER_CHROME); } /** * Determine if the browser is among the custom browser rules or not. Rules are checked in the order they were * added. * @access protected * @return boolean Returns true if we found the browser we were looking for in the custom rules, false otherwise. */ protected function checkBrowserCustom() { foreach ($this->_customBrowserDetection as $browserName => $customBrowser) { $uaNameToLookFor = $customBrowser['uaNameToLookFor']; $isMobile = $customBrowser['isMobile']; $separator = $customBrowser['separator']; $uaNameFindWords = $customBrowser['uaNameFindWords']; if ($this->checkSimpleBrowserUA($uaNameToLookFor, $this->_agent, $browserName, $isMobile, $separator, $uaNameFindWords)) { return true; } } return false; } /** * Determine if the browser is Edge or not. * @access protected * @return boolean Returns true if the browser is Edge, false otherwise. */ protected function checkBrowserEdge() { return $this->checkSimpleBrowserUA(array('Edg', 'Edge', 'EdgA'), $this->_agent, self::BROWSER_EDGE); } /** * Determine if the browser is Firebird or not. Firebird was the name of Firefox from version 0.6 to 0.7.1. * @access protected * @return boolean Returns true if the browser is Firebird, false otherwise. */ protected function checkBrowserFirebird() { return $this->checkSimpleBrowserUA('Firebird', $this->_agent, self::BROWSER_FIREBIRD); } /** * Determine if the browser is Firefox or not. * @access protected * @link https://www.mozilla.org/en-US/firefox/new/ * @return boolean Returns true if the browser is Firefox, false otherwise. */ protected function checkBrowserFirefox() { //Safari heavily matches with Firefox, ensure that Safari is filtered out... if (preg_match('/.*Firefox[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches) && !$this->containString($this->_agent, 'Safari')) { $this->setBrowser(self::BROWSER_FIREFOX); $this->setVersion($matches[1]); $this->setMobile(false); $this->setRobot(false); return true; } return false; } /** * Determine if the browser is iCab or not. * @access protected * @link http://www.icab.de/ * @return boolean Returns true if the browser is iCab, false otherwise. */ protected function checkBrowserIcab() { //Some (early) iCab versions don't use the standard "iCab/1.0", they uses "iCab 1.0;" instead return $this->checkSimpleBrowserUA('iCab', $this->_agent, self::BROWSER_ICAB); } /** * Determine if the browser is GNU IceCat (formerly known as GNU IceWeasel) or not. * @access protected * @link https://www.gnu.org/software/gnuzilla/ * @return boolean Returns true if the browser is GNU IceCat, false otherwise. */ protected function checkBrowserIceCat() { return $this->checkSimpleBrowserUA('IceCat', $this->_agent, self::BROWSER_ICECAT); } /** * Determine if the browser is GNU IceWeasel (now know as GNU IceCat) or not. * @access protected * @see checkBrowserIceCat() * @return boolean Returns true if the browser is GNU IceWeasel, false otherwise. */ protected function checkBrowserIceWeasel() { return $this->checkSimpleBrowserUA('Iceweasel', $this->_agent, self::BROWSER_ICEWEASEL); } /** * Determine if the browser is Internet Explorer or not. * @access protected * @link https://en.wikipedia.org/wiki/Internet_Explorer * @link https://en.wikipedia.org/wiki/Internet_Explorer_Mobile * @return boolean Returns true if the browser is Internet Explorer, false otherwise. */ protected function checkBrowserInternetExplorer() { //Test for Internet Explorer Mobile (formerly Pocket Internet Explorer) if ($this->checkSimpleBrowserUA(array('IEMobile', 'MSPIE'), $this->_agent, self::BROWSER_IE_MOBILE, true)) { return true; } //Several browsers uses IE compatibility UAs filter these browsers out (but after testing for IE Mobile) if ($this->containString($this->_agent, 'Opera') || $this->containString($this->_agent, array('BlackBerry', 'Nokia'), true, false)) { return false; } //Test for Internet Explorer 1 if ($this->checkSimpleBrowserUA('Microsoft Internet Explorer', $this->_agent, self::BROWSER_IE)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { if (preg_match('/308|425|426|474|0b1/i', $this->_agent)) { $this->setVersion('1.5'); } else { $this->setVersion('1.0'); } } return true; } //Test for Internet Explorer 2+ if ($this->containString($this->_agent, array('MSIE', 'Trident'))) { $version = ''; if ($this->containString($this->_agent, 'Trident')) { //Test for Internet Explorer 11+ (check the rv: string) if ($this->containString($this->_agent, 'rv:', true, false)) { if ($this->checkSimpleBrowserUA('Trident', $this->_agent, self::BROWSER_IE, false, 'rv:')) { return true; } } else { //Test for Internet Explorer 8, 9 & 10 (check the Trident string) if (preg_match('/Trident\/([\d]+)/i', $this->_agent, $foundVersion)) { //Trident started with version 4.0 on IE 8 $verFromTrident = $this->parseInt($foundVersion[1]) + 4; if ($verFromTrident >= 8) { $version = $verFromTrident . '.0'; } } } //If we have the IE version from Trident, we can check for the compatibility view mode if ($version != '') { $emulatedVer = ''; preg_match_all('/MSIE\s*([^\s;$]+)/i', $this->_agent, $foundVersions); foreach ($foundVersions[1] as $currVer) { //Keep the lowest MSIE version for the emulated version (in compatibility view mode) if ($emulatedVer == '' || $this->compareVersions($emulatedVer, $currVer) == 1) { $emulatedVer = $currVer; } } //Set the compatibility view mode if $version != $emulatedVer if ($this->compareVersions($version, $emulatedVer) != 0) { $this->_compatibilityViewName = self::BROWSER_IE; $this->_compatibilityViewVer = $this->cleanVersion($emulatedVer); } } } //Test for Internet Explorer 2-7 versions if needed if ($version == '') { preg_match_all('/MSIE\s+([^\s;$]+)/i', $this->_agent, $foundVersions); foreach ($foundVersions[1] as $currVer) { //Keep the highest MSIE version if ($version == '' || $this->compareVersions($version, $currVer) == -1) { $version = $currVer; } } } $this->setBrowser(self::BROWSER_IE); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); return true; } return false; } /** * Determine if the browser is Konqueror or not. * @access protected * @link https://www.konqueror.org/ * @return boolean Returns true if the browser is Konqueror, false otherwise. */ protected function checkBrowserKonqueror() { return $this->checkSimpleBrowserUA('Konqueror', $this->_agent, self::BROWSER_KONQUEROR); } /** * Determine if the browser is Lynx or not. It is the oldest web browser currently in general use and development. * It is a text-based only Web browser. * @access protected * @link https://en.wikipedia.org/wiki/Lynx_(web_browser) * @return boolean Returns true if the browser is Lynx, false otherwise. */ protected function checkBrowserLynx() { return $this->checkSimpleBrowserUA('Lynx', $this->_agent, self::BROWSER_LYNX); } /** * Determine if the browser is Mozilla or not. * @access protected * @return boolean Returns true if the browser is Mozilla, false otherwise. */ protected function checkBrowserMozilla() { return $this->checkSimpleBrowserUA('Mozilla', $this->_agent, self::BROWSER_MOZILLA, false, 'rv:'); } /** * Determine if the browser is MSN TV (formerly WebTV) or not. * @access protected * @link https://en.wikipedia.org/wiki/MSN_TV * @return boolean Returns true if the browser is WebTv, false otherwise. */ protected function checkBrowserMsnTv() { return $this->checkSimpleBrowserUA('webtv', $this->_agent, self::BROWSER_MSNTV); } /** * Determine if the browser is Netscape or not. Official support for this browser ended on March 1st, 2008. * @access protected * @link https://en.wikipedia.org/wiki/Netscape * @return boolean Returns true if the browser is Netscape, false otherwise. */ protected function checkBrowserNetscape() { //BlackBerry & Nokia UAs can conflict with Netscape UAs if ($this->containString($this->_agent, array('BlackBerry', 'Nokia'), true, false)) { return false; } //Netscape v6 to v9 check if ($this->checkSimpleBrowserUA(array('Netscape', 'Navigator', 'Netscape6'), $this->_agent, self::BROWSER_NETSCAPE)) { return true; } //Netscape v1-4 (v5 don't exists) $found = false; if ($this->containString($this->_agent, 'Mozilla') && !$this->containString($this->_agent, 'rv:', true, false)) { $version = ''; $verParts = explode('/', stristr($this->_agent, 'Mozilla')); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $verParts = explode('.', $verParts[0]); $majorVer = $this->parseInt($verParts[0]); if ($majorVer > 0 && $majorVer < 5) { $version = implode('.', $verParts); $found = true; if (strtolower(substr($version, -4)) == '-sgi') { $version = substr($version, 0, -4); } else { if (strtolower(substr($version, -4)) == 'gold') { $version = substr($version, 0, -4) . ' Gold'; //Doubles spaces (if any) will be normalized by setVersion() } } } } } if ($found) { $this->setBrowser(self::BROWSER_NETSCAPE); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); } return $found; } /** * Determine if the browser is a Nokia browser or not. * @access protected * @link https://web.archive.org/web/20141012034159/http://www.developer.nokia.com/Community/Wiki/User-Agent_headers_for_Nokia_devices * @return boolean Returns true if the browser is a Nokia browser, false otherwise. */ protected function checkBrowserNokia() { if ($this->containString($this->_agent, array('Nokia5800', 'Nokia5530', 'Nokia5230'), true, false)) { $this->setBrowser(self::BROWSER_NOKIA); $this->setVersion('7.0'); $this->setMobile(true); $this->setRobot(false); return true; } if ($this->checkSimpleBrowserUA(array('NokiaBrowser', 'BrowserNG', 'Series60', 'S60', 'S40OviBrowser'), $this->_agent, self::BROWSER_NOKIA, true)) { return true; } return false; } /** * Determine if the browser is Opera or not. * @access protected * @link https://www.opera.com/ * @link https://www.opera.com/mobile/ * @link https://web.archive.org/web/20140220123653/http://my.opera.com/community/openweb/idopera/ * @return boolean Returns true if the browser is Opera, false otherwise. */ protected function checkBrowserOpera() { if ($this->checkBrowserUAWithVersion('Opera Mobi', $this->_agent, self::BROWSER_OPERA_MOBILE, true)) { return true; } if ($this->checkSimpleBrowserUA('Opera Mini', $this->_agent, self::BROWSER_OPERA_MINI, true)) { return true; } $version = ''; $found = $this->checkBrowserUAWithVersion('Opera', $this->_agent, self::BROWSER_OPERA); if ($found && $this->getVersion() != self::VERSION_UNKNOWN) { $version = $this->getVersion(); } if (!$found || $version == '') { if ($this->checkSimpleBrowserUA('Opera', $this->_agent, self::BROWSER_OPERA)) { return true; } } if (!$found && $this->checkSimpleBrowserUA('Chrome', $this->_agent, self::BROWSER_CHROME) ) { if ($this->checkSimpleBrowserUA('OPR', $this->_agent, self::BROWSER_OPERA)) { return true; } } return $found; } /** * Determine if the browser is Phoenix or not. Phoenix was the name of Firefox from version 0.1 to 0.5. * @access protected * @return boolean Returns true if the browser is Phoenix, false otherwise. */ protected function checkBrowserPhoenix() { return $this->checkSimpleBrowserUA('Phoenix', $this->_agent, self::BROWSER_PHOENIX); } /** * Determine what is the browser used by the user. * @access protected * @return boolean Returns true if the browser has been identified, false otherwise. */ protected function checkBrowser() { //Changing the check order can break the class detection results! return /* Major browsers and browsers that need to be detected in a special order */ $this->checkBrowserCustom() || /* Customs rules are always checked first */ $this->checkBrowserMsnTv() || /* MSN TV is based on IE so we must check for MSN TV before IE */ $this->checkBrowserInternetExplorer() || $this->checkBrowserOpera() || /* Opera must be checked before Firefox, Netscape and Chrome to avoid conflicts */ $this->checkBrowserEdge() || /* Edge must be checked before Firefox, Safari and Chrome to avoid conflicts */ $this->checkBrowserSamsung() || /* Samsung Internet browser must be checked before Chrome and Safari to avoid conflicts */ $this->checkBrowserUC() || /* UC Browser must be checked before Chrome and Safari to avoid conflicts */ $this->checkBrowserChrome() || /* Chrome must be checked before Netscaoe and Mozilla to avoid conflicts */ $this->checkBrowserIcab() || /* Check iCab before Netscape since iCab have Mozilla UAs */ $this->checkBrowserNetscape() || /* Must be checked before Firefox since Netscape 8-9 are based on Firefox */ $this->checkBrowserIceCat() || /* Check IceCat and IceWeasel before Firefox since they are GNU builds of Firefox */ $this->checkBrowserIceWeasel() || $this->checkBrowserFirefox() || /* Current browsers that don't need to be detected in any special order */ $this->checkBrowserKonqueror() || $this->checkBrowserLynx() || /* Mobile */ $this->checkBrowserAndroid() || $this->checkBrowserBlackBerry() || $this->checkBrowserNokia() || /* WebKit base check (after most other checks) */ $this->checkBrowserSafari() || /* Deprecated browsers that don't need to be detected in any special order */ $this->checkBrowserFirebird() || $this->checkBrowserPhoenix() || /* Mozilla is such an open standard that it must be checked last */ $this->checkBrowserMozilla(); } /** * Determine if the browser is Safari or not. * @access protected * @link https://www.apple.com/safari/ * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history * @return boolean Returns true if the browser is Safari, false otherwise. */ protected function checkBrowserSafari() { $version = ''; //Check for current versions of Safari $found = $this->checkBrowserUAWithVersion(array('Safari', 'AppleWebKit'), $this->_agent, self::BROWSER_SAFARI); if ($found && $this->getVersion() != self::VERSION_UNKNOWN) { $version = $this->getVersion(); } //Safari 1-2 didn't had a "Version" string in the UA, only a WebKit build and/or Safari build, extract version from these... if (!$found || $version == '') { if (preg_match('/.*Safari[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches)) { $version = $this->safariBuildToSafariVer($matches[1]); $found = true; } } if (!$found || $version == '') { if (preg_match('/.*AppleWebKit[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches)) { $version = $this->webKitBuildToSafariVer($matches[1]); $found = true; } } if ($found) { $this->setBrowser(self::BROWSER_SAFARI); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); } return $found; } /** * Determine if the browser is the Samsung Internet browser or not. * @access protected * @return boolean Returns true if the browser is the the Samsung Internet browser, false otherwise. */ protected function checkBrowserSamsung() { return $this->checkSimpleBrowserUA('SamsungBrowser', $this->_agent, self::BROWSER_SAMSUNG, true); } /** * Test the user agent for a specific browser that use a "Version" string (like Safari and Opera). The user agent * should look like: "Version/1.0 Browser name/123.456" or "Browser name/123.456 Version/1.0". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $browserName The literal browser name. Always use a class constant! * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param boolean $findWords (optional) Determines if the needle should match a word to be found. For example "Bar" * would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be * found anywhere in the haystack. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function checkBrowserUAWithVersion($uaNameToLookFor, $userAgent, $browserName, $isMobile = false, $findWords = true) { if (!is_array($uaNameToLookFor)) { $uaNameToLookFor = array($uaNameToLookFor); } foreach ($uaNameToLookFor as $currUANameToLookFor) { if ($this->containString($userAgent, $currUANameToLookFor, true, $findWords)) { $version = ''; $verParts = explode('/', stristr($this->_agent, 'Version')); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $version = $verParts[0]; } $this->setBrowser($browserName); $this->setVersion($version); $this->setMobile($isMobile); return true; } } return false; } /** * Determine if the browser is UC Browser or not. * @access protected * @return boolean Returns true if the browser is UC Browser, false otherwise. */ protected function checkBrowserUC() { return $this->checkSimpleBrowserUA('UCBrowser', $this->_agent, self::BROWSER_UC, true); } /** * Determine the user's platform. * @access protected */ protected function checkPlatform() { if (!$this->checkPlatformCustom()) { /* Customs rules are always checked first */ /* Mobile platforms */ if ($this->containString($this->_agent, array('Windows Phone', 'IEMobile'))) { /* Check Windows Phone (formerly Windows Mobile) before Windows */ $this->setPlatform(self::PLATFORM_WINDOWS_PHONE); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Windows CE')) { /* Check Windows CE before Windows */ $this->setPlatform(self::PLATFORM_WINDOWS_CE); $this->setMobile(true); } else if ($this->containString($this->_agent, array('CPU OS', 'CPU iPhone OS', 'iPhone', 'iPad', 'iPod'))) { /* Check iOS (iPad/iPod/iPhone) before Macintosh */ $this->setPlatform(self::PLATFORM_IOS); $this->setMobile(true); } else if ($this->containString($this->_agent, array('CrOS', 'Chromebook'))) { $this->setPlatform(self::PLATFORM_CHROME_OS); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Android')) { $this->setPlatform(self::PLATFORM_ANDROID); $this->setMobile(true); } else if ($this->containString($this->_agent, 'BlackBerry', true, false) || $this->containString($this->_agent, array('BB10', 'RIM Tablet OS'))) { $this->setPlatform(self::PLATFORM_BLACKBERRY); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Nokia', true, false)) { $this->setPlatform(self::PLATFORM_NOKIA); $this->setMobile(true); /* Desktop platforms */ } else if ($this->containString($this->_agent, 'Windows')) { $this->setPlatform(self::PLATFORM_WINDOWS); } else if ($this->containString($this->_agent, 'Macintosh')) { $this->setPlatform(self::PLATFORM_MACINTOSH); } else if ($this->containString($this->_agent, 'Linux')) { $this->setPlatform(self::PLATFORM_LINUX); } else if ($this->containString($this->_agent, 'FreeBSD')) { $this->setPlatform(self::PLATFORM_FREEBSD); } else if ($this->containString($this->_agent, 'OpenBSD')) { $this->setPlatform(self::PLATFORM_OPENBSD); } else if ($this->containString($this->_agent, 'NetBSD')) { $this->setPlatform(self::PLATFORM_NETBSD); /* Discontinued */ } else if ($this->containString($this->_agent, array('Symbian', 'SymbianOS'))) { $this->setPlatform(self::PLATFORM_SYMBIAN); $this->setMobile(true); } else if ($this->containString($this->_agent, 'OpenSolaris')) { $this->setPlatform(self::PLATFORM_OPENSOLARIS); /* Generic */ } else if ($this->containString($this->_agent, 'Win', true, false)) { $this->setPlatform(self::PLATFORM_WINDOWS); } else if ($this->containString($this->_agent, 'Mac', true, false)) { $this->setPlatform(self::PLATFORM_MACINTOSH); } } //Check if it's a 64-bit platform if ($this->containString($this->_agent, array('WOW64', 'Win64', 'AMD64', 'x86_64', 'x86-64', 'Aarch64', 'ia64', 'IRIX64', 'ppc64', 'sparc64', 'x64;', 'x64_64'))) { $this->set64bit(true); } $this->checkPlatformVersion(); } /** * Determine if the platform is among the custom platform rules or not. Rules are checked in the order they were * added. * @access protected * @return boolean Returns true if we found the platform we were looking for in the custom rules, false otherwise. */ protected function checkPlatformCustom() { foreach ($this->_customPlatformDetection as $platformName => $customPlatform) { $platformNameToLookFor = $customPlatform['platformNameToLookFor']; $isMobile = $customPlatform['isMobile']; $findWords = $customPlatform['uaNameFindWords']; if ($this->containString($this->_agent, $platformNameToLookFor, true, $findWords)) { $this->setPlatform($platformName); if ($isMobile) { $this->setMobile(true); } return true; } } return false; } /** * Determine the user's platform version. * @access protected */ protected function checkPlatformVersion() { $result = ''; switch ($this->getPlatform()) { case self::PLATFORM_WINDOWS: if (preg_match('/Windows NT\s*(\d+(?:\.\d+)*)/i', $this->_agent, $foundVersion)) { $result = 'NT ' . $foundVersion[1]; } else { //https://support.microsoft.com/en-us/kb/158238 if ($this->containString($this->_agent, array('Windows XP', 'WinXP', 'Win XP'))) { $result = '5.1'; } else if ($this->containString($this->_agent, 'Windows 2000', 'Win 2000', 'Win2000')) { $result = '5.0'; } else if ($this->containString($this->_agent, array('Win 9x 4.90', 'Windows ME', 'WinME', 'Win ME'))) { $result = '4.90.3000'; //Windows Me version range from 4.90.3000 to 4.90.3000A } else if ($this->containString($this->_agent, array('Windows 98', 'Win98', 'Win 98'))) { $result = '4.10'; //Windows 98 version range from 4.10.1998 to 4.10.2222B } else if ($this->containString($this->_agent, array('Windows 95', 'Win95', 'Win 95'))) { $result = '4.00'; //Windows 95 version range from 4.00.950 to 4.03.1214 } else if (($foundAt = stripos($this->_agent, 'Windows 3')) !== false) { $result = '3'; if (preg_match('/\d+(?:\.\d+)*/', substr($this->_agent, $foundAt + strlen('Windows 3')), $foundVersion)) { $result .= '.' . $foundVersion[0]; } } else if ($this->containString($this->_agent, 'Win16')) { $result = '3.1'; } } break; case self::PLATFORM_MACINTOSH: if (preg_match('/Mac OS X\s*(\d+(?:_\d+)+)/i', $this->_agent, $foundVersion)) { $result = str_replace('_', '.', $this->cleanVersion($foundVersion[1])); } else if ($this->containString($this->_agent, 'Mac OS X')) { $result = '10'; } break; case self::PLATFORM_CHROME_OS: if (preg_match('/CrOS\s*\w*\s*([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1]); } else if (preg_match('/Chromebook\s+([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1], 'Build'); } break; case self::PLATFORM_ANDROID: if (preg_match('/Android\s+([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1]); } break; case self::PLATFORM_IOS: if (preg_match('/(?:CPU OS|iPhone OS|iOS)[\s_]*([\d_]+)/i', $this->_agent, $foundVersion)) { $result = str_replace('_', '.', $this->cleanVersion($foundVersion[1])); } break; } if (trim($result) == '') { $result = self::PLATFORM_VERSION_UNKNOWN; } $this->setPlatformVersion($result); } /** * Determine if the robot is the Bingbot crawler or not. * @access protected * @link https://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0 * @return boolean Returns true if the robot is Bingbot, false otherwise. */ protected function checkRobotBingbot() { return $this->checkSimpleRobot('bingbot', $this->_agent, self::ROBOT_BINGBOT); } /** * Determine if the robot is the Googlebot crawler or not. * @access protected * @return boolean Returns true if the robot is Googlebot, false otherwise. */ protected function checkRobotGooglebot() { if ($this->checkSimpleRobot('Googlebot', $this->_agent, self::ROBOT_GOOGLEBOT)) { if ($this->containString($this->_agent, 'googlebot-mobile')) { $this->setMobile(true); } return true; } return false; } /** * Determine if the robot is the MSNBot crawler or not. In October 2010 it was replaced by the Bingbot robot. * @access protected * @see checkRobotBingbot() * @return boolean Returns true if the robot is MSNBot, false otherwise. */ protected function checkRobotMsnBot() { return $this->checkSimpleRobot('msnbot', $this->_agent, self::ROBOT_MSNBOT); } /** * Determine if it's a robot crawling the page and find it's name and version. * @access protected */ protected function checkRobot() { $this->checkRobotCustom() || /* Customs rules are always checked first */ $this->checkRobotGooglebot() || $this->checkRobotBingbot() || $this->checkRobotMsnBot() || $this->checkRobotSlurp() || $this->checkRobotYahooMultimedia() || $this->checkRobotW3CValidator(); } /** * Determine if the robot is among the custom robot rules or not. Rules are checked in the order they were added. * @access protected * @return boolean Returns true if we found the robot we were looking for in the custom rules, false otherwise. */ protected function checkRobotCustom() { foreach ($this->_customRobotDetection as $robotName => $customRobot) { $uaNameToLookFor = $customRobot['uaNameToLookFor']; $isMobile = $customRobot['isMobile']; $separator = $customRobot['separator']; $uaNameFindWords = $customRobot['uaNameFindWords']; if ($this->checkSimpleRobot($uaNameToLookFor, $this->_agent, $robotName, $separator, $uaNameFindWords)) { return true; } } return false; } /** * Determine if the robot is the Yahoo! Slurp crawler or not. * @access protected * @return boolean Returns true if the robot is Yahoo! Slurp, false otherwise. */ protected function checkRobotSlurp() { return $this->checkSimpleRobot('Yahoo! Slurp', $this->_agent, self::ROBOT_SLURP); } /** * Determine if the robot is the W3C Validator or not. * @access protected * @link https://validator.w3.org/ * @return boolean Returns true if the robot is the W3C Validator, false otherwise. */ protected function checkRobotW3CValidator() { //Since the W3C validates pages with different robots we will prefix our versions with the part validated on the page... //W3C Link Checker (prefixed with "Link-") if ($this->checkSimpleRobot('W3C-checklink', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('Link-' . $this->getRobotVersion()); } return true; } //W3C CSS Validation Service (prefixed with "CSS-") if ($this->checkSimpleRobot('Jigsaw', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('CSS-' . $this->getRobotVersion()); } return true; } //W3C mobileOK Checker (prefixed with "mobileOK-") if ($this->checkSimpleRobot('W3C-mobileOK', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('mobileOK-' . $this->getRobotVersion()); } return true; } //W3C Markup Validation Service (no prefix) return $this->checkSimpleRobot('W3C_Validator', $this->_agent, self::ROBOT_W3CVALIDATOR); } /** * Determine if the robot is the Yahoo! multimedia crawler or not. * @access protected * @return boolean Returns true if the robot is the Yahoo! multimedia crawler, false otherwise. */ protected function checkRobotYahooMultimedia() { return $this->checkSimpleRobot('Yahoo-MMCrawler', $this->_agent, self::ROBOT_YAHOO_MM); } /** * Test the user agent for a specific browser where the browser name is immediately followed by the version number. * The user agent should look like: "Browser name/1.0" or "Browser 1.0;". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $browserName The literal browser name. Always use a class constant! * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param string $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function checkSimpleBrowserUA($uaNameToLookFor, $userAgent, $browserName, $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($this->findAndGetVersion($uaNameToLookFor, $userAgent, $version, $separator, $uaNameFindWords)) { $this->setBrowser($browserName); $this->setVersion($version); $this->setMobile($isMobile); return true; } return false; } /** * Test the user agent for a specific robot where the robot name is immediately followed by the version number. * The user agent should look like: "Robot name/1.0" or "Robot 1.0;". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the robot name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $robotName The literal robot name. Always use a class constant! * @param string $separator (optional) The separator string used to split the robot name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the robot name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the robot name can be found anywhere in the user agent string. * @return boolean Returns true if we found the robot we were looking for, false otherwise. */ protected function checkSimpleRobot($uaNameToLookFor, $userAgent, $robotName, $separator = '/', $uaNameFindWords = true) { if ($this->findAndGetVersion($uaNameToLookFor, $userAgent, $version, $separator, $uaNameFindWords)) { $this->setRobot(true); $this->setRobotName($robotName); $this->setRobotVersion($version); return true; } return false; } /** * Clean a version string from unwanted characters. * @access protected * @param string $version The version string to clean. * @param mixed $toRemove (optional) String or array of strings representing additional string(s) to remove. * @return string Returns the cleaned version number string. */ protected function cleanVersion($version, $toRemove = NULL) { $cleanVer = $version; if ($toRemove !== NULL) { $cleanVer = str_ireplace($toRemove, '', $cleanVer); } //Clear anything that is in parentheses (and the parentheses themselves) - will clear started but unclosed ones too $cleanVer = preg_replace('/\([^)]+\)?/', '', $cleanVer); //Replace with a space any character which is NOT an alphanumeric, dot (.), hyphen (-), underscore (_) or space $cleanVer = preg_replace('/[^0-9.a-zA-Z_ -]/', ' ', $cleanVer); //Remove trailing and leading spaces $cleanVer = trim($cleanVer); //Remove trailing dot (.), hyphen (-), underscore (_) while (in_array(substr($cleanVer, -1), array('.', '-', '_'))) { $cleanVer = substr($cleanVer, 0, -1); } //Remove leading dot (.), hyphen (-), underscore (_) and character v while (in_array(substr($cleanVer, 0, 1), array('.', '-', '_', 'v', 'V'))) { $cleanVer = substr($cleanVer, 1); } //Remove double spaces if any while (strpos($cleanVer, ' ') !== false) { $cleanVer = str_replace(' ', ' ', $cleanVer); } return trim($cleanVer); } /** * Find if one or more substring is contained in a string. * @access protected * @param string $haystack The string to search in. * @param mixed $needle The string to search for. Can be a string or an array of strings if multiples values are to * be searched. * @param boolean $insensitive (optional) Determines if we do a case-sensitive search (false) or a case-insensitive * one (true). * @param boolean $findWords (optional) Determines if the needle should match a word to be found. For example "Bar" * would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be * found anywhere in the haystack. * @param int $foundPos (optional) Integer buffer that will contain the position of the needle (if found and if a * non NULL variable has been passed). * @return boolean Returns true if the needle (or one of the needles) has been found in the haystack, false * otherwise. */ protected function containString($haystack, $needle, $insensitive = true, $findWords = true, &$foundPos = NULL) { if (!is_array($needle)) { $needle = array($needle); } foreach ($needle as $currNeedle) { if ($findWords) { $position = $this->wordPos($haystack, $currNeedle, $insensitive); } else { if ($insensitive) { $position = stripos($haystack, $currNeedle); } else { $position = strpos($haystack, $currNeedle); } } if ($position !== false) { if ($foundPos !== NULL) { $foundPos = $position; } return true; } } return false; } /** * Detect the user environment from the details in the user agent string. * @access protected */ protected function detect() { $this->checkBrowser(); $this->checkPlatform(); //Check the platform after the browser since some platforms can change the mobile value $this->checkRobot(); } /** * Test the user agent for a specific browser and extract it's version. * @access protected * @param type $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param type $userAgent The user agent string to work with. * @param type $version String buffer that will contain the version found (if any). * @param type $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param type $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function findAndGetVersion($uaNameToLookFor, $userAgent, &$version, $separator = '/', $uaNameFindWords = true) { $version = ''; if (!is_array($uaNameToLookFor)) { $uaNameToLookFor = array($uaNameToLookFor); } foreach ($uaNameToLookFor as $currUANameToLookFor) { $foundPos = -1; if ($this->containString($userAgent, $currUANameToLookFor, true, $uaNameFindWords, $foundPos)) { //Many browsers don't use the standard "Browser/1.0" format, they uses "Browser 1.0;" instead if (stripos($userAgent, $currUANameToLookFor . $separator) === false) { $userAgent = str_ireplace($currUANameToLookFor . ' ', $currUANameToLookFor . $separator, $userAgent); } $verParts = explode($separator, substr($userAgent, $foundPos)); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $version = $verParts[0]; } return true; } } return false; } /** * Convert the iOS version numbers to the operating system name. For instance '2.0' returns 'iPhone OS 2.0'. * @access protected * @param string $iOSVer The iOS version numbers as a string. * @return string The operating system name. */ protected function iOSVerToStr($iOSVer) { if ($this->compareVersions($iOSVer, '3.0') <= 0) { return 'iPhone OS ' . $iOSVer; } else { return 'iOS ' . $iOSVer; } } /** * Convert the macOS version numbers to the operating system name. For instance '10.7' returns 'Mac OS X Lion'. * * Firefox, Safari and Chromium development teams have discovered a long tail of websites broken when reporting * "Mac OS X 11" in the user agent string. In order to slightly improve user privacy as well as Web compatibility, * they all capped the reported macOS version to 10.15 (Catalina) in the user agent string. * * Firefox reported macOS version is capped at 10.15 since Firefox 87 (March 23, 2021). This change has been also * backported in Firefox 78.9.0esr (March 23, 2021). * * Safari reported macOS version is capped at 10.15.7 since Safari 14.1 (April 26, 2021). * * Chromium reported macOS version is capped at 10.15.7 since Chromium 91.0.4437.0 (May 25, 2021). * * See below links for more details. * @access protected * @param string $macVer The macOS version numbers as a string. * @link https://bugzilla.mozilla.org/show_bug.cgi?id=1679929 * @link https://github.com/WebKit/WebKit/commit/94d3ce0900c31c929798e91ea86dcfe604251a9e * @link https://github.com/WebKit/WebKit/commit/a46b2c6dd07fab463f1b2353c5d5b2ff43000f58 * @link https://chromiumdash.appspot.com/commit/a632542e79f2589e1b3f470827c7d03092be0afb * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function macVerToStr($macVer) { //https://en.wikipedia.org/wiki/OS_X#Release_history if ($this->_platformVersion === '10') { return 'Mac OS X'; //Unspecified Mac OS X version } else if ($this->compareVersions($macVer, '15.0') >= 0 && $this->compareVersions($macVer, '16.0') < 0) { return 'macOS Sequoia'; } else if ($this->compareVersions($macVer, '14.0') >= 0 && $this->compareVersions($macVer, '15.0') < 0) { return 'macOS Sonoma'; } else if ($this->compareVersions($macVer, '13.0') >= 0 && $this->compareVersions($macVer, '14.0') < 0) { return 'macOS Ventura'; } else if ($this->compareVersions($macVer, '12.0') >= 0 && $this->compareVersions($macVer, '13.0') < 0) { return 'macOS Monterey'; } else if ($this->compareVersions($macVer, '11.0') >= 0 && $this->compareVersions($macVer, '12.0') < 0) { return 'macOS Big Sur'; } else if ($this->compareVersions($macVer, '10.15') >= 0 && $this->compareVersions($macVer, '10.16') < 0) { return 'macOS Catalina'; } else if ($this->compareVersions($macVer, '10.14') >= 0 && $this->compareVersions($macVer, '10.15') < 0) { return 'macOS Mojave'; } else if ($this->compareVersions($macVer, '10.13') >= 0 && $this->compareVersions($macVer, '10.14') < 0) { return 'macOS High Sierra'; } else if ($this->compareVersions($macVer, '10.12') >= 0 && $this->compareVersions($macVer, '10.13') < 0) { return 'macOS Sierra'; } else if ($this->compareVersions($macVer, '10.11') >= 0 && $this->compareVersions($macVer, '10.12') < 0) { return 'OS X El Capitan'; } else if ($this->compareVersions($macVer, '10.10') >= 0 && $this->compareVersions($macVer, '10.11') < 0) { return 'OS X Yosemite'; } else if ($this->compareVersions($macVer, '10.9') >= 0 && $this->compareVersions($macVer, '10.10') < 0) { return 'OS X Mavericks'; } else if ($this->compareVersions($macVer, '10.8') >= 0 && $this->compareVersions($macVer, '10.9') < 0) { return 'OS X Mountain Lion'; } else if ($this->compareVersions($macVer, '10.7') >= 0 && $this->compareVersions($macVer, '10.8') < 0) { return 'Mac OS X Lion'; } else if ($this->compareVersions($macVer, '10.6') >= 0 && $this->compareVersions($macVer, '10.7') < 0) { return 'Mac OS X Snow Leopard'; } else if ($this->compareVersions($macVer, '10.5') >= 0 && $this->compareVersions($macVer, '10.6') < 0) { return 'Mac OS X Leopard'; } else if ($this->compareVersions($macVer, '10.4') >= 0 && $this->compareVersions($macVer, '10.5') < 0) { return 'Mac OS X Tiger'; } else if ($this->compareVersions($macVer, '10.3') >= 0 && $this->compareVersions($macVer, '10.4') < 0) { return 'Mac OS X Panther'; } else if ($this->compareVersions($macVer, '10.2') >= 0 && $this->compareVersions($macVer, '10.3') < 0) { return 'Mac OS X Jaguar'; } else if ($this->compareVersions($macVer, '10.1') >= 0 && $this->compareVersions($macVer, '10.2') < 0) { return 'Mac OS X Puma'; } else if ($this->compareVersions($macVer, '10.0') >= 0 && $this->compareVersions($macVer, '10.1') < 0) { return 'Mac OS X Cheetah'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Unknown/unnamed Mac OS version } } /** * Get the integer value of a string variable. * @access protected * @param string $intStr The scalar value being converted to an integer. * @return int The integer value of $intStr on success, or 0 on failure. */ protected function parseInt($intStr) { return intval($intStr, 10); } /** * Reset all the properties of the class. * @access protected */ protected function reset() { $this->_agent = ''; $this->_browserName = self::BROWSER_UNKNOWN; $this->_compatibilityViewName = ''; $this->_compatibilityViewVer = ''; $this->_is64bit = false; $this->_isMobile = false; $this->_isRobot = false; $this->_platform = self::PLATFORM_UNKNOWN; $this->_platformVersion = self::PLATFORM_VERSION_UNKNOWN; $this->_robotName = self::ROBOT_UNKNOWN; $this->_robotVersion = self::ROBOT_VERSION_UNKNOWN; $this->_version = self::VERSION_UNKNOWN; } /** * Convert a Safari build number to a Safari version number. * @access protected * @param string $version A string representing the version number. * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @return string Returns the Safari version string. If the version can't be determined, an empty string is * returned. */ protected function safariBuildToSafariVer($version) { $verParts = explode('.', $version); //We need a 3 parts version (version 2 will becomes 2.0.0) while (count($verParts) < 3) { $verParts[] = 0; } foreach ($verParts as $i => $currPart) { $verParts[$i] = $this->parseInt($currPart); } switch ($verParts[0]) { case 419: $result = '2.0.4'; break; case 417: $result = '2.0.3'; break; case 416: $result = '2.0.2'; break; case 412: if ($verParts[1] >= 5) { $result = '2.0.1'; } else { $result = '2.0'; } break; case 312: if ($verParts[1] >= 5) { $result = '1.3.2'; } else { if ($verParts[1] >= 3) { $result = '1.3.1'; } else { $result = '1.3'; } } break; case 125: if ($verParts[1] >= 11) { $result = '1.2.4'; } else { if ($verParts[1] >= 9) { $result = '1.2.3'; } else { if ($verParts[1] >= 7) { $result = '1.2.2'; } else { $result = '1.2'; } } } break; case 100: if ($verParts[1] >= 1) { $result = '1.1.1'; } else { $result = '1.1'; } break; case 85: if ($verParts[1] >= 8) { $result = '1.0.3'; } else { if ($verParts[1] >= 7) { $result = '1.0.2'; } else { $result = '1.0'; } } break; case 73: $result = '0.9'; break; case 51: $result = '0.8.1'; break; case 48: $result = '0.8'; break; default: $result = ''; } return $result; } /** * Set if the browser is executed from a 64-bit platform. * @access protected * @param boolean $is64bit Value that tells if the browser is executed from a 64-bit platform. */ protected function set64bit($is64bit) { $this->_is64bit = $is64bit == true; } /** * Set the name of the browser. * @access protected * @param string $browserName The name of the browser. */ protected function setBrowser($browserName) { $this->_browserName = $browserName; } /** * Set the browser to be from a mobile device or not. * @access protected * @param boolean $isMobile (optional) Value that tells if the browser is on a mobile device or not. */ protected function setMobile($isMobile = true) { $this->_isMobile = $isMobile == true; } /** * Set the platform on which the browser is on. * @access protected * @param string $platform The name of the platform. */ protected function setPlatform($platform) { $this->_platform = $platform; } /** * Set the platform version on which the browser is on. * @access protected * @param string $platformVer The version numbers of the platform. */ protected function setPlatformVersion($platformVer) { $this->_platformVersion = $platformVer; } /** * Set the browser to be a robot (crawler) or not. * @access protected * @param boolean $isRobot (optional) Value that tells if the browser is a robot or not. */ protected function setRobot($isRobot = true) { $this->_isRobot = $isRobot == true; } /** * Set the name of the robot. * @access protected * @param string $robotName The name of the robot. */ protected function setRobotName($robotName) { $this->_robotName = $robotName; } /** * Set the version of the robot. * @access protected * @param string $robotVersion The version of the robot. */ protected function setRobotVersion($robotVersion) { $cleanVer = $this->cleanVersion($robotVersion); if ($cleanVer == '') { $this->_robotVersion = self::ROBOT_VERSION_UNKNOWN; } else { $this->_robotVersion = $cleanVer; } } /** * Set the version of the browser. * @access protected * @param string $version The version of the browser. */ protected function setVersion($version) { $cleanVer = $this->cleanVersion($version); if ($cleanVer == '') { $this->_version = self::VERSION_UNKNOWN; } else { $this->_version = $cleanVer; } } /** * Convert a WebKit build number to a Safari version number. * @access protected * @param string $version A string representing the version number. * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @return string Returns the Safari version string. If the version can't be determined, an empty string is * returned. */ protected function webKitBuildToSafariVer($version) { $verParts = explode('.', $version); //We need a 3 parts version (version 2 will becomes 2.0.0) while (count($verParts) < 3) { $verParts[] = 0; } foreach ($verParts as $i => $currPart) { $verParts[$i] = $this->parseInt($currPart); } switch ($verParts[0]) { case 419: $result = '2.0.4'; break; case 418: if ($verParts[1] >= 8) { $result = '2.0.4'; } else { $result = '2.0.3'; } break; case 417: $result = '2.0.3'; break; case 416: $result = '2.0.2'; break; case 412: if ($verParts[1] >= 7) { $result = '2.0.1'; } else { $result = '2.0'; } break; case 312: if ($verParts[1] >= 8) { $result = '1.3.2'; } else { if ($verParts[1] >= 5) { $result = '1.3.1'; } else { $result = '1.3'; } } break; case 125: if ($this->compareVersions('5.4', $verParts[1] . '.' . $verParts[2]) == -1) { $result = '1.2.4'; //125.5.5+ } else { if ($verParts[1] >= 4) { $result = '1.2.3'; } else { if ($verParts[1] >= 2) { $result = '1.2.2'; } else { $result = '1.2'; } } } break; //WebKit 100 can be either Safari 1.1 (Safari build 100) or 1.1.1 (Safari build 100.1) //for this reason, check the Safari build before the WebKit build. case 100: $result = '1.1.1'; break; case 85: if ($verParts[1] >= 8) { $result = '1.0.3'; } else { if ($verParts[1] >= 7) { //WebKit 85.7 can be either Safari 1.0 (Safari build 85.5) or 1.0.2 (Safari build 85.7) //for this reason, check the Safari build before the WebKit build. $result = '1.0.2'; } else { $result = '1.0'; } } break; case 73: $result = '0.9'; break; case 51: $result = '0.8.1'; break; case 48: $result = '0.8'; break; default: $result = ''; } return $result; } /** * Convert the Windows NT family version numbers to the operating system name. For instance '5.1' returns * 'Windows XP'. * * Windows 10 and Windows 11 share the same major version number (10). Windows 11 starts with build 22000 (version * 10.0.22000) but the build is not included in the UA. * * Windows Server 2022, 2019 & 2016 have also the same version number (10). Again, only the build can differentiate * these versions. * @access protected * @param string $winVer The Windows NT family version numbers as a string. * @param boolean $returnServerFlavor (optional) Since some Windows NT versions have the same values, this flag * determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use * version 6.3. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function windowsNTVerToStr($winVer, $returnServerFlavor = false) { //https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions $cleanWinVer = explode('.', $winVer); while (count($cleanWinVer) > 2) { array_pop($cleanWinVer); } $cleanWinVer = implode('.', $cleanWinVer); if ($this->compareVersions($cleanWinVer, '11') >= 0) { return self::PLATFORM_WINDOWS . ' ' . $winVer; } else if ($this->compareVersions($cleanWinVer, '10') >= 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2022') : (self::PLATFORM_WINDOWS . ' 10'); } else if ($this->compareVersions($cleanWinVer, '7') < 0) { if ($this->compareVersions($cleanWinVer, '6.3') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2012 R2') : (self::PLATFORM_WINDOWS . ' 8.1'); } else if ($this->compareVersions($cleanWinVer, '6.2') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2012') : (self::PLATFORM_WINDOWS . ' 8'); } else if ($this->compareVersions($cleanWinVer, '6.1') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2008 R2') : (self::PLATFORM_WINDOWS . ' 7'); } else if ($this->compareVersions($cleanWinVer, '6') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2008') : (self::PLATFORM_WINDOWS . ' Vista'); } else if ($this->compareVersions($cleanWinVer, '5.2') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2003 / ' . self::PLATFORM_WINDOWS . ' Server 2003 R2') : (self::PLATFORM_WINDOWS . ' XP x64 Edition'); } else if ($this->compareVersions($cleanWinVer, '5.1') == 0) { return self::PLATFORM_WINDOWS . ' XP'; } else if ($this->compareVersions($cleanWinVer, '5') == 0) { return self::PLATFORM_WINDOWS . ' 2000'; } else if ($this->compareVersions($cleanWinVer, '5') < 0 && $this->compareVersions($cleanWinVer, '3') >= 0) { return self::PLATFORM_WINDOWS . ' NT ' . $winVer; } } return self::PLATFORM_VERSION_UNKNOWN; //Invalid Windows NT version } /** * Convert the Windows 3.x & 9x family version numbers to the operating system name. For instance '4.10.1998' * returns 'Windows 98'. * @access protected * @param string $winVer The Windows 3.x or 9x family version numbers as a string. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function windowsVerToStr($winVer) { //https://support.microsoft.com/en-us/kb/158238 if ($this->compareVersions($winVer, '4.90') >= 0 && $this->compareVersions($winVer, '4.91') < 0) { return self::PLATFORM_WINDOWS . ' Me'; //Normally range from 4.90.3000 to 4.90.3000A } else if ($this->compareVersions($winVer, '4.10') >= 0 && $this->compareVersions($winVer, '4.11') < 0) { return self::PLATFORM_WINDOWS . ' 98'; //Normally range from 4.10.1998 to 4.10.2222B } else if ($this->compareVersions($winVer, '4') >= 0 && $this->compareVersions($winVer, '4.04') < 0) { return self::PLATFORM_WINDOWS . ' 95'; //Normally range from 4.00.950 to 4.03.1214 } else if ($this->compareVersions($winVer, '3.1') == 0 || $this->compareVersions($winVer, '3.11') == 0) { return self::PLATFORM_WINDOWS . ' ' . $winVer; } else if ($this->compareVersions($winVer, '3.10') == 0) { return self::PLATFORM_WINDOWS . ' 3.1'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Invalid Windows version } } /** * Find the position of the first occurrence of a word in a string. * @access protected * @param string $haystack The string to search in. * @param string $needle The string to search for. * @param boolean $insensitive (optional) Determines if we do a case-sensitive search (false) or a case-insensitive * one (true). * @param int $offset If specified, search will start this number of characters counted from the beginning of the * string. If the offset is negative, the search will start this number of characters counted from the end of the * string. * @param string $foundString String buffer that will contain the exact matching needle found. Set to NULL when * return value of the function is false. * @return mixed Returns the position of the needle (int) if found, false otherwise. Warning this function may * return Boolean false, but may also return a non-Boolean value which evaluates to false. */ protected function wordPos($haystack, $needle, $insensitive = true, $offset = 0, &$foundString = NULL) { if ($offset != 0) { $haystack = substr($haystack, $offset); } $parts = explode(' ', $needle); foreach ($parts as $i => $currPart) { $parts[$i] = preg_quote($currPart, '/'); } $regex = '/(?<=\A|[\s\/\\.,;:_()-])' . implode('[\s\/\\.,;:_()-]', $parts) . '(?=[\s\/\\.,;:_()-]|$)/'; if ($insensitive) { $regex .= 'i'; } if (preg_match($regex, $haystack, $matches, PREG_OFFSET_CAPTURE)) { $foundString = $matches[0][0]; return (int)$matches[0][1]; } return false; } } ================================================ FILE: docs/files/browserdetection.html ================================================ Wolfcast BrowserDetection Documentation

    Wolfcast BrowserDetection Documentation

    BrowserDetection.php

    Browser detection class file.

    This file contains everything required to use the BrowserDetection class. Tested with PHP 8.3.6, 7.4.33 and 5.6.40.

    This program is free software; you can redistribute it and/or modify it under the terms of EITHER the MIT License (SPDX short identifier: MIT) OR the GNU Lesser General Public License Version 3 (SPDX short identifier: LGPL-3.0-only). License details can be found in the LICENSE-*.md files of this project or on the below URLs.

    Tags
    version
    2.9.9
    last-modified

    March 23, 2025

    author

    Alexandre Valiquette

    copyright

    Copyright (c) 2025, Wolfcast

    license

    https://spdx.org/licenses/GPL-3.0-only.html

    license

    https://spdx.org/licenses/MIT.html

    link
    https://wolfcast.com/

    Table of Contents

    Classes

    BrowserDetection
    The BrowserDetection class facilitates the identification of the user's environment such as Web browser, version, platform and device type.
    
            
    On this page

    Search results

      ================================================ FILE: docs/graphs/classes.html ================================================ Wolfcast BrowserDetection Documentation

      Wolfcast BrowserDetection Documentation

      Search results

        ================================================ FILE: docs/index.html ================================================ Wolfcast BrowserDetection Documentation

        Wolfcast BrowserDetection Documentation

        Documentation

        Table of Contents

        Packages

        BrowserDetection

        Namespaces

        Wolfcast

        Search results

          ================================================ FILE: docs/indices/files.html ================================================ Wolfcast BrowserDetection Documentation

          Wolfcast BrowserDetection Documentation

          Search results

            ================================================ FILE: docs/js/search.js ================================================ // Search module for phpDocumentor // // This module is a wrapper around fuse.js that will use a given index and attach itself to a // search form and to a search results pane identified by the following data attributes: // // 1. data-search-form // 2. data-search-results // // The data-search-form is expected to have a single input element of type 'search' that will trigger searching for // a series of results, were the data-search-results pane is expected to have a direct UL child that will be populated // with rendered results. // // The search has various stages, upon loading this stage the data-search-form receives the CSS class // 'phpdocumentor-search--enabled'; this indicates that JS is allowed and indices are being loaded. It is recommended // to hide the form by default and show it when it receives this class to achieve progressive enhancement for this // feature. // // After loading this module, it is expected to load a search index asynchronously, for example: // // // // In this script the generated index should attach itself to the search module using the `appendIndex` function. By // doing it like this the page will continue loading, unhindered by the loading of the search. // // After the page has fully loaded, and all these deferred indexes loaded, the initialization of the search module will // be called and the form will receive the class 'phpdocumentor-search--active', indicating search is ready. At this // point, the input field will also have it's 'disabled' attribute removed. var Search = (function () { var fuse; var index = []; var options = { shouldSort: true, threshold: 0.6, location: 0, distance: 100, maxPatternLength: 32, minMatchCharLength: 1, keys: [ "fqsen", "name", "summary", "url" ] }; // Credit David Walsh (https://davidwalsh.name/javascript-debounce-function) // Returns a function, that, as long as it continues to be invoked, will not // be triggered. The function will be called after it stops being called for // N milliseconds. If `immediate` is passed, trigger the function on the // leading edge, instead of the trailing. function debounce(func, wait, immediate) { var timeout; return function executedFunction() { var context = this; var args = arguments; var later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; } function close() { // Start scroll prevention: https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/ const scrollY = document.body.style.top; document.body.style.position = ''; document.body.style.top = ''; window.scrollTo(0, parseInt(scrollY || '0') * -1); // End scroll prevention var form = document.querySelector('[data-search-form]'); var searchResults = document.querySelector('[data-search-results]'); form.classList.toggle('phpdocumentor-search--has-results', false); searchResults.classList.add('phpdocumentor-search-results--hidden'); var searchField = document.querySelector('[data-search-form] input[type="search"]'); searchField.blur(); } function search(event) { // Start scroll prevention: https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/ document.body.style.position = 'fixed'; document.body.style.top = `-${window.scrollY}px`; // End scroll prevention // prevent enter's from autosubmitting event.stopPropagation(); var form = document.querySelector('[data-search-form]'); var searchResults = document.querySelector('[data-search-results]'); var searchResultEntries = document.querySelector('[data-search-results] .phpdocumentor-search-results__entries'); searchResultEntries.innerHTML = ''; if (!event.target.value) { close(); return; } form.classList.toggle('phpdocumentor-search--has-results', true); searchResults.classList.remove('phpdocumentor-search-results--hidden'); var results = fuse.search(event.target.value, {limit: 25}); results.forEach(function (result) { var entry = document.createElement("li"); entry.classList.add("phpdocumentor-search-results__entry"); entry.innerHTML += '

            ' + result.name + "

            \n"; entry.innerHTML += '' + result.fqsen + "\n"; entry.innerHTML += '
            ' + result.summary + '
            '; searchResultEntries.appendChild(entry) }); } function appendIndex(added) { index = index.concat(added); // re-initialize search engine when appending an index after initialisation if (typeof fuse !== 'undefined') { fuse = new Fuse(index, options); } } function init() { fuse = new Fuse(index, options); var form = document.querySelector('[data-search-form]'); var searchField = document.querySelector('[data-search-form] input[type="search"]'); var closeButton = document.querySelector('.phpdocumentor-search-results__close'); closeButton.addEventListener('click', function() { close() }.bind(this)); var searchResults = document.querySelector('[data-search-results]'); searchResults.addEventListener('click', function() { close() }.bind(this)); form.classList.add('phpdocumentor-search--active'); searchField.setAttribute('placeholder', 'Search (Press "/" to focus)'); searchField.removeAttribute('disabled'); searchField.addEventListener('keyup', debounce(search, 300)); window.addEventListener('keyup', function (event) { if (event.key === '/') { searchField.focus(); } if (event.code === 'Escape') { close(); } }.bind(this)); } return { appendIndex, init } })(); window.addEventListener('DOMContentLoaded', function () { var form = document.querySelector('[data-search-form]'); // When JS is supported; show search box. Must be before including the search for it to take effect immediately form.classList.add('phpdocumentor-search--enabled'); }); window.addEventListener('load', function () { Search.init(); }); ================================================ FILE: docs/js/searchIndex.js ================================================ Search.appendIndex( [ { "fqsen": "\\Wolfcast\\BrowserDetection", "name": "BrowserDetection", "summary": "The\u0020BrowserDetection\u0020class\u0020facilitates\u0020the\u0020identification\u0020of\u0020the\u0020user\u0027s\u0020environment\u0020such\u0020as\u0020Web\u0020browser,\u0020version,\nplatform\u0020and\u0020device\u0020type.", "url": "classes/Wolfcast-BrowserDetection.html" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A__construct\u0028\u0029", "name": "__construct", "summary": "BrowserDetection\u0020class\u0020constructor.", "url": "classes/Wolfcast-BrowserDetection.html#method___construct" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A__toString\u0028\u0029", "name": "__toString", "summary": "Determine\u0020how\u0020the\u0020class\u0020will\u0020react\u0020when\u0020it\u0020is\u0020treated\u0020like\u0020a\u0020string.", "url": "classes/Wolfcast-BrowserDetection.html#method___toString" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AaddCustomBrowserDetection\u0028\u0029", "name": "addCustomBrowserDetection", "summary": "Dynamically\u0020add\u0020support\u0020for\u0020a\u0020new\u0020Web\u0020browser.", "url": "classes/Wolfcast-BrowserDetection.html#method_addCustomBrowserDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AaddCustomPlatformDetection\u0028\u0029", "name": "addCustomPlatformDetection", "summary": "Dynamically\u0020add\u0020support\u0020for\u0020a\u0020new\u0020platform.", "url": "classes/Wolfcast-BrowserDetection.html#method_addCustomPlatformDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AaddCustomRobotDetection\u0028\u0029", "name": "addCustomRobotDetection", "summary": "Dynamically\u0020add\u0020support\u0020for\u0020a\u0020new\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_addCustomRobotDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcompareVersions\u0028\u0029", "name": "compareVersions", "summary": "Compare\u0020two\u0020version\u0020number\u0020strings.", "url": "classes/Wolfcast-BrowserDetection.html#method_compareVersions" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetIECompatibilityView\u0028\u0029", "name": "getIECompatibilityView", "summary": "Get\u0020the\u0020name\u0020and\u0020version\u0020of\u0020the\u0020browser\u0020emulated\u0020in\u0020the\u0020compatibility\u0020view\u0020mode\u0020\u0028if\u0020any\u0029.\u0020Since\u0020Internet\nExplorer\u00208,\u0020IE\u0020can\u0020be\u0020put\u0020in\u0020compatibility\u0020mode\u0020to\u0020make\u0020websites\u0020that\u0020were\u0020created\u0020for\u0020older\u0020browsers,\u0020especially\nIE\u00206\u0020and\u00207,\u0020look\u0020better\u0020in\u0020IE\u00208\u002B\u0020which\u0020renders\u0020web\u0020pages\u0020closer\u0020to\u0020the\u0020standards\u0020and\u0020thus\u0020differently\u0020from\u0020those\nolder\u0020versions\u0020of\u0020IE.", "url": "classes/Wolfcast-BrowserDetection.html#method_getIECompatibilityView" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetLibVersion\u0028\u0029", "name": "getLibVersion", "summary": "Return\u0020the\u0020BrowserDetection\u0020class\u0020version.", "url": "classes/Wolfcast-BrowserDetection.html#method_getLibVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetName\u0028\u0029", "name": "getName", "summary": "Get\u0020the\u0020name\u0020of\u0020the\u0020browser.\u0020All\u0020of\u0020the\u0020return\u0020values\u0020are\u0020class\u0020constants.\u0020You\u0020can\u0020compare\u0020them\u0020like\u0020this\u003A\n\u0024myBrowserInstance\u002D\u003EgetName\u0028\u0029\u0020\u003D\u003D\u0020BrowserDetection\u003A\u003ABROWSER_FIREFOX.", "url": "classes/Wolfcast-BrowserDetection.html#method_getName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetPlatform\u0028\u0029", "name": "getPlatform", "summary": "Get\u0020the\u0020name\u0020of\u0020the\u0020platform\u0020family\u0020on\u0020which\u0020the\u0020browser\u0020is\u0020run\u0020on\u0020\u0028such\u0020as\u0020Windows,\u0020Apple,\u0020etc.\u0029.\u0020All\u0020of\nthe\u0020return\u0020values\u0020are\u0020class\u0020constants.\u0020You\u0020can\u0020compare\u0020them\u0020like\u0020this\u003A\n\u0024myBrowserInstance\u002D\u003EgetPlatform\u0028\u0029\u0020\u003D\u003D\u0020BrowserDetection\u003A\u003APLATFORM_ANDROID.", "url": "classes/Wolfcast-BrowserDetection.html#method_getPlatform" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetPlatformVersion\u0028\u0029", "name": "getPlatformVersion", "summary": "Get\u0020the\u0020platform\u0020version\u0020on\u0020which\u0020the\u0020browser\u0020is\u0020run\u0020on.\u0020It\u0020can\u0020be\u0020returned\u0020as\u0020a\u0020string\u0020number\u0020like\u0020\u0027NT\u00206.3\u0027\u0020or\nas\u0020a\u0020name\u0020like\u0020\u0027Windows\u00208.1\u0027.\u0020When\u0020returning\u0020version\u0020string\u0020numbers\u0020for\u0020Windows\u0020NT\u0020OS\u0020families\u0020the\u0020number\u0020is\nprefixed\u0020by\u0020\u0027NT\u0020\u0027\u0020to\u0020differentiate\u0020from\u0020older\u0020Windows\u00203.x\u0020\u0026\u00209x\u0020release.\u0020At\u0020the\u0020moment\u0020only\u0020the\u0020Windows\u0020and\nAndroid\u0020operating\u0020systems\u0020are\u0020supported.", "url": "classes/Wolfcast-BrowserDetection.html#method_getPlatformVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetRobotName\u0028\u0029", "name": "getRobotName", "summary": "Get\u0020the\u0020name\u0020of\u0020the\u0020robot.\u0020All\u0020of\u0020the\u0020return\u0020values\u0020are\u0020class\u0020constants.\u0020You\u0020can\u0020compare\u0020them\u0020like\u0020this\u003A\n\u0024myBrowserInstance\u002D\u003EgetRobotName\u0028\u0029\u0020\u003D\u003D\u0020BrowserDetection\u003A\u003AROBOT_GOOGLEBOT.", "url": "classes/Wolfcast-BrowserDetection.html#method_getRobotName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetRobotVersion\u0028\u0029", "name": "getRobotVersion", "summary": "Get\u0020the\u0020version\u0020of\u0020the\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_getRobotVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetUserAgent\u0028\u0029", "name": "getUserAgent", "summary": "Get\u0020the\u0020user\u0020agent\u0020value\u0020used\u0020by\u0020the\u0020class\u0020to\u0020determine\u0020the\u0020browser\u0020details.", "url": "classes/Wolfcast-BrowserDetection.html#method_getUserAgent" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AgetVersion\u0028\u0029", "name": "getVersion", "summary": "Get\u0020the\u0020version\u0020of\u0020the\u0020browser.", "url": "classes/Wolfcast-BrowserDetection.html#method_getVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003Ais64bitPlatform\u0028\u0029", "name": "is64bitPlatform", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020executed\u0020from\u0020a\u002064\u002Dbit\u0020platform.\u0020Keep\u0020in\u0020mind\u0020that\u0020not\u0020all\u0020platforms\/browsers\u0020report\nthis\u0020and\u0020the\u0020result\u0020may\u0020not\u0020always\u0020be\u0020accurate.", "url": "classes/Wolfcast-BrowserDetection.html#method_is64bitPlatform" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AisChromeFrame\u0028\u0029", "name": "isChromeFrame", "summary": "Determine\u0020if\u0020the\u0020browser\u0020runs\u0020Google\u0020Chrome\u0020Frame\u0020\u0028it\u0027s\u0020a\u0020plug\u002Din\u0020designed\u0020for\u0020Internet\u0020Explorer\u00206\u002B\u0020based\u0020on\u0020the\nopen\u002Dsource\u0020Chromium\u0020project\u0020\u002D\u0020it\u0027s\u0020like\u0020a\u0020Chrome\u0020browser\u0020within\u0020IE\u0029.", "url": "classes/Wolfcast-BrowserDetection.html#method_isChromeFrame" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AisInIECompatibilityView\u0028\u0029", "name": "isInIECompatibilityView", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020in\u0020compatibility\u0020view\u0020or\u0020not.\u0020Since\u0020Internet\u0020Explorer\u00208,\u0020IE\u0020can\u0020be\u0020put\u0020in\ncompatibility\u0020mode\u0020to\u0020make\u0020websites\u0020that\u0020were\u0020created\u0020for\u0020older\u0020browsers,\u0020especially\u0020IE\u00206\u0020and\u00207,\u0020look\u0020better\u0020in\nIE\u00208\u002B\u0020which\u0020renders\u0020web\u0020pages\u0020closer\u0020to\u0020the\u0020standards\u0020and\u0020thus\u0020differently\u0020from\u0020those\u0020older\u0020versions\u0020of\u0020IE.", "url": "classes/Wolfcast-BrowserDetection.html#method_isInIECompatibilityView" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AisMobile\u0028\u0029", "name": "isMobile", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020from\u0020a\u0020mobile\u0020device\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_isMobile" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AisRobot\u0028\u0029", "name": "isRobot", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020a\u0020robot\u0020\u0028Googlebot,\u0020Bingbot,\u0020Yahoo\u0021\u0020Slurp...\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_isRobot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AremoveCustomBrowserDetection\u0028\u0029", "name": "removeCustomBrowserDetection", "summary": "Remove\u0020support\u0020for\u0020a\u0020previously\u0020added\u0020Web\u0020browser.", "url": "classes/Wolfcast-BrowserDetection.html#method_removeCustomBrowserDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AremoveCustomPlatformDetection\u0028\u0029", "name": "removeCustomPlatformDetection", "summary": "Remove\u0020support\u0020for\u0020a\u0020previously\u0020added\u0020platform.", "url": "classes/Wolfcast-BrowserDetection.html#method_removeCustomPlatformDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AremoveCustomRobotDetection\u0028\u0029", "name": "removeCustomRobotDetection", "summary": "Remove\u0020support\u0020for\u0020a\u0020previously\u0020added\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_removeCustomRobotDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetUserAgent\u0028\u0029", "name": "setUserAgent", "summary": "Set\u0020the\u0020user\u0020agent\u0020to\u0020use\u0020with\u0020the\u0020class.", "url": "classes/Wolfcast-BrowserDetection.html#method_setUserAgent" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AandroidVerToStr\u0028\u0029", "name": "androidVerToStr", "summary": "Convert\u0020the\u0020Android\u0020version\u0020numbers\u0020to\u0020the\u0020operating\u0020system\u0020name.\u0020For\u0020instance\u0020\u00271.6\u0027\u0020returns\u0020\u0027Donut\u0027.", "url": "classes/Wolfcast-BrowserDetection.html#method_androidVerToStr" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserAndroid\u0028\u0029", "name": "checkBrowserAndroid", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020the\u0020Android\u0020browser\u0020\u0028based\u0020on\u0020the\u0020WebKit\u0020layout\u0020engine\u0020and\u0020coupled\u0020with\u0020Chrome\u0027s\nJavaScript\u0020engine\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserAndroid" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserBlackBerry\u0028\u0029", "name": "checkBrowserBlackBerry", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020the\u0020BlackBerry\u0020browser\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserBlackBerry" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserChrome\u0028\u0029", "name": "checkBrowserChrome", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Chrome\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserChrome" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserCustom\u0028\u0029", "name": "checkBrowserCustom", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020among\u0020the\u0020custom\u0020browser\u0020rules\u0020or\u0020not.\u0020Rules\u0020are\u0020checked\u0020in\u0020the\u0020order\u0020they\u0020were\nadded.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserCustom" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserEdge\u0028\u0029", "name": "checkBrowserEdge", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Edge\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserEdge" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserFirebird\u0028\u0029", "name": "checkBrowserFirebird", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Firebird\u0020or\u0020not.\u0020Firebird\u0020was\u0020the\u0020name\u0020of\u0020Firefox\u0020from\u0020version\u00200.6\u0020to\u00200.7.1.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserFirebird" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserFirefox\u0028\u0029", "name": "checkBrowserFirefox", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Firefox\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserFirefox" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserIcab\u0028\u0029", "name": "checkBrowserIcab", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020iCab\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserIcab" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserIceCat\u0028\u0029", "name": "checkBrowserIceCat", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020GNU\u0020IceCat\u0020\u0028formerly\u0020known\u0020as\u0020GNU\u0020IceWeasel\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserIceCat" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserIceWeasel\u0028\u0029", "name": "checkBrowserIceWeasel", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020GNU\u0020IceWeasel\u0020\u0028now\u0020know\u0020as\u0020GNU\u0020IceCat\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserIceWeasel" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserInternetExplorer\u0028\u0029", "name": "checkBrowserInternetExplorer", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Internet\u0020Explorer\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserInternetExplorer" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserKonqueror\u0028\u0029", "name": "checkBrowserKonqueror", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Konqueror\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserKonqueror" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserLynx\u0028\u0029", "name": "checkBrowserLynx", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Lynx\u0020or\u0020not.\u0020It\u0020is\u0020the\u0020oldest\u0020web\u0020browser\u0020currently\u0020in\u0020general\u0020use\u0020and\u0020development.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserLynx" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserMozilla\u0028\u0029", "name": "checkBrowserMozilla", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Mozilla\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserMozilla" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserMsnTv\u0028\u0029", "name": "checkBrowserMsnTv", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020MSN\u0020TV\u0020\u0028formerly\u0020WebTV\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserMsnTv" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserNetscape\u0028\u0029", "name": "checkBrowserNetscape", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Netscape\u0020or\u0020not.\u0020Official\u0020support\u0020for\u0020this\u0020browser\u0020ended\u0020on\u0020March\u00201st,\u00202008.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserNetscape" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserNokia\u0028\u0029", "name": "checkBrowserNokia", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020a\u0020Nokia\u0020browser\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserNokia" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserOpera\u0028\u0029", "name": "checkBrowserOpera", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Opera\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserOpera" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserPhoenix\u0028\u0029", "name": "checkBrowserPhoenix", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Phoenix\u0020or\u0020not.\u0020Phoenix\u0020was\u0020the\u0020name\u0020of\u0020Firefox\u0020from\u0020version\u00200.1\u0020to\u00200.5.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserPhoenix" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowser\u0028\u0029", "name": "checkBrowser", "summary": "Determine\u0020what\u0020is\u0020the\u0020browser\u0020used\u0020by\u0020the\u0020user.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowser" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserSafari\u0028\u0029", "name": "checkBrowserSafari", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020Safari\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserSafari" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserSamsung\u0028\u0029", "name": "checkBrowserSamsung", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020the\u0020Samsung\u0020Internet\u0020browser\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserSamsung" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserUAWithVersion\u0028\u0029", "name": "checkBrowserUAWithVersion", "summary": "Test\u0020the\u0020user\u0020agent\u0020for\u0020a\u0020specific\u0020browser\u0020that\u0020use\u0020a\u0020\u0022Version\u0022\u0020string\u0020\u0028like\u0020Safari\u0020and\u0020Opera\u0029.\u0020The\u0020user\u0020agent\nshould\u0020look\u0020like\u003A\u0020\u0022Version\/1.0\u0020Browser\u0020name\/123.456\u0022\u0020or\u0020\u0022Browser\u0020name\/123.456\u0020Version\/1.0\u0022.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserUAWithVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckBrowserUC\u0028\u0029", "name": "checkBrowserUC", "summary": "Determine\u0020if\u0020the\u0020browser\u0020is\u0020UC\u0020Browser\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkBrowserUC" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckPlatform\u0028\u0029", "name": "checkPlatform", "summary": "Determine\u0020the\u0020user\u0027s\u0020platform.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkPlatform" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckPlatformCustom\u0028\u0029", "name": "checkPlatformCustom", "summary": "Determine\u0020if\u0020the\u0020platform\u0020is\u0020among\u0020the\u0020custom\u0020platform\u0020rules\u0020or\u0020not.\u0020Rules\u0020are\u0020checked\u0020in\u0020the\u0020order\u0020they\u0020were\nadded.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkPlatformCustom" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckPlatformVersion\u0028\u0029", "name": "checkPlatformVersion", "summary": "Determine\u0020the\u0020user\u0027s\u0020platform\u0020version.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkPlatformVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotBingbot\u0028\u0029", "name": "checkRobotBingbot", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020Bingbot\u0020crawler\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotBingbot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotGooglebot\u0028\u0029", "name": "checkRobotGooglebot", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020Googlebot\u0020crawler\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotGooglebot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotMsnBot\u0028\u0029", "name": "checkRobotMsnBot", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020MSNBot\u0020crawler\u0020or\u0020not.\u0020In\u0020October\u00202010\u0020it\u0020was\u0020replaced\u0020by\u0020the\u0020Bingbot\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotMsnBot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobot\u0028\u0029", "name": "checkRobot", "summary": "Determine\u0020if\u0020it\u0027s\u0020a\u0020robot\u0020crawling\u0020the\u0020page\u0020and\u0020find\u0020it\u0027s\u0020name\u0020and\u0020version.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotCustom\u0028\u0029", "name": "checkRobotCustom", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020among\u0020the\u0020custom\u0020robot\u0020rules\u0020or\u0020not.\u0020Rules\u0020are\u0020checked\u0020in\u0020the\u0020order\u0020they\u0020were\u0020added.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotCustom" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotSlurp\u0028\u0029", "name": "checkRobotSlurp", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020Yahoo\u0021\u0020Slurp\u0020crawler\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotSlurp" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotW3CValidator\u0028\u0029", "name": "checkRobotW3CValidator", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020W3C\u0020Validator\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotW3CValidator" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckRobotYahooMultimedia\u0028\u0029", "name": "checkRobotYahooMultimedia", "summary": "Determine\u0020if\u0020the\u0020robot\u0020is\u0020the\u0020Yahoo\u0021\u0020multimedia\u0020crawler\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkRobotYahooMultimedia" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckSimpleBrowserUA\u0028\u0029", "name": "checkSimpleBrowserUA", "summary": "Test\u0020the\u0020user\u0020agent\u0020for\u0020a\u0020specific\u0020browser\u0020where\u0020the\u0020browser\u0020name\u0020is\u0020immediately\u0020followed\u0020by\u0020the\u0020version\u0020number.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkSimpleBrowserUA" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcheckSimpleRobot\u0028\u0029", "name": "checkSimpleRobot", "summary": "Test\u0020the\u0020user\u0020agent\u0020for\u0020a\u0020specific\u0020robot\u0020where\u0020the\u0020robot\u0020name\u0020is\u0020immediately\u0020followed\u0020by\u0020the\u0020version\u0020number.", "url": "classes/Wolfcast-BrowserDetection.html#method_checkSimpleRobot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcleanVersion\u0028\u0029", "name": "cleanVersion", "summary": "Clean\u0020a\u0020version\u0020string\u0020from\u0020unwanted\u0020characters.", "url": "classes/Wolfcast-BrowserDetection.html#method_cleanVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AcontainString\u0028\u0029", "name": "containString", "summary": "Find\u0020if\u0020one\u0020or\u0020more\u0020substring\u0020is\u0020contained\u0020in\u0020a\u0020string.", "url": "classes/Wolfcast-BrowserDetection.html#method_containString" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003Adetect\u0028\u0029", "name": "detect", "summary": "Detect\u0020the\u0020user\u0020environment\u0020from\u0020the\u0020details\u0020in\u0020the\u0020user\u0020agent\u0020string.", "url": "classes/Wolfcast-BrowserDetection.html#method_detect" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AfindAndGetVersion\u0028\u0029", "name": "findAndGetVersion", "summary": "Test\u0020the\u0020user\u0020agent\u0020for\u0020a\u0020specific\u0020browser\u0020and\u0020extract\u0020it\u0027s\u0020version.", "url": "classes/Wolfcast-BrowserDetection.html#method_findAndGetVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AiOSVerToStr\u0028\u0029", "name": "iOSVerToStr", "summary": "Convert\u0020the\u0020iOS\u0020version\u0020numbers\u0020to\u0020the\u0020operating\u0020system\u0020name.\u0020For\u0020instance\u0020\u00272.0\u0027\u0020returns\u0020\u0027iPhone\u0020OS\u00202.0\u0027.", "url": "classes/Wolfcast-BrowserDetection.html#method_iOSVerToStr" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AmacVerToStr\u0028\u0029", "name": "macVerToStr", "summary": "Convert\u0020the\u0020macOS\u0020version\u0020numbers\u0020to\u0020the\u0020operating\u0020system\u0020name.\u0020For\u0020instance\u0020\u002710.7\u0027\u0020returns\u0020\u0027Mac\u0020OS\u0020X\u0020Lion\u0027.", "url": "classes/Wolfcast-BrowserDetection.html#method_macVerToStr" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AparseInt\u0028\u0029", "name": "parseInt", "summary": "Get\u0020the\u0020integer\u0020value\u0020of\u0020a\u0020string\u0020variable.", "url": "classes/Wolfcast-BrowserDetection.html#method_parseInt" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003Areset\u0028\u0029", "name": "reset", "summary": "Reset\u0020all\u0020the\u0020properties\u0020of\u0020the\u0020class.", "url": "classes/Wolfcast-BrowserDetection.html#method_reset" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsafariBuildToSafariVer\u0028\u0029", "name": "safariBuildToSafariVer", "summary": "Convert\u0020a\u0020Safari\u0020build\u0020number\u0020to\u0020a\u0020Safari\u0020version\u0020number.", "url": "classes/Wolfcast-BrowserDetection.html#method_safariBuildToSafariVer" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003Aset64bit\u0028\u0029", "name": "set64bit", "summary": "Set\u0020if\u0020the\u0020browser\u0020is\u0020executed\u0020from\u0020a\u002064\u002Dbit\u0020platform.", "url": "classes/Wolfcast-BrowserDetection.html#method_set64bit" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetBrowser\u0028\u0029", "name": "setBrowser", "summary": "Set\u0020the\u0020name\u0020of\u0020the\u0020browser.", "url": "classes/Wolfcast-BrowserDetection.html#method_setBrowser" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetMobile\u0028\u0029", "name": "setMobile", "summary": "Set\u0020the\u0020browser\u0020to\u0020be\u0020from\u0020a\u0020mobile\u0020device\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_setMobile" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetPlatform\u0028\u0029", "name": "setPlatform", "summary": "Set\u0020the\u0020platform\u0020on\u0020which\u0020the\u0020browser\u0020is\u0020on.", "url": "classes/Wolfcast-BrowserDetection.html#method_setPlatform" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetPlatformVersion\u0028\u0029", "name": "setPlatformVersion", "summary": "Set\u0020the\u0020platform\u0020version\u0020on\u0020which\u0020the\u0020browser\u0020is\u0020on.", "url": "classes/Wolfcast-BrowserDetection.html#method_setPlatformVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetRobot\u0028\u0029", "name": "setRobot", "summary": "Set\u0020the\u0020browser\u0020to\u0020be\u0020a\u0020robot\u0020\u0028crawler\u0029\u0020or\u0020not.", "url": "classes/Wolfcast-BrowserDetection.html#method_setRobot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetRobotName\u0028\u0029", "name": "setRobotName", "summary": "Set\u0020the\u0020name\u0020of\u0020the\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_setRobotName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetRobotVersion\u0028\u0029", "name": "setRobotVersion", "summary": "Set\u0020the\u0020version\u0020of\u0020the\u0020robot.", "url": "classes/Wolfcast-BrowserDetection.html#method_setRobotVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AsetVersion\u0028\u0029", "name": "setVersion", "summary": "Set\u0020the\u0020version\u0020of\u0020the\u0020browser.", "url": "classes/Wolfcast-BrowserDetection.html#method_setVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AwebKitBuildToSafariVer\u0028\u0029", "name": "webKitBuildToSafariVer", "summary": "Convert\u0020a\u0020WebKit\u0020build\u0020number\u0020to\u0020a\u0020Safari\u0020version\u0020number.", "url": "classes/Wolfcast-BrowserDetection.html#method_webKitBuildToSafariVer" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AwindowsNTVerToStr\u0028\u0029", "name": "windowsNTVerToStr", "summary": "Convert\u0020the\u0020Windows\u0020NT\u0020family\u0020version\u0020numbers\u0020to\u0020the\u0020operating\u0020system\u0020name.\u0020For\u0020instance\u0020\u00275.1\u0027\u0020returns\n\u0027Windows\u0020XP\u0027.", "url": "classes/Wolfcast-BrowserDetection.html#method_windowsNTVerToStr" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AwindowsVerToStr\u0028\u0029", "name": "windowsVerToStr", "summary": "Convert\u0020the\u0020Windows\u00203.x\u0020\u0026\u00209x\u0020family\u0020version\u0020numbers\u0020to\u0020the\u0020operating\u0020system\u0020name.\u0020For\u0020instance\u0020\u00274.10.1998\u0027\nreturns\u0020\u0027Windows\u002098\u0027.", "url": "classes/Wolfcast-BrowserDetection.html#method_windowsVerToStr" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AwordPos\u0028\u0029", "name": "wordPos", "summary": "Find\u0020the\u0020position\u0020of\u0020the\u0020first\u0020occurrence\u0020of\u0020a\u0020word\u0020in\u0020a\u0020string.", "url": "classes/Wolfcast-BrowserDetection.html#method_wordPos" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_ANDROID", "name": "BROWSER_ANDROID", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_ANDROID" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_BLACKBERRY", "name": "BROWSER_BLACKBERRY", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_BLACKBERRY" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_CHROME", "name": "BROWSER_CHROME", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_CHROME" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_EDGE", "name": "BROWSER_EDGE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_EDGE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_FIREBIRD", "name": "BROWSER_FIREBIRD", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_FIREBIRD" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_FIREFOX", "name": "BROWSER_FIREFOX", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_FIREFOX" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_ICAB", "name": "BROWSER_ICAB", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_ICAB" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_ICECAT", "name": "BROWSER_ICECAT", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_ICECAT" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_ICEWEASEL", "name": "BROWSER_ICEWEASEL", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_ICEWEASEL" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_IE", "name": "BROWSER_IE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_IE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_IE_MOBILE", "name": "BROWSER_IE_MOBILE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_IE_MOBILE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_KONQUEROR", "name": "BROWSER_KONQUEROR", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_KONQUEROR" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_LYNX", "name": "BROWSER_LYNX", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_LYNX" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_MOZILLA", "name": "BROWSER_MOZILLA", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_MOZILLA" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_MSNTV", "name": "BROWSER_MSNTV", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_MSNTV" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_NETSCAPE", "name": "BROWSER_NETSCAPE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_NETSCAPE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_NOKIA", "name": "BROWSER_NOKIA", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_NOKIA" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_OPERA", "name": "BROWSER_OPERA", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_OPERA" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_OPERA_MINI", "name": "BROWSER_OPERA_MINI", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_OPERA_MINI" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_OPERA_MOBILE", "name": "BROWSER_OPERA_MOBILE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_OPERA_MOBILE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_PHOENIX", "name": "BROWSER_PHOENIX", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_PHOENIX" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_SAFARI", "name": "BROWSER_SAFARI", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_SAFARI" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_SAMSUNG", "name": "BROWSER_SAMSUNG", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_SAMSUNG" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_TABLET_OS", "name": "BROWSER_TABLET_OS", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_TABLET_OS" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_UC", "name": "BROWSER_UC", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_UC" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003ABROWSER_UNKNOWN", "name": "BROWSER_UNKNOWN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_BROWSER_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_ANDROID", "name": "PLATFORM_ANDROID", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_ANDROID" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_BLACKBERRY", "name": "PLATFORM_BLACKBERRY", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_BLACKBERRY" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_CHROME_OS", "name": "PLATFORM_CHROME_OS", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_CHROME_OS" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_FREEBSD", "name": "PLATFORM_FREEBSD", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_FREEBSD" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_IOS", "name": "PLATFORM_IOS", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_IOS" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_LINUX", "name": "PLATFORM_LINUX", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_LINUX" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_MACINTOSH", "name": "PLATFORM_MACINTOSH", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_MACINTOSH" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_NETBSD", "name": "PLATFORM_NETBSD", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_NETBSD" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_NOKIA", "name": "PLATFORM_NOKIA", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_NOKIA" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_OPENBSD", "name": "PLATFORM_OPENBSD", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_OPENBSD" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_OPENSOLARIS", "name": "PLATFORM_OPENSOLARIS", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_OPENSOLARIS" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_SYMBIAN", "name": "PLATFORM_SYMBIAN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_SYMBIAN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_UNKNOWN", "name": "PLATFORM_UNKNOWN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_VERSION_UNKNOWN", "name": "PLATFORM_VERSION_UNKNOWN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_VERSION_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_WINDOWS", "name": "PLATFORM_WINDOWS", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_WINDOWS" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_WINDOWS_CE", "name": "PLATFORM_WINDOWS_CE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_WINDOWS_CE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003APLATFORM_WINDOWS_PHONE", "name": "PLATFORM_WINDOWS_PHONE", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_PLATFORM_WINDOWS_PHONE" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_BINGBOT", "name": "ROBOT_BINGBOT", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_BINGBOT" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_GOOGLEBOT", "name": "ROBOT_GOOGLEBOT", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_GOOGLEBOT" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_MSNBOT", "name": "ROBOT_MSNBOT", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_MSNBOT" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_SLURP", "name": "ROBOT_SLURP", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_SLURP" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_UNKNOWN", "name": "ROBOT_UNKNOWN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_VERSION_UNKNOWN", "name": "ROBOT_VERSION_UNKNOWN", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_VERSION_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_W3CVALIDATOR", "name": "ROBOT_W3CVALIDATOR", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_W3CVALIDATOR" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AROBOT_YAHOO_MM", "name": "ROBOT_YAHOO_MM", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#constant_ROBOT_YAHOO_MM" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003AVERSION_UNKNOWN", "name": "VERSION_UNKNOWN", "summary": "Version\u0020unknown\u0020constant.", "url": "classes/Wolfcast-BrowserDetection.html#constant_VERSION_UNKNOWN" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_agent", "name": "_agent", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__agent" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_browserName", "name": "_browserName", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__browserName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_compatibilityViewName", "name": "_compatibilityViewName", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__compatibilityViewName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_compatibilityViewVer", "name": "_compatibilityViewVer", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__compatibilityViewVer" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_customBrowserDetection", "name": "_customBrowserDetection", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__customBrowserDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_customPlatformDetection", "name": "_customPlatformDetection", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__customPlatformDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_customRobotDetection", "name": "_customRobotDetection", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__customRobotDetection" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_is64bit", "name": "_is64bit", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__is64bit" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_isMobile", "name": "_isMobile", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__isMobile" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_isRobot", "name": "_isRobot", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__isRobot" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_platform", "name": "_platform", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__platform" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_platformVersion", "name": "_platformVersion", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__platformVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_robotName", "name": "_robotName", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__robotName" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_robotVersion", "name": "_robotVersion", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__robotVersion" }, { "fqsen": "\\Wolfcast\\BrowserDetection\u003A\u003A\u0024_version", "name": "_version", "summary": "", "url": "classes/Wolfcast-BrowserDetection.html#property__version" }, { "fqsen": "\\", "name": "\\", "summary": "", "url": "namespaces/default.html" }, { "fqsen": "\\Wolfcast", "name": "Wolfcast", "summary": "", "url": "namespaces/wolfcast.html" } ] ); ================================================ FILE: docs/js/template.js ================================================ (function(){ window.addEventListener('load', () => { const el = document.querySelector('.phpdocumentor-on-this-page__content') if (!el) { return; } const observer = new IntersectionObserver( ([e]) => { e.target.classList.toggle("-stuck", e.intersectionRatio < 1); }, {threshold: [1]} ); observer.observe(el); }) })(); function openSvg(svg) { // convert to a valid XML source const as_text = new XMLSerializer().serializeToString(svg); // store in a Blob const blob = new Blob([as_text], { type: "image/svg+xml" }); // create an URI pointing to that blob const url = URL.createObjectURL(blob); const win = open(url); // so the Garbage Collector can collect the blob win.onload = (evt) => URL.revokeObjectURL(url); }; var svgs = document.querySelectorAll(".phpdocumentor-uml-diagram svg"); for( var i=0,il = svgs.length; i< il; i ++ ) { svgs[i].onclick = (evt) => openSvg(evt.target); } ================================================ FILE: docs/namespaces/default.html ================================================ Wolfcast BrowserDetection Documentation

            Wolfcast BrowserDetection Documentation

            API Documentation

            Table of Contents

            Namespaces

            Wolfcast
            
                    
            On this page
            • Table Of Contents

            Search results

              ================================================ FILE: docs/namespaces/wolfcast.html ================================================ Wolfcast BrowserDetection Documentation

              Wolfcast BrowserDetection Documentation

              Wolfcast

              Table of Contents

              Classes

              BrowserDetection
              The BrowserDetection class facilitates the identification of the user's environment such as Web browser, version, platform and device type.
              
                      
              On this page

              Search results

                ================================================ FILE: docs/packages/BrowserDetection.html ================================================ Wolfcast BrowserDetection Documentation

                Wolfcast BrowserDetection Documentation

                BrowserDetection

                Table of Contents

                Classes

                BrowserDetection
                The BrowserDetection class facilitates the identification of the user's environment such as Web browser, version, platform and device type.
                
                        
                On this page

                Search results

                  ================================================ FILE: docs/packages/default.html ================================================ Wolfcast BrowserDetection Documentation

                  Wolfcast BrowserDetection Documentation

                  API Documentation

                  Table of Contents

                  Packages

                  BrowserDetection
                  
                          
                  On this page
                  • Table Of Contents

                  Search results

                    ================================================ FILE: docs/reports/deprecated.html ================================================ Wolfcast BrowserDetection Documentation » Deprecated elements

                    Wolfcast BrowserDetection Documentation

                    Deprecated

                    No deprecated elements have been found in this project.

                    Search results

                      ================================================ FILE: docs/reports/errors.html ================================================ Wolfcast BrowserDetection Documentation » Compilation errors

                      Wolfcast BrowserDetection Documentation

                      Errors

                      No errors have been found in this project.

                      Search results

                        ================================================ FILE: docs/reports/markers.html ================================================ Wolfcast BrowserDetection Documentation » Markers

                        Wolfcast BrowserDetection Documentation

                        Markers

                        No markers have been found in this project.

                        Search results

                          ================================================ FILE: lib/BrowserDetection.php ================================================ getName() == Wolfcast\BrowserDetection::BROWSER_FIREFOX && * $browser->compareVersions($browser->getVersion(), '5.0') >= 0) { * echo 'You are using FireFox version 5 or greater.'; * } * ``` * * The class is a rewrite of Chris Schuld's Browser class version 1.9 which is mostly unmaintained since August 20th, * 2010. Chris' class was based on the original work from Gary White. * * Updates: * * 2025-03-23: Version 2.9.9 * + Added macOS Sequoia detection for browsers that still correctly report the macOS version. * * 2024-04-21: Version 2.9.8 * + Added macOS Sonoma and macOS Ventura detection. Note that all the majors Web browsers have reported macOS Catalina * since 2021 for any macOS 11+ versions. See the documentation of macVerToStr() for more details. * + Improved the library documentation when detecting Windows version names since Windows 11 is always reported as * Windows 10. See windowsNTVerToStr() for more details. * + Updated HTML documentation of the library to the latest version of phpDocumentor. * * 2022-09-20: Version 2.9.7 * + Changed licensing to dual licensing: MIT or LGPL-3.0-only. This has no impact on existing users. You can continue * under the previous license or switch to MIT. * * 2022-05-01: Version 2.9.6 * + Added support for Chrome OS. * + Added support for macOS Monterey and macOS Big Sur. * + Now correctly detects AArch64 as 64-bit. * + Added support for PHP 8. * + Tested with latest Web Browsers and platforms. * * 2020-02-02: Version 2.9.5 * + WARNING! Breaking change: complete rework of robots detection. Now robot name and version is detected in addition * of browser name and version. Use getRobotName() and getRobotVersion() when isRobot() is true. * + WARNING! Breaking change: due to robots detection rework the following methods signatures has changed (isRobot * parameter removed): addCustomBrowserDetection(), checkSimpleBrowserUA(), checkBrowserUAWithVersion(). * + Added possibility to support new robots with addCustomRobotDetection(). * + Added support for the new Microsoft Edge based on Chromium. * + Added version names for Android 10 and later (Google no longer use candy names for new versions). * + Added macOS Catalina detection. * + Added Windows Server 2019 detection (Windows Server 2016 can be no longer detected due to the fact that they both * use the same version number and that the build is not included in the user agent). * * 2019-03-27: Version 2.9.3 * + Fixed Edge detection on Android. * + Added Android Q detection. * + Now filtering superglobals. * * 2019-02-28: Version 2.9.2 * + Fixed Opera detection. * * 2018-08-23: Version 2.9.1 * + Fixed Chrome detection under iOS. * + Added Android Pie detection. * + Added macOS Mojave detection. * * 2018-07-15: Version 2.9.0 * + WARNING! Breaking change: new Wolfcast namespace. Use new Wolfcast\BrowserDetection(). * + iPad, iPhone and iPod are all under iOS now. * + Added Android Oreo detection. * + Added macOS High Sierra detection. * + Added UC Browser detection. * + Improved regular expressions (even less false positives). * + Removed AOL detection. * + Removed the following Web browsers detection: Amaya, Galeon, NetPositive, OmniWeb, Vivaldi detection (use * addCustomBrowserDetection()). * + Removed the following legacy platforms detection: BeOS, OS/2, SunOS (use addCustomPlatformDetection()). * * 2016-11-28: Version 2.5.1 * + Better detection of 64-bit platforms. * * 2016-08-19: Version 2.5.0 * + Platform version and platform version name are now supported for Mac. * + Fixed platform version name for Android. * * 2016-08-02: Version 2.4.0 * + Platform version and platform version name are now supported for Android. * + Added support for the Samsung Internet browser. * + Added support for the Vivaldi browser. * + Better support for legacy Windows versions. * * 2016-02-11: Version 2.3.0 * + WARNING! Breaking change: public method getBrowser() is renamed to getName(). * + WARNING! Breaking change: changed the compareVersions() return values to be more in line with other libraries. * + You can now get the exact platform version (name or version numbers) on which the browser is run on with * getPlatformVersion(). Only working with Windows operating systems at the moment. * + You can now determine if the browser is executed from a 64-bit platform with is64bitPlatform(). * + Better detection of mobile platform for Googlebot. * * 2016-01-04: Version 2.2.0 * + Added support for Microsoft Edge. * * 2014-12-30: Version 2.1.2 * + Better detection of Opera. * * 2014-07-11: Version 2.1.1 * + Better detection of mobile devices and platforms. * * 2014-06-04: Version 2.1.0 * + Added support for IE 11+. * * 2013-05-27: Version 2.0.0 which is (almost) a complete rewrite based on Chris Schuld's Browser class version 1.9 plus * changes below. * + Added support for Opera Mobile * + Added support for the Windows Phone (formerly Windows Mobile) platform * + Added support for BlackBerry Tablet OS and BlackBerry 10 * + Added support for the Symbian platform * + Added support for Bingbot * + Added support for the Yahoo! Multimedia crawler * + Removed iPhone/iPad/iPod browsers since there are not browsers but platforms - test them with getPlatform() * + Removed support for Shiretoko (Firefox 3.5 alpha/beta) and MSN Browser * + Merged Nokia and Nokia S60 * + Updated some deprecated browser names * + Many public methods are now protected * + Documentation updated * * 2010-07-04: * + Added detection of IE compatibility view - test with getIECompatibilityView() * + Added support for all (deprecated) Netscape versions * + Added support for Safari < 3.0 * + Better Firefox version parsing * + Better Opera version parsing * + Better Mozilla detection * * @package BrowserDetection * @version 2.9.9 * @last-modified March 23, 2025 * @author Alexandre Valiquette, Chris Schuld, Gary White * @copyright Copyright (c) 2025, Wolfcast * @license https://spdx.org/licenses/GPL-3.0-only.html * @license https://spdx.org/licenses/MIT.html * @link https://wolfcast.com/ * @link https://wolfcast.com/open-source/browser-detection/tutorial.php * @link https://chrisschuld.com/ */ class BrowserDetection { /**#@+ * Constant for the name of the Web browser. */ const BROWSER_ANDROID = 'Android'; const BROWSER_BLACKBERRY = 'BlackBerry'; const BROWSER_CHROME = 'Chrome'; const BROWSER_EDGE = 'Edge'; const BROWSER_FIREBIRD = 'Firebird'; const BROWSER_FIREFOX = 'Firefox'; const BROWSER_ICAB = 'iCab'; const BROWSER_ICECAT = 'GNU IceCat'; const BROWSER_ICEWEASEL = 'GNU IceWeasel'; const BROWSER_IE = 'Internet Explorer'; const BROWSER_IE_MOBILE = 'Internet Explorer Mobile'; const BROWSER_KONQUEROR = 'Konqueror'; const BROWSER_LYNX = 'Lynx'; const BROWSER_MOZILLA = 'Mozilla'; const BROWSER_MSNTV = 'MSN TV'; const BROWSER_NETSCAPE = 'Netscape'; const BROWSER_NOKIA = 'Nokia Browser'; const BROWSER_OPERA = 'Opera'; const BROWSER_OPERA_MINI = 'Opera Mini'; const BROWSER_OPERA_MOBILE = 'Opera Mobile'; const BROWSER_PHOENIX = 'Phoenix'; const BROWSER_SAFARI = 'Safari'; const BROWSER_SAMSUNG = 'Samsung Internet'; const BROWSER_TABLET_OS = 'BlackBerry Tablet OS'; const BROWSER_UC = 'UC Browser'; const BROWSER_UNKNOWN = 'unknown'; /**#@-*/ /**#@+ * Constant for the name of the platform on which the Web browser runs. */ const PLATFORM_ANDROID = 'Android'; const PLATFORM_BLACKBERRY = 'BlackBerry'; const PLATFORM_CHROME_OS = 'Chrome OS'; const PLATFORM_FREEBSD = 'FreeBSD'; const PLATFORM_IOS = 'iOS'; const PLATFORM_LINUX = 'Linux'; const PLATFORM_MACINTOSH = 'Macintosh'; const PLATFORM_NETBSD = 'NetBSD'; const PLATFORM_NOKIA = 'Nokia'; const PLATFORM_OPENBSD = 'OpenBSD'; const PLATFORM_OPENSOLARIS = 'OpenSolaris'; const PLATFORM_SYMBIAN = 'Symbian'; const PLATFORM_UNKNOWN = 'unknown'; const PLATFORM_VERSION_UNKNOWN = 'unknown'; const PLATFORM_WINDOWS = 'Windows'; const PLATFORM_WINDOWS_CE = 'Windows CE'; const PLATFORM_WINDOWS_PHONE = 'Windows Phone'; /**#@-*/ /**#@+ * Constant for the name of the robot. */ const ROBOT_BINGBOT = 'Bingbot'; const ROBOT_GOOGLEBOT = 'Googlebot'; const ROBOT_MSNBOT = 'MSNBot'; const ROBOT_SLURP = 'Yahoo! Slurp'; const ROBOT_UNKNOWN = ''; const ROBOT_VERSION_UNKNOWN = ''; const ROBOT_W3CVALIDATOR = 'W3C Validator'; const ROBOT_YAHOO_MM = 'Yahoo! Multimedia'; /**#@-*/ /** * Version unknown constant. */ const VERSION_UNKNOWN = 'unknown'; /** * @var string * @access private */ private $_agent = ''; /** * @var string * @access private */ private $_browserName = ''; /** * @var string * @access private */ private $_compatibilityViewName = ''; /** * @var string * @access private */ private $_compatibilityViewVer = ''; /** * @var array * @access private */ private $_customBrowserDetection = array(); /** * @var array * @access private */ private $_customPlatformDetection = array(); /** * @var array * @access private */ private $_customRobotDetection = array(); /** * @var boolean * @access private */ private $_is64bit = false; /** * @var boolean * @access private */ private $_isMobile = false; /** * @var boolean * @access private */ private $_isRobot = false; /** * @var string * @access private */ private $_platform = ''; /** * @var string * @access private */ private $_platformVersion = ''; /** * @var string * @access private */ private $_robotName = ''; /** * @var string * @access private */ private $_robotVersion = ''; /** * @var string * @access private */ private $_version = ''; //--- MAGIC METHODS ------------------------------------------------------------------------------------------------ /** * BrowserDetection class constructor. * @param string $useragent (optional) The user agent to work with. Leave empty for the current user agent * (contained in $_SERVER['HTTP_USER_AGENT']). */ public function __construct($useragent = '') { $this->setUserAgent($useragent); } /** * Determine how the class will react when it is treated like a string. * @return string Returns an HTML formatted string with a summary of the browser informations. */ public function __toString() { $result = ''; $values = array(); $values[] = array('label' => 'User agent', 'value' => $this->getUserAgent()); $values[] = array('label' => 'Browser name', 'value' => $this->getName()); $values[] = array('label' => 'Browser version', 'value' => $this->getVersion()); $values[] = array('label' => 'Platform family', 'value' => $this->getPlatform()); $values[] = array('label' => 'Platform version', 'value' => $this->getPlatformVersion(true)); $values[] = array('label' => 'Platform version name', 'value' => $this->getPlatformVersion()); $values[] = array('label' => 'Platform is 64-bit', 'value' => $this->is64bitPlatform() ? 'true' : 'false'); $values[] = array('label' => 'Is mobile', 'value' => $this->isMobile() ? 'true' : 'false'); $values[] = array('label' => 'Is robot', 'value' => $this->isRobot() ? 'true' : 'false'); $values[] = array('label' => 'Robot name', 'value' => $this->isRobot() ? ($this->getRobotName() != self::ROBOT_UNKNOWN ? $this->getRobotName() : 'Unknown') : 'Not applicable'); $values[] = array('label' => 'Robot version', 'value' => $this->isRobot() ? ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN ? $this->getRobotVersion() : 'Unknown') : 'Not applicable'); $values[] = array('label' => 'IE is in compatibility view', 'value' => $this->isInIECompatibilityView() ? 'true' : 'false'); $values[] = array('label' => 'Emulated IE version', 'value' => $this->isInIECompatibilityView() ? $this->getIECompatibilityView() : 'Not applicable'); $values[] = array('label' => 'Is Chrome Frame', 'value' => $this->isChromeFrame() ? 'true' : 'false'); foreach ($values as $currVal) { $result .= '' . htmlspecialchars($currVal['label'], ENT_NOQUOTES) . ': ' . $currVal['value'] . '
                          ' . PHP_EOL; } return $result; } //--- PUBLIC MEMBERS ----------------------------------------------------------------------------------------------- /** * Dynamically add support for a new Web browser. * @param string $browserName The Web browser name (used for display). * @param mixed $uaNameToLookFor (optional) The string (or array of strings) representing the browser name to find * in the user agent. If omitted, $browserName will be used. * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param string $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @see removeCustomBrowserDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomBrowserDetection($browserName, $uaNameToLookFor = '', $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($browserName == '') { return false; } if (array_key_exists($browserName, $this->_customBrowserDetection)) { unset($this->_customBrowserDetection[$browserName]); } if ($uaNameToLookFor == '') { $uaNameToLookFor = $browserName; } $this->_customBrowserDetection[$browserName] = array('uaNameToLookFor' => $uaNameToLookFor, 'isMobile' => $isMobile == true, 'separator' => $separator, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Dynamically add support for a new platform. * @param string $platformName The platform name (used for display). * @param mixed $platformNameToLookFor (optional) The string (or array of strings) representing the platform name to * find in the user agent. If omitted, $platformName will be used. * @param boolean $isMobile (optional) Determines if the platform is from a mobile device. * @param boolean $uaNameFindWords (optional) Determines if the platform name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * @see removeCustomPlatformDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomPlatformDetection($platformName, $platformNameToLookFor = '', $isMobile = false, $uaNameFindWords = true) { if ($platformName == '') { return false; } if (array_key_exists($platformName, $this->_customPlatformDetection)) { unset($this->_customPlatformDetection[$platformName]); } if ($platformNameToLookFor == '') { $platformNameToLookFor = $platformName; } $this->_customPlatformDetection[$platformName] = array('platformNameToLookFor' => $platformNameToLookFor, 'isMobile' => $isMobile == true, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Dynamically add support for a new robot. * @param string $robotName The robot name (used for display). * @param mixed $uaNameToLookFor (optional) The string (or array of strings) representing the robot name to find * in the user agent. If omitted, $robotName will be used. * @param boolean $isMobile (optional) Determines if the robot should be considered as mobile or not. * @param string $separator (optional) The separator string used to split the robot name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the robot name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the robot name can be found anywhere in the user agent string. * @see removeCustomRobotDetection() * @return boolean Returns true if the custom rule has been added, false otherwise. */ public function addCustomRobotDetection($robotName, $uaNameToLookFor = '', $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($robotName == '') { return false; } if (array_key_exists($robotName, $this->_customRobotDetection)) { unset($this->_customRobotDetection[$robotName]); } if ($uaNameToLookFor == '') { $uaNameToLookFor = $robotName; } $this->_customRobotDetection[$robotName] = array('uaNameToLookFor' => $uaNameToLookFor, 'isMobile' => $isMobile == true, 'separator' => $separator, 'uaNameFindWords' => $uaNameFindWords == true); return true; } /** * Compare two version number strings. * @param string $sourceVer The source version number. * @param string $compareVer The version number to compare with the source version number. * @return int Returns -1 if $sourceVer < $compareVer, 0 if $sourceVer == $compareVer or 1 if $sourceVer > * $compareVer. */ public function compareVersions($sourceVer, $compareVer) { $sourceVer = explode('.', $sourceVer); foreach ($sourceVer as $k => $v) { $sourceVer[$k] = $this->parseInt($v); } $compareVer = explode('.', $compareVer); foreach ($compareVer as $k => $v) { $compareVer[$k] = $this->parseInt($v); } if (count($sourceVer) != count($compareVer)) { if (count($sourceVer) > count($compareVer)) { for ($i = count($compareVer); $i < count($sourceVer); $i++) { $compareVer[$i] = 0; } } else { for ($i = count($sourceVer); $i < count($compareVer); $i++) { $sourceVer[$i] = 0; } } } foreach ($sourceVer as $i => $srcVerPart) { if ($srcVerPart > $compareVer[$i]) { return 1; } else { if ($srcVerPart < $compareVer[$i]) { return -1; } } } return 0; } /** * Get the name and version of the browser emulated in the compatibility view mode (if any). Since Internet * Explorer 8, IE can be put in compatibility mode to make websites that were created for older browsers, especially * IE 6 and 7, look better in IE 8+ which renders web pages closer to the standards and thus differently from those * older versions of IE. * @param boolean $asArray (optional) Determines if the return value must be an array (true) or a string (false). * @return mixed If a string was requested, the function returns the name and version of the browser emulated in * the compatibility view mode or an empty string if the browser is not in compatibility view mode. If an array was * requested, an array with the keys 'browser' and 'version' is returned. */ public function getIECompatibilityView($asArray = false) { if ($asArray) { return array('browser' => $this->_compatibilityViewName, 'version' => $this->_compatibilityViewVer); } else { return trim($this->_compatibilityViewName . ' ' . $this->_compatibilityViewVer); } } /** * Return the BrowserDetection class version. * @return string Returns the version as a sting with the #.#.# format. */ public function getLibVersion() { return '2.9.9'; } /** * Get the name of the browser. All of the return values are class constants. You can compare them like this: * $myBrowserInstance->getName() == BrowserDetection::BROWSER_FIREFOX. * @return string Returns the name of the browser or BrowserDetection::BROWSER_UNKNOWN if unknown. */ public function getName() { return $this->_browserName; } /** * Get the name of the platform family on which the browser is run on (such as Windows, Apple, etc.). All of * the return values are class constants. You can compare them like this: * $myBrowserInstance->getPlatform() == BrowserDetection::PLATFORM_ANDROID. * @return string Returns the name of the platform or BrowserDetection::PLATFORM_UNKNOWN if unknown. */ public function getPlatform() { return $this->_platform; } /** * Get the platform version on which the browser is run on. It can be returned as a string number like 'NT 6.3' or * as a name like 'Windows 8.1'. When returning version string numbers for Windows NT OS families the number is * prefixed by 'NT ' to differentiate from older Windows 3.x & 9x release. At the moment only the Windows and * Android operating systems are supported. * @param boolean $returnVersionNumbers (optional) Determines if the return value must be versions numbers as a * string (true) or the version name (false). * @param boolean $returnServerFlavor (optional) Since some Windows NT versions have the same values, this flag * determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use * version 6.3. This parameter is only useful when testing for Windows. * @return string Returns the version name/version numbers of the platform or the constant PLATFORM_VERSION_UNKNOWN * if unknown. */ public function getPlatformVersion($returnVersionNumbers = false, $returnServerFlavor = false) { if ($this->_platformVersion == self::PLATFORM_VERSION_UNKNOWN || $this->_platformVersion == '') { return self::PLATFORM_VERSION_UNKNOWN; } if ($returnVersionNumbers) { return $this->_platformVersion; } else { switch ($this->getPlatform()) { case self::PLATFORM_WINDOWS: if (substr($this->_platformVersion, 0, 3) == 'NT ') { return $this->windowsNTVerToStr(substr($this->_platformVersion, 3), $returnServerFlavor); } else { return $this->windowsVerToStr($this->_platformVersion); } break; case self::PLATFORM_MACINTOSH: return $this->macVerToStr($this->_platformVersion); case self::PLATFORM_ANDROID: return $this->androidVerToStr($this->_platformVersion); case self::PLATFORM_IOS: return $this->iOSVerToStr($this->_platformVersion); default: return self::PLATFORM_VERSION_UNKNOWN; } } } /** * Get the name of the robot. All of the return values are class constants. You can compare them like this: * $myBrowserInstance->getRobotName() == BrowserDetection::ROBOT_GOOGLEBOT. * @return string Returns the name of the robot or BrowserDetection::ROBOT_UNKNOWN if unknown. */ public function getRobotName() { return $this->_robotName; } /** * Get the version of the robot. * @return string Returns the version of the robot or BrowserDetection::ROBOT_VERSION_UNKNOWN if unknown. */ public function getRobotVersion() { return $this->_robotVersion; } /** * Get the user agent value used by the class to determine the browser details. * @return string The user agent string. */ public function getUserAgent() { return $this->_agent; } /** * Get the version of the browser. * @return string Returns the version of the browser or BrowserDetection::VERSION_UNKNOWN if unknown. */ public function getVersion() { return $this->_version; } /** * Determine if the browser is executed from a 64-bit platform. Keep in mind that not all platforms/browsers report * this and the result may not always be accurate. * @return boolean Returns true if the browser is executed from a 64-bit platform. */ public function is64bitPlatform() { return $this->_is64bit; } /** * Determine if the browser runs Google Chrome Frame (it's a plug-in designed for Internet Explorer 6+ based on the * open-source Chromium project - it's like a Chrome browser within IE). * @return boolean Returns true if the browser is using Google Chrome Frame, false otherwise. */ public function isChromeFrame() { return $this->containString($this->_agent, 'chromeframe'); } /** * Determine if the browser is in compatibility view or not. Since Internet Explorer 8, IE can be put in * compatibility mode to make websites that were created for older browsers, especially IE 6 and 7, look better in * IE 8+ which renders web pages closer to the standards and thus differently from those older versions of IE. * @return boolean Returns true if the browser is in compatibility view, false otherwise. */ public function isInIECompatibilityView() { return ($this->_compatibilityViewName != '') || ($this->_compatibilityViewVer != ''); } /** * Determine if the browser is from a mobile device or not. * @return boolean Returns true if the browser is from a mobile device, false otherwise. */ public function isMobile() { return $this->_isMobile; } /** * Determine if the browser is a robot (Googlebot, Bingbot, Yahoo! Slurp...) or not. * @return boolean Returns true if the browser is a robot, false otherwise. */ public function isRobot() { return $this->_isRobot; } /** * Remove support for a previously added Web browser. * @param string $browserName The Web browser name as used when added. * @see addCustomBrowserDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomBrowserDetection($browserName) { if (array_key_exists($browserName, $this->_customBrowserDetection)) { unset($this->_customBrowserDetection[$browserName]); return true; } return false; } /** * Remove support for a previously added platform. * @param string $platformName The platform name as used when added. * @see addCustomPlatformDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomPlatformDetection($platformName) { if (array_key_exists($platformName, $this->_customPlatformDetection)) { unset($this->_customPlatformDetection[$platformName]); return true; } return false; } /** * Remove support for a previously added robot. * @param string $robotName The robot name as used when added. * @see addCustomRobotDetection() * @return boolean Returns true if the custom rule has been found and removed, false otherwise. */ public function removeCustomRobotDetection($robotName) { if (array_key_exists($robotName, $this->_customRobotDetection)) { unset($this->_customRobotDetection[$robotName]); return true; } return false; } /** * Set the user agent to use with the class. * @param string $agentString (optional) The value of the user agent. If an empty string is sent (default), * $_SERVER['HTTP_USER_AGENT'] will be used. */ public function setUserAgent($agentString = '') { if (!is_string($agentString) || trim($agentString) == '') { //https://bugs.php.net/bug.php?id=49184 if (filter_has_var(INPUT_SERVER, 'HTTP_USER_AGENT')) { $agentString = filter_input(INPUT_SERVER, 'HTTP_USER_AGENT', FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); } else if (array_key_exists('HTTP_USER_AGENT', $_SERVER) && is_string($_SERVER['HTTP_USER_AGENT'])) { $agentString = filter_var($_SERVER['HTTP_USER_AGENT'], FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); } else { $agentString = ''; } if ($agentString === false || $agentString === NULL) { //filter_input or filter_var failed $agentString = ''; } } $this->reset(); $this->_agent = $agentString; $this->detect(); } //--- PROTECTED MEMBERS -------------------------------------------------------------------------------------------- /** * Convert the Android version numbers to the operating system name. For instance '1.6' returns 'Donut'. * @access protected * @param string $androidVer The Android version numbers as a string. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function androidVerToStr($androidVer) { //https://en.wikipedia.org/wiki/Android_version_history if ($this->compareVersions($androidVer, '10') >= 0) { $majorVer = strstr($androidVer, '.', true); if ($majorVer == '') { $majorVer = $androidVer; } return self::BROWSER_ANDROID . ' ' . $majorVer; } else if ($this->compareVersions($androidVer, '9') >= 0 && $this->compareVersions($androidVer, '10') < 0) { return 'Pie'; } else if ($this->compareVersions($androidVer, '8') >= 0 && $this->compareVersions($androidVer, '9') < 0) { return 'Oreo'; } else if ($this->compareVersions($androidVer, '7') >= 0 && $this->compareVersions($androidVer, '8') < 0) { return 'Nougat'; } else if ($this->compareVersions($androidVer, '6') >= 0 && $this->compareVersions($androidVer, '7') < 0) { return 'Marshmallow'; } else if ($this->compareVersions($androidVer, '5') >= 0 && $this->compareVersions($androidVer, '5.2') < 0) { return 'Lollipop'; } else if ($this->compareVersions($androidVer, '4.4') >= 0 && $this->compareVersions($androidVer, '4.5') < 0) { return 'KitKat'; } else if ($this->compareVersions($androidVer, '4.1') >= 0 && $this->compareVersions($androidVer, '4.4') < 0) { return 'Jelly Bean'; } else if ($this->compareVersions($androidVer, '4') >= 0 && $this->compareVersions($androidVer, '4.1') < 0) { return 'Ice Cream Sandwich'; } else if ($this->compareVersions($androidVer, '3') >= 0 && $this->compareVersions($androidVer, '3.3') < 0) { return 'Honeycomb'; } else if ($this->compareVersions($androidVer, '2.3') >= 0 && $this->compareVersions($androidVer, '2.4') < 0) { return 'Gingerbread'; } else if ($this->compareVersions($androidVer, '2.2') >= 0 && $this->compareVersions($androidVer, '2.3') < 0) { return 'Froyo'; } else if ($this->compareVersions($androidVer, '2') >= 0 && $this->compareVersions($androidVer, '2.2') < 0) { return 'Eclair'; } else if ($this->compareVersions($androidVer, '1.6') == 0) { return 'Donut'; } else if ($this->compareVersions($androidVer, '1.5') == 0) { return 'Cupcake'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Unknown/unnamed Android version } } /** * Determine if the browser is the Android browser (based on the WebKit layout engine and coupled with Chrome's * JavaScript engine) or not. * @access protected * @return boolean Returns true if the browser is the Android browser, false otherwise. */ protected function checkBrowserAndroid() { //Android don't use the standard "Android/1.0", it uses "Android 1.0;" instead return $this->checkSimpleBrowserUA('Android', $this->_agent, self::BROWSER_ANDROID, true); } /** * Determine if the browser is the BlackBerry browser or not. * @access protected * @link https://web.archive.org/web/20170328000854/http://supportforums.blackberry.com/t5/Web-and-WebWorks-Development/How-to-detect-the-BlackBerry-Browser/ta-p/559862 * @return boolean Returns true if the browser is the BlackBerry browser, false otherwise. */ protected function checkBrowserBlackBerry() { $found = false; //Tablet OS check if ($this->checkSimpleBrowserUA('RIM Tablet OS', $this->_agent, self::BROWSER_TABLET_OS, true)) { return true; } //Version 6, 7 & 10 check (versions 8 & 9 does not exists) if ($this->checkBrowserUAWithVersion(array('BlackBerry', 'BB10'), $this->_agent, self::BROWSER_BLACKBERRY, true)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { $found = true; } else { return true; } } //Version 4.2 to 5.0 check if ($this->checkSimpleBrowserUA('BlackBerry', $this->_agent, self::BROWSER_BLACKBERRY, true, '/', false)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { $found = true; } else { return true; } } return $found; } /** * Determine if the browser is Chrome or not. * @access protected * @link https://www.google.com/chrome/ * @return boolean Returns true if the browser is Chrome, false otherwise. */ protected function checkBrowserChrome() { return $this->checkSimpleBrowserUA(array('Chrome', 'CriOS'), $this->_agent, self::BROWSER_CHROME); } /** * Determine if the browser is among the custom browser rules or not. Rules are checked in the order they were * added. * @access protected * @return boolean Returns true if we found the browser we were looking for in the custom rules, false otherwise. */ protected function checkBrowserCustom() { foreach ($this->_customBrowserDetection as $browserName => $customBrowser) { $uaNameToLookFor = $customBrowser['uaNameToLookFor']; $isMobile = $customBrowser['isMobile']; $separator = $customBrowser['separator']; $uaNameFindWords = $customBrowser['uaNameFindWords']; if ($this->checkSimpleBrowserUA($uaNameToLookFor, $this->_agent, $browserName, $isMobile, $separator, $uaNameFindWords)) { return true; } } return false; } /** * Determine if the browser is Edge or not. * @access protected * @return boolean Returns true if the browser is Edge, false otherwise. */ protected function checkBrowserEdge() { return $this->checkSimpleBrowserUA(array('Edg', 'Edge', 'EdgA'), $this->_agent, self::BROWSER_EDGE); } /** * Determine if the browser is Firebird or not. Firebird was the name of Firefox from version 0.6 to 0.7.1. * @access protected * @return boolean Returns true if the browser is Firebird, false otherwise. */ protected function checkBrowserFirebird() { return $this->checkSimpleBrowserUA('Firebird', $this->_agent, self::BROWSER_FIREBIRD); } /** * Determine if the browser is Firefox or not. * @access protected * @link https://www.mozilla.org/en-US/firefox/new/ * @return boolean Returns true if the browser is Firefox, false otherwise. */ protected function checkBrowserFirefox() { //Safari heavily matches with Firefox, ensure that Safari is filtered out... if (preg_match('/.*Firefox[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches) && !$this->containString($this->_agent, 'Safari')) { $this->setBrowser(self::BROWSER_FIREFOX); $this->setVersion($matches[1]); $this->setMobile(false); $this->setRobot(false); return true; } return false; } /** * Determine if the browser is iCab or not. * @access protected * @link http://www.icab.de/ * @return boolean Returns true if the browser is iCab, false otherwise. */ protected function checkBrowserIcab() { //Some (early) iCab versions don't use the standard "iCab/1.0", they uses "iCab 1.0;" instead return $this->checkSimpleBrowserUA('iCab', $this->_agent, self::BROWSER_ICAB); } /** * Determine if the browser is GNU IceCat (formerly known as GNU IceWeasel) or not. * @access protected * @link https://www.gnu.org/software/gnuzilla/ * @return boolean Returns true if the browser is GNU IceCat, false otherwise. */ protected function checkBrowserIceCat() { return $this->checkSimpleBrowserUA('IceCat', $this->_agent, self::BROWSER_ICECAT); } /** * Determine if the browser is GNU IceWeasel (now know as GNU IceCat) or not. * @access protected * @see checkBrowserIceCat() * @return boolean Returns true if the browser is GNU IceWeasel, false otherwise. */ protected function checkBrowserIceWeasel() { return $this->checkSimpleBrowserUA('Iceweasel', $this->_agent, self::BROWSER_ICEWEASEL); } /** * Determine if the browser is Internet Explorer or not. * @access protected * @link https://en.wikipedia.org/wiki/Internet_Explorer * @link https://en.wikipedia.org/wiki/Internet_Explorer_Mobile * @return boolean Returns true if the browser is Internet Explorer, false otherwise. */ protected function checkBrowserInternetExplorer() { //Test for Internet Explorer Mobile (formerly Pocket Internet Explorer) if ($this->checkSimpleBrowserUA(array('IEMobile', 'MSPIE'), $this->_agent, self::BROWSER_IE_MOBILE, true)) { return true; } //Several browsers uses IE compatibility UAs filter these browsers out (but after testing for IE Mobile) if ($this->containString($this->_agent, 'Opera') || $this->containString($this->_agent, array('BlackBerry', 'Nokia'), true, false)) { return false; } //Test for Internet Explorer 1 if ($this->checkSimpleBrowserUA('Microsoft Internet Explorer', $this->_agent, self::BROWSER_IE)) { if ($this->getVersion() == self::VERSION_UNKNOWN) { if (preg_match('/308|425|426|474|0b1/i', $this->_agent)) { $this->setVersion('1.5'); } else { $this->setVersion('1.0'); } } return true; } //Test for Internet Explorer 2+ if ($this->containString($this->_agent, array('MSIE', 'Trident'))) { $version = ''; if ($this->containString($this->_agent, 'Trident')) { //Test for Internet Explorer 11+ (check the rv: string) if ($this->containString($this->_agent, 'rv:', true, false)) { if ($this->checkSimpleBrowserUA('Trident', $this->_agent, self::BROWSER_IE, false, 'rv:')) { return true; } } else { //Test for Internet Explorer 8, 9 & 10 (check the Trident string) if (preg_match('/Trident\/([\d]+)/i', $this->_agent, $foundVersion)) { //Trident started with version 4.0 on IE 8 $verFromTrident = $this->parseInt($foundVersion[1]) + 4; if ($verFromTrident >= 8) { $version = $verFromTrident . '.0'; } } } //If we have the IE version from Trident, we can check for the compatibility view mode if ($version != '') { $emulatedVer = ''; preg_match_all('/MSIE\s*([^\s;$]+)/i', $this->_agent, $foundVersions); foreach ($foundVersions[1] as $currVer) { //Keep the lowest MSIE version for the emulated version (in compatibility view mode) if ($emulatedVer == '' || $this->compareVersions($emulatedVer, $currVer) == 1) { $emulatedVer = $currVer; } } //Set the compatibility view mode if $version != $emulatedVer if ($this->compareVersions($version, $emulatedVer) != 0) { $this->_compatibilityViewName = self::BROWSER_IE; $this->_compatibilityViewVer = $this->cleanVersion($emulatedVer); } } } //Test for Internet Explorer 2-7 versions if needed if ($version == '') { preg_match_all('/MSIE\s+([^\s;$]+)/i', $this->_agent, $foundVersions); foreach ($foundVersions[1] as $currVer) { //Keep the highest MSIE version if ($version == '' || $this->compareVersions($version, $currVer) == -1) { $version = $currVer; } } } $this->setBrowser(self::BROWSER_IE); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); return true; } return false; } /** * Determine if the browser is Konqueror or not. * @access protected * @link https://www.konqueror.org/ * @return boolean Returns true if the browser is Konqueror, false otherwise. */ protected function checkBrowserKonqueror() { return $this->checkSimpleBrowserUA('Konqueror', $this->_agent, self::BROWSER_KONQUEROR); } /** * Determine if the browser is Lynx or not. It is the oldest web browser currently in general use and development. * It is a text-based only Web browser. * @access protected * @link https://en.wikipedia.org/wiki/Lynx_(web_browser) * @return boolean Returns true if the browser is Lynx, false otherwise. */ protected function checkBrowserLynx() { return $this->checkSimpleBrowserUA('Lynx', $this->_agent, self::BROWSER_LYNX); } /** * Determine if the browser is Mozilla or not. * @access protected * @return boolean Returns true if the browser is Mozilla, false otherwise. */ protected function checkBrowserMozilla() { return $this->checkSimpleBrowserUA('Mozilla', $this->_agent, self::BROWSER_MOZILLA, false, 'rv:'); } /** * Determine if the browser is MSN TV (formerly WebTV) or not. * @access protected * @link https://en.wikipedia.org/wiki/MSN_TV * @return boolean Returns true if the browser is WebTv, false otherwise. */ protected function checkBrowserMsnTv() { return $this->checkSimpleBrowserUA('webtv', $this->_agent, self::BROWSER_MSNTV); } /** * Determine if the browser is Netscape or not. Official support for this browser ended on March 1st, 2008. * @access protected * @link https://en.wikipedia.org/wiki/Netscape * @return boolean Returns true if the browser is Netscape, false otherwise. */ protected function checkBrowserNetscape() { //BlackBerry & Nokia UAs can conflict with Netscape UAs if ($this->containString($this->_agent, array('BlackBerry', 'Nokia'), true, false)) { return false; } //Netscape v6 to v9 check if ($this->checkSimpleBrowserUA(array('Netscape', 'Navigator', 'Netscape6'), $this->_agent, self::BROWSER_NETSCAPE)) { return true; } //Netscape v1-4 (v5 don't exists) $found = false; if ($this->containString($this->_agent, 'Mozilla') && !$this->containString($this->_agent, 'rv:', true, false)) { $version = ''; $verParts = explode('/', stristr($this->_agent, 'Mozilla')); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $verParts = explode('.', $verParts[0]); $majorVer = $this->parseInt($verParts[0]); if ($majorVer > 0 && $majorVer < 5) { $version = implode('.', $verParts); $found = true; if (strtolower(substr($version, -4)) == '-sgi') { $version = substr($version, 0, -4); } else { if (strtolower(substr($version, -4)) == 'gold') { $version = substr($version, 0, -4) . ' Gold'; //Doubles spaces (if any) will be normalized by setVersion() } } } } } if ($found) { $this->setBrowser(self::BROWSER_NETSCAPE); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); } return $found; } /** * Determine if the browser is a Nokia browser or not. * @access protected * @link https://web.archive.org/web/20141012034159/http://www.developer.nokia.com/Community/Wiki/User-Agent_headers_for_Nokia_devices * @return boolean Returns true if the browser is a Nokia browser, false otherwise. */ protected function checkBrowserNokia() { if ($this->containString($this->_agent, array('Nokia5800', 'Nokia5530', 'Nokia5230'), true, false)) { $this->setBrowser(self::BROWSER_NOKIA); $this->setVersion('7.0'); $this->setMobile(true); $this->setRobot(false); return true; } if ($this->checkSimpleBrowserUA(array('NokiaBrowser', 'BrowserNG', 'Series60', 'S60', 'S40OviBrowser'), $this->_agent, self::BROWSER_NOKIA, true)) { return true; } return false; } /** * Determine if the browser is Opera or not. * @access protected * @link https://www.opera.com/ * @link https://www.opera.com/mobile/ * @link https://web.archive.org/web/20140220123653/http://my.opera.com/community/openweb/idopera/ * @return boolean Returns true if the browser is Opera, false otherwise. */ protected function checkBrowserOpera() { if ($this->checkBrowserUAWithVersion('Opera Mobi', $this->_agent, self::BROWSER_OPERA_MOBILE, true)) { return true; } if ($this->checkSimpleBrowserUA('Opera Mini', $this->_agent, self::BROWSER_OPERA_MINI, true)) { return true; } $version = ''; $found = $this->checkBrowserUAWithVersion('Opera', $this->_agent, self::BROWSER_OPERA); if ($found && $this->getVersion() != self::VERSION_UNKNOWN) { $version = $this->getVersion(); } if (!$found || $version == '') { if ($this->checkSimpleBrowserUA('Opera', $this->_agent, self::BROWSER_OPERA)) { return true; } } if (!$found && $this->checkSimpleBrowserUA('Chrome', $this->_agent, self::BROWSER_CHROME) ) { if ($this->checkSimpleBrowserUA('OPR', $this->_agent, self::BROWSER_OPERA)) { return true; } } return $found; } /** * Determine if the browser is Phoenix or not. Phoenix was the name of Firefox from version 0.1 to 0.5. * @access protected * @return boolean Returns true if the browser is Phoenix, false otherwise. */ protected function checkBrowserPhoenix() { return $this->checkSimpleBrowserUA('Phoenix', $this->_agent, self::BROWSER_PHOENIX); } /** * Determine what is the browser used by the user. * @access protected * @return boolean Returns true if the browser has been identified, false otherwise. */ protected function checkBrowser() { //Changing the check order can break the class detection results! return /* Major browsers and browsers that need to be detected in a special order */ $this->checkBrowserCustom() || /* Customs rules are always checked first */ $this->checkBrowserMsnTv() || /* MSN TV is based on IE so we must check for MSN TV before IE */ $this->checkBrowserInternetExplorer() || $this->checkBrowserOpera() || /* Opera must be checked before Firefox, Netscape and Chrome to avoid conflicts */ $this->checkBrowserEdge() || /* Edge must be checked before Firefox, Safari and Chrome to avoid conflicts */ $this->checkBrowserSamsung() || /* Samsung Internet browser must be checked before Chrome and Safari to avoid conflicts */ $this->checkBrowserUC() || /* UC Browser must be checked before Chrome and Safari to avoid conflicts */ $this->checkBrowserChrome() || /* Chrome must be checked before Netscaoe and Mozilla to avoid conflicts */ $this->checkBrowserIcab() || /* Check iCab before Netscape since iCab have Mozilla UAs */ $this->checkBrowserNetscape() || /* Must be checked before Firefox since Netscape 8-9 are based on Firefox */ $this->checkBrowserIceCat() || /* Check IceCat and IceWeasel before Firefox since they are GNU builds of Firefox */ $this->checkBrowserIceWeasel() || $this->checkBrowserFirefox() || /* Current browsers that don't need to be detected in any special order */ $this->checkBrowserKonqueror() || $this->checkBrowserLynx() || /* Mobile */ $this->checkBrowserAndroid() || $this->checkBrowserBlackBerry() || $this->checkBrowserNokia() || /* WebKit base check (after most other checks) */ $this->checkBrowserSafari() || /* Deprecated browsers that don't need to be detected in any special order */ $this->checkBrowserFirebird() || $this->checkBrowserPhoenix() || /* Mozilla is such an open standard that it must be checked last */ $this->checkBrowserMozilla(); } /** * Determine if the browser is Safari or not. * @access protected * @link https://www.apple.com/safari/ * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @link https://en.wikipedia.org/wiki/Safari_version_history#Release_history * @return boolean Returns true if the browser is Safari, false otherwise. */ protected function checkBrowserSafari() { $version = ''; //Check for current versions of Safari $found = $this->checkBrowserUAWithVersion(array('Safari', 'AppleWebKit'), $this->_agent, self::BROWSER_SAFARI); if ($found && $this->getVersion() != self::VERSION_UNKNOWN) { $version = $this->getVersion(); } //Safari 1-2 didn't had a "Version" string in the UA, only a WebKit build and/or Safari build, extract version from these... if (!$found || $version == '') { if (preg_match('/.*Safari[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches)) { $version = $this->safariBuildToSafariVer($matches[1]); $found = true; } } if (!$found || $version == '') { if (preg_match('/.*AppleWebKit[ (\/]*([a-z0-9.-]*)/i', $this->_agent, $matches)) { $version = $this->webKitBuildToSafariVer($matches[1]); $found = true; } } if ($found) { $this->setBrowser(self::BROWSER_SAFARI); $this->setVersion($version); $this->setMobile(false); $this->setRobot(false); } return $found; } /** * Determine if the browser is the Samsung Internet browser or not. * @access protected * @return boolean Returns true if the browser is the the Samsung Internet browser, false otherwise. */ protected function checkBrowserSamsung() { return $this->checkSimpleBrowserUA('SamsungBrowser', $this->_agent, self::BROWSER_SAMSUNG, true); } /** * Test the user agent for a specific browser that use a "Version" string (like Safari and Opera). The user agent * should look like: "Version/1.0 Browser name/123.456" or "Browser name/123.456 Version/1.0". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $browserName The literal browser name. Always use a class constant! * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param boolean $findWords (optional) Determines if the needle should match a word to be found. For example "Bar" * would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be * found anywhere in the haystack. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function checkBrowserUAWithVersion($uaNameToLookFor, $userAgent, $browserName, $isMobile = false, $findWords = true) { if (!is_array($uaNameToLookFor)) { $uaNameToLookFor = array($uaNameToLookFor); } foreach ($uaNameToLookFor as $currUANameToLookFor) { if ($this->containString($userAgent, $currUANameToLookFor, true, $findWords)) { $version = ''; $verParts = explode('/', stristr($this->_agent, 'Version')); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $version = $verParts[0]; } $this->setBrowser($browserName); $this->setVersion($version); $this->setMobile($isMobile); return true; } } return false; } /** * Determine if the browser is UC Browser or not. * @access protected * @return boolean Returns true if the browser is UC Browser, false otherwise. */ protected function checkBrowserUC() { return $this->checkSimpleBrowserUA('UCBrowser', $this->_agent, self::BROWSER_UC, true); } /** * Determine the user's platform. * @access protected */ protected function checkPlatform() { if (!$this->checkPlatformCustom()) { /* Customs rules are always checked first */ /* Mobile platforms */ if ($this->containString($this->_agent, array('Windows Phone', 'IEMobile'))) { /* Check Windows Phone (formerly Windows Mobile) before Windows */ $this->setPlatform(self::PLATFORM_WINDOWS_PHONE); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Windows CE')) { /* Check Windows CE before Windows */ $this->setPlatform(self::PLATFORM_WINDOWS_CE); $this->setMobile(true); } else if ($this->containString($this->_agent, array('CPU OS', 'CPU iPhone OS', 'iPhone', 'iPad', 'iPod'))) { /* Check iOS (iPad/iPod/iPhone) before Macintosh */ $this->setPlatform(self::PLATFORM_IOS); $this->setMobile(true); } else if ($this->containString($this->_agent, array('CrOS', 'Chromebook'))) { $this->setPlatform(self::PLATFORM_CHROME_OS); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Android')) { $this->setPlatform(self::PLATFORM_ANDROID); $this->setMobile(true); } else if ($this->containString($this->_agent, 'BlackBerry', true, false) || $this->containString($this->_agent, array('BB10', 'RIM Tablet OS'))) { $this->setPlatform(self::PLATFORM_BLACKBERRY); $this->setMobile(true); } else if ($this->containString($this->_agent, 'Nokia', true, false)) { $this->setPlatform(self::PLATFORM_NOKIA); $this->setMobile(true); /* Desktop platforms */ } else if ($this->containString($this->_agent, 'Windows')) { $this->setPlatform(self::PLATFORM_WINDOWS); } else if ($this->containString($this->_agent, 'Macintosh')) { $this->setPlatform(self::PLATFORM_MACINTOSH); } else if ($this->containString($this->_agent, 'Linux')) { $this->setPlatform(self::PLATFORM_LINUX); } else if ($this->containString($this->_agent, 'FreeBSD')) { $this->setPlatform(self::PLATFORM_FREEBSD); } else if ($this->containString($this->_agent, 'OpenBSD')) { $this->setPlatform(self::PLATFORM_OPENBSD); } else if ($this->containString($this->_agent, 'NetBSD')) { $this->setPlatform(self::PLATFORM_NETBSD); /* Discontinued */ } else if ($this->containString($this->_agent, array('Symbian', 'SymbianOS'))) { $this->setPlatform(self::PLATFORM_SYMBIAN); $this->setMobile(true); } else if ($this->containString($this->_agent, 'OpenSolaris')) { $this->setPlatform(self::PLATFORM_OPENSOLARIS); /* Generic */ } else if ($this->containString($this->_agent, 'Win', true, false)) { $this->setPlatform(self::PLATFORM_WINDOWS); } else if ($this->containString($this->_agent, 'Mac', true, false)) { $this->setPlatform(self::PLATFORM_MACINTOSH); } } //Check if it's a 64-bit platform if ($this->containString($this->_agent, array('WOW64', 'Win64', 'AMD64', 'x86_64', 'x86-64', 'Aarch64', 'ia64', 'IRIX64', 'ppc64', 'sparc64', 'x64;', 'x64_64'))) { $this->set64bit(true); } $this->checkPlatformVersion(); } /** * Determine if the platform is among the custom platform rules or not. Rules are checked in the order they were * added. * @access protected * @return boolean Returns true if we found the platform we were looking for in the custom rules, false otherwise. */ protected function checkPlatformCustom() { foreach ($this->_customPlatformDetection as $platformName => $customPlatform) { $platformNameToLookFor = $customPlatform['platformNameToLookFor']; $isMobile = $customPlatform['isMobile']; $findWords = $customPlatform['uaNameFindWords']; if ($this->containString($this->_agent, $platformNameToLookFor, true, $findWords)) { $this->setPlatform($platformName); if ($isMobile) { $this->setMobile(true); } return true; } } return false; } /** * Determine the user's platform version. * @access protected */ protected function checkPlatformVersion() { $result = ''; switch ($this->getPlatform()) { case self::PLATFORM_WINDOWS: if (preg_match('/Windows NT\s*(\d+(?:\.\d+)*)/i', $this->_agent, $foundVersion)) { $result = 'NT ' . $foundVersion[1]; } else { //https://support.microsoft.com/en-us/kb/158238 if ($this->containString($this->_agent, array('Windows XP', 'WinXP', 'Win XP'))) { $result = '5.1'; } else if ($this->containString($this->_agent, 'Windows 2000', 'Win 2000', 'Win2000')) { $result = '5.0'; } else if ($this->containString($this->_agent, array('Win 9x 4.90', 'Windows ME', 'WinME', 'Win ME'))) { $result = '4.90.3000'; //Windows Me version range from 4.90.3000 to 4.90.3000A } else if ($this->containString($this->_agent, array('Windows 98', 'Win98', 'Win 98'))) { $result = '4.10'; //Windows 98 version range from 4.10.1998 to 4.10.2222B } else if ($this->containString($this->_agent, array('Windows 95', 'Win95', 'Win 95'))) { $result = '4.00'; //Windows 95 version range from 4.00.950 to 4.03.1214 } else if (($foundAt = stripos($this->_agent, 'Windows 3')) !== false) { $result = '3'; if (preg_match('/\d+(?:\.\d+)*/', substr($this->_agent, $foundAt + strlen('Windows 3')), $foundVersion)) { $result .= '.' . $foundVersion[0]; } } else if ($this->containString($this->_agent, 'Win16')) { $result = '3.1'; } } break; case self::PLATFORM_MACINTOSH: if (preg_match('/Mac OS X\s*(\d+(?:_\d+)+)/i', $this->_agent, $foundVersion)) { $result = str_replace('_', '.', $this->cleanVersion($foundVersion[1])); } else if ($this->containString($this->_agent, 'Mac OS X')) { $result = '10'; } break; case self::PLATFORM_CHROME_OS: if (preg_match('/CrOS\s*\w*\s*([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1]); } else if (preg_match('/Chromebook\s+([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1], 'Build'); } break; case self::PLATFORM_ANDROID: if (preg_match('/Android\s+([^\s;$]+)/i', $this->_agent, $foundVersion)) { $result = $this->cleanVersion($foundVersion[1]); } break; case self::PLATFORM_IOS: if (preg_match('/(?:CPU OS|iPhone OS|iOS)[\s_]*([\d_]+)/i', $this->_agent, $foundVersion)) { $result = str_replace('_', '.', $this->cleanVersion($foundVersion[1])); } break; } if (trim($result) == '') { $result = self::PLATFORM_VERSION_UNKNOWN; } $this->setPlatformVersion($result); } /** * Determine if the robot is the Bingbot crawler or not. * @access protected * @link https://www.bing.com/webmaster/help/which-crawlers-does-bing-use-8c184ec0 * @return boolean Returns true if the robot is Bingbot, false otherwise. */ protected function checkRobotBingbot() { return $this->checkSimpleRobot('bingbot', $this->_agent, self::ROBOT_BINGBOT); } /** * Determine if the robot is the Googlebot crawler or not. * @access protected * @return boolean Returns true if the robot is Googlebot, false otherwise. */ protected function checkRobotGooglebot() { if ($this->checkSimpleRobot('Googlebot', $this->_agent, self::ROBOT_GOOGLEBOT)) { if ($this->containString($this->_agent, 'googlebot-mobile')) { $this->setMobile(true); } return true; } return false; } /** * Determine if the robot is the MSNBot crawler or not. In October 2010 it was replaced by the Bingbot robot. * @access protected * @see checkRobotBingbot() * @return boolean Returns true if the robot is MSNBot, false otherwise. */ protected function checkRobotMsnBot() { return $this->checkSimpleRobot('msnbot', $this->_agent, self::ROBOT_MSNBOT); } /** * Determine if it's a robot crawling the page and find it's name and version. * @access protected */ protected function checkRobot() { $this->checkRobotCustom() || /* Customs rules are always checked first */ $this->checkRobotGooglebot() || $this->checkRobotBingbot() || $this->checkRobotMsnBot() || $this->checkRobotSlurp() || $this->checkRobotYahooMultimedia() || $this->checkRobotW3CValidator(); } /** * Determine if the robot is among the custom robot rules or not. Rules are checked in the order they were added. * @access protected * @return boolean Returns true if we found the robot we were looking for in the custom rules, false otherwise. */ protected function checkRobotCustom() { foreach ($this->_customRobotDetection as $robotName => $customRobot) { $uaNameToLookFor = $customRobot['uaNameToLookFor']; $isMobile = $customRobot['isMobile']; $separator = $customRobot['separator']; $uaNameFindWords = $customRobot['uaNameFindWords']; if ($this->checkSimpleRobot($uaNameToLookFor, $this->_agent, $robotName, $separator, $uaNameFindWords)) { return true; } } return false; } /** * Determine if the robot is the Yahoo! Slurp crawler or not. * @access protected * @return boolean Returns true if the robot is Yahoo! Slurp, false otherwise. */ protected function checkRobotSlurp() { return $this->checkSimpleRobot('Yahoo! Slurp', $this->_agent, self::ROBOT_SLURP); } /** * Determine if the robot is the W3C Validator or not. * @access protected * @link https://validator.w3.org/ * @return boolean Returns true if the robot is the W3C Validator, false otherwise. */ protected function checkRobotW3CValidator() { //Since the W3C validates pages with different robots we will prefix our versions with the part validated on the page... //W3C Link Checker (prefixed with "Link-") if ($this->checkSimpleRobot('W3C-checklink', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('Link-' . $this->getRobotVersion()); } return true; } //W3C CSS Validation Service (prefixed with "CSS-") if ($this->checkSimpleRobot('Jigsaw', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('CSS-' . $this->getRobotVersion()); } return true; } //W3C mobileOK Checker (prefixed with "mobileOK-") if ($this->checkSimpleRobot('W3C-mobileOK', $this->_agent, self::ROBOT_W3CVALIDATOR)) { if ($this->getRobotVersion() != self::ROBOT_VERSION_UNKNOWN) { $this->setRobotVersion('mobileOK-' . $this->getRobotVersion()); } return true; } //W3C Markup Validation Service (no prefix) return $this->checkSimpleRobot('W3C_Validator', $this->_agent, self::ROBOT_W3CVALIDATOR); } /** * Determine if the robot is the Yahoo! multimedia crawler or not. * @access protected * @return boolean Returns true if the robot is the Yahoo! multimedia crawler, false otherwise. */ protected function checkRobotYahooMultimedia() { return $this->checkSimpleRobot('Yahoo-MMCrawler', $this->_agent, self::ROBOT_YAHOO_MM); } /** * Test the user agent for a specific browser where the browser name is immediately followed by the version number. * The user agent should look like: "Browser name/1.0" or "Browser 1.0;". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $browserName The literal browser name. Always use a class constant! * @param boolean $isMobile (optional) Determines if the browser is from a mobile device. * @param string $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function checkSimpleBrowserUA($uaNameToLookFor, $userAgent, $browserName, $isMobile = false, $separator = '/', $uaNameFindWords = true) { if ($this->findAndGetVersion($uaNameToLookFor, $userAgent, $version, $separator, $uaNameFindWords)) { $this->setBrowser($browserName); $this->setVersion($version); $this->setMobile($isMobile); return true; } return false; } /** * Test the user agent for a specific robot where the robot name is immediately followed by the version number. * The user agent should look like: "Robot name/1.0" or "Robot 1.0;". * @access protected * @param mixed $uaNameToLookFor The string (or array of strings) representing the robot name to find in the user * agent. * @param string $userAgent The user agent string to work with. * @param string $robotName The literal robot name. Always use a class constant! * @param string $separator (optional) The separator string used to split the robot name and the version number in * the user agent. * @param boolean $uaNameFindWords (optional) Determines if the robot name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the robot name can be found anywhere in the user agent string. * @return boolean Returns true if we found the robot we were looking for, false otherwise. */ protected function checkSimpleRobot($uaNameToLookFor, $userAgent, $robotName, $separator = '/', $uaNameFindWords = true) { if ($this->findAndGetVersion($uaNameToLookFor, $userAgent, $version, $separator, $uaNameFindWords)) { $this->setRobot(true); $this->setRobotName($robotName); $this->setRobotVersion($version); return true; } return false; } /** * Clean a version string from unwanted characters. * @access protected * @param string $version The version string to clean. * @param mixed $toRemove (optional) String or array of strings representing additional string(s) to remove. * @return string Returns the cleaned version number string. */ protected function cleanVersion($version, $toRemove = NULL) { $cleanVer = $version; if ($toRemove !== NULL) { $cleanVer = str_ireplace($toRemove, '', $cleanVer); } //Clear anything that is in parentheses (and the parentheses themselves) - will clear started but unclosed ones too $cleanVer = preg_replace('/\([^)]+\)?/', '', $cleanVer); //Replace with a space any character which is NOT an alphanumeric, dot (.), hyphen (-), underscore (_) or space $cleanVer = preg_replace('/[^0-9.a-zA-Z_ -]/', ' ', $cleanVer); //Remove trailing and leading spaces $cleanVer = trim($cleanVer); //Remove trailing dot (.), hyphen (-), underscore (_) while (in_array(substr($cleanVer, -1), array('.', '-', '_'))) { $cleanVer = substr($cleanVer, 0, -1); } //Remove leading dot (.), hyphen (-), underscore (_) and character v while (in_array(substr($cleanVer, 0, 1), array('.', '-', '_', 'v', 'V'))) { $cleanVer = substr($cleanVer, 1); } //Remove double spaces if any while (strpos($cleanVer, ' ') !== false) { $cleanVer = str_replace(' ', ' ', $cleanVer); } return trim($cleanVer); } /** * Find if one or more substring is contained in a string. * @access protected * @param string $haystack The string to search in. * @param mixed $needle The string to search for. Can be a string or an array of strings if multiples values are to * be searched. * @param boolean $insensitive (optional) Determines if we do a case-sensitive search (false) or a case-insensitive * one (true). * @param boolean $findWords (optional) Determines if the needle should match a word to be found. For example "Bar" * would not be found in "FooBar" when true but would be found in "Foo Bar". When set to false, the needle can be * found anywhere in the haystack. * @param int $foundPos (optional) Integer buffer that will contain the position of the needle (if found and if a * non NULL variable has been passed). * @return boolean Returns true if the needle (or one of the needles) has been found in the haystack, false * otherwise. */ protected function containString($haystack, $needle, $insensitive = true, $findWords = true, &$foundPos = NULL) { if (!is_array($needle)) { $needle = array($needle); } foreach ($needle as $currNeedle) { if ($findWords) { $position = $this->wordPos($haystack, $currNeedle, $insensitive); } else { if ($insensitive) { $position = stripos($haystack, $currNeedle); } else { $position = strpos($haystack, $currNeedle); } } if ($position !== false) { if ($foundPos !== NULL) { $foundPos = $position; } return true; } } return false; } /** * Detect the user environment from the details in the user agent string. * @access protected */ protected function detect() { $this->checkBrowser(); $this->checkPlatform(); //Check the platform after the browser since some platforms can change the mobile value $this->checkRobot(); } /** * Test the user agent for a specific browser and extract it's version. * @access protected * @param type $uaNameToLookFor The string (or array of strings) representing the browser name to find in the user * agent. * @param type $userAgent The user agent string to work with. * @param type $version String buffer that will contain the version found (if any). * @param type $separator (optional) The separator string used to split the browser name and the version number in * the user agent. * @param type $uaNameFindWords (optional) Determines if the browser name to find should match a word instead of * a part of a word. For example "Bar" would not be found in "FooBar" when true but would be found in "Foo Bar". * When set to false, the browser name can be found anywhere in the user agent string. * @return boolean Returns true if we found the browser we were looking for, false otherwise. */ protected function findAndGetVersion($uaNameToLookFor, $userAgent, &$version, $separator = '/', $uaNameFindWords = true) { $version = ''; if (!is_array($uaNameToLookFor)) { $uaNameToLookFor = array($uaNameToLookFor); } foreach ($uaNameToLookFor as $currUANameToLookFor) { $foundPos = -1; if ($this->containString($userAgent, $currUANameToLookFor, true, $uaNameFindWords, $foundPos)) { //Many browsers don't use the standard "Browser/1.0" format, they uses "Browser 1.0;" instead if (stripos($userAgent, $currUANameToLookFor . $separator) === false) { $userAgent = str_ireplace($currUANameToLookFor . ' ', $currUANameToLookFor . $separator, $userAgent); } $verParts = explode($separator, substr($userAgent, $foundPos)); if (count($verParts) > 1) { $verParts = explode(' ', $verParts[1]); $version = $verParts[0]; } return true; } } return false; } /** * Convert the iOS version numbers to the operating system name. For instance '2.0' returns 'iPhone OS 2.0'. * @access protected * @param string $iOSVer The iOS version numbers as a string. * @return string The operating system name. */ protected function iOSVerToStr($iOSVer) { if ($this->compareVersions($iOSVer, '3.0') <= 0) { return 'iPhone OS ' . $iOSVer; } else { return 'iOS ' . $iOSVer; } } /** * Convert the macOS version numbers to the operating system name. For instance '10.7' returns 'Mac OS X Lion'. * * Firefox, Safari and Chromium development teams have discovered a long tail of websites broken when reporting * "Mac OS X 11" in the user agent string. In order to slightly improve user privacy as well as Web compatibility, * they all capped the reported macOS version to 10.15 (Catalina) in the user agent string. * * Firefox reported macOS version is capped at 10.15 since Firefox 87 (March 23, 2021). This change has been also * backported in Firefox 78.9.0esr (March 23, 2021). * * Safari reported macOS version is capped at 10.15.7 since Safari 14.1 (April 26, 2021). * * Chromium reported macOS version is capped at 10.15.7 since Chromium 91.0.4437.0 (May 25, 2021). * * See below links for more details. * @access protected * @param string $macVer The macOS version numbers as a string. * @link https://bugzilla.mozilla.org/show_bug.cgi?id=1679929 * @link https://github.com/WebKit/WebKit/commit/94d3ce0900c31c929798e91ea86dcfe604251a9e * @link https://github.com/WebKit/WebKit/commit/a46b2c6dd07fab463f1b2353c5d5b2ff43000f58 * @link https://chromiumdash.appspot.com/commit/a632542e79f2589e1b3f470827c7d03092be0afb * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function macVerToStr($macVer) { //https://en.wikipedia.org/wiki/OS_X#Release_history if ($this->_platformVersion === '10') { return 'Mac OS X'; //Unspecified Mac OS X version } else if ($this->compareVersions($macVer, '15.0') >= 0 && $this->compareVersions($macVer, '16.0') < 0) { return 'macOS Sequoia'; } else if ($this->compareVersions($macVer, '14.0') >= 0 && $this->compareVersions($macVer, '15.0') < 0) { return 'macOS Sonoma'; } else if ($this->compareVersions($macVer, '13.0') >= 0 && $this->compareVersions($macVer, '14.0') < 0) { return 'macOS Ventura'; } else if ($this->compareVersions($macVer, '12.0') >= 0 && $this->compareVersions($macVer, '13.0') < 0) { return 'macOS Monterey'; } else if ($this->compareVersions($macVer, '11.0') >= 0 && $this->compareVersions($macVer, '12.0') < 0) { return 'macOS Big Sur'; } else if ($this->compareVersions($macVer, '10.15') >= 0 && $this->compareVersions($macVer, '10.16') < 0) { return 'macOS Catalina'; } else if ($this->compareVersions($macVer, '10.14') >= 0 && $this->compareVersions($macVer, '10.15') < 0) { return 'macOS Mojave'; } else if ($this->compareVersions($macVer, '10.13') >= 0 && $this->compareVersions($macVer, '10.14') < 0) { return 'macOS High Sierra'; } else if ($this->compareVersions($macVer, '10.12') >= 0 && $this->compareVersions($macVer, '10.13') < 0) { return 'macOS Sierra'; } else if ($this->compareVersions($macVer, '10.11') >= 0 && $this->compareVersions($macVer, '10.12') < 0) { return 'OS X El Capitan'; } else if ($this->compareVersions($macVer, '10.10') >= 0 && $this->compareVersions($macVer, '10.11') < 0) { return 'OS X Yosemite'; } else if ($this->compareVersions($macVer, '10.9') >= 0 && $this->compareVersions($macVer, '10.10') < 0) { return 'OS X Mavericks'; } else if ($this->compareVersions($macVer, '10.8') >= 0 && $this->compareVersions($macVer, '10.9') < 0) { return 'OS X Mountain Lion'; } else if ($this->compareVersions($macVer, '10.7') >= 0 && $this->compareVersions($macVer, '10.8') < 0) { return 'Mac OS X Lion'; } else if ($this->compareVersions($macVer, '10.6') >= 0 && $this->compareVersions($macVer, '10.7') < 0) { return 'Mac OS X Snow Leopard'; } else if ($this->compareVersions($macVer, '10.5') >= 0 && $this->compareVersions($macVer, '10.6') < 0) { return 'Mac OS X Leopard'; } else if ($this->compareVersions($macVer, '10.4') >= 0 && $this->compareVersions($macVer, '10.5') < 0) { return 'Mac OS X Tiger'; } else if ($this->compareVersions($macVer, '10.3') >= 0 && $this->compareVersions($macVer, '10.4') < 0) { return 'Mac OS X Panther'; } else if ($this->compareVersions($macVer, '10.2') >= 0 && $this->compareVersions($macVer, '10.3') < 0) { return 'Mac OS X Jaguar'; } else if ($this->compareVersions($macVer, '10.1') >= 0 && $this->compareVersions($macVer, '10.2') < 0) { return 'Mac OS X Puma'; } else if ($this->compareVersions($macVer, '10.0') >= 0 && $this->compareVersions($macVer, '10.1') < 0) { return 'Mac OS X Cheetah'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Unknown/unnamed Mac OS version } } /** * Get the integer value of a string variable. * @access protected * @param string $intStr The scalar value being converted to an integer. * @return int The integer value of $intStr on success, or 0 on failure. */ protected function parseInt($intStr) { return intval($intStr, 10); } /** * Reset all the properties of the class. * @access protected */ protected function reset() { $this->_agent = ''; $this->_browserName = self::BROWSER_UNKNOWN; $this->_compatibilityViewName = ''; $this->_compatibilityViewVer = ''; $this->_is64bit = false; $this->_isMobile = false; $this->_isRobot = false; $this->_platform = self::PLATFORM_UNKNOWN; $this->_platformVersion = self::PLATFORM_VERSION_UNKNOWN; $this->_robotName = self::ROBOT_UNKNOWN; $this->_robotVersion = self::ROBOT_VERSION_UNKNOWN; $this->_version = self::VERSION_UNKNOWN; } /** * Convert a Safari build number to a Safari version number. * @access protected * @param string $version A string representing the version number. * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @return string Returns the Safari version string. If the version can't be determined, an empty string is * returned. */ protected function safariBuildToSafariVer($version) { $verParts = explode('.', $version); //We need a 3 parts version (version 2 will becomes 2.0.0) while (count($verParts) < 3) { $verParts[] = 0; } foreach ($verParts as $i => $currPart) { $verParts[$i] = $this->parseInt($currPart); } switch ($verParts[0]) { case 419: $result = '2.0.4'; break; case 417: $result = '2.0.3'; break; case 416: $result = '2.0.2'; break; case 412: if ($verParts[1] >= 5) { $result = '2.0.1'; } else { $result = '2.0'; } break; case 312: if ($verParts[1] >= 5) { $result = '1.3.2'; } else { if ($verParts[1] >= 3) { $result = '1.3.1'; } else { $result = '1.3'; } } break; case 125: if ($verParts[1] >= 11) { $result = '1.2.4'; } else { if ($verParts[1] >= 9) { $result = '1.2.3'; } else { if ($verParts[1] >= 7) { $result = '1.2.2'; } else { $result = '1.2'; } } } break; case 100: if ($verParts[1] >= 1) { $result = '1.1.1'; } else { $result = '1.1'; } break; case 85: if ($verParts[1] >= 8) { $result = '1.0.3'; } else { if ($verParts[1] >= 7) { $result = '1.0.2'; } else { $result = '1.0'; } } break; case 73: $result = '0.9'; break; case 51: $result = '0.8.1'; break; case 48: $result = '0.8'; break; default: $result = ''; } return $result; } /** * Set if the browser is executed from a 64-bit platform. * @access protected * @param boolean $is64bit Value that tells if the browser is executed from a 64-bit platform. */ protected function set64bit($is64bit) { $this->_is64bit = $is64bit == true; } /** * Set the name of the browser. * @access protected * @param string $browserName The name of the browser. */ protected function setBrowser($browserName) { $this->_browserName = $browserName; } /** * Set the browser to be from a mobile device or not. * @access protected * @param boolean $isMobile (optional) Value that tells if the browser is on a mobile device or not. */ protected function setMobile($isMobile = true) { $this->_isMobile = $isMobile == true; } /** * Set the platform on which the browser is on. * @access protected * @param string $platform The name of the platform. */ protected function setPlatform($platform) { $this->_platform = $platform; } /** * Set the platform version on which the browser is on. * @access protected * @param string $platformVer The version numbers of the platform. */ protected function setPlatformVersion($platformVer) { $this->_platformVersion = $platformVer; } /** * Set the browser to be a robot (crawler) or not. * @access protected * @param boolean $isRobot (optional) Value that tells if the browser is a robot or not. */ protected function setRobot($isRobot = true) { $this->_isRobot = $isRobot == true; } /** * Set the name of the robot. * @access protected * @param string $robotName The name of the robot. */ protected function setRobotName($robotName) { $this->_robotName = $robotName; } /** * Set the version of the robot. * @access protected * @param string $robotVersion The version of the robot. */ protected function setRobotVersion($robotVersion) { $cleanVer = $this->cleanVersion($robotVersion); if ($cleanVer == '') { $this->_robotVersion = self::ROBOT_VERSION_UNKNOWN; } else { $this->_robotVersion = $cleanVer; } } /** * Set the version of the browser. * @access protected * @param string $version The version of the browser. */ protected function setVersion($version) { $cleanVer = $this->cleanVersion($version); if ($cleanVer == '') { $this->_version = self::VERSION_UNKNOWN; } else { $this->_version = $cleanVer; } } /** * Convert a WebKit build number to a Safari version number. * @access protected * @param string $version A string representing the version number. * @link https://web.archive.org/web/20080514173941/http://developer.apple.com/internet/safari/uamatrix.html * @return string Returns the Safari version string. If the version can't be determined, an empty string is * returned. */ protected function webKitBuildToSafariVer($version) { $verParts = explode('.', $version); //We need a 3 parts version (version 2 will becomes 2.0.0) while (count($verParts) < 3) { $verParts[] = 0; } foreach ($verParts as $i => $currPart) { $verParts[$i] = $this->parseInt($currPart); } switch ($verParts[0]) { case 419: $result = '2.0.4'; break; case 418: if ($verParts[1] >= 8) { $result = '2.0.4'; } else { $result = '2.0.3'; } break; case 417: $result = '2.0.3'; break; case 416: $result = '2.0.2'; break; case 412: if ($verParts[1] >= 7) { $result = '2.0.1'; } else { $result = '2.0'; } break; case 312: if ($verParts[1] >= 8) { $result = '1.3.2'; } else { if ($verParts[1] >= 5) { $result = '1.3.1'; } else { $result = '1.3'; } } break; case 125: if ($this->compareVersions('5.4', $verParts[1] . '.' . $verParts[2]) == -1) { $result = '1.2.4'; //125.5.5+ } else { if ($verParts[1] >= 4) { $result = '1.2.3'; } else { if ($verParts[1] >= 2) { $result = '1.2.2'; } else { $result = '1.2'; } } } break; //WebKit 100 can be either Safari 1.1 (Safari build 100) or 1.1.1 (Safari build 100.1) //for this reason, check the Safari build before the WebKit build. case 100: $result = '1.1.1'; break; case 85: if ($verParts[1] >= 8) { $result = '1.0.3'; } else { if ($verParts[1] >= 7) { //WebKit 85.7 can be either Safari 1.0 (Safari build 85.5) or 1.0.2 (Safari build 85.7) //for this reason, check the Safari build before the WebKit build. $result = '1.0.2'; } else { $result = '1.0'; } } break; case 73: $result = '0.9'; break; case 51: $result = '0.8.1'; break; case 48: $result = '0.8'; break; default: $result = ''; } return $result; } /** * Convert the Windows NT family version numbers to the operating system name. For instance '5.1' returns * 'Windows XP'. * * Windows 10 and Windows 11 share the same major version number (10). Windows 11 starts with build 22000 (version * 10.0.22000) but the build is not included in the UA. * * Windows Server 2022, 2019 & 2016 have also the same version number (10). Again, only the build can differentiate * these versions. * @access protected * @param string $winVer The Windows NT family version numbers as a string. * @param boolean $returnServerFlavor (optional) Since some Windows NT versions have the same values, this flag * determines if the Server flavor is returned or not. For instance Windows 8.1 and Windows Server 2012 R2 both use * version 6.3. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function windowsNTVerToStr($winVer, $returnServerFlavor = false) { //https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions $cleanWinVer = explode('.', $winVer); while (count($cleanWinVer) > 2) { array_pop($cleanWinVer); } $cleanWinVer = implode('.', $cleanWinVer); if ($this->compareVersions($cleanWinVer, '11') >= 0) { return self::PLATFORM_WINDOWS . ' ' . $winVer; } else if ($this->compareVersions($cleanWinVer, '10') >= 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2022') : (self::PLATFORM_WINDOWS . ' 10'); } else if ($this->compareVersions($cleanWinVer, '7') < 0) { if ($this->compareVersions($cleanWinVer, '6.3') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2012 R2') : (self::PLATFORM_WINDOWS . ' 8.1'); } else if ($this->compareVersions($cleanWinVer, '6.2') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2012') : (self::PLATFORM_WINDOWS . ' 8'); } else if ($this->compareVersions($cleanWinVer, '6.1') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2008 R2') : (self::PLATFORM_WINDOWS . ' 7'); } else if ($this->compareVersions($cleanWinVer, '6') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2008') : (self::PLATFORM_WINDOWS . ' Vista'); } else if ($this->compareVersions($cleanWinVer, '5.2') == 0) { return $returnServerFlavor ? (self::PLATFORM_WINDOWS . ' Server 2003 / ' . self::PLATFORM_WINDOWS . ' Server 2003 R2') : (self::PLATFORM_WINDOWS . ' XP x64 Edition'); } else if ($this->compareVersions($cleanWinVer, '5.1') == 0) { return self::PLATFORM_WINDOWS . ' XP'; } else if ($this->compareVersions($cleanWinVer, '5') == 0) { return self::PLATFORM_WINDOWS . ' 2000'; } else if ($this->compareVersions($cleanWinVer, '5') < 0 && $this->compareVersions($cleanWinVer, '3') >= 0) { return self::PLATFORM_WINDOWS . ' NT ' . $winVer; } } return self::PLATFORM_VERSION_UNKNOWN; //Invalid Windows NT version } /** * Convert the Windows 3.x & 9x family version numbers to the operating system name. For instance '4.10.1998' * returns 'Windows 98'. * @access protected * @param string $winVer The Windows 3.x or 9x family version numbers as a string. * @return string The operating system name or the constant PLATFORM_VERSION_UNKNOWN if nothing match the version * numbers. */ protected function windowsVerToStr($winVer) { //https://support.microsoft.com/en-us/kb/158238 if ($this->compareVersions($winVer, '4.90') >= 0 && $this->compareVersions($winVer, '4.91') < 0) { return self::PLATFORM_WINDOWS . ' Me'; //Normally range from 4.90.3000 to 4.90.3000A } else if ($this->compareVersions($winVer, '4.10') >= 0 && $this->compareVersions($winVer, '4.11') < 0) { return self::PLATFORM_WINDOWS . ' 98'; //Normally range from 4.10.1998 to 4.10.2222B } else if ($this->compareVersions($winVer, '4') >= 0 && $this->compareVersions($winVer, '4.04') < 0) { return self::PLATFORM_WINDOWS . ' 95'; //Normally range from 4.00.950 to 4.03.1214 } else if ($this->compareVersions($winVer, '3.1') == 0 || $this->compareVersions($winVer, '3.11') == 0) { return self::PLATFORM_WINDOWS . ' ' . $winVer; } else if ($this->compareVersions($winVer, '3.10') == 0) { return self::PLATFORM_WINDOWS . ' 3.1'; } else { return self::PLATFORM_VERSION_UNKNOWN; //Invalid Windows version } } /** * Find the position of the first occurrence of a word in a string. * @access protected * @param string $haystack The string to search in. * @param string $needle The string to search for. * @param boolean $insensitive (optional) Determines if we do a case-sensitive search (false) or a case-insensitive * one (true). * @param int $offset If specified, search will start this number of characters counted from the beginning of the * string. If the offset is negative, the search will start this number of characters counted from the end of the * string. * @param string $foundString String buffer that will contain the exact matching needle found. Set to NULL when * return value of the function is false. * @return mixed Returns the position of the needle (int) if found, false otherwise. Warning this function may * return Boolean false, but may also return a non-Boolean value which evaluates to false. */ protected function wordPos($haystack, $needle, $insensitive = true, $offset = 0, &$foundString = NULL) { if ($offset != 0) { $haystack = substr($haystack, $offset); } $parts = explode(' ', $needle); foreach ($parts as $i => $currPart) { $parts[$i] = preg_quote($currPart, '/'); } $regex = '/(?<=\A|[\s\/\\.,;:_()-])' . implode('[\s\/\\.,;:_()-]', $parts) . '(?=[\s\/\\.,;:_()-]|$)/'; if ($insensitive) { $regex .= 'i'; } if (preg_match($regex, $haystack, $matches, PREG_OFFSET_CAPTURE)) { $foundString = $matches[0][0]; return (int)$matches[0][1]; } return false; } }