├── .editorconfig ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── src └── BrowserDetection.php └── tests ├── benchmark.php ├── browser.php ├── chrome_os.php ├── common.php ├── console.php ├── darwin.php ├── desktop_mode.php ├── device.php ├── edge.php ├── float_issue.php ├── gecko_issue.php ├── ios.php ├── ios_webview.php ├── macos.php ├── new.php ├── os.php ├── random.php ├── rare.php ├── single.php ├── tv.php ├── useragents.db └── webview.php /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{php}] 4 | charset = utf-8 5 | indent_style = tab 6 | indent_size = 4 7 | trim_trailing_whitespace = true 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this `PHP Browser Detection` project documented in this file. 4 | 5 | ## [2.8] - 2024-09-03 6 | 7 | ### Changed 8 | 9 | - Safari Mobile browser detection improved; 10 | - Yandex App and Yandex Browser detection improved; 11 | - Baidu Mobile Browser renamed to DU Browser; 12 | - MIUI Browser renamed to Mi Browser; 13 | - Naver Search App renamed to Naver App; 14 | - 115Browser renamed to 115 Browser; 15 | - QQBrowser renamed to QQ Browser; 16 | - AVG Secure Browser renamed to AVG Browser; 17 | - MxNitro renamed to Maxthon Nitro; 18 | - WeChat App moved to cross-device detections. 19 | 20 | ### Added 21 | 22 | - Added detection for: DuckDuckGo, Aloha Browser, Opera GX, Ghostery Browser, SmartTV Browser, Adblock Browser, Stargon, Hi Browser, JioPages, You Browser, Max Browser, Biscuit, Chromium GOST, Dashob, Dezor, Duoyu Browser, Mypal Browser, iTop Browser, Mercury, Polarity, Sielo, Roccat, Arctic Fox, Norton Browser, Avira Browser, Lenovo Browser, Sber Browser, Soul Browser, Samsung Browser TV; 23 | - Gnome Web browser detection on Linux; 24 | - Opera Touch on iOS detection added; 25 | - Chromium OS detection added as Chrome OS. 26 | 27 | ### Fixed 28 | 29 | - MacOS/iOS WKWebView detection fixed and improved; 30 | - Desktop Mode detection fixed and improved for Android and iOS browsers; 31 | - Possible collisions with 'iPad' string matching in User-Agent (e.g HiPad on Android device) fixed; 32 | - Basilisk browser detection fixed; 33 | - Chrome iOS browser detection fixed; 34 | - Firefox iOS browser detection fixed. 35 | 36 | ## [2.7] - 2023-04-27 37 | 38 | ### Fixed 39 | 40 | - Gecko browser engine issue fixed for Gecko versions > 109 for correct Gecko version detection (see issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1806690) 41 | 42 | ## [2.6] - 2023-03-12 43 | 44 | ### Added 45 | 46 | - About ~ 10 browsers/apps detection added; 47 | - Added detection of rare Windows OS User-Agents. 48 | 49 | ### Changed 50 | 51 | - iOS WebKit WebView detection improved. 52 | 53 | ### Fixed 54 | 55 | - EdgeHTML browser engine (Edge Browser from 12 to 18 versions) no longer detects as Chromium engine based 56 | 57 | ## [2.5] - 2023-03-10 58 | 59 | ### Added 60 | 61 | - MacOS Ventura detection added; 62 | - About ~ 20 browsers and apps detection added; 63 | - Added 30+ TV devices detection; 64 | - Darwin -> MacOS/iOS versions corresponding conversion database has been updated; 65 | 66 | ### Changed 67 | 68 | - Safari and Safari Mobile browsers detection improved. 69 | 70 | ### Fixed 71 | 72 | - Fixed a bug with the upper browser version limit; 73 | - Fixed a bug with Darwin -> MacOS/iOS versions corresponding conversion; 74 | - Fixed a webview detection bug when using the getBrowser() method. 75 | 76 | ## [2.4] - 2021-09-06 77 | 78 | ### Changed 79 | 80 | - MacOS Monterey detection improvements; 81 | - MacOS Big Sur detection improvements: MacOS User-Agent with '10_15_7' version matching now detectable as MacOS Big Sur instead MacOS Catalina; 82 | - New MacOS Big Sur detection feature. Since Firefox version 87 on MacOS with '10.15' version matching, this MacOS version will be considered as MacOS Big Sur (see reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox#macintosh). 83 | 84 | ## [2.3] - 2021-09-03 85 | 86 | ### Added 87 | 88 | - SpreadTrum based Android devices detection added. 89 | 90 | ### Changed 91 | 92 | - Chromecast detection improvements; 93 | - MacOS Big Sur detection improvements. 94 | 95 | ### Fixed 96 | 97 | - Chrome OS now detectable as desktop type OS; 98 | - Chrome OS devices now detectable as desktop types; 99 | - Fixed previously not identified PHP Warning Notices like 'Trying to access array offset ...' which appears since PHP version 7.4. 100 | 101 | ## [2.2] - 2021-07-05 102 | 103 | ### Added 104 | 105 | - MacOS Monterey detection added; 106 | - Windows 11 detection added. 107 | 108 | ## [2.1] - 2021-04-06 109 | 110 | ### Changed 111 | 112 | - Fixed PHP Warning Notices like 'Trying to access array offset ...' which appears since PHP version 7.4. 113 | 114 | ## [2.0] - 2021-03-12 115 | 116 | ### Added 117 | 118 | - More than 40 browsers detection added; 119 | - 64bits mode detection; 120 | - MacOS Big Sur detection; 121 | - Darwin OS detection and it's versions to MacOS/iOS versions corresponding detection; 122 | - MacOS/iOS Apps detection; 123 | - Roku OS detection; 124 | - MAUI Platform detection; 125 | - PlayStation Platform detection. 126 | 127 | ### Changed 128 | 129 | - User-Agent matching performance improvements; 130 | - Matching methods optimization; 131 | - Mobile operation systems and devices matching improvements; 132 | - Desktop mode matching accuracy improvements for Android browsers; 133 | - Desktop mode matching accuracy improvements for Windows Phone; 134 | - Android WebView detection improvements; 135 | - Safari WebView (iOS) detection improvements; 136 | - Console and TV devices detection improvements; 137 | - Linux OS detection improvements; 138 | - Safari and Safari Mobile browsers matching accuracy improvements; 139 | - Opera browser matching optimization and improvements; 140 | - Fixed some minor inaccuracy browser matching. 141 | 142 | ## [1.1] - 2020-06-10 143 | 144 | ### Added 145 | 146 | - Desktop mode detection for mobile browsers (Android, iOS, Windows Phone); 147 | - More than 20 browsers detection added. 148 | 149 | ### Changed 150 | 151 | - Windows OS detection improvements; 152 | - Linux OS detection improvements; 153 | - Fixed some minor inaccuracy User-Agent matching. 154 | 155 | ## [1.0] - 2020-05-22 156 | 157 | ### First release. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2024 Artem Murugov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP Browser Detection 2 | 3 | A PHP library for detecting the browser, operating system (OS), platform, and device type through User-Agent parsing, designed with a focus on high performance and minimal memory usage during HTTP client parsing.\ 4 | It uses a simple yet fast algorithm to accurately identify over 200 browsers/apps and more than 60 OS.\ 5 | Parsing the most common browsers takes less than 0.0005 seconds, even on low-end shared hosting environments. For rare User-Agents, recognition times are under 0.0008 seconds in the same hosting conditions.\ 6 | The library is exclusively tailored for current browsers and OS, omitting support for outdated environments that are no longer in use.\ 7 | The library operates using a single file and does not rely on any third-party dependencies. 8 | 9 | ## Requirements 10 | 11 | This library requires PHP 5.3 or later. 12 | 13 | ## Manual installation 14 | 15 | 1. Simply upload the library file `BrowserDetection.php` (located in the `src` directory) to your project; 16 | 2. Include the PHP library file using `require_once`: 17 | 18 | ```php 19 | 24 | ``` 25 | 26 | ## Installation by using Composer 27 | 28 | Install this library using Composer: 29 | 30 | ` 31 | composer require foroco/php-browser-detection 32 | ` 33 | 34 | Update library package by running a command: 35 | 36 | ` 37 | composer update foroco/php-browser-detection 38 | ` 39 | 40 | The first step requires the Composer autoloader: 41 | 42 | ```php 43 | 50 | ``` 51 | 52 | ## Usage 53 | 54 | The library attempts to retrieve environment data from the `HTTP_USER_AGENT` header sent by the HTTP client.\ 55 | The `BrowserDetection` PHP class within this library provides four public methods that return either an array or a JSON string containing the detected data extracted from the `HTTP_USER_AGENT`: 56 | 57 | * `getAll();` 58 | * `getOS();` 59 | * `getBrowser();` 60 | * `getDevice();` 61 | 62 | First argument should contain User-Agent string from the `HTTP_USER_AGENT` header or your custom User-Agent string.\ 63 | Second argument (optional) may contain 'JSON' if you want to get returned result as JSON format. 64 | 65 | ```php 66 | getAll($useragent); 74 | 75 | // Get OS data (array): 76 | $result = $Browser->getOS($useragent); 77 | 78 | // Get Browser data (array): 79 | $result = $Browser->getBrowser($useragent); 80 | 81 | // Get Device type data (array): 82 | $result = $Browser->getDevice($useragent); 83 | 84 | /* 85 | Also methods may returned result as JSON string 86 | Just use second argument of methods as 'JSON' 87 | */ 88 | 89 | // Get all possible environment data (JSON): 90 | $result = $Browser->getAll($useragent, 'JSON'); 91 | 92 | print_r($result); 93 | 94 | // ... etc 95 | ?> 96 | ``` 97 | 98 | The library class `BrowserDetection` also contains special method `setTouchSupport()` (optional, available from version 1.1).\ 99 | This method is necessary to detect mobile browsers in `Desktop Mode` condition (Android and iOS).\ 100 | For `Desktop Mode` detection `setTouchSupport()` method should call if browser supports Touch events.\ 101 | Touch events detection is performed by client-side JavaScript code in the target browser. Example: 102 | 103 | ```javascript 104 | if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 105 | // Touch Event detected 106 | } 107 | ``` 108 | 109 | ## Description for returned variables 110 | 111 | **OS Type** (`os_type`)\ 112 | Returns type of operating system (OS).\ 113 | All possible values: 114 | * desktop 115 | * mobile 116 | * mixed 117 | * unknown 118 | 119 | **OS Family** (`os_family`)\ 120 | Returns operating system (OS) family or `unknown` in cases of unable OS family recognition.\ 121 | Example: `windows`, `linux`, `unix` etc. 122 | 123 | **OS Name** (`os_name`)\ 124 | Returns operating system (OS) name or `unknown` in cases of unable OS name recognition.\ 125 | Example: `Windows`, `Android`, `macOS`, `iOS` etc. 126 | 127 | **OS Version** (`os_version`)\ 128 | Returns operating system (OS) version or `0` in cases of unable OS version recognition.\ 129 | May contains numeric, string or mixed types OS versions.\ 130 | In case of numeric OS version (e.g. `Android`) contains major and minor version parts values, e.g. `4.4`, `8.1`, `10`, `14` etc.\ 131 | In case of string OS version (e.g. `macOS`) contains string version name values, e.g. `Mavericks`, `Mojave`, `Catalina`, `Big Sur` etc.\ 132 | For `Windows` may contains mixed version types values: `10`, `Vista`, `XP` etc. 133 | 134 | **OS Title** (`os_title`)\ 135 | Returns operating system (OS) title which contains OS name and OS version together.\ 136 | Also returns `unknown` if OS name is not recognized. 137 | 138 | **Device Type** (`device_type`)\ 139 | Returns device type based on some User-Agent data.\ 140 | All possible values: 141 | * desktop 142 | * mobile 143 | * tv 144 | * console 145 | * mediaplayer 146 | * car 147 | * watch 148 | * unknown 149 | 150 | **Browser Name** (`browser_name`)\ 151 | Returns browser name or `unknown` in cases of unable browser name recognition.\ 152 | Example: `Chrome`, `Firefox`, `UC Browser`, `Huawei Browser`, `Vivaldi` etc. 153 | 154 | **Browser Version** (`browser_version`)\ 155 | Returns browser version number or `0` in cases of unable browser version recognition.\ 156 | Always contains numeric values (integer or float numbers).\ 157 | Returns float number (e.g. `3.5`, `10.5`, `13.1`) for some browsers which should contains both major and minor browser version parts (`Safari`, `Vivaldi`, `PaleMoon` etc).\ 158 | Returns only major decimal browser version (e.g. `15`, `37`, `128`) for other browsers which has a lot of major versions (`Chrome`, `Firefox`, `Opera` etc). 159 | 160 | **Browser Title** (`browser_title`)\ 161 | Returns browser title which contains browser name and browser version together.\ 162 | Also returns `unknown` if browser name is not recognized. 163 | 164 | **Browser Chrome Original** (`browser_chrome_original`)\ 165 | Returns `1` number if browser recognized as original Google Chrome browser or returns `0` if it's not. 166 | 167 | **Browser Firefox Original** (`browser_firefox_original`)\ 168 | Returns `1` number if browser recognized as original Mozilla Firefox browser or returns `0` if it's not. 169 | 170 | **Browser Safari Original** (`browser_safari_original`)\ 171 | Returns `1` number if browser recognized as original Apple Safari browser or returns `0` if it's not. 172 | 173 | **Browser Chromium Version** (`browser_chromium_version`)\ 174 | Returns Chromium major engine version number if browser based on Chromium engine or returns `0` if it's not. 175 | 176 | **Browser Gecko Version** (`browser_gecko_version`)\ 177 | Returns Gecko major engine version number if browser based on Gecko engine or returns `0` if it's not. 178 | 179 | **Browser WebKit Version** (`browser_webkit_version`)\ 180 | Returns WebKit version engine number if browser based on WebKit engine or returns `0` if it's not.\ 181 | Always float number value. 182 | 183 | **Browser Android Webview** (`browser_android_webview`)\ 184 | Returns `1` number if Android Webview mode detected or returns `0` if it's not. 185 | 186 | **Browser iOS Webview** (`browser_ios_webview`)\ 187 | Returns `1` number if iOS Webview mode detected or returns `0` if it's not. 188 | 189 | **Browser Desktop Mode** (`browser_desktop_mode`)\ 190 | Returns `1` number if mobile browser works in `Desktop Mode` or returns `0` if it's not detected.\ 191 | `setTouchSupport()` method should call for `Desktop Mode` detection if browser supports Touch events. 192 | 193 | **64 Bits Mode** (`64bits_mode`)\ 194 | Returns `1` number if operating system (OS) and browser work together in 64-bit mode or returns `0` if 64-bit mode not detected.\ 195 | Available only for `getAll();` and `getOS();` methods. 196 | 197 | ## Usage Examples 198 | 199 | Here are some examples to help you understand the library usage scenarios. 200 | 201 | ### Detect All 202 | 203 | To detect all possible environment data use: 204 | 205 | ```php 206 | getAll($useragent); 212 | print_r($result); 213 | 214 | ?> 215 | ``` 216 | 217 | Returns: 218 | 219 | ``` 220 | Array 221 | ( 222 | [os_type] => desktop 223 | [os_family] => windows 224 | [os_name] => Windows 225 | [os_version] => 7 226 | [os_title] => Windows 7 227 | [device_type] => desktop 228 | [browser_name] => Iron 229 | [browser_version] => 80 230 | [browser_title] => Iron 80 231 | [browser_chrome_original] => 0 232 | [browser_firefox_original] => 0 233 | [browser_safari_original] => 0 234 | [browser_chromium_version] => 80 235 | [browser_gecko_version] => 0 236 | [browser_webkit_version] => 0 237 | [browser_android_webview] => 0 238 | [browser_ios_webview] => 0 239 | [browser_desktop_mode] => 0 240 | [64bits_mode] => 1 241 | ) 242 | ``` 243 | 244 | ### OS Detection 245 | 246 | To parse only OS data use: 247 | 248 | ```php 249 | getOS($useragent); 255 | print_r($result); 256 | 257 | ?> 258 | ``` 259 | 260 | Returns: 261 | 262 | ``` 263 | Array 264 | ( 265 | [os_type] => mobile 266 | [os_family] => android 267 | [os_name] => Android 268 | [os_version] => 14 269 | [os_title] => Android 14 270 | [64bits_mode] => 1 271 | ) 272 | ``` 273 | 274 | ### Browser Detection 275 | 276 | To parse only browser data use: 277 | 278 | ```php 279 | getBrowser($useragent); 285 | print_r($result); 286 | 287 | ?> 288 | ``` 289 | 290 | Returns: 291 | 292 | ``` 293 | Array 294 | ( 295 | [browser_name] => Chrome 296 | [browser_version] => 128 297 | [browser_title] => Chrome 128 298 | [browser_chrome_original] => 1 299 | [browser_firefox_original] => 0 300 | [browser_safari_original] => 0 301 | [browser_chromium_version] => 128 302 | [browser_gecko_version] => 0 303 | [browser_webkit_version] => 0 304 | [browser_android_webview] => 0 305 | [browser_ios_webview] => 0 306 | [browser_desktop_mode] => 0 307 | ) 308 | ``` 309 | 310 | ### Device Detection 311 | 312 | To parse only device type data use: 313 | 314 | ```php 315 | getDevice($useragent); 321 | print_r($result); 322 | 323 | ?> 324 | ``` 325 | 326 | Returns: 327 | 328 | ``` 329 | Array 330 | ( 331 | [device_type] => tv 332 | ) 333 | ``` 334 | 335 | ### Desktop Mode Detection 336 | 337 | To detect if mobile browser works in `Desktop Mode` use: 338 | 339 | ```php 340 | setTouchSupport(); // Call if Touch events detected in browser by JavaScript code ('ontouchstart' in window) 346 | $result = $Browser->getAll($useragent); 347 | print_r($result); 348 | 349 | ?> 350 | ``` 351 | 352 | Returns: 353 | 354 | ``` 355 | Array 356 | ( 357 | [os_type] => mobile 358 | [os_family] => android 359 | [os_name] => Android 360 | [os_version] => 0 361 | [os_title] => Android 362 | [device_type] => mobile 363 | [browser_name] => Chrome 364 | [browser_version] => 128 365 | [browser_title] => Chrome 128 366 | [browser_chrome_original] => 1 367 | [browser_firefox_original] => 0 368 | [browser_safari_original] => 0 369 | [browser_chromium_version] => 128 370 | [browser_gecko_version] => 0 371 | [browser_webkit_version] => 0 372 | [browser_android_webview] => 0 373 | [browser_ios_webview] => 0 374 | [browser_desktop_mode] => 1 375 | [64bits_mode] => 0 376 | ) 377 | ``` 378 | 379 | ### Detect All (JSON) 380 | 381 | To pasre all possible environment data and returns JSON format string: 382 | 383 | ```php 384 | getAll($useragent, 'JSON'); 390 | print_r($result); 391 | 392 | ?> 393 | ``` 394 | 395 | Returns: 396 | 397 | ``` 398 | {"os_type":"mobile","os_family":"macintosh","os_name":"iOS","os_version":6,"os_title":"iOS 6","device_type":"mobile","browser_name":"Chrome","browser_version":78,"browser_title":"Chrome 78","browser_chrome_original":1,"browser_firefox_original":0,"browser_safari_original":0,"browser_chromium_version":78,"browser_gecko_version":0,"browser_webkit_version":0,"browser_android_webview":0,"browser_ios_webview":0,"browser_desktop_mode":0,"64bits_mode":0} 399 | ``` 400 | 401 | ## Benchmarking Test 402 | 403 | Benchmarking was performed on a low-level shared hosting environment.\ 404 | Test server configuration: RedHat Linux + LiteSpeed + PHP Extension.\ 405 | Test conditions based on collection of random ~446000 non repeated real life User-Agent strings. 406 | 407 | User-Agent recognition performance in PHP 7.3 (requests per second): 408 | 409 | ``` 410 | getAll: ~ 31000 rps 411 | getOS: ~ 120000 rps 412 | getBrowser: ~ 43000 rps 413 | getDevice: ~ 70000 rps 414 | ``` 415 | 416 | ## Important notice 417 | 418 | Unfortunately, the major browser engines have "frozen" the OS version information in the User-Agent header.\ 419 | For example, on macOS, the OS version information in the User-Agent is **"frozen"** at the `macOS Big Sur` release level (`Mac OS X 10_15_7`).\ 420 | On Windows, the OS version information is **"frozen"** in the User-Agent at the `Windows 10` release level (`Windows NT 10.0`). 421 | 422 | Recent releases of WebKit, Chromium, and Gecko-based browsers no longer include **correct** current OS version information in the User-Agent header. 423 | 424 | **See reference**: 425 | 426 | https://issues.chromium.org/issues/40167872 \ 427 | https://bugzilla.mozilla.org/show_bug.cgi?id=1679929 \ 428 | https://bugs.webkit.org/show_bug.cgi?id=217364 429 | 430 | One approach is to use the HTTP Client Hints headers, specifically the Sec-CH-UA-Platform-Version header. It's important to note, however, that only Chromium-based browsers currently support sending Client Hints headers. 431 | 432 | ## License 433 | 434 | The MIT License (MIT) 435 | 436 | Copyright (c) 2020-2024 Artem Murugov 437 | 438 | Permission is hereby granted, free of charge, to any person obtaining a copy of 439 | this software and associated documentation files (the "Software"), to deal in 440 | the Software without restriction, including without limitation the rights to 441 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 442 | the Software, and to permit persons to whom the Software is furnished to do so, 443 | subject to the following conditions: 444 | 445 | The above copyright notice and this permission notice shall be included in all 446 | copies or substantial portions of the Software. 447 | 448 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 449 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 450 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 451 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 452 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 453 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 454 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foroco/php-browser-detection", 3 | "type": "library", 4 | "description": "Ultra fast PHP library to detect browser, OS, platform and device type by User-Agent parsing", 5 | "keywords": ["user-agent","php","browser","detection","environment","useragent"], 6 | "homepage": "https://github.com/foroco/php-browser-detection", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Artem Murugov", 11 | "email": "murugov@gmail.com", 12 | "homepage": "https://github.com/foroco/", 13 | "role": "Developer" 14 | } 15 | ], 16 | "require": { 17 | "php": ">=5.3.0" 18 | }, 19 | "minimum-stability": "dev", 20 | "autoload": { 21 | "classmap": [ 22 | "src/BrowserDetection.php" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /src/BrowserDetection.php: -------------------------------------------------------------------------------- 1 | 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy of 12 | * this software and associated documentation files (the "Software"), to deal in 13 | * the Software without restriction, including without limitation the rights to 14 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 15 | * the Software, and to permit persons to whom the Software is furnished to do so, 16 | * subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 23 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 24 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | * 28 | * @version 2.8 29 | * @last-modified September 3, 2024 30 | * @link https://github.com/foroco/php-browser-detection 31 | */ 32 | 33 | namespace foroco; 34 | 35 | class BrowserDetection 36 | { 37 | public $useragent; 38 | private $get_mode; 39 | private $touch_support_mode; 40 | private $real_os_name; 41 | private $macos_version_minor; 42 | private $result_ios; 43 | private $result_mobile; 44 | private $result_os_type; 45 | private $result_os_family; 46 | private $result_os_name ; 47 | private $result_os_version; 48 | private $result_os_title; 49 | private $result_device_type; 50 | private $result_browser_name; 51 | private $result_browser_version; 52 | private $result_browser_title; 53 | private $result_browser_chromium_version; 54 | private $result_browser_gecko_version; 55 | private $result_browser_webkit_version; 56 | private $result_browser_chrome_original; 57 | private $result_browser_firefox_original; 58 | private $result_browser_safari_original; 59 | private $result_browser_android_webview; 60 | private $result_browser_ios_webview; 61 | private $result_browser_desktop_mode; 62 | private $result_64bits_mode; 63 | 64 | /** 65 | * Reset all common defined properties method 66 | * 67 | * @return null 68 | */ 69 | 70 | private function resetProperties() 71 | { 72 | $this->real_os_name = ''; 73 | $this->result_ios = FALSE; 74 | $this->result_mobile = 0; 75 | $this->macos_version_minor = 0; 76 | $this->result_os_type = 'unknown'; 77 | $this->result_os_family = 'unknown'; 78 | $this->result_os_name = 'unknown'; 79 | $this->result_os_version = 0; 80 | $this->result_os_title = 'unknown'; 81 | $this->result_device_type = 'unknown'; 82 | $this->result_browser_name = 'unknown'; 83 | $this->result_browser_version = 0; 84 | $this->result_browser_title = 'unknown'; 85 | $this->result_browser_chromium_version = 0; 86 | $this->result_browser_gecko_version = 0; 87 | $this->result_browser_webkit_version = 0; 88 | $this->result_browser_chrome_original = 0; 89 | $this->result_browser_firefox_original = 0; 90 | $this->result_browser_safari_original = 0; 91 | $this->result_browser_android_webview = 0; 92 | $this->result_browser_ios_webview = 0; 93 | $this->result_browser_desktop_mode = 0; 94 | $this->result_64bits_mode = 0; 95 | return NULL; 96 | } 97 | 98 | /** 99 | * Common User-Agent matching 100 | * 101 | * @param string $data The string to data search for 102 | * @param boolean $case_s Determines if we do a case-sensitive search (false) or a case insensitive (true) 103 | * @return boolean Returns true if $data found in $useragent property, false otherwise. 104 | */ 105 | 106 | private function match_ua($data, $case_s = FALSE) 107 | { 108 | if (empty($data)) return FALSE; 109 | 110 | if (substr($data, 0, 1)==='/' && substr($data, -1)==='/') 111 | { 112 | if ($case_s == TRUE) $data = $data.'i'; 113 | if (preg_match($data, $this->useragent, $matches)) 114 | { 115 | if (!isset($matches[0])) $matches[0] = 0; 116 | if (!isset($matches[1])) $matches[1] = 0; 117 | if (!isset($matches[2])) $matches[2] = 0; 118 | return $matches; 119 | } 120 | else 121 | { 122 | return FALSE; 123 | } 124 | } 125 | else 126 | { 127 | $data_a = explode('|', $data); 128 | foreach ($data_a as $v) 129 | { 130 | if ($case_s == FALSE) 131 | { 132 | if (strpos($this->useragent, $v) !== FALSE) return TRUE; 133 | } 134 | else 135 | { 136 | if (stripos($this->useragent, $v) !== FALSE) return TRUE; 137 | } 138 | } 139 | } 140 | 141 | return FALSE; 142 | } 143 | 144 | /** 145 | * Method to call User-Agent matching method if matching data is case insensitive 146 | * 147 | * @param string $data The string to data search for 148 | * @return boolean Returns true if case insensitive $data found in $useragent property, false otherwise. 149 | */ 150 | 151 | private function matchi_ua($data) 152 | { 153 | return $this->match_ua($data, TRUE); 154 | } 155 | 156 | /** 157 | * Detect iOS 158 | * The method will try to recognize iOS signs from $useragent property and will placed true in result_ios property if iOS found, false otherwise. Also returns true if iOS found, false otherwise 159 | * 160 | * @return bool 161 | */ 162 | 163 | private function match_ios() 164 | { 165 | if ($this->match_ua('iPhone|iphone|iPad;|iPod') && !$this->match_ua('x86_64|i386')) 166 | { 167 | $this->result_ios = TRUE; 168 | return TRUE; 169 | } 170 | return FALSE; 171 | } 172 | 173 | /** 174 | * Detect mobile OS 175 | * The method will try to recognize mobile OS signs from $useragent property and will placed true in result_mobile property if mobile OS found, false otherwise. 176 | * 177 | * @return null 178 | */ 179 | 180 | private function match_mobile() 181 | { 182 | // Match 64 bits Windows Desktop OS 183 | 184 | if ($this->match_ua('WOW64|Win64')) 185 | { 186 | $this->result_64bits_mode = 1; 187 | return NULL; 188 | } 189 | 190 | // Match Windows Desktop OS 191 | 192 | if ($this->match_ua('Windows NT')) return NULL; 193 | 194 | // Match Qt embedded system 195 | 196 | if ($this->match_ua('QtEmbedded;')) return NULL; 197 | 198 | // Match Android OS 199 | 200 | if ($this->match_ua('Android')) 201 | { 202 | $this->result_mobile = 1; 203 | return NULL; 204 | } 205 | 206 | // Match iOS 207 | 208 | if ($this->match_ios()) 209 | { 210 | $this->result_mobile = 1; 211 | return NULL; 212 | } 213 | 214 | // Match iOS browsers in Desktop Mode 215 | 216 | if ($this->match_ua('Mac OS X')) 217 | { 218 | if ($this->match_ua('/Mac\sOS\sX.*iOS/')) $this->result_mobile = 1; 219 | return NULL; 220 | } 221 | 222 | // Match Android browsers in Desktop Mode 223 | 224 | if ($this->match_ua('/X11\;(?:[U\;\s]+)?\sLinux/') && $this->match_ua('Version/4.0 Chrome/|SamsungBrowser|Miui|XiaoMi|EdgA|Puffin|UCBrowser|JioPages|Ecosia android')) 225 | { 226 | $this->result_mobile = 1; 227 | return NULL; 228 | } 229 | 230 | // Match other mobile signs 231 | 232 | if ($this->matchi_ua('mobile|tablet') || $this->match_ua('BlackBerry|BB10;|MIDP|PlayBook|Windows Phone|Windows Mobile|Windows CE|IEMobile|Opera Mini|OPiOS|Opera Mobi|CrKey armv|Kindle|Silk/|Bada|Tizen|Lumia|Symbian|SymbOS|(Series|PalmOS|PalmSource|Dolfin|Crosswalk|Obigo|MQQBrowser|CriOS|WhatsApp/') || $this->matchi_ua('nokia|playstation|watch')) $this->result_mobile = 1; 233 | return NULL; 234 | } 235 | 236 | /** 237 | * Convert MacOS numeric version to MacOS codename 238 | * 239 | * @param int $version The given MacOS version 240 | * @return string Returns MacOS codename string 241 | */ 242 | 243 | private function macos_codename($version) 244 | { 245 | switch($version) 246 | { 247 | case 0: $result_codename = 'Cheetah'; break; 248 | case 1: $result_codename = 'Puma'; break; 249 | case 2: $result_codename = 'Jaguar'; break; 250 | case 3: $result_codename = 'Panther'; break; 251 | case 4: $result_codename = 'Tiger'; break; 252 | case 5: $result_codename = 'Leopard'; break; 253 | case 6: $result_codename = 'Snow Leopard'; break; 254 | case 7: $result_codename = 'Lion'; break; 255 | case 8: $result_codename = 'Mountain Lion'; break; 256 | case 9: $result_codename = 'Mavericks'; break; 257 | case 10: $result_codename = 'Yosemite'; break; 258 | case 11: $result_codename = 'El Capitan'; break; 259 | case 12: $result_codename = 'Sierra'; break; 260 | case 13: $result_codename = 'High Sierra'; break; 261 | case 14: $result_codename = 'Mojave'; break; 262 | case 15: $result_codename = 'Catalina'; break; 263 | case 16: $result_codename = 'Big Sur'; break; 264 | case 17: $result_codename = 'Monterey'; break; 265 | case 18: $result_codename = 'Ventura'; break; 266 | default: $result_codename = 'New'; break; 267 | } 268 | return $result_codename; 269 | } 270 | 271 | /** 272 | * Common User-Agent parsing 273 | * The method will try to recognize environment data from $useragent property and will placed it in defined properties. 274 | * 275 | * @return null 276 | */ 277 | 278 | private function getResult() 279 | { 280 | // Detect mobile device 281 | 282 | $this->match_mobile(); 283 | 284 | // Detect mobile browser Desktop Mode 285 | 286 | if ($this->touch_support_mode == TRUE) 287 | { 288 | // Android Desktop Mode 289 | 290 | if ($this->match_ua('X11; Linux x86_64|X11; Linux aarch64|X11; U; U; Linux x86_64|X11; Linux; U;|X11; Linux zbov') && !$this->match_ua('kded/|kioclient|queror|Goanna|Epiphany|Brick|Iceweasel|SeaMonkey|Thunderbird|Qt|Arora|Ubuntu|Debian|Fedora|Linux Mint|elementary|Raspbian|Slackware|ArchLinux|Gentoo')) 291 | { 292 | $this->real_os_name = 'Android'; 293 | $this->result_mobile = 1; 294 | $this->result_browser_desktop_mode = 1; 295 | } 296 | 297 | // iOS Desktop Mode 298 | 299 | if ($this->match_ua('Intel Mac OS X')) 300 | { 301 | $this->real_os_name = 'iOS'; 302 | $this->result_mobile = 1; 303 | $this->result_browser_desktop_mode = 1; 304 | } 305 | } 306 | 307 | // Windows Phone Desktop Mode 308 | 309 | if ($this->match_ua('WPDesktop;')) 310 | { 311 | $this->real_os_name = 'Windows Phone'; 312 | $this->result_mobile = 1; 313 | $this->result_browser_desktop_mode = 1; 314 | } 315 | 316 | // Android Desktop Mode without touch support check 317 | 318 | if ($this->result_mobile == 1 && $this->result_os_type === 'unknown') 319 | { 320 | if ($this->match_ua('/X11\;(?:[U\;\s]+)?\sLinux/') && $this->match_ua('Version/4.0 Chrome/|SamsungBrowser|Miui|XiaoMi|EdgA|Puffin|UCBrowser|JioPages|Ecosia android')) 321 | { 322 | $this->real_os_name = 'Android'; 323 | $this->result_browser_desktop_mode = 1; 324 | } 325 | } 326 | 327 | // iOS Desktop Mode without touch support check 328 | 329 | if ($this->result_mobile == 1 && $this->result_ios == FALSE && $this->result_os_type === 'unknown') 330 | { 331 | if ($this->match_ua('/Mac\sOS\sX.*iOS/')) 332 | { 333 | $this->real_os_name = 'iOS'; 334 | $this->result_browser_desktop_mode = 1; 335 | } 336 | } 337 | 338 | /* 339 | -------------- 340 | OS DETECTION 341 | -------------- 342 | 343 | -------------- 344 | Mixed OS(es) 345 | -------------- 346 | */ 347 | 348 | $os_need_continue = TRUE; 349 | 350 | // Windows OS 351 | 352 | if ($this->get_mode !== 'browser' && $this->match_ua('Windows|Win32') && !$this->match_ua('Windows Phone|Windows Mobile|Windows CE|WPDesktop')) 353 | { 354 | $this->result_os_name = 'Windows'; 355 | $matches = $this->match_ua('/Windows ([ .a-zA-Z0-9]+)[;\\)]/'); 356 | $version = is_array($matches) ? $matches[1] : 0; 357 | if ($version === 'NT 11.0') $this->result_os_version = '11'; 358 | if ($version === 'NT 10.1') $this->result_os_version = '11'; 359 | if ($version === 'NT 10.0') $this->result_os_version = '10'; 360 | if ($version === 'NT 6.4') $this->result_os_version = '10'; 361 | if ($version === 'NT 6.3') $this->result_os_version = '8.1'; 362 | if ($version === 'NT 6.2') $this->result_os_version = '8'; 363 | if ($version === 'NT 6.1') $this->result_os_version = '7'; 364 | if ($version === 'NT 6.0') $this->result_os_version = 'Vista'; 365 | if ($version === 'NT 6') $this->result_os_version = 'NT'; 366 | if ($version === 'NT 5.2') $this->result_os_version = 'XP'; 367 | if ($version === 'NT 5.1') $this->result_os_version = 'XP'; 368 | if ($version === 'NT 5.01') $this->result_os_version = '2000'; 369 | if ($version === 'NT 5.0') $this->result_os_version = '2000'; 370 | if ($version === 'NT 5') $this->result_os_version = '2000'; 371 | if ($version === 'NT 4.0') $this->result_os_version = 'NT 4.0'; 372 | if ($version === 'NT4.0') $this->result_os_version = 'NT 4.0'; 373 | if ($version === 'NT') $this->result_os_version = 'NT'; 374 | if ($version === '98') $this->result_os_version = '98'; 375 | if ($version === '95') $this->result_os_version = '95'; 376 | if ($version === 'ME') $this->result_os_version = 'ME'; 377 | if (empty($this->result_os_version)) 378 | { 379 | if ($this->match_ua('/Win16/')) $this->result_os_version = '3.1'; 380 | if ($this->match_ua('/(Windows\s95|Win95|Windows_95)/')) $this->result_os_version = '95'; 381 | if ($this->match_ua('/(Windows\s98|Win98)/')) $this->result_os_version = '98'; 382 | if ($this->match_ua('/Windows\s2000/')) $this->result_os_version = '2000'; 383 | if ($this->match_ua('/Win\sNT\s5\.0/')) $this->result_os_version = '2000'; 384 | if ($this->match_ua('/Windows\sXP/')) $this->result_os_version = 'XP'; 385 | if ($this->match_ua('/WinNT4\.0/')) $this->result_os_version = 'NT 4.0'; 386 | if ($this->match_ua('/Windows\sVista/')) $this->result_os_version = 'Vista'; 387 | if ($this->match_ua('/Windows\s7/')) $this->result_os_version = '7'; 388 | if ($this->match_ua('/Windows\s8/')) $this->result_os_version = '8'; 389 | if ($this->match_ua('/Windows\s8.1/')) $this->result_os_version = '8.1'; 390 | if ($this->match_ua('/Windows\s10/')) $this->result_os_version = '10'; 391 | if ($this->match_ua('/Windows\s11/')) $this->result_os_version = '11'; 392 | } 393 | if (!empty($this->result_os_version)) $this->result_os_title = 'Windows '.$this->result_os_version; 394 | else $this->result_os_title = 'Windows (unknown version)'; 395 | if (intval($this->result_os_version)<7 || intval($this->result_os_version)>10) $this->result_os_type = 'desktop'; 396 | else $this->result_os_type = 'mixed'; 397 | $this->result_os_family = 'windows'; 398 | $os_need_continue = FALSE; 399 | } 400 | 401 | /* 402 | ------------- 403 | Desktop OS 404 | ------------- 405 | */ 406 | 407 | if ($this->get_mode !== 'browser' && $this->result_mobile == 0) 408 | { 409 | $this->result_os_type = 'desktop'; 410 | 411 | // Mac OS (X) / macOS 412 | 413 | if ($os_need_continue && $this->match_ua('Mac OS X|Mac_PowerPC|Macintosh|Mac_68K') && !$this->match_ua('AmigaOS')) 414 | { 415 | $this->result_os_version = 0; 416 | $this->result_os_name = 'MacOS'; 417 | if ($this->match_ua('Mac OS X')) 418 | { 419 | $matches = $this->match_ua('/Mac OS X (\d+)[_.](\d+)(?:[_.](\d+)|)/'); 420 | 421 | $version = isset($matches[1]) ? $matches[1] : 0; 422 | $version_minor = isset($matches[2]) ? $matches[2] : 0; 423 | $version_revision = isset($matches[3]) ? $matches[3] : -1; 424 | 425 | // macOS version to minor version conversion (needs since Big Sur) 426 | if ($version == 10 && $version_minor == 0) $version_minor = 16; 427 | if ($version == 11) $version_minor = 16; 428 | if ($version == 12) $version_minor = 17; 429 | 430 | // macOS with a particular major/minor/revision version structure (needs since Big Sur) 431 | if ($version == 10 && $version_minor == 15 && $version_revision == 7) $version_minor = 16; 432 | if ($version == 10 && $version_minor == 16 && $version_revision == 0) $version_minor = 17; 433 | 434 | if (!empty($version_minor)) 435 | { 436 | if ($version >= 10) $this->result_os_version = $this->macos_codename($version_minor); 437 | $this->macos_version_minor = $version_minor; 438 | } 439 | 440 | if (!empty($this->result_os_version)) $this->result_os_title = 'MacOS '.$this->result_os_version; 441 | else $this->result_os_title = 'MacOS (unknown version)'; 442 | } 443 | else 444 | { 445 | $this->result_os_title = 'MacOS'; 446 | } 447 | $this->result_os_family = 'macintosh'; 448 | $os_need_continue = FALSE; 449 | } 450 | 451 | // Linux family OS(es) 452 | 453 | if ($os_need_continue) 454 | { 455 | $os_list[] = array('Ubuntu'=>'/Ubuntu(?: )?(?:\/)?([0-9]+\.[0-9]+)/'); 456 | $os_list[] = array('Kubuntu'=>'/Kubuntu(?: )?(?:\/)?([0-9]+\.[0-9]+)/'); 457 | $os_list[] = array('Linux Mint'=>'/Linux Mint\/([.0-9]+)/'); 458 | $os_list[] = array('CentOS'=>'/CentOS\/([0-9]+\.[0-9]+)/'); 459 | $os_list[] = array('OpenSUSE'=>'/SUSE\/([0-9]+\.[0-9]+)/'); 460 | $os_list[] = array('Red Hat'=>'/Red\sHat\/([0-9]+\.[0-9]+)/'); 461 | 462 | foreach($os_list as $os_list_va) 463 | { 464 | $k = key($os_list_va); 465 | $v = $os_list_va[$k]; 466 | 467 | $matches = $this->match_ua($v); 468 | if ($matches) 469 | { 470 | $this->result_os_family = 'linux'; 471 | $this->result_os_name = $k; 472 | $this->result_os_version = is_array($matches) ? (float)$matches[1] : 0; 473 | $os_need_continue = FALSE; 474 | break; 475 | } 476 | } 477 | $os_list = NULL; 478 | } 479 | 480 | // Other Desktop OS(es) 481 | 482 | if ($os_need_continue) 483 | { 484 | $other_os = array(); 485 | 486 | $other_os[] = array('Chrome OS'=>'CrOS'); 487 | $other_os[] = array('Chrome OS'=>'Chromium OS'); 488 | $other_os[] = array('Linux Mint'=>'Linux Mint'); 489 | $other_os[] = array('Kubuntu'=>'Kubuntu'); 490 | $other_os[] = array('Ubuntu'=>'Ubuntu'); 491 | $other_os[] = array('Ubuntu'=>'ubuntu'); 492 | $other_os[] = array('Debian'=>'Debian'); 493 | $other_os[] = array('CentOS'=>'CentOS'); 494 | $other_os[] = array('Fedora'=>'Fedora'); 495 | $other_os[] = array('Arch Linux'=>'ArchLinux'); 496 | $other_os[] = array('OpenSUSE'=>'SUSE'); 497 | $other_os[] = array('Red Hat'=>'Red Hat'); 498 | $other_os[] = array('Elementary'=>' elementary'); 499 | $other_os[] = array('OpenBSD'=>'OpenBSD'); 500 | $other_os[] = array('NetBSD'=>'NetBSD'); 501 | $other_os[] = array('FreeBSD'=>'FreeBSD'); 502 | $other_os[] = array('SunOS'=>'SunOS'); 503 | $other_os[] = array('RISC OS'=>'RISC OS'); 504 | $other_os[] = array('Linux'=>'Linux'); 505 | $other_os[] = array('Linux'=>'X11;'); 506 | $other_os[] = array('Linux'=>'Mozilla/5.0 (x86_64)'); 507 | $other_os[] = array('Linux'=>'Mozilla/5.0 (i686)'); 508 | $other_os[] = array('Linux'=>'U; NETFLIX'); 509 | $other_os[] = array('Linux'=>'GNU; '); 510 | $other_os[] = array('Linux'=>'QtEmbedded; U; Linux;'); 511 | $other_os[] = array('AmigaOS'=>'AmigaOS'); 512 | $other_os[] = array('Haiku'=>'Haiku'); 513 | $other_os[] = array('Roku OS'=>'Roku/'); 514 | $other_os[] = array('BeOS'=>'BeOS'); 515 | 516 | foreach ($other_os as $other_os_va) 517 | { 518 | $k = key($other_os_va); 519 | $v = $other_os_va[$k]; 520 | 521 | if ($this->match_ua($v)) 522 | { 523 | $this->result_os_family = 'linux'; 524 | if ($k === 'AmigaOS') $this->result_os_family = 'amiga'; 525 | if ($k === 'Haiku' || $k === 'BeOS') $this->result_os_family = 'beos'; 526 | if ($k === 'OpenBSD' || $k === 'NetBSD' || $k === 'FreeBSD' || $k === 'SunOS' || $k === 'RISC OS') $this->result_os_family = 'unix'; 527 | $this->result_os_version = 0; 528 | $this->result_os_name = $k; 529 | $this->result_os_title = $k; 530 | $os_need_continue = FALSE; 531 | break; 532 | } 533 | } 534 | $other_os = NULL; 535 | } 536 | 537 | // End of desktop OS detection 538 | } 539 | 540 | /* 541 | ------------- 542 | Mobile OS 543 | ------------- 544 | */ 545 | 546 | if ($this->result_mobile == 1) 547 | { 548 | if ($this->result_os_type==='unknown') $this->result_os_type = 'mobile'; 549 | 550 | // Desktop Mode on generic mobile OS 551 | 552 | // Android Desktop Mode 553 | 554 | if ($os_need_continue && $this->result_browser_desktop_mode == 1 && $this->real_os_name === 'Android') 555 | { 556 | $this->result_os_version = 0; 557 | $this->result_os_name = 'Android'; 558 | $this->result_os_family = 'android'; 559 | $os_need_continue = FALSE; 560 | } 561 | 562 | // iOS Desktop Mode 563 | 564 | if ($os_need_continue && $this->result_browser_desktop_mode == 1 && $this->real_os_name === 'iOS') 565 | { 566 | $this->result_os_version = 0; 567 | $this->result_os_name = 'iOS'; 568 | $this->result_os_family = 'macintosh'; 569 | $os_need_continue = FALSE; 570 | } 571 | 572 | // WP Desktop Mode 573 | 574 | if ($os_need_continue && $this->result_browser_desktop_mode == 1 && $this->real_os_name === 'Windows Phone') 575 | { 576 | $this->result_os_version = 0; 577 | $this->result_os_name = 'Windows Phone'; 578 | $this->result_os_family = 'windows'; 579 | $os_need_continue = FALSE; 580 | } 581 | 582 | // Android OS 583 | 584 | if ($os_need_continue && $this->match_ua('Android') && !$this->match_ua('Windows Phone|Windows Mobile|Tizen')) 585 | { 586 | $this->result_os_version = 0; 587 | $this->result_os_name = 'Android'; 588 | $matches = $this->match_ua('/Android(?: |\-)([0-9]+\.[0-9]+)/'); 589 | $this->result_os_version = is_array($matches) ? (float)$matches[1] : 0; 590 | if (empty($this->result_os_version)) 591 | { 592 | $matches = $this->match_ua('/Android(?: |\-)(\d+)/'); 593 | $this->result_os_version = is_array($matches) ? (float)$matches[1] : 0; 594 | } 595 | $this->result_os_family = 'android'; 596 | $os_need_continue = FALSE; 597 | } 598 | 599 | // iOS OS 600 | 601 | if ($os_need_continue && $this->result_ios!=FALSE && !$this->match_ua('Windows Phone|Windows Mobile')) 602 | { 603 | $this->result_os_version = 0; 604 | $this->result_os_name = 'iOS'; 605 | $matches = $this->match_ua('/\sOS\s(\d+)[_.](\d+)/'); 606 | $version = is_array($matches) ? $matches[1] : 0; 607 | $version_minor = is_array($matches) ? $matches[2] : 0; 608 | if (!empty($version)) $this->result_os_version = floatval($version.'.'.$version_minor); 609 | $this->result_os_family = 'macintosh'; 610 | $os_need_continue = FALSE; 611 | } 612 | 613 | // WhatsApp Android / iOS 614 | 615 | if ($os_need_continue && $this->match_ua('WhatsApp/')) 616 | { 617 | $matches = $this->match_ua('/WhatsApp\/([.0-9]+)\s(A|i)$/'); 618 | $os_match = is_array($matches) ? $matches[2] : 0; 619 | 620 | if ($os_match === 'A') 621 | { 622 | $this->result_os_name = 'Android'; 623 | $this->result_os_family = 'android'; 624 | } 625 | 626 | if ($os_match === 'i') 627 | { 628 | $this->result_os_name = 'iOS'; 629 | $this->result_os_family = 'macintosh'; 630 | } 631 | } 632 | 633 | // Windows Phone OS, Tizen OS, Bada OS, Kindle OS, FIre OS, Java Platform 634 | 635 | if ($os_need_continue) 636 | { 637 | $os_list[] = array('Windows Phone'=>'/Phone(?: OS)? ([.0-9]+)/'); 638 | $os_list[] = array('Windows Mobile'=>'/Windows Mobile ([.0-9]+)/'); 639 | $os_list[] = array('Windows Mobile'=>'Windows Mobile'); 640 | $os_list[] = array('Windows CE'=>'Windows CE'); 641 | $os_list[] = array('Firefox OS'=>'/Mozilla\/5\.0\s\((?:Mobile|Tablet);(?:.*;)?\srv:[.0-9]+\)\sGecko\/[.0-9]+\sFirefox\/[.0-9]+$/'); 642 | $os_list[] = array('Tizen'=>'/Tizen[\/\s]([.0-9]+)/'); 643 | $os_list[] = array('Bada'=>'/Bada[;\/]([.0-9]+)/'); 644 | $os_list[] = array('Kindle'=>'/Kindle\/([0-9]+\.[0-9]+)/'); 645 | $os_list[] = array('Fire OS'=>'KFJW|Silk/'); 646 | $os_list[] = array('Java Platform'=>'/MIDP\-([0-9]+\.[0-9]+)/'); 647 | $os_list[] = array('Java Platform'=>'/MIDP/'); 648 | $os_list[] = array('MAUI Platform'=>'/MAUI\s|\sMAUI/'); 649 | 650 | foreach($os_list as $os_list_va) 651 | { 652 | $k = key($os_list_va); 653 | $v = $os_list_va[$k]; 654 | 655 | $matches = $this->match_ua($v); 656 | if ($matches) 657 | { 658 | $this->result_os_family = 'linux'; 659 | if (strpos($k, 'Windows') !== FALSE) $this->result_os_family = 'windows'; 660 | $this->result_os_name = $k; 661 | $this->result_os_version = is_array($matches) ? (float)$matches[1] : 0; 662 | $os_need_continue = FALSE; 663 | 664 | // J2ME/MIDP or MAUI 665 | 666 | if (strpos($k, 'Java Platform') !== FALSE || strpos($k, 'MAUI Platform') !== FALSE) 667 | { 668 | $this->result_os_family = 'unknown'; 669 | $os_need_continue = TRUE; 670 | } 671 | break; 672 | } 673 | } 674 | $os_list = NULL; 675 | } 676 | 677 | // Other Mobile OS(es) 678 | 679 | if ($os_need_continue) 680 | { 681 | $other_os = array(); 682 | 683 | $other_os[] = array('Android'=>'CrKey armv'); 684 | $other_os[] = array('Android'=>'SpreadTrum;'); 685 | $other_os[] = array('BlackBerry'=>'BlackBerry'); 686 | $other_os[] = array('BlackBerry'=>'BB10;'); 687 | $other_os[] = array('BlackBerry'=>'RIM Tablet'); 688 | $other_os[] = array('Symbian'=>'Symbian'); 689 | $other_os[] = array('Symbian'=>'(Series'); 690 | $other_os[] = array('Symbian'=>'SymbOS'); 691 | $other_os[] = array('WatchOS'=>'Watch'); 692 | $other_os[] = array('KaiOS'=>'KAIOS'); 693 | $other_os[] = array('RemixOS'=>'Remix Mini'); 694 | $other_os[] = array('RemixOS'=>'RemixOS'); 695 | $other_os[] = array('Sailfish OS'=>'Sailfish'); 696 | $other_os[] = array('LiveArea'=>'PlayStation Vita'); 697 | $other_os[] = array('PalmOS'=>'PalmOS'); 698 | $other_os[] = array('PalmOS'=>'PalmSource'); 699 | $other_os[] = array('Maemo'=>'Maemo'); 700 | $other_os[] = array('PlayStation Platform'=>'PlayStation'); 701 | $other_os[] = array('PlayStation Platform'=>'PLAYSTATION'); 702 | 703 | foreach ($other_os as $other_os_va) 704 | { 705 | $k = key($other_os_va); 706 | $v = $other_os_va[$k]; 707 | 708 | if ($this->match_ua($v)) 709 | { 710 | if ($k === 'Android') $this->result_os_family = 'android'; 711 | if ($k === 'BlackBerry') $this->result_os_family = 'blackberry'; 712 | if ($k === 'Symbian') $this->result_os_family = 'symbian'; 713 | if ($k === 'WatchOS') $this->result_os_family = 'macintosh'; 714 | if ($k === 'Sailfish OS' || $k === 'KaiOS' || $k === 'Maemo') $this->result_os_family = 'linux'; 715 | if ($k === 'RemixOS') $this->result_os_family = 'android'; 716 | if ($k === 'LiveArea') $this->result_os_family = 'livearea'; 717 | if ($k === 'PalmOS') $this->result_os_family = 'palm'; 718 | if ($k === 'PlayStation Platform') $this->result_os_family = 'unix'; 719 | $this->result_os_version = 0; 720 | $this->result_os_name = $k; 721 | $this->result_os_title = $k; 722 | $os_need_continue = FALSE; 723 | break; 724 | } 725 | } 726 | 727 | $other_os = NULL; 728 | } 729 | 730 | // End of mobile OS detection 731 | } 732 | 733 | // Other mixed-type linux-family OS(es) 734 | 735 | if ($this->get_mode !== 'browser' && ($this->result_os_family === 'linux' || $this->result_os_family === 'unknown')) 736 | { 737 | $other_os = array(); 738 | 739 | $other_os[] = array('WebOS'=>'hpwOS'); 740 | $other_os[] = array('WebOS'=>'Web0S'); 741 | $other_os[] = array('WebOS'=>'WebOS'); 742 | $other_os[] = array('WebOS'=>'webOS'); 743 | 744 | foreach ($other_os as $other_os_va) 745 | { 746 | $k = key($other_os_va); 747 | $v = $other_os_va[$k]; 748 | 749 | if ($this->match_ua($v)) 750 | { 751 | $this->result_os_family = 'linux'; 752 | $this->result_os_type = 'mixed'; 753 | $this->result_os_version = 0; 754 | $this->result_os_name = $k; 755 | $this->result_os_title = $k; 756 | break; 757 | } 758 | } 759 | $other_os = NULL; 760 | } 761 | 762 | // Darwin (MacOS and iOS) 763 | 764 | if ($os_need_continue && $this->match_ua(' Darwin') && !$this->match_ua('X11;')) 765 | { 766 | $this->result_os_family = 'macintosh'; 767 | 768 | if ($this->match_ua('x86_64|i386|Mac')) 769 | { 770 | $this->result_os_type = 'desktop'; 771 | $this->result_os_name = 'MacOS'; 772 | } 773 | else 774 | { 775 | $this->result_os_type = 'mobile'; 776 | $this->result_mobile = 1; 777 | $this->result_os_name = 'iOS'; 778 | $this->result_ios = TRUE; 779 | } 780 | 781 | $this->result_os_version = 0; 782 | $darwin_os_version = 0; 783 | 784 | $matches = $this->match_ua('/\sDarwin(\s|\/)([0-9]+\.[0-9]+)/'); 785 | if (!empty($matches[2])) $darwin_os_version = (float)$matches[2]; 786 | 787 | $darwin_macos_map = array('1.3'=>'0', '1.4'=>'1', '5.1'=>'1', '5.5'=>'1', '6.0'=>'2', '6.8'=>'2', '7.0'=>'3', '7.9'=>'3', '8.0'=>'4', '8.1'=>'4', '9.0'=>'5', '9.8'=>'5', '10.0'=>'6', '10.8'=>'6', '11.0'=>'7', '11.4'=>'7', '12.0'=>'8', '12.6'=>'8', '13.0'=>'9', '13.4'=>'9', '14.0'=>'10', '14.5'=>'10', '15.0'=>'11', '15.6'=>'11', '16.0'=>'12', '16.6'=>'12', '17.0'=>'13', '17.7'=>'13', '18.0'=>'14', '18.2'=>'14', '19.0'=>'15', '19.6'=>'15', '20.0'=>'16', '20.6'=>'16', '21.0'=>'17', '21.6'=>'17', '22.0'=>'18', '22.3'=>'18'); 788 | $darwin_ios_map = array('9.0'=>'1', '9.8'=>'1', '10.0'=>'4', '10.8'=>'4', '11.0'=>'5', '11.4'=>'5', '12.0'=>'6', '13.0'=>'7', '14.0'=>'8', '15.0'=>'9', '15.6'=>'9', '16.0'=>'10', '16.6'=>'10', '17.0'=>'11', '17.7'=>'11', '18.0'=>'12', '18.2'=>'12', '19.0'=>'13', '19.6'=>'13', '20.0'=>'14', '20.6'=>'14', '21.0'=>'15', '21.6'=>'15', '22.0'=>'16', '22.3'=>'16'); 789 | 790 | if ($this->result_os_name === 'MacOS') $darwin_map = $darwin_macos_map; 791 | else $darwin_map = $darwin_ios_map; 792 | 793 | foreach ($darwin_map as $k=>$v) 794 | { 795 | $darwin_map_min[$k] = abs($k-$darwin_os_version); 796 | } 797 | 798 | asort($darwin_map_min); 799 | $darwin_map_key = key($darwin_map_min); 800 | $this->result_os_version = $darwin_map[$darwin_map_key]; 801 | 802 | if ($this->result_os_name === 'MacOS') 803 | { 804 | $this->result_os_version = $this->macos_codename($darwin_map[$darwin_map_key]); 805 | if (!empty($this->result_os_version)) $this->result_os_title = 'MacOS '.$this->result_os_version; 806 | else $this->result_os_title = 'MacOS'; 807 | } 808 | 809 | $darwin_map = NULL; 810 | $darwin_map_min = NULL; 811 | $darwin_macos_map = NULL; 812 | $darwin_ios_map = NULL; 813 | $os_need_continue = FALSE; 814 | } 815 | 816 | // Set OS title and type 817 | 818 | if ($this->get_mode !== 'browser' && $this->result_os_name !== 'MacOS') 819 | { 820 | if (!empty($this->result_os_version)) $this->result_os_title = $this->result_os_name.' '.$this->result_os_version; 821 | else 822 | { 823 | if ($this->result_os_name !== 'Windows') $this->result_os_title = $this->result_os_name; 824 | else $this->result_os_title = $this->result_os_name.' (unknown version)'; 825 | } 826 | if (strpos($this->result_os_name, 'unknown') !== false) $this->result_os_type = 'unknown'; 827 | if ($this->result_os_version == NULL) $this->result_os_version = 0; 828 | } 829 | 830 | /* 831 | --------------------- 832 | Detect 64bits mode 833 | --------------------- 834 | */ 835 | 836 | if ($this->result_os_name === 'iOS' && $this->result_os_version >= 11) $this->result_64bits_mode = 1; 837 | if ($this->result_os_name === 'MacOS' && $this->macos_version_minor >= 8) $this->result_64bits_mode = 1; 838 | 839 | if ($this->result_64bits_mode == 0) 840 | { 841 | if ($this->match_ua('64') && $this->match_ua('x64;|x86_64|x86-64|arm64|arm_64|aarch64|Linux x64|mips64|amd64|AMD64|ia64|IRIX64|ppc64|sparc64|x64_64')) 842 | { 843 | $this->result_64bits_mode = 1; 844 | } 845 | } 846 | 847 | if ($this->result_os_name === 'Android' && $this->result_browser_desktop_mode == 1) $this->result_64bits_mode = 0; 848 | if ($this->result_64bits_mode == 1 && $this->match_ua('86') && $this->match_ua('i386|i686')) $this->result_64bits_mode = 0; 849 | 850 | // If mode 'os' only 851 | 852 | if ($this->get_mode === 'os') return NULL; 853 | 854 | /* 855 | ------------------- 856 | BROWSER DETECTION 857 | ------------------- 858 | 859 | --------------------- 860 | Mixed-type Browsers 861 | --------------------- 862 | */ 863 | 864 | $browser_need_continue = TRUE; 865 | if ($this->get_mode === 'device') $browser_need_continue = FALSE; 866 | 867 | // Chrome / Chromium 868 | 869 | if ($browser_need_continue && $this->match_ua('Chrome/|Chromium/|CriOS/|CrMo/')) 870 | { 871 | $this->result_browser_version = 0; 872 | $matches = $this->match_ua('/(Chrome|Chromium|CriOS|CrMo)\/([0-9]+)\.?/'); 873 | $this->result_browser_name = 'Chrome'; 874 | if (!empty($matches[1]) && $matches[1]==='Chromium') $this->result_browser_name = 'Chromium'; 875 | if (!empty($matches[2])) $this->result_browser_version = (int)$matches[2]; 876 | $this->result_browser_chromium_version = $this->result_browser_version; 877 | if ($this->match_ua('CriOS/')) $this->result_browser_chromium_version = 0; 878 | if ($this->match_ua('/Gecko\)\s(Chrome|CrMo)\/(\d+\.\d+\.\d+\.\d+)\s(?:Mobile)?(?:\/[.0-9A-Za-z]+\s|\s)?Safari\/[.0-9]+$/') && !$this->match_ua('SalamWeb| Valve | GOST')) $this->result_browser_chrome_original = 1; 879 | } 880 | 881 | // Firefox 882 | 883 | if ($browser_need_continue && $this->result_browser_chromium_version == 0 && $this->match_ua('Firefox/') && !$this->match_ua('Focus/|FxiOS|Waterfox|Ghostery:')) 884 | { 885 | $this->result_browser_version = 0; 886 | $matches = $this->match_ua('/Firefox\/([0-9]+)\./'); 887 | $this->result_browser_name = 'Firefox'; 888 | if (!empty($matches[1])) $this->result_browser_version = (int)$matches[1]; 889 | if($this->match_ua('/\)\sGecko\/[.0-9]+\sFirefox\/[.0-9]+$/')) $this->result_browser_firefox_original = 1; 890 | } 891 | 892 | // Cross-device browsers (Yandex, Edge, Firefox, Opera, Puffin, Vivaldi, QQ Browser, Whale, Brave etc) 893 | 894 | if ($browser_need_continue && $this->result_browser_chrome_original == 0 && $this->result_browser_firefox_original == 0) 895 | { 896 | $browser_list[] = array('Yandex Browser', 'YaBrowser', '/YaBrowser\/([0-9]+\.[0-9]+)/', '1', 'YaApp_'); 897 | $browser_list[] = array('Edge', 'Edg', '/Edg(|e|A|iOS)\/([0-9]+)\./', '2', ''); 898 | $browser_list[] = array('Opera', ' OPR/', '/OPR\/(\d+)/', '1', 'Opera Mini|OPiOS|OPT/|OPRGX/|AlohaBrowser'); 899 | $browser_list[] = array('Opera', 'Opera', '/Opera.*Version\/([0-9]+\.[0-9]+)/', '1', 'Opera Mini|OPiOS|OPT/|InettvBrowser/'); 900 | $browser_list[] = array('Opera', 'Opera', '/Opera(\s|\/)([0-9]+\.[0-9]+)/', '2', 'Opera Mini|OPiOS|OPT/|InettvBrowser/'); 901 | $browser_list[] = array('UC Browser', 'UBrowser|UCBrowser|UCMini', '/(UBrowser|UCBrowser|UCMini)\/([0-9]+\.[0-9]+)/', '2', 'UCTurbo|AliApp'); 902 | $browser_list[] = array('UC Browser Turbo', 'UCTurbo/', '/UCTurbo\/([0-9]+\.[0-9]+)/', '1', ''); 903 | $browser_list[] = array('Puffin', 'Puffin/', '/Puffin\/([0-9]+\.[0-9]+)/', '1', ''); 904 | $browser_list[] = array('Vivaldi', 'Vivaldi/', '/Vivaldi\/([0-9]+\.[0-9]+)/', '1', ''); 905 | $browser_list[] = array('QQ Browser', 'QQBrowser/', '/QQBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 906 | $browser_list[] = array('Coc Coc', 'coc_coc_browser', '/coc_coc_browser\/([0-9]+)/', '1', ''); 907 | $browser_list[] = array('Whale', 'Whale/', '/Whale\/([0-9]+\.[0-9]+)/', '1', 'NAVER(inapp;'); 908 | $browser_list[] = array('Brave', 'Brave', '/Brave(?: Chrome)?\/([0-9]+)/', '1', ''); 909 | $browser_list[] = array('Maxthon', 'Maxthon/', '/Maxthon\/([0-9]+\.[0-9]+)/', '1', ''); 910 | $browser_list[] = array('Maxthon', 'MxBrowser/', '/MxBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 911 | $browser_list[] = array('2345 Explorer', '2345Explorer|2345Browser', '/(2345Explorer|2345Browser)(?: |\/)?([0-9]+\.[0-9]+)/', '2', ''); 912 | $browser_list[] = array('IceCat', 'IceCat/', '/IceCat\/([0-9]+)/', '1', ''); 913 | $browser_list[] = array('Lunascape', 'Lunascape', '/Lunascape(?: |\/)?([0-9]+\.[0-9]+)/', '1', ''); 914 | $browser_list[] = array('Seznam Browser', 'Seznam.cz/|SznProhlizec/', '/(Seznam\.cz|SznProhlizec)\/([0-9]+\.[0-9]+)/', '2', ''); 915 | $browser_list[] = array('Sleipnir', 'Sleipnir/', '/Sleipnir\/([0-9]+\.[0-9]+)/', '1', ''); 916 | $browser_list[] = array('Sputnik', 'SputnikBrowser/', '/SputnikBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 917 | $browser_list[] = array('Oculus Browser', 'OculusBrowser/', '/OculusBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 918 | $browser_list[] = array('PaleMoon', 'PaleMoon', '/PaleMoon\/([0-9]+\.[0-9]+)/', '1', ''); 919 | $browser_list[] = array('SalamWeb', 'SalamWeb|Salam Browser', '/SalamWeb\/([0-9]+\.[0-9]+)/', '1', ''); 920 | $browser_list[] = array('Swing', 'Swing/|Swing(And)/', '/Swing(?:\(And\))?\/([0-9]+\.[0-9]+)/', '1', ''); 921 | $browser_list[] = array('Safe Exam Browser', 'SEB/', '/SEB\/([0-9]+\.[0-9]+)/', '1', ''); 922 | $browser_list[] = array('Colibri', 'Colibri/', '/Colibri\/([0-9]+\.[0-9]+)/', '1', ''); 923 | $browser_list[] = array('Opera GX', 'OPRGX', '/OPRGX\/([0-9]+)/', '1', ''); 924 | $browser_list[] = array('Opera GX', 'OPX/', '/OPX\/([0-9]+\.[0-9]+)/', '1', ''); 925 | $browser_list[] = array('Xvast', 'Xvast/', '/Xvast\/([0-9]+\.[0-9]+)/', '1', ''); 926 | $browser_list[] = array('Atom', 'Atom/', '/Atom\/([0-9]+\.[0-9]+)/', '1', ''); 927 | $browser_list[] = array('NetCast', 'SmartTV/', '/SmartTV\/([0-9]+)/', '1', ''); 928 | $browser_list[] = array('LG Browser', ' LG Browser/', '/\sLG\sBrowser\/([0-9]+)/', '1', ''); 929 | $browser_list[] = array('Ghostery Browser', 'Ghostery:', '/Ghostery\:([0-9]+\.[0-9]+)/', '1', ''); 930 | $browser_list[] = array('Aloha Browser', 'AlohaBrowser/', '/AlohaBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 931 | $browser_list[] = array('Lenovo Browser', 'SLBrowser/', '/SLBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 932 | $browser_list[] = array('Samsung Browser TV', '/SamsungBrowser\/[.0-9]+\sTV\s/', '/SamsungBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 933 | $browser_list[] = array('WeChat App', 'MicroMessenger/', '/MicroMessenger\/([0-9]+\.[0-9]+)/', '1', ''); 934 | $browser_list[] = array('WKWebView', '/Intel\sMac\sOS\sX\s\d+.*\)\sAppleWebKit\/[.0-9]+.*Gecko\)$/', 'AppleWebKit', '1', ''); 935 | $browser_list[] = array('Sber Browser', 'SberBrowser/', '/SberBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 936 | 937 | foreach($browser_list as $browser_list_va) 938 | { 939 | $match = $browser_list_va[1]; 940 | $match_exclude = $browser_list_va[4]; 941 | 942 | if ($this->match_ua($match) && !$this->match_ua($match_exclude)) 943 | { 944 | $this->result_browser_version = 0; 945 | $this->result_browser_name = $browser_list_va[0]; 946 | $matches = $this->match_ua($browser_list_va[2]); 947 | $matches_n = intval($browser_list_va[3]); 948 | $this->result_browser_version = is_array($matches) ? (float)$matches[$matches_n] : 0; 949 | if (!empty($this->result_browser_version)) 950 | { 951 | $browser_need_continue = FALSE; 952 | break; 953 | } 954 | } 955 | } 956 | 957 | $browser_list = NULL; 958 | } 959 | 960 | // Gecko engine detection 961 | 962 | if ($this->get_mode !== 'device' && $this->result_browser_chromium_version == 0 && $this->match_ua('Gecko/|ArtisBrowser/') && ($this->match_ua('/\srv:[.0-9a-z]+(?:\;\s.*|)\)\sGecko\/[.0-9]+\s/') || $this->match_ua('QwantMobile/|ArtisBrowser/'))) 963 | { 964 | $this->result_browser_gecko_version = 0; 965 | $match = $this->match_ua('/\srv:([0-9]+\.[0-9]+)(?:[.0-9a-z]+)?(?:\;\s.*|)\)\sGecko\/[.0-9]+\s/'); 966 | 967 | if (is_array($match)) 968 | { 969 | if ($match[1]>=5) $match[1] = intval($match[1]); 970 | else $match[1] = (float)$match[1]; 971 | } 972 | 973 | if (!empty($match[1])) $this->result_browser_gecko_version = $match[1]; 974 | else 975 | { 976 | $match = $this->match_ua('/\sGecko\/([.0-9]+)\s.*QwantMobile\/[.0-9]+$/'); 977 | if (!empty($match[1])) $this->result_browser_gecko_version = intval($match[1]); 978 | else 979 | { 980 | $match = $this->match_ua('/\srv:([0-9]+\.[0-9]+)\)\s.*ArtisBrowser\/[.0-9]+$/'); 981 | if (!empty($match[1])) $this->result_browser_gecko_version = intval($match[1]); 982 | } 983 | } 984 | 985 | // Gecko >= 109 issue 986 | 987 | if ($this->result_browser_gecko_version >= 109 && $this->result_browser_gecko_version < 120) 988 | { 989 | $match = $this->match_ua('/\srv:[.0-9a-z]+(?:\;\s.*|)\)\sGecko\/[.0-9]+\s.*(?:Firefox|MaxBrowser)\/([0-9]+)\./'); 990 | if (!empty($match[1])) $this->result_browser_gecko_version = intval($match[1]); 991 | } 992 | } 993 | 994 | // WebKit engine detection 995 | 996 | if ($this->get_mode !== 'device' && $this->result_browser_chromium_version == 0 && $this->result_browser_gecko_version == 0 && $this->matchi_ua('AppleWebKit/')) 997 | { 998 | $this->result_browser_webkit_version = 0; 999 | $match = $this->matchi_ua('/AppleWebKit\/([0-9]+\.[0-9]+)/'); 1000 | if (!empty($match[1])) $this->result_browser_webkit_version = (float)$match[1]; 1001 | } 1002 | 1003 | /* 1004 | ------------------ 1005 | Desktop Browsers 1006 | ------------------ 1007 | */ 1008 | 1009 | if ($browser_need_continue && $this->result_browser_chrome_original==0 && $this->result_browser_firefox_original==0 && $this->result_mobile == 0) 1010 | { 1011 | // Safari 1012 | 1013 | $browser_list[] = array('Safari', '/AppleWebKit\/[.0-9]+.*Gecko\)\sSafari\/[.0-9A-Za-z]+$/', '/Safari\/(\d+)/', '1', 'Version/'); 1014 | $browser_list[] = array('Safari', '/Version\/([0-9]+\.[0-9]+).*Safari/', '/Version\/([0-9]+\.[0-9]+).*Safari/', '1', 'Epiphany|Arora/|Midori|midori|SlimBoat|Roccat'); 1015 | 1016 | // IE 1017 | 1018 | $browser_list[] = array('Internet Explorer', 'MSIE', '/MSIE(?:\s|)([0-9]+)/', '1', 'Opera|IEMobile|Trident/'); 1019 | $browser_list[] = array('Internet Explorer', 'Trident/', '/Trident\/([0-9]+)/', '1', 'Opera|IEMobile'); 1020 | 1021 | // Chromium based browsers 1022 | 1023 | $browser_list[] = array('Avast Browser', 'Avast/', '/Avast\/([0-9]+)/', '1', ''); 1024 | $browser_list[] = array('AVG Browser', 'AVG/', '/AVG\/([0-9]+)/', '1', ''); 1025 | $browser_list[] = array('CCleaner Browser', 'CCleaner/', '/CCleaner\/([0-9]+)/', '1', ''); 1026 | $browser_list[] = array('Comodo Dragon', 'Dragon/', '/Dragon\/([0-9]+)/', '1', 'IceDragon'); 1027 | $browser_list[] = array('Iridium', 'Iridium/', '/Iridium\/.*Safari.*Chrome\/([0-9]+)/', '1', ''); 1028 | $browser_list[] = array('Maxthon Nitro', 'MxNitro|mxnitro', '/(MxNitro|mxnitro)\/([0-9]+\.[0-9]+)/', '2', ''); 1029 | $browser_list[] = array('Iron', ' Iron ', '/Chrome\/([0-9]+)/', '1', ''); 1030 | $browser_list[] = array('Iron', 'Iron/', '/Iron\/([0-9]+)/', '1', ''); 1031 | $browser_list[] = array('Hola Browser', 'Hola/', '/Hola\/([0-9]+\.[0-9]+)/', '1', ''); 1032 | $browser_list[] = array('Sogou Explorer', '/Chrome.*Safari.*SE\s.*MetaSr/', '/Chrome\/([0-9]+)/', '1', ''); 1033 | $browser_list[] = array('360 browser', 'QIHU 360', '/Chrome\/([0-9]+)/', '1', ''); 1034 | $browser_list[] = array('Slimjet', 'Slimjet/', '/Slimjet\/([0-9]+)/', '1', ''); 1035 | $browser_list[] = array('FreeU', 'FreeU|Freeu', '/(FreeU|Freeu)\/([0-9]+)/', '2', ''); 1036 | $browser_list[] = array('Kinza', 'Kinza/', '/Kinza\/([0-9]+\.[0-9]+)/', '1', ''); 1037 | $browser_list[] = array('Station', 'Station/', '/Station\/([0-9]+\.[0-9]+)/', '1', ''); 1038 | $browser_list[] = array('Superbird', 'Superbird|SuperBird', '/(Superbird|SuperBird)\/([0-9]+)/', '2', ''); 1039 | $browser_list[] = array('Polypane', 'Polypane/', '/Polypane\/([0-9]+\.[0-9]+)/', '1', ''); 1040 | $browser_list[] = array('OhHai Browser', 'OhHaiBrowser/', '/OhHaiBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1041 | $browser_list[] = array('Sizzy', 'Sizzy', '/Sizzy\/([0-9]+\.[0-9]+)/', '1', ''); 1042 | $browser_list[] = array('AOL Desktop', 'ADG/', '/ADG\/([0-9]+\.[0-9]+)/', '1', ''); 1043 | $browser_list[] = array('Elements Browser', 'Elements Browser', '/Elements\sBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1044 | $browser_list[] = array('115 Browser', '115Browser', '/115Browser\/([0-9]+\.[0-9]+)/', '1', ''); 1045 | $browser_list[] = array('Falkon', 'Falkon/', '/Falkon\/([0-9]+\.[0-9]+)/', '1', ''); 1046 | $browser_list[] = array('AOL Shield Pro', 'AOLShield', '/AOLShield\/([0-9]+)/', '1', ''); 1047 | $browser_list[] = array('Google Earth', 'Google Earth', '/Google Earth(?:|\sPro)\/([0-9]+\.[0-9]+)/', '1', ''); 1048 | $browser_list[] = array('Chedot', 'Chedot/', '/Chedot\/([0-9]+\.[0-9]+)/', '1', ''); 1049 | $browser_list[] = array('SlimBoat', 'SlimBoat/', '/SlimBoat\/([0-9]+\.[0-9]+)/', '1', ''); 1050 | $browser_list[] = array('Rambler Browser', 'Nichrome/', '/Chrome\/([0-9]+)/', '1', ''); 1051 | $browser_list[] = array('Beaker Browser', 'BeakerBrowser/', '/BeakerBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1052 | $browser_list[] = array('Amigo', 'Amigo/', '/Amigo\/([0-9]+\.[0-9]+)/', '1', ''); 1053 | $browser_list[] = array('Opera Neon', ' MMS/', '/\sMMS\/([0-9]+\.[0-9]+)/', '1', ''); 1054 | $browser_list[] = array('SmartTV Browser', 'Thano/', '/Thano\/([0-9]+\.[0-9]+)/', '1', ''); 1055 | $browser_list[] = array('Biscuit', 'Biscuit/', '/Biscuit\/([0-9]+\.[0-9]+)/', '1', ''); 1056 | $browser_list[] = array('Chromium GOST', 'Chromium GOST', '/Chrome\/([0-9]+\.[0-9]+)/', '1', ''); 1057 | $browser_list[] = array('Dashob', 'Dashob/', '/Dashob\/([0-9]+\.[0-9]+)/', '1', ''); 1058 | $browser_list[] = array('Dezor', 'Dezor/', '/Dezor\/([0-9]+\.[0-9]+)/', '1', ''); 1059 | $browser_list[] = array('Duoyu Browser', 'duoyu_business/', '/duoyu_business\/([0-9]+\.[0-9]+)/', '1', ''); 1060 | $browser_list[] = array('iTop Browser', ' iTop', '/Chrome\/([0-9]+\.[0-9]+)*.+\siTop$/', '1', ''); 1061 | $browser_list[] = array('Polarity', 'Polarity/', '/Polarity\/([0-9]+\.[0-9]+)/', '1', ''); 1062 | $browser_list[] = array('Sielo', 'Sielo/', '/Sielo\/([0-9]+\.[0-9]+)/', '1', ''); 1063 | $browser_list[] = array('Norton Browser', 'Norton/', '/Norton\/([0-9]+)/', '1', ''); 1064 | $browser_list[] = array('Avira Browser', 'Avira/', '/Avira\/([0-9]+)/', '1', ''); 1065 | 1066 | // Webkit, Gecko and other engine based browsers 1067 | 1068 | $browser_list[] = array('Cyberfox', 'Cyberfox/', '/Cyberfox\/([0-9]+)/', '1', ''); 1069 | $browser_list[] = array('SeaMonkey', 'SeaMonkey/', '/SeaMonkey\/([0-9]+\.[0-9]+)/', '1', ''); 1070 | $browser_list[] = array('K-Meleon', 'K-Meleon', '/K\-Meleon\/([0-9]+\.[0-9]+)/', '1', ''); 1071 | $browser_list[] = array('Iceweasel', '/[iI]ce[wW]easel/', '/[iI]ce[wW]easel/', '1', ''); 1072 | $browser_list[] = array('IceApe', 'Iceape/', '/Iceape\/([0-9]+\.[0-9]+)/', '1', ''); 1073 | $browser_list[] = array('Comodo Ice Dragon', 'IceDragon/', '/IceDragon\/([0-9]+\.[0-9]+)/', '1', ''); 1074 | $browser_list[] = array('QtWeb', 'QtWeb Internet Browser/', '/QtWeb\sInternet\sBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1075 | $browser_list[] = array('QtWebEngine', 'QtWebEngine', '/QtWebEngine\/([0-9]+\.[0-9]+)/', '1', 'Konqueror'); 1076 | $browser_list[] = array('Qt', 'Qt/', '/Qt\/([0-9]+\.[0-9]+)/', '1', ''); 1077 | $browser_list[] = array('WebKitGTK', 'WebKitGTK+/', '/WebKitGTK\+\/([0-9]+\.[0-9]+)/', '1', ''); 1078 | $browser_list[] = array('Konqueror', 'Konqueror', '/Konqueror\/([0-9]+\.[0-9]+)/', '1', 'QtWebEngine'); 1079 | $browser_list[] = array('Konqueror', 'konqueror', '/konqueror\/([0-9]+\.[0-9]+)/', '1', 'QtWebEngine'); 1080 | $browser_list[] = array('Konqueror', 'Konqueror', '/\sQtWebEngine\/([0-9]+\.[0-9]+)(|[.0-9]+)\sChrome\/[.0-9]+.*\sSafari\/[.0-9]+.*Konqueror\s/', '1', ''); 1081 | $browser_list[] = array('Epiphany', 'Epiphany', '/Epiphany\/([0-9]+\.[0-9]+)/', '1', ''); 1082 | $browser_list[] = array('OmniWeb', 'OmniWeb/', '/OmniWeb\//', '1', ''); 1083 | $browser_list[] = array('iCab', 'iCab', '/iCab(\s|\/)([0-9]+\.[0-9]+)/', '2', ''); 1084 | $browser_list[] = array('Camino', 'Camino/', '/Camino\/([0-9]+\.[0-9]+)/', '1', ''); 1085 | $browser_list[] = array('Midori', 'Midori|midori', '/Midori\/([.0-9]+)/', '1', ''); 1086 | $browser_list[] = array('Otter', 'Otter/', '/Otter\/([0-9]+\.[0-9]+)/', '1', ''); 1087 | $browser_list[] = array('Kazehakase', 'Kazehakase/', '/Kazehakase\/([0-9]+\.[0-9]+)/', '1', ''); 1088 | $browser_list[] = array('QupZilla', 'QupZilla/', '/QupZilla\/([0-9]+\.[0-9]+)/', '1', ''); 1089 | $browser_list[] = array('Waterfox', 'Waterfox/', '/Waterfox\/([0-9]+)/', '1', ''); 1090 | $browser_list[] = array('Waterfox', 'Waterfox', '/Firefox\/([0-9]+)/', '1', ''); 1091 | $browser_list[] = array('Basilisk', 'Basilisk/', '/\srv:([0-9]+\.[0-9]+)/', '1', ''); 1092 | $browser_list[] = array('Dooble', 'Dooble/', '/Dooble\/([0-9]+\.[0-9]+)/', '1', ''); 1093 | $browser_list[] = array('Fluid', 'Fluid/', '/Fluid\/([0-9]+\.[0-9]+)/', '1', ''); 1094 | $browser_list[] = array('Arora', 'Arora/', '/Arora\/([0-9]+\.[0-9]+)/', '1', ''); 1095 | $browser_list[] = array('Artis Browser', 'ArtisBrowser/', '/ArtisBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1096 | $browser_list[] = array('Steam Client', ' Valve ', '/Valve\s(|Steam\s)Client/', '1', 'Tenfoot'); 1097 | $browser_list[] = array('Steam Overlay', ' Valve ', '/Valve\sSteam\sGameOverlay/', '1', 'Tenfoot|Client/'); 1098 | $browser_list[] = array('Rekonq', ' rekonq', '/rekonq\/([0-9]+\.[0-9]+)/', '1', ''); 1099 | $browser_list[] = array('Odyssey Web Browser', 'Odyssey Web Browser', '/OWB\/([0-9]+\.[0-9]+)/', '1', ''); 1100 | $browser_list[] = array('Safari SDK', '/^Safari\/[.0-9]+\sCFNetwork\/[.0-9]+\sDarwin\/[.0-9]+/', '/Safari\//', '1', ''); 1101 | $browser_list[] = array('Internet TV Browser', 'InettvBrowser/', '/InettvBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1102 | $browser_list[] = array('Firefox', 'BonEcho/', '/BonEcho\/([0-9]+)/', '1', ''); 1103 | $browser_list[] = array('Firefox', 'GranParadiso/', '/GranParadiso\/([0-9]+)/', '1', ''); 1104 | $browser_list[] = array('Firefox', 'Shiretoko/', '/Shiretoko\/([0-9]+)/', '1', ''); 1105 | $browser_list[] = array('Firefox', 'Namoroka/', '/Namoroka\/([0-9]+)/', '1', ''); 1106 | $browser_list[] = array('iTunes App', 'iTunes/', '/iTunes\/([0-9]+\.[0-9]+)/', '1', ''); 1107 | $browser_list[] = array('Mypal Browser', 'Mypal/', '/Mypal\/([0-9]+\.[0-9]+)/', '1', ''); 1108 | $browser_list[] = array('Mercury', 'Mercury/', '/Firefox\/([0-9]+\.[0-9]+)/', '1', ''); 1109 | $browser_list[] = array('Arctic Fox', 'ArcticFox/', '/ArcticFox\/([0-9]+\.[0-9]+)/', '1', ''); 1110 | $browser_list[] = array('Roccat', ' Roccat/', '/Roccat\/([0-9]+\.[0-9]+)/', '1', ''); 1111 | $browser_list[] = array('Lunascape', ' lswebkit ', ' lswebkit ', '1', ''); 1112 | 1113 | foreach($browser_list as $browser_list_va) 1114 | { 1115 | $match = $browser_list_va[1]; 1116 | $match_exclude = $browser_list_va[4]; 1117 | 1118 | if ($this->match_ua($match) && !$this->match_ua($match_exclude)) 1119 | { 1120 | $this->result_browser_version = 0; 1121 | $this->result_browser_name = $browser_list_va[0]; 1122 | $matches = $this->match_ua($browser_list_va[2]); 1123 | $matches_n = intval($browser_list_va[3]); 1124 | $this->result_browser_version = is_array($matches) ? (float)$matches[$matches_n] : 0; 1125 | 1126 | // Gnome Web browser detection on Linux/Unix OS 1127 | 1128 | if ($this->result_browser_name === 'Safari' && ($this->result_os_family === 'linux' || $this->result_os_family === 'unix')) 1129 | { 1130 | $this->result_browser_name = 'Gnome Web'; 1131 | } 1132 | 1133 | // Safari old version conversion 1134 | 1135 | if ($match === '/AppleWebKit\/[.0-9]+.*Gecko\)\sSafari\/[.0-9A-Za-z]+$/') 1136 | { 1137 | $ev = intval($this->result_browser_version); 1138 | if (!empty($ev)) $this->result_browser_version = 1; 1139 | if ($ev>400) $this->result_browser_version = 2; 1140 | if ($ev>500) $this->result_browser_version = 3; 1141 | if ($ev>527) $this->result_browser_version = 4; 1142 | if ($ev>532) $this->result_browser_version = 5; 1143 | if ($ev>535) $this->result_browser_version = 6; 1144 | $this->result_browser_safari_original = 1; 1145 | } 1146 | 1147 | // IE Trident engine version conversion 1148 | 1149 | if ($match === 'Trident/') 1150 | { 1151 | if ($this->result_browser_version==4) $this->result_browser_version = 8; 1152 | if ($this->result_browser_version==5) $this->result_browser_version = 9; 1153 | if ($this->result_browser_version==6) $this->result_browser_version = 10; 1154 | if ($this->result_browser_version==7) $this->result_browser_version = 11; 1155 | } 1156 | 1157 | if (!empty($this->result_browser_version)) 1158 | { 1159 | $browser_need_continue = FALSE; 1160 | break; 1161 | } 1162 | } 1163 | } 1164 | 1165 | $browser_list = NULL; 1166 | 1167 | // End of desktop browsers detection 1168 | } 1169 | 1170 | /* 1171 | ----------------- 1172 | Mobile Browsers 1173 | ----------------- 1174 | */ 1175 | 1176 | if ($browser_need_continue && $this->result_browser_chrome_original==0 && $this->result_browser_firefox_original==0 && $this->result_mobile == 1) 1177 | { 1178 | // Mobile browsers with detectable versions 1179 | 1180 | $browser_list[] = array('Safari Mobile', '/(iPhone|iphone|iPad;|iPod).*AppleWebKit\/[.0-9]+\s\(KHTML,\slike\sGecko\)\s.*Version\/[.,0-9]+\sMobile\//', '/Version\/([0-9]+\.[0-9]+)(|\.[0-9]+|\,[0-9]+)\sMobile\//', '1', 'RDDocuments|AlohaBrowser|DuckDuckGo|MiuiBrowser|Snapchat|NAVER(inapp;|1Password|OPT/|Ddg/'); 1181 | $browser_list[] = array('Safari Mobile', '/(Intel\sMac\sOS\sX).*AppleWebKit\/.*Version\/[.,0-9]+\s(?:|Mobile\/\w+\s)Safari\/[.0-9A-Za-z]+(|\/[0-9]+|\s\(.*\))+$/', '/Version\/([0-9]+\.[0-9]+)(|\.[0-9]+|\,[0-9]+)/', '1', 'CriOS|RDDocuments|AlohaBrowser|DuckDuckGo|MiuiBrowser|Snapchat|NAVER(inapp;|1Password|OPT/|Ddg/'); 1182 | $browser_list[] = array('Android Browser', '/Android.*Version\/[.0-9]+\s(?:Mobile\s)?Safari\/[.0-9]+(|\-[0-9]+)$/', '/Android.*Version\/([0-9]+\.[0-9]+)/', '1', 'Chrome/'); 1183 | $browser_list[] = array('Android Browser', 'Dalvik/', '/Dalvik\/([.0-9]+)\s\(Linux;\sU;\sAndroid\s/', '2', 'Chrome/'); 1184 | $browser_list[] = array('Samsung Browser', 'SamsungBrowser', '/SamsungBrowser\/([0-9]+\.[0-9]+)/', '1', 'CrossApp'); 1185 | $browser_list[] = array('Firefox Focus', 'Focus/', '/Focus\/([0-9]+\.[0-9]+)/', '1', ''); 1186 | $browser_list[] = array('Firefox iOS', 'FxiOS', '/FxiOS\/([0-9]*[.]?[0-9]+)/', '1', ''); 1187 | $browser_list[] = array('Opera Mini', 'Opera Mini|OPiOS', '/(Opera Mini|OPiOS)\/([0-9]+\.[0-9]+)/', '2', ''); 1188 | $browser_list[] = array('Opera Touch', 'OPT/', '/OPT\/([0-9]+\.[0-9]+)/', '1', ''); 1189 | $browser_list[] = array('Huawei Browser', 'HuaweiBrowser/', '/HuaweiBrowser\/([0-9]+)/', '1', ''); 1190 | $browser_list[] = array('DuckDuckGo', 'DuckDuckGo/', '/DuckDuckGo\/([0-9]+)/', '1', ''); 1191 | $browser_list[] = array('DuckDuckGo', 'Ddg/', '/Ddg\/([0-9]+\.[0-9]+)/', '1', ''); 1192 | $browser_list[] = array('Mi Browser', 'MiuiBrowser/', '/MiuiBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1193 | $browser_list[] = array('Mint Browser', 'Mint Browser/', '/Mint\sBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1194 | $browser_list[] = array('Avast Browser', 'AvastSecureBrowser/', '/AvastSecureBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1195 | $browser_list[] = array('Google App', '/(iPhone|iphone|iPad;|iPod).*\)\sGSA\/([0-9]+)/', '/(iPhone|iphone|iPad;|iPod).*\)\sGSA\/([0-9]+)/', '2', ''); 1196 | $browser_list[] = array('Google App', '/\sGSA\//', '/\sGSA\/([0-9]+)/', '1', ''); 1197 | $browser_list[] = array('Facebook App', 'FBAV/|FBSV/', '/(FBAV|FBSV)\/([0-9]+)\./', '2', 'FBAN/Messenger|FB_IAB/MESSENGER'); 1198 | $browser_list[] = array('Instagram App', 'Instagram', '/Instagram\s([0-9]+)\./', '1', ''); 1199 | $browser_list[] = array('Facebook Messenger', 'FBAN/Messenger|FB_IAB/MESSENGER', '/(FBAV|FBSV)\/([0-9]+)\./', '2', ''); 1200 | $browser_list[] = array('Snapchat', 'Snapchat', '/\sSnapchat\/([0-9]+\.[0-9]+)/', '1', ''); 1201 | $browser_list[] = array('WhatsApp', 'WhatsApp', '/WhatsApp\/([0-9]+\.[0-9]+)/', '1', ''); 1202 | $browser_list[] = array('Viber', 'Viber/', '/Viber\/([0-9]+\.[0-9]+)/', '1', ''); 1203 | $browser_list[] = array('Yandex App', 'YaApp_', '/YaApp_(Android|iOS)\/([0-9]+\.[0-9]+)/', '2', ''); 1204 | $browser_list[] = array('Yandex App', 'YandexSearch/', '/YandexSearch\/([0-9]+\.[0-9]+)/', '1', ''); 1205 | $browser_list[] = array('Yandex App', 'YaSearchBrowser/', '/YaSearchBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1206 | $browser_list[] = array('Dolfin', 'Dolfin/', '/Dolfin\/([0-9]+\.[0-9]+)/', '1', ''); 1207 | $browser_list[] = array('Flipboard App', 'Flipboard/', '/Flipboard\/([0-9]+\.[0-9]+)/', '1', ''); 1208 | $browser_list[] = array('FreeU', 'FreeU|Freeu', '/(FreeU|Freeu)\/([0-9]+\.[0-9]+)/', '2', ''); 1209 | $browser_list[] = array('Iron', 'Iron Safari|MobileIron', '/Chrome\/([0-9]+)/', '1', ''); 1210 | $browser_list[] = array('Sogou Mobile Browser', 'SogouMobileBrowser/', '/SogouMobileBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1211 | $browser_list[] = array('Meizu Browser', 'MZBrowser/', '/MZBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1212 | $browser_list[] = array('360 Mobile Browser', '360 Aphone', '/360\sAphone\sBrowser\s\(([0-9]+\.[0-9]+)/', '1', ''); 1213 | $browser_list[] = array('Adblock Browser', 'ABB/', '/ABB\/([0-9]+\.[0-9]+)/', '1', ''); 1214 | $browser_list[] = array('Ecosia Browser', 'Ecosia', '/Chrome\/([0-9]+)/', '1', ''); 1215 | $browser_list[] = array('HeyTap Browser', 'HeyTapBrowser/', '/HeyTapBrowser\/([0-9]+)/', '1', ''); 1216 | $browser_list[] = array('Oppo Browser', 'OppoBrowser/', '/OppoBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1217 | $browser_list[] = array('Silk', 'Silk/', '/Silk\/([0-9]+\.[0-9]+)/', '1', ''); 1218 | $browser_list[] = array('Surf Browser', 'SurfBrowser/', '/SurfBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1219 | $browser_list[] = array('Phoenix Browser', 'PHX/', '/PHX\/([0-9]+\.[0-9]+)/', '1', ''); 1220 | $browser_list[] = array('CM Mobile', 'ACHEETAHI', '/Chrome\/([0-9]+)/', '1', ''); 1221 | $browser_list[] = array('Bing App', ' BingWeb', '/BingWeb\/([0-9]+\.[0-9]+)/', '1', ''); 1222 | $browser_list[] = array('Firefox Klar', 'Klar/', '/Klar\/([0-9]+\.[0-9]+)/', '1', ''); 1223 | $browser_list[] = array('Super Fast Browser', 'SFBrowser|tssomas', '/(SFBrowser|tssomas)\/([0-9]+\.[0-9]+)/', '2', ''); 1224 | $browser_list[] = array('Tenta Browser', 'Tenta/', '/Tenta\/([0-9]+\.[0-9]+)/', '1', ''); 1225 | $browser_list[] = array('Kiwi Browser', 'Kiwi Chrome/', '/Kiwi\sChrome\/([0-9]+)/', '1', ''); 1226 | $browser_list[] = array('JioPages', 'JioBrowser/', '/JioBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1227 | $browser_list[] = array('JioPages', 'JioPages/', '/JioPages\/([0-9]+\.[0-9]+)/', '1', ''); 1228 | $browser_list[] = array('Qwant Mobile', 'QwantBrowser', '/QwantBrowser\/([0-9]+)/', '1', ''); 1229 | $browser_list[] = array('Qwant Mobile', 'QwantMobile', '/QwantMobile\/([0-9]+\.[0-9]+)/', '1', ''); 1230 | $browser_list[] = array('Cake Browser', '; Cake) ', '/\;\sCake\).*AppleWebKit.*Version\/([0-9]+\.[0-9]+)/', '1', ''); 1231 | $browser_list[] = array('DU Browser', 'bdbrowser', '/bdbrowser(|_i18n)\/([0-9]+\.[0-9]+)/', '2', ''); 1232 | $browser_list[] = array('DU Browser', 'baidubrowser', '/baidubrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1233 | $browser_list[] = array('Baidu Search App', 'baiduboxapp/', '/baiduboxapp\/([0-9]+\.[0-9]+)/', '1', ''); 1234 | $browser_list[] = array('DU Browser HD', 'BaiduHD/', '/BaiduHD\/([0-9]+\.[0-9]+)/', '1', ''); 1235 | $browser_list[] = array('Hi Browser', 'HiBrowser/', '/HiBrowser\/?(?:v)?([0-9]+\.[0-9]+)/', '1', ''); 1236 | $browser_list[] = array('VmWare Browser', 'AirWatch Browser', '/AirWatch\sBrowser\sv([0-9]+\.[0-9]+)/', '1', ''); 1237 | $browser_list[] = array('Iron Mobile', 'MobileIron/', '/MobileIron\/([0-9]+\.[0-9]+)/', '1', ''); 1238 | $browser_list[] = array('NineSky', 'Ninesky-android-mobile/', '/Ninesky\-android\-mobile\/([0-9]+\.[0-9]+)/', '1', ''); 1239 | $browser_list[] = array('Realme Browser', 'RealmeBrowser/', '/RealmeBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1240 | $browser_list[] = array('Vivo Browser', 'VivoBrowser/', '/VivoBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1241 | $browser_list[] = array('Web Explorer', 'Web Explorer/', '/Web\sExplorer\/([0-9]+\.[0-9]+)/', '1', ''); 1242 | $browser_list[] = array('NTENT Browser', 'NTENTBrowser/', '/NTENTBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1243 | $browser_list[] = array('Nox Browser', 'NoxBrowser/', '/NoxBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1244 | $browser_list[] = array('Quark Browser', 'Quark/', '/Quark\/([0-9]+\.[0-9]+)/', '1', ''); 1245 | $browser_list[] = array('Yaani Browser', 'YaaniBrowser', '/YaaniBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1246 | $browser_list[] = array('Tizen Browser', '/Tizen(?: )?(?:\/)?[.0-9]+.*AppleWebKit\/.*(Version|SLP Browser|Tizen Browser|TizenBrowser)\/([0-9]+\.[0-9]+)/', '/Tizen(?: )?(?:\/)?[.0-9]+.*AppleWebKit\/.*(Version|SLP Browser|Tizen Browser|TizenBrowser)\/([0-9]+\.[0-9]+)/', '2', ''); 1247 | $browser_list[] = array('Internet Explorer Mobile', 'IEMobile', '/IEMobile(?: )?(?:\/)?([0-9]+)/', '1', ''); 1248 | $browser_list[] = array('Internet Explorer Mobile', 'Trident/', '/Trident\/[.0-9].*Touch;*.rv\:([0-9]+)/', '1', ''); 1249 | $browser_list[] = array('ZetaKey', 'Zetakey/', '/Zetakey\/([0-9]+\.[0-9]+)/', '1', ''); 1250 | $browser_list[] = array('Nokia Browser', 'NokiaBrowser/', '/NokiaBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1251 | $browser_list[] = array('NetFront', 'NetFront/', '/NetFront\/([0-9]+\.[0-9]+)/', '1', ''); 1252 | $browser_list[] = array('BlackBerry Browser', '/(BB10;|BlackBerry|PlayBook).*AppleWebKit.*Version\/([0-9]+\.[0-9]+)/', '/(BB10;|BlackBerry|PlayBook).*AppleWebKit.*Version\/([0-9]+\.[0-9]+)/', '2', ''); 1253 | $browser_list[] = array('ONE Browser', 'OneBrowser/', '/OneBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1254 | $browser_list[] = array('Web Explorer', 'webexplorer/', '/webexplorer\/([0-9]+)/', '1', ''); 1255 | $browser_list[] = array('Start Internet Browser', 'Start/', '/Start\/([0-9]+)/', '1', ''); 1256 | $browser_list[] = array('EUI Browser', 'EUI Browser', '/EUI\sBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1257 | $browser_list[] = array('iCab Mobile', 'iCabMobile', '/iCabMobile(\s|\/)([0-9]+\.[0-9]+)/', '2', ''); 1258 | $browser_list[] = array('Mercury', 'Mercury/', '/Mercury\/([0-9]+\.[0-9]+)/', '1', ''); 1259 | $browser_list[] = array('Samsung Browser', '; SAMSUNG S|; SAMSUNG G', '/\;\sSAMSUNG\s(S|G)+.*\sBuild\/.*\)\sAppleWebKit\/.*Version\/([0-9]+\.[0-9]+)\sChrome\/[.0-9]+.*\sSafari\/[.0-9]+$/', '2', 'SamsungBrowser'); 1260 | $browser_list[] = array('Documents App', 'RDDocuments/', '/RDDocuments\/([0-9]+\.[0-9]+)/', '1', ''); 1261 | $browser_list[] = array('Opera Coast', 'Coast/', '/Coast\/([0-9]+)/', '1', ''); 1262 | $browser_list[] = array('Android Browser', '/Android.*Version\/[.0-9]+\s(?:Mobile\s)?Safari(|\/[.0-9]+\sCyanogenMod.*)+$/', '/Android.*Version\/([0-9]+\.[0-9]+)/', '1', 'Chrome/'); 1263 | $browser_list[] = array('Playstation Browser', '/(PlayStation\s|PLAYSTATION\s)/', '/(PlayStation\s|PLAYSTATION\s)/', '1', ''); 1264 | $browser_list[] = array('Naver App', 'NAVER(inapp;', '/NAVER\(inapp;\ssearch;\s\d+;\s([0-9]+\.[0-9]+)/', '1', ''); 1265 | $browser_list[] = array('Line App', ' Line/', '/\sLine\/([0-9]+\.[0-9]+)/', '1', ''); 1266 | $browser_list[] = array('QQ App', ' QQ/', '/\sQQ\/([0-9]+\.[0-9]+)/', '1', ''); 1267 | $browser_list[] = array('GNews App', ' GNews ', '/\sGNews\s.*\/([0-9]+\.[0-9]+)/', '1', ''); 1268 | $browser_list[] = array('1Password App', '1Password', '/\s1Password\/([0-9]+\.[0-9]+)/', '1', ''); 1269 | $browser_list[] = array('Pinterest App', 'Pinterest', '/Pinterest/', '1', ''); 1270 | $browser_list[] = array('Twitter App', ' Twitter', '/Twitter/', '1', ''); 1271 | $browser_list[] = array('Ali App', ' AliApp', '/\sAliApp/', '1', ''); 1272 | $browser_list[] = array('Alipay', 'AlipayClient', '/AlipayClient\/([0-9]+\.[0-9]+)/', '1', ''); 1273 | $browser_list[] = array('Samsung CrossApp', 'CrossApp/', '/CrossApp\/([0-9]+\.[0-9]+)/', '1', ''); 1274 | $browser_list[] = array('Diigo', 'DiigoBrowser', '/DiigoBrowser/', '1', ''); 1275 | $browser_list[] = array('Stargon', 'Stargon/', '/Stargon\/([0-9]+\.[0-9]+)/', '1', ''); 1276 | $browser_list[] = array('You Browser', 'YouBrowser/', '/YouBrowser\/([0-9]+\.[0-9]+)/', '1', ''); 1277 | $browser_list[] = array('Max Browser', 'MaxBrowser/', '/MaxBrowser\/([0-9]+)/', '1', ''); 1278 | $browser_list[] = array('Soul Browser', 'Soul/', '/Soul\/([0-9]+)/', '1', ''); 1279 | 1280 | foreach($browser_list as $browser_list_va) 1281 | { 1282 | $match = $browser_list_va[1]; 1283 | $match_exclude = $browser_list_va[4]; 1284 | 1285 | // Some OS specified browsers matching optimization 1286 | 1287 | $current_browser_continue = TRUE; 1288 | if ($this->get_mode !== 'browser') 1289 | { 1290 | $current_browser = $browser_list_va[0]; 1291 | 1292 | // Some iOS specified browsers matching optimization 1293 | 1294 | if ($current_browser === 'Safari Mobile' || $current_browser === 'Firefox iOS') 1295 | { 1296 | if ($this->result_os_name !== 'iOS') $current_browser_continue = FALSE; 1297 | } 1298 | 1299 | // Some Android specified browsers matching optimization 1300 | 1301 | if ($current_browser === 'Android Browser' || $current_browser === 'Samsung Browser' || $current_browser === 'Huawei Browser') 1302 | { 1303 | if ($this->result_os_name !== 'Android') $current_browser_continue = FALSE; 1304 | } 1305 | 1306 | // WP specified browser matching optimization 1307 | 1308 | if ($current_browser === 'Internet Explorer Mobile' && $this->result_os_name !== 'Windows Phone' && $this->result_os_name !== 'Windows Mobile') $current_browser_continue = FALSE; 1309 | 1310 | // Tizen specified browser matching optimization 1311 | 1312 | if ($current_browser === 'Tizen Browser' && $this->result_os_name !== 'Tizen') $current_browser_continue = FALSE; 1313 | 1314 | // BlackBerry specified browser matching optimization 1315 | 1316 | if ($current_browser === 'BlackBerry Browser' && $this->result_os_name !== 'BlackBerry') $current_browser_continue = FALSE; 1317 | 1318 | // Google App matching optimization 1319 | 1320 | if ($current_browser === 'Google App' && !$this->match_ua(' GSA/')) $current_browser_continue = FALSE; 1321 | } 1322 | 1323 | if ($current_browser_continue == TRUE && $this->match_ua($match) && !$this->match_ua($match_exclude)) 1324 | { 1325 | $this->result_browser_version = 0; 1326 | $this->result_browser_name = $browser_list_va[0]; 1327 | $matches = $this->match_ua($browser_list_va[2]); 1328 | $matches_n = intval($browser_list_va[3]); 1329 | 1330 | if (is_array($matches)) 1331 | { 1332 | if ($this->result_browser_name === 'Safari Mobile' && strpos($matches[$matches_n], '_') !== FALSE) $matches[$matches_n] = str_replace('_', '.', $matches[$matches_n]); 1333 | $this->result_browser_version = (float)$matches[$matches_n]; 1334 | } 1335 | else 1336 | { 1337 | $this->result_browser_version = 0; 1338 | } 1339 | 1340 | if (!empty($this->result_browser_version)) 1341 | { 1342 | $browser_need_continue = FALSE; 1343 | break; 1344 | } 1345 | } 1346 | } 1347 | 1348 | $browser_list = NULL; 1349 | 1350 | // End of mobile browsers detection 1351 | } 1352 | 1353 | // Other browsers without version specified 1354 | 1355 | if ($browser_need_continue) 1356 | { 1357 | $other_bsr = array(); 1358 | 1359 | $other_bsr[] = array('Maple'=>'Maple'); 1360 | $other_bsr[] = array('Espial'=>'Espial'); 1361 | 1362 | foreach ($other_bsr as $other_bsr_va) 1363 | { 1364 | $k = key($other_bsr_va); 1365 | $v = $other_bsr_va[$k]; 1366 | 1367 | if ($this->match_ua($v)) 1368 | { 1369 | $this->result_browser_version = 0; 1370 | $this->result_browser_name = $k; 1371 | $this->result_browser_title = $k; 1372 | break; 1373 | } 1374 | } 1375 | $other_bsr = NULL; 1376 | } 1377 | 1378 | // MacOS and iOS Apps 1379 | 1380 | if ($this->result_browser_name === 'unknown' && $this->match_ua('CFNetwork/') && $this->match_ua('Darwin/') && !$this->match_ua('Safari/')) 1381 | { 1382 | $matches = $this->match_ua('/^(.*)(\/[.0-9]+|\s\(unknown\sversion\))(.*)\sCFNetwork\/[.0-9]+\sDarwin\/[.0-9]+/'); 1383 | if (!empty($matches[1])) 1384 | { 1385 | $matches[1] = str_replace('%20', ' ', $matches[1]); 1386 | $matches[1] = str_replace('com.apple.Safari.', '', $matches[1]); 1387 | $matches[1] = str_replace('com.apple.WebKit.', '', $matches[1]); 1388 | $matches[1] = str_replace('com.apple.Notes.', '', $matches[1]); 1389 | $matches[1] = str_replace('com.apple.mobilenotes.', '', $matches[1]); 1390 | $this->result_browser_name = $matches[1].' App'; 1391 | if ($this->result_browser_name === 'Browser App') $this->result_browser_name = 'Darwin Browser'; 1392 | $darwin_app = TRUE; 1393 | } 1394 | } 1395 | 1396 | /* 1397 | ------------------- 1398 | WebView detection 1399 | ------------------- 1400 | */ 1401 | 1402 | if ($this->result_mobile == 1) 1403 | { 1404 | // Android WebView 1405 | 1406 | if ($this->result_os_name === 'Android') 1407 | { 1408 | if ($this->match_ua('; wv|;FB|FB_IAB|OKApp|DuckDuckGo')) $this->result_browser_android_webview = 1; 1409 | if ($this->result_browser_chrome_original == 0 && $this->result_browser_chromium_version != 0 && $this->match_ua('/like\sGecko\)\sVersion\/[.0-9]+\sChrome\/[.0-9]+\s/')) $this->result_browser_android_webview = 1; 1410 | } 1411 | 1412 | // WKWebView 1413 | 1414 | if ($this->result_ios) 1415 | { 1416 | $webkit_webview = FALSE; 1417 | 1418 | if ($this->match_ua('/\s\((iPhone|iphone|iPad|iPod);.*\)\sAppleWebKit\/[.0-9]+\s\(KHTML\,\slike Gecko\)\s(?!CriOS|FxiOS|OPiOS|EdgiOS)(?!Version).*Mobile\/([0-9A-Z]+)/')) $webkit_webview = TRUE; 1419 | if ($this->result_browser_name === 'unknown' && $this->match_ua('MobileSafari/') && $this->match_ua('CFNetwork/')) $webkit_webview = TRUE; 1420 | 1421 | if ($webkit_webview) 1422 | { 1423 | $this->result_browser_ios_webview = 1; 1424 | 1425 | if ($this->result_browser_name === 'unknown') 1426 | { 1427 | $this->result_browser_name = 'WKWebView'; 1428 | $this->result_browser_version = 0; 1429 | } 1430 | } 1431 | } 1432 | } 1433 | 1434 | /* 1435 | ------------------------- 1436 | Detect Safari original 1437 | ------------------------- 1438 | */ 1439 | 1440 | if ($this->result_browser_name === 'Safari' || $this->result_browser_name === 'Safari Mobile') 1441 | { 1442 | if ($this->match_ua('/AppleWebKit\/[.0-9]+.*Gecko\)\sVersion\/[.0-9].*Safari\/[.0-9A-Za-z]+$/')) $this->result_browser_safari_original = 1; 1443 | } 1444 | 1445 | // Check and correct browser version anomaly 1446 | 1447 | if (intval($this->result_browser_version)>200 && !$this->match_ua('FBAV/|FBSV/|GSA/|Instagram')) $this->result_browser_version = 0; 1448 | 1449 | // Set Browser title 1450 | 1451 | if (!empty($this->result_browser_version)) $this->result_browser_title = $this->result_browser_name.' '.$this->result_browser_version; 1452 | else 1453 | { 1454 | $this->result_browser_title = $this->result_browser_name.' (unknown version)'; 1455 | 1456 | $browsers_without_versions = array(); 1457 | $browsers_without_versions[] = 'Android Browser'; 1458 | $browsers_without_versions[] = 'WKWebView'; 1459 | $browsers_without_versions[] = 'Safari SDK'; 1460 | $browsers_without_versions[] = 'Playstation Browser'; 1461 | $browsers_without_versions[] = 'OmniWeb'; 1462 | $browsers_without_versions[] = 'Steam Client'; 1463 | $browsers_without_versions[] = 'Steam Overlay'; 1464 | $browsers_without_versions[] = 'Maple'; 1465 | $browsers_without_versions[] = 'Espial'; 1466 | $browsers_without_versions[] = 'Diigo Browser'; 1467 | $browsers_without_versions[] = 'IceWeasel'; 1468 | $browsers_without_versions[] = 'Iceweasel'; 1469 | $browsers_without_versions[] = 'Facebook App'; 1470 | $browsers_without_versions[] = 'Twitter App'; 1471 | $browsers_without_versions[] = 'Bing App'; 1472 | $browsers_without_versions[] = 'Pinterest App'; 1473 | $browsers_without_versions[] = 'Ali App'; 1474 | $browsers_without_versions[] = 'Alipay App'; 1475 | $browsers_without_versions[] = 'Lunascape'; 1476 | 1477 | if (in_array($this->result_browser_name, $browsers_without_versions) || isset($darwin_app)) 1478 | { 1479 | $this->result_browser_title = $this->result_browser_name; 1480 | } 1481 | 1482 | $browsers_without_versions = NULL; 1483 | } 1484 | 1485 | if (strpos($this->result_browser_name, 'unknown') !== FALSE) $this->result_browser_title = 'unknown'; 1486 | if ($this->result_browser_version == NULL) $this->result_browser_version = 0; 1487 | 1488 | // EdgeHTML browser should not be detected as a Chromium engine 1489 | if ($this->result_browser_name === 'Edge' && $this->result_browser_version >= 12 && $this->result_browser_version <= 18) $this->result_browser_chromium_version = 0; 1490 | 1491 | if ($this->get_mode === 'browser') return NULL; 1492 | 1493 | /* 1494 | --------------------- 1495 | Detect device types 1496 | --------------------- 1497 | */ 1498 | 1499 | // Desktop 1500 | 1501 | if ($this->result_os_family !== 'unknown' && $this->result_os_type !== 'mixed') $this->result_device_type = 'desktop'; 1502 | 1503 | // Mobile 1504 | 1505 | if ($this->result_mobile == 1) $this->result_device_type = 'mobile'; 1506 | 1507 | // TV 1508 | 1509 | if ($this->match_ua('TV|HDMI|CrKey| Escape |Kylo/|SmartLabs|SC/IHD|Viera|BRAVIA|NetCast|Roku/DVP| Roku |Maple|DuneHD|CE-HTML|EIS iPanel|Sunniwell; Resolution|Freebox|Netbox|Netgem|AFTT|AFTM|AFTB|DLNADOC| iconBIT |olleh tv|stbapp |; MIBOX|ABOX-I|; H96 |; X96|HX S905|; M8S |MINIM8S|MXIII-|; NEO-X|; NEO-U| Nexus Player |TPM171E|; V88 |MXQPRO|NEXBOX-|; Leelbox|ZIDOO|; A95X| Beelink |; T95Z|; TX3 ') && !$this->match_ua('BTV-')) $this->result_device_type = 'tv'; 1510 | 1511 | // Console 1512 | 1513 | if ($this->matchi_ua('playstation') || $this->match_ua('Xbox|GAMEPAD|Nintendo|OUYA|; SHIELD Build')) $this->result_device_type = 'console'; 1514 | 1515 | // MediaPlayer 1516 | 1517 | if ($this->match_ua('iPod|AlexaMediaPlayer|AppleCoreMedia')) $this->result_device_type = 'mediaplayer'; 1518 | 1519 | // Car 1520 | 1521 | if ($this->match_ua('CarBrowser|Tesla/')) $this->result_device_type = 'car'; 1522 | 1523 | // Watch 1524 | 1525 | if ($this->matchi_ua('watch') && !$this->match_ua('AirWatch')) $this->result_device_type = 'watch'; 1526 | 1527 | if ($this->get_mode === 'device') return NULL; 1528 | 1529 | /* 1530 | --------------------------------------------- 1531 | Detect 64bits mode (browser + OS specified) 1532 | --------------------------------------------- 1533 | */ 1534 | 1535 | if ($this->result_os_name === 'MacOS' && $this->macos_version_minor >= 6) 1536 | { 1537 | if ($this->result_browser_name === 'Safari' || $this->result_browser_name === 'Safari SDK') $this->result_64bits_mode = 1; 1538 | } 1539 | 1540 | /* 1541 | --------------------------------------------------------- 1542 | MacOS Big Sur + Firefox version > 86 detection feature 1543 | --------------------------------------------------------- 1544 | */ 1545 | 1546 | if ($this->result_os_name === 'MacOS' && $this->macos_version_minor == 15 && $this->result_browser_name === 'Firefox' && $this->result_browser_version > 86) 1547 | { 1548 | $this->result_os_version = 'Big Sur'; 1549 | $this->result_os_title = 'MacOS '.$this->result_os_version; 1550 | } 1551 | 1552 | return NULL; 1553 | } 1554 | 1555 | /** 1556 | * The method returns all possible environment data from User-Agent 1557 | * 1558 | * @param string $ua The User-Agent string 1559 | * @param string $result_format If specified, method returns result as JSON 1560 | * @return mixed Returns User-Agent parsing result as array or JSON string (optional) 1561 | */ 1562 | 1563 | public function getAll($ua, $result_format = '') 1564 | { 1565 | $this->useragent = trim($ua); 1566 | $this->get_mode = 'all'; 1567 | $this->resetProperties(); 1568 | $this->getResult(); 1569 | $result = array('os_type'=>$this->result_os_type, 1570 | 'os_family'=>$this->result_os_family, 1571 | 'os_name'=>$this->result_os_name, 1572 | 'os_version'=>$this->result_os_version, 1573 | 'os_title'=>$this->result_os_title, 1574 | 'device_type'=>$this->result_device_type, 1575 | 'browser_name'=>$this->result_browser_name, 1576 | 'browser_version'=>$this->result_browser_version, 1577 | 'browser_title'=>$this->result_browser_title, 1578 | 'browser_chrome_original'=>$this->result_browser_chrome_original, 1579 | 'browser_firefox_original'=>$this->result_browser_firefox_original, 1580 | 'browser_safari_original'=>$this->result_browser_safari_original, 1581 | 'browser_chromium_version'=>$this->result_browser_chromium_version, 1582 | 'browser_gecko_version'=>$this->result_browser_gecko_version, 1583 | 'browser_webkit_version'=>$this->result_browser_webkit_version, 1584 | 'browser_android_webview'=>$this->result_browser_android_webview, 1585 | 'browser_ios_webview'=>$this->result_browser_ios_webview, 1586 | 'browser_desktop_mode'=>$this->result_browser_desktop_mode, 1587 | '64bits_mode'=>$this->result_64bits_mode); 1588 | 1589 | if (strtolower($result_format) === 'json') $result = json_encode($result); 1590 | $this->touch_support_mode = FALSE; 1591 | return $result; 1592 | } 1593 | 1594 | /** 1595 | * The method returns OS data from User-Agent 1596 | * 1597 | * @param string $ua The User-Agent string 1598 | * @param string $result_format If specified, method returns result as JSON 1599 | * @return mixed Returns User-Agent parsing result as array or JSON string (optional) 1600 | */ 1601 | 1602 | public function getOS($ua, $result_format = '') 1603 | { 1604 | $this->useragent = trim($ua); 1605 | $this->get_mode = 'os'; 1606 | $this->resetProperties(); 1607 | $this->getResult(); 1608 | $result = array('os_type'=>$this->result_os_type, 1609 | 'os_family'=>$this->result_os_family, 1610 | 'os_name'=>$this->result_os_name, 1611 | 'os_version'=>$this->result_os_version, 1612 | 'os_title'=>$this->result_os_title, 1613 | '64bits_mode'=>$this->result_64bits_mode); 1614 | 1615 | if (strtolower($result_format) === 'json') $result = json_encode($result); 1616 | $this->touch_support_mode = FALSE; 1617 | return $result; 1618 | } 1619 | 1620 | /** 1621 | * The method returns Browser data from User-Agent 1622 | * 1623 | * @param string $ua The User-Agent string 1624 | * @param string $result_format If specified, method returns result as JSON 1625 | * @return mixed Returns User-Agent parsing result as array or JSON string (optional) 1626 | */ 1627 | 1628 | public function getBrowser($ua, $result_format = '') 1629 | { 1630 | $this->useragent = trim($ua); 1631 | $this->get_mode = 'browser'; 1632 | $this->resetProperties(); 1633 | $this->getResult(); 1634 | $result = array('browser_name'=>$this->result_browser_name, 1635 | 'browser_version'=>$this->result_browser_version, 1636 | 'browser_title'=>$this->result_browser_title, 1637 | 'browser_chrome_original'=>$this->result_browser_chrome_original, 1638 | 'browser_firefox_original'=>$this->result_browser_firefox_original, 1639 | 'browser_safari_original'=>$this->result_browser_safari_original, 1640 | 'browser_chromium_version'=>$this->result_browser_chromium_version, 1641 | 'browser_gecko_version'=>$this->result_browser_gecko_version, 1642 | 'browser_webkit_version'=>$this->result_browser_webkit_version, 1643 | 'browser_android_webview'=>$this->result_browser_android_webview, 1644 | 'browser_ios_webview'=>$this->result_browser_ios_webview, 1645 | 'browser_desktop_mode'=>$this->result_browser_desktop_mode); 1646 | 1647 | if (strtolower($result_format) === 'json') $result = json_encode($result); 1648 | $this->touch_support_mode = FALSE; 1649 | return $result; 1650 | } 1651 | 1652 | /** 1653 | * The method returns Device Type data from User-Agent 1654 | * 1655 | * @param string $ua The User-Agent string 1656 | * @param string $result_format If specified, method returns result as JSON 1657 | * @return mixed Returns User-Agent parsing result as array or JSON string (optional) 1658 | */ 1659 | 1660 | public function getDevice($ua, $result_format = '') 1661 | { 1662 | $this->useragent = trim($ua); 1663 | $this->get_mode = 'device'; 1664 | $this->resetProperties(); 1665 | $this->getResult(); 1666 | $result = array('device_type'=>$this->result_device_type); 1667 | 1668 | if (strtolower($result_format) === 'json') $result = json_encode($result); 1669 | $this->touch_support_mode = FALSE; 1670 | return $result; 1671 | } 1672 | 1673 | /** 1674 | * This method is needed to detect mobile browsers in Desktop Mode (Android and iOS) 1675 | * The method should call if browser supports Touch events (client-side JS detection is necessary) 1676 | * 1677 | * @return null 1678 | */ 1679 | 1680 | public function setTouchSupport() 1681 | { 1682 | $this->touch_support_mode = TRUE; 1683 | return NULL; 1684 | } 1685 | } 1686 | 1687 | ?> -------------------------------------------------------------------------------- /tests/benchmark.php: -------------------------------------------------------------------------------- 1 | exec("PRAGMA journal_mode=WAL;"); 10 | $db->exec("PRAGMA synchronous=NORMAL;"); 11 | $results = $db->query('SELECT ua FROM useragents'); 12 | 13 | $time_start = microtime(true); 14 | $counter = 0; 15 | 16 | while ($row = $results->fetchArray()) 17 | { 18 | $result = $Browser->getAll($row['ua']); 19 | if (microtime(true) - $time_start > 1) break; 20 | $counter++; 21 | } 22 | 23 | $time_end = microtime(true); 24 | $time_result = $time_end - $time_start; 25 | 26 | echo '

Iterations: '.$counter.' RPS.

'; 27 | echo '

Execution time: '.substr($time_result,0,7).' sec.

'; 28 | 29 | ?> -------------------------------------------------------------------------------- /tests/browser.php: -------------------------------------------------------------------------------- 1 | getBrowser($u); 58 | 59 | echo '
';
60 | 	echo $u;
61 | 	echo '
'; 62 | 63 | echo '
';
64 | 	print_r($result);
65 | 	echo '
'; 66 | 67 | echo '
';
68 | 	echo '--------------------------------------------------------------------------------';
69 | 	echo '
'; 70 | 71 | } 72 | 73 | $time_end = microtime(true); 74 | $time_result = $time_end - $time_start; 75 | 76 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 77 | 78 | ?> -------------------------------------------------------------------------------- /tests/chrome_os.php: -------------------------------------------------------------------------------- 1 | getAll($u); 22 | 23 | echo '
';
24 | 	echo $u;
25 | 	echo '
'; 26 | 27 | echo '
';
28 | 	print_r($result);
29 | 	echo '
'; 30 | 31 | echo '
';
32 | 	echo '--------------------------------------------------------------------------------';
33 | 	echo '
'; 34 | 35 | } 36 | 37 | $time_end = microtime(true); 38 | $time_result = $time_end - $time_start; 39 | 40 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 41 | 42 | ?> -------------------------------------------------------------------------------- /tests/common.php: -------------------------------------------------------------------------------- 1 | getAll($u); 73 | 74 | echo '
';
75 | 	echo $u;
76 | 	echo '
'; 77 | 78 | echo '
';
79 | 	print_r($result);
80 | 	echo '
'; 81 | 82 | echo '
';
83 | 	echo '--------------------------------------------------------------------------------';
84 | 	echo '
'; 85 | 86 | } 87 | 88 | $time_end = microtime(true); 89 | $time_result = $time_end - $time_start; 90 | 91 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 92 | 93 | ?> -------------------------------------------------------------------------------- /tests/console.php: -------------------------------------------------------------------------------- 1 | setTouchSupport(); 34 | 35 | // Detect all possible environment data from User-Agents 36 | $result = $Browser->getAll($u); 37 | 38 | echo '
';
39 | 	echo $u;
40 | 	echo '
'; 41 | 42 | echo '
';
43 | 	print_r($result);
44 | 	echo '
'; 45 | 46 | echo '
';
47 | 	echo '--------------------------------------------------------------------------------';
48 | 	echo '
'; 49 | 50 | } 51 | 52 | $time_end = microtime(true); 53 | $time_result = $time_end - $time_start; 54 | 55 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 56 | 57 | ?> -------------------------------------------------------------------------------- /tests/darwin.php: -------------------------------------------------------------------------------- 1 | getAll($u); 44 | 45 | echo '
';
46 | 	echo $u;
47 | 	echo '
'; 48 | 49 | echo '
';
50 | 	print_r($result);
51 | 	echo '
'; 52 | 53 | echo '
';
54 | 	echo '--------------------------------------------------------------------------------';
55 | 	echo '
'; 56 | 57 | } 58 | 59 | $time_end = microtime(true); 60 | $time_result = $time_end - $time_start; 61 | 62 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 63 | 64 | ?> -------------------------------------------------------------------------------- /tests/desktop_mode.php: -------------------------------------------------------------------------------- 1 | setTouchSupport(); 60 | 61 | // Detect all possible environment data from User-Agents 62 | $result = $Browser->getAll($u); 63 | 64 | echo '
';
65 | 	echo $u;
66 | 	echo '
'; 67 | 68 | echo '
';
69 | 	print_r($result);
70 | 	echo '
'; 71 | 72 | echo '
';
73 | 	echo '--------------------------------------------------------------------------------';
74 | 	echo '
'; 75 | 76 | } 77 | 78 | $time_end = microtime(true); 79 | $time_result = $time_end - $time_start; 80 | 81 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 82 | 83 | ?> -------------------------------------------------------------------------------- /tests/device.php: -------------------------------------------------------------------------------- 1 | getDevice($u); 58 | 59 | echo '
';
60 | 	echo $u;
61 | 	echo '
'; 62 | 63 | echo '
';
64 | 	print_r($result);
65 | 	echo '
'; 66 | 67 | echo '
';
68 | 	echo '--------------------------------------------------------------------------------';
69 | 	echo '
'; 70 | 71 | } 72 | 73 | $time_end = microtime(true); 74 | $time_result = $time_end - $time_start; 75 | 76 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 77 | 78 | ?> -------------------------------------------------------------------------------- /tests/edge.php: -------------------------------------------------------------------------------- 1 | getAll($u); 25 | 26 | echo '
';
27 | 	echo $u;
28 | 	echo '
'; 29 | 30 | echo '
';
31 | 	print_r($result);
32 | 	echo '
'; 33 | 34 | echo '
';
35 | 	echo '--------------------------------------------------------------------------------';
36 | 	echo '
'; 37 | 38 | } 39 | 40 | $time_end = microtime(true); 41 | $time_result = $time_end - $time_start; 42 | 43 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 44 | 45 | ?> -------------------------------------------------------------------------------- /tests/float_issue.php: -------------------------------------------------------------------------------- 1 | getAll($u); 21 | 22 | echo '
';
23 | 	echo $u;
24 | 	echo '
'; 25 | 26 | echo '
';
27 | 	print_r($result);
28 | 	echo '
'; 29 | 30 | echo '
';
31 | 	echo '--------------------------------------------------------------------------------';
32 | 	echo '
'; 33 | 34 | } 35 | 36 | $time_end = microtime(true); 37 | $time_result = $time_end - $time_start; 38 | 39 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 40 | 41 | ?> -------------------------------------------------------------------------------- /tests/gecko_issue.php: -------------------------------------------------------------------------------- 1 | getAll($u); 28 | 29 | echo '
';
30 | 	echo $u;
31 | 	echo '
'; 32 | 33 | echo '
';
34 | 	print_r($result);
35 | 	echo '
'; 36 | 37 | echo '
';
38 | 	echo '--------------------------------------------------------------------------------';
39 | 	echo '
'; 40 | 41 | } 42 | 43 | $time_end = microtime(true); 44 | $time_result = $time_end - $time_start; 45 | 46 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 47 | 48 | ?> -------------------------------------------------------------------------------- /tests/ios.php: -------------------------------------------------------------------------------- 1 | getAll($u); 45 | 46 | echo '
';
47 | 	echo $u;
48 | 	echo '
'; 49 | 50 | echo '
';
51 | 	print_r($result);
52 | 	echo '
'; 53 | 54 | echo '
';
55 | 	echo '--------------------------------------------------------------------------------';
56 | 	echo '
'; 57 | 58 | } 59 | 60 | $time_end = microtime(true); 61 | $time_result = $time_end - $time_start; 62 | 63 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 64 | 65 | ?> -------------------------------------------------------------------------------- /tests/ios_webview.php: -------------------------------------------------------------------------------- 1 | getAll($u); 40 | 41 | echo '
';
42 | 	echo $u;
43 | 	echo '
'; 44 | 45 | echo '
';
46 | 	print_r($result);
47 | 	echo '
'; 48 | 49 | echo '
';
50 | 	echo '--------------------------------------------------------------------------------';
51 | 	echo '
'; 52 | 53 | } 54 | 55 | $time_end = microtime(true); 56 | $time_result = $time_end - $time_start; 57 | 58 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 59 | 60 | ?> -------------------------------------------------------------------------------- /tests/macos.php: -------------------------------------------------------------------------------- 1 | getAll($u); 46 | 47 | echo '
';
48 | 	echo $u;
49 | 	echo '
'; 50 | 51 | echo '
';
52 | 	print_r($result);
53 | 	echo '
'; 54 | 55 | echo '
';
56 | 	echo '--------------------------------------------------------------------------------';
57 | 	echo '
'; 58 | 59 | } 60 | 61 | $time_end = microtime(true); 62 | $time_result = $time_end - $time_start; 63 | 64 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 65 | 66 | ?> -------------------------------------------------------------------------------- /tests/new.php: -------------------------------------------------------------------------------- 1 | getAll($u); 178 | 179 | echo '
';
180 | 	echo $u;
181 | 	echo '
'; 182 | 183 | echo '
';
184 | 	print_r($result);
185 | 	echo '
'; 186 | 187 | echo '
';
188 | 	echo '--------------------------------------------------------------------------------';
189 | 	echo '
'; 190 | 191 | } 192 | 193 | $time_end = microtime(true); 194 | $time_result = $time_end - $time_start; 195 | 196 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 197 | 198 | ?> -------------------------------------------------------------------------------- /tests/os.php: -------------------------------------------------------------------------------- 1 | getOS($u); 58 | 59 | echo '
';
60 | 	echo $u;
61 | 	echo '
'; 62 | 63 | echo '
';
64 | 	print_r($result);
65 | 	echo '
'; 66 | 67 | echo '
';
68 | 	echo '--------------------------------------------------------------------------------';
69 | 	echo '
'; 70 | 71 | } 72 | 73 | $time_end = microtime(true); 74 | $time_result = $time_end - $time_start; 75 | 76 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 77 | 78 | ?> -------------------------------------------------------------------------------- /tests/random.php: -------------------------------------------------------------------------------- 1 | exec("PRAGMA journal_mode=WAL;"); 13 | $db->exec("PRAGMA synchronous=NORMAL;"); 14 | $results = $db->query('SELECT ua FROM useragents LIMIT '.$useragents_random_count.' OFFSET ABS(RANDOM()) % MAX((SELECT COUNT(*) FROM useragents), 1);'); 15 | 16 | while ($row = $results->fetchArray()) 17 | { 18 | $useragent[] = ($row['ua']); 19 | } 20 | 21 | $time_start = microtime(true); 22 | 23 | foreach ($useragent as $u) 24 | { 25 | 26 | $result = $Browser->getAll($u); 27 | 28 | echo '
';
29 | 	echo $u;
30 | 	echo '
'; 31 | 32 | echo '
';
33 | 	print_r($result);
34 | 	echo '
'; 35 | 36 | echo '
';
37 | 	echo '--------------------------------------------------------------------------------';
38 | 	echo '
'; 39 | 40 | } 41 | 42 | $time_end = microtime(true); 43 | $time_result = $time_end - $time_start; 44 | 45 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 46 | 47 | ?> -------------------------------------------------------------------------------- /tests/rare.php: -------------------------------------------------------------------------------- 1 | getAll($u); 140 | 141 | echo '
';
142 | 	echo $u;
143 | 	echo '
'; 144 | 145 | echo '
';
146 | 	print_r($result);
147 | 	echo '
'; 148 | 149 | echo '
';
150 | 	echo '--------------------------------------------------------------------------------';
151 | 	echo '
'; 152 | 153 | } 154 | 155 | $time_end = microtime(true); 156 | $time_result = $time_end - $time_start; 157 | 158 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 159 | 160 | ?> -------------------------------------------------------------------------------- /tests/single.php: -------------------------------------------------------------------------------- 1 | setTouchSupport(); 11 | 12 | $useragent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'; 13 | 14 | $time_start = microtime(true); 15 | 16 | // Detect all possible environment data from User-Agent 17 | $result = $Browser->getAll($useragent); 18 | 19 | echo '
';
20 | echo $useragent;
21 | echo '
'; 22 | 23 | echo '
';
24 | print_r($result);
25 | echo '
'; 26 | 27 | echo '
';
28 | echo '--------------------------------------------------------------------------------';
29 | echo '
'; 30 | 31 | $time_end = microtime(true); 32 | $time_result = $time_end - $time_start; 33 | 34 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 35 | 36 | ?> -------------------------------------------------------------------------------- /tests/tv.php: -------------------------------------------------------------------------------- 1 | getAll($u); 145 | 146 | echo '
';
147 | 	echo $u;
148 | 	echo '
'; 149 | 150 | echo '
';
151 | 	print_r($result);
152 | 	echo '
'; 153 | 154 | echo '
';
155 | 	echo '--------------------------------------------------------------------------------';
156 | 	echo '
'; 157 | 158 | } 159 | 160 | $time_end = microtime(true); 161 | $time_result = $time_end - $time_start; 162 | 163 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 164 | 165 | ?> -------------------------------------------------------------------------------- /tests/useragents.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foroco/php-browser-detection/0a640254c6e61fe8e741d1e5c3495308cfec51c1/tests/useragents.db -------------------------------------------------------------------------------- /tests/webview.php: -------------------------------------------------------------------------------- 1 | getBrowser($u); 21 | 22 | echo '
';
23 | 	echo $u;
24 | 	echo '
'; 25 | 26 | echo '
';
27 | 	print_r($result);
28 | 	echo '
'; 29 | 30 | echo '
';
31 | 	echo '--------------------------------------------------------------------------------';
32 | 	echo '
'; 33 | 34 | } 35 | 36 | $time_end = microtime(true); 37 | $time_result = $time_end - $time_start; 38 | 39 | echo '

Total execution time: '.substr($time_result,0,7).' sec.

'; 40 | 41 | ?> --------------------------------------------------------------------------------