Compare commits

..

13 Commits
2.0.7 ... 2.0.8

Author SHA1 Message Date
Faisal Salman
7abb90bf3b Bump version 2.0.8 2026-01-13 15:56:31 +07:00
Hyper-Z11
f1eed9e0b0 chore: update pattern to ONLY include top-level js files in dist (#820) 2026-01-13 14:44:31 +07:00
Faisal Salman
66f38587b8 [extensions] Add new library: http.rb, Jetty, ocaml-cohttp 2026-01-13 09:38:35 +07:00
Faisal Salman
0273bf64e6 Improve browser detection: Brave 2026-01-13 09:38:35 +07:00
Faisal Salman
21186ae1c6 Add new browser: HiBrowser 2026-01-13 09:38:35 +07:00
Faisal Salman
de2ef644ec Fix #815 - Improve device detection: OnePlus device misidentified as LG tablet 2026-01-13 09:38:35 +07:00
Faisal Salman
cf4cba5d97 Add new browser: Opera Neon - https://www.operaneon.com/ 2026-01-13 09:38:35 +07:00
Faisal Salman
7fcf3f0ac4 [extensions] Add new CLI: Windows' PowerShell 2026-01-13 09:38:35 +07:00
Faisal Salman
68f8684d09 Improve OS detection: Firefox OS 2026-01-13 09:38:35 +07:00
Faisal Salman
611221bcfb Add new engine: Dillo - https://dillo-browser.org/ 2026-01-13 09:38:35 +07:00
Faisal Salman
d54474d8e3 Fix #814 - Resolve syntax error related to import renaming in ESM version build 2026-01-13 09:38:35 +07:00
Casey Grimes
bab55a28df feat(email): expand email client detection & add Outlook edition helper (#819)
* feat(email): significantly expanded email client detection to support 40+ new user agents, including Alpine, Canary Mail, FairEmail, ProtonMail Bridge, Tutanota, and The Bat!
feat(helpers): added getOutlookEdition() utility to interpret raw version strings into specific Outlook editions (e.g., distinguishing Outlook 2016 MSI vs. Click-to-Run/365).

chore(enums): added comprehensive BrowserName.Email enums for all newly supported clients.
chore(types): added TypeScript definitions for the new getOutlookEdition helper.

test(email): added comprehensive test suite covering 60+ email client user agent strings.

test(helpers): added unit tests for getOutlookEdition covering Windows (MSI/C2R) and Mac variants.

* chore: Some small updates for business logic around K-9, Yahoo Mail, Outlook

* test: Edgecase alignment and fixes
chore(deps): npm vulnerability fix in package-lock.json
chore: Updated dist builds

* Revert accidentally-removed additional code and comments

* Correct comment syntax in ua-parser-extensions.js

Fix comment formatting and clean up code.

* chore: build fix
2026-01-12 11:34:59 +07:00
giantyo26
1696b87b58 Improve existing browser detection for Tiktok (#817)
* Improve browser detection: Tiktok

* remove .mjs files changes
2026-01-12 10:58:06 +07:00
41 changed files with 2204 additions and 278 deletions

View File

@@ -76,6 +76,21 @@
--- ---
## Version 2.0.8
- Resolve syntax error related to import renaming in ESM build
- Add new browser: HiBrowser, Opera Neon
- Add new engine: Dillo
- Improve browser detection: Brave, TikTok
- Improve device detection: OnePlus
- Improve OS detection: Firefox OS
- `extensions` submodule:
- Add new CLI: PowerShell
- Add new email: Alpine, Android, AquaMail, Balsa, Barca, Canary, Claws Mail, eM Client, Eudora, FairEmail, Geary, Gnus, Horde::IMP, Lotus-Notes, IncrediMail, K-9 Mail, Mailbird, MailMate, Mailspring, Mutt, Newton, Nine, NylasMail, Outlook-Express, Pegasus Mail, PocoMail, Postbox, ProtonMail Bridge, Quala, R2Mail2, Rainloop, Roundcube Webmail, SamsungEmail, Spicebird, SquirrelMail, Sylpheed, The Bat!, Trojita, Turnpike, tutanota-desktop, Wanderlust, Windows-Live-Mail
- Add new library: http.rb, Jetty, ocaml-cohttp
- `helpers` submodule:
- Add new method: `getOutlookEdition()` to map Outlook versions to their marketing editions
## Version 2.0.7 ## Version 2.0.7
- Add support for chaining `withClientHints()` & `withFeatureCheck()` - Add support for chaining `withClientHints()` & `withFeatureCheck()`

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1007
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"title": "UAParser.js", "title": "UAParser.js",
"name": "ua-parser-js", "name": "ua-parser-js",
"version": "2.0.7", "version": "2.0.8",
"author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)", "author": "Faisal Salman <f@faisalman.com> (http://faisalman.com)",
"description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment", "description": "Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent & Client Hints data. Supports browser & node.js environment",
"keywords": [ "keywords": [
@@ -222,7 +222,7 @@
} }
}, },
"files": [ "files": [
"dist", "dist/*.?(m)js",
"src" "src"
], ],
"bin": "./script/cli.js", "bin": "./script/cli.js",
@@ -232,9 +232,9 @@
"fuzz": "jazzer ./test/fuzz/redos.js --sync", "fuzz": "jazzer ./test/fuzz/redos.js --sync",
"test": "./script/test-all.sh", "test": "./script/test-all.sh",
"test:dts-lint": "tsd --typings src/main/ua-parser.d.ts --files test/static/dts-lint.ts", "test:dts-lint": "tsd --typings src/main/ua-parser.d.ts --files test/static/dts-lint.ts",
"test:eslint": "eslint src && eslint script", "test:eslint": "eslint --no-config-lookup src",
"test:jshint": "jshint src/main", "test:jshint": "jshint src/main",
"test:lockfile-lint": "npx lockfile-lint -p package-lock.json", "test:lockfile-lint": "lockfile-lint -p package-lock.json",
"test:mocha": "mocha --recursive test/unit", "test:mocha": "mocha --recursive test/unit",
"test:playwright": "npx playwright install && playwright test test/e2e --browser all" "test:playwright": "npx playwright install && playwright test test/e2e --browser all"
}, },
@@ -247,7 +247,9 @@
"@babel/parser": "7.15.8", "@babel/parser": "7.15.8",
"@babel/traverse": "7.23.2", "@babel/traverse": "7.23.2",
"@playwright/test": "^1.57.0", "@playwright/test": "^1.57.0",
"eslint": "^9.39.1",
"jshint": "~2.13.6", "jshint": "~2.13.6",
"lockfile-lint": "^4.14.1",
"mocha": "~8.2.0", "mocha": "~8.2.0",
"requirejs": "2.3.2", "requirejs": "2.3.2",
"safe-regex": "^2.1.1", "safe-regex": "^2.1.1",

View File

@@ -4,6 +4,7 @@ const fs = require('fs');
const defaultReplacements = { const defaultReplacements = {
mjs: [ mjs: [
[/(?<=const.+)(:)(?=.+require)/ig, ' as'],
[/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'\.$2.mjs\''], [/const (.+?)\s*=\s*require\(\'\.(.+)\'\)/ig, 'import $1 from \'\.$2.mjs\''],
[/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2\''], [/const (.+?)\s*=\s*require\(\'(.+)\'\)/ig, 'import $1 from \'$2\''],
[/module\.exports =/ig, 'export'] [/module\.exports =/ig, 'export']

View File

@@ -9,7 +9,7 @@ echo '
- lint js code - lint js code
' '
npm run test:jshint || exit 1 npm run test:jshint || exit 1
#npm run test:eslint || exit 1 npm run test:eslint || exit 1
echo ' echo '
- test using mocha - test using mocha

View File

@@ -1,4 +1,4 @@
// Type definitions for bot-detection submodule of UAParser.js v2.0.7 // Type definitions for bot-detection submodule of UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
////////////////////////////////////////////////// //////////////////////////////////////////////////
/* bot-detection submodule of UAParser.js v2.0.7 /* bot-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/bot-detection/bot-detection.js // Source: /src/bot-detection/bot-detection.js
////////////////////////////////////////////////// //////////////////////////////////////////////////
/* bot-detection submodule of UAParser.js v2.0.7 /* bot-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -1,4 +1,4 @@
// Type definitions for browser-detection submodule of UAParser.js v2.0.7 // Type definitions for browser-detection submodule of UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
/* browser-detection submodule of UAParser.js v2.0.7 /* browser-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/browser-detection/browser-detection.js // Source: /src/browser-detection/browser-detection.js
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
/* browser-detection submodule of UAParser.js v2.0.7 /* browser-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -1,4 +1,4 @@
// Type definitions for device-detection submodule of UAParser.js v2.0.7 // Type definitions for device-detection submodule of UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/* device-detection submodule of UAParser.js v2.0.7 /* device-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/device-detection/device-detection.js // Source: /src/device-detection/device-detection.js
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/* device-detection submodule of UAParser.js v2.0.7 /* device-detection submodule of UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */

View File

@@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.7 /* Enums for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -66,6 +66,7 @@ export const BrowserName: Readonly<{
GOOGLE_SEARCH: 'GSA', GOOGLE_SEARCH: 'GSA',
HELIO: 'Helio', HELIO: 'Helio',
HEYTAP: 'HeyTap', HEYTAP: 'HeyTap',
HIBROWSER: 'HiBrowser',
HONOR: 'Honor', HONOR: 'Honor',
HUAWEI: 'Huawei Browser', HUAWEI: 'Huawei Browser',
ICAB: 'iCab', ICAB: 'iCab',
@@ -116,6 +117,7 @@ export const BrowserName: Readonly<{
OPERA_GX: 'Opera GX', OPERA_GX: 'Opera GX',
OPERA_MINI: 'Opera Mini', OPERA_MINI: 'Opera Mini',
OPERA_MOBI: 'Opera Mobi', OPERA_MOBI: 'Opera Mobi',
OPERA_NEON: 'Opera Neon',
OPERA_TABLET: 'Opera Tablet', OPERA_TABLET: 'Opera Tablet',
OPERA_TOUCH: 'Opera Touch', OPERA_TOUCH: 'Opera Touch',
OTTER: 'Otter', OTTER: 'Otter',
@@ -316,6 +318,7 @@ export const EngineName: Readonly<{
AMAYA: 'Amaya', AMAYA: 'Amaya',
ARKWEB: 'ArkWeb', ARKWEB: 'ArkWeb',
BLINK: 'Blink', BLINK: 'Blink',
DILLO: 'Dillo',
EDGEHTML: 'EdgeHTML', EDGEHTML: 'EdgeHTML',
FLOW: 'Flow', FLOW: 'Flow',
GECKO: 'Gecko', GECKO: 'Gecko',
@@ -451,6 +454,7 @@ export const Extension: Readonly<{
ELINKS: 'ELinks', ELINKS: 'ELinks',
HTTPIE: 'HTTPie', HTTPIE: 'HTTPie',
LYNX: 'Lynx', LYNX: 'Lynx',
POWERSHELL: 'PowerShell',
WGET: 'Wget' WGET: 'Wget'
}, },
Crawler: { Crawler: {
@@ -613,24 +617,66 @@ export const Extension: Readonly<{
}, },
Email: { Email: {
AIRMAIL: 'Airmail', AIRMAIL: 'Airmail',
ALPINE: 'Alpine',
ANDROID_MAIL: 'Android',
APPLE_MAIL: 'Mail', APPLE_MAIL: 'Mail',
AQUA_MAIL: 'AquaMail',
BALSA: 'Balsa',
BARCA: 'Barca',
BLUEMAIL: 'BlueMail', BLUEMAIL: 'BlueMail',
CANARY: 'Canary',
CLAWS_MAIL: 'Claws Mail',
DAUM_MAIL: 'DaumMail', DAUM_MAIL: 'DaumMail',
EVOLUTION: 'Evolution',
EM_CLIENT: 'eM Client', EM_CLIENT: 'eM Client',
EUDORA: 'Eudora',
EVOLUTION: 'Evolution',
FAIR_EMAIL: 'FairEmail',
FOXMAIL: 'Foxmail', FOXMAIL: 'Foxmail',
GEARY: 'Geary',
GNUS: 'Gnus',
HORDE_IMP: 'Horde::IMP',
IBM_NOTES: 'Lotus-Notes',
INCREDIMAIL: 'IncrediMail',
K9_MAIL: 'K-9 Mail',
KMAIL: 'KMail', KMAIL: 'KMail',
KMAIL2: 'kmail2', KMAIL2: 'kmail2',
KONTACT: 'Kontact', KONTACT: 'Kontact',
MAILBIRD: 'Mailbird',
MAILMATE: 'MailMate',
MAILSPRING: 'Mailspring',
MICROSOFT_OUTLOOK: 'Microsoft Outlook', MICROSOFT_OUTLOOK: 'Microsoft Outlook',
MICROSOFT_OUTLOOK_MAC: 'MacOutlook', MICROSOFT_OUTLOOK_MAC: 'MacOutlook',
MUTT: 'Mutt',
NAVER_MAILAPP: 'NaverMailApp', NAVER_MAILAPP: 'NaverMailApp',
NEWTON: 'Newton',
NINE: 'Nine',
NYLAS_MAIL: 'NylasMail',
OUTLOOK_EXPRESS: 'Outlook-Express',
PEGASUS_MAIL: 'Pegasus Mail',
POCOMAIL: 'PocoMail',
POLYMAIL: 'Polymail', POLYMAIL: 'Polymail',
POSTBOX: 'Postbox',
PROTON_MAIL: 'ProtonMail', PROTON_MAIL: 'ProtonMail',
PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',
QUALA_MAIL: 'Quala',
R2MAIL2: 'R2Mail2',
RAINLOOP: 'RainLoop',
ROUNDCUBE: 'Roundcube Webmail',
SAMSUNG_EMAIL: 'SamsungEmail',
SPARK_MAIL: 'SparkDesktop', SPARK_MAIL: 'SparkDesktop',
SPARROW: 'Sparrow', SPARROW: 'Sparrow',
SPICEBIRD: 'Spicebird',
SQUIRRELMAIL: 'SquirrelMail',
SYLPHEED: 'Sylpheed',
THE_BAT: 'The Bat!',
THUNDERBIRD: 'Thunderbird', THUNDERBIRD: 'Thunderbird',
YAHOO_MAIL: 'Yahoo', TROJITA: 'Trojita',
TURNPIKE: 'Turnpike',
TUTANOTA: 'tutanota-desktop',
WANDERLUST: 'Wanderlust',
WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',
YAHOO_MAIL: 'Yahoo Mail',
YAHOO_MAIL_IOS: 'Yahoo Mail',
ZIMBRA: 'Zimbra', ZIMBRA: 'Zimbra',
ZOHO_MAIL: 'ZohoMail-Desktop' ZOHO_MAIL: 'ZohoMail-Desktop'
}, },
@@ -721,8 +767,10 @@ export const Extension: Readonly<{
GOT: 'got', GOT: 'got',
GUZZLEHTTP: 'GuzzleHttp', GUZZLEHTTP: 'GuzzleHttp',
HACKNEY: 'hackney', HACKNEY: 'hackney',
HTTP_RB: 'http.rb',
JAVA: 'Java', JAVA: 'Java',
JAVA_HTTPCLIENT: 'Java-http-client', JAVA_HTTPCLIENT: 'Java-http-client',
JETTY: 'Jetty',
JSDOM: 'jsdom', JSDOM: 'jsdom',
LIBWWW_PERL: 'libwww-perl', LIBWWW_PERL: 'libwww-perl',
LUA_RESTY_HTTP: 'lua-resty-http', LUA_RESTY_HTTP: 'lua-resty-http',
@@ -732,6 +780,7 @@ export const Extension: Readonly<{
NODE_JS: 'Node.js', NODE_JS: 'Node.js',
NODE_SUPERAGENT: 'node-superagent', NODE_SUPERAGENT: 'node-superagent',
OKHTTP: 'OkHttp', OKHTTP: 'OkHttp',
OCAML_COHTTP: 'ocaml-cohttp',
PHP_SOAP: 'PHP-SOAP', PHP_SOAP: 'PHP-SOAP',
POSTMAN_RUNTIME: 'PostmanRuntime', POSTMAN_RUNTIME: 'PostmanRuntime',
PYTHON_HTTPX: 'python-httpx', PYTHON_HTTPX: 'python-httpx',

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.7 /* Enums for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -62,6 +62,7 @@ const BrowserName = Object.freeze({
GOOGLE_SEARCH: 'GSA', GOOGLE_SEARCH: 'GSA',
HELIO: 'Helio', HELIO: 'Helio',
HEYTAP: 'HeyTap', HEYTAP: 'HeyTap',
HIBROWSER: 'HiBrowser',
HONOR: 'Honor', HONOR: 'Honor',
HUAWEI: 'Huawei Browser', HUAWEI: 'Huawei Browser',
ICAB: 'iCab', ICAB: 'iCab',
@@ -112,6 +113,7 @@ const BrowserName = Object.freeze({
OPERA_GX: 'Opera GX', OPERA_GX: 'Opera GX',
OPERA_MINI: 'Opera Mini', OPERA_MINI: 'Opera Mini',
OPERA_MOBI: 'Opera Mobi', OPERA_MOBI: 'Opera Mobi',
OPERA_NEON: 'Opera Neon',
OPERA_TABLET: 'Opera Tablet', OPERA_TABLET: 'Opera Tablet',
OPERA_TOUCH: 'Opera Touch', OPERA_TOUCH: 'Opera Touch',
OTTER: 'Otter', OTTER: 'Otter',
@@ -312,6 +314,7 @@ const EngineName = Object.freeze({
AMAYA: 'Amaya', AMAYA: 'Amaya',
ARKWEB: 'ArkWeb', ARKWEB: 'ArkWeb',
BLINK: 'Blink', BLINK: 'Blink',
DILLO: 'Dillo',
EDGEHTML: 'EdgeHTML', EDGEHTML: 'EdgeHTML',
FLOW: 'Flow', FLOW: 'Flow',
GECKO: 'Gecko', GECKO: 'Gecko',
@@ -447,6 +450,7 @@ const Extension = Object.freeze({
ELINKS: 'ELinks', ELINKS: 'ELinks',
HTTPIE: 'HTTPie', HTTPIE: 'HTTPie',
LYNX: 'Lynx', LYNX: 'Lynx',
POWERSHELL: 'PowerShell',
WGET: 'Wget' WGET: 'Wget'
}, },
Crawler: { Crawler: {
@@ -609,24 +613,66 @@ const Extension = Object.freeze({
}, },
Email: { Email: {
AIRMAIL: 'Airmail', AIRMAIL: 'Airmail',
ALPINE: 'Alpine',
ANDROID_MAIL: 'Android',
APPLE_MAIL: 'Mail', APPLE_MAIL: 'Mail',
AQUA_MAIL: 'AquaMail',
BALSA: 'Balsa',
BARCA: 'Barca',
BLUEMAIL: 'BlueMail', BLUEMAIL: 'BlueMail',
CANARY: 'Canary',
CLAWS_MAIL: 'Claws Mail',
DAUM_MAIL: 'DaumMail', DAUM_MAIL: 'DaumMail',
EVOLUTION: 'Evolution',
EM_CLIENT: 'eM Client', EM_CLIENT: 'eM Client',
EUDORA: 'Eudora',
EVOLUTION: 'Evolution',
FAIR_EMAIL: 'FairEmail',
FOXMAIL: 'Foxmail', FOXMAIL: 'Foxmail',
GEARY: 'Geary',
GNUS: 'Gnus',
HORDE_IMP: 'Horde::IMP',
IBM_NOTES: 'Lotus-Notes',
INCREDIMAIL: 'IncrediMail',
K9_MAIL: 'K-9 Mail',
KMAIL: 'KMail', KMAIL: 'KMail',
KMAIL2: 'kmail2', KMAIL2: 'kmail2',
KONTACT: 'Kontact', KONTACT: 'Kontact',
MAILBIRD: 'Mailbird',
MAILMATE: 'MailMate',
MAILSPRING: 'Mailspring',
MICROSOFT_OUTLOOK: 'Microsoft Outlook', MICROSOFT_OUTLOOK: 'Microsoft Outlook',
MICROSOFT_OUTLOOK_MAC: 'MacOutlook', MICROSOFT_OUTLOOK_MAC: 'MacOutlook',
MUTT: 'Mutt',
NAVER_MAILAPP: 'NaverMailApp', NAVER_MAILAPP: 'NaverMailApp',
NEWTON: 'Newton',
NINE: 'Nine',
NYLAS_MAIL: 'NylasMail',
OUTLOOK_EXPRESS: 'Outlook-Express',
PEGASUS_MAIL: 'Pegasus Mail',
POCOMAIL: 'PocoMail',
POLYMAIL: 'Polymail', POLYMAIL: 'Polymail',
POSTBOX: 'Postbox',
PROTON_MAIL: 'ProtonMail', PROTON_MAIL: 'ProtonMail',
PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',
QUALA_MAIL: 'Quala',
R2MAIL2: 'R2Mail2',
RAINLOOP: 'RainLoop',
ROUNDCUBE: 'Roundcube Webmail',
SAMSUNG_EMAIL: 'SamsungEmail',
SPARK_MAIL: 'SparkDesktop', SPARK_MAIL: 'SparkDesktop',
SPARROW: 'Sparrow', SPARROW: 'Sparrow',
SPICEBIRD: 'Spicebird',
SQUIRRELMAIL: 'SquirrelMail',
SYLPHEED: 'Sylpheed',
THE_BAT: 'The Bat!',
THUNDERBIRD: 'Thunderbird', THUNDERBIRD: 'Thunderbird',
YAHOO_MAIL: 'Yahoo', TROJITA: 'Trojita',
TURNPIKE: 'Turnpike',
TUTANOTA: 'tutanota-desktop',
WANDERLUST: 'Wanderlust',
WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',
YAHOO_MAIL: 'Yahoo Mail',
YAHOO_MAIL_IOS: 'Yahoo Mail',
ZIMBRA: 'Zimbra', ZIMBRA: 'Zimbra',
ZOHO_MAIL: 'ZohoMail-Desktop' ZOHO_MAIL: 'ZohoMail-Desktop'
}, },
@@ -717,8 +763,10 @@ const Extension = Object.freeze({
GOT: 'got', GOT: 'got',
GUZZLEHTTP: 'GuzzleHttp', GUZZLEHTTP: 'GuzzleHttp',
HACKNEY: 'hackney', HACKNEY: 'hackney',
HTTP_RB: 'http.rb',
JAVA: 'Java', JAVA: 'Java',
JAVA_HTTPCLIENT: 'Java-http-client', JAVA_HTTPCLIENT: 'Java-http-client',
JETTY: 'Jetty',
JSDOM: 'jsdom', JSDOM: 'jsdom',
LIBWWW_PERL: 'libwww-perl', LIBWWW_PERL: 'libwww-perl',
LUA_RESTY_HTTP: 'lua-resty-http', LUA_RESTY_HTTP: 'lua-resty-http',
@@ -728,6 +776,7 @@ const Extension = Object.freeze({
NODE_JS: 'Node.js', NODE_JS: 'Node.js',
NODE_SUPERAGENT: 'node-superagent', NODE_SUPERAGENT: 'node-superagent',
OKHTTP: 'OkHttp', OKHTTP: 'OkHttp',
OCAML_COHTTP: 'ocaml-cohttp',
PHP_SOAP: 'PHP-SOAP', PHP_SOAP: 'PHP-SOAP',
POSTMAN_RUNTIME: 'PostmanRuntime', POSTMAN_RUNTIME: 'PostmanRuntime',
PYTHON_HTTPX: 'python-httpx', PYTHON_HTTPX: 'python-httpx',

View File

@@ -3,7 +3,7 @@
// Source: /src/enums/ua-parser-enums.js // Source: /src/enums/ua-parser-enums.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.7 /* Enums for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -66,6 +66,7 @@ const BrowserName = Object.freeze({
GOOGLE_SEARCH: 'GSA', GOOGLE_SEARCH: 'GSA',
HELIO: 'Helio', HELIO: 'Helio',
HEYTAP: 'HeyTap', HEYTAP: 'HeyTap',
HIBROWSER: 'HiBrowser',
HONOR: 'Honor', HONOR: 'Honor',
HUAWEI: 'Huawei Browser', HUAWEI: 'Huawei Browser',
ICAB: 'iCab', ICAB: 'iCab',
@@ -116,6 +117,7 @@ const BrowserName = Object.freeze({
OPERA_GX: 'Opera GX', OPERA_GX: 'Opera GX',
OPERA_MINI: 'Opera Mini', OPERA_MINI: 'Opera Mini',
OPERA_MOBI: 'Opera Mobi', OPERA_MOBI: 'Opera Mobi',
OPERA_NEON: 'Opera Neon',
OPERA_TABLET: 'Opera Tablet', OPERA_TABLET: 'Opera Tablet',
OPERA_TOUCH: 'Opera Touch', OPERA_TOUCH: 'Opera Touch',
OTTER: 'Otter', OTTER: 'Otter',
@@ -316,6 +318,7 @@ const EngineName = Object.freeze({
AMAYA: 'Amaya', AMAYA: 'Amaya',
ARKWEB: 'ArkWeb', ARKWEB: 'ArkWeb',
BLINK: 'Blink', BLINK: 'Blink',
DILLO: 'Dillo',
EDGEHTML: 'EdgeHTML', EDGEHTML: 'EdgeHTML',
FLOW: 'Flow', FLOW: 'Flow',
GECKO: 'Gecko', GECKO: 'Gecko',
@@ -451,6 +454,7 @@ const Extension = Object.freeze({
ELINKS: 'ELinks', ELINKS: 'ELinks',
HTTPIE: 'HTTPie', HTTPIE: 'HTTPie',
LYNX: 'Lynx', LYNX: 'Lynx',
POWERSHELL: 'PowerShell',
WGET: 'Wget' WGET: 'Wget'
}, },
Crawler: { Crawler: {
@@ -613,24 +617,66 @@ const Extension = Object.freeze({
}, },
Email: { Email: {
AIRMAIL: 'Airmail', AIRMAIL: 'Airmail',
ALPINE: 'Alpine',
ANDROID_MAIL: 'Android',
APPLE_MAIL: 'Mail', APPLE_MAIL: 'Mail',
AQUA_MAIL: 'AquaMail',
BALSA: 'Balsa',
BARCA: 'Barca',
BLUEMAIL: 'BlueMail', BLUEMAIL: 'BlueMail',
CANARY: 'Canary',
CLAWS_MAIL: 'Claws Mail',
DAUM_MAIL: 'DaumMail', DAUM_MAIL: 'DaumMail',
EVOLUTION: 'Evolution',
EM_CLIENT: 'eM Client', EM_CLIENT: 'eM Client',
EUDORA: 'Eudora',
EVOLUTION: 'Evolution',
FAIR_EMAIL: 'FairEmail',
FOXMAIL: 'Foxmail', FOXMAIL: 'Foxmail',
GEARY: 'Geary',
GNUS: 'Gnus',
HORDE_IMP: 'Horde::IMP',
IBM_NOTES: 'Lotus-Notes',
INCREDIMAIL: 'IncrediMail',
K9_MAIL: 'K-9 Mail',
KMAIL: 'KMail', KMAIL: 'KMail',
KMAIL2: 'kmail2', KMAIL2: 'kmail2',
KONTACT: 'Kontact', KONTACT: 'Kontact',
MAILBIRD: 'Mailbird',
MAILMATE: 'MailMate',
MAILSPRING: 'Mailspring',
MICROSOFT_OUTLOOK: 'Microsoft Outlook', MICROSOFT_OUTLOOK: 'Microsoft Outlook',
MICROSOFT_OUTLOOK_MAC: 'MacOutlook', MICROSOFT_OUTLOOK_MAC: 'MacOutlook',
MUTT: 'Mutt',
NAVER_MAILAPP: 'NaverMailApp', NAVER_MAILAPP: 'NaverMailApp',
NEWTON: 'Newton',
NINE: 'Nine',
NYLAS_MAIL: 'NylasMail',
OUTLOOK_EXPRESS: 'Outlook-Express',
PEGASUS_MAIL: 'Pegasus Mail',
POCOMAIL: 'PocoMail',
POLYMAIL: 'Polymail', POLYMAIL: 'Polymail',
POSTBOX: 'Postbox',
PROTON_MAIL: 'ProtonMail', PROTON_MAIL: 'ProtonMail',
PROTON_MAIL_BRIDGE: 'ProtonMail Bridge',
QUALA_MAIL: 'Quala',
R2MAIL2: 'R2Mail2',
RAINLOOP: 'RainLoop',
ROUNDCUBE: 'Roundcube Webmail',
SAMSUNG_EMAIL: 'SamsungEmail',
SPARK_MAIL: 'SparkDesktop', SPARK_MAIL: 'SparkDesktop',
SPARROW: 'Sparrow', SPARROW: 'Sparrow',
SPICEBIRD: 'Spicebird',
SQUIRRELMAIL: 'SquirrelMail',
SYLPHEED: 'Sylpheed',
THE_BAT: 'The Bat!',
THUNDERBIRD: 'Thunderbird', THUNDERBIRD: 'Thunderbird',
YAHOO_MAIL: 'Yahoo', TROJITA: 'Trojita',
TURNPIKE: 'Turnpike',
TUTANOTA: 'tutanota-desktop',
WANDERLUST: 'Wanderlust',
WINDOWS_LIVE_MAIL: 'Windows-Live-Mail',
YAHOO_MAIL: 'Yahoo Mail',
YAHOO_MAIL_IOS: 'Yahoo Mail',
ZIMBRA: 'Zimbra', ZIMBRA: 'Zimbra',
ZOHO_MAIL: 'ZohoMail-Desktop' ZOHO_MAIL: 'ZohoMail-Desktop'
}, },
@@ -721,8 +767,10 @@ const Extension = Object.freeze({
GOT: 'got', GOT: 'got',
GUZZLEHTTP: 'GuzzleHttp', GUZZLEHTTP: 'GuzzleHttp',
HACKNEY: 'hackney', HACKNEY: 'hackney',
HTTP_RB: 'http.rb',
JAVA: 'Java', JAVA: 'Java',
JAVA_HTTPCLIENT: 'Java-http-client', JAVA_HTTPCLIENT: 'Java-http-client',
JETTY: 'Jetty',
JSDOM: 'jsdom', JSDOM: 'jsdom',
LIBWWW_PERL: 'libwww-perl', LIBWWW_PERL: 'libwww-perl',
LUA_RESTY_HTTP: 'lua-resty-http', LUA_RESTY_HTTP: 'lua-resty-http',
@@ -732,6 +780,7 @@ const Extension = Object.freeze({
NODE_JS: 'Node.js', NODE_JS: 'Node.js',
NODE_SUPERAGENT: 'node-superagent', NODE_SUPERAGENT: 'node-superagent',
OKHTTP: 'OkHttp', OKHTTP: 'OkHttp',
OCAML_COHTTP: 'ocaml-cohttp',
PHP_SOAP: 'PHP-SOAP', PHP_SOAP: 'PHP-SOAP',
POSTMAN_RUNTIME: 'PostmanRuntime', POSTMAN_RUNTIME: 'PostmanRuntime',
PYTHON_HTTPX: 'python-httpx', PYTHON_HTTPX: 'python-httpx',

View File

@@ -1,4 +1,4 @@
// Type definitions for Helpers submodule of UAParser.js v2.0.5 // Type definitions for Helpers submodule of UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.7 /* Extensions for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -22,14 +22,27 @@ const INAPP = 'inapp';
const MEDIAPLAYER = 'mediaplayer'; const MEDIAPLAYER = 'mediaplayer';
const LIBRARY = 'library'; const LIBRARY = 'library';
// Helper to normalize specific email client names
const normalizeEmailName = function (str) {
const map = {
'YahooMobile': 'Yahoo Mail',
'YahooMail': 'Yahoo Mail',
'K-9': 'K-9 Mail',
'K-9 Mail': 'K-9 Mail',
'Zdesktop': 'Zimbra',
'zdesktop': 'Zimbra'
};
return map[str] || str;
};
////////////////////// //////////////////////
// COMMAND LINE APPS // COMMAND LINE APPS
///////////////////// /////////////////////
const CLIs = Object.freeze({ const CLIs = Object.freeze({
browser : [ browser : [
// wget / curl / Lynx / ELinks / HTTPie // wget / curl / Lynx / ELinks / HTTPie / PowerShell
[/(wget|curl|lynx|elinks|httpie)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]] [/(wget|curl|lynx|elinks|httpie|powershell)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]
] ]
}); });
@@ -229,25 +242,55 @@ const ExtraDevices = Object.freeze({
] ]
}); });
/////////////// //////////////
// EMAIL APPS // EMAIL APPS
////////////// //////////////
const Emails = Object.freeze({ const Emails = Object.freeze({
browser : [ browser : [
// 1. Specific Android Mail Rule
[/(android)\/([\w\.-]+email)/i],
[NAME, VERSION, [TYPE, EMAIL]],
// 2. Standard Email Clients
[ [
// Evolution / Kontact/KMail[2] / [Microsoft/Mac] Outlook / Thunderbird new RegExp(
// Airmail / BlueMail / DaumMail / eMClient / Foxmail / NaverMailApp / Polymail '(' +
// ProtonMail / SparkDesktop / Sparrow / Yahoo! Mail / Zimbra / ZohoMail-Desktop // Clients ending in 'mail' (Case 1: Prefix + optional space + [e]mail)
/((?:air|blue|daum|fox|poly|proton)mail|emclient|evolution|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|sparkdesktop|thunderbird|yahoo|zohomail-desktop)(?:m.+ail; |[\/ ])([\w\.]+)/i, // Covers: AirMail, Claws Mail, FairEmail, SamsungEmail, Yahoo Mail, etc.
'(?:air|aqua|blue|claws|daum|fair|fox|k-9|mac|nylas|pegasus|poco|poly|proton|samsung|squirrel|yahoo) ?e?mail(?:-desktop| app| bridge)?|' +
// Standalone / Specific Names
'microsoft outlook|r2mail2|spicebird|turnpike|yahoomobile|' +
// Microsoft & Outlook Variants
'(?:microsoft )?outlook(?:-express)?|macoutlook|windows-live-mail|' +
// Specific Clients
'alpine|balsa|barca|canary|emclient|eudora|evolution|geary|gnus|' +
'horde::imp|incredimail|kmail2?|kontact|lotus-notes|' +
'mail(?:bird|mate|spring)|mutt|navermailapp|newton|nine|postbox|' +
'rainloop|roundcube webmail|spar(?:row|kdesktop)|sylpheed|' +
'the bat!|thunderbird|trojita|tutanota-desktop|wanderlust|' +
'zdesktop|zohomail-desktop' +
')' +
// Separator
'(?:m.+ail; |[\\/ ])' +
// Version (Updated to allow hyphens for Turnpike)
'([\\w\\.-]+)',
'i'
)
],
[
[NAME, normalizeEmailName],
VERSION,
[TYPE, EMAIL]
],
// Apple's Mail // 3. Apple Mail Context
/(mail)\/([\w\.]+) cf/i [/(mail)\/([\w\.]+) cf/i],
], [NAME, VERSION, [TYPE, EMAIL]], [ [NAME, VERSION, [TYPE, EMAIL]],
// Zimbra // 4. Zimbra Server
/zdesktop\/([\w\.]+)/i [/(zimbra)\/([\w\.-]+)/i],
], [VERSION, [NAME, 'Zimbra'], [TYPE, EMAIL]] [NAME, VERSION, [TYPE, EMAIL]]
] ]
}); });
@@ -390,8 +433,8 @@ const MediaPlayers = Object.freeze({
const Libraries = Object.freeze({ const Libraries = Object.freeze({
browser : [ browser : [
[ [
// Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/Java[-HttpClient]/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent // Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/http.rb/Java[-HttpClient]/Jetty/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/ocaml-cohttp/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent
/^(apache-httpclient|axios|bun|dart|deno|(?:go|java)-http-client|got|guzzlehttp|hackney|java|libwww-perl|lua-resty-http|needle|node(?:\.js|-fetch|-superagent)|okhttp|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\/([\w\.]+)/i, /^((?:apache|go|java)-http-?client|axios|bun|dart|deno|got|(?:guzzle|lua-resty-|ocaml-co|ok)http|hackney|http\.rb|java|jetty|libwww-perl|needle|node(?:\.js|-fetch|-superagent)|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\/([\w\.]+)/i,
/(adobeair|aiohttp|jsdom)\/([\w\.]+)/i, /(adobeair|aiohttp|jsdom)\/([\w\.]+)/i,
/(nutch)-([\w\.-]+)(\(|$)/i, /(nutch)-([\w\.-]+)(\(|$)/i,
/\((java)\/([\w\.]+)/i /\((java)\/([\w\.]+)/i

View File

@@ -3,7 +3,7 @@
// Source: /src/extensions/ua-parser-extensions.js // Source: /src/extensions/ua-parser-extensions.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.7 /* Extensions for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -26,14 +26,27 @@ const INAPP = 'inapp';
const MEDIAPLAYER = 'mediaplayer'; const MEDIAPLAYER = 'mediaplayer';
const LIBRARY = 'library'; const LIBRARY = 'library';
// Helper to normalize specific email client names
const normalizeEmailName = function (str) {
const map = {
'YahooMobile': 'Yahoo Mail',
'YahooMail': 'Yahoo Mail',
'K-9': 'K-9 Mail',
'K-9 Mail': 'K-9 Mail',
'Zdesktop': 'Zimbra',
'zdesktop': 'Zimbra'
};
return map[str] || str;
};
////////////////////// //////////////////////
// COMMAND LINE APPS // COMMAND LINE APPS
///////////////////// /////////////////////
const CLIs = Object.freeze({ const CLIs = Object.freeze({
browser : [ browser : [
// wget / curl / Lynx / ELinks / HTTPie // wget / curl / Lynx / ELinks / HTTPie / PowerShell
[/(wget|curl|lynx|elinks|httpie)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]] [/(wget|curl|lynx|elinks|httpie|powershell)[\/ ]\(?([\w\.-]+)/i], [NAME, VERSION, [TYPE, CLI]]
] ]
}); });
@@ -233,25 +246,55 @@ const ExtraDevices = Object.freeze({
] ]
}); });
/////////////// //////////////
// EMAIL APPS // EMAIL APPS
////////////// //////////////
const Emails = Object.freeze({ const Emails = Object.freeze({
browser : [ browser : [
// 1. Specific Android Mail Rule
[/(android)\/([\w\.-]+email)/i],
[NAME, VERSION, [TYPE, EMAIL]],
// 2. Standard Email Clients
[ [
// Evolution / Kontact/KMail[2] / [Microsoft/Mac] Outlook / Thunderbird new RegExp(
// Airmail / BlueMail / DaumMail / eMClient / Foxmail / NaverMailApp / Polymail '(' +
// ProtonMail / SparkDesktop / Sparrow / Yahoo! Mail / Zimbra / ZohoMail-Desktop // Clients ending in 'mail' (Case 1: Prefix + optional space + [e]mail)
/((?:air|blue|daum|fox|poly|proton)mail|emclient|evolution|kmail2?|kontact|(?:microsoft |mac)?outlook(?:-express)?|navermailapp|(?!chrom.+)sparrow|sparkdesktop|thunderbird|yahoo|zohomail-desktop)(?:m.+ail; |[\/ ])([\w\.]+)/i, // Covers: AirMail, Claws Mail, FairEmail, SamsungEmail, Yahoo Mail, etc.
'(?:air|aqua|blue|claws|daum|fair|fox|k-9|mac|nylas|pegasus|poco|poly|proton|samsung|squirrel|yahoo) ?e?mail(?:-desktop| app| bridge)?|' +
// Standalone / Specific Names
'microsoft outlook|r2mail2|spicebird|turnpike|yahoomobile|' +
// Microsoft & Outlook Variants
'(?:microsoft )?outlook(?:-express)?|macoutlook|windows-live-mail|' +
// Specific Clients
'alpine|balsa|barca|canary|emclient|eudora|evolution|geary|gnus|' +
'horde::imp|incredimail|kmail2?|kontact|lotus-notes|' +
'mail(?:bird|mate|spring)|mutt|navermailapp|newton|nine|postbox|' +
'rainloop|roundcube webmail|spar(?:row|kdesktop)|sylpheed|' +
'the bat!|thunderbird|trojita|tutanota-desktop|wanderlust|' +
'zdesktop|zohomail-desktop' +
')' +
// Separator
'(?:m.+ail; |[\\/ ])' +
// Version (Updated to allow hyphens for Turnpike)
'([\\w\\.-]+)',
'i'
)
],
[
[NAME, normalizeEmailName],
VERSION,
[TYPE, EMAIL]
],
// Apple's Mail // 3. Apple Mail Context
/(mail)\/([\w\.]+) cf/i [/(mail)\/([\w\.]+) cf/i],
], [NAME, VERSION, [TYPE, EMAIL]], [ [NAME, VERSION, [TYPE, EMAIL]],
// Zimbra // 4. Zimbra Server
/zdesktop\/([\w\.]+)/i [/(zimbra)\/([\w\.-]+)/i],
], [VERSION, [NAME, 'Zimbra'], [TYPE, EMAIL]] [NAME, VERSION, [TYPE, EMAIL]]
] ]
}); });
@@ -394,8 +437,8 @@ const MediaPlayers = Object.freeze({
const Libraries = Object.freeze({ const Libraries = Object.freeze({
browser : [ browser : [
[ [
// Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/Java[-HttpClient]/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent // Apache-HttpClient/Axios/Bun/Dart/go-http-client/got/GuzzleHttp/hackney/http.rb/Java[-HttpClient]/Jetty/jsdom/libwww-perl/lua-resty-http/Needle/Node.js/node-fetch/ocaml-cohttp/OkHttp/PHP-SOAP/PostmanRuntime/python-urllib/python-requests/rest-client/Scrapy/superagent
/^(apache-httpclient|axios|bun|dart|deno|(?:go|java)-http-client|got|guzzlehttp|hackney|java|libwww-perl|lua-resty-http|needle|node(?:\.js|-fetch|-superagent)|okhttp|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\/([\w\.]+)/i, /^((?:apache|go|java)-http-?client|axios|bun|dart|deno|got|(?:guzzle|lua-resty-|ocaml-co|ok)http|hackney|http\.rb|java|jetty|libwww-perl|needle|node(?:\.js|-fetch|-superagent)|php-soap|postmanruntime|python-(?:httpx|urllib[23]?|requests)|rest-client|scrapy)\/([\w\.]+)/i,
/(adobeair|aiohttp|jsdom)\/([\w\.]+)/i, /(adobeair|aiohttp|jsdom)\/([\w\.]+)/i,
/(nutch)-([\w\.-]+)(\(|$)/i, /(nutch)-([\w\.-]+)(\(|$)/i,
/\((java)\/([\w\.]+)/i /\((java)\/([\w\.]+)/i

View File

@@ -1,9 +1,10 @@
// Type definitions for Helpers submodule of UAParser.js v2.0.5 // Type definitions for Helpers submodule of UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>
import type { IResult } from "../main/ua-parser"; import type { IResult } from "../main/ua-parser";
export function getOutlookEdition(name: string, version: string): string;
export function isFrozenUA(ua: string): boolean; export function isFrozenUA(ua: string): boolean;
/** /**

View File

@@ -1,5 +1,5 @@
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.7 /* Helpers for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -7,8 +7,6 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
const { UAParser } = require('../main/ua-parser');
const { EngineName } = require('../enums/ua-parser-enums');
const { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } = require('../device-detection/device-detection'); const { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } = require('../device-detection/device-detection');
const { isBot: _isBot, isAICrawler } = require('../bot-detection/bot-detection'); const { isBot: _isBot, isAICrawler } = require('../bot-detection/bot-detection');
const { isChromeFamily: _isChromeFamily, isElectron: _isElectron, isStandalonePWA: _isStandalonePWA } = require('../browser-detection/browser-detection'); const { isChromeFamily: _isChromeFamily, isElectron: _isElectron, isStandalonePWA: _isStandalonePWA } = require('../browser-detection/browser-detection');
@@ -55,6 +53,50 @@ const isFromEU = _isFromEU;
*/ */
const isStandalonePWA = _isStandalonePWA; const isStandalonePWA = _isStandalonePWA;
/**
* Translates a raw Outlook User-Agent name/version into a
* Developer-friendly Edition (e.g., "Outlook 2019 (Modern Word)").
*/
const getOutlookEdition = (name, version) => {
if (!name || !version) return name;
const cleanName = name.toLowerCase().replace(/microsoft\s+/, '');
// 1. Handle Mac Separately (Different Rendering Engine)
if (cleanName === 'macoutlook') {
const major = parseInt(version.split('.')[0], 10);
if (major >= 16) return "Outlook for Mac (Modern)";
return "Outlook for Mac (Legacy)";
}
// 2. Handle Windows Outlook
if (cleanName === 'outlook') {
const parts = version.split('.').map(Number);
const major = parts[0];
const build = parts[2] || 0; // Build number is usually the 3rd part
// Pre-2016 Versions (Clear Major Version mapping)
if (major === 15) return "Outlook 2013";
if (major === 14) return "Outlook 2010";
if (major === 12) return "Outlook 2007";
if (major < 12) return "Outlook (Legacy)";
// The Version 16.0 Confusion
if (major === 16) {
// Build < 10000 = MSI (Volume License 2016/2019)
// These render poorly (No SVG, older bugs)
if (build < 10000) {
return "Outlook 2016 (MSI / Volume License)";
}
// Build >= 10000 = Click-to-Run (Retail 2016 / 2019 / 365)
// These render well (SVG support, modern CSS)
return "Outlook 365 / 2019+ (Modern)";
}
}
// 3. Fallback for 'Outlook Express' or 'New Outlook' (Browser)
return name;
};
module.exports = { module.exports = {
getDeviceVendor, getDeviceVendor,
isAppleSilicon, isAppleSilicon,
@@ -64,5 +106,6 @@ module.exports = {
isElectron, isElectron,
isFromEU, isFromEU,
isFrozenUA, isFrozenUA,
isStandalonePWA isStandalonePWA,
getOutlookEdition
} }

View File

@@ -3,7 +3,7 @@
// Source: /src/helpers/ua-parser-helpers.js // Source: /src/helpers/ua-parser-helpers.js
/////////////////////////////////////////////// ///////////////////////////////////////////////
/* Helpers for UAParser.js v2.0.7 /* Helpers for UAParser.js v2.0.8
https://github.com/faisalman/ua-parser-js https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com> Author: Faisal Salman <f@faisalman.com>
AGPLv3 License */ AGPLv3 License */
@@ -11,12 +11,10 @@
/*jshint esversion: 6 */ /*jshint esversion: 6 */
import { UAParser } from '../main/ua-parser.mjs'; import { getDeviceVendor as _getDeviceVendor, isAppleSilicon as _isAppleSilicon } from '../device-detection/device-detection.mjs';
import { EngineName } from '../enums/ua-parser-enums.mjs'; import { isBot as _isBot, isAICrawler } from '../bot-detection/bot-detection.mjs';
import { getDeviceVendor: _getDeviceVendor, isAppleSilicon: _isAppleSilicon } from '../device-detection/device-detection.mjs'; import { isChromeFamily as _isChromeFamily, isElectron as _isElectron, isStandalonePWA as _isStandalonePWA } from '../browser-detection/browser-detection.mjs';
import { isBot: _isBot, isAICrawler } from '../bot-detection/bot-detection.mjs'; import { isFromEU as _isFromEU } from '../browser-detection/browser-detection.mjs';
import { isChromeFamily: _isChromeFamily, isElectron: _isElectron, isStandalonePWA: _isStandalonePWA } from '../browser-detection/browser-detection.mjs';
import { isFromEU: _isFromEU } from '../browser-detection/browser-detection.mjs';
import { isFrozenUA } from 'ua-is-frozen'; import { isFrozenUA } from 'ua-is-frozen';
/** /**
@@ -59,6 +57,50 @@ const isFromEU = _isFromEU;
*/ */
const isStandalonePWA = _isStandalonePWA; const isStandalonePWA = _isStandalonePWA;
/**
* Translates a raw Outlook User-Agent name/version into a
* Developer-friendly Edition (e.g., "Outlook 2019 (Modern Word)").
*/
const getOutlookEdition = (name, version) => {
if (!name || !version) return name;
const cleanName = name.toLowerCase().replace(/microsoft\s+/, '');
// 1. Handle Mac Separately (Different Rendering Engine)
if (cleanName === 'macoutlook') {
const major = parseInt(version.split('.')[0], 10);
if (major >= 16) return "Outlook for Mac (Modern)";
return "Outlook for Mac (Legacy)";
}
// 2. Handle Windows Outlook
if (cleanName === 'outlook') {
const parts = version.split('.').map(Number);
const major = parts[0];
const build = parts[2] || 0; // Build number is usually the 3rd part
// Pre-2016 Versions (Clear Major Version mapping)
if (major === 15) return "Outlook 2013";
if (major === 14) return "Outlook 2010";
if (major === 12) return "Outlook 2007";
if (major < 12) return "Outlook (Legacy)";
// The Version 16.0 Confusion
if (major === 16) {
// Build < 10000 = MSI (Volume License 2016/2019)
// These render poorly (No SVG, older bugs)
if (build < 10000) {
return "Outlook 2016 (MSI / Volume License)";
}
// Build >= 10000 = Click-to-Run (Retail 2016 / 2019 / 365)
// These render well (SVG support, modern CSS)
return "Outlook 365 / 2019+ (Modern)";
}
}
// 3. Fallback for 'Outlook Express' or 'New Outlook' (Browser)
return name;
};
export { export {
getDeviceVendor, getDeviceVendor,
isAppleSilicon, isAppleSilicon,
@@ -68,5 +110,6 @@ export {
isElectron, isElectron,
isFromEU, isFromEU,
isFrozenUA, isFrozenUA,
isStandalonePWA isStandalonePWA,
getOutlookEdition
} }

View File

@@ -1,4 +1,4 @@
// Type definitions for UAParser.js v2.0.7 // Type definitions for UAParser.js v2.0.8
// Project: https://github.com/faisalman/ua-parser-js // Project: https://github.com/faisalman/ua-parser-js
// Definitions by: Faisal Salman <https://github.com/faisalman> // Definitions by: Faisal Salman <https://github.com/faisalman>

View File

@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.7 /* UAParser.js v2.0.8
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -19,7 +19,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.7', var LIBVERSION = '2.0.8',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',
@@ -375,9 +375,10 @@
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon/HiBrowser
/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i, /(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\/v?([-\w\.]+)/i,
// Atlas/Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon // Atlas/Rekonq/Puffin/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
/(brave)(?: chrome)?\/([\d\.]+)/i, // Brave
/(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf /(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant /(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo /(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
@@ -404,7 +405,9 @@
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [ ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
/\bfocus\/([\w\.]+)/i // Firefox Focus /\bfocus\/([\w\.]+)/i // Firefox Focus
], [VERSION, [NAME, FIREFOX+' Focus']], [ ], [VERSION, [NAME, FIREFOX+' Focus']], [
/\bopt\/([\w\.]+)/i // Opera Touch / mms\/([\w\.]+)$/i // Opera Neon
], [VERSION, [NAME, OPERA+' Neon']], [
/ opt\/([\w\.]+)$/i // Opera Touch
], [VERSION, [NAME, OPERA+' Touch']], [ ], [VERSION, [NAME, OPERA+' Touch']], [
/coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
], [VERSION, [NAME, 'Coc Coc']], [ ], [VERSION, [NAME, 'Coc Coc']], [
@@ -453,7 +456,7 @@
], [NAME, VERSION, [TYPE, INAPP]], [ ], [NAME, VERSION, [TYPE, INAPP]], [
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok /(?:musical_ly|trill)(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [ ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
], [NAME, [TYPE, INAPP]], [ ], [NAME, [TYPE, INAPP]], [
@@ -608,7 +611,7 @@
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
// OnePlus // OnePlus
/droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i, /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-l]\w[1m]10)\b/i,
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
@@ -648,7 +651,7 @@
], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
// LG // LG
/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i /\b(?:lg)?([vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
/\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i, /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
@@ -939,7 +942,7 @@
/(presto)\/([\w\.]+)/i, // Presto /(presto)\/([\w\.]+)/i, // Presto
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
/ekioh(flow)\/([\w\.]+)/i, // Flow /ekioh(flow)\/([\w\.]+)/i, // Flow
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(khtml|tasman|links|dillo)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links/Dillo
/(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
/\b(libweb)/i // LibWeb /\b(libweb)/i // LibWeb
@@ -1001,7 +1004,7 @@
], [VERSION, [NAME, BLACKBERRY]], [ ], [VERSION, [NAME, BLACKBERRY]], [
/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian
], [VERSION, [NAME, 'Symbian']], [ ], [VERSION, [NAME, 'Symbian']], [
/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS /mozilla\/[\d\.]+ \((?:mobile[;\w ]*|tablet|tv|[^\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\w\.]+)\).+gecko\//i // Firefox OS
], [VERSION, [NAME, FIREFOX+' OS']], [ ], [VERSION, [NAME, FIREFOX+' OS']], [
/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
/webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
@@ -1017,7 +1020,6 @@
], [[NAME, "Chrome OS"], VERSION],[ ], [[NAME, "Chrome OS"], VERSION],[
// Smart TVs // Smart TVs
/panasonic;(viera)/i, // Panasonic Viera
/(netrange)mmh/i, // Netrange /(netrange)mmh/i, // Netrange
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV

View File

@@ -3,7 +3,7 @@
// Source: /src/main/ua-parser.js // Source: /src/main/ua-parser.js
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.7 /* UAParser.js v2.0.8
Copyright © 2012-2025 Faisal Salman <f@faisalman.com> Copyright © 2012-2025 Faisal Salman <f@faisalman.com>
AGPLv3 License *//* AGPLv3 License *//*
Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data. Detect Browser, Engine, OS, CPU, and Device type/model from User-Agent data.
@@ -21,7 +21,7 @@
// Constants // Constants
///////////// /////////////
var LIBVERSION = '2.0.7', var LIBVERSION = '2.0.8',
UA_MAX_LENGTH = 500, UA_MAX_LENGTH = 500,
USER_AGENT = 'user-agent', USER_AGENT = 'user-agent',
EMPTY = '', EMPTY = '',
@@ -377,9 +377,10 @@
/(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i, // Avant/IEMobile/SlimBrowser/SlimBoat/Slimjet
/(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer /(?:ms|\()(ie) ([\w\.]+)/i, // Internet Explorer
// Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon // Blink/Webkit/KHTML based // Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser/QupZilla/Falkon/LG Browser/Otter/qutebrowser/Dooble/Palemoon/HiBrowser
/(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|brave|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:lg |qute)browser|palemoon)\/([-\w\.]+)/i, /(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\/v?([-\w\.]+)/i,
// Atlas/Rekonq/Puffin/Brave/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon // Atlas/Rekonq/Puffin/Whale/QQBrowserLite/QQ//Vivaldi/DuckDuckGo/Klar/Helio/Dragon
/(brave)(?: chrome)?\/([\d\.]+)/i, // Brave
/(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf /(heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i, // HeyTap/Ovi/115/Surf
/(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant /(qwant)(?:ios|mobile)\/([\d\.]+)/i, // Qwant
/(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo /(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i // Ecosia/Weibo
@@ -406,7 +407,9 @@
], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [ ], [[NAME, /(.+)/, '$1 Secure' + SUFFIX_BROWSER], VERSION], [
/\bfocus\/([\w\.]+)/i // Firefox Focus /\bfocus\/([\w\.]+)/i // Firefox Focus
], [VERSION, [NAME, FIREFOX+' Focus']], [ ], [VERSION, [NAME, FIREFOX+' Focus']], [
/\bopt\/([\w\.]+)/i // Opera Touch / mms\/([\w\.]+)$/i // Opera Neon
], [VERSION, [NAME, OPERA+' Neon']], [
/ opt\/([\w\.]+)$/i // Opera Touch
], [VERSION, [NAME, OPERA+' Touch']], [ ], [VERSION, [NAME, OPERA+' Touch']], [
/coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser /coc_coc\w+\/([\w\.]+)/i // Coc Coc Browser
], [VERSION, [NAME, 'Coc Coc']], [ ], [VERSION, [NAME, 'Coc Coc']], [
@@ -455,7 +458,7 @@
], [NAME, VERSION, [TYPE, INAPP]], [ ], [NAME, VERSION, [TYPE, INAPP]], [
/\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS /\bgsa\/([\w\.]+) .*safari\//i // Google Search Appliance on iOS
], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [ ], [VERSION, [NAME, 'GSA'], [TYPE, INAPP]], [
/musical_ly(?:.+app_?version\/|_)([\w\.]+)/i // TikTok /(?:musical_ly|trill)(?:.+app_?version\/|_)([\w\.]+)/i // TikTok
], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [ ], [VERSION, [NAME, 'TikTok'], [TYPE, INAPP]], [
/\[(linkedin)app\]/i // LinkedIn App for iOS & Android /\[(linkedin)app\]/i // LinkedIn App for iOS & Android
], [NAME, [TYPE, INAPP]], [ ], [NAME, [TYPE, INAPP]], [
@@ -610,7 +613,7 @@
], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [ ], [[MODEL, /_/g, ' '], [VENDOR, XIAOMI], [TYPE, MOBILE]], [
// OnePlus // OnePlus
/droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-k]\w[1m]10)\b/i, /droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-l]\w[1m]10)\b/i,
/(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i
], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [ ], [MODEL, [VENDOR, ONEPLUS], [TYPE, MOBILE]], [
@@ -650,7 +653,7 @@
], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, MOTOROLA], [TYPE, TABLET]], [
// LG // LG
/((?=lg)?[vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i /\b(?:lg)?([vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i
], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [ ], [MODEL, [VENDOR, LG], [TYPE, TABLET]], [
/(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i, /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
/\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i, /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
@@ -941,7 +944,7 @@
/(presto)\/([\w\.]+)/i, // Presto /(presto)\/([\w\.]+)/i, // Presto
/(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m/Goanna/Servo
/ekioh(flow)\/([\w\.]+)/i, // Flow /ekioh(flow)\/([\w\.]+)/i, // Flow
/(khtml|tasman|links)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(khtml|tasman|links|dillo)[\/ ]\(?([\w\.]+)/i, // KHTML/Tasman/Links/Dillo
/(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab /(icab)[\/ ]([23]\.[\d\.]+)/i, // iCab
/\b(libweb)/i // LibWeb /\b(libweb)/i // LibWeb
@@ -1003,7 +1006,7 @@
], [VERSION, [NAME, BLACKBERRY]], [ ], [VERSION, [NAME, BLACKBERRY]], [
/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian /(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i // Symbian
], [VERSION, [NAME, 'Symbian']], [ ], [VERSION, [NAME, 'Symbian']], [
/mozilla\/[\d\.]+ \((?:mobile|tablet|tv|mobile; [\w ]+); rv:.+ gecko\/([\w\.]+)/i // Firefox OS /mozilla\/[\d\.]+ \((?:mobile[;\w ]*|tablet|tv|[^\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\w\.]+)\).+gecko\//i // Firefox OS
], [VERSION, [NAME, FIREFOX+' OS']], [ ], [VERSION, [NAME, FIREFOX+' OS']], [
/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS /\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, // WebOS
/webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i
@@ -1019,7 +1022,6 @@
], [[NAME, "Chrome OS"], VERSION],[ ], [[NAME, "Chrome OS"], VERSION],[
// Smart TVs // Smart TVs
/panasonic;(viera)/i, // Panasonic Viera
/(netrange)mmh/i, // Netrange /(netrange)mmh/i, // Netrange
/(nettv)\/(\d+\.[\w\.]+)/i, // NetTV /(nettv)\/(\d+\.[\w\.]+)/i, // NetTV

View File

@@ -866,6 +866,16 @@
"major" : "40" "major" : "40"
} }
}, },
{
"desc" : "Hi Browser",
"ua" : "Mozilla/5.0 (Linux; Android 14; en; TECNO BG6m Build/SP1A.210812.016) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 HiBrowser/v2.25.6.3;lang=es;nation=DO;locale=es_DO UWS/ Mobile Safari/537.36",
"expect" :
{
"name" : "HiBrowser",
"version" : "2.25.6.3",
"major" : "2"
}
},
{ {
"desc" : "HuaweiBrowser", "desc" : "HuaweiBrowser",
"ua" : "Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00HMSCore/4.0.0 GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36", "ua" : "Mozilla/5.0 (Linux; Android 6.0.1; LYA-AL00HMSCore/4.0.0 GMS/10.4 ) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.64 HuaweiBrowser/10.0.3.102 Mobile Safari/537.36",
@@ -1608,6 +1618,16 @@
"major" : "60" "major" : "60"
} }
}, },
{
"desc" : "Opera Neon",
"ua" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.21 Safari/537.36 MMS/1.0.2531.0",
"expect" :
{
"name" : "Opera Neon",
"version" : "1.0.2531.0",
"major" : "1"
}
},
{ {
"desc" : "Opera Tablet", "desc" : "Opera Tablet",
"ua" : "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1", "ua" : "Opera/9.80 (Windows NT 6.1; Opera Tablet/15165; U; en) Presto/2.8.149 Version/11.1",
@@ -2498,6 +2518,26 @@
"major" : "1" "major" : "1"
} }
}, },
{
"desc" : "Brave",
"ua" : "Mozilla/5.0 (Linux; Android 11; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Brave Chrome/88.0.4324.96 Safari/537.36",
"expect" :
{
"name" : "Brave",
"version" : "88.0.4324.96",
"major" : "88"
}
},
{
"desc" : "Brave",
"ua" : "Mozilla/5.0 (Linux; Android 11; Samsung Galaxy F62 SM-E625F Build/SME625F512091028;) AppleWebKit/537.36 (KHTML, like Gecko) Brave/1.75.110 Mobile Safari/537.36",
"expect" :
{
"name" : "Brave",
"version" : "1.75.110",
"major" : "1"
}
},
{ {
"desc" : "Brave Browser", "desc" : "Brave Browser",
"ua" : "Brave/4.5.16 CFNetwork/893.13.1 Darwin/17.3.0 (x86_64)", "ua" : "Brave/4.5.16 CFNetwork/893.13.1 Darwin/17.3.0 (x86_64)",
@@ -2742,6 +2782,16 @@
"major" : "28", "major" : "28",
"type" : "inapp" "type" : "inapp"
} }
},
{
"desc" : "TikTok",
"ua" : "Mozilla/5.0 (iPhone; CPU iPhone OS 18_6_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Safari/604.1 trill_43.0.0 BytedanceWebview/d8a21c6",
"expect" : {
"name" : "TikTok",
"version": "43.0.0",
"major" : "43",
"type" : "inapp"
}
}, },
{ {
"desc" : "Chrome Mobile", "desc" : "Chrome Mobile",

View File

@@ -188,6 +188,15 @@
"type": "tablet" "type": "tablet"
} }
}, },
{
"desc": "LG G Pad F2",
"ua": "Mozilla/5.0 (Linux; Android 7.1.1; LG-LK460 Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.98 Safari/537.36",
"expect": {
"vendor": "LG",
"model": "LK460",
"type": "tablet"
}
},
{ {
"desc": "LG Watch Urbane", "desc": "LG Watch Urbane",
"ua": "Mozilla/5.0 Linux; Android 7.1.1; LG Watch Urbane Build/NWD1.180306.004 AppleWebKit/537.36 KHTML, like Gecko Chrome/19.77.34.5 Mobile Safari/537.36", "ua": "Mozilla/5.0 Linux; Android 7.1.1; LG Watch Urbane Build/NWD1.180306.004 AppleWebKit/537.36 KHTML, like Gecko Chrome/19.77.34.5 Mobile Safari/537.36",

View File

@@ -170,6 +170,15 @@
"type": "mobile" "type": "mobile"
} }
}, },
{
"desc": "OnePlus 15",
"ua": "Mozilla/5.0 (Linux; Android 16; PLK110 Build/BP2A.250605.015; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/134.0.6998.135 Mobile Safari/537.36",
"expect": {
"vendor": "OnePlus",
"model": "PLK110",
"type": "mobile"
}
},
{ {
"desc": "OnePlus Ace", "desc": "OnePlus Ace",
"ua": "Mozilla/5.0 (Linux; U; Android 15; zh-cn; PGKM10 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.6.2", "ua": "Mozilla/5.0 (Linux; U; Android 15; zh-cn; PGKM10 Build/AP3A.240617.008) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/115.0.5790.168 Mobile Safari/537.36 HeyTapBrowser/40.9.6.2",

View File

@@ -17,6 +17,15 @@
"version" : "57.0.2987.146" "version" : "57.0.2987.146"
} }
}, },
{
"desc" : "Dillo",
"ua" : "Dillo/3.1.0",
"expect" :
{
"name" : "Dillo",
"version" : "3.1.0"
}
},
{ {
"desc" : "EdgeHTML", "desc" : "EdgeHTML",
"ua" : "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0", "ua" : "Mozilla/5.0 (Windows NT 6.4; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36 Edge/12.0",

View File

@@ -59,6 +59,26 @@
"type" : "cli" "type" : "cli"
} }
}, },
{
"desc" : "PowerShell",
"ua" : "Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0",
"expect" :
{
"name" : "PowerShell",
"version" : "6.0.0",
"type" : "cli"
}
},
{
"desc" : "PowerShell",
"ua" : "Mozilla/5.0 (Windows NT; Windows NT 10.0; de-DE) WindowsPowerShell/5.1.19041.5737",
"expect" :
{
"name" : "PowerShell",
"version" : "5.1.19041.5737",
"type" : "cli"
}
},
{ {
"desc" : "wget", "desc" : "wget",
"ua" : "Wget/1.21.1", "ua" : "Wget/1.21.1",

View File

@@ -2,88 +2,214 @@
{ {
"desc": "Airmail", "desc": "Airmail",
"ua": "Airmail 1.0 rv:148 (Macintosh; Mac OS X 10.8.3; en_BE)", "ua": "Airmail 1.0 rv:148 (Macintosh; Mac OS X 10.8.3; en_BE)",
"expect" : "expect": {
{
"name": "Airmail", "name": "Airmail",
"version": "1.0", "version": "1.0",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Alpine",
"ua": "Alpine/2.21 (Linux; x86_64)",
"expect": {
"name": "Alpine",
"version": "2.21",
"type": "email"
}
},
{
"desc": "Android Mail (AOSP)",
"ua": "Android/9-email",
"expect": {
"name": "Android",
"version": "9-email",
"type": "email"
}
},
{ {
"desc": "Apple Mail", "desc": "Apple Mail",
"ua": "Mail/3826.500.181.1.5 CFNetwork/3826.500.111.1.1 Darwin/24.4.0", "ua": "Mail/3826.500.181.1.5 CFNetwork/3826.500.111.1.1 Darwin/24.4.0",
"expect" : "expect": {
{
"name": "Mail", "name": "Mail",
"version": "3826.500.181.1.5", "version": "3826.500.181.1.5",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Aqua Mail",
"ua": "AquaMail/1.16.0-1081 (build: 101600003)",
"expect": {
"name": "AquaMail",
"version": "1.16.0-1081",
"type": "email"
}
},
{
"desc": "Balsa",
"ua": "Balsa/2.6.4",
"expect": {
"name": "Balsa",
"version": "2.6.4",
"type": "email"
}
},
{
"desc": "Barca",
"ua": "Barca/2.8 (Windows NT 5.1)",
"expect": {
"name": "Barca",
"version": "2.8",
"type": "email"
}
},
{ {
"desc": "BlueMail", "desc": "BlueMail",
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) BlueMail/0.10.31 Chrome/61.0.3163.100 Electron/2.0.18 Safari/537.36", "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) BlueMail/0.10.31 Chrome/61.0.3163.100 Electron/2.0.18 Safari/537.36",
"expect" : "expect": {
{
"name": "BlueMail", "name": "BlueMail",
"version": "0.10.31", "version": "0.10.31",
"type": "email" "type": "email"
} }
}, },
{ {
"desc" : "BlueMail", "desc": "BlueMail (iOS)",
"ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A405 BlueMail iOS", "ua": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/16A405 BlueMail iOS",
"expect" : "expect": {
{
"name": "BlueMail", "name": "BlueMail",
"version": "iOS", "version": "iOS",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Canary Mail",
"ua": "Canary/413 (Macintosh; OS X 14.2.1)",
"expect": {
"name": "Canary",
"version": "413",
"type": "email"
}
},
{
"desc": "Claws Mail",
"ua": "Claws Mail/3.17.5 (x86_64-pc-linux-gnu)",
"expect": {
"name": "Claws Mail",
"version": "3.17.5",
"type": "email"
}
},
{ {
"desc": "DaumMail", "desc": "DaumMail",
"ua": "DaumMobileApp (LG-KU5400; U; Android 2.3.7|10; ko-kr) DaumMail/1.0.8 ", "ua": "DaumMobileApp (LG-KU5400; U; Android 2.3.7|10; ko-kr) DaumMail/1.0.8 ",
"expect" : "expect": {
{
"name": "DaumMail", "name": "DaumMail",
"version": "1.0.8", "version": "1.0.8",
"type": "email" "type": "email"
} }
}, },
{
"desc" : "Evolution",
"ua" : "Evolution/3.52.3",
"expect" :
{
"name" : "Evolution",
"version" : "3.52.3",
"type" : "email"
}
},
{ {
"desc": "eM Client", "desc": "eM Client",
"ua": "eMClient/9.2.2157.0", "ua": "eMClient/9.2.2157.0",
"expect" : "expect": {
{
"name": "eMClient", "name": "eMClient",
"version": "9.2.2157.0", "version": "9.2.2157.0",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Eudora OSE",
"ua": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.19) Gecko/20110420 Eudora/3.0.4",
"expect": {
"name": "Eudora",
"version": "3.0.4",
"type": "email"
}
},
{
"desc": "Evolution",
"ua": "Evolution/3.52.3",
"expect": {
"name": "Evolution",
"version": "3.52.3",
"type": "email"
}
},
{
"desc": "FairEmail",
"ua": "FairEmail/1.2066 (Android 13; Pixel 7)",
"expect": {
"name": "FairEmail",
"version": "1.2066",
"type": "email"
}
},
{ {
"desc": "Foxmail", "desc": "Foxmail",
"ua": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 foxmail/7.2.15.80", "ua": "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.110 Safari/537.36 foxmail/7.2.15.80",
"expect" : "expect": {
{
"name": "foxmail", "name": "foxmail",
"version": "7.2.15.80", "version": "7.2.15.80",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Geary",
"ua": "Geary/40.0 (Linux; x86_64)",
"expect": {
"name": "Geary",
"version": "40.0",
"type": "email"
}
},
{
"desc": "Gnus",
"ua": "Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)",
"expect": {
"name": "Gnus",
"version": "5.13",
"type": "email"
}
},
{
"desc": "Horde IMP",
"ua": "Horde::IMP/6.2.27 (Linux)",
"expect": {
"name": "Horde::IMP",
"version": "6.2.27",
"type": "email"
}
},
{
"desc": "IBM Notes",
"ua": "Lotus-Notes/8.5.3",
"expect": {
"name": "Lotus-Notes",
"version": "8.5.3",
"type": "email"
}
},
{
"desc": "IncrediMail",
"ua": "IncrediMail/6.29.5126",
"expect": {
"name": "IncrediMail",
"version": "6.29.5126",
"type": "email"
}
},
{
"desc": "K-9 Mail",
"ua": "K-9 Mail/5.600",
"expect": {
"name": "K-9 Mail",
"version": "5.600",
"type": "email"
}
},
{ {
"desc": "KMail", "desc": "KMail",
"ua": "KMail/4.14.10 (FreeBSD/12.0-CURRENT; KDE/4.14.10; amd64; ; )", "ua": "KMail/4.14.10 (FreeBSD/12.0-CURRENT; KDE/4.14.10; amd64; ; )",
"expect" : "expect": {
{
"name": "KMail", "name": "KMail",
"version": "4.14.10", "version": "4.14.10",
"type": "email" "type": "email"
@@ -92,8 +218,7 @@
{ {
"desc": "KMail2", "desc": "KMail2",
"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kmail2/5.7.3 Safari/534.34", "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kmail2/5.7.3 Safari/534.34",
"expect" : "expect": {
{
"name": "kmail2", "name": "kmail2",
"version": "5.7.3", "version": "5.7.3",
"type": "email" "type": "email"
@@ -102,18 +227,43 @@
{ {
"desc": "Kontact", "desc": "Kontact",
"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kontact/4.13.3 Safari/534.34", "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) kontact/4.13.3 Safari/534.34",
"expect" : "expect": {
{
"name": "kontact", "name": "kontact",
"version": "4.13.3", "version": "4.13.3",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Mailbird",
"ua": "Mailbird/2.9.0.0",
"expect": {
"name": "Mailbird",
"version": "2.9.0.0",
"type": "email"
}
},
{
"desc": "MailMate",
"ua": "MailMate/5663 (Macintosh; Intel Mac OS X 10.15.7)",
"expect": {
"name": "MailMate",
"version": "5663",
"type": "email"
}
},
{
"desc": "Mailspring",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Mailspring/1.7.8 Chrome/69.0.3497.128 Electron/4.2.12 Safari/537.36",
"expect": {
"name": "Mailspring",
"version": "1.7.8",
"type": "email"
}
},
{ {
"desc": "Microsoft Outlook", "desc": "Microsoft Outlook",
"ua": "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.5431; Pro)", "ua": "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Outlook 16.0.5431; Pro)",
"expect" : "expect": {
{
"name": "Microsoft Outlook", "name": "Microsoft Outlook",
"version": "16.0.5431", "version": "16.0.5431",
"type": "email" "type": "email"
@@ -122,48 +272,160 @@
{ {
"desc": "Microsoft Outlook for Mac", "desc": "Microsoft Outlook for Mac",
"ua": "MacOutlook/14.7.1.161129 (Intel Mac OS X 10.9.6)", "ua": "MacOutlook/14.7.1.161129 (Intel Mac OS X 10.9.6)",
"expect" : "expect": {
{
"name": "MacOutlook", "name": "MacOutlook",
"version": "14.7.1.161129", "version": "14.7.1.161129",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Mutt",
"ua": "Mutt/1.5.21 (2010-09-15)",
"expect": {
"name": "Mutt",
"version": "1.5.21",
"type": "email"
}
},
{ {
"desc": "NaverMailApp", "desc": "NaverMailApp",
"ua": "NaverMailApp/2.1.23 (Android 10; SM-N960N)", "ua": "NaverMailApp/2.1.23 (Android 10; SM-N960N)",
"expect" : "expect": {
{
"name": "NaverMailApp", "name": "NaverMailApp",
"version": "2.1.23", "version": "2.1.23",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Newton Mail",
"ua": "Newton/10.0.52 (Android 10; K)",
"expect": {
"name": "Newton",
"version": "10.0.52",
"type": "email"
}
},
{
"desc": "Nine",
"ua": "Nine/4.5.3a",
"expect": {
"name": "Nine",
"version": "4.5.3a",
"type": "email"
}
},
{
"desc": "Nylas Mail",
"ua": "NylasMail/2.0.32 (Macintosh; OS X 10.12.6)",
"expect": {
"name": "NylasMail",
"version": "2.0.32",
"type": "email"
}
},
{
"desc": "Outlook Express",
"ua": "Outlook-Express/6.0 (MSIE 6.0; Windows NT 5.1; SV1)",
"expect": {
"name": "Outlook-Express",
"version": "6.0",
"type": "email"
}
},
{
"desc": "Pegasus Mail",
"ua": "Pegasus Mail/4.70",
"expect": {
"name": "Pegasus Mail",
"version": "4.70",
"type": "email"
}
},
{
"desc": "PocoMail",
"ua": "PocoMail 4.8 (4320) - Licensed Version",
"expect": {
"name": "PocoMail",
"version": "4.8",
"type": "email"
}
},
{ {
"desc": "Polymail", "desc": "Polymail",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Polymail/2.3.12 Chrome/114.0.5735.134 Electron/25.2.0 Safari/537.36", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Polymail/2.3.12 Chrome/114.0.5735.134 Electron/25.2.0 Safari/537.36",
"expect" : "expect": {
{
"name": "Polymail", "name": "Polymail",
"version": "2.3.12", "version": "2.3.12",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Postbox",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Postbox/7.0.26",
"expect": {
"name": "Postbox",
"version": "7.0.26",
"type": "email"
}
},
{ {
"desc": "ProtonMail", "desc": "ProtonMail",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ProtonMail/1.4.0 Chrome/122.0.6261.156 Electron/29.4.6 Safari/537.36", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) ProtonMail/1.4.0 Chrome/122.0.6261.156 Electron/29.4.6 Safari/537.36",
"expect" : "expect": {
{
"name": "ProtonMail", "name": "ProtonMail",
"version": "1.4.0", "version": "1.4.0",
"type": "email" "type": "email"
} }
}, },
{
"desc": "ProtonMail Bridge",
"ua": "ProtonMail Bridge/3.8.2 (Macintosh; Intel Mac OS X 10_15_7)",
"expect": {
"name": "ProtonMail Bridge",
"version": "3.8.2",
"type": "email"
}
},
{
"desc": "R2Mail2",
"ua": "R2Mail2/2.50 (Android)",
"expect": {
"name": "R2Mail2",
"version": "2.50",
"type": "email"
}
},
{
"desc": "RainLoop",
"ua": "RainLoop/1.17.0",
"expect": {
"name": "RainLoop",
"version": "1.17.0",
"type": "email"
}
},
{
"desc": "Roundcube Webmail",
"ua": "Roundcube Webmail/1.6.0",
"expect": {
"name": "Roundcube Webmail",
"version": "1.6.0",
"type": "email"
}
},
{
"desc": "Samsung Email",
"ua": "SamsungEmail/6.1.80.12",
"expect": {
"name": "SamsungEmail",
"version": "6.1.80.12",
"type": "email"
}
},
{ {
"desc": "SparkDesktop", "desc": "SparkDesktop",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) SparkDesktop/3.0.30 Chrome/102.0.5005.63 Electron/19.0.4 Safari/537.36", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) SparkDesktop/3.0.30 Chrome/102.0.5005.63 Electron/19.0.4 Safari/537.36",
"expect" : "expect": {
{
"name": "SparkDesktop", "name": "SparkDesktop",
"version": "3.0.30", "version": "3.0.30",
"type": "email" "type": "email"
@@ -172,58 +434,151 @@
{ {
"desc": "Sparrow", "desc": "Sparrow",
"ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Sparrow/1043.1", "ua": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/604.5.6 (KHTML, like Gecko) Sparrow/1043.1",
"expect" : "expect": {
{
"name": "Sparrow", "name": "Sparrow",
"version": "1043.1", "version": "1043.1",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Spicebird",
"ua": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.9pre) Gecko/20100216 Spicebird/0.8",
"expect": {
"name": "Spicebird",
"version": "0.8",
"type": "email"
}
},
{
"desc": "SquirrelMail",
"ua": "SquirrelMail/1.4.23 [SVN]",
"expect": {
"name": "SquirrelMail",
"version": "1.4.23",
"type": "email"
}
},
{
"desc": "Sylpheed",
"ua": "Sylpheed/3.7.0 (MinGW32; Windows NT 6.1; x86_64)",
"expect": {
"name": "Sylpheed",
"version": "3.7.0",
"type": "email"
}
},
{
"desc": "The Bat!",
"ua": "The Bat! 9.2.1",
"expect": {
"name": "The Bat!",
"version": "9.2.1",
"type": "email"
}
},
{ {
"desc": "Thunderbird", "desc": "Thunderbird",
"ua": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0", "ua": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0",
"expect" : "expect": {
{
"name": "Thunderbird", "name": "Thunderbird",
"version": "78.13.0", "version": "78.13.0",
"type": "email" "type": "email"
} }
}, },
{ {
"desc" : "Yahoo! Mail", "desc": "Trojita",
"ua" : "YahooMobile/1.0 (mail; 3.0.5.1311380); (Linux; U; Android 4.0.3; htc_runnymede Build/ICE_CREAM_SANDWICH_MR1);", "ua": "Trojita/0.7",
"expect" : "expect": {
{ "name": "Trojita",
"name" : "Yahoo", "version": "0.7",
"version" : "3.0.5.1311380",
"type": "email" "type": "email"
} }
}, },
{ {
"desc" : "Yahoo! Mail", "desc": "Turnpike",
"ua" : "YahooMobileMail/1.0 (Android Mail; 1.3.10) (supersonic;HTC;PC36100;2.3.5/GRJ90) ", "ua": "Turnpike/6.07-U",
"expect" : "expect": {
"name": "Turnpike",
"version": "6.07-U",
"type": "email"
}
},
{ {
"name" : "Yahoo", "desc": "Tuta Desktop (Tutanota)",
"ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) tutanota-desktop/3.110.1 Chrome/110.0.5481.179 Electron/23.1.3 Safari/537.36",
"expect": {
"name": "tutanota-desktop",
"version": "3.110.1",
"type": "email"
}
},
{
"desc": "Wanderlust",
"ua": "Wanderlust/2.15.9 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (Gojō) APEL/10.8 Emacs/23.1 (i486-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO)",
"expect": {
"name": "Wanderlust",
"version": "2.15.9",
"type": "email"
}
},
{
"desc": "Windows Live Mail",
"ua": "Windows-Live-Mail/15.4.3508.1109",
"expect": {
"name": "Windows-Live-Mail",
"version": "15.4.3508.1109",
"type": "email"
}
},
{
"desc": "Yahoo! Mail (Android)",
"ua": "YahooMobile/1.0 (mail; 3.0.5.1311380); (Linux; U; Android 4.0.3; htc_runnymede Build/ICE_CREAM_SANDWICH_MR1);",
"expect": {
"name": "Yahoo Mail",
"version": "1.0",
"type": "email"
}
},
{
"desc": "Yahoo! Mail (Legacy)",
"ua": "YahooMobileMail/1.0 (Android Mail; 1.3.10) (supersonic;HTC;PC36100;2.3.5/GRJ90) ",
"expect": {
"name": "Yahoo Mail",
"version": "1.3.10", "version": "1.3.10",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Yahoo! Mail (iOS)",
"ua": "YahooMail/1.0 (iOS; 1.0.0; en_US)",
"expect": {
"name": "Yahoo Mail",
"version": "1.0",
"type": "email"
}
},
{ {
"desc": "Zimbra", "desc": "Zimbra",
"ua": "Mozilla/5.0 (Windows; U; Windows NT 6.2; it; rv:1.9.2.19pre) Gecko/20110902 Prism zdesktop/7.2.8", "ua": "Mozilla/5.0 (Windows; U; Windows NT 6.2; it; rv:1.9.2.19pre) Gecko/20110902 Prism zdesktop/7.2.8",
"expect" : "expect": {
{
"name": "Zimbra", "name": "Zimbra",
"version": "7.2.8", "version": "7.2.8",
"type": "email" "type": "email"
} }
}, },
{
"desc": "Zimbra (Server)",
"ua": "Zimbra/9.0.0_GA_4138",
"expect": {
"name": "Zimbra",
"version": "9.0.0_GA_4138",
"type": "email"
}
},
{ {
"desc": "ZohoMail", "desc": "ZohoMail",
"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ZohoMail-Desktop/1.6.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36", "ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) ZohoMail-Desktop/1.6.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36",
"expect" : "expect": {
{
"name": "ZohoMail-Desktop", "name": "ZohoMail-Desktop",
"version": "1.6.3", "version": "1.6.3",
"type": "email" "type": "email"

View File

@@ -89,6 +89,16 @@
"type" : "library" "type" : "library"
} }
}, },
{
"desc" : "GuzzleHttp",
"ua" : "GuzzleHttp/6.5.5 curl/7.70.0 PHP/7.4.22",
"expect" :
{
"name" : "GuzzleHttp",
"version" : "6.5.5",
"type" : "library"
}
},
{ {
"desc" : "hackney", "desc" : "hackney",
"ua" : "hackney/1.20.1", "ua" : "hackney/1.20.1",
@@ -100,12 +110,12 @@
} }
}, },
{ {
"desc" : "GuzzleHttp", "desc" : "http.rb",
"ua" : "GuzzleHttp/6.5.5 curl/7.70.0 PHP/7.4.22", "ua" : "http.rb/4.2.0",
"expect" : "expect" :
{ {
"name" : "GuzzleHttp", "name" : "http.rb",
"version" : "6.5.5", "version" : "4.2.0",
"type" : "library" "type" : "library"
} }
}, },
@@ -129,6 +139,16 @@
"type" : "library" "type" : "library"
} }
}, },
{
"desc" : "Jetty",
"ua" : "Jetty/11.0.13",
"expect" :
{
"name" : "Jetty",
"version" : "11.0.13",
"type" : "library"
}
},
{ {
"desc" : "jsdom", "desc" : "jsdom",
"ua" : "Mozilla/5.0 (unknown OS) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0", "ua" : "Mozilla/5.0 (unknown OS) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.12.0",
@@ -199,6 +219,16 @@
"type" : "library" "type" : "library"
} }
}, },
{
"desc" : "ocaml-cohttp",
"ua" : "ocaml-cohttp/1.2.00",
"expect" :
{
"name" : "ocaml-cohttp",
"version" : "1.2.00",
"type" : "library"
}
},
{ {
"desc" : "OkHttp", "desc" : "OkHttp",
"ua" : "okhttp/3.2.0", "ua" : "okhttp/3.2.0",

View File

@@ -25,5 +25,59 @@
"name" : "Firefox OS", "name" : "Firefox OS",
"version" : "44.0" "version" : "44.0"
} }
},
{
"desc" : "Firefox OS on Alcatel One Touch Fire",
"ua" : "Mozilla/5.0 (Mobile; ALCATELOneTouch4012X; rv:18.1) Gecko/18.1 Firefox/18.1",
"expect" :
{
"name" : "Firefox OS",
"version" : "18.1"
}
},
{
"desc" : "Firefox OS on Huawei Y300II",
"ua" : "Mozilla/5.0 (Mobile; HUAWEIY300-F1; rv:18.1) Gecko/18.1 Firefox/18.1",
"expect" :
{
"name" : "Firefox OS",
"version" : "18.1"
}
},
{
"desc" : "Firefox OS on LG Fireweb",
"ua" : "Mozilla/5.0 (Mobile; LG-D300; rv:18.1) Gecko/18.1 Firefox/18.1",
"expect" :
{
"name" : "Firefox OS",
"version" : "18.1"
}
},
{
"desc" : "Firefox OS on LG FX0",
"ua" : "Mozilla/5.0 (Mobile; LGL25; rv:32.0) Gecko/32.0 Firefox/32.0",
"expect" :
{
"name" : "Firefox OS",
"version" : "32.0"
}
},
{
"desc" : "Firefox OS on Panasonic Viera TV",
"ua" : "Mozilla/5.0 (Linux; Viera; rv:34.0) Gecko/20100101 Firefox/34.0",
"expect" :
{
"name" : "Firefox OS",
"version" : "34.0"
}
},
{
"desc" : "Firefox OS on ZTE Open",
"ua" : "Mozilla/5.0 (Mobile; ZTEOPEN; rv:18.1) Gecko/18.1 Firefox/18.1",
"expect" :
{
"name" : "Firefox OS",
"version" : "18.1"
}
} }
] ]

View File

@@ -7,5 +7,14 @@
"name" : "FreeBSD", "name" : "FreeBSD",
"version" : "undefined" "version" : "undefined"
} }
},
{
"desc" : "FreeBSD",
"ua" : "Mozilla/5.0 (X11; FreeBSD; U; Viera; pl-PL) AppleWebKit/537.11 (KHTML, like Gecko) Viera/3.3.3 Chrome/23.0.1271.97 Safari/537.11",
"expect" :
{
"name" : "FreeBSD",
"version" : "undefined"
}
} }
] ]

View File

@@ -38,18 +38,34 @@ describe('Extensions', () => {
}); });
}); });
// Existing test cases
const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)'; const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)';
const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0'; const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';
const axios = 'axios/1.3.5'; const axios = 'axios/1.3.5';
const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3'; const jsdom = 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/20.0.3';
const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)'; const scrapy = 'Scrapy/1.5.0 (+https://scrapy.org)';
// New test cases for updated Regex logic
const macOutlook = 'MacOutlook/16.61.22041701 (Intel Mac OS X 10.15.7)';
const yahooMobile = 'YahooMobile/1.0 (mail; 3.0.5.1311380)';
assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY); assert.equal(UAParser(scrapy, Bots).browser.name, Library.SCRAPY);
const emailParser = new UAParser(Emails); const emailParser = new UAParser(Emails);
// Verify Standard Outlook
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: "16.0.9126", major: "16", type: BrowserType.EMAIL}); assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK, version: "16.0.9126", major: "16", type: BrowserType.EMAIL});
// Verify Thunderbird
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: "78.13.0", major: "78", type: BrowserType.EMAIL}); assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: Email.THUNDERBIRD, version: "78.13.0", major: "78", type: BrowserType.EMAIL});
// Verify New MacOutlook Logic (Distinguishing it from Windows Outlook)
assert.deepEqual(emailParser.setUA(macOutlook).getBrowser(), {name: Email.MICROSOFT_OUTLOOK_MAC, version: "16.61.22041701", major: "16", type: BrowserType.EMAIL});
// Verify Yahoo Mobile Logic (Tightened Regex)
// Note: We expect 'Yahoo Mail' (Email.YAHOO_MAIL) because of the normalization helper.
assert.deepEqual(emailParser.setUA(yahooMobile).getBrowser(), {name: Email.YAHOO_MAIL, version: "1.0", major: "1", type: BrowserType.EMAIL});
const libraryParser = new UAParser(Libraries); const libraryParser = new UAParser(Libraries);
assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: "1.3.5", major: "1", type: BrowserType.LIBRARY}); assert.deepEqual(libraryParser.setUA(axios).getBrowser(), {name: Library.AXIOS, version: "1.3.5", major: "1", type: BrowserType.LIBRARY});
assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: "20.0.3", major: "20", type: BrowserType.LIBRARY}); assert.deepEqual(libraryParser.setUA(jsdom).getBrowser(), {name: Library.JSDOM, version: "20.0.3", major: "20", type: BrowserType.LIBRARY});

View File

@@ -1,5 +1,5 @@
const assert = require('assert'); const assert = require('assert');
const { isFrozenUA } = require('../../../src/helpers/ua-parser-helpers'); const { isFrozenUA, getOutlookEdition } = require('../../../src/helpers/ua-parser-helpers');
describe('isFrozenUA()', () => { describe('isFrozenUA()', () => {
it('matches supplied user-agent string with known frozen user-agent pattern', () => { it('matches supplied user-agent string with known frozen user-agent pattern', () => {
@@ -11,3 +11,29 @@ describe('isFrozenUA()', () => {
assert.equal(isFrozenUA(frozenMobileUA), true); assert.equal(isFrozenUA(frozenMobileUA), true);
}); });
}); });
describe('getOutlookEdition()', () => {
it('identifies Windows versions correctly', () => {
// MSI Version (Older engine)
assert.equal(getOutlookEdition('Microsoft Outlook', '16.0.4266.1001'), 'Outlook 2016 (MSI / Volume License)');
// Click-to-Run (Modern engine)
assert.equal(getOutlookEdition('Microsoft Outlook', '16.0.14326.20000'), 'Outlook 365 / 2019+ (Modern)');
// Legacy Major Version
assert.equal(getOutlookEdition('Microsoft Outlook', '15.0.4569.1506'), 'Outlook 2013');
});
it('identifies Mac versions correctly', () => {
assert.equal(getOutlookEdition('MacOutlook', '16.61'), 'Outlook for Mac (Modern)');
assert.equal(getOutlookEdition('MacOutlook', '15.4'), 'Outlook for Mac (Legacy)');
});
it('returns original name for unknown inputs', () => {
assert.equal(getOutlookEdition('Thunderbird', '91.0'), 'Thunderbird');
});
it('handles New Outlook (OneOutlook) correctly', () => {
// New Outlook usually sends a browser UA, but if it sends "Outlook" without version info matches,
// it shouldn't trigger the Legacy/MSI logic.
assert.equal(getOutlookEdition('Microsoft Outlook', 'SomeRandomString'), 'Microsoft Outlook');
});
});