├── .eslintrc.json ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .husky └── pre-commit ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin ├── update-applications.js ├── update-browser-ids.js ├── update-chrome.js ├── update-indices.js ├── update-models.js ├── update-profiles.js └── update-regexes.js ├── data ├── applications-bots.js ├── applications-browsers.js ├── applications-others.js ├── browsers-chrome.js ├── build-android.js ├── id-android.js ├── indices │ ├── models-android.js │ ├── models-asha.js │ ├── models-bada.js │ ├── models-brew.js │ ├── models-feature.js │ ├── models-firefoxos.js │ ├── models-kddi.js │ ├── models-palmos.js │ ├── models-s30plus.js │ ├── models-s40.js │ ├── models-symbian.js │ ├── models-tizen.js │ ├── models-touchwiz.js │ ├── models-wm.js │ └── models-wp.js ├── manufacturer-names.js ├── models-android.js ├── models-asha.js ├── models-bada.js ├── models-blackberry.js ├── models-brew.js ├── models-feature.js ├── models-firefoxos.js ├── models-ios.js ├── models-kddi.js ├── models-palmos.js ├── models-s30plus.js ├── models-s40.js ├── models-symbian.js ├── models-tizen.js ├── models-touchwiz.js ├── models-wm.js ├── models-wp.js ├── os-cfnetwork.js ├── os-darwin.js ├── profiles.js └── regexes │ ├── applications-bots.js │ ├── applications-browsers.js │ └── applications-others.js ├── package-lock.json ├── package.json ├── src ├── Analyser.js ├── Analyser │ ├── Camouflage.js │ ├── Corrections.js │ ├── Derive.js │ ├── Header.js │ ├── Header │ │ ├── Baidu.js │ │ ├── BrowserId.js │ │ ├── OperaMini.js │ │ ├── Puffin.js │ │ ├── UCBrowserNew.js │ │ ├── UCBrowserOld.js │ │ ├── Useragent.js │ │ ├── Useragent │ │ │ ├── Application.js │ │ │ ├── Bot.js │ │ │ ├── Browser.js │ │ │ ├── Device.js │ │ │ ├── Device │ │ │ │ ├── Appliance.js │ │ │ │ ├── Cars.js │ │ │ │ ├── Ereader.js │ │ │ │ ├── Gaming.js │ │ │ │ ├── Gps.js │ │ │ │ ├── Media.js │ │ │ │ ├── Mobile.js │ │ │ │ ├── Pda.js │ │ │ │ ├── Phone.js │ │ │ │ ├── Printer.js │ │ │ │ ├── Signage.js │ │ │ │ ├── Tablet.js │ │ │ │ ├── Television.js │ │ │ │ └── index.js │ │ │ ├── Engine.js │ │ │ ├── Os.js │ │ │ ├── Using.js │ │ │ └── index.js │ │ ├── Wap.js │ │ └── index.js │ └── index.js ├── Cache.js ├── Parser.js ├── constants │ ├── browserType.js │ ├── deviceSubType.js │ ├── deviceType.js │ ├── engineType.js │ ├── feature.js │ ├── flag.js │ ├── id.js │ └── index.js ├── data │ ├── Applications.js │ ├── BrowserIds.js │ ├── BuildIds.js │ ├── CFNetwork.js │ ├── Chrome.js │ ├── Darwin.js │ ├── DeviceModels.js │ ├── DeviceProfiles.js │ └── Manufacturers.js └── model │ ├── Browser.js │ ├── Device.js │ ├── Engine.js │ ├── Family.js │ ├── Main.js │ ├── Os.js │ ├── Using.js │ ├── Version.js │ └── primitive │ ├── Base.js │ └── NameVersion.js ├── test ├── data │ ├── appliance │ │ ├── amstrad.yaml │ │ ├── familyhub.yaml │ │ ├── i-opener.yaml │ │ └── weblight.yaml │ ├── bots │ │ ├── disabled.yaml │ │ ├── false-positive.yaml │ │ └── generic.yaml │ ├── camera │ │ ├── os-android.yaml │ │ └── os-tizen.yaml │ ├── car │ │ ├── tesla.yaml │ │ └── volvo.yaml │ ├── desktop │ │ ├── app-editor.yaml │ │ ├── app-mediaplayer.yaml │ │ ├── browser-arachne.yaml │ │ ├── browser-brave.yaml │ │ ├── browser-chrome.yaml │ │ ├── browser-chromium.yaml │ │ ├── browser-edge.yaml │ │ ├── browser-firefox.yaml │ │ ├── browser-flow.yaml │ │ ├── browser-icab.yaml │ │ ├── browser-ie.yaml │ │ ├── browser-konqueror.yaml │ │ ├── browser-maxthon.yaml │ │ ├── browser-midori.yaml │ │ ├── browser-mosaic.yaml │ │ ├── browser-netfront.yaml │ │ ├── browser-netscape.yaml │ │ ├── browser-omniweb.yaml │ │ ├── browser-opera.yaml │ │ ├── browser-other.yaml │ │ ├── browser-qq.yaml │ │ ├── browser-safari.yaml │ │ ├── browser-seamonkey.yaml │ │ ├── browser-text.yaml │ │ ├── browser-uc.yaml │ │ ├── engine-goanna.yaml │ │ ├── engine-servo.yaml │ │ ├── os-amigaos.yaml │ │ ├── os-aros.yaml │ │ ├── os-beos.yaml │ │ ├── os-bsd.yaml │ │ ├── os-chromeos.yaml │ │ ├── os-haiku.yaml │ │ ├── os-irix.yaml │ │ ├── os-joli.yaml │ │ ├── os-linux.yaml │ │ ├── os-morphos.yaml │ │ ├── os-os2.yaml │ │ ├── os-osx.yaml │ │ ├── os-redstar.yaml │ │ ├── os-remix.yaml │ │ ├── os-riscos.yaml │ │ ├── os-solaris.yaml │ │ ├── os-syllable.yaml │ │ ├── os-unix.yaml │ │ ├── os-windows.yaml │ │ ├── other.yaml │ │ ├── platform-electron.yaml │ │ └── platform-qt.yaml │ ├── ereader │ │ ├── amazon.yaml │ │ ├── kobo.yaml │ │ ├── nook.yaml │ │ ├── other.yaml │ │ ├── pocketbook.yaml │ │ └── sony.yaml │ ├── gaming │ │ ├── microsoft.yaml │ │ ├── nintendo.yaml │ │ ├── other.yaml │ │ ├── sega.yaml │ │ └── sony.yaml │ ├── headset │ │ ├── device-gear.yaml │ │ ├── device-glass.yaml │ │ └── device-oculus.yaml │ ├── media │ │ ├── device-archos.yaml │ │ ├── device-walkman.yaml │ │ └── device-zune.yaml │ ├── mobile │ │ ├── app-chat.yaml │ │ ├── app-download.yaml │ │ ├── app-email.yaml │ │ ├── app-media.yaml │ │ ├── app-news.yaml │ │ ├── app-other.yaml │ │ ├── app-search.yaml │ │ ├── app-shopping.yaml │ │ ├── app-social.yaml │ │ ├── browser-2345.yaml │ │ ├── browser-360.yaml │ │ ├── browser-au.yaml │ │ ├── browser-baidu.yaml │ │ ├── browser-chrome.yaml │ │ ├── browser-dolfin.yaml │ │ ├── browser-dolphin.yaml │ │ ├── browser-edge.yaml │ │ ├── browser-eui.yaml │ │ ├── browser-firefox-ios.yaml │ │ ├── browser-ibrowser.yaml │ │ ├── browser-iris.yaml │ │ ├── browser-jig.yaml │ │ ├── browser-lg.yaml │ │ ├── browser-maxthon.yaml │ │ ├── browser-mib.yaml │ │ ├── browser-minibrowser.yaml │ │ ├── browser-mme.yaml │ │ ├── browser-netfront.yaml │ │ ├── browser-ninesky.yaml │ │ ├── browser-nokiaxpress.yaml │ │ ├── browser-novarra.yaml │ │ ├── browser-obigo.yaml │ │ ├── browser-openwave.yaml │ │ ├── browser-opera.yaml │ │ ├── browser-other.yaml │ │ ├── browser-polaris.yaml │ │ ├── browser-puffin.yaml │ │ ├── browser-qq.yaml │ │ ├── browser-samsung.yaml │ │ ├── browser-skyfire.yaml │ │ ├── browser-sogou.yaml │ │ ├── browser-uc.yaml │ │ ├── browser-webview.yaml │ │ ├── carrier-docomo.yaml │ │ ├── carrier-emobile.yaml │ │ ├── carrier-kddi.yaml │ │ ├── carrier-softbank.yaml │ │ ├── carrier-willcom.yaml │ │ ├── device-kin.yaml │ │ ├── device-nokiax.yaml │ │ ├── engine-servo.yaml │ │ ├── header-requestedwith.yaml │ │ ├── header-wap.yaml │ │ ├── manufacturer-lg.yaml │ │ ├── manufacturer-microsoft.yaml │ │ ├── manufacturer-motorola.yaml │ │ ├── manufacturer-nokia-asha.yaml │ │ ├── manufacturer-nokia-series40.yaml │ │ ├── manufacturer-nokia-series60.yaml │ │ ├── manufacturer-nokia-windows.yaml │ │ ├── manufacturer-samsung-android.yaml │ │ ├── manufacturer-samsung-bada.yaml │ │ ├── manufacturer-siemens.yaml │ │ ├── manufacturer-sony.yaml │ │ ├── manufacturer-sonyericsson.yaml │ │ ├── manufacturer-xiaomi.yaml │ │ ├── os-aliyun.yaml │ │ ├── os-android.yaml │ │ ├── os-asha.yaml │ │ ├── os-bada.yaml │ │ ├── os-baiduyi.yaml │ │ ├── os-blackberry-10.yaml │ │ ├── os-blackberry.yaml │ │ ├── os-brew.yaml │ │ ├── os-cos.yaml │ │ ├── os-ezxlinux.yaml │ │ ├── os-feature.yaml │ │ ├── os-firefoxos.yaml │ │ ├── os-fireos.yaml │ │ ├── os-geos.yaml │ │ ├── os-harmony.yaml │ │ ├── os-ios.yaml │ │ ├── os-kaios.yaml │ │ ├── os-limo.yaml │ │ ├── os-maemo.yaml │ │ ├── os-meego.yaml │ │ ├── os-mre.yaml │ │ ├── os-s30.yaml │ │ ├── os-s40.yaml │ │ ├── os-s80.yaml │ │ ├── os-sailfish.yaml │ │ ├── os-spreadtrum.yaml │ │ ├── os-symbian.yaml │ │ ├── os-threadx.yaml │ │ ├── os-tizen.yaml │ │ ├── os-ubuntu.yaml │ │ ├── os-vre.yaml │ │ ├── os-webos.yaml │ │ ├── os-windowsce.yaml │ │ ├── os-windowsmobile.yaml │ │ ├── os-windowsphone.yaml │ │ ├── os-wophone.yaml │ │ ├── platform-air.yaml │ │ └── wap.yaml │ ├── other │ │ ├── camouflage.yaml │ │ ├── reported.yaml │ │ └── xmlhttprequest.yaml │ ├── pda │ │ ├── airboard.yaml │ │ ├── casio.yaml │ │ ├── generic.yaml │ │ ├── mylo.yaml │ │ ├── oasys.yaml │ │ ├── palm.yaml │ │ ├── psion.yaml │ │ └── zaurus.yaml │ ├── phone │ │ └── snom.yaml │ ├── printer │ │ ├── canon.yaml │ │ ├── hp.yaml │ │ ├── other.yaml │ │ └── taskalfa.yaml │ ├── signage │ │ └── other.yaml │ ├── tablet │ │ ├── browser-opera.yaml │ │ ├── manufacturer-samsung.yaml │ │ ├── manufacturer-webtab.yaml │ │ ├── os-android.yaml │ │ ├── os-blackberry.yaml │ │ ├── os-firefoxos.yaml │ │ ├── os-fireos.yaml │ │ ├── os-ios.yaml │ │ ├── os-leos.yaml │ │ ├── os-ubuntu.yaml │ │ └── os-webos.yaml │ ├── television │ │ ├── appletv.yaml │ │ ├── browser-espial.yaml │ │ ├── browser-machblue.yaml │ │ ├── browser-nx.yaml │ │ ├── browser-opera.yaml │ │ ├── firetv.yaml │ │ ├── google.yaml │ │ ├── hitachi.yaml │ │ ├── kreatv.yaml │ │ ├── lg.yaml │ │ ├── mitsubishi.yaml │ │ ├── nvidia.yaml │ │ ├── opentv.yaml │ │ ├── other.yaml │ │ ├── panasonic.yaml │ │ ├── philips.yaml │ │ ├── pioneer.yaml │ │ ├── roku.yaml │ │ ├── samsung.yaml │ │ ├── sanyo.yaml │ │ ├── sharp.yaml │ │ ├── sony.yaml │ │ └── toshiba.yaml │ └── watch │ │ ├── os-android-wear.yaml │ │ ├── os-android.yaml │ │ └── os-tizen.yaml ├── model │ ├── BrowserTest.js │ ├── DeviceTest.js │ ├── EngineTest.js │ ├── FamilyTest.js │ ├── MainTest.js │ ├── OsTest.js │ ├── UsingTest.js │ ├── VersionTest.js │ └── primitive │ │ ├── BaseTest.js │ │ └── NameVersionTest.js └── unit │ ├── AnalyserTest.js │ ├── CacheTest.js │ ├── MassiveTest.js │ └── ParserTest.js └── which-browser.d.ts /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6 4 | }, 5 | "env": { 6 | "node": true, 7 | "es6": true 8 | }, 9 | "extends": [ 10 | "eslint:recommended", 11 | "google", 12 | "plugin:prettier/recommended" 13 | ], 14 | "rules": { 15 | "no-control-regex": 0, 16 | "no-console":"warn", 17 | "require-jsdoc": 0 18 | } 19 | } -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build and test 2 | "on": 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | Build: 11 | runs-on: ubuntu-latest 12 | strategy: 13 | matrix: 14 | node-version: 15 | - "16.x" 16 | - "17.x" 17 | - "18.x" 18 | - "19.x" 19 | - "20.x" 20 | steps: 21 | - name: "Set up Node.js ${{ matrix.node-version }}" 22 | uses: actions/setup-node@v1 23 | with: 24 | node-version: "${{ matrix.node-version }}" 25 | - uses: actions/checkout@v2 26 | - run: npm install 27 | - run: npm run lint 28 | - run: npm run test-and-coverage 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | package 40 | 41 | # Typescript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | yarn.lock 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | #IDE 64 | .idea 65 | .history 66 | .vscode 67 | *.iml 68 | 69 | #dist ES5 folder 70 | dist 71 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn stuffs 55 | .yarn-integrity 56 | yarn.lock 57 | 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | #IDE 63 | .idea 64 | .history 65 | .vscode 66 | *.iml 67 | 68 | test 69 | bin 70 | package 71 | .travis.yml 72 | .eslintrc.json 73 | .gitignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Simone Mariotti 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 | -------------------------------------------------------------------------------- /bin/update-browser-ids.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const request = require('request'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | console.log('Updating browser ids...'); 6 | const filepath = path.join(__dirname, '../data/id-android.js'); 7 | const fileStream = fs.createWriteStream(filepath); 8 | 9 | request('https://api.whichbrowser.net/resources/browser-ids.json', (err, response = {}) => { 10 | if (err) { 11 | return; 12 | } 13 | const result = JSON.parse(response.body); 14 | fileStream.write('/* This file is automatically generated, do not edit manually! */\n\n'); 15 | fileStream.write('exports.ANDROID_BROWSERS = {\n'); 16 | result.forEach((val) => fileStream.write(` '${val.browserId}': ${deviceString(val.browserName)},\n`), null); 17 | fileStream.write('};\n\n'); 18 | fileStream.write('/* This file is automatically generated, do not edit manually! */\n'); 19 | fileStream.end(); 20 | console.log(`Browser ids update complete with ${result.length} entries...`); 21 | }); 22 | 23 | /** 24 | * Escapes \ and ' inside string 25 | * 26 | * @param {string|null} str 27 | * 28 | * @return {string|null} 29 | */ 30 | function deviceString(str) { 31 | if (!str) { 32 | return null; 33 | } 34 | return `'${(str + '').replace(/[\\']/g, '\\$&').replace(/\u0000/g, '\\0')}'`; 35 | } 36 | -------------------------------------------------------------------------------- /bin/update-chrome.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const request = require('request'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const Chrome = require('../src/data/Chrome'); 6 | console.log('Updating chrome versions...'); 7 | const filepath = path.join(__dirname, '../data/browsers-chrome.js'); 8 | const fileStream = fs.createWriteStream(filepath); 9 | const stable = { 10 | desktop: [], 11 | mobile: [], 12 | }; 13 | function comparator(a, b) { 14 | return parseInt(a, 10) - parseInt(b, 10); 15 | } 16 | 17 | request('http://omahaproxy.appspot.com/history', (err, response = {}) => { 18 | if (err) { 19 | return; 20 | } 21 | const omaha = response.body.split('\n'); 22 | omaha.forEach((line) => { 23 | const [os, stability, version] = line.split(','); 24 | if (os === 'mac' && stability === 'stable') { 25 | stable.desktop.push(version.split('.').slice(0, 3).join('.')); 26 | } 27 | if (os === 'android' && stability === 'stable') { 28 | stable.mobile.push(version.split('.').slice(0, 3).join('.')); 29 | } 30 | }); 31 | 32 | stable.desktop.sort(comparator); 33 | stable.mobile.sort(comparator); 34 | 35 | let countNewDesktop = 0; 36 | stable.desktop.forEach((version) => { 37 | if (!Chrome.DESKTOP[version]) { 38 | Chrome.DESKTOP[version] = 'stable'; 39 | countNewDesktop++; 40 | } 41 | }); 42 | 43 | let countNewMobile = 0; 44 | stable.mobile.forEach((version) => { 45 | if (!Chrome.MOBILE[version]) { 46 | Chrome.MOBILE[version] = 'stable'; 47 | countNewMobile++; 48 | } 49 | }); 50 | 51 | fileStream.write('module.exports = {\n'); 52 | fileStream.write(' DESKTOP: {\n'); 53 | Object.keys(Chrome.DESKTOP).forEach((version) => 54 | fileStream.write(` '${version}': '${Chrome.DESKTOP[version]}',\n`) 55 | ); 56 | fileStream.write(' },\n'); 57 | fileStream.write(' MOBILE: {\n'); 58 | Object.keys(Chrome.MOBILE).forEach((version) => 59 | fileStream.write(` '${version}': '${Chrome.MOBILE[version]}',\n`) 60 | ); 61 | fileStream.write(' },\n'); 62 | fileStream.write('};\n'); 63 | 64 | fileStream.end(); 65 | 66 | console.log(`Updated chrome with ${countNewDesktop} new stable version for DEKSTOP`); 67 | console.log(`Updated chrome with ${countNewMobile} new stable version for MOBILE`); 68 | }); 69 | -------------------------------------------------------------------------------- /bin/update-profiles.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const request = require('request'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | console.log('Updating profiles...'); 6 | const filepath = path.join(__dirname, '../data/profiles.js'); 7 | const fileStream = fs.createWriteStream(filepath); 8 | 9 | request('https://api.whichbrowser.net/resources/profiles.json', (err, response = {}) => { 10 | if (err) { 11 | return; 12 | } 13 | const result = JSON.parse(response.body); 14 | fileStream.write('/* This file is automatically generated, do not edit manually! */\n\n'); 15 | fileStream.write('/* eslint-disable max-len */\n\n'); 16 | fileStream.write("const DeviceType = require('../src/constants').deviceType;\n\n"); 17 | fileStream.write('exports.PROFILES = {\n'); 18 | result.forEach( 19 | (profile) => 20 | fileStream.write( 21 | ` ${escapeString(profile.url)}: ` + 22 | `[${escapeString(profile.deviceManufacturer)}, ${escapeString(profile.deviceModel)}, ` + 23 | `${escapeString(profile.osName)}` + 24 | `${deviceType(profile.deviceType) ? `, ${deviceType(profile.deviceType)}` : ''}],\n` 25 | ), 26 | null 27 | ); 28 | fileStream.write('};\n\n'); 29 | fileStream.write('/* eslint-enable max-len */\n\n'); 30 | fileStream.write('/* This file is automatically generated, do not edit manually! */\n'); 31 | fileStream.end(); 32 | console.log(`Downloaded ${result.length} profiles...`); 33 | }); 34 | 35 | /** 36 | * Escapes \ and ' inside string 37 | * 38 | * @param {string|null} str 39 | * 40 | * @return {string|null} 41 | */ 42 | function escapeString(str) { 43 | if (!str) { 44 | return null; 45 | } 46 | return `'${(str + '') 47 | .replace(/[\\']/g, '\\$&') 48 | .replace(/\u{0000}/gu, '\\0') 49 | .replace(/\u{2002}/gu, ' ')}'`; 50 | } 51 | 52 | /** 53 | * Return right constants for devices 54 | * 55 | * @param {string|null} type 56 | * 57 | * @return {string|null} 58 | */ 59 | function deviceType(type) { 60 | switch (type) { 61 | case 'mobile': 62 | return 'DeviceType.MOBILE'; 63 | case 'tablet': 64 | return 'DeviceType.TABLET'; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /bin/update-regexes.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const Applications = require('../src/data/Applications'); 5 | const types = ['BOTS', 'BROWSERS', 'OTHERS']; 6 | 7 | /** 8 | * Write to file the regex for the specified type 9 | * @param {string} type 10 | */ 11 | function updateRegexes(type) { 12 | console.log(`Updating ${type} regexs`); 13 | let ids = []; 14 | if (type === 'BOTS') { 15 | ids = getSet(Applications[type]); 16 | } else { 17 | Object.keys(Applications[type]).forEach((subtype) => { 18 | ids = new Set([...ids, ...getSet(Applications[type][subtype])]); 19 | }); 20 | } 21 | const regex = new RegExp(`(${[...ids].join('|')})`, 'i').toString(); 22 | 23 | fs.writeFileSync( 24 | path.join(__dirname, `../data/regexes/applications-${type.toLowerCase()}.js`), 25 | '/* This file is automatically generated, do not edit manually! */\n\n' + 26 | '/* eslint-disable */\n\n' + 27 | `exports.${type}_REGEX = ${regex};` 28 | ); 29 | console.log(`${type} regexes contains ${regex.split('|').length + 1} entries\n`); 30 | } 31 | 32 | /** 33 | * @param {array} list 34 | * @return {Set} 35 | */ 36 | function getSet(list) { 37 | const set = new Set(); 38 | list.forEach(({ id }) => set.add(id)); 39 | return set; 40 | } 41 | 42 | types.forEach(updateRegexes); 43 | -------------------------------------------------------------------------------- /data/indices/models-asha.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.ASHA_INDEX = { 6 | 7 | '@50': 8 | [ 9 | 500, 10 | 501, 11 | '501s', 12 | '501.1', 13 | '501.2', 14 | 502, 15 | 503, 16 | '503s', 17 | ], 18 | '@AS': 19 | [ 20 | 'Asha230SingleSIM', 21 | 'Asha230DualSIM', 22 | 'Asha500SingleSIM', 23 | 'Asha500DualSIM', 24 | ], 25 | }; 26 | 27 | /* This file is automatically generated, do not edit manually! */ 28 | -------------------------------------------------------------------------------- /data/indices/models-bada.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BADA_INDEX = { 6 | 7 | '@GT': 8 | [ 9 | 'GT- ?S52(50|53)!', 10 | 'GT-S53(30|33)!', 11 | 'GT-S5380!', 12 | 'GT-S57(50|53)!', 13 | 'GT-S57(80)!', 14 | 'GT-S72(30|33)!', 15 | 'GT-S7250!', 16 | 'GT-S8500!', 17 | 'GT- ?S8530!', 18 | 'GT- ?S8600!', 19 | ], 20 | '@SC': 21 | [ 22 | 'SCH-F859!', 23 | ], 24 | '@SH': 25 | [ 26 | 'SHW-M410', 27 | ], 28 | }; 29 | 30 | /* This file is automatically generated, do not edit manually! */ 31 | -------------------------------------------------------------------------------- /data/indices/models-brew.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BREW_INDEX = { 6 | '@AX': ['AX8575'], 7 | '@CD': ['CDM8992', 'CDM8999'], 8 | '@CO': ['Coolpad D508', 'Coolpad D510', 'Coolpad E600'], 9 | '@E4': ['E4255'], 10 | '@EX': ['EX200!'], 11 | '@HS': ['HS-E316!'], 12 | '@HU': [ 13 | 'HUAWEI U526', 14 | 'HUAWEI U528', 15 | 'HUAWEI U2801!', 16 | 'HUAWEI U5200!', 17 | 'HUAWEI U5300!', 18 | 'HUAWEI U5310!', 19 | 'HUAWEI U6150!' 20 | ], 21 | '@LG': [ 22 | 'LG272', 23 | 'LG510', 24 | 'LGE AX840', 25 | 'LGE LG700', 26 | 'LGE LG840', 27 | 'LGE UX700', 28 | 'LGE UX840', 29 | 'LGE VX11K', 30 | 'LGE VX8575', 31 | 'LGE VX9700' 32 | ], 33 | '@LN': ['LN240', 'LN510'], 34 | '@LX': ['LX610'], 35 | '@M2': ['M260!'], 36 | '@M3': ['M350!', 'M370!', 'M380!', 'M390!'], 37 | '@M5': ['M550!', 'M560!'], 38 | '@NO': ['NOKIA 7705'], 39 | '@P5': ['P5000'], 40 | '@P6': ['P6020', 'P6030'], 41 | '@PA': ['Pantech CDM8992!', 'Pantech CDM8999!', 'Pantech TXT8045!'], 42 | '@PL': ['PLS M330'], 43 | '@S2': ['S2151!'], 44 | '@SA': ['sam-r631', 'sam-r640', 'sam-r900'], 45 | '@SC': [ 46 | 'SCH-B309!', 47 | 'SCH-F839', 48 | 'SCH-M519!', 49 | 'SCH-S559!', 50 | 'SCH-S579!', 51 | 'SCH-U380!', 52 | 'SCH-U485', 53 | 'SCH-U640!', 54 | 'SCH-U660!', 55 | 'SCH-U680!', 56 | 'SCH-U750!', 57 | 'SCH-U820!', 58 | 'SCH-U960!', 59 | 'SCH-W709!', 60 | 'SCH-W799!', 61 | 'SCP-3810', 62 | 'SCP3810', 63 | 'SCP-6750', 64 | 'SCP6760', 65 | 'SCP-6760', 66 | 'SCP6780' 67 | ], 68 | '@SG': ['SGH-A937!', 'SGH-A947!'], 69 | '@SM': ['SM-B690V'], 70 | '@SP': ['SPH M330', 'SPH-M570', 'Sprint M850'], 71 | '@TX': ['TXT8045'], 72 | '@VN': ['VN170!', 'VN250!', 'VN271!', 'VN280!', 'VN360!', 'VN370!', 'VN530'], 73 | '@VX': ['VX5600!', 'VX9200!', 'VX9600!', 'VX11000!'], 74 | '@ZT': ['ZTE F-450!', 'ZTE R516!', 'ZTE R518!'] 75 | }; 76 | 77 | /* This file is automatically generated, do not edit manually! */ 78 | -------------------------------------------------------------------------------- /data/indices/models-feature.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.FEATURE_INDEX = { 6 | '@AM': ['Amstrad Gamma'], 7 | '@BE': ['Benefon Q'], 8 | '@CK': ['CK13[ai]?$!', 'CK15[ai]?$!'], 9 | '@CO': ['COCOON'], 10 | '@EF': ['EF71'], 11 | '@EX': ['EX115', 'EX118', 'EX119', 'EX128', 'EX225', 'EX226', 'EX430'], 12 | '@F1': ['F100[ai]?$!'], 13 | '@GM': ['GM360'], 14 | '@GR': ['GR700'], 15 | '@GS': ['GS290', 'GS500'], 16 | '@GT': [ 17 | 'GT500!', 18 | 'GT550', 19 | 'GT-B2710', 20 | 'GT-B3210', 21 | 'GT-B3313', 22 | 'GT-C3200', 23 | 'GT-C3222', 24 | 'GT-C3322', 25 | 'GT-C3500', 26 | 'GT-C5010!', 27 | 'GT-E1282!', 28 | 'GT-E2152', 29 | 'GT-E2220', 30 | 'GT-E2222', 31 | 'GT-E2202', 32 | 'GT-E2250', 33 | 'GT-E2252', 34 | 'GT-E3213', 35 | 'GT-E3309I', 36 | 'GT-M8910', 37 | 'GT-S3332', 38 | 'GT-S33(50|53)!', 39 | 'GT-S35(70|72)!', 40 | 'GT-S5229', 41 | 'GT-S5270!', 42 | 'GT-S5610!', 43 | 'GT-I6410!', 44 | 'GT-I8320!', 45 | 'GT-I8330!' 46 | ], 47 | '@J1': ['J105[ai]?$!', 'J108[ai]?$!', 'J10(i2?)?$!'], 48 | '@J2': ['J20[ai]?$!'], 49 | '@K6': ['K612'], 50 | '@KC': ['KC910i'], 51 | '@KP': ['KP500!', 'KP570!'], 52 | '@KU': ['KU990i'], 53 | '@LG': ['LG-KU380', 'LG-KU580', 'LG-KU990'], 54 | '@LI': ['Lightpipe'], 55 | '@M3': ['m3510c'], 56 | '@MO': ['MOTOQA1'], 57 | '@P7': ['P7000'], 58 | '@P9': ['P9020', 'P9050'], 59 | '@PL': ['PLS6600KJ'], 60 | '@PM': ['PM-8200'], 61 | '@S7': ['S7350'], 62 | '@SA': ['sam-r560'], 63 | '@SC': ['SCP-5300', 'SCP-5500', 'SCP-6600', 'SCH-W169', 'SCH-W279'], 64 | '@SE': ['Sendo Wap'], 65 | '@SG': [ 66 | 'SGH-A667', 67 | 'SGH-A697', 68 | 'SGH-A877', 69 | 'SGH-A927', 70 | 'SGH-A997', 71 | 'SGH-D880', 72 | 'SGH-E250i', 73 | 'SGH-E250V', 74 | 'SGH-G600', 75 | 'SGH-J700i', 76 | 'SGH-J700V', 77 | 'SGH-M200', 78 | 'SGH-S150G', 79 | 'SGH-S390G', 80 | 'SGH-T189N', 81 | 'SGHX660V', 82 | 'SGH-Z107!', 83 | 'SGH-Z130!', 84 | 'SGH-Z500!' 85 | ], 86 | '@SM': ['SM-B313E', 'SM-B350E', 'SM-B360E', 'SM-B780(A|W)!'], 87 | '@TE': ['tecnot36'], 88 | '@U1': ['U100[ai]?$!', 'U10[ai]?$!'], 89 | '@VO': ['Vodafone 575'], 90 | '@W1': ['W100i?$!', 'W150i?$!'], 91 | '@W2': ['W20i?$!'], 92 | '@WI': ['WIDETEL WCX150'], 93 | '@WT': ['WT13i$!'], 94 | '@X5': ['X5i$!'] 95 | }; 96 | 97 | /* This file is automatically generated, do not edit manually! */ 98 | -------------------------------------------------------------------------------- /data/indices/models-firefoxos.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.FIREFOXOS_INDEX = { 6 | '@': ['.LYF\\/.F30C!', '.LYF\\/.F101K!'], 7 | '@AL': [ 8 | 'ALCATEL ONE TOUCH FIRE', 9 | 'ALCATEL ONE TOUCH 4012A', 10 | 'ALCATEL ONE TOUCH 4012X', 11 | 'ALCATELOneTouch4012A!', 12 | 'ALCATELOneTouch4012X!', 13 | 'ALCATELOneTouch4019A!', 14 | 'ALCATELOneTouch4019X!', 15 | 'ALCATELOneTouch4020D!', 16 | 'ALCATELOneTouch4022!', 17 | 'ALCATELOneTouch4023!', 18 | 'ALCATELOneTouch6015X!', 19 | 'ALCATEL4044[MNOTVW]!', 20 | 'ALCATEL4044C!' 21 | ], 22 | '@HU': ['HUAWEI Ascend Y300-F1', 'HUAWEIY300-F1'], 23 | '@LG': ['LG-D3(00|01)!', 'LGL25'], 24 | '@LY': ['LYF\\/F30C!', 'LYF\\/F41T!', 'LYF\\/F50Y!', 'LYF\\/F61F!', 'LYF\\/F81E!', 'LYF\\/F90M!', 'LYF\\/F101K!'], 25 | '@MA': ['madai'], 26 | '@ON': ['OneTouch4019A'], 27 | '@OP': ['OPEN', 'OpenC', 'Open C', 'OPENC2', 'OPEN2'], 28 | '@OR': ['Orange KLIF', 'Orange KLIFD'], 29 | '@ZT': ['ZTEOPEN'] 30 | }; 31 | 32 | /* This file is automatically generated, do not edit manually! */ 33 | -------------------------------------------------------------------------------- /data/indices/models-palmos.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.PALMOS_INDEX = { 6 | 7 | '@AC': 8 | [ 9 | 'acer-momo', 10 | 'acer-coco', 11 | 'Acea-MZ01', 12 | 'Acea-PD01', 13 | ], 14 | '@GR': 15 | [ 16 | 'grmn-3200', 17 | 'grmn-3600', 18 | 'grmn-3700', 19 | ], 20 | '@GS': 21 | [ 22 | 'gsRl-zicn', 23 | 'gsRl-zcn2', 24 | 'gsRl-zcn5', 25 | ], 26 | '@HS': 27 | [ 28 | 'hspr-H101', 29 | 'hspr-H102', 30 | ], 31 | '@KW': 32 | [ 33 | 'kwc.-7135', 34 | ], 35 | '@PA': 36 | [ 37 | 'Palm-D061', 38 | 'Palm-D062', 39 | 'Palm-TunX', 40 | 'Palm-stuj', 41 | 'Palm-hbbs', 42 | 'Palm-trnd', 43 | 'Palm-ecty', 44 | 'Palm-lith', 45 | 'Palm-sky1', 46 | 'Palm-D053', 47 | 'Palm-D052', 48 | 'Palm-D060', 49 | 'Palm-MT64', 50 | 'Palm-Cct1', 51 | 'Palm-Zir4', 52 | 'Palm-Frg1', 53 | 'Palm-Frg2', 54 | 'Palm-Arz1', 55 | 'Palm-TnT5', 56 | 'Palm-atc1', 57 | 'Palm-D050', 58 | 'Palm-Cubs', 59 | 'Palm-Zi21', 60 | 'Palm-D051', 61 | 'Palm-Zi22', 62 | 'Palm-Zpth', 63 | 'Palm-Zi72', 64 | ], 65 | '@QC': 66 | [ 67 | 'qcom-qc20', 68 | ], 69 | '@SM': 70 | [ 71 | 'smsn-phix', 72 | 'smsn-Phx2', 73 | 'smsn-blch', 74 | 'smsn-BLFM', 75 | 'smsn-glxy', 76 | ], 77 | '@SO': 78 | [ 79 | 'sony-ystn', 80 | 'sony-ysmt', 81 | 'sony-ysm2', 82 | 'sony-nsca', 83 | 'sony-nsc2', 84 | 'sony-vnce', 85 | 'sony-mdna', 86 | 'sony-npls', 87 | 'sony-rdwd', 88 | 'sony-crdb', 89 | 'sony-tldo', 90 | 'sony-mdrd', 91 | 'sony-grnd', 92 | 'sony-frta', 93 | 'sony-cocs', 94 | 'sony-glps', 95 | 'sony-mcnd', 96 | 'sony-vrna', 97 | 'sony-atom', 98 | 'sony-goha', 99 | 'sony-leia', 100 | 'sony-hwai', 101 | 'sony-goku', 102 | 'sony-luke', 103 | 'sony-amno', 104 | 'sony-prmr', 105 | 'sony-ancy', 106 | ], 107 | '@TP': 108 | [ 109 | 'Tpwv-Rdog', 110 | ], 111 | '@TR': 112 | [ 113 | 'trgp-trg1', 114 | 'trgp-trg2', 115 | ], 116 | }; 117 | 118 | /* This file is automatically generated, do not edit manually! */ 119 | -------------------------------------------------------------------------------- /data/indices/models-s30plus.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.S30PLUS_INDEX = { 6 | 7 | '@21': 8 | [ 9 | 215, 10 | ], 11 | '@22': 12 | [ 13 | 220, 14 | 222, 15 | 225, 16 | ], 17 | '@23': 18 | [ 19 | 230, 20 | ], 21 | }; 22 | 23 | /* This file is automatically generated, do not edit manually! */ 24 | -------------------------------------------------------------------------------- /data/indices/models-tizen.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.TIZEN_INDEX = { 6 | '@AR': ['(ARMV7 )?SM-Z9005!'], 7 | '@BA': ['Baltic'], 8 | '@EM': ['Emulator'], 9 | '@FA': ['FamilyHub'], 10 | '@GT': ['GT-I8800!', 'GT-I8805!', 'GT-I9500!'], 11 | '@HA': ['hawkp'], 12 | '@KI': ['KIRAN'], 13 | '@MO': ['Mobile-RD-PQ', 'Mobile-Emulator'], 14 | '@NX': ['NX300'], 15 | '@RF': ['RF10M9995!', 'RF23M8590!', 'RF265BEAE!', 'RF28M9580!', 'RF56M9540!', 'RF85K9993!', 'RF85M95A2!'], 16 | '@RH': ['RH81M8090!'], 17 | '@SC': ['SC-03F'], 18 | '@SD': ['sdk'], 19 | '@SE': ['SEC SC-001', 'SEC SC-03F'], 20 | '@SG': ['SGH-N099'], 21 | '@SM': [ 22 | 'SM-HIGGS', 23 | '(ARMV7 )?SM-Z9005!', 24 | 'SM-Z130!', 25 | 'SM-Z200!', 26 | 'SM-Z250!', 27 | 'SM-Z300!', 28 | 'SM-Z400!', 29 | 'SM-Z500!', 30 | 'SM-Z700!', 31 | 'SM-Z900!', 32 | 'SM-Z910!', 33 | 'SM-G870F0', 34 | 'SM-R360!', 35 | 'SM-R600!', 36 | 'SM-R720!', 37 | 'SM-R730!', 38 | 'SM-R732!', 39 | 'SM-R735!', 40 | 'SM-R750!', 41 | 'SM-R760!', 42 | 'SM-R765!', 43 | 'SM-R770!', 44 | 'SM-R805!' 45 | ], 46 | '@TI': ['TIZEN SM-Z130!', 'TIZEN SM-Z300!', 'TIZEN Emulator'], 47 | '@TM': ['TM1'], 48 | '@XU': ['xu3'], 49 | '@Z3': ['Z3 Z910F'] 50 | }; 51 | 52 | /* This file is automatically generated, do not edit manually! */ 53 | -------------------------------------------------------------------------------- /data/indices/models-touchwiz.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.TOUCHWIZ_INDEX = { 6 | 7 | '@GT': 8 | [ 9 | 'GT-B5310!', 10 | 'GT-B3410', 11 | 'GT-B7722', 12 | 'GT-C3262', 13 | 'GT-C33(00|03)!', 14 | 'GT-C3312R', 15 | 'GT-C3312!', 16 | 'GT-C3330', 17 | 'GT-C6712', 18 | 'GT-E2652!', 19 | 'GT-I6230!', 20 | 'GT-I6712!', 21 | 'GT-M3710', 22 | 'GT-M5650', 23 | 'GT-S3370!', 24 | 'GT-S36(50|53)!', 25 | 'GT-S3770!', 26 | 'GT-S38(00|02)!', 27 | 'GT-S3850', 28 | 'GT-S5220', 29 | 'GT-S5222R', 30 | 'GT-S5222', 31 | 'GT-S52(30|33)!', 32 | 'GT-S5260P', 33 | 'GT-S52(60|63)!', 34 | 'GT-S5292R', 35 | 'GT-S5292', 36 | 'GT-S5560!', 37 | 'GT-S5600', 38 | 'GT-S5603', 39 | 'GT-S5620!', 40 | 'GT-S5680', 41 | 'GT-S7550', 42 | 'GT-S8000c', 43 | 'GT-S8003', 44 | ], 45 | '@S8': 46 | [ 47 | 'S80(00|03)!', 48 | ], 49 | '@SG': 50 | [ 51 | 'SGH-A597', 52 | 'SGH-F480', 53 | 'SGH-F480I', 54 | 'SGH-T528g', 55 | ], 56 | }; 57 | 58 | /* This file is automatically generated, do not edit manually! */ 59 | -------------------------------------------------------------------------------- /data/manufacturer-names.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | MANUFACTURERS: { 3 | GENERIC: { 4 | 'LG Electronics': 'LG', 5 | LGE: 'LG', 6 | TOSHIBA: 'Toshiba', 7 | SAMSUNG: 'Samsung', 8 | SHARP: 'Sharp', 9 | SONY: 'Sony', 10 | }, 11 | TELEVISION: { 12 | ALDISUED: 'Aldi', 13 | BANGOLUFSEN: 'Bang & Olufsen', 14 | CHANGHONG: 'Changhong', 15 | changhong: 'Changhong', 16 | FINLUX: 'Finlux', 17 | 'HHW HAIER': 'Haier', 18 | HITACHI: 'Hitachi', 19 | HYUNDAI: 'Hyundai', 20 | inverto: 'Inverto', 21 | LOEWE: 'Loewe', 22 | MEDION: 'Medion', 23 | 'Nagra OpenTV': 'NAGRA', 24 | PANASONIC: 'Panasonic', 25 | Sagemcom_Broadband_SAS: 'Sagemcom', 26 | SERAPHIC: 'Seraphic', 27 | selevision: 'Selevision', 28 | smart: 'Smart', 29 | Sky_worth: 'Skyworth', 30 | 'TechnoTrend Goerler': 'TechnoTrend', 31 | 'TechnoTrend Goerler/Kathrein': 'TechnoTrend', 32 | TELEFUNKEN: 'Telefunken', 33 | THOM: 'Thomson', 34 | THOMSON: 'Thomson', 35 | tv2n: 'TV2N', 36 | VESTEL: 'Vestel', 37 | }, 38 | }, 39 | }; 40 | -------------------------------------------------------------------------------- /data/models-asha.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.ASHA_MODELS = { 6 | 'Asha230SingleSIM' : [ 'Nokia', 'Asha 230' ], 7 | 'Asha230DualSIM' : [ 'Nokia', 'Asha 230' ], 8 | '500' : [ 'Nokia', 'Asha 500' ], 9 | 'Asha500SingleSIM' : [ 'Nokia', 'Asha 500' ], 10 | 'Asha500DualSIM' : [ 'Nokia', 'Asha 500' ], 11 | '501' : [ 'Nokia', 'Asha 501' ], 12 | '501s' : [ 'Nokia', 'Asha 501' ], 13 | '501.1' : [ 'Nokia', 'Asha 501' ], 14 | '501.2' : [ 'Nokia', 'Asha 501' ], 15 | '502' : [ 'Nokia', 'Asha 502' ], 16 | '503' : [ 'Nokia', 'Asha 503' ], 17 | '503s' : [ 'Nokia', 'Asha 503' ], 18 | }; 19 | 20 | /* This file is automatically generated, do not edit manually! */ 21 | -------------------------------------------------------------------------------- /data/models-bada.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BADA_MODELS = { 6 | 'GT- ?S52(50|53)!' : [ 'Samsung', 'Wave 525' ], 7 | 'GT-S53(30|33)!' : [ 'Samsung', 'Wave 533' ], 8 | 'GT-S5380!' : [ 'Samsung', 'Wave Y' ], 9 | 'GT-S57(50|53)!' : [ 'Samsung', 'Wave 575' ], 10 | 'GT-S57(80)!' : [ 'Samsung', 'Wave 578' ], 11 | 'GT-S72(30|33)!' : [ 'Samsung', 'Wave 723' ], 12 | 'GT-S7250!' : [ 'Samsung', 'Wave M' ], 13 | 'GT-S8500!' : [ 'Samsung', 'Wave' ], 14 | 'SCH-F859!' : [ 'Samsung', 'Wave' ], 15 | 'GT- ?S8530!' : [ 'Samsung', 'Wave II' ], 16 | 'GT- ?S8600!' : [ 'Samsung', 'Wave 3' ], 17 | 'SHW-M410' : [ 'Samsung', 'Wave 3' ] 18 | }; 19 | 20 | /* This file is automatically generated, do not edit manually! */ 21 | -------------------------------------------------------------------------------- /data/models-blackberry.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BLACKBERRY_MODELS = { 6 | '9000' : 'Bold', 7 | '9600' : 'Bold', 8 | '9650' : 'Bold', 9 | '9700' : 'Bold', 10 | '9780' : 'Bold', 11 | '9788' : 'Bold', 12 | '9790' : 'Bold', 13 | '9900' : 'Bold', 14 | '9930' : 'Bold', 15 | '8300' : 'Curve', 16 | '8310' : 'Curve', 17 | '8320' : 'Curve', 18 | '8330' : 'Curve', 19 | '8350i' : 'Curve', 20 | '8520' : 'Curve', 21 | '8530' : 'Curve', 22 | '8900' : 'Curve', 23 | '9220' : 'Curve', 24 | '9300' : 'Curve', 25 | '9310' : 'Curve', 26 | '9315' : 'Curve', 27 | '9320' : 'Curve', 28 | '9330' : 'Curve', 29 | '9350' : 'Curve', 30 | '9360' : 'Curve', 31 | '9370' : 'Curve', 32 | '9380' : 'Curve', 33 | '8100' : 'Pearl', 34 | '8110' : 'Pearl', 35 | '8120' : 'Pearl', 36 | '8130' : 'Pearl', 37 | '8220' : 'Pearl', 38 | '8230' : 'Pearl', 39 | '9100' : 'Pearl', 40 | '9105' : 'Pearl', 41 | '9500' : 'Storm', 42 | '9520' : 'Storm2', 43 | '9530' : 'Storm', 44 | '9550' : 'Storm', 45 | '9670' : 'Style', 46 | '9800' : 'Torch', 47 | '9810' : 'Torch', 48 | '9850' : 'Torch', 49 | '9860' : 'Torch', 50 | '9630' : 'Tour', 51 | '9981' : 'Porsche P' 52 | }; 53 | 54 | /* This file is automatically generated, do not edit manually! */ 55 | -------------------------------------------------------------------------------- /data/models-firefoxos.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.FIREFOXOS_MODELS = { 6 | 'ALCATEL ONE TOUCH FIRE': ['Alcatel', 'One Touch Fire'], 7 | 'ALCATEL ONE TOUCH 4012A': ['Alcatel', 'One Touch Fire'], 8 | 'ALCATEL ONE TOUCH 4012X': ['Alcatel', 'One Touch Fire'], 9 | 'ALCATELOneTouch4012A!': ['Alcatel', 'One Touch Fire'], 10 | 'ALCATELOneTouch4012X!': ['Alcatel', 'One Touch Fire'], 11 | OneTouch4019A: ['Alcatel', 'One Touch Fire C'], 12 | 'ALCATELOneTouch4019A!': ['Alcatel', 'One Touch Fire C'], 13 | 'ALCATELOneTouch4019X!': ['Alcatel', 'One Touch Fire C'], 14 | 'ALCATELOneTouch4020D!': ['Alcatel', 'One Touch Fire C'], 15 | 'ALCATELOneTouch4022!': ['Alcatel', 'One Touch Pixi 3 (3.5)'], 16 | 'ALCATELOneTouch4023!': ['Alcatel', 'One Touch Pixi 3 (3.5)'], 17 | 'ALCATELOneTouch6015X!': ['Alcatel', 'One Touch Fire E'], 18 | 'HUAWEI Ascend Y300-F1': ['Huawei', 'Ascend Y300 F1'], 19 | 'HUAWEIY300-F1': ['Huawei', 'Ascend Y300 F1'], 20 | 'LG-D3(00|01)!': ['LG', 'Fireweb'], 21 | LGL25: ['LG', 'Fx0'], 22 | madai: ['LG', 'Fx0'], 23 | 'Orange KLIF': ['Orange', 'Kilf'], 24 | 'Orange KLIFD': ['Orange', 'Kilf'], 25 | OPEN: ['ZTE', 'Open'], 26 | ZTEOPEN: ['ZTE', 'Open'], 27 | OpenC: ['ZTE', 'Open C'], 28 | 'Open C': ['ZTE', 'Open C'], 29 | OPENC2: ['ZTE', 'Open C2'], 30 | OPEN2: ['ZTE', 'Open II'], 31 | 32 | 'ALCATEL4044[MNOTVW]!': ['Alcatel', 'Go Flip'], 33 | 'ALCATEL4044C!': ['Alcatel', 'QUICKFLIP'], 34 | '.LYF/.F30C!': ['Jio', 'JioPhone F30C'], 35 | '.LYF/.F101K!': ['Jio', 'JioPhone F101K'], 36 | 'LYF/F30C!': ['Jio', 'JioPhone F30C'], 37 | 'LYF/F41T!': ['Jio', 'JioPhone F41T'], 38 | 'LYF/F50Y!': ['Jio', 'JioPhone F50Y'], 39 | 'LYF/F61F!': ['Jio', 'JioPhone F61F'], 40 | 'LYF/F81E!': ['Jio', 'JioPhone F81E'], 41 | 'LYF/F90M!': ['Jio', 'JioPhone F90M'], 42 | 'LYF/F101K!': ['Jio', 'JioPhone F101K'] 43 | }; 44 | 45 | /* This file is automatically generated, do not edit manually! */ 46 | -------------------------------------------------------------------------------- /data/models-s30plus.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.S30PLUS_MODELS = { 6 | '215' : [ 'Nokia', '215' ], 7 | '220' : [ 'Nokia', '220' ], 8 | '222' : [ 'Nokia', '222' ], 9 | '225' : [ 'Nokia', '225' ], 10 | '230' : [ 'Nokia', '230' ] 11 | }; 12 | 13 | /* This file is automatically generated, do not edit manually! */ 14 | -------------------------------------------------------------------------------- /data/os-darwin.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | DARWIN: { 3 | OSX: { 4 | 1: { value: '10.0' }, 5 | 5: { value: '10.1' }, 6 | 6: { value: '10.2' }, 7 | 7: { value: '10.3' }, 8 | 8: { value: '10.4' }, 9 | 9: { value: '10.5' }, 10 | 10: { value: '10.6' }, 11 | 11: { value: '10.7' }, 12 | 12: { value: '10.8' }, 13 | 13: { value: '10.9' }, 14 | 14: { value: '10.10' }, 15 | 15: { value: '10.11' }, 16 | }, 17 | IOS: { 18 | 9: { value: '1' }, 19 | 10: { value: '4' }, 20 | 11: { value: '5' }, 21 | 13: { value: '6' }, 22 | 14: { value: '7' }, 23 | 15: { value: '9' }, 24 | }, 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /data/regexes/applications-bots.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BOTS_REGEX = /(008|360|a6|abound|muncher|adaxas|addthis|admantx|adsbot|ahrefs|archiver|altavista|curious|cloudfront|amorank|apple|archive|jeeves|astra|backlink|baidu|barkrowler|bazqux|bingbot|msnbot|msmobot|bing|blex|blogbridge|blogger|bloglines|bloglovin|blogpulse|blogram|blogtrot|blogshares|boardreader|lddc|browsershots|bubing|buck|builtwith|butterfly|buzzsumo|bytespider|heritrix|clarabot|cliqz|cloudflare|coccoc|comodo|commafeed|cbot|cresearch|watchdog|datanyze|datasearch|dataprovider|daum|daumoa|digg|domaincrawl|domainstats|discord|domain|dmca|duckduck|embed|evc|exabot|exactseek|ezooms|facebook|fast|flamingo|fastladder|feed|wrangler|validator|fever|florienzh|friendica|robot|genieo|fetchor|google|gofeed|gomez|ichiro|gooblog|goorss|gowiki|grammarly|grub|hatena|capture|heureka|hootsuite|htdig|httpmon|hubpages|hubspot|spider|indeed|iodc|istellabot|crawler|kakao|kouio|larbin|letsearch|line|linkedin|linkpad|linkdex|livedoor|seeker|ltx71|magpie|mj12bot|mapion|mail.ru|medium|megaindex|socialstreams|mixi|minds|mnogo|mojeek|monitor|dotbot|rogerbot|yeti|mxtoolbox|netcraft|netestate|netvibes|newsblur|newsgator|nimbostratus|odklbot|orange|pages|petal|aspiegel|psbot|pingdom|pinterest|plurk|pocket|postrank|comment|reddit|rssbar|hunter|quora|safesearch|scrapy|searchatlas|seekport|semrush|serpstat|seokicks|seznam|shopwiki|reader|simplepie|site24|skype|slack|sogou|sophora|soso|spaziodati|spdycheck|spinn|sputnik|detector|summify|telegram|twisted|twitter|tiny|tineye|tlsprober|trustedsite|typhoeus|vagabondo|velen|vkshare|voat|voila|vocus|mcrawler|vuhuv|w3bot|jigsaw|w3c|wappalyzer|wayback|webindexer|wordpress|mechanize|xenu|xerka|sitemap|yacy|yandex|yahoo|y!j|slurp|yelp|yioop|yisou|zgrab|zmeu|httpclient|nutch|synapse|indy|go|httpunit|okhttp|node|wget|curl|package|java|simple|libwww|lwp|urllib|requests|php|pear|zend|ruby)/i; 6 | -------------------------------------------------------------------------------- /data/regexes/applications-browsers.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.BROWSERS_REGEX = /(115|126|2345|37abc|qihu|1stbrowser|7star|abrowse|acorn|acoo|amigo|aol|america|apus|arachne|arora|aweb|avant|asw|avg|aviator|avira|flyflow|bdbrowser|bdspark|basilisk|beamrise|beonex|blackwren|blackhawk|bolt|blackbird|brave|brisk|browsex|browzar|byffox|camino|canure|ccleaner|cent|charon|chedot|cheshire|chimlac|chimera|chromeplus|colibri|columbus|cometbird|comodo|dragon|conkeror|coc|coolnovo|corom|crazy|crusta|cunaguaro|cyberdog|cyberfox|daedalus|degan|demeter|deskbrowse|diigo|dillo|doczilla|rhodonit|dplus|elements|eudoraweb|falkon|flamesky|flock|framafox|freeu|galeon|globalmojo|epiphany|greenbrowser|hola|hydra|ibrowse|icab|iceape|icecat|icedove|iceweasel|irider|iridium|iron|kapiko|kazehakase|kchrome|kinza|kkman|klondike|kylo|meleon|lbrowser|lbbrowser|light|lobo|lolifox|lovense|lunascape|naenara|netcaptor|madfox|mxbrowser|min|mini|mixshark|mlbrowser|mypal|multixp|netpositive|nichrome|origyn|owb|live|juzi|orca|oregano|otter|palemoon|patriott|perk|polarity|privacy|qiyu|qtweb|quicklook|qupzilla|qute|rekonq|ryouko|sylera|saayaa|salam|shiira|sielo|sitekiosk|sleipnir|slimjet|metasr|sparrow|sputnik|stainless|station|sunchrome|sundance|sundial|superbird|swiftweasel|swiftfox|swing|to-browser|tencent|tenfourfox|theworld|tulip|tungsten|ultrab|usejump|vimprobable|vivaldi|airwatch|vonkeror|voyager|waterfox|whale|winwap|xvast|yabrowser|zvu|zipzap|zombie|1password|3g explorer|4g explorer|aloha|atomiclite|au|awakening|baidu|bdmobile|bidu|baiduboxapp|browser|blazer|acheetahi|cornowser|coolmarket|cute|digia|doris|doroty|ecosia|www browser|epic|eui|go.web|helium|heytap|huohoubrowser|surfboard|isurf|jig browser|jumanji|tnsbrowser|kiosk|kiwi|lebrowser|liebao|macross|mammoth|mcent|mint|mobicip|mib|cmcs|motorola|multizilla|netfrontlife|onebrowser|oneplus|plink|polaris|pure|openwave|up|km|oppo|quark|realme|semc|stnc|sogou|symphony|tenta|ucpro|vivo|weblite|wk|yaani|alti|aplix|awox|browserserver|isis|netbox|spyglass|oregan|viera|zetakey|bunjalloo|nwf|nuanti|wib|prince|demobrowser|dooble|dwb|evm|fireweb|hive|intermec|phantom|qt|roccat|raven|rockmelt|scope|slim|smbrowser|snowshoe|surf|tao|taz|uzbl|villanova|vimb|wada|wavelink|webrender|webster|wyzo|yelang|yrcweb|linemode|lynx|links|w3m|nimbus|Webwasher|sankore|adapi|brightsign|coship)/i; 6 | -------------------------------------------------------------------------------- /data/regexes/applications-others.js: -------------------------------------------------------------------------------- 1 | /* This file is automatically generated, do not edit manually! */ 2 | 3 | /* eslint-disable */ 4 | 5 | exports.OTHERS_REGEX = /(itunes|qt|bluefish|nightingale|songbird|stagefright|substream|vlc|windows-media|coreplayer|flycast|boxee|kodi|xbmc|lightning|thunderbird|outlook|lotus|postbox|bat|yahoo|daum|flipboard|akregator|blogos|cococ|feed|liferea|news|jetbrains|rss|reeder|reedkit|rome|ziepod|messenger|kakao|kik|line|slack|viber|whatsapp|wire|yammer|zalo|fbios|fb4a|googleplus|instagram|pinterest|weibo|tumblr|twitter|wp-android|yelp|office|bingweb|hao123|gsa|naver|sogousearch|yandex|atom|golive|brackets|iweb|frontpage|amaya|websphere|download|tansodl|origin|secondlife|valve|raptr|alipay|cooliris|google|leechcraft|expeditor)/i; 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "which-browser", 3 | "version": "0.7.1", 4 | "description": "Browser sniffing tool and UA parser. Browser sniffing gone too far — A useragent parser library for JavaScript", 5 | "main": "src/Parser.js", 6 | "types": "which-browser.d.ts", 7 | "scripts": { 8 | "test": "lab -a @hapi/code -v", 9 | "test-and-coverage": "nyc lab -a @hapi/code -v --timeout 10000 -l", 10 | "lint": "eslint --quiet .", 11 | "update-applications": "node ./bin/update-applications", 12 | "update-browser-ids": "node ./bin/update-browser-ids", 13 | "update-chrome": "node ./bin/update-chrome", 14 | "update-indices": "node ./bin/update-indices", 15 | "update-models": "node ./bin/update-models", 16 | "update-profiles": "node ./bin/update-profiles", 17 | "update-regexes": "node ./bin/update-regexes", 18 | "update-all": "npm run update-applications && npm run update-browser-ids && npm run update-chrome && npm run update-indices && npm run update-models && npm run update-profiles && npm run update-regexes", 19 | "prepare": "husky install" 20 | }, 21 | "engines": { 22 | "node": ">=6.0.0" 23 | }, 24 | "repository": { 25 | "type": "git", 26 | "url": "https://github.com/mariotsi/WhichBrowser-js.git" 27 | }, 28 | "keywords": [ 29 | "browser", 30 | "sniffing", 31 | "user-agent", 32 | "useragent", 33 | "node", 34 | "ua", 35 | "parser", 36 | "whichbrowser" 37 | ], 38 | "author": "Simone Mariotti", 39 | "license": "MIT", 40 | "devDependencies": { 41 | "@hapi/code": "^9.0.3", 42 | "@hapi/lab": "^25.1.3", 43 | "eslint": "^8.52.0", 44 | "eslint-config-google": "^0.14.0", 45 | "eslint-config-prettier": "^9.0.0", 46 | "eslint-plugin-prettier": "^5.0.1", 47 | "husky": "^8.0.0", 48 | "lint-staged": "^15.0.2", 49 | "nyc": "^15.1.0", 50 | "prettier": "^3.0.3", 51 | "request": "^2.88.2", 52 | "sinon": "^17.0.0", 53 | "yamljs": "^0.3.0" 54 | }, 55 | "lint-staged": { 56 | "*.js": [ 57 | "prettier --write", 58 | "eslint --fix" 59 | ] 60 | }, 61 | "prettier": { 62 | "singleQuote": true, 63 | "printWidth": 117, 64 | "trailingComma": "es5" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Analyser.js: -------------------------------------------------------------------------------- 1 | const Main = require('./model/Main'); 2 | const { Camouflage, Corrections, Derive, Header } = require('./Analyser/'); 3 | 4 | /** 5 | * Class that parse the user-agent 6 | */ 7 | class Analyser { 8 | /** 9 | * Create a Analyser instance 10 | * 11 | * @param {object} headers An object with all of the headers or a string with just the User-Agent header 12 | * @param {object} options Optional, an object with configuration options 13 | */ 14 | constructor(headers = {}, options = {}) { 15 | this.headers = headers; 16 | this.options = options; 17 | } 18 | 19 | /** 20 | * set data to data property 21 | * 22 | * @param {object} data 23 | */ 24 | setData(data) { 25 | this.data = data; 26 | } 27 | 28 | /** 29 | * return data from data property 30 | * 31 | * @return {object} data 32 | */ 33 | getData() { 34 | return this.data; 35 | } 36 | 37 | /** 38 | * Analyse the provided headers or User-Agent string 39 | * 40 | */ 41 | analyse() { 42 | if (!this.data) { 43 | this.data = new Main(); 44 | } 45 | Header.analyseHeaders.call(this); 46 | Derive.deriveInformation.call(this); 47 | Corrections.applyCorrections.call(this); 48 | Camouflage.detectCamouflage.call(this); 49 | Derive.deriveDeviceSubType.call(this); 50 | } 51 | } 52 | 53 | module.exports = Analyser; 54 | -------------------------------------------------------------------------------- /src/Analyser/Header/Baidu.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | /** 3 | * Class for baidu detection 4 | */ 5 | class Baidu { 6 | constructor(header, data = { browser: {} }) { 7 | this.data = data; 8 | if (!this.data.browser.name || this.data.browser.name !== 'Baidu Browser') { 9 | this.data.browser.name = 'Baidu Browser'; 10 | this.data.browser.version = null; 11 | this.data.browser.stock = false; 12 | } 13 | } 14 | } 15 | 16 | module.exports = Baidu; 17 | -------------------------------------------------------------------------------- /src/Analyser/Header/BrowserId.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Using = require('../../model/Using'); 4 | const Version = require('../../model/Version'); 5 | const Constants = require('../../constants'); 6 | const BrowserIds = require('../../data/BrowserIds'); 7 | 8 | class BrowserId { 9 | constructor(header, data = { browser: {} }) { 10 | if (header === 'XMLHttpRequest') { 11 | return; 12 | } 13 | 14 | this.data = data; 15 | 16 | /* The X-Requested-With header is send by the WebView, so our browser name is Chrome it is probably the Chromium WebView which is sometimes misidentified. */ 17 | 18 | if (this.data.browser.name && this.data.browser.name === 'Chrome') { 19 | const version = this.data.browser.getVersion(); 20 | 21 | this.data.browser.reset(); 22 | this.data.browser.using = new Using({ 23 | name: 'Chromium WebView', 24 | version: new Version({ value: version.split('.')[0] }), 25 | }); 26 | } 27 | 28 | /* Detect the correct browser based on the header */ 29 | 30 | const browser = BrowserIds.identify(header); 31 | if (browser) { 32 | if (!this.data.browser.name) { 33 | this.data.browser.name = browser; 34 | } else { 35 | if (!this.data.browser.name.startsWith(browser)) { 36 | this.data.browser.name = browser; 37 | this.data.browser.version = null; 38 | this.data.browser.stock = false; 39 | } else { 40 | this.data.browser.name = browser; 41 | } 42 | } 43 | } 44 | 45 | /* The X-Requested-With header is only send from Android devices */ 46 | 47 | if ( 48 | !this.data.os.name || 49 | (this.data.os.name !== 'Android' && (!this.data.os.family || this.data.os.family.getName() !== 'Android')) 50 | ) { 51 | this.data.os.name = 'Android'; 52 | this.data.os.alias = null; 53 | this.data.os.version = null; 54 | 55 | this.data.device.manufacturer = null; 56 | this.data.device.model = null; 57 | this.data.device.identified = Constants.id.NONE; 58 | 59 | if ( 60 | this.data.device.type !== Constants.deviceType.MOBILE && 61 | this.data.device.type !== Constants.deviceType.TABLET 62 | ) { 63 | this.data.device.type = Constants.deviceType.MOBILE; 64 | } 65 | } 66 | 67 | /* The X-Requested-With header is send by the WebKit or Chromium Webview */ 68 | 69 | if (!this.data.engine.name || (this.data.engine.name !== 'Webkit' && this.data.engine.name !== 'Blink')) { 70 | this.data.engine.name = 'Webkit'; 71 | this.data.engine.version = null; 72 | } 73 | } 74 | } 75 | 76 | module.exports = BrowserId; 77 | -------------------------------------------------------------------------------- /src/Analyser/Header/OperaMini.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../constants'); 4 | const DeviceModels = require('../../data/DeviceModels'); 5 | 6 | class OperaMini { 7 | constructor(header, data) { 8 | this.data = data; 9 | const [manufacturer = '', model = ''] = header.split(' # '); 10 | if (manufacturer !== '?' && model !== '?') { 11 | if (this.data.device.identified < Constants.id.PATTERN) { 12 | if (this.identifyBasedOnModel(model)) { 13 | return; 14 | } 15 | this.data.device.manufacturer = manufacturer; 16 | this.data.device.model = model; 17 | this.data.device.identified = true; 18 | } 19 | } 20 | } 21 | 22 | identifyBasedOnModel(model) { 23 | let device = DeviceModels.identify('bada', model); 24 | if (device.identified) { 25 | device.identified |= this.data.device.identified; 26 | this.data.device = device; 27 | if (!this.data.os.name || this.data.os.name !== 'Bada') { 28 | this.data.os.name = 'Bada'; 29 | this.data.os.version = null; 30 | } 31 | return true; 32 | } 33 | device = DeviceModels.identify('blackberry', model); 34 | if (device.identified) { 35 | device.identified |= this.data.device.identified; 36 | this.data.device = device; 37 | if (!this.data.os.name || this.data.os.name !== 'BlackBerry OS') { 38 | this.data.os.name = 'BlackBerry OS'; 39 | this.data.os.version = null; 40 | } 41 | return true; 42 | } 43 | device = DeviceModels.identify('wm', model); 44 | if (device.identified) { 45 | device.identified |= this.data.device.identified; 46 | this.data.device = device; 47 | if (!this.data.os.name || this.data.os.name !== 'Windows Mobile') { 48 | this.data.os.name = 'Windows Mobile'; 49 | this.data.os.version = null; 50 | } 51 | return true; 52 | } 53 | } 54 | } 55 | 56 | module.exports = OperaMini; 57 | -------------------------------------------------------------------------------- /src/Analyser/Header/Puffin.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const DeviceModels = require('../../data/DeviceModels'); 4 | 5 | class Puffin { 6 | constructor(header, data) { 7 | this.data = data; 8 | const parts = header.split('/'); 9 | if (this.data.browser.name !== 'Puffin') { 10 | this.data.browser.name = 'Puffin'; 11 | this.data.browser.version = null; 12 | this.data.browser.stock = false; 13 | } 14 | this.data.device.type = 'mobile'; 15 | let device; 16 | if (parts.length > 1 && parts[0] === 'Android') { 17 | if (!this.data.os.name || this.data.os.name !== 'Android') { 18 | this.data.os.name = 'Android'; 19 | this.data.os.version = null; 20 | } 21 | device = DeviceModels.identify('android', parts[1]); 22 | if (device.identified) { 23 | device.identified |= this.data.device.identified; 24 | this.data.device = device; 25 | } 26 | } 27 | if (parts.length > 1 && parts[0] === 'iPhone OS') { 28 | if (!this.data.os.name || this.data.os.name !== 'iOS') { 29 | this.data.os.name = 'iOS'; 30 | this.data.os.version = null; 31 | } 32 | device = DeviceModels.identify('ios', parts[1]); 33 | if (device.identified) { 34 | device.identified |= this.data.device.identified; 35 | this.data.device = device; 36 | } 37 | } 38 | } 39 | } 40 | 41 | module.exports = Puffin; 42 | -------------------------------------------------------------------------------- /src/Analyser/Header/UCBrowserOld.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../constants'); 4 | 5 | class UCBrowserOld { 6 | constructor(header, data) { 7 | const Parser = require('../../Parser'); 8 | this.data = data; 9 | 10 | if (this.data.device.type === Constants.deviceType.DESKTOP) { 11 | this.data.device.type = Constants.deviceType.MOBILE; 12 | 13 | this.data.os.reset(); 14 | } 15 | 16 | if (!this.data.browser.name || this.data.browser.name !== 'UC Browser') { 17 | this.data.browser.name = 'UC Browser'; 18 | this.data.browser.version = null; 19 | } 20 | 21 | this.data.browser.mode = 'proxy'; 22 | this.data.engine.reset({ name: 'Gecko' }); 23 | 24 | const extra = new Parser({ headers: { 'User-Agent': header } }); 25 | 26 | if (extra.device.type !== Constants.deviceType.DESKTOP) { 27 | if (extra.os.getName() !== '' && (this.data.os.getName() === '' || extra.os.getVersion() !== '')) { 28 | this.data.os = extra.os; 29 | } 30 | if (extra.device.identified) { 31 | this.data.device = extra.device; 32 | } 33 | } 34 | } 35 | } 36 | 37 | module.exports = UCBrowserOld; 38 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const { Application, Bot, Browser, Device, Engine, Os, Using } = require('./Useragent/'); 4 | 5 | class Useragent { 6 | constructor(header, data, options) { 7 | this.data = data; 8 | this.options = options; 9 | /* Make sure we do not have a duplicate concatenated useragent string */ 10 | 11 | header = header.replace(/^(Mozilla\/[0-9]\.[0-9].{20,})\s+Mozilla\/[0-9]\.[0-9].*$/iu, '$1'); 12 | /* Detect the basic information */ 13 | Os.detectOperatingSystem.call(this, header); 14 | Device.detectDevice.call(this, header); 15 | Browser.detectBrowser.call(this, header); 16 | Application.detectApplication.call(this, header); 17 | Using.detectUsing.call(this, header); 18 | Engine.detectEngine.call(this, header); 19 | /* Detect bots */ 20 | if (typeof this.options.detectBots === 'undefined' || this.options.detectBots === true) { 21 | Bot.detectBot.call(this, header); 22 | } 23 | /* Refine some of the information */ 24 | Browser.refineBrowser.call(this, header); 25 | Os.refineOperatingSystem.call(this, header); 26 | } 27 | 28 | static removeKnownPrefixes(ua) { 29 | ua = ua.replace(/^OneBrowser\/[0-9.]+\//, ''); 30 | ua = ua.replace(/^MQQBrowser\/[0-9.]+\//, ''); 31 | return ua; 32 | } 33 | } 34 | 35 | module.exports = Useragent; 36 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Bot.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../constants'); 4 | const Applications = require('../../../data/Applications'); 5 | 6 | class Bot { 7 | static detectBot(ua) { 8 | /* Detect bots based on url in the UA string */ 9 | if (/\+https?:\/\//iu.test(ua)) { 10 | this.data.browser.reset(); 11 | this.data.os.reset(); 12 | this.data.engine.reset(); 13 | this.data.device.reset(); 14 | this.data.device.type = Constants.deviceType.BOT; 15 | } 16 | /* Detect bots based on common markers */ 17 | if (/(?:Bot|Robot|Spider|Crawler)([/);]|$)/iu.test(ua) && !/CUBOT/iu.test(ua)) { 18 | this.data.browser.reset(); 19 | this.data.os.reset(); 20 | this.data.engine.reset(); 21 | this.data.device.reset(); 22 | this.data.device.type = Constants.deviceType.BOT; 23 | } 24 | /* Detect based on a predefined list or markers */ 25 | const bot = Applications.identifyBot(ua); 26 | if (bot) { 27 | this.data.browser = bot; 28 | this.data.os.reset(); 29 | this.data.engine.reset(); 30 | this.data.device.reset(); 31 | this.data.device.type = Constants.deviceType.BOT; 32 | } 33 | return this; 34 | } 35 | } 36 | 37 | module.exports = Bot; 38 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const { 4 | Appliance, 5 | Cars, 6 | Ereader, 7 | Gaming, 8 | Gps, 9 | Media, 10 | Mobile, 11 | Pda, 12 | Phone, 13 | Printer, 14 | Signage, 15 | Tablet, 16 | Television, 17 | } = require('./Device/'); 18 | 19 | class Device { 20 | static detectDevice(ua) { 21 | Appliance.detectAppliance.call(this, ua); 22 | Cars.detectCars.call(this, ua); 23 | Gps.detectGps.call(this, ua); 24 | Ereader.detectEreader.call(this, ua); 25 | Gaming.detectGaming.call(this, ua); 26 | Television.detectTelevision.call(this, ua); 27 | Signage.detectSignage.call(this, ua); 28 | Media.detectMedia.call(this, ua); 29 | Pda.detectPda.call(this, ua); 30 | Printer.detectPrinter.call(this, ua); 31 | Tablet.detectTablet.call(this, ua); 32 | Phone.detectPhone.call(this, ua); 33 | Mobile.detectMobile.call(this, ua); 34 | return this; 35 | } 36 | } 37 | 38 | module.exports = Device; 39 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Appliance.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Appliance { 6 | static detectAppliance(ua) { 7 | Appliance.detectIOpener.call(this, ua); 8 | Appliance.detectWebLight.call(this, ua); 9 | } 10 | 11 | /* Netpliance i-Opener */ 12 | static detectIOpener(ua) { 13 | if (/I-Opener [0-9.]+; Netpliance/u.test(ua)) { 14 | this.data.os.reset(); 15 | this.data.device.setIdentification({ 16 | manufacturer: 'Netpliance', 17 | model: 'i-Opener', 18 | type: Constants.deviceType.DESKTOP, 19 | }); 20 | } 21 | } 22 | 23 | /* KOMATSU WebLight */ 24 | static detectWebLight(ua) { 25 | if (/KOMATSU.*WL\//u.test(ua)) { 26 | this.data.os.reset(); 27 | this.data.device.setIdentification({ 28 | manufacturer: 'KOMATSU', 29 | model: 'WebLight', 30 | type: Constants.deviceType.DESKTOP, 31 | }); 32 | } 33 | } 34 | } 35 | 36 | module.exports = Appliance; 37 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Cars.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Cars { 6 | static detectCars(ua) { 7 | if (!/Car/iu.test(ua)) { 8 | return; 9 | } 10 | Cars.detectTesla.call(this, ua); 11 | } 12 | 13 | /* Tesla S */ 14 | static detectTesla(ua) { 15 | if (/QtCarBrowser/u.test(ua)) { 16 | this.data.os.reset(); 17 | this.data.device.setIdentification({ 18 | manufacturer: 'Tesla', 19 | model: 'Model S', 20 | type: Constants.deviceType.CAR, 21 | }); 22 | } 23 | } 24 | } 25 | 26 | module.exports = Cars; 27 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Gps.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Gps { 6 | static detectGps(ua) { 7 | if (!/Nuvi/iu.test(ua)) { 8 | return; 9 | } 10 | 11 | Gps.detectGarmin.call(this, ua); 12 | } 13 | 14 | /* Garmin Nuvi */ 15 | static detectGarmin(ua) { 16 | if (/Nuvi/u.test(ua) && /Qtopia/u.test(ua)) { 17 | this.data.device.setIdentification({ 18 | manufacturer: 'Garmin', 19 | model: 'Nuvi', 20 | type: Constants.deviceType.GPS, 21 | }); 22 | } 23 | } 24 | } 25 | 26 | module.exports = Gps; 27 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Phone.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Phone { 6 | static detectPhone(ua) { 7 | Phone.detectNttTeless.call(this, ua); 8 | Phone.detectSnom.call(this, ua); 9 | } 10 | 11 | /* NTT Teless */ 12 | static detectNttTeless(ua) { 13 | if (/Product=NTT\/Teless/iu.test(ua)) { 14 | this.data.device.manufacturer = 'NTT'; 15 | this.data.device.model = 'Teless'; 16 | this.data.device.identified |= Constants.id.MATCH_UA; 17 | this.data.device.type = Constants.deviceType.MOBILE; 18 | this.data.device.subtype = Constants.deviceSubType.DESKTOP; 19 | } 20 | } 21 | 22 | /* SNOM */ 23 | static detectSnom(ua) { 24 | let match; 25 | if ((match = /snom(.+)-SIP/iu.exec(ua))) { 26 | this.data.device.manufacturer = 'SNOM'; 27 | this.data.device.model = match[1] + ' IP Telephone'; 28 | this.data.device.identified |= Constants.id.MATCH_UA; 29 | this.data.device.type = Constants.deviceType.MOBILE; 30 | this.data.device.subtype = Constants.deviceSubType.DESKTOP; 31 | } 32 | } 33 | } 34 | 35 | module.exports = Phone; 36 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Printer.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Printer { 6 | static detectPrinter(ua) { 7 | if (!/(TASKalfa|CanonIJCL|IR-S|PrintSmart|EpsonHello)/iu.test(ua)) { 8 | return; 9 | } 10 | let match; 11 | /* TASKalfa */ 12 | if ((match = /TASKalfa ([0-9A-Z]+)/iu.exec(ua))) { 13 | this.data.device.setIdentification({ 14 | manufacturer: 'Kyocera', 15 | model: `TASKalfa ${match[1]}`, 16 | type: Constants.deviceType.PRINTER, 17 | }); 18 | } 19 | /* Canon IJ */ 20 | if (/CanonIJCL/iu.test(ua)) { 21 | this.data.device.setIdentification({ 22 | manufacturer: 'Canon', 23 | model: 'IJ Printer', 24 | type: Constants.deviceType.PRINTER, 25 | }); 26 | } 27 | /* Canon iR S */ 28 | if (/IR-S/iu.test(ua)) { 29 | this.data.device.setIdentification({ 30 | manufacturer: 'Canon', 31 | model: 'imageRUNNER', 32 | type: Constants.deviceType.PRINTER, 33 | }); 34 | } 35 | /* HP Web PrintSmart */ 36 | if (/HP Web PrintSmart/iu.test(ua)) { 37 | this.data.device.setIdentification({ 38 | manufacturer: 'HP', 39 | model: 'Web PrintSmart', 40 | type: Constants.deviceType.PRINTER, 41 | }); 42 | } 43 | /* Epson Hello */ 44 | if (/EpsonHello\//iu.test(ua)) { 45 | this.data.device.setIdentification({ 46 | manufacturer: 'Epson', 47 | model: 'Hello', 48 | type: Constants.deviceType.PRINTER, 49 | }); 50 | } 51 | } 52 | } 53 | 54 | module.exports = Printer; 55 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Signage.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Signage { 6 | static detectSignage(ua) { 7 | let match; 8 | if (!/(BrightSign|ADAPI)/iu.test(ua)) { 9 | return; 10 | } 11 | /* BrightSign */ 12 | if ((match = /BrightSign\/[0-9.]+(?:-[a-z0-9-]+)? \(([^)]+)/u.exec(ua))) { 13 | this.data.os.reset(); 14 | this.data.device.setIdentification({ 15 | manufacturer: 'BrightSign', 16 | model: match[1], 17 | type: Constants.deviceType.SIGNAGE, 18 | }); 19 | } 20 | /* Iadea */ 21 | if (/ADAPI/u.test(ua) && (match = /\(MODEL:([^)]+)\)/u.exec(ua))) { 22 | if (!this.data.isOs('Android')) { 23 | this.data.os.reset(); 24 | } 25 | this.data.device.setIdentification({ 26 | manufacturer: 'IAdea', 27 | model: match[1], 28 | type: Constants.deviceType.SIGNAGE, 29 | }); 30 | } 31 | } 32 | } 33 | 34 | module.exports = Signage; 35 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/Tablet.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../../../constants'); 4 | 5 | class Tablet { 6 | static detectTablet(ua) { 7 | Tablet.detectWebTab.call(this, ua); 8 | } 9 | 10 | /* WeTab */ 11 | static detectWebTab(ua) { 12 | if (/WeTab-Browser /iu.test(ua)) { 13 | this.data.device.manufacturer = 'WeTab'; 14 | this.data.device.model = 'WeTab'; 15 | this.data.device.identified |= Constants.id.MATCH_UA; 16 | this.data.device.type = Constants.deviceType.TABLET; 17 | this.data.browser.name = 'WebTab Browser'; 18 | this.data.browser.version = null; 19 | this.data.os.name = 'MeeGo'; 20 | this.data.os.version = null; 21 | } 22 | } 23 | } 24 | 25 | module.exports = Tablet; 26 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Device/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Appliance: require('./Appliance'), 3 | Cars: require('./Cars'), 4 | Ereader: require('./Ereader'), 5 | Gaming: require('./Gaming'), 6 | Gps: require('./Gps'), 7 | Media: require('./Media'), 8 | Mobile: require('./Mobile'), 9 | Pda: require('./Pda'), 10 | Phone: require('./Phone'), 11 | Printer: require('./Printer'), 12 | Signage: require('./Signage'), 13 | Tablet: require('./Tablet'), 14 | Television: require('./Television'), 15 | }; 16 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/Using.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Version = require('../../../model/Version'); 4 | const UsingClass = require('../../../model/Using'); 5 | 6 | class Using { 7 | static detectUsing(ua) { 8 | if ( 9 | !/(AdobeAIR|Awesomium|Embedded|bsalsa|Canvace|Ekioh|AtomShell|Electron|JavaFX|GFXe|luakit|Titanium|OpenWebKitSharp|Prism|Qt|Reqwireless|RhoSimulator|UWebKit|nw-tests|WebKit2)/iu.test( 10 | ua 11 | ) 12 | ) { 13 | return this; 14 | } 15 | const items = [ 16 | { name: 'AdobeAIR', regexp: /AdobeAIR\/([0-9.]*)/u }, 17 | { name: 'Awesomium', regexp: /Awesomium\/([0-9.]*)/u }, 18 | { name: 'Delphi Embedded Web Browser', regexp: /EmbeddedWB ([0-9.]*)/u }, 19 | { name: 'Delphi Embedded Web Browser', regexp: /bsalsa\.com/u }, 20 | { name: 'Delphi Embedded Web Browser', regexp: /Embedded Web Browser/u }, 21 | { name: 'Canvace', regexp: /Canvace Standalone\/([0-9.]*)/u }, 22 | { name: 'Ekioh', regexp: /Ekioh\/([0-9.]*)/u }, 23 | { name: 'Electron', regexp: /AtomShell\/([0-9.]*)/u }, 24 | { name: 'Electron', regexp: /Electron\/([0-9.]*)/u }, 25 | { name: 'JavaFX', regexp: /JavaFX\/([0-9.]*)/u }, 26 | { name: 'GFXe', regexp: /GFXe\/([0-9.]*)/u }, 27 | { name: 'LuaKit', regexp: /luakit/u }, 28 | { name: 'Titanium', regexp: /Titanium\/([0-9.]*)/u }, 29 | { name: 'OpenWebKitSharp', regexp: /OpenWebKitSharp/u }, 30 | { name: 'Prism', regexp: /Prism\/([0-9.]*)/u }, 31 | { name: 'Qt', regexp: /Qt\/([0-9.]*)/u }, 32 | { name: 'Qt', regexp: /QtWebEngine\/([4-9][0-9.]*)?/u }, 33 | { name: 'Qt', regexp: /QtEmbedded/u }, 34 | { name: 'Qt', regexp: /QtEmbedded.*Qt\/([0-9.]*)/u }, 35 | { name: 'ReqwirelessWeb', regexp: /ReqwirelessWeb\/([0-9.]*)/u }, 36 | { name: 'RhoSimulator', regexp: /RhoSimulator/u }, 37 | { name: 'UWebKit', regexp: /UWebKit\/([0-9.]*)/u }, 38 | { name: 'Node-WebKit', regexp: /nw-tests\/([0-9.]*)/u }, 39 | { name: 'WebKit2.NET', regexp: /WebKit2.NET/u }, 40 | ]; 41 | const count = items.length; 42 | for (let i = 0; i < count; i++) { 43 | let match; 44 | if ((match = items[i]['regexp'].exec(ua))) { 45 | this.data.browser.using = new UsingClass({ 46 | name: items[i]['name'], 47 | }); 48 | if (match[1]) { 49 | this.data.browser.using.version = new Version({ 50 | value: match[1], 51 | details: items[i]['details'] ? items[i]['details'] : null, 52 | }); 53 | } 54 | break; 55 | } 56 | } 57 | return this; 58 | } 59 | } 60 | 61 | module.exports = Using; 62 | -------------------------------------------------------------------------------- /src/Analyser/Header/Useragent/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Application: require('./Application'), 3 | Bot: require('./Bot'), 4 | Browser: require('./Browser'), 5 | Device: require('./Device'), 6 | Engine: require('./Engine'), 7 | Os: require('./Os'), 8 | Using: require('./Using'), 9 | }; 10 | -------------------------------------------------------------------------------- /src/Analyser/Header/Wap.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const Constants = require('../../constants'); 4 | const DeviceProfiles = require('../../data/DeviceProfiles'); 5 | 6 | class Wap { 7 | constructor(header, data) { 8 | this.data = data; 9 | header = header.trim(); 10 | if (header.startsWith('"')) { 11 | header = header.split(','); 12 | header = header[0].replace(/^"+/, '').replace(/"+$/, ''); 13 | } 14 | const result = DeviceProfiles.identify(header); 15 | if (result) { 16 | this.data.device.manufacturer = result[0]; 17 | this.data.device.model = result[1]; 18 | this.data.device.identified |= Constants.id.MATCH_PROF; 19 | if (result[2] && (!this.data.os.name || this.data.os.name !== result[2])) { 20 | this.data.os.name = result[2]; 21 | this.data.os.version = null; 22 | this.data.engine.name = null; 23 | this.data.engine.version = null; 24 | } 25 | if (result[3]) { 26 | this.data.device.type = result[3]; 27 | } 28 | } 29 | } 30 | } 31 | 32 | module.exports = Wap; 33 | -------------------------------------------------------------------------------- /src/Analyser/Header/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Baidu: require('./Baidu'), 3 | BrowserId: require('./BrowserId'), 4 | OperaMini: require('./OperaMini'), 5 | Puffin: require('./Puffin'), 6 | UCBrowserNew: require('./UCBrowserNew'), 7 | UCBrowserOld: require('./UCBrowserOld'), 8 | Useragent: require('./Useragent'), 9 | Wap: require('./Wap'), 10 | }; 11 | -------------------------------------------------------------------------------- /src/Analyser/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Camouflage: require('./Camouflage'), 3 | Corrections: require('./Corrections'), 4 | Derive: require('./Derive'), 5 | Header: require('./Header'), 6 | }; 7 | -------------------------------------------------------------------------------- /src/Parser.js: -------------------------------------------------------------------------------- 1 | const Main = require('./model/Main'); 2 | const Analyser = require('./Analyser'); 3 | const Cache = require('./Cache'); 4 | 5 | /** 6 | * Class that parse the user-agent 7 | */ 8 | class Parser extends Main { 9 | /** 10 | * Create a new object that contains all the detected information 11 | * 12 | * @param {object|string} headers Optional, an object with all of the headers or a string with just the User-Agent header 13 | * @param {object} options Optional, an object with configuration options 14 | * @param {int} [options.cacheExpires=900] Expiry time in seconds 15 | * @param {int} [options.cacheCheckInterval=1/5 * options.cacheExpires] Time in seconds between each cache check to remove expired records. Minimum 1 16 | */ 17 | constructor(headers = null, options = {}) { 18 | super(); 19 | 20 | if (headers) { 21 | this.analyse(headers, options); 22 | } 23 | } 24 | 25 | /** 26 | * Analyse the provided headers or User-Agent string 27 | * 28 | * @param {object|string} headers An object with all of the headers or a string with just the User-Agent header 29 | * @param {object} options Optional, an object with configuration options 30 | */ 31 | analyse(headers, options = {}) { 32 | let o = options; 33 | let h; 34 | if (typeof headers === 'string') { 35 | h = { 'User-Agent': headers }; 36 | } else if (headers['headers']) { 37 | h = headers['headers']; 38 | 39 | headers['headers'] = null; 40 | o = Object.assign({}, headers, options); 41 | } else { 42 | h = headers; 43 | } 44 | let data; 45 | if ((data = Cache.analyseWithCache(h, o, this))) { 46 | if (typeof data === 'object') { 47 | Object.assign(this, data); 48 | this.cached = true; 49 | } 50 | return; 51 | } 52 | 53 | const analyser = new Analyser(h, o); 54 | analyser.setData(this); 55 | analyser.analyse(); 56 | } 57 | } 58 | Parser.SIMPLE_CACHE = 'simple'; 59 | module.exports = Parser; 60 | -------------------------------------------------------------------------------- /src/constants/browserType.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | UNKNOWN: 'unknown', 3 | BROWSER: 'browser', 4 | BROWSER_TEXT: 'browser:text', 5 | APP: 'app', 6 | APP_EMAIL: 'app:email', 7 | APP_GAME: 'app:game', 8 | APP_MEDIAPLAYER: 'app:mediaplayer', 9 | APP_FEEDREADER: 'app:feedreader', 10 | APP_PODCAST: 'app:podcast', 11 | APP_SOCIAL: 'app:social', 12 | APP_OFFICE: 'app:office', 13 | APP_EDITOR: 'app:editor', 14 | APP_DOWNLOAD: 'app:download', 15 | APP_SEARCH: 'app:search', 16 | APP_NEWS: 'app:news', 17 | APP_ANTIVIRUS: 'app:antivirus', 18 | APP_SHOPPING: 'app:shopping', 19 | APP_CHAT: 'app:chat', 20 | }; 21 | -------------------------------------------------------------------------------- /src/constants/deviceSubType.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | FEATURE: 'feature', 3 | SMART: 'smart', 4 | DESKTOP: 'desktop', 5 | CONSOLE: 'console', 6 | PORTABLE: 'portable', 7 | }; 8 | -------------------------------------------------------------------------------- /src/constants/deviceType.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | DESKTOP: 'desktop', 3 | MOBILE: 'mobile', 4 | PDA: 'pda', 5 | DECT: 'dect', 6 | TABLET: 'tablet', 7 | GAMING: 'gaming', 8 | EREADER: 'ereader', 9 | MEDIA: 'media', 10 | HEADSET: 'headset', 11 | WATCH: 'watch', 12 | EMULATOR: 'emulator', 13 | TELEVISION: 'television', 14 | MONITOR: 'monitor', 15 | CAMERA: 'camera', 16 | PRINTER: 'printer', 17 | SIGNAGE: 'signage', 18 | WHITEBOARD: 'whiteboard', 19 | DEVBOARD: 'devboard', 20 | INFLIGHT: 'inflight', 21 | APPLIANCE: 'appliance', 22 | GPS: 'gps', 23 | CAR: 'car', 24 | POS: 'pos', 25 | BOT: 'bot', 26 | PROJECTOR: 'projector', 27 | }; 28 | -------------------------------------------------------------------------------- /src/constants/engineType.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | TRIDENT: 1, 3 | PRESTO: 2, 4 | CHROMIUM: 4, 5 | GECKO: 8, 6 | WEBKIT: 16, 7 | V8: 32, 8 | }; 9 | -------------------------------------------------------------------------------- /src/constants/feature.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | SANDBOX: 1, 3 | WEBSOCKET: 2, 4 | WORKER: 4, 5 | APPCACHE: 8, 6 | HISTORY: 16, 7 | FULLSCREEN: 32, 8 | FILEREADER: 64, 9 | }; 10 | -------------------------------------------------------------------------------- /src/constants/flag.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | GOOGLETV: 1, 3 | GOOGLEGLASS: 2, 4 | ANDROIDWEAR: 4, 5 | ANDROIDTV: 8, 6 | NOKIAX: 16, 7 | FIREOS: 32, 8 | UIQ: 64, 9 | S60: 128, 10 | MOAPS: 256, 11 | }; 12 | -------------------------------------------------------------------------------- /src/constants/id.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NONE: 0, 3 | INFER: 1, 4 | PATTERN: 2, 5 | MATCH_UA: 4, 6 | MATCH_PROF: 8, 7 | }; 8 | -------------------------------------------------------------------------------- /src/constants/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | browserType: require('./browserType'), 3 | deviceSubType: require('./deviceSubType'), 4 | deviceType: require('./deviceType'), 5 | engineType: require('./engineType'), 6 | feature: require('./feature'), 7 | flag: require('./flag'), 8 | id: require('./id'), 9 | }; 10 | -------------------------------------------------------------------------------- /src/data/BrowserIds.js: -------------------------------------------------------------------------------- 1 | /** 2 | * BrowserIds utility 3 | * 4 | * @internal 5 | */ 6 | class BrowserIds { 7 | /** 8 | * 9 | * @param {string} model 10 | * 11 | * @return {string|undefined} 12 | */ 13 | static identify(model) { 14 | return BrowserIds.ANDROID_BROWSERS[model]; 15 | } 16 | } 17 | BrowserIds.ANDROID_BROWSERS = require('../../data/id-android').ANDROID_BROWSERS; 18 | 19 | module.exports = BrowserIds; 20 | -------------------------------------------------------------------------------- /src/data/BuildIds.js: -------------------------------------------------------------------------------- 1 | const Version = require('../model/Version'); 2 | /** 3 | * BuildIds utility 4 | * 5 | * @internal 6 | */ 7 | class BuildIds { 8 | /** 9 | * 10 | * @param {string} id 11 | * 12 | * @return {Version|undefined} 13 | */ 14 | static identify(id) { 15 | const build = BuildIds.ANDROID_BUILDS[id]; 16 | if (build) { 17 | if (typeof build === 'object') { 18 | return new Version(build); 19 | } else { 20 | return new Version({ value: build }); 21 | } 22 | } 23 | } 24 | } 25 | BuildIds.ANDROID_BUILDS = require('../../data/build-android').ANDROID_BUILDS; 26 | 27 | module.exports = BuildIds; 28 | -------------------------------------------------------------------------------- /src/data/CFNetwork.js: -------------------------------------------------------------------------------- 1 | const CFNetworks = require('../../data/os-cfnetwork'); 2 | /** 3 | * CFNetwork utility 4 | * 5 | * @internal 6 | */ 7 | class CFNetwork { 8 | /** 9 | * 10 | * @param {string} platform 11 | * @param {string} version 12 | * 13 | * @return {object} 14 | */ 15 | static getVersion(platform, version) { 16 | switch (platform) { 17 | case 'osx': 18 | return CFNetwork.OSK[version]; 19 | case 'ios': 20 | return CFNetwork.IOS[version]; 21 | } 22 | } 23 | } 24 | CFNetwork.OSK = CFNetworks.CFNetwork.OSX; 25 | CFNetwork.IOS = CFNetworks.CFNetwork.IOS; 26 | 27 | module.exports = CFNetwork; 28 | -------------------------------------------------------------------------------- /src/data/Chrome.js: -------------------------------------------------------------------------------- 1 | const chromeVersions = require('../../data/browsers-chrome.js'); 2 | /** 3 | * Chrome utility 4 | * 5 | * @internal 6 | */ 7 | class Chrome { 8 | /** 9 | * 10 | * @param {string} platform 11 | * @param {string} version 12 | * 13 | * @return {string} 14 | */ 15 | static getChannel(platform, version) { 16 | version = version.split('.').slice(0, 3).join('.'); 17 | 18 | switch (platform) { 19 | case 'desktop': 20 | return Chrome.DESKTOP[version]; 21 | case 'mobile': 22 | return Chrome.MOBILE[version]; 23 | } 24 | 25 | // return 'canary'; 26 | } 27 | } 28 | Chrome.DESKTOP = chromeVersions.DESKTOP; 29 | Chrome.MOBILE = chromeVersions.MOBILE; 30 | 31 | module.exports = Chrome; 32 | -------------------------------------------------------------------------------- /src/data/Darwin.js: -------------------------------------------------------------------------------- 1 | const Darwins = require('../../data/os-darwin'); 2 | /** 3 | * Darwin utility 4 | * 5 | * @internal 6 | */ 7 | class Darwin { 8 | /** 9 | * 10 | * @param {string} platform 11 | * @param {string} version 12 | * 13 | * @return {object} 14 | */ 15 | static getVersion(platform, version) { 16 | version = version.split('.').slice(0, 3).join('.'); 17 | 18 | switch (platform) { 19 | case 'osx': 20 | return Darwin.OSK[version]; 21 | case 'ios': 22 | return Darwin.IOS[version]; 23 | } 24 | } 25 | } 26 | Darwin.OSK = Darwins.DARWIN.OSX; 27 | Darwin.IOS = Darwins.DARWIN.IOS; 28 | 29 | module.exports = Darwin; 30 | -------------------------------------------------------------------------------- /src/data/DeviceProfiles.js: -------------------------------------------------------------------------------- 1 | /** 2 | * DeviceProfiles utility 3 | * 4 | * @internal 5 | */ 6 | class DeviceProfiles { 7 | /** 8 | * 9 | * @param {url} url 10 | * 11 | * @return {string|undefined} 12 | */ 13 | static identify(url) { 14 | return DeviceProfiles.PROFILES[url] || false; 15 | } 16 | } 17 | DeviceProfiles.PROFILES = require('../../data/profiles').PROFILES; 18 | 19 | module.exports = DeviceProfiles; 20 | -------------------------------------------------------------------------------- /src/data/Manufacturers.js: -------------------------------------------------------------------------------- 1 | const Constants = require('../constants'); 2 | const { 3 | MANUFACTURERS: { TELEVISION, GENERIC }, 4 | } = require('../../data/manufacturer-names'); 5 | /** 6 | * Manufacturers utility 7 | * 8 | * @internal 9 | */ 10 | class Manufacturers { 11 | /** 12 | * 13 | * @param {string} type 14 | * @param {string} name 15 | * 16 | * @return {string} 17 | */ 18 | static identify(type, name) { 19 | name = name.trim().replace(/^CUS:/u, ''); 20 | 21 | if (type === Constants.deviceType.TELEVISION) { 22 | if (Manufacturers.TELEVISION[name]) { 23 | return Manufacturers.TELEVISION[name]; 24 | } 25 | } 26 | if (Manufacturers.GENERIC[name]) { 27 | return Manufacturers.GENERIC[name]; 28 | } 29 | 30 | return name; 31 | } 32 | } 33 | 34 | Manufacturers.TELEVISION = TELEVISION; 35 | Manufacturers.GENERIC = GENERIC; 36 | 37 | module.exports = Manufacturers; 38 | -------------------------------------------------------------------------------- /src/model/Engine.js: -------------------------------------------------------------------------------- 1 | const NameVersion = require('./primitive/NameVersion'); 2 | /** 3 | * @internal 4 | */ 5 | class Engine extends NameVersion { 6 | /** 7 | * Get an object with all defined properties 8 | * 9 | * @internal 10 | * 11 | * @return {object|string} 12 | */ 13 | toObject() { 14 | const result = {}; 15 | 16 | if (this.name) { 17 | result.name = this.name; 18 | } 19 | 20 | let versionObj; 21 | if (this.version && Object.keys((versionObj = this.version.toObject())).length) { 22 | result.version = versionObj; 23 | } 24 | 25 | return result; 26 | } 27 | } 28 | 29 | module.exports = Engine; 30 | -------------------------------------------------------------------------------- /src/model/Family.js: -------------------------------------------------------------------------------- 1 | const NameVersion = require('./primitive/NameVersion'); 2 | /** 3 | * @internal 4 | */ 5 | class Family extends NameVersion { 6 | /** 7 | * Get an object with all defined properties 8 | * 9 | * @internal 10 | * 11 | * @return {object|string} 12 | */ 13 | toObject() { 14 | const result = {}; 15 | if (this.name && !this.version) { 16 | return this.name; 17 | } 18 | 19 | if (this.name) { 20 | result.name = this.name; 21 | } 22 | 23 | if (this.version) { 24 | result.version = this.version.toObject(); 25 | if (typeof result.version === 'string' && !result.version.includes('.')) { 26 | result.version = Number(result.version); 27 | } 28 | } 29 | 30 | return result; 31 | } 32 | } 33 | 34 | module.exports = Family; 35 | -------------------------------------------------------------------------------- /src/model/Using.js: -------------------------------------------------------------------------------- 1 | const NameVersion = require('./primitive/NameVersion'); 2 | /** 3 | * @internal 4 | */ 5 | class Using extends NameVersion { 6 | /** 7 | * Get an object with all defined properties 8 | * 9 | * @internal 10 | * 11 | * @return {object|string} 12 | */ 13 | toObject() { 14 | const result = {}; 15 | if (this.name && !this.version) { 16 | return this.name; 17 | } 18 | 19 | if (this.name) { 20 | result.name = this.name; 21 | } 22 | 23 | if (this.version) { 24 | result.version = this.version.toObject(); 25 | } 26 | 27 | return result; 28 | } 29 | } 30 | module.exports = Using; 31 | -------------------------------------------------------------------------------- /src/model/primitive/Base.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @internal 3 | */ 4 | class Base { 5 | /** 6 | * Set the properties of the object the the values specified in the object 7 | * 8 | * @param {Object|null} defaults An Object, the key of an element determines the name of the property 9 | */ 10 | constructor(defaults) { 11 | defaults && this.set(defaults); 12 | } 13 | 14 | /** 15 | * Set the properties of the object the the values specified in the object 16 | * 17 | * @param {Object} properties An Object, the key of an element determines the name of the property 18 | * 19 | * @internal 20 | */ 21 | set(properties) { 22 | Object.assign(this, properties); 23 | } 24 | } 25 | module.exports = Base; 26 | -------------------------------------------------------------------------------- /src/model/primitive/NameVersion.js: -------------------------------------------------------------------------------- 1 | const Base = require('./Base'); 2 | const Version = require('../Version'); 3 | /** 4 | * Class representing a NameVersion. 5 | * @extends Base 6 | */ 7 | class NameVersion extends Base { 8 | /** 9 | * Set the properties to the default values 10 | * 11 | * @param {Object|null} properties An optional object of properties to set after setting it to the default values 12 | * 13 | * @internal 14 | */ 15 | reset(properties = null) { 16 | this.name = null; 17 | this.alias = null; 18 | this.version = null; 19 | properties && this.set(properties); 20 | } 21 | 22 | /** 23 | * Identify the version based on a pattern 24 | * 25 | * @param {RegExp} pattern The regular expression that defines the group that matches the version string 26 | * @param {string} subject The string the regular expression is matched with 27 | * @param {Object|null} defaults An optional array of properties to set together with the value 28 | * 29 | */ 30 | identifyVersion(pattern, subject, defaults = {}) { 31 | let match; 32 | let version; 33 | if ((match = pattern.exec(subject)) !== null) { 34 | version = match[1]; 35 | 36 | if (defaults.type) { 37 | switch (defaults.type) { 38 | case 'underscore': 39 | version = version.replace(/_/g, '.'); 40 | break; 41 | case 'legacy': 42 | version = version.replace(/([0-9])([0-9])/, '$1.$2'); 43 | break; 44 | } 45 | } 46 | 47 | this.version = new Version(Object.assign({}, defaults, { value: version })); 48 | } 49 | } 50 | 51 | /** 52 | * Get the name in a human readable format 53 | * 54 | * @return {string} 55 | */ 56 | getName() { 57 | return this.alias || this.name || ''; 58 | } 59 | 60 | /** 61 | * Get the version in a human readable format 62 | * 63 | * @return {string} 64 | */ 65 | getVersion() { 66 | return this.version ? this.version.toString() : ''; 67 | } 68 | 69 | /** 70 | * Is a name detected? 71 | * 72 | * @return {boolean} 73 | */ 74 | isDetected() { 75 | return !!this.name; 76 | } 77 | 78 | /** 79 | * Get the name and version in a human readable format 80 | * 81 | * @return {string} 82 | */ 83 | toString() { 84 | return `${this.getName()} ${this.version && !this.version.hidden ? this.getVersion() : ''}`.trim(); 85 | } 86 | } 87 | 88 | module.exports = NameVersion; 89 | -------------------------------------------------------------------------------- /test/data/appliance/amstrad.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: MobileExplorer/3.00 (Mozilla/1.22; compatible; MMEF300; Amstrad; Gamma)' 3 | readable: 'Microsoft Mobile Explorer 3.0 on an Amstrad E-m@iler Plus' 4 | result: { browser: { name: 'Microsoft Mobile Explorer', version: '3.0', type: browser }, device: { type: desktop, manufacturer: Amstrad, model: 'E-m@iler Plus' } } 5 | -------------------------------------------------------------------------------- /test/data/appliance/familyhub.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Tizen 2.3; FamilyHub) AppleWebKit/537.3 (KHTML, like Gecko) Version/2.3 Mobile Safari/537.3' 3 | readable: 'Samsung Browser on a Samsung Family Hub running Tizen 2.3' 4 | result: { browser: { name: 'Samsung Browser' }, engine: { name: Webkit, version: '537.3' }, os: { name: Tizen, version: '2.3' }, device: { type: appliance, manufacturer: Samsung, model: 'Family Hub' } } 5 | -------------------------------------------------------------------------------- /test/data/appliance/i-opener.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.x (I-Opener 1.1; Netpliance)' 3 | readable: 'a Netpliance i-Opener' 4 | result: { device: { type: desktop, manufacturer: Netpliance, model: i-Opener } } 5 | -------------------------------------------------------------------------------- /test/data/appliance/weblight.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.0 KOMATSU (AveFront/2.6 WebLight) WL/3.0 V2.45ohi M=11E2A2499945' 3 | readable: 'NetFront 2.6 on a KOMATSU WebLight' 4 | result: { browser: { name: NetFront, version: '2.6', type: browser }, engine: { name: NetFront }, device: { type: desktop, manufacturer: KOMATSU, model: WebLight } } 5 | - 6 | headers: 'User-Agent: Mozilla/3.0 KOMATSU WL/3.0' 7 | readable: 'Netscape Navigator 3.0 on a KOMATSU WebLight' 8 | result: { browser: { name: 'Netscape Navigator', version: '3.0', type: browser }, device: { type: desktop, manufacturer: KOMATSU, model: WebLight } } -------------------------------------------------------------------------------- /test/data/bots/disabled.yaml: -------------------------------------------------------------------------------- 1 | - 2 | detectBots: false 3 | headers: 'User-Agent: (Windows NT 10.0; Googlebot Googlebot-Image/1.0 msnbot-media/1.1 facebookexternalhit/1.1 Trident/7.0) Maxthon/4.4.5.3000 Firefox/38' 4 | result: { browser: { name: "Maxthon", family: { name: "Firefox", version: 38 }, version: "4.4.5", type: "browser" }, engine: { name: "Trident", version: "7.0" }, os: { name: "Windows", version: { value: "10.0", alias: "10" } }, device: { type: "desktop" } } 5 | readable: 'Maxthon 4.4.5 on Windows 10' 6 | - 7 | detectBots: false 8 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534+ (KHTML, like Gecko) MsnBot-Media /1.0b' 9 | result: { engine: { name: "Webkit", version: "534" }, os: { name: "Windows", version: { value: "6.1", alias: "7" } }, device: { type: "desktop" } } 10 | readable: 'an unknown browser based on Webkit 534 running on Windows 7' 11 | - 12 | detectBots: false 13 | headers: 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' 14 | result: { browser: { name: "Safari", version: "6.0", type: "browser" }, engine: { name: "Webkit", version: "536.26" }, os: { name: "iOS", version: "6.0" }, device: { type: "mobile", subtype: "smart", manufacturer: "Apple", model: "iPhone" }} 15 | readable: 'Safari on an Apple iPhone running iOS 6.0' 16 | - 17 | detectBots: false 18 | headers: 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)' 19 | result: { browser: { name: "Safari", version: "7.0", type: "browser" }, engine: { name: "Webkit", version: "537.51.1" }, os: { name: "iOS", version: "7.0" }, device: { type: "mobile", subtype: "smart", manufacturer: "Apple", model: "iPhone" }} 20 | readable: 'Safari on an Apple iPhone running iOS 7.0' 21 | - 22 | detectBots: false 23 | headers: 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Page Speed Insights) Chrome/27.0.1453 Safari/537.36' 24 | result: { browser: { name: "Chrome", version: "27", type: "browser" }, engine: { name: "Blink" }, os: { name: "Linux" }, device: { type: "desktop" }, camouflage: true } 25 | readable: 'an unknown browser that imitates Chrome 27 on Linux' -------------------------------------------------------------------------------- /test/data/bots/false-positive.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.2.2; tr-tr; S308 Build/CUBOT) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 [FB_IAB/FB4A;FBAV/71.0.0.17.73;]' 3 | readable: 'Facebook on a Cubot S308 running Android 4.2.2' 4 | result: { browser: { name: Facebook, type: 'app:social' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, manufacturer: Cubot, model: S308 } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.2.2; de-de; CUBOT S108 Build/CUBOT) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 [FB_IAB/FB4A;FBAV/55.0.0.18.66;]' 7 | readable: 'Facebook on a Cubot S108 running Android 4.2.2' 8 | result: { browser: { name: Facebook, type: 'app:social' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, manufacturer: Cubot, model: S108 } } 9 | -------------------------------------------------------------------------------- /test/data/camera/os-android.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.3; ja-jp; COOLPIX S800c Build/CP01_WW) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 3 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '533.1' }, os: { name: Android, version: 2.3.3 }, device: { type: camera, manufacturer: Nikon, model: 'Coolpix S800c' } } 4 | readable: 'Android Browser on a Nikon Coolpix S800c running Android 2.3.3' 5 | -------------------------------------------------------------------------------- /test/data/camera/os-tizen.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.3; ko-kr; SAMSUNG; NX30) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19' 3 | result: { browser: { family: { name: Chrome, version: 18 } }, engine: { name: Webkit, version: '535.19' }, os: { name: Tizen }, device: { type: camera, manufacturer: Samsung, model: NX30 } } 4 | readable: 'a Samsung NX30 running Tizen' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Tizen 1.0; xx; Samsung NX300) AppleWebKit/534.16 (KHTML, like Gecko) Version/1.0 Mobile Android compatible' 7 | result: { engine: { name: Webkit, version: '534.16' }, os: { name: Tizen, version: '1.0' }, device: { type: camera, manufacturer: Samsung, model: NX300 } } 8 | readable: 'a Samsung NX300 running Tizen 1.0' 9 | -------------------------------------------------------------------------------- /test/data/car/tesla.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (X11; Linux) AppleWebKit/534.34 (KHTML, like Gecko) QtCarBrowser Safari/534.34' 3 | result: { engine: { name: Webkit, version: '534.34' }, device: { type: car, manufacturer: Tesla, model: 'Model S' } } 4 | readable: 'a Tesla Model S' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux; C) AppleWebKit/533.3 (KHTML, like Gecko) QtCarBrowser Safari/533.3' 7 | result: { engine: { name: Webkit, version: '533.3' }, device: { type: car, manufacturer: Tesla, model: 'Model S' } } 8 | readable: 'a Tesla Model S' 9 | -------------------------------------------------------------------------------- /test/data/car/volvo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (VCC; 1.0; like Gecko) NetFront/4.2' 3 | readable: 'NetFront 4.2' 4 | result: { browser: { name: NetFront, version: '4.2', type: browser }, engine: { name: NetFront }, device: { type: car } } 5 | - 6 | headers: 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MSIE 5.5; Windows NT 5.0) Opera 7.02 Bork-edition [en]' 7 | useragent: 'Mozilla/5.0 (VCC; 1.0; like Gecko) NetFront/4.2' 8 | readable: 'Opera 7.02 on Windows 2000' 9 | result: { browser: { name: Opera, version: '7.02', type: browser }, engine: { name: Presto }, os: { name: Windows, version: { value: '5.0', alias: '2000' } }, device: { type: desktop } } 10 | -------------------------------------------------------------------------------- /test/data/desktop/app-editor.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Brackets/1.1.0 Chrome/39.0.2171.36 Safari/537.36' 3 | result: { browser: { name: Brackets, family: { name: Chrome, version: 39 }, version: 1.1.0, type: 'app:editor' }, engine: { name: Blink }, os: { name: 'OS X', version: { value: '10.9', nickname: Mavericks } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 4 | readable: 'Brackets 1.1.0 on OS X Mavericks 10.9' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Atom/1.0.19 Chrome/43.0.2357.65 Electron/0.30.7 Safari/537.36' 7 | result: { browser: { name: Atom, using: { name: Electron, version: 0.30.7 }, family: { name: Chrome, version: 43 }, version: 1.0.19, type: 'app:editor' }, engine: { name: Blink }, os: { name: Linux }, device: { type: desktop } } 8 | readable: 'Atom 1.0.19 on Linux' 9 | - 10 | headers: 'User-Agent: Mozilla/3.0 (compatible; GoLive 6.0; Windows 2000)' 11 | result: { browser: { name: 'Adobe GoLive', version: '6.0', type: 'app:editor' }, os: { name: Windows, version: { value: '5.0', alias: '2000' } }, device: { type: desktop } } 12 | readable: 'Adobe GoLive 6.0 on Windows 2000' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10) AppleWebKit/600.1.25 (KHTML, like Gecko) iWeb/304' 15 | result: { browser: { name: iWeb, version: '3', type: 'app:editor' }, engine: { name: Webkit, version: 600.1.25 }, os: { name: 'OS X', version: { value: '10.10', nickname: Yosemite } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 16 | readable: 'iWeb 3 on OS X Yosemite 10.10' 17 | - 18 | headers: 'User-Agent: Mozilla/4.0 (IBM WebSphere Homepage Builder V12.0/Version 12.0.4.0)' 19 | readable: 'IBM WebSphere Homepage Builder 12.0' 20 | result: { browser: { name: 'IBM WebSphere Homepage Builder', version: '12.0', type: 'app:editor' } } 21 | - 22 | headers: 'User-Agent: Mozilla/4.0 (IBM WebSphere Homepage Builder V7.0/Version 7.0.1.0)' 23 | readable: 'IBM WebSphere Homepage Builder 7.0' 24 | result: { browser: { name: 'IBM WebSphere Homepage Builder', version: '7.0', type: 'app:editor' } } 25 | - 26 | headers: 'User-Agent: Mozilla/4.0 (IBM WebSphere Homepage Builder V10.0/Version 10.0.3.0)' 27 | readable: 'IBM WebSphere Homepage Builder 10.0' 28 | result: { browser: { name: 'IBM WebSphere Homepage Builder', version: '10.0', type: 'app:editor' } } -------------------------------------------------------------------------------- /test/data/desktop/app-mediaplayer.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.28) Gecko/20130316 Nightingale/1.12.2 (20140112193149)' 3 | result: { browser: { name: Nightingale, version: 1.12.2, type: 'app:mediaplayer' }, engine: { name: Gecko, version: 1.9.2 }, os: { name: Linux }, device: { type: desktop } } 4 | readable: 'Nightingale 1.12.2 on Linux' 5 | -------------------------------------------------------------------------------- /test/data/desktop/browser-arachne.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: xChaos_Arachne/4.1.71;UE01 (DOS x86;WATTCP/1.05; 640x480,16c; www.arachne.cz)' 3 | result: { browser: { name: Arachne, version: '1.71', type: browser }, device: { type: desktop } } 4 | readable: 'Arachne 1.71' 5 | - 6 | headers: 'User-Agent: xChaos_Arachne/5.1.89;GPL,386+' 7 | result: { browser: { name: Arachne, version: '1.89', type: browser }, device: { type: desktop } } 8 | readable: 'Arachne 1.89' 9 | -------------------------------------------------------------------------------- /test/data/desktop/browser-brave.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.0.2 Chrome/47.0.2526.73 Electron/0.36.1 Safari/537.36' 3 | result: { browser: { name: Brave, using: { name: Electron, version: 0.36.1 }, family: { name: Chrome, version: 47 }, version: 0.0.2, type: browser }, engine: { name: Blink }, os: { name: 'OS X', version: { value: '10.11', nickname: 'El Capitan' } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 4 | readable: 'Brave 0.0.2 on OS X El Capitan 10.11' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.7.7 Chrome/47.0.2526.73 Electron/0.36.2 Safari/537.36' 7 | result: { browser: { name: Brave, using: { name: Electron, version: 0.36.2 }, family: { name: Chrome, version: 47 }, version: 0.7.7, type: browser }, engine: { name: Blink }, os: { name: 'OS X', version: { value: '10.11', nickname: 'El Capitan' } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 8 | readable: 'Brave 0.7.7 on OS X El Capitan 10.11' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) brave/0.7.7 Chrome/47.0.2526.73 Electron/0.36.2 Safari/537.36' 11 | result: { browser: { name: Brave, using: { name: Electron, version: 0.36.2 }, family: { name: Chrome, version: 47 }, version: 0.7.7, type: browser }, engine: { name: Blink }, os: { name: 'OS X', version: { value: '10.11', nickname: 'El Capitan' } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 12 | readable: 'Brave 0.7.7 on OS X El Capitan 10.11' 13 | -------------------------------------------------------------------------------- /test/data/desktop/browser-flow.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) EkiohFlow/5.10.0.32202 Flow/5.10.0 (like Gecko Firefox/62.0 rv:62.0)' 3 | result: { browser: { name: Flow, version: 5.10.0, type: browser }, engine: { name: EkiohFlow, version: 5.10.0.32202 }, os: { name: 'OS X', alias: macOS, version: { value: '10.15', nickname: Catalina } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 4 | readable: 'Flow 5.10.0 on macOS Catalina 10.15' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) EkiohFlow/5.9.4.32015 Flow/5.9.4 (like Gecko Firefox/53.0 rv:53.0)' 7 | result: { browser: { name: Flow, version: 5.9.4, type: browser }, engine: { name: EkiohFlow, version: 5.9.4.32015 }, os: { name: 'OS X', alias: macOS, version: { value: '10.15', nickname: Catalina } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 8 | readable: 'Flow 5.9.4 on macOS Catalina 10.15' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) EkiohFlow/5.9.4.32015M Flow/5.9.4 (like Gecko Firefox/53.0 rv:53.0)' 11 | result: { browser: { name: 'Flow Nightly Build', type: browser }, engine: { name: EkiohFlow, version: 5.9.4.32015 }, os: { name: 'OS X', alias: macOS, version: { value: '10.15', nickname: Catalina } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 12 | readable: 'Flow Nightly Build on macOS Catalina 10.15' -------------------------------------------------------------------------------- /test/data/desktop/browser-netfront.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WKC) AppleWebKit/536.5.1 (KHTML, like Gecko) NetFrontBrowserNX/3.0.0' 3 | result: { browser: { name: 'NetFront NX', version: '3.0', type: browser }, engine: { name: Webkit, version: 536.5.1 }, device: { type: desktop } } 4 | readable: 'NetFront NX 3.0' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WKC) AppleWebKit/534.52.7 (KHTML, like Gecko) NetFrontBrowserNX/2.1.0' 7 | result: { browser: { name: 'NetFront NX', version: '2.1', type: browser }, engine: { name: Webkit, version: 534.52.7 }, device: { type: desktop } } 8 | readable: 'NetFront NX 2.1' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.15 (KHTML, like Gecko) NX/3.0 Chrome/24.0.1295.0 Safari/537.15' 11 | result: { browser: { name: 'NetFront NX', family: { name: Chrome, version: 24 }, version: '3.0', type: browser }, engine: { name: Webkit, version: '537.15' }, device: { type: desktop } } 12 | readable: 'NetFront NX 3.0' 13 | - 14 | headers: 'User-Agent: NX/2.1' 15 | result: { browser: { name: 'NetFront NX', version: '2.1', type: browser }, device: { type: desktop } } 16 | readable: 'NetFront NX 2.1' 17 | - 18 | headers: 'User-Agent: NX/3.0' 19 | result: { browser: { name: 'NetFront NX', version: '3.0', type: browser }, device: { type: desktop } } 20 | readable: 'NetFront NX 3.0' 21 | -------------------------------------------------------------------------------- /test/data/desktop/browser-text.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: ELinks (0.11.3; Linux 2.6.23-gentoo-r5 i686; 209x77)' 3 | result: { browser: { name: ELinks, version: 0.11.3, type: 'browser:text' }, os: { name: Linux }, device: { type: desktop } } 4 | readable: 'ELinks 0.11.3 on Linux' 5 | - 6 | headers: 'User-Agent: Elinks (0.3.2; Linux 2.4.21 i686)' 7 | result: { browser: { name: ELinks, version: 0.3.2, type: 'browser:text' }, os: { name: Linux }, device: { type: desktop } } 8 | readable: 'ELinks 0.3.2 on Linux' 9 | - 10 | headers: 'User-Agent: Elinks (0.3; FreeBSD 4.3-RELEASE i386)' 11 | result: { browser: { name: ELinks, version: '0.3', type: 'browser:text' }, os: { name: FreeBSD, family: BSD, version: '4.3' }, device: { type: desktop } } 12 | readable: 'ELinks 0.3 on FreeBSD 4.3' 13 | - 14 | headers: 'User-Agent: ELinks (0.4.3rc2; Linux 2.4.22 i686; 110x40)' 15 | result: { browser: { name: ELinks, version: 0.4.3, type: 'browser:text' }, os: { name: Linux }, device: { type: desktop } } 16 | readable: 'ELinks 0.4.3 on Linux' 17 | - 18 | headers: 'User-Agent: ELinks/0.10.4-7-debian (textmode; Linux 2.6.14 i686; 110x48-2)' 19 | result: { browser: { name: ELinks, version: 0.10.4, type: 'browser:text' }, os: { name: Linux }, device: { type: desktop } } 20 | readable: 'ELinks 0.10.4 on Linux' 21 | - 22 | headers: 'User-Agent: ELinks/0.9.1 (textmode; Linux; 127x48)' 23 | result: { browser: { name: ELinks, version: 0.9.1, type: 'browser:text' }, os: { name: Linux }, device: { type: desktop } } 24 | readable: 'ELinks 0.9.1 on Linux' 25 | - 26 | headers: 'User-Agent: Emacs-w3m/1.3.3 w3m/0.3.1' 27 | result: { browser: { name: w3m, version: 1.3.3, type: 'browser:text' } } 28 | readable: 'w3m 1.3.3' 29 | - 30 | headers: 'User-Agent: Emacs-w3m/1.4.4 w3m/0.5.1' 31 | result: { browser: { name: w3m, version: 1.4.4, type: 'browser:text' } } 32 | readable: 'w3m 1.4.4' 33 | - 34 | headers: 'User-Agent: Emacs-w3m/1.4.77 w3m/0.5' 35 | result: { browser: { name: w3m, version: 1.4.77, type: 'browser:text' } } 36 | readable: 'w3m 1.4.77' 37 | - 38 | headers: 'User-Agent: CERN-LineMode/2.12' 39 | result: { browser: { name: 'CERN LineMode', version: '2.12', type: 'browser:text' } } 40 | readable: 'CERN LineMode 2.12' 41 | - 42 | headers: 'User-Agent: CERN-LineMode/2.14' 43 | result: { browser: { name: 'CERN LineMode', version: '2.14', type: 'browser:text' } } 44 | readable: 'CERN LineMode 2.14' 45 | - 46 | headers: 'User-Agent: CERN-LineMode/3.0' 47 | result: { browser: { name: 'CERN LineMode', version: '3.0', type: 'browser:text' } } 48 | readable: 'CERN LineMode 3.0' 49 | -------------------------------------------------------------------------------- /test/data/desktop/engine-servo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Servo/1.0 Firefox/37.0' 3 | result: { browser: { name: 'Servo Nightly Build', type: browser }, engine: { name: Servo, version: '1.0' }, os: { name: 'OS X', version: { value: '10.10', nickname: Yosemite } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 4 | readable: 'Servo Nightly Build on OS X Yosemite 10.10' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:37.0) Servo/1.0 Firefox/37.0' 7 | readable: 'Servo Nightly Build on Linux' 8 | result: { browser: { name: 'Servo Nightly Build', type: browser }, engine: { name: Servo, version: '1.0' }, os: { name: Linux }, device: { type: desktop } } 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:55.0) Servo/1.0 Firefox/55.0' 11 | readable: 'Servo Nightly Build on OS X Yosemite 10.10' 12 | result: { browser: { name: 'Servo Nightly Build', type: browser }, engine: { name: Servo, version: '1.0' }, os: { name: 'OS X', version: { value: '10.10', nickname: Yosemite } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } -------------------------------------------------------------------------------- /test/data/desktop/os-aros.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (compatible; Odyssey Web Browser; AROS; rv:1.16) AppleWebKit/535.14 (KHTML, like Gecko) OWB/1.16 Safari/535.14' 3 | result: { browser: { name: Odyssey, version: '1.16', type: browser }, engine: { name: Webkit, version: '535.14' }, os: { name: AROS }, device: { type: desktop } } 4 | readable: 'Odyssey 1.16 on AROS' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (i386; AROS 0.0; Odyssey Web Browser; rv:1.23) AppleWebKit/538.1 (KHTML, like Gecko) OWB/1.23 Safari/538.1' 7 | result: { browser: { name: Odyssey, version: '1.23', type: browser }, engine: { name: Webkit, version: '538.1' }, os: { name: AROS }, device: { type: desktop } } 8 | readable: 'Odyssey 1.23 on AROS' 9 | -------------------------------------------------------------------------------- /test/data/desktop/os-beos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.0 (compatible; NetPositive/2.2.1; BeOS)' 3 | result: { browser: { name: NetPositive, version: 2.2.1, type: browser }, os: { name: BeOS }, device: { type: desktop } } 4 | readable: 'NetPositive 2.2.1 on BeOS' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (BeOS; U; BeOS BePC; xx; rv:1.8.1) Gecko/20061108 BonEcho/2.0' 7 | result: { browser: { name: Firefox, version: '2.0', type: browser }, engine: { name: Gecko, version: 1.8.1 }, os: { name: BeOS }, device: { type: desktop } } 8 | readable: 'Firefox BonEcho 2.0 on BeOS' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (BeOS; U; BeOS BePC; xx; rv:1.8.1.17) Gecko/20080831 BonEcho/2.0.0.17' 11 | result: { browser: { name: Firefox, version: 2.0.0.17, type: browser }, engine: { name: Gecko, version: 1.8.1 }, os: { name: BeOS }, device: { type: desktop } } 12 | readable: 'Firefox BonEcho 2.0.0.17 on BeOS' 13 | -------------------------------------------------------------------------------- /test/data/desktop/os-irix.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.04Gold (X11; U; IRIX 5.3 IP22)' 3 | result: { browser: { name: 'Netscape Navigator', version: 3.0.4, type: browser }, os: { name: IRIX, family: UNIX, version: '5.3' }, device: { type: desktop } } 4 | readable: 'Netscape Navigator 3.0.4 on IRIX 5.3' 5 | - 6 | headers: 'User-Agent: Mozilla/4.08 [en] (X11; U; IRIX 5.3 IP5; Nav)' 7 | result: { browser: { name: 'Netscape Navigator', version: 4.0.8, type: browser }, os: { name: IRIX, family: UNIX, version: '5.3' }, device: { type: desktop } } 8 | readable: 'Netscape Navigator 4.0.8 on IRIX 5.3' 9 | - 10 | headers: 'User-Agent: Mozilla/4.76C-SGI [ru] (X11; I; IRIX64 6.5 IP30)' 11 | result: { browser: { name: 'Netscape Communicator', version: 4.7.6, type: browser }, os: { name: IRIX, family: UNIX, version: '6.5' }, device: { type: desktop } } 12 | readable: 'Netscape Communicator 4.7.6 on IRIX 6.5' 13 | - 14 | headers: 'User-Agent: Mozilla/4.77 [en] (X11; I; IRIX;64 6.5 IP30)' 15 | result: { browser: { name: 'Netscape Communicator', version: 4.7.7, type: browser }, os: { name: IRIX, family: UNIX, version: '6.5' }, device: { type: desktop } } 16 | readable: 'Netscape Communicator 4.7.7 on IRIX 6.5' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (X11; U; IRIX IP32; xx; rv:1.9.0.19) Gecko/2013020113 Firefox/3.0.19' 19 | result: { browser: { name: Firefox, version: 3.0.19, type: browser }, engine: { name: Gecko, version: 1.9.0 }, os: { name: IRIX, family: UNIX }, device: { type: desktop } } 20 | readable: 'Firefox 3.0.19 on IRIX' 21 | -------------------------------------------------------------------------------- /test/data/desktop/os-joli.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (X11; Jolicloud Linux i686) AppleWebKit/537.6 (KHTML, like Gecko) Joli OS/1.2 Chromium/23.0.1240.0 Chrome/23.0.1240.0 Safari/537.6' 3 | result: { browser: { name: Chromium, family: { name: Chrome, version: 23 }, version: 23.0.1240.0, type: browser }, engine: { name: Webkit, version: '537.6' }, os: { name: 'Joli OS', version: '1.2' }, device: { type: desktop } } 4 | readable: 'Chromium 23.0.1240.0 on Joli OS 1.2' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Jolicloud Linux i686; xx) AppleWebKit/534.16 (KHTML, like Gecko) Joli OS/1.2 Chromium/10.0.648.82 Chrome/10.0.648.82 Safari/534.16' 7 | result: { browser: { name: Chromium, family: { name: Chrome, version: 10 }, version: 10.0.648.82, type: browser }, engine: { name: Webkit, version: '534.16' }, os: { name: 'Joli OS', version: '1.2' }, device: { type: desktop } } 8 | readable: 'Chromium 10.0.648.82 on Joli OS 1.2' 9 | -------------------------------------------------------------------------------- /test/data/desktop/os-osx.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: QuickTime/7.6 (qtver=7.6;cpu=IA32;os=Mac 10,5,7)' 3 | result: { browser: { name: QuickTime, version: '7.6', type: 'app:mediaplayer' }, os: { name: 'OS X', alias: 'Mac OS X', version: '10.5' }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 4 | readable: 'QuickTime 7.6 on Mac OS X 10.5' 5 | -------------------------------------------------------------------------------- /test/data/desktop/os-redstar.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; xx; rv:1.9.1b4) Gecko/20130508 Fedora/1.9.1-2.5.rs3.0 NaenaraBrowser/3.5b4' 3 | result: { browser: { name: Naenara, version: '3.5', type: browser }, engine: { name: Gecko, version: 1.9.1b4 }, os: { name: 'Red Star', version: '3.0' }, device: { type: desktop } } 4 | readable: 'Naenara 3.5 on Red Star 3.0' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; ko-KP, en; rv:1.8.1.8) Gecko/20090718 《붉은별》/2.5 NaenaraBrowser/2.0.0.8' 7 | result: { browser: { name: Naenara, version: '2.0', type: browser }, engine: { name: Gecko, version: 1.8.1 }, os: { name: 'Red Star', version: '2.5' }, device: { type: desktop } } 8 | readable: 'Naenara 2.0 on Red Star 2.5' 9 | -------------------------------------------------------------------------------- /test/data/desktop/os-remix.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Browse/0.6 (Linux 3.10.0+; RemixOS 5.1.1; RemixOS SDK built for x86; en_us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.0.0 Desktop (Opera Mini/Compression)' 3 | readable: 'Browse 0.6 on Remix OS 1.0' 4 | result: { browser: { name: Browse, version: '0.6', type: browser }, engine: { name: Blink }, os: { name: 'Remix OS', family: Android, version: '1.0' }, device: { type: desktop } } 5 | - 6 | headers: 'User-Agent: Browse/0.6 (Linux 3.10.0+; RemixOS 6.0; RemixOS SDK built for x86; en_us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.119 Desktop' 7 | readable: 'Browse 0.6 on Remix OS 2.0' 8 | result: { browser: { name: Browse, family: { name: Chrome, version: 44 }, version: '0.6', type: browser }, engine: { name: Blink }, os: { name: 'Remix OS', family: Android, version: '2.0' }, device: { type: desktop } } 9 | - 10 | headers: 'User-Agent: Browse/0.6.mini (Linux 3.4.0+; RemixOS 6.0; Motorola Moto G 2014; en_us) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.119 Desktop' 11 | readable: 'Browse 0.6 on a Motorola Moto G (Google Edition, 2014) running Remix OS 2.0' 12 | result: { browser: { name: Browse, family: { name: Chrome, version: 44 }, version: 0.6., type: browser }, engine: { name: Blink }, os: { name: 'Remix OS', family: Android, version: '2.0' }, device: { type: mobile, subtype: smart, manufacturer: Motorola, model: 'Moto G (Google Edition, 2014)' } } 13 | -------------------------------------------------------------------------------- /test/data/desktop/os-riscos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/1.10 [en] (Compatible; RISC OS 3.70; Oregano 1.10)' 3 | result: { browser: { name: Oregano, version: '1.10', type: browser }, os: { name: 'RISC OS', version: '3.70' }, device: { type: desktop } } 4 | readable: 'Oregano 1.10 on RISC OS 3.70' 5 | - 6 | headers: 'User-Agent: Mozilla/3.04 (compatible; ANTFresco/2.13; RISC OS 4.02)' 7 | result: { browser: { name: 'ANT Fresco', version: '2.13', type: browser }, os: { name: 'RISC OS', version: '4.02' }, device: { type: desktop } } 8 | readable: 'ANT Fresco 2.13 on RISC OS 4.02' 9 | - 10 | headers: 'User-Agent: Mozilla/4.01 (Compatible; Acorn Browse 1.25 [23-Oct-97] AW 97; RISC OS 4.39) Acorn-HTTP/0.84' 11 | result: { browser: { name: 'Acorn Browse', version: '1.25', type: browser }, os: { name: 'RISC OS', version: '4.39' }, device: { type: desktop } } 12 | readable: 'Acorn Browse 1.25 on RISC OS 4.39' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (ChoX11; U; RISC OS; xx; rv:1.8.1.12) Gecko/20080224 BonEcho/2.0.0.12' 15 | result: { browser: { name: Firefox, version: 2.0.0.12, type: browser }, engine: { name: Gecko, version: 1.8.1 }, os: { name: 'RISC OS' }, device: { type: desktop } } 16 | readable: 'Firefox BonEcho 2.0.0.12 on RISC OS' 17 | - 18 | headers: 'User-Agent: NetSurf/2.0 (RISC OS; armv5l)' 19 | result: { browser: { name: Surf, version: '2.0', type: browser }, os: { name: 'RISC OS' }, device: { type: desktop } } 20 | readable: 'Surf 2.0 on RISC OS' 21 | - 22 | headers: 'User-Agent: NetSurf/3.0 (RISC OS)' 23 | result: { browser: { name: Surf, version: '3.0', type: browser }, os: { name: 'RISC OS' }, device: { type: desktop } } 24 | readable: 'Surf 3.0 on RISC OS' 25 | - 26 | headers: 'User-Agent: Mozilla/4.01 (Compatible; Acorn Phoenix 2.08 [intermediate]; RISC OS 4.39) Acorn-HTTP/0.84' 27 | result: { browser: { name: 'Acorn Browse', version: '2.08', type: browser }, os: { name: 'RISC OS', version: '4.39' }, device: { type: desktop } } 28 | readable: 'Acorn Browse 2.08 on RISC OS 4.39' 29 | - 30 | headers: 'User-Agent: Mozilla/4.00 [en] (Compatible; RISC OS 4.39; MSIE 5.01; Windows 98; Oregano 1.10)' 31 | result: { browser: { name: Oregano, version: '1.10', type: browser }, os: { name: 'RISC OS', version: '4.39' }, device: { type: desktop } } 32 | readable: 'Oregano 1.10 on RISC OS 4.39' 33 | -------------------------------------------------------------------------------- /test/data/desktop/os-syllable.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (compatible; ABrowse 0.4; Syllable)' 3 | result: { browser: { name: ABrowse, version: '0.4', type: browser }, os: { name: Syllable }, device: { type: desktop } } 4 | readable: 'ABrowse 0.4 on Syllable' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (compatible; U; ABrowse 0.6; Syllable) AppleWebKit/420+ (KHTML, like Gecko)' 7 | result: { browser: { name: ABrowse, version: '0.6', type: browser }, engine: { name: Webkit, version: '420' }, os: { name: Syllable }, device: { type: desktop } } 8 | readable: 'ABrowse 0.6 on Syllable' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (compatible; U; ABrowse 0.7; Syllable) AppleWebKit/420+ (KHTML, like Gecko)' 11 | result: { browser: { name: ABrowse, version: '0.7', type: browser }, engine: { name: Webkit, version: '420' }, os: { name: Syllable }, device: { type: desktop } } 12 | readable: 'ABrowse 0.7 on Syllable' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (compatible; U; Webster 0.1; Syllable) AppleWebKit/420+ (KHTML, like Gecko)' 15 | result: { browser: { name: Webster, version: '0.1', type: browser }, engine: { name: Webkit, version: '420' }, os: { name: Syllable }, device: { type: desktop } } 16 | readable: 'Webster 0.1 on Syllable' 17 | -------------------------------------------------------------------------------- /test/data/desktop/other.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: WorldWideweb (NEXT)' 3 | result: { browser: { name: WorldWideWeb, type: browser }, os: { name: NextStep }, device: { type: desktop } } 4 | readable: 'WorldWideWeb on NextStep' 5 | - 6 | headers: 'User-Agent: Mozilla/4.08 (Charon; Inferno)' 7 | result: { browser: { name: Charon, type: browser }, os: { name: Inferno }, device: { type: desktop } } 8 | readable: 'Charon on Inferno' 9 | - 10 | headers: 'User-Agent: VMS_Mosaic/3.8-1 (Motif;OpenVMS V7.3-2 DEC 3000 - M700) libwww/2.12_Mosaic' 11 | result: { browser: { name: 'VMS Mosaic', family: Mosaic, version: '3.8', type: browser }, os: { name: OpenVMS, version: '7.3' }, device: { type: desktop } } 12 | readable: 'VMS Mosaic 3.8 on OpenVMS 7.3' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 ASW/1.51.2220.53' 15 | readable: 'Avast SafeZone 1.51 on Windows 10' 16 | result: { browser: { name: 'Avast SafeZone', family: { name: Chrome, version: 51 }, version: '1.51', type: browser }, engine: { name: Blink }, os: { name: Windows, version: { value: '10.0', alias: '10' } }, device: { type: desktop } } 17 | -------------------------------------------------------------------------------- /test/data/desktop/platform-qt.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (N; Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) QtMiniBrowser/0.1 Safari/538.1' 3 | result: { browser: { name: QtMiniBrowser, version: '0.1', type: browser }, engine: { name: Webkit, version: '538.1' }, os: { name: Windows, version: { value: '6.1', alias: '7' } }, device: { type: desktop } } 4 | readable: 'QtMiniBrowser 0.1 on Windows 7' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Unknown; Linux armv7l) AppleWebKit/537.36 (KHTML, like Gecko) QtWebEngine/0.9.0 Chrome/33.0.1750.149 Safari/537.36' 7 | result: { browser: { using: Qt, family: { name: Chrome, version: 33 }, type: browser }, engine: { name: Blink }, os: { name: Linux }, device: { type: desktop } } 8 | readable: 'Qt on Linux' 9 | -------------------------------------------------------------------------------- /test/data/ereader/amazon.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.0 (compatible; Linux 2.6.10) NetFront/3.3 Kindle/1.0 (screen 600x800)' 3 | result: { browser: { name: NetFront, version: '3.3', type: browser }, engine: { name: NetFront }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle 1' } } 4 | readable: 'NetFront 3.3 on an Amazon Kindle 1' 5 | - 6 | headers: 'User-Agent: Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.0 (screen 600x800)' 7 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle 2' } } 8 | readable: 'NetFront 3.4 on an Amazon Kindle 2' 9 | - 10 | headers: 'User-Agent: Mozilla/4.0 (compatible; Linux 2.6.22) NetFront/3.4 Kindle/2.5 (screen 600x800; rotate)' 11 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle 2' } } 12 | readable: 'NetFront 3.4 on an Amazon Kindle 2' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; en-US) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) Version/4.0 Kindle/3.0 (screen 600X800; rotate)' 15 | result: { engine: { name: Webkit, version: '528.5' }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle 3' } } 16 | readable: 'an Amazon Kindle 3' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (X11; ; U; Linux armv7l; zh-cn) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ Kindle SkipStone 1.0.1' 19 | result: { engine: { name: Webkit, version: '534.26' }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle Touch or later' } } 20 | readable: 'an Amazon Kindle Touch or later' 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux armv7l like Android; en-us) AppleWebKit/531.2+ (KHTML, like Gecko) Version/5.0 Safari/533.2+ Kindle/3.0+' 23 | result: { engine: { name: Webkit, version: '531.2' }, device: { type: ereader, manufacturer: Amazon, model: 'Kindle 3 or later' } } 24 | readable: 'an Amazon Kindle 3 or later' 25 | -------------------------------------------------------------------------------- /test/data/ereader/kobo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.0; en-us;) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 (Kobo Touch)' 3 | result: { engine: { name: Webkit, version: '533.1' }, device: { type: ereader, manufacturer: Kobo, series: eReader } } 4 | readable: 'a Kobo eReader' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (QtEmbedded; Linux) AppleWebKit/534.34 (KHTML, like Gecko) Kobo eReader Safari/534.34' 7 | result: { browser: { using: Qt }, engine: { name: Webkit, version: '534.34' }, device: { type: ereader, manufacturer: Kobo, series: eReader } } 8 | readable: 'Qt on a Kobo eReader' 9 | -------------------------------------------------------------------------------- /test/data/ereader/other.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Iriver ; EB07 ) AppleWebKit/534.16 (KHTML, like Gecko) Version/5.0 Safari/534.16' 3 | result: { engine: { name: Webkit, version: '534.16' }, device: { type: ereader, manufacturer: iRiver, model: 'Story HD EB07' } } 4 | readable: 'an iRiver Story HD EB07' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (mobile; CPU ARM Linux 2.6.21;en-us) AppleWebKit/525.1 (bookeen/cybook) Orizon/1.0 (screen 600x800)' 7 | result: { engine: { name: Webkit, version: '525.1' }, device: { type: ereader, manufacturer: Bookeen, series: Cybook } } 8 | readable: 'a Bookeen Cybook' 9 | -------------------------------------------------------------------------------- /test/data/ereader/sony.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; en-us; EBRD1101; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 3 | result: { engine: { name: Webkit, version: '533.1' }, device: { type: ereader, manufacturer: Sony, model: PRS-T1, series: Reader } } 4 | readable: 'a Sony PRS-T1 Reader' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; en-us; EBRD1201; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 7 | result: { engine: { name: Webkit, version: '533.1' }, device: { type: ereader, manufacturer: Sony, model: PRS-T2, series: Reader } } 8 | readable: 'a Sony PRS-T2 Reader' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; en-us; EBRD1301; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 11 | result: { engine: { name: Webkit, version: '533.1' }, device: { type: ereader, manufacturer: Sony, model: PRS-T3, series: Reader } } 12 | readable: 'a Sony PRS-T3 Reader' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; ja-jp; EBRD1102; EXT) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 15 | result: { engine: { name: Webkit, version: '533.1' }, device: { type: ereader, manufacturer: Sony, model: PRS-G1, series: Reader } } 16 | readable: 'a Sony PRS-G1 Reader' 17 | -------------------------------------------------------------------------------- /test/data/gaming/microsoft.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586' 3 | result: { browser: { name: Edge, version: '13', type: browser }, engine: { name: EdgeHTML, version: '13.10586' }, os: { name: Windows, version: { value: '10.0', alias: '10' } }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox One' } } 4 | readable: 'Edge 13 on a Microsoft Xbox One running Windows 10' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Xbox; Xbox One) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/13.10586' 7 | result: { browser: { name: Edge, version: '13', type: browser }, engine: { name: EdgeHTML, version: '13.10586' }, os: { name: Windows, version: { value: '10.0', alias: '10' } }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox One' } } 8 | readable: 'Edge 13 on a Microsoft Xbox One running Windows 10' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0; Xbox; Xbox One)' 11 | result: { browser: { name: 'Internet Explorer', version: '10.0', type: browser }, engine: { name: Trident, version: '6.0' }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox One' } } 12 | readable: 'Internet Explorer 10.0 on a Microsoft Xbox One' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)' 15 | result: { browser: { name: 'Internet Explorer', version: '9.0', type: browser }, engine: { name: Trident, version: '5.0' }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox 360' } } 16 | readable: 'Internet Explorer 9.0 on a Microsoft Xbox 360' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; Xbox)' 19 | result: { browser: { name: 'Internet Explorer', version: '9.0', type: browser }, engine: { name: Trident, version: '5.0' }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox 360' } } 20 | readable: 'Internet Explorer 9.0 on a Microsoft Xbox 360' 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Xbox; Xbox Series X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36 Edge/20.02' 23 | result: { browser: { name: Edge, version: '20', type: browser }, engine: { name: EdgeHTML, version: '20.02' }, device: { type: gaming, subtype: console, manufacturer: Microsoft, model: 'Xbox Series X' } } 24 | readable: 'Edge 20 on a Microsoft Xbox Series X' 25 | -------------------------------------------------------------------------------- /test/data/gaming/other.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.3; SHIELD Build/JSS15J) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.99 Mobile Safari/537.36' 3 | result: { browser: { name: Chrome, version: '32', type: browser }, engine: { name: Blink }, os: { name: Android, version: '4.3' }, device: { type: gaming, subtype: console, manufacturer: Nvidia, model: SHIELD } } 4 | readable: 'Chrome 32 on a Nvidia SHIELD running Android 4.3' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.1; es-es; ARCHOS GAMEPAD Build/JRO03H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30' 7 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.1.1 }, device: { type: gaming, subtype: portable, manufacturer: Archos, model: Gamepad } } 8 | readable: 'Android Browser on an Archos Gamepad running Android 4.1.1' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android OUYA 4.1.2; en-us; OUYA Build/JZO54L-OUYA) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30' 11 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.1.2 }, device: { type: gaming, subtype: console, manufacturer: OUYA, model: OUYA } } 12 | readable: 'Android Browser on an OUYA running Android 4.1.2' 13 | -------------------------------------------------------------------------------- /test/data/gaming/sega.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Aplix_SEGASATURN_browser/2.0 (Japanese)' 3 | result: { browser: { name: Aplix, version: '2.0', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Saturn } } 4 | readable: 'Aplix 2.0 on a Sega Saturn' 5 | - 6 | headers: 'User-Agent: Aplix_SEGASATURN_browser/1.x (Japanese)' 7 | result: { browser: { name: Aplix, version: '1', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Saturn } } 8 | readable: 'Aplix 1 on a Sega Saturn' 9 | - 10 | headers: 'User-Agent: Mozilla/3.0 (DreamPassport/3.0; SEGA/SAKURA-DP3)' 11 | result: { browser: { name: 'Dream Passport', version: '3.0', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 12 | readable: 'Dream Passport 3.0 on a Sega Dreamcast' 13 | - 14 | headers: 'User-Agent: Mozilla/3.0 (DreamPassport/3.15; SEGA/VF.NET)' 15 | result: { browser: { name: 'Dream Passport', version: '3.15', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 16 | readable: 'Dream Passport 3.15 on a Sega Dreamcast' 17 | - 18 | headers: 'User-Agent: Mozilla/3.0 (DreamPassport/3.0; isao/MyDiGiRabi)' 19 | result: { browser: { name: 'Dream Passport', version: '3.0', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 20 | readable: 'Dream Passport 3.0 on a Sega Dreamcast' 21 | - 22 | headers: 'User-Agent: Mozilla/3.0 (DreamPassport/2.1)' 23 | result: { browser: { name: 'Dream Passport', version: '2.1', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 24 | readable: 'Dream Passport 2.1 on a Sega Dreamcast' 25 | - 26 | headers: 'User-Agent: Mozilla/3.0 (DreamPassport/1.01)' 27 | result: { browser: { name: 'Dream Passport', version: '1.01', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 28 | readable: 'Dream Passport 1.01 on a Sega Dreamcast' 29 | - 30 | headers: 'User-Agent: Mozilla/3.0 (Planetweb/2.100 JS SSL US; Dreamcast US)' 31 | result: { browser: { name: Planetweb, version: '2.100', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 32 | readable: 'Planetweb 2.100 on a Sega Dreamcast' 33 | - 34 | headers: 'User-Agent: Mozilla/3.0 (DreamKey/1.0)' 35 | result: { browser: { name: Dreamkey, version: '1.0', type: browser }, device: { type: gaming, subtype: console, manufacturer: Sega, model: Dreamcast } } 36 | readable: 'Dreamkey 1.0 on a Sega Dreamcast' 37 | -------------------------------------------------------------------------------- /test/data/headset/device-gear.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 5.1.1; SAMSUNG SM-G920F Build/LMY47X) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile VR Safari/537.36' 3 | readable: 'Samsung Internet 4.0 on a Samsung Gear VR running Android 5.1.1' 4 | result: { browser: { name: 'Samsung Internet', version: '4.0', type: browser }, engine: { name: Blink }, os: { name: Android, version: 5.1.1 }, device: { type: headset, manufacturer: Samsung, model: 'Gear VR' } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 5.0.1; SAMSUNG SM-N916K Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/3.0 Chrome/38.0.2125.102 Mobile VR Safari/537.36' 7 | readable: 'Samsung Internet 3.0 on a Samsung Gear VR running Android 5.0.1' 8 | result: { browser: { name: 'Samsung Internet', version: '3.0', type: browser }, engine: { name: Blink }, os: { name: Android, version: 5.0.1 }, device: { type: headset, manufacturer: Samsung, model: 'Gear VR' } } 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; SAMSUNG SM-G935F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/4.0 Chrome/44.0.2403.133 Mobile VR Safari/537.36' 11 | readable: 'Samsung Internet 4.0 on a Samsung Gear VR running Android 6.0.1' 12 | result: { browser: { name: 'Samsung Internet', version: '4.0', type: browser }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: headset, manufacturer: Samsung, model: 'Gear VR' } } 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; SM-G920F Build/MMB29K) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/3.1.0 SamsungBrowser/4.0 Chrome/57.0.2987.146 Mobile VR Safari/537.36' 15 | readable: 'Oculus Browser 3.1 on a Samsung Gear VR running Android 6.0.1' 16 | result: { browser: { name: 'Oculus Browser', version: '3.1', type: browser }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: headset, manufacturer: Samsung, model: 'Gear VR' } } 17 | -------------------------------------------------------------------------------- /test/data/headset/device-glass.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.4.2; Glass 1 Build/XRV49) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36' 3 | result: { browser: { using: { name: 'Chromium WebView', version: '30' } }, engine: { name: Blink }, os: { family: Android }, device: { type: headset, manufacturer: Google, model: Glass } } 4 | readable: 'Chromium WebView 30 on a Google Glass' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.4.2; Glass 1 Build/XRX13B; XE22; 1511057; user; release-keys; 48cad1880fd0f82644ef86f5a7f6535b) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36' 7 | result: { browser: { using: { name: 'Chromium WebView', version: '30' } }, engine: { name: Blink }, os: { family: Android }, device: { type: headset, manufacturer: Google, model: Glass } } 8 | readable: 'Chromium WebView 30 on a Google Glass' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.0.4; xx; Glass 1 Build/IMM76L; XE10) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 11 | result: { engine: { name: Webkit, version: '534.30' }, os: { family: Android }, device: { type: headset, manufacturer: Google, model: Glass } } 12 | readable: 'a Google Glass' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.0.4; xx; Glass 1 Build/IMM76L; XE17) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 15 | result: { engine: { name: Webkit, version: '534.30' }, os: { family: Android }, device: { type: headset, manufacturer: Google, model: Glass } } 16 | readable: 'a Google Glass' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.0.4; xx; Glass 1 Build/XRT73B) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 19 | result: { engine: { name: Webkit, version: '534.30' }, os: { family: Android }, device: { type: headset, manufacturer: Google, model: Glass } } 20 | readable: 'a Google Glass' 21 | -------------------------------------------------------------------------------- /test/data/headset/device-oculus.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 7.1.2; Pacific Build/N2G48H) AppleWebKit/537.36 (KHTML, like Gecko) OculusBrowser/4.6.0.114370170 SamsungBrowser/4.0 Chrome/61.0.3163.141 Mobile VR Safari/537.36' 3 | readable: 'Oculus Browser 4.6 on an Oculus Go running Android 7.1.2' 4 | result: { browser: { name: 'Oculus Browser', version: '4.6', type: browser }, engine: { name: Blink }, os: { name: Android, version: 7.1.2 }, device: { type: headset, manufacturer: Oculus, model: 'Go' } } 5 | -------------------------------------------------------------------------------- /test/data/media/device-walkman.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (DigitalMediaPlayer; Walkman/NW-X1000 Series/1.00; like Gecko; wireless) NetFront/3.4' 3 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: media, manufacturer: Sony, model: 'NW-X1000 Walkman' } } 4 | readable: 'NetFront 3.4 on a Sony NW-X1000 Walkman' 5 | -------------------------------------------------------------------------------- /test/data/media/device-zune.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; Microsoft ZuneHD 4.5)', UA-OS: 'Windows CE (Pocket PC) - Version 6' } 3 | result: { browser: { name: 'Mobile Internet Explorer', version: '6.0', type: browser }, engine: { name: Trident }, device: { type: media, manufacturer: Microsoft, model: 'Zune HD' } } 4 | readable: 'Mobile Internet Explorer 6.0 on a Microsoft Zune HD' 5 | -------------------------------------------------------------------------------- /test/data/mobile/app-download.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; Le X526 Build/IIXOSOP5801607082S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36/TansoDL' 3 | readable: 'Tanso Download Manager on a LeEco Le 2 X526 running Android 6.0.1' 4 | result: { browser: { name: 'Tanso Download Manager', using: { name: 'Chromium WebView', version: '49' }, type: 'app:download' }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le 2 X526' } } -------------------------------------------------------------------------------- /test/data/mobile/app-media.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: stamhub 13082903.1.00.03/SM-N9005; 2013082903; 13082903.1.00.03; com.samsung.everglades.video; hlte; samsung/hltexx/hlte:4.3/JSS15J/N9005XXUBMJ1:user/release-keys' 3 | readable: 'Mediahub on a Samsung Galaxy Note 3 running Android 4.3' 4 | result: { browser: { name: Mediahub, type: 'app:mediaplayer' }, os: { name: Android, version: '4.3' }, device: { type: mobile, subtype: smart, manufacturer: Samsung, model: 'Galaxy Note 3' } } 5 | - 6 | headers: 'User-Agent: stamhub 1.7.0(MD02, 1113513)/SGH-T999; 606; 1.7.0(MD02, 1113513); com.samsung.mediahub; d2tmo; samsung/d2tmo/d2tmo:4.1.2/JZO54K/T999UVDMD5:user/release-keys' 7 | readable: 'Mediahub on a Samsung Galaxy S III running Android 4.1.2' 8 | result: { browser: { name: Mediahub, type: 'app:mediaplayer' }, os: { name: Android, version: 4.1.2 }, device: { type: mobile, subtype: smart, manufacturer: Samsung, model: 'Galaxy S III' } } 9 | -------------------------------------------------------------------------------- /test/data/mobile/app-news.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: YahooMobileWeather/1.0 (Android Weather; 1.2) (ME173X; asus; ME173X; 4.2.2/JDQ39)' 3 | result: { browser: { name: 'Yahoo Weather', version: '1.2', type: 'app:news' }, os: { name: Android, version: 4.2.2 }, device: { type: tablet, manufacturer: Asus, model: 'MeMO Pad HD 7 (ME173X)' } } 4 | readable: 'Yahoo Weather 1.2 on an Asus MeMO Pad HD 7 (ME173X) running Android 4.2.2' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; Le X820 Build/FEXCNFN5601304222S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36 Flipboard/3.4.13/2947,3.4.13.2947' 7 | readable: 'Flipboard 3.4.13 on a LeEco Le Max 2 X820 running Android 6.0.1' 8 | result: { browser: { name: Flipboard, using: { name: 'Chromium WebView', version: '49' }, version: 3.4.13, type: 'app:news' }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le Max 2 X820' } } -------------------------------------------------------------------------------- /test/data/mobile/app-search.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: YahooJMobileApp/1.1 (Android yjtop; 2.0.1) (samsung; SC-02C; samsung; SC-02C; 2.3.3/GINGERBREAD)' 3 | result: { browser: { name: 'Yahoo Mobile', version: 2.0.1, type: 'app:search' }, os: { name: Android, version: 2.3.3 }, device: { type: mobile, subtype: smart, manufacturer: Samsung, model: 'GALAXY S II SC-02C', carrier: DoCoMo } } 4 | readable: 'Yahoo Mobile 2.0.1 on a Samsung GALAXY S II SC-02C running Android 2.3.3' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; Le X527 Build/IMXOSOP5801910251S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36 YandexSearch/7.15' 7 | readable: 'Yandex Search 7.15 on a LeEco Le 2 X527 running Android 6.0.1' 8 | result: { browser: { name: 'Yandex Search', using: { name: 'Chromium WebView', version: '49' }, version: '7.15', type: 'app:search' }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le 2 X527' } } 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0.1; Le X526 Build/IIXOSOP5801910121S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36 BingWeb/6.4.25182938' 11 | readable: 'Bing Search 6.4.25182938 on a LeEco Le 2 X526 running Android 6.0.1' 12 | result: { browser: { name: 'Bing Search', using: { name: 'Chromium WebView', version: '49' }, version: 6.4.25182938, type: 'app:search' }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le 2 X526' } } 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 6.0; Le X620 Build/HEXCNFN5801708221S; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36 SogouSearch Android1.0 version3.0' 15 | readable: 'Sogou Search 3.0 on a LeEco Le 2 Pro X620 running Android 6.0' 16 | result: { browser: { name: 'Sogou Search', using: { name: 'Chromium WebView', version: '49' }, version: '3.0', type: 'app:search' }, engine: { name: Blink }, os: { name: Android, version: '6.0' }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le 2 Pro X620' } } -------------------------------------------------------------------------------- /test/data/mobile/app-shopping.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Groupon/2.10.3166 (Android 4.1.2; LGE Vee4ss / Lge LG-E440; )[preload=true;locale=de_DE;clientidbase=android-om-lge]' 3 | result: { browser: { name: Groupon, version: '2.10', type: 'app:shopping' }, os: { name: Android, version: 4.1.2 }, device: { type: mobile, subtype: smart, manufacturer: LG, model: 'Optimus L4 II' } } 4 | readable: 'Groupon 2.10 on a LG Optimus L4 II running Android 4.1.2' 5 | - 6 | headers: 'User-Agent: Groupon/2.10.3156 (Android 4.2.2; HTC Endeavoru / Htc HTC One X; O2 - de)[preload=false;locale=en_DE;clientidbase=android-htc-rev]' 7 | result: { browser: { name: Groupon, version: '2.10', type: 'app:shopping' }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, manufacturer: HTC, model: 'One X' } } 8 | readable: 'Groupon 2.10 on a HTC One X running Android 4.2.2' 9 | - 10 | headers: 'User-Agent: Groupon/2.10.3156 (Android 4.2.2; Samsung Jflte / Samsung GT-I9505; Telekom.de)[preload=true;locale=de_DE;clientidbase=android-samsung]' 11 | result: { browser: { name: Groupon, version: '2.10', type: 'app:shopping' }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, manufacturer: Samsung, model: 'Galaxy S4' } } 12 | readable: 'Groupon 2.10 on a Samsung Galaxy S4 running Android 4.2.2' 13 | -------------------------------------------------------------------------------- /test/data/mobile/browser-2345.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Mozilla/5.0 (Linux; U; Android 4.2.2; zh-cn; Galaxy Nexus Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/5.0 Mb2345Browser/4.0 Mobile Safari/534.30', X-Requested-With: com.browser2345 } 3 | result: { browser: { name: '2345 Browser', version: '4.0', type: browser }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, manufacturer: Samsung, model: 'Galaxy Nexus' } } 4 | readable: '2345 Browser 4.0 on a Samsung Galaxy Nexus running Android 4.2.2' 5 | - 6 | headers: { User-Agent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7', X-Requested-With: com.browser2345 } 7 | result: { browser: { name: '2345 Browser', type: browser }, engine: { name: Webkit, version: '532.9' }, os: { name: Android }, device: { type: mobile, subtype: smart } } 8 | readable: '2345 Browser on Android' 9 | -------------------------------------------------------------------------------- /test/data/mobile/browser-au.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: BIRD.S580 AU.Browser/1.2' 3 | result: { browser: { name: AU, version: '1.2', type: browser }, device: { type: mobile, subtype: feature, manufacturer: Bird, model: S580 } } 4 | readable: 'AU 1.2 on a Bird S580' 5 | - 6 | headers: 'User-Agent: LG-G3100 AU/4.10' 7 | result: { browser: { name: AU, version: '4.10', type: browser }, device: { type: mobile, subtype: feature, manufacturer: LG, model: G3100 } } 8 | readable: 'AU 4.10 on a LG G3100' 9 | - 10 | headers: 'User-Agent: LG-G1500 AU/4.2' 11 | result: { browser: { name: AU, version: '4.2', type: browser }, device: { type: mobile, subtype: feature, manufacturer: LG, model: G1500 } } 12 | readable: 'AU 4.2 on a LG G1500' 13 | - 14 | headers: 'User-Agent: LG-G4010 AU/4.12 UP.Link/1.1' 15 | result: { browser: { name: AU, version: '4.12', type: browser }, device: { type: mobile, subtype: feature, manufacturer: LG, model: G4010 } } 16 | readable: 'AU 4.12 on a LG G4010' 17 | - 18 | headers: 'User-Agent: LG-G5300i/JM AU/4.10 Profile/MIDP-1.0 Configuration/CLDC-1.0' 19 | result: { browser: { name: AU, version: '4.10', type: browser }, device: { type: mobile, subtype: feature, manufacturer: LG, model: G5300i } } 20 | readable: 'AU 4.10 on a LG G5300i' 21 | - 22 | headers: 'User-Agent: LG-G7070 AU/4.10 Profile/MIDP-1.0 Configuration/CLDC-1.0' 23 | result: { browser: { name: AU, version: '4.10', type: browser }, device: { type: mobile, subtype: feature, manufacturer: LG, model: G7070 } } 24 | readable: 'AU 4.10 on a LG G7070' 25 | -------------------------------------------------------------------------------- /test/data/mobile/browser-eui.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 6.0.1;en_us; Le X829 Build/FEXCNFN5902811088S) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/49.0.2623.91 Mobile Safari/537.36 EUI Browser/??????1.4.1.47' 3 | readable: 'EUI Browser 1.4 on a LeEco Le Max 2 X829 running Android 6.0.1' 4 | result: { browser: { name: 'EUI Browser', family: { name: Chrome, version: 49 }, version: '1.4', type: browser }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le Max 2 X829' } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 6.0.1;zh_cn; Le X829 Build/FIXNAOP5801911101S) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/49.0.0.0 Mobile Safari/537.36 EUI Browser/5.8.019S' 7 | readable: 'EUI Browser 5.8 on a LeEco Le Max 2 X829 running Android 6.0.1' 8 | result: { browser: { name: 'EUI Browser', using: { name: 'Chromium WebView', version: '49' }, version: '5.8', type: browser }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le Max 2 X829' } } 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 6.0.1;zh_cn; Le X820 Build/FEXCNFN5601405314S) AppleWebKit/537.36 (KHTML, like Gecko)Version/4.0 Chrome/49.0.0.0 Mobile Safari/537.36 EUI Browser/6.0' 11 | readable: 'EUI Browser 6.0 on a LeEco Le Max 2 X820 running Android 6.0.1' 12 | result: { browser: { name: 'EUI Browser', using: { name: 'Chromium WebView', version: '49' }, version: '6.0', type: browser }, engine: { name: Blink }, os: { name: Android, version: 6.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LeEco, model: 'Le Max 2 X820' } } -------------------------------------------------------------------------------- /test/data/mobile/browser-iris.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (U; Mobile; iPhone; PPC; xx; 320x320) AppleWebKit/525.18.1 (KHTML, like Gecko) WM5 Iris/1.1.9 Version/3.1.1 Mobile/5A345 Safari/525.20' 3 | result: { browser: { name: Iris, version: 1.1.9, type: browser }, engine: { name: Webkit, version: 525.18.1 }, os: { name: 'Windows Mobile', version: '5.0' }, device: { type: mobile, subtype: smart } } 4 | readable: 'Iris 1.1.9 on Windows Mobile 5.0' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (U; Mobile; iPhone; Smartphone; xx; 320x240) AppleWebKit/525.18.1 (KHTML, like Gecko) WM5 Iris/1.1.7 Version/3.1.1 Mobile/5A345 Safari/525.20' 7 | result: { browser: { name: Iris, version: 1.1.7, type: browser }, engine: { name: Webkit, version: 525.18.1 }, os: { name: 'Windows Mobile', version: '5.0' }, device: { type: mobile, subtype: smart } } 8 | readable: 'Iris 1.1.7 on Windows Mobile 5.0' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Windows NT; U; xx) AppleWebKit/522+ (KHTML, like Gecko) Iris/1.0.14 Safari/419.3' 11 | result: { browser: { name: Iris, version: 1.0.14, type: browser }, engine: { name: Webkit, version: '522' }, os: { name: 'Windows Mobile' }, device: { type: mobile, subtype: smart } } 12 | readable: 'Iris 1.0.14 on Windows Mobile' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Windows NT; U; xx) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Iris/1.1.8 Safari/525.20' 15 | result: { browser: { name: Iris, version: 1.1.8, type: browser }, engine: { name: Webkit, version: 525.18.1 }, os: { name: 'Windows Mobile' }, device: { type: mobile, subtype: smart } } 16 | readable: 'Iris 1.1.8 on Windows Mobile' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (Windows CE; U; Mobile; iPhone; PPC; en) AppleWebKit/522+ (KHTML, like Gecko) WM5 Iris/1.0.14 Safari/419.3' 19 | result: { browser: { name: Iris, version: 1.0.14, type: browser }, engine: { name: Webkit, version: '522' }, os: { name: 'Windows Mobile', version: '5.0' }, device: { type: mobile, subtype: smart } } 20 | readable: 'Iris 1.0.14 on Windows Mobile 5.0' 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; arm; en, Nuvi) AppleWebKit/523.13 (KHTML, like Gecko) Version/3.0 Mobile Safari/419.3 Qt Qtopia Iris/1.1.2' 23 | result: { browser: { name: Iris, version: 1.1.2, type: browser }, engine: { name: Webkit, version: '523.13' }, os: { name: Qtopia }, device: { type: gps, manufacturer: Garmin, model: Nuvi } } 24 | readable: 'Iris 1.1.2 on a Garmin Nuvi running Qtopia' 25 | -------------------------------------------------------------------------------- /test/data/mobile/browser-lg.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 5.0.1; LG-D802/V114 Build/LRX21Y) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/38.0.2125.102 Mobile Safari/537.36' 3 | result: { browser: { name: 'LG Browser', type: browser }, engine: { name: Blink }, os: { name: Android, version: 5.0.1 }, device: { type: mobile, subtype: smart, manufacturer: LG, model: G2 } } 4 | readable: 'LG Browser on a LG G2 running Android 5.0.1' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LG-D800/D80020y Build/KOT49I.D80020y) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.2 Chrome/30.0.1599.103 Mobile Safari/537.36' 7 | result: { browser: { name: 'LG Browser', type: browser }, engine: { name: Blink }, os: { name: Android, version: 4.4.2 }, device: { type: mobile, subtype: smart, manufacturer: LG, model: G2 } } 8 | readable: 'LG Browser on a LG G2 running Android 4.4.2' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.2; in-id; LG-D325 Build/KOT49I.A1407941488) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.1599.103 Mobile Safari/537.36' 11 | result: { browser: { name: 'LG Browser', type: browser }, engine: { name: Blink }, os: { name: Android, version: 4.4.2 }, device: { type: mobile, subtype: smart, manufacturer: LG, model: L70 } } 12 | readable: 'LG Browser on a LG L70 running Android 4.4.2' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.2; pl-pl; LG-D802 Build/KVT49L.A1412000029) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.1847.118 Mobile Safari/537.36' 15 | result: { browser: { name: 'LG Browser', type: browser }, engine: { name: Blink }, os: { name: Android, version: 4.4.2 }, device: { type: mobile, subtype: smart, manufacturer: LG, model: G2 } } 16 | readable: 'LG Browser on a LG G2 running Android 4.4.2' 17 | -------------------------------------------------------------------------------- /test/data/mobile/browser-mib.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: MOT-C168i/1.0 Release/13.07.2007 Browser/CMCS1.0 Software/2.350' 3 | result: { browser: { name: 'Motorola Internet Browser', version: '1.0', type: browser }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: C168i } } 4 | readable: 'Motorola Internet Browser 1.0 on a Motorola C168i' 5 | - 6 | headers: 'User-Agent: MOT-V730/1.0 MIB1.2/v1.0' 7 | result: { browser: { name: 'Motorola Internet Browser', version: '1.2', type: browser }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: V730 } } 8 | readable: 'Motorola Internet Browser 1.2 on a Motorola V730' 9 | -------------------------------------------------------------------------------- /test/data/mobile/browser-novarra.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7 MG (Novarra-Vision/6.1)', X-Device-User-Agent: 'Nokia6288/2.0 (05.94) Profile/MIDP-2.0 Configuration/CLDC-1.1' } 3 | result: { browser: { name: 'Novarra Vision', version: '6.1', type: browser }, engine: { name: Gecko, version: 1.8.0 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: '6288' } } 4 | readable: 'Novarra Vision 6.1 on a Nokia 6288' 5 | - 6 | headers: 'User-Agent: NokiaC1-01/2.0 (03.35) Profile/MIDP-2.1 Configuration/CLDC-1.1 Novarra-Vision/8.0' 7 | result: { browser: { name: 'Novarra Vision', version: '8.0', type: browser }, os: { name: Series40 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: C1-01 } } 8 | readable: 'Novarra Vision 8.0 on a Nokia C1-01 running Series40' 9 | - 10 | headers: 'User-Agent: Nokia6600/1.0 (5.53.0) SymbianOS/7.0s Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0 Novarra-Vision/7.3' 11 | result: { browser: { name: 'Novarra Vision', version: '7.3', type: browser }, os: { name: Series60, family: { name: Symbian, version: '7.0' }, version: '2.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: '6600' } } 12 | readable: 'Novarra Vision 7.3 on a Nokia 6600 running Series60 2.0' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (X11; Linux i686; U; en-US) Gecko/20081217 Vision-Browser/8.1 301x200 LG VN530' 15 | result: { browser: { name: 'Novarra Vision', version: '8.1', type: browser }, engine: { name: Gecko }, os: { name: Brew }, device: { type: mobile, subtype: feature, manufacturer: LG, model: Octane } } 16 | readable: 'Novarra Vision 8.1 on a LG Octane running Brew' 17 | -------------------------------------------------------------------------------- /test/data/mobile/browser-polaris.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: SCH-S239/ POLARIS/6.15 (GUI; compatible; UP.Browser)' 3 | result: { browser: { name: Polaris, version: '6.15', type: browser }, device: { type: mobile, subtype: feature, manufacturer: Samsung, model: SCH-S239 } } 4 | readable: 'Polaris 6.15 on a Samsung SCH-S239' 5 | - 6 | headers: 'User-Agent: SCH-W279/ POLARIS/6.2 (GUI; compatible; UP.Browser)' 7 | result: { browser: { name: Polaris, version: '6.2', type: browser }, device: { type: mobile, subtype: feature, manufacturer: Samsung, model: 'Primo Duos' } } 8 | readable: 'Polaris 6.2 on a Samsung Primo Duos' 9 | -------------------------------------------------------------------------------- /test/data/mobile/browser-skyfire.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; xx) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/2.0' 3 | result: { browser: { name: Skyfire, version: '2.0', type: browser }, engine: { name: Webkit, version: '530.17' }, os: { name: Android }, device: { type: mobile, subtype: smart } } 4 | readable: 'Skyfire 2.0 on Android' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_7; xx) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Safari/530.17 Skyfire/6DE' 7 | result: { browser: { name: Skyfire, version: '6', type: browser }, engine: { name: Webkit, version: '530.17' }, os: { name: Android }, device: { type: mobile, subtype: smart } } 8 | readable: 'Skyfire 6 on Android' 9 | - 10 | headers: 'User-Agent: Skyfire/5.0.1 (Linux; U; Android 4.1.2; xx; PlayBook Build/jelly bean) AppleWebKit/535.1+ (KHTML, like Gecko) Version/7.2.0.0 Safari/535.19' 11 | result: { browser: { name: Skyfire, version: 5.0.1, type: browser }, engine: { name: Webkit, version: '535.1' }, os: { name: Android }, device: { type: mobile, subtype: smart, manufacturer: RIM, model: 'BlackBerry PlayBook' } } 12 | readable: 'Skyfire 5.0.1 on a RIM BlackBerry PlayBook running Android' 13 | -------------------------------------------------------------------------------- /test/data/mobile/device-kin.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; en-US; KIN.One 1.0)' 3 | result: { browser: { name: 'Mobile Internet Explorer', version: '6.0', type: browser }, engine: { name: Trident }, os: { name: 'Kin OS', version: '1.0' }, device: { type: mobile, subtype: smart, manufacturer: Microsoft, model: 'Kin ONE' } } 4 | readable: 'Mobile Internet Explorer 6.0 on a Microsoft Kin ONE running Kin OS 1.0' 5 | - 6 | headers: 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 6.12; en-US; KIN.Two 1.0)' 7 | result: { browser: { name: 'Mobile Internet Explorer', version: '6.0', type: browser }, engine: { name: Trident }, os: { name: 'Kin OS', version: '1.0' }, device: { type: mobile, subtype: smart, manufacturer: Microsoft, model: 'Kin TWO' } } 8 | readable: 'Mobile Internet Explorer 6.0 on a Microsoft Kin TWO running Kin OS 1.0' 9 | -------------------------------------------------------------------------------- /test/data/mobile/engine-servo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Android; Mobile; rv:37.0) Servo/1.0 Firefox/37.0' 3 | result: { browser: { name: 'Servo Nightly Build', type: browser }, engine: { name: Servo, version: '1.0' }, os: { name: Android }, device: { type: mobile, subtype: smart } } 4 | readable: 'Servo Nightly Build on Android' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Mobile; rv:37.0) Servo/1.0 Firefox/37.0' 7 | result: { browser: { name: 'Servo Nightly Build', type: browser }, engine: { name: Servo, version: '1.0' }, os: { name: 'Firefox OS' }, device: { type: mobile, subtype: smart } } 8 | readable: 'Servo Nightly Build on Firefox OS' 9 | -------------------------------------------------------------------------------- /test/data/mobile/manufacturer-nokia-asha.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Series40; Nokia501.1/14.0.4/java_runtime_version=Nokia_Asha_1_2; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/4.0.0.0.45' 3 | result: { browser: { name: 'Nokia Xpress', version: 4.0.0, type: browser }, engine: { name: Gecko }, os: { name: 'Nokia Asha Platform', version: '1.2' }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 'Asha 501' } } 4 | readable: 'Nokia Xpress 4.0.0 on a Nokia Asha 501 running Nokia Asha Platform 1.2' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Series40; Nokia502/11.1.1/java_runtime_version=Nokia_Asha_1_1_1; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/3.1.1.0.27' 7 | result: { browser: { name: 'Nokia Xpress', version: 3.1.1, type: browser }, engine: { name: Gecko }, os: { name: 'Nokia Asha Platform', version: 1.1.1 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 'Asha 502' } } 8 | readable: 'Nokia Xpress 3.1.1 on a Nokia Asha 502 running Nokia Asha Platform 1.1.1' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Series40; Nokia503/0.1402.11/java_runtime_version=Nokia_Asha_1_1_1; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/4.0.0.0.17' 11 | result: { browser: { name: 'Nokia Xpress', version: 4.0.0, type: browser }, engine: { name: Gecko }, os: { name: 'Nokia Asha Platform', version: 1.1.1 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 'Asha 503' } } 12 | readable: 'Nokia Xpress 4.0.0 on a Nokia Asha 503 running Nokia Asha Platform 1.1.1' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Series40; NokiaAsha230DualSIM/13.5.2/java_runtime_version=Nokia_Asha_1_1_1; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/3.1.1.0.27' 15 | result: { browser: { name: 'Nokia Xpress', version: 3.1.1, type: browser }, engine: { name: Gecko }, os: { name: 'Nokia Asha Platform', version: 1.1.1 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 'Asha 230' } } 16 | readable: 'Nokia Xpress 3.1.1 on a Nokia Asha 230 running Nokia Asha Platform 1.1.1' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (Series40; NokiaAsha500DualSIM/13.0.6/java_runtime_version=Nokia_Asha_1_1_1; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/3.1.1.0.27' 19 | result: { browser: { name: 'Nokia Xpress', version: 3.1.1, type: browser }, engine: { name: Gecko }, os: { name: 'Nokia Asha Platform', version: 1.1.1 }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 'Asha 500' } } 20 | readable: 'Nokia Xpress 3.1.1 on a Nokia Asha 500 running Nokia Asha Platform 1.1.1' 21 | -------------------------------------------------------------------------------- /test/data/mobile/manufacturer-siemens.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: SIE-3118' 3 | readable: 'a Siemens 3118' 4 | result: { device: { type: mobile, subtype: feature, manufacturer: Siemens, model: '3118' } } 5 | - 6 | headers: 'User-Agent: SIE-6618' 7 | readable: 'a Siemens 6618' 8 | result: { device: { type: mobile, subtype: feature, manufacturer: Siemens, model: '6618' } } 9 | -------------------------------------------------------------------------------- /test/data/mobile/os-baiduyi.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: MQQBrowser/1.0 Mozilla/5.0 (Linux; U; Android 2.3.4; xx; Baidu Yi on Passion Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Mobile Safari/533.1 Aurora/10' 3 | result: { browser: { name: 'QQ Browser', version: '1.0', type: browser }, engine: { name: Webkit, version: '533.1' }, os: { name: 'Baidu Yi', family: Android }, device: { type: mobile, subtype: smart, manufacturer: HTC, model: 'Nexus One' } } 4 | readable: 'QQ Browser 1.0 on a HTC Nexus One running Baidu Yi' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.4; xx; Baidu Yi on Passion Build/GRJ22) AppleWebKit/530.17 (KHTML, like Gecko) FlyFlow/2.4 Version/4.0 Mobile Safari/530.17 baidubrowser/042_9.0.4.2_diordna_008_084/CTH_01_4.3.2_noissaP-no-iY-udiaB/1200a/556D6BBE7792DA7' 7 | result: { browser: { name: 'Baidu Browser', version: '2.4', type: browser }, engine: { name: Webkit, version: '530.17' }, os: { name: 'Baidu Yi', family: Android }, device: { type: mobile, subtype: smart, manufacturer: HTC, model: 'Nexus One' } } 8 | readable: 'Baidu Browser 2.4 on a HTC Nexus One running Baidu Yi' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.4; xx; Baidu Yi on Passion Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) FlyFlow/2.2 Version/4.0 Mobile Safari/533.1' 11 | result: { browser: { name: 'Baidu Browser', version: '2.2', type: browser }, engine: { name: Webkit, version: '533.1' }, os: { name: 'Baidu Yi', family: Android }, device: { type: mobile, subtype: smart, manufacturer: HTC, model: 'Nexus One' } } 12 | readable: 'Baidu Browser 2.2 on a HTC Nexus One running Baidu Yi' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.4; xx; Baidu Yi on Passion Build/GRJ22) AppleWebKit/534.31 (KHTML, like Gecko) UCBrowser/8.8.1.258 U3/0.8.0 Mobile Safari/534.31' 15 | result: { browser: { name: 'UC Browser', version: '8.8', type: browser }, engine: { name: Webkit, version: '534.31' }, os: { name: 'Baidu Yi', family: Android }, device: { type: mobile, subtype: smart, manufacturer: HTC, model: 'Nexus One' } } 16 | readable: 'UC Browser 8.8 on a HTC Nexus One running Baidu Yi' 17 | -------------------------------------------------------------------------------- /test/data/mobile/os-ezxlinux.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: MOT-A1200e/1.0 LinuxOS/2.4.20 Release/1.31.2007 Browser/Opera8.00 Profile/MIDP-2.0 Configuration/CLDC-1.1 Software/R541_G_11.56.11R' 3 | result: { browser: { name: 'Opera Mobile', version: '8.00', type: browser }, engine: { name: Presto }, os: { name: 'EZX Linux' }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: A1200e } } 4 | readable: 'Opera Mobile 8.00 on a Motorola A1200e running EZX Linux' 5 | - 6 | headers: 'User-Agent: MOT-A1200r/1.0 LinuxOS/2.4.20 Release/8.22.2006 Browser/Opera8.00 Profile/MIDP-2.0 Configuration/CLDC-1.1 Software/R541_G_11.52.08R' 7 | result: { browser: { name: 'Opera Mobile', version: '8.00', type: browser }, engine: { name: Presto }, os: { name: 'EZX Linux' }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: A1200r } } 8 | readable: 'Opera Mobile 8.00 on a Motorola A1200r running EZX Linux' 9 | - 10 | headers: 'User-Agent: MOT-A1200r/1.0 LinuxOS/2.4.20 Release/8.22.2006 Browser/Opera8.00 Profile/MIDP-2.0 Configuration/CLDC-1.1 Software/R541_G_11.52.13R' 11 | result: { browser: { name: 'Opera Mobile', version: '8.00', type: browser }, engine: { name: Presto }, os: { name: 'EZX Linux' }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: A1200r } } 12 | readable: 'Opera Mobile 8.00 on a Motorola A1200r running EZX Linux' 13 | - 14 | headers: 'User-Agent: MOT-A1600/1.0 LinuxOS/2.4.20 Release/8.22.2006 Browser/Opera8.00 Profile/MIDP-2.0 Configuration/CLDC-1.1 Software/R542_G_11.61.33R' 15 | result: { browser: { name: 'Opera Mobile', version: '8.00', type: browser }, engine: { name: Presto }, os: { name: 'EZX Linux' }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: A1600 } } 16 | readable: 'Opera Mobile 8.00 on a Motorola A1600 running EZX Linux' 17 | - 18 | headers: 'User-Agent: MOTO-W760r/Mozilla/4.0 (compatible;MSIE 6.0;Linux W760r)/R63712_U_71.xx.yyI Profile/MIDP-2.0 Configuration/CLDC-1.1 Symphony 1.0' 19 | readable: 'Symphony 1.0 on a Motorola W760r running Linux' 20 | result: { browser: { name: Symphony, version: '1.0', type: browser }, os: { name: Linux }, device: { type: mobile, subtype: feature, manufacturer: Motorola, model: W760r } } 21 | -------------------------------------------------------------------------------- /test/data/mobile/os-fireos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.4.4; SD4930UR Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.0.0 Mobile Safari/537.36' 3 | result: { browser: { using: 'Amazon WebView' }, engine: { name: Blink }, os: { name: FireOS, family: Android }, device: { type: mobile, subtype: smart, manufacturer: Amazon, model: 'Fire Phone' } } 4 | readable: 'Amazon WebView on an Amazon Fire Phone running FireOS' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Silk/1.0.13.81_10003810) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 Silk-Accelerated=true' 7 | result: { browser: { name: Silk, version: '1.0', type: browser }, engine: { name: Webkit, version: '533.1' }, os: { name: FireOS, family: Android }, device: { type: tablet, manufacturer: Amazon, model: 'Kindle Fire' } } 8 | readable: 'Silk 1.0 on an Amazon Kindle Fire running FireOS' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.2.2; xx; SD4930UR Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Silk/3.29 like Chrome/34.0.1847.137 Mobile Safari/537.36' 11 | result: { browser: { name: Silk, family: { name: Chrome, version: 34 }, version: '3.29', type: browser }, engine: { name: Blink }, os: { name: FireOS, family: Android, version: '3' }, device: { type: mobile, subtype: smart, manufacturer: Amazon, model: 'Fire Phone' } } 12 | readable: 'Silk 3.29 on an Amazon Fire Phone running FireOS 3' 13 | -------------------------------------------------------------------------------- /test/data/mobile/os-geos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Nokia-Communicator-WWW-Browser/2.0 (Geos 3.0 Nokia-9000i)' 3 | result: { browser: { name: 'Nokia Browser', version: '2.0', type: browser }, os: { name: GEOS, version: '3.0' }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: 9000i } } 4 | readable: 'Nokia Browser 2.0 on a Nokia 9000i running GEOS 3.0' 5 | - 6 | headers: 'User-Agent: Nokia-Communicator-WWW-Browser/3.0 (Geos 3.0 Nokia-9110)' 7 | result: { browser: { name: 'Nokia Browser', version: '3.0', type: browser }, os: { name: GEOS, version: '3.0' }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: '9110' } } 8 | readable: 'Nokia Browser 3.0 on a Nokia 9110 running GEOS 3.0' 9 | -------------------------------------------------------------------------------- /test/data/mobile/os-harmony.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 10; HarmonyOS; DVC-AN20; HMSCore 6.4.0.312) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.105 HuaweiBrowser/12.0.1.302 Mobile Safari/537.36' 3 | readable: 'Huawei Browser 12.0 on a Huawei Enjoy 20 Pro running Harmony OS' 4 | result: { browser: { name: 'Huawei Browser', family: { name: Chrome, version: 92 }, version: '12.0', type: browser }, engine: { name: Blink }, os: { name: 'Harmony OS', family: { name: Android, version: 10 } }, device: { type: mobile, subtype: smart, manufacturer: Huawei, model: 'Enjoy 20 Pro' } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 10; HarmonyOS; HLK-AL00; HMSCore 6.3.0.327; GMSCore 21.33.14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.105 HuaweiBrowser/12.0.0.303 Mobile Safari/537.36' 7 | readable: 'Huawei Browser 12.0 on a Huawei Honor 9X running Harmony OS' 8 | result: { browser: { name: 'Huawei Browser', family: { name: Chrome, version: 92 }, version: '12.0', type: browser }, engine: { name: Blink }, os: { name: 'Harmony OS', family: { name: Android, version: 10 } }, device: { type: mobile, subtype: smart, manufacturer: Huawei, model: 'Honor 9X' } } -------------------------------------------------------------------------------- /test/data/mobile/os-limo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: SAMSUNG-GT-I6410-Vodafone/I6410BUJB7 Linux/X2/R1 Opera/9.6 SMS-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1' 3 | result: { browser: { name: 'Opera Mobile', version: '9.6', type: browser }, engine: { name: Presto }, os: { name: LiMo }, device: { type: mobile, subtype: feature, manufacturer: Vodafone, model: '360 M1' } } 4 | readable: 'Opera Mobile 9.6 on a Vodafone 360 M1 running LiMo' 5 | - 6 | headers: 'User-Agent: SAMSUNG-GT-I8320-Vodafone/I8320BUJC1 Linux/X2/R1 Opera/9.6 SMS-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1' 7 | result: { browser: { name: 'Opera Mobile', version: '9.6', type: browser }, engine: { name: Presto }, os: { name: LiMo }, device: { type: mobile, subtype: feature, manufacturer: Vodafone, model: '360 H1' } } 8 | readable: 'Opera Mobile 9.6 on a Vodafone 360 H1 running LiMo' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-I9200/1.0; U; Linux/SLP/2.0; xx) AppleWebKit/534.4 (KHTML, like Gecko) Dolfin/2.0 Mobile' 11 | result: { browser: { name: Dolfin, version: '2.0', type: browser }, engine: { name: Webkit, version: '534.4' }, os: { name: 'Linux SLP', version: '2.0' }, device: { type: mobile, subtype: feature, manufacturer: Samsung, model: GT-I9200 } } 12 | readable: 'Dolfin 2.0 on a Samsung GT-I9200 running Linux SLP 2.0' 13 | -------------------------------------------------------------------------------- /test/data/mobile/os-s30.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Series30Plus; Nokia220/13.00.11; Profile/Series30Plus Configuration/Series30Plus) Gecko/20100401 S40OviBrowser/3.8.1.0.5' 3 | result: { browser: { name: 'Nokia Xpress', version: 3.8.1, type: browser }, engine: { name: Gecko }, os: { name: Series30+ }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: '220' } } 4 | readable: 'Nokia Xpress 3.8.1 on a Nokia 220 running Series30+' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Series30Plus; Nokia225/20.06.17; Profile/Series30Plus Configuration/Series30Plus) Gecko/20100401 S40OviBrowser/3.8.1.2.3005' 7 | result: { browser: { name: 'Nokia Xpress', version: 3.8.1, type: browser }, engine: { name: Gecko }, os: { name: Series30+ }, device: { type: mobile, subtype: feature, manufacturer: Nokia, model: '225' } } 8 | readable: 'Nokia Xpress 3.8.1 on a Nokia 225 running Series30+' 9 | -------------------------------------------------------------------------------- /test/data/mobile/os-s80.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9300/05.22 Profile/MIDP-2.0 Configuration/CLDC-1.1)' 3 | result: { os: { name: Series80, family: Symbian, version: '2.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: '9300' } } 4 | readable: 'a Nokia 9300 running Series80 2.0' 5 | - 6 | headers: 'User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Series80/2.0 Nokia9300i Profile/MIDP-2.0 Configuration/CLDC-1.1)' 7 | readable: 'a Nokia 9300i running Series80 2.0' 8 | result: { os: { name: Series80, family: Symbian, version: '2.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: 9300i } } 9 | - 10 | headers: 'User-Agent: Mozilla/4.0 (compatible, MSIE 5.0; Series80/2.0 Nokia9500/4.51 Profile/MIDP-2.0 Configuration/CLDC-1.1)' 11 | readable: 'a Nokia 9500 running Series80 2.0' 12 | result: { os: { name: Series80, family: Symbian, version: '2.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: '9500' } } 13 | - 14 | headers: 'User-Agent: EPOC32-WTL/2.2 Crystal/6.0 STNC-WTL/6.0(611)' 15 | readable: 'STNC HitchHiker on a Nokia 9210 running Series80 1.0' 16 | result: { browser: { name: 'STNC HitchHiker', type: browser }, os: { name: Series80, family: { name: Symbian, version: '6.0' }, version: '1.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: '9210' } } 17 | - 18 | headers: 'User-Agent: Mozilla/4.1 (compatible; MSIE 5.0; EPOC) Opera 6.0 [de]Nokia/Series-9200' 19 | readable: 'Opera Mobile 6.0 on a Nokia 9210i running Series80 1.0' 20 | result: { browser: { name: 'Opera Mobile', version: '6.0', type: browser }, engine: { name: Electra }, os: { name: Series80, family: Symbian, version: '1.0' }, device: { type: mobile, subtype: smart, manufacturer: Nokia, model: 9210i } } 21 | -------------------------------------------------------------------------------- /test/data/mobile/os-spreadtrum.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Opera/9.80 (SpreadTrum; Opera Mini/4.4.29625/34.1970; U; xx) Presto/2.8.119 Version/11.10', X-OperaMini-Phone: '? # ?', X-OperaMini-Phone-UA: 'NativeOperaMini(Spreadtrum/Unknown;Native Opera Mini/4.4.29625;pt)', X-OperaMini-Features: 'httpping, advanced, routing, folding, file_system, download', Device-Stock-UA: 'NativeOperaMini(Spreadtrum/Unknown;Native Opera Mini/4.4.29625;pt)' } 3 | result: { browser: { name: 'Opera Mini', version: '4.4', type: browser }, engine: { name: Presto, version: 2.8.119 }, os: { name: SpreadTrum }, device: { type: mobile, subtype: feature } } 4 | readable: 'Opera Mini 4.4 on SpreadTrum' 5 | - 6 | headers: { User-Agent: 'Opera/9.80 (SpreadTrum; Opera Mini/4.4.31227/34.1088; U; xx) Presto/2.8.119 Version/11.10', Device-Stock-UA: 'NativeOperaMini(Spreadtrum/HW Version: SC6531_OPENPHONE;Native Opera Mini/4.4.31227;en)', X-OperaMini-Phone-UA: 'NativeOperaMini(Spreadtrum/HW Version: SC6531_OPENPHONE;Native Opera Mini/4.4.31227;en)', X-OperaMini-Phone: '? # ?', X-OperaMini-Features: 'advanced, httpping, routing, file_system, download, folding' } 7 | result: { browser: { name: 'Opera Mini', version: '4.4', type: browser }, engine: { name: Presto, version: 2.8.119 }, os: { name: SpreadTrum }, device: { type: mobile, subtype: feature } } 8 | readable: 'Opera Mini 4.4 on SpreadTrum' 9 | -------------------------------------------------------------------------------- /test/data/mobile/os-threadx.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: HUAWEI T1201_TD/1.0 ThreadX_OS/04.00 SC8800H/S4 Release/6.17.2010 Browser/NetFont-3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1' 3 | result: { browser: { name: NetFront, version: '3.5', type: browser }, engine: { name: NetFront }, os: { name: ThreadX, version: '04.00' }, device: { type: mobile, subtype: feature, manufacturer: Huawei, model: T1201 } } 4 | readable: 'NetFront 3.5 on a Huawei T1201 running ThreadX 04.00' 5 | - 6 | headers: 'User-Agent: PhilipsX2300/W1245_V12 ThreadX_OS/4.0 MOCOR/W12 Release/11.08.2012 Browser/Dorado1.0' 7 | result: { browser: { name: 'Dorado WAP', version: '1.0', type: browser }, os: { name: ThreadX, version: '4.0' }, device: { type: mobile, subtype: feature, manufacturer: Philips, model: X2300 } } 8 | readable: 'Dorado WAP 1.0 on a Philips X2300 running ThreadX 4.0' 9 | - 10 | headers: { User-Agent: 'Opera/9.80 (J2ME/MIDP; Opera Mini/4.5.33867/35.3088; U; xx) Presto/2.8.119 Version/11.10', X-OperaMini-Phone: '? # ?', X-OperaMini-Phone-UA: 'PhilipsX2300/W1245_V12 ThreadX_OS/4.0 MOCOR/W12 Release/11.08.2012 Browser/Dorado1.0', X-OperaMini-Features: 'advanced, httpping, routing, folding, file_system', Device-Stock-UA: 'PhilipsX2300/W1245_V12 ThreadX_OS/4.0 MOCOR/W12 Release/11.08.2012 Browser/Dorado1.0' } 11 | result: { browser: { name: 'Opera Mini', version: '4.5', type: browser }, engine: { name: Presto, version: 2.8.119 }, os: { name: ThreadX, version: '4.0' }, device: { type: mobile, subtype: feature, manufacturer: Philips, model: X2300 } } 12 | readable: 'Opera Mini 4.5 on a Philips X2300 running ThreadX 4.0' 13 | -------------------------------------------------------------------------------- /test/data/mobile/os-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Ubuntu 14.04 like Android 4.4) AppleWebKit/537.36 Chromium/35.0.1870.2 Mobile Safari/537.36' 3 | result: { browser: { family: { name: Chrome, version: 35 } }, engine: { name: Blink }, os: { name: 'Ubuntu Touch', version: '14.04' }, device: { type: mobile, subtype: smart } } 4 | readable: 'Ubuntu Touch 14.04' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Ubuntu; Mobile) WebKit/537.36' 7 | result: { engine: { name: Webkit, version: '537.36' }, os: { name: 'Ubuntu Touch' }, device: { type: mobile, subtype: smart } } 8 | readable: 'Ubuntu Touch' 9 | -------------------------------------------------------------------------------- /test/data/mobile/os-vre.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Opera/9.80 (VRE; Opera Mini/4.2/32.1312; U; xx) Presto/2.8.119 Version/11.10', X-OperaMini-Phone-UA: ReksioVRE(196683), X-OperaMini-Phone: '? # ?', X-OperaMini-Features: 'httpping, advanced, folding, file_system, download', Device-Stock-UA: ReksioVRE(196683) } 3 | result: { browser: { name: 'Opera Mini', version: '4.2', type: browser }, engine: { name: Presto, version: 2.8.119 }, os: { name: VRE }, device: { type: mobile, subtype: feature } } 4 | readable: 'Opera Mini 4.2 on VRE' 5 | -------------------------------------------------------------------------------- /test/data/mobile/os-wophone.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: TCL_J720/1.0 WoPhone/1.0 UPhone/1.0 Browser/UPhoneWebBrowser1.0 Profile/MIDP-1.0 Configuration/CLDC-1.0 Mozilla/5.0+(Linux;+U;+UPhone+TOPS+1.0UPhone+TOPS+1.0;+zh-cn;+Android+9.8)+AppleWebKit/532.9++UPhoneWebKit/532.9++(KHTML, like Gecko)+Mobile+Safari/532.9+' 3 | result: { engine: { name: Webkit, version: '532.9' }, os: { name: WoPhone, family: Android, version: '1.0' }, device: { type: mobile, subtype: smart, manufacturer: TCL, model: J720 } } 4 | readable: 'a TCL J720 running WoPhone 1.0' 5 | - 6 | headers: 'User-Agent: TOPS/1.0 WoPhone/1.0 UPhone/1.0 Browser/UPhoneWebBrowser1.0 Profile/MIDP-1.0 Configuration/CLDC-1.0 Mozilla/5.0+(Linux;+U;+UPhone+TOPS+1.0UPhone+TOPS+1.0;+zh-cn;+Android+9.8)+AppleWebKit/532.9++UPhoneWebKit/532.9++(KHTML, like Gecko)+Mobile+Safari/532.9+' 7 | result: { engine: { name: Webkit, version: '532.9' }, os: { name: WoPhone, family: Android, version: '1.0' }, device: { type: mobile, subtype: smart } } 8 | readable: 'WoPhone 1.0' 9 | -------------------------------------------------------------------------------- /test/data/mobile/platform-air.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (iOS; U; en) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/13.0' 3 | readable: 'AdobeAIR 13.0 on iOS' 4 | result: { browser: { using: { name: AdobeAIR, version: '13.0' } }, engine: { name: Webkit, version: 533.19.4 }, os: { name: iOS }, device: { type: mobile, subtype: smart, manufacturer: Apple } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (iOS; U; en-GB) AppleWebKit/533.19.4 (KHTML, like Gecko) AdobeAIR/13.0' 7 | readable: 'AdobeAIR 13.0 on iOS' 8 | result: { browser: { using: { name: AdobeAIR, version: '13.0' } }, engine: { name: Webkit, version: 533.19.4 }, os: { name: iOS }, device: { type: mobile, subtype: smart, manufacturer: Apple } } 9 | -------------------------------------------------------------------------------- /test/data/other/reported.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.2.2; KENEKSI Build/JDQ39; ru-ru) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Mobile Safari/537.36 Puffin/6.1.4.16005AP' 3 | readable: 'Puffin 6.1.4 on a KENEKSI running Android 4.2.2' 4 | result: { browser: { name: Puffin, family: { name: Chrome, version: 42 }, version: 6.1.4, type: browser }, engine: { name: Blink }, os: { name: Android, version: 4.2.2 }, device: { type: mobile, subtype: smart, model: KENEKSI } } -------------------------------------------------------------------------------- /test/data/other/xmlhttprequest.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: { User-Agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36', X-Requested-With: XMLHttpRequest } 3 | readable: 'Chrome 52 on OS X El Capitan 10.11' 4 | result: { browser: { name: Chrome, version: '52', type: browser }, engine: { name: Blink }, os: { name: 'OS X', version: { value: '10.11', nickname: 'El Capitan' } }, device: { type: desktop, manufacturer: Apple, model: Macintosh } } 5 | -------------------------------------------------------------------------------- /test/data/pda/airboard.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.0 (LocationFreeTV; Airboard/LF-X5) NetFront/3.0' 3 | result: { browser: { name: NetFront, version: '3.0', type: browser }, engine: { name: NetFront }, device: { type: pda, manufacturer: Sony, model: 'Airboard LF-X5' } } 4 | readable: 'NetFront 3.0 on a Sony Airboard LF-X5' 5 | - 6 | headers: 'User-Agent: Mozilla/3.0 airboard 1.0 (BrowserInfo Screen=800x600x64K;InputMethod=PEN;Page=1M;Category=Personal IT Television;CPU=R4000;Storage=8M;Product=SONY/airboard/IDT-LF1;HTML-Level=3.2;Language=ja.SJIS;)' 7 | result: { device: { type: pda, manufacturer: Sony, model: 'Airboard LF1' } } 8 | readable: 'a Sony Airboard LF1' 9 | - 10 | headers: 'User-Agent: Mozilla/3.0 airboard 1.0 (BrowserInfo Screen=800x600x64K;InputMethod=PEN;Page=1M;Category=Personal IT Television;CPU=R4000;Storage=8M;Product=SONY/airboard/IDT-LF3;HTML-Level=3.2;Language=ja.SJIS;)' 11 | result: { device: { type: pda, manufacturer: Sony, model: 'Airboard LF3' } } 12 | readable: 'a Sony Airboard LF3' 13 | - 14 | headers: 'User-Agent: Mozilla/3.0 airboard 1.0 (BrowserInfo Screen=800x600x64K;InputMethod=PEN;Page=1M;Category=Personal IT Television;CPU=R4000;Storage=8M;Product=SONY/airboard/IDT-NS1P;HTML-Level=3.2;Language=ja.SJIS;)' 15 | result: { device: { type: pda, manufacturer: Sony, model: 'Airboard NS1P' } } 16 | readable: 'a Sony Airboard NS1P' 17 | -------------------------------------------------------------------------------- /test/data/pda/casio.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.5 (Screen=240x320x64K; InputMethod=PEN; Page=1M; Product=CASIO/CASSIOPEIA BE; HTML-level=3.2; Category=PDA; JavaScript=yes) (WorldTALK/2.2.24)' 3 | result: { device: { type: pda, manufacturer: Casio, model: Cassiopeia } } 4 | readable: 'a Casio Cassiopeia' 5 | - 6 | headers: 'User-Agent: Mozilla/4.5 (Screen=320x240x64K; InputMethod=KEYBOARD; Page=1M; Product=CASIO/PPP101; HTML-level=3.2; Category=PDA)(WorldTALK/2.0.0),1' 7 | result: { device: { type: pda, manufacturer: Casio, model: 'Pocket PostPet', carrier: DoCoMo } } 8 | readable: 'a Casio Pocket PostPet' 9 | -------------------------------------------------------------------------------- /test/data/pda/generic.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.08 (PDA; NF32PPC3AR/1.01) NetFront/3.2' 3 | result: { browser: { name: NetFront, version: '3.2', type: browser }, engine: { name: NetFront }, device: { type: pda } } 4 | readable: 'NetFront 3.2' 5 | - 6 | headers: 'User-Agent: Mozilla/4.08 (PDA; NF33PPC3AR/1.0) NetFront/3.3' 7 | result: { browser: { name: NetFront, version: '3.3', type: browser }, engine: { name: NetFront }, device: { type: pda } } 8 | readable: 'NetFront 3.3' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (PDA; NF35WMPRO/1.0; like Gecko) NetFront/3.5' 11 | result: { browser: { name: NetFront, version: '3.5', type: browser }, engine: { name: NetFront }, os: { name: 'Windows Mobile' }, device: { type: pda } } 12 | readable: 'NetFront 3.5 on Windows Mobile' 13 | - 14 | headers: 'User-Agent: Mozilla/4.0 (PDA; Windows CE/1.0.1) NetFront/3.0' 15 | result: { browser: { name: NetFront, version: '3.0', type: browser }, engine: { name: NetFront }, os: { name: 'Windows CE' }, device: { type: pda } } 16 | readable: 'NetFront 3.0 on Windows CE' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (PDA; NF34PPC/1.0; like Gecko) NetFront/3.4' 19 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, os: { name: 'Windows Mobile' }, device: { type: pda } } 20 | readable: 'NetFront 3.4 on Windows Mobile' 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (PDA; NF41WMPRO/1.0; like Gecko) NetFront/4.1' 23 | result: { browser: { name: NetFront, version: '4.1', type: browser }, engine: { name: NetFront }, os: { name: 'Windows Mobile' }, device: { type: pda } } 24 | readable: 'NetFront 4.1 on Windows Mobile' 25 | - 26 | headers: 'User-Agent: Mozilla/5.0 (PDA; NF35WMPRO/3.2; like Gecko) NetFront/3.5 T-01A_6.5' 27 | result: { browser: { name: NetFront, version: '3.5', type: browser }, engine: { name: NetFront }, os: { name: 'Windows Mobile' }, device: { type: pda, manufacturer: Toshiba, model: T-01A, carrier: DoCoMo } } 28 | readable: 'NetFront 3.5 on a Toshiba T-01A running Windows Mobile' 29 | - 30 | headers: 'User-Agent: Mozilla/3.0N AVE-Front/2.5 (Screen=640x390x256;Product=NTT/PI-2000_1.20; )' 31 | result: { browser: { name: NetFront, version: '2.5', type: browser }, engine: { name: NetFront }, device: { type: pda, manufacturer: NTT, model: 'PetitWeb PI-2000' } } 32 | readable: 'NetFront 2.5 on a NTT PetitWeb PI-2000' 33 | -------------------------------------------------------------------------------- /test/data/pda/mylo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Opera/8.02 (Qt embedded; Linux armv4ll; U) [en] SONY/COM1' 3 | result: { browser: { name: Opera, version: '8.02', type: browser }, engine: { name: Presto }, os: { name: Qtopia }, device: { type: pda, manufacturer: Sony, model: 'Mylo 1' } } 4 | readable: 'Opera 8.02 on a Sony Mylo 1 running Qtopia' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux, Sony/COM2/1.01 [ja]; like Gecko/2007) Firefox/2' 7 | result: { browser: { name: NetFront, type: browser }, engine: { name: NetFront }, device: { type: pda, manufacturer: Sony, model: 'Mylo 2' } } 8 | readable: 'NetFront on a Sony Mylo 2' 9 | -------------------------------------------------------------------------------- /test/data/pda/oasys.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.0 eNavigator (7; 1; Fujitsu; OASYS; 1998.10; (null); 1.0)' 3 | result: { browser: { name: eNavigator, type: browser }, device: { type: pda, manufacturer: Fujitsu, model: OASYS } } 4 | readable: 'eNavigator on a Fujitsu OASYS' 5 | -------------------------------------------------------------------------------- /test/data/pda/psion.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.51 (compatible; Opera 3.62; EPOC; 640x240)' 3 | result: { browser: { name: Opera, version: '3.62', type: browser }, engine: { name: Electra }, os: { name: EPOC, family: Symbian }, device: { type: pda } } 4 | readable: 'Opera 3.62 on EPOC' 5 | - 6 | headers: 'User-Agent: Psion Cpw/1.00f(S5) War/1.00f' 7 | readable: 'WAP Browser on a Psion Series 5mx running EPOC' 8 | result: { browser: { name: 'WAP Browser', type: browser }, os: { name: EPOC, family: Symbian }, device: { type: pda, manufacturer: Psion, model: 'Series 5mx' } } 9 | - 10 | headers: 'User-Agent: Psion Cpw/1.00f(RV) War/1.00f' 11 | readable: 'WAP Browser on a Psion Revo running EPOC' 12 | result: { browser: { name: 'WAP Browser', type: browser }, os: { name: EPOC, family: Symbian }, device: { type: pda, manufacturer: Psion, model: Revo } } 13 | - 14 | headers: 'User-Agent: Psion Cpw/1.00f(S7) War/1.00f' 15 | readable: 'WAP Browser on a Psion Series 7 running EPOC' 16 | result: { browser: { name: 'WAP Browser', type: browser }, os: { name: EPOC, family: Symbian }, device: { type: pda, manufacturer: Psion, model: 'Series 7' } } 17 | - 18 | headers: 'User-Agent: EPOC32-WTL/1.1' 19 | readable: EPOC 20 | result: { os: { name: EPOC, family: Symbian }, device: { type: pda } } 21 | -------------------------------------------------------------------------------- /test/data/phone/snom.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/4.0 (compatible; snom760-SIP 8.8.2.16 2010.06 OCS)' 3 | readable: 'a SNOM 760 IP Telephone' 4 | result: { device: { type: mobile, subtype: desktop, manufacturer: SNOM, model: '760 IP Telephone' } } -------------------------------------------------------------------------------- /test/data/printer/canon.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Standard; Scheme:lsa CanonIJCL/1.1; like Gecko;) Mobile NetFront/4.1' 3 | result: { browser: { name: NetFront, version: '4.1', type: browser }, engine: { name: NetFront }, device: { type: printer, manufacturer: Canon, model: 'IJ Printer' } } 4 | readable: 'NetFront 4.1 on a Canon IJ Printer' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (MFP;IR-S/2.2; like Gecko) NetFront/3.4' 7 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 8 | readable: 'NetFront 3.4 on a Canon imageRUNNER' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (MFP;IR-S/1.3.1; like Gecko) NetFront/3.4' 11 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 12 | readable: 'NetFront 3.4 on a Canon imageRUNNER' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (MFP;IR-S/1.8; like Gecko) NetFront/3.4' 15 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 16 | readable: 'NetFront 3.4 on a Canon imageRUNNER' 17 | - 18 | headers: 'User-Agent: Mozilla/5.0 (Canon Ewloe-S;IR-S/3.0.0) CoralWebkit/2.0.0(KHTML, like Gecko)' 19 | readable: 'a Canon imageRUNNER' 20 | result: { engine: { name: Webkit }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (Canon Madriu-S;IR-S/3.0.0) CoralWebkit/2.0.0(KHTML, like Gecko)' 23 | readable: 'a Canon imageRUNNER' 24 | result: { engine: { name: Webkit }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 25 | - 26 | headers: 'User-Agent: Mozilla/5.0 (558122f6ec4c4a7cb95fbee81d5c96e1-02-00;IR-S/3.3.0) CoralWebkit/2.24.0 (KHTML, like Gecko)' 27 | readable: 'a Canon imageRUNNER' 28 | result: { engine: { name: Webkit }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } 29 | - 30 | headers: 'User-Agent: Mozilla/5.0 (3d9f0c0ffffe40c198b18c7bde9e4b03-01-00;IR-S/3.0.0) CoralWebkit/2.9.2(KHTML, like Gecko)' 31 | readable: 'a Canon imageRUNNER' 32 | result: { engine: { name: Webkit }, device: { type: printer, manufacturer: Canon, model: imageRUNNER } } -------------------------------------------------------------------------------- /test/data/printer/hp.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/3.0 (compatible; HP Web PrintSmart 04b0 1.0.1.34)' 3 | result: { device: { type: printer, manufacturer: HP, model: 'Web PrintSmart' } } 4 | readable: 'a HP Web PrintSmart' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.1; xx; HP eStation/1.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' 7 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '530.17' }, os: { name: Android, version: '2.1' }, device: { type: printer, manufacturer: HP, model: eStation } } 8 | readable: 'Android Browser on a HP eStation running Android 2.1' 9 | -------------------------------------------------------------------------------- /test/data/printer/other.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (MFP; 98/0100R200; like Gecko) NetFront/3.5' 3 | result: { browser: { name: NetFront, version: '3.5', type: browser }, engine: { name: NetFront }, device: { type: printer } } 4 | readable: 'NetFront 3.5' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (MFP; 99/0100o100; like Gecko) NetFront/3.5' 7 | result: { browser: { name: NetFront, version: '3.5', type: browser }, engine: { name: NetFront }, device: { type: printer } } 8 | readable: 'NetFront 3.5' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 AppleWebKit/537.21 (KHTML, like Gecko) Safari/537.21 EpsonHello/1.0(device_id:TFQY010390)' 11 | readable: 'an Epson Hello' 12 | result: { engine: { name: Webkit, version: '537.21' }, device: { type: printer, manufacturer: Epson, model: Hello } } 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 AppleWebKit/537.21 (KHTML, like Gecko) Safari/537.21 EpsonHello/1.0(uuid:303030303030303000)' 15 | readable: 'an Epson Hello' 16 | result: { engine: { name: Webkit, version: '537.21' }, device: { type: printer, manufacturer: Epson, model: Hello } } -------------------------------------------------------------------------------- /test/data/printer/taskalfa.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Standard; NF41SW/1.1; like Gecko; TASKalfa 306ci) NetFront/4.1' 3 | result: { browser: { name: NetFront, version: '4.1', type: browser }, engine: { name: NetFront }, device: { type: printer, manufacturer: Kyocera, model: 'TASKalfa 306ci' } } 4 | readable: 'NetFront 4.1 on a Kyocera TASKalfa 306ci' 5 | -------------------------------------------------------------------------------- /test/data/tablet/browser-opera.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Opera/9.80 (Android 1.6; Linux; Opera Tablet/ADR-1202011015; U; xx) Presto/2.9.201 Version/11.50' 3 | result: { browser: { name: 'Opera Mobile', version: '11.50', type: browser }, engine: { name: Presto, version: 2.9.201 }, os: { name: Android, version: '1.6' }, device: { type: tablet } } 4 | readable: 'Opera Mobile 11.50 on Android 1.6' 5 | - 6 | headers: 'User-Agent: Opera/9.80 (Android 2.2.1; Linux; Opera Tablet/ADR-1301080958) Presto/2.11.355 Version/12.10' 7 | result: { browser: { name: 'Opera Mobile', version: '12.10', type: browser }, engine: { name: Presto, version: 2.11.355 }, os: { name: Android, version: 2.2.1 }, device: { type: tablet } } 8 | readable: 'Opera Mobile 12.10 on Android 2.2.1' 9 | - 10 | headers: 'User-Agent: Opera/9.80 (Android 2.3.1; Linux; Opera Tablet/ADR-1203051651; U; xx) Presto/2.10.254 Version/12.00' 11 | result: { browser: { name: 'Opera Mobile', version: '12.00', type: browser }, engine: { name: Presto, version: 2.10.254 }, os: { name: Android, version: 2.3.1 }, device: { type: tablet } } 12 | readable: 'Opera Mobile 12.00 on Android 2.3.1' 13 | - 14 | headers: 'User-Agent: Opera/9.80 (Android 3.1; Linux; Opera Tablet/ADR-1205181138; U; xx) Presto/2.10.254 Version/12.00' 15 | result: { browser: { name: 'Opera Mobile', version: '12.00', type: browser }, engine: { name: Presto, version: 2.10.254 }, os: { name: Android, version: '3.1' }, device: { type: tablet } } 16 | readable: 'Opera Mobile 12.00 on Android 3.1' 17 | - 18 | headers: 'User-Agent: Opera/9.80 (Android 4.1.1; Linux; Opera Tablet/OupengHD-1.6/ADR-1301101023) Presto/2.11.355 Version/12.10' 19 | result: { browser: { name: 'Opera Oupeng', version: '1.6', type: browser }, engine: { name: Presto, version: 2.11.355 }, os: { name: Android, version: 4.1.1 }, device: { type: tablet } } 20 | readable: 'Opera Oupeng 1.6 on Android 4.1.1' 21 | -------------------------------------------------------------------------------- /test/data/tablet/manufacturer-webtab.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (X11; U; Linux i686; nl-NL) AppleWebKit/534.3 (KHTML, like Gecko) WeTab-Browser Safari/534.3' 3 | readable: 'WebTab Browser on a WeTab running MeeGo' 4 | result: { browser: { name: 'WebTab Browser' }, engine: { name: Webkit, version: '534.3' }, os: { name: MeeGo }, device: { type: tablet, manufacturer: WeTab, model: WeTab } } 5 | -------------------------------------------------------------------------------- /test/data/tablet/os-android.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.1; xx; HP eStation/1.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17' 3 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '530.17' }, os: { name: Android, version: '2.1' }, device: { type: printer, manufacturer: HP, model: eStation } } 4 | readable: 'Android Browser on a HP eStation running Android 2.1' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; xx; HP eStation/1.0) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1' 7 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '533.1' }, os: { name: Android, version: '2.2' }, device: { type: printer, manufacturer: HP, model: eStation } } 8 | readable: 'Android Browser on a HP eStation running Android 2.2' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 8.1; T8_T106 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Kiwi Chrome/69.0.3440.40 Safari/537.36' 11 | readable: 'Kiwi Browser 69.0.3440.40 on a T8_T106 running Android 4.4.2' 12 | result: { browser: { name: 'Kiwi Browser', family: { name: Chrome, version: 69 }, version: 69.0.3440.40, type: browser }, engine: { name: Blink }, os: { name: Android, version: 4.4.2 }, device: { type: tablet, model: T8_T106 } } -------------------------------------------------------------------------------- /test/data/tablet/os-firefoxos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Tablet; rv:28.0) Gecko/28.0 Firefox/28.0' 3 | result: { browser: { name: 'Firefox Mobile', family: { name: Firefox, version: '28.0' }, version: '28.0', type: browser }, engine: { name: Gecko, version: '28.0' }, os: { name: 'Firefox OS', version: '1.3' }, device: { type: tablet } } 4 | readable: 'Firefox Mobile 28.0 on Firefox OS 1.3' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Tablet; rv:30.0) Gecko/30.0 Firefox/30.0' 7 | result: { browser: { name: 'Firefox Mobile', family: { name: Firefox, version: '30.0' }, version: '30.0', type: browser }, engine: { name: Gecko, version: '30.0' }, os: { name: 'Firefox OS', version: '1.4' }, device: { type: tablet } } 8 | readable: 'Firefox Mobile 30.0 on Firefox OS 1.4' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Tablet; rv:32.0) Gecko/32.0 Firefox/32.0' 11 | result: { browser: { name: 'Firefox Mobile', family: { name: Firefox, version: '32.0' }, version: '32.0', type: browser }, engine: { name: Gecko, version: '32.0' }, os: { name: 'Firefox OS', version: '2.0' }, device: { type: tablet } } 12 | readable: 'Firefox Mobile 32.0 on Firefox OS 2.0' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (Tablet; rv:37.0) Gecko/37.0 Firefox/37.0' 15 | result: { browser: { name: 'Firefox Mobile', family: { name: Firefox, version: '37.0' }, version: '37.0', type: browser }, engine: { name: Gecko, version: '37.0' }, os: { name: 'Firefox OS', version: '2.2' }, device: { type: tablet } } 16 | readable: 'Firefox Mobile 37.0 on Firefox OS 2.2' 17 | -------------------------------------------------------------------------------- /test/data/tablet/os-ios.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: FeeddlerRSS 2.4 (iPad; iPhone OS 5.1.1; en_US)' 3 | result: { browser: { name: Feeddler, version: '2.4', type: 'app:feedreader' }, os: { name: iOS, version: 5.1.1 }, device: { type: tablet, manufacturer: Apple, model: iPad } } 4 | readable: 'Feeddler 2.4 on an Apple iPad running iOS 5.1.1' 5 | -------------------------------------------------------------------------------- /test/data/tablet/os-leos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; LeOS1.0; xx; lepad_001n Build/PQXU100.4.0073.021511) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.33 Safari/532.0' 3 | readable: 'Chrome 3 on a Lenovo LePad running LeOS 1.0' 4 | result: { browser: { name: Chrome, version: '3', type: browser }, engine: { name: Webkit, version: '532.0' }, os: { name: LeOS, family: Android, version: '1.0' }, device: { type: tablet, manufacturer: Lenovo, model: LePad } } 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; LeOS1.0; xx; lepad_001b Build/PQXU100.4.0097.042211) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.33 Safari/532.0' 7 | readable: 'Chrome 3 on a Lenovo LePad running LeOS 1.0' 8 | result: { browser: { name: Chrome, version: '3', type: browser }, engine: { name: Webkit, version: '532.0' }, os: { name: LeOS, family: Android, version: '1.0' }, device: { type: tablet, manufacturer: Lenovo, model: LePad } } 9 | -------------------------------------------------------------------------------- /test/data/tablet/os-ubuntu.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Ubuntu; Tablet) WebKit/537.21' 3 | result: { engine: { name: Webkit, version: '537.21' }, os: { name: 'Ubuntu Touch' }, device: { type: tablet } } 4 | readable: 'Ubuntu Touch' 5 | -------------------------------------------------------------------------------- /test/data/tablet/os-webos.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.4; U; xx) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.68 Safari/534.6 TouchPad/1.0' 3 | result: { browser: { name: 'webOS Browser', type: browser }, engine: { name: Webkit, version: '534.6' }, os: { name: webOS, version: '3.0.4' }, device: { type: tablet, manufacturer: HP, model: TouchPad } } 4 | readable: 'webOS Browser on a HP TouchPad running webOS 3.0.4' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.5; U; xx) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.83 Safari/534.6 TouchPad/1.0' 7 | result: { browser: { name: 'webOS Browser', type: browser }, engine: { name: Webkit, version: '534.6' }, os: { name: webOS, version: '3.0.5' }, device: { type: tablet, manufacturer: HP, model: TouchPad } } 8 | readable: 'webOS Browser on a HP TouchPad running webOS 3.0.5' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (iPad; U; xx) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/234.83 Safari/534.6 011/07' 11 | result: { browser: { name: 'webOS Browser', type: browser }, engine: { name: Webkit, version: '534.6' }, os: { name: webOS }, device: { type: tablet, manufacturer: HP, model: TouchPad } } 12 | readable: 'webOS Browser on a HP TouchPad running webOS' -------------------------------------------------------------------------------- /test/data/television/appletv.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: iTunes-AppleTV/4.1' 3 | result: { browser: { name: iTunes, type: 'app:mediaplayer' }, device: { type: television, manufacturer: Apple, model: AppleTV } } 4 | readable: 'iTunes on an AppleTV' 5 | - 6 | headers: 'User-Agent: AppleCoreMedia/1.0.0.12F69 (Apple TV; U; CPU OS 8_3 like Mac OS X; en_us)' 7 | readable: 'an AppleTV' 8 | result: { device: { type: television, manufacturer: Apple, model: AppleTV } } 9 | -------------------------------------------------------------------------------- /test/data/television/browser-machblue.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: MachBlue' 3 | result: { browser: { name: 'MachBlue XT', type: browser }, device: { type: television } } 4 | readable: 'MachBlue XT on a television' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (U; Linux ICE4200; C) AppleWebKit/534.26 mbxtWebKit/1.0.0_pre-alpha (intelce)' 7 | result: { browser: { name: 'MachBlue XT', version: '1.0', type: browser }, engine: { name: Webkit, version: '534.26' }, device: { type: television } } 8 | readable: 'MachBlue XT 1.0 on a television' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (U; Linux x86_64; en_CA.UTF-8) AppleWebKit/534.26+ (KHTML, like Gecko) mbxtWebKit/1.0.0 (gtk)' 11 | result: { browser: { name: 'MachBlue XT', version: '1.0', type: browser }, engine: { name: Webkit, version: '534.26' }, device: { type: television } } 12 | readable: 'MachBlue XT 1.0 on a television' 13 | - 14 | headers: 'User-Agent: Mozilla/5.0 (U; Linux x86_64; en_CA.UTF-8) AppleWebKit/534.26+ mbxtWebKit/1.0.0_pre-alpha (gtk)' 15 | result: { browser: { name: 'MachBlue XT', version: '1.0', type: browser }, engine: { name: Webkit, version: '534.26' }, device: { type: television } } 16 | readable: 'MachBlue XT 1.0 on a television' 17 | -------------------------------------------------------------------------------- /test/data/television/firetv.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 4.2.2; AFTM Build/JDQ39) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/34.0.0.0 Mobile Safari/537.36 cordova-amazon-fireos/3.4.0 AmazonWebAppPlatform/3.4.0;2.0' 3 | result: { browser: { using: 'Amazon WebView' }, engine: { name: Blink }, os: { name: FireOS, family: Android, version: '3' }, device: { type: television, manufacturer: Amazon, model: 'Fire TV Stick' } } 4 | readable: 'Amazon WebView on an Amazon Fire TV Stick running FireOS 3' 5 | -------------------------------------------------------------------------------- /test/data/television/hitachi.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Standard; NF34SW/1.1; like Gecko) NetFront/3.4 InettvBrowser/2.2C (000087;IP03-01;0100;0000)' 3 | result: { browser: { name: NetFront, version: '3.4', type: browser }, engine: { name: NetFront }, device: { type: television, manufacturer: Hitachi, series: 'Smart TV' } } 4 | readable: 'NetFront 3.4 on a Hitachi Smart TV' 5 | -------------------------------------------------------------------------------- /test/data/television/kreatv.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: KreaTVWebKit/531 (Motorola STB; Linux)' 3 | result: { engine: { name: Webkit, version: '531' }, device: { type: television, manufacturer: Motorola, series: KreaTV } } 4 | readable: 'a Motorola KreaTV' 5 | - 6 | headers: 'User-Agent: Motorola KreaTV STB (Linux)/WebKit' 7 | result: { device: { type: television, manufacturer: Motorola, series: KreaTV } } 8 | readable: 'a Motorola KreaTV' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux) AppleWebKit/534.51 (KHTML, like Gecko) Ekioh/2.2.4.7-moto-mob Safari/534.51:534 Motorola KreaTV STB VIP1003' 11 | result: { browser: { using: { name: Ekioh, version: 2.2.4.7 } }, engine: { name: Webkit, version: '534.51' }, device: { type: television, manufacturer: Motorola, series: KreaTV } } 12 | readable: 'Ekioh 2.2.4.7 on a Motorola KreaTV' 13 | - 14 | headers: 'User-Agent: OPR/19.0.1325.0 OMI/4.1.4.54, KreaTV/0.16197.0.0 (ARRIS, VMS1100, wired)' 15 | result: { browser: { name: 'Opera Devices', version: '4.1', type: browser }, device: { type: television, manufacturer: Arris, model: VMS1100, series: KreaTV } } 16 | readable: 'Opera Devices 4.1 on an Arris VMS1100 KreaTV' 17 | - 18 | headers: 'User-Agent: OPR/19.0.1325.0 OMI/4.1.4.54, KreaTV/0.923.0.0 (ARRIS, VMS1100, wired)' 19 | result: { browser: { name: 'Opera Devices', version: '4.1', type: browser }, device: { type: television, manufacturer: Arris, model: VMS1100, series: KreaTV } } 20 | readable: 'Opera Devices 4.1 on an Arris VMS1100 KreaTV' 21 | - 22 | headers: 'User-Agent: OPR/19.0.1325.0 OMI/4.1.4.54, KreaTV/15.99.2.1 (ARRIS, IPC1100P2, wired)' 23 | result: { browser: { name: 'Opera Devices', version: '4.1', type: browser }, device: { type: television, manufacturer: Arris, model: IPC1100P2, series: KreaTV } } 24 | readable: 'Opera Devices 4.1 on an Arris IPC1100P2 KreaTV' 25 | - 26 | headers: 'User-Agent: OPR/19.0.1325.0 OMI/4.1.4.54, KreaTV/15.99.2.1 (ARRIS, IPC1100P2, wired)' 27 | result: { browser: { name: 'Opera Devices', version: '4.1', type: browser }, device: { type: television, manufacturer: Arris, model: IPC1100P2, series: KreaTV } } 28 | readable: 'Opera Devices 4.1 on an Arris IPC1100P2 KreaTV' 29 | -------------------------------------------------------------------------------- /test/data/television/mitsubishi.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Linux 2.6.32; xx;) AppleWebKit/534(KHTML, like Gecko) NX/2.1 (DTV; HTML; R1.0;) InettvBrowser/2.2 (38E08E;0014GAIAV3;001;000) Hybridcast/1.0 (;38E08E;0014GAIAV3;001;000;)' 3 | result: { browser: { name: 'NetFront NX', version: '2.1', type: browser }, engine: { name: Webkit, version: '534' }, device: { type: television, manufacturer: Mitsubishi, series: 'Smart TV' } } 4 | readable: 'NetFront NX 2.1 on a Mitsubishi Smart TV' 5 | -------------------------------------------------------------------------------- /test/data/television/nvidia.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Andr0id 6.0; SHIELD Andr0id TV Build/MRA58K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.23 Safari/537.36 OPR/32.0.2128.0 OMI/4.8.0.17.release' 3 | readable: 'Opera Devices 4.8 on a Nvidia SHIELD Android TV running Android TV 6.0' 4 | result: { browser: { name: 'Opera Devices', family: { name: Chrome, version: 49 }, version: '4.8', type: browser }, engine: { name: Blink }, os: { name: 'Android TV', family: Android, version: '6.0' }, device: { type: television, manufacturer: Nvidia, model: 'SHIELD Android TV' } } 5 | -------------------------------------------------------------------------------- /test/data/television/pioneer.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Opera/9.80 (Linux armv6l; Opera TV Store/5581) Presto/2.12.362 Version/12.11 Blu-ray Player/v00.17 (Pioneer, BDP-160, wired)' 3 | result: { browser: { name: 'Opera Devices', version: '3.4', type: browser }, engine: { name: Presto, version: 2.12.362 }, device: { type: television, manufacturer: Pioneer, model: BDP-160, series: 'Blu-ray Player' } } 4 | readable: 'Opera Devices 3.4 on a Pioneer BDP-160 Blu-ray Player' 5 | - 6 | headers: 'User-Agent: Mozilla/4.08 (Standard; NF32SW/2.0) NetFront/3.2 InettvBrowser/1.0(00E036;BD-V3;02;00)' 7 | result: { browser: { name: NetFront, version: '3.2', type: browser }, engine: { name: NetFront }, device: { type: television, manufacturer: Pioneer, series: 'Smart TV' } } 8 | readable: 'NetFront 3.2 on a Pioneer Smart TV' 9 | -------------------------------------------------------------------------------- /test/data/television/roku.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Roku) AppleWebKit/537.36 (KHTML, like Gecko) Web/1.1 Safari/537.36' 3 | result: { browser: { name: Web, version: '1.1', type: browser }, engine: { name: Webkit, version: '537.36' }, device: { type: television, manufacturer: Roku } } 4 | readable: 'Web 1.1 on a Roku' 5 | - 6 | headers: 'User-Agent: Roku/DVP-3100EU-4.3 (024.03E10000A)' 7 | result: { device: { type: television, manufacturer: Roku, model: '2 XS' } } 8 | readable: 'a Roku 2 XS' 9 | - 10 | headers: 'User-Agent: Roku/DVP-5.4 (045.04E03198A)' 11 | result: { device: { type: television, manufacturer: Roku, model: '3' } } 12 | readable: 'a Roku 3' 13 | - 14 | headers: 'User-Agent: Roku/DVP-4.9 (074.09E08022A)' 15 | result: { device: { type: television, manufacturer: Roku, model: LT } } 16 | readable: 'a Roku LT' 17 | - 18 | headers: 'User-Agent: Roku/DVP-5.5 (095.05E02025A)' 19 | result: { device: { type: television, manufacturer: Roku, model: 'Streaming Stick' } } 20 | readable: 'a Roku Streaming Stick' 21 | - 22 | headers: 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36 Roku/DVP-8.10 (468.10E04145A)' 23 | readable: 'a Roku' 24 | result: { browser: { family: { name: Chrome, version: 70 }, type: browser }, engine: { name: Blink }, device: { type: television, manufacturer: Roku } } 25 | - 26 | headers: 'User-Agent: Roku/DVP-9.10 (519.10E04111A)' 27 | readable: 'a Roku Express' 28 | result: { device: { type: television, manufacturer: Roku, model: Express } } 29 | - 30 | headers: 'User-Agent: Roku4640X/DVP-7.70 (297.70E04154A)' 31 | readable: 'a Roku Ultra' 32 | result: { device: { type: television, manufacturer: Roku, model: Ultra } } 33 | - 34 | headers: 'User-Agent: Roku/DVP-9.30 (309.30E04182A)' 35 | readable: 'a TCL 4K Roku TV' 36 | result: { device: { type: television, manufacturer: TCL, model: '4K Roku TV' } } -------------------------------------------------------------------------------- /test/data/television/sanyo.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Aplix_SANYO_browser/1.x (Japanese)' 3 | result: { browser: { name: Aplix, version: '1', type: browser }, device: { type: television, manufacturer: Sanyo, series: 'Internet TV' } } 4 | readable: 'Aplix 1 on a Sanyo Internet TV' 5 | - 6 | headers: 'User-Agent: Aplix_SANYO_browser/1.03 (Japanese)' 7 | result: { browser: { name: Aplix, version: '1.03', type: browser }, device: { type: television, manufacturer: Sanyo, series: 'Internet TV' } } 8 | readable: 'Aplix 1.03 on a Sanyo Internet TV' 9 | -------------------------------------------------------------------------------- /test/data/watch/os-android.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Android 2.3.4; Motorola-F100 Build/4.5.1-26_G2-436_US-MR7-24) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.45 Mobile Safari/537.36 OPR/15.0.1162.59192' 3 | result: { browser: { name: Opera, family: { name: Chrome, version: 28 }, version: '15.0', type: browser }, engine: { name: Blink }, os: { name: Android, version: 2.3.4 }, device: { type: watch, manufacturer: Motorola, model: MOTOACTV } } 4 | readable: 'Opera 15.0 on a Motorola MOTOACTV running Android 2.3.4' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.2.2; xx; NT-1501C Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 7 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.2.2 }, device: { type: watch, manufacturer: IconBit, model: 'NetTab Callisto 100' } } 8 | readable: 'Android Browser on an IconBit NetTab Callisto 100 running Android 4.2.2' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; U; Android 4.2.2; xx; SM-V700 Build/JDQ39) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' 11 | result: { browser: { name: 'Android Browser' }, engine: { name: Webkit, version: '534.30' }, os: { name: Android, version: 4.2.2 }, device: { type: watch, manufacturer: Samsung, model: 'Galaxy Gear' } } 12 | readable: 'Android Browser on a Samsung Galaxy Gear running Android 4.2.2' 13 | -------------------------------------------------------------------------------- /test/data/watch/os-tizen.yaml: -------------------------------------------------------------------------------- 1 | - 2 | headers: 'User-Agent: Mozilla/5.0 (Linux; Tizen 2.2.1.3; SAMSUNG SM-R750) AppleWebKit/538.1 (KHTML, like Gecko) Version/2.2.1.3 Mobile Safari/538.1' 3 | result: { engine: { name: Webkit, version: '538.1' }, os: { name: Tizen, version: 2.2.1.3 }, device: { type: watch, manufacturer: Samsung, model: 'Gear S' } } 4 | readable: 'a Samsung Gear S running Tizen 2.2.1.3' 5 | - 6 | headers: 'User-Agent: Mozilla/5.0 (Linux; Tizen 2.2.1.3; SAMSUNG SM-R750A) AppleWebKit/538.1 (KHTML, like Gecko) Version/2.2.1.3 Mobile Safari/538.1' 7 | result: { engine: { name: Webkit, version: '538.1' }, os: { name: Tizen, version: 2.2.1.3 }, device: { type: watch, manufacturer: Samsung, model: 'Gear S' } } 8 | readable: 'a Samsung Gear S running Tizen 2.2.1.3' 9 | - 10 | headers: 'User-Agent: Mozilla/5.0 (Linux; Tizen 2.2.1.3; SM-R750) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.76 efl-webengine/0.1.1.1 Mobile Safari/537.36' 11 | result: { browser: { family: { name: Chrome, version: 34 } }, engine: { name: Blink }, os: { name: Tizen, version: 2.2.1.3 }, device: { type: watch, manufacturer: Samsung, model: 'Gear S' } } 12 | readable: 'a Samsung Gear S running Tizen 2.2.1.3' 13 | -------------------------------------------------------------------------------- /test/model/primitive/BaseTest.js: -------------------------------------------------------------------------------- 1 | const { describe, it } = (exports.lab = require('@hapi/lab').script()); 2 | const expect = require('@hapi/code').expect; 3 | const Base = require('../../../src/model/primitive/Base'); 4 | 5 | describe('Base Class', () => { 6 | describe('constructor', () => { 7 | it('should create the class correctly', () => { 8 | expect(new Base({ name: 'Generic' }).name).to.be.equal('Generic'); 9 | }); 10 | }); 11 | 12 | describe('set method', () => { 13 | it('should set properties correctly', () => { 14 | const base = new Base(); 15 | base.set({ name: 'Generic' }); 16 | expect(base.name).to.be.equal('Generic'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /test/unit/AnalyserTest.js: -------------------------------------------------------------------------------- 1 | const { describe, it } = (exports.lab = require('@hapi/lab').script()); 2 | const expect = require('@hapi/code').expect; 3 | const Main = require('../../src/model/Main'); 4 | const Analyser = require('../../src/Analyser'); 5 | 6 | describe('Analyser Class', () => { 7 | describe('Create and getData back', () => { 8 | it('should return an instance of Main Class', () => { 9 | const analyser = new Analyser({ 10 | 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)', 11 | }); 12 | expect(analyser).to.be.instanceOf(Analyser); 13 | 14 | analyser.analyse(); 15 | 16 | expect(analyser.getData()).to.be.instanceOf(Main); 17 | }); 18 | }); 19 | 20 | describe('create and setData ', () => { 21 | it('getData should return an instance of Main Class', () => { 22 | const analyser = new Analyser({ 23 | 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)', 24 | }); 25 | expect(analyser).to.be.instanceOf(Analyser); 26 | 27 | const input = new Main(); 28 | 29 | expect(input).to.be.instanceOf(Main); 30 | 31 | analyser.setData(input); 32 | analyser.analyse(); 33 | 34 | expect(analyser.getData()).to.be.instanceOf(Main); 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /test/unit/MassiveTest.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const { describe, it } = (exports.lab = require('@hapi/lab').script()); 4 | const expect = require('@hapi/code').expect; 5 | const Parser = require('../../src/Parser'); 6 | const path = require('path'); 7 | const fs = require('fs'); 8 | const yaml = require('yamljs'); 9 | 10 | function getDirContent(category = '') { 11 | return fs.readdirSync(path.join(__dirname, '../data', category)); 12 | } 13 | 14 | describe('Testing Parser with YAML files', () => { 15 | getDirContent().forEach((category) => { 16 | getDirContent(category).forEach((file) => { 17 | try { 18 | const yamlContent = yaml.load(path.join(__dirname, '../data', category, file)); 19 | yamlContent.forEach(makeTest); 20 | } catch (e) { 21 | // eslint-disable-next-line no-console 22 | console.error(e); 23 | // eslint-disable-next-line no-console 24 | console.error('The above error is caused in the test file ' + category + '/' + file); 25 | 26 | throw new Error('Aborting the tests'); 27 | } 28 | }); 29 | }); 30 | }); 31 | 32 | function makeTest(options) { 33 | it(`With header: ${options.headers}`, () => { 34 | if (options.headers && typeof options.headers === 'string') { 35 | options.headers = parseHeaders(options.headers); 36 | } 37 | const parserObj = new Parser(options); 38 | 39 | expect(parserObj.toString()).to.be.equal(options.readable); 40 | expect(parserObj.toObject()).to.be.equal(options.result); 41 | expect(parserObj.cached).to.not.exists(); 42 | }); 43 | } 44 | 45 | function parseHeaders(rawHeaders) { 46 | const headers = {}; 47 | let key = ''; 48 | 49 | for (const header of rawHeaders.split('\n')) { 50 | let [headerName, ...headerValue] = header.split(':'); 51 | headerValue = headerValue.join(':'); 52 | if (headerValue) { 53 | if (!headers[headerName]) { 54 | headers[headerName] = headerValue.trim(); 55 | } else if (Array.isArray(headers[headerName])) { 56 | headers[headerName] = [...headers[headerName], headerValue.trim()]; 57 | } else { 58 | headers[headerName] = [headers[headerName], headerValue.trim()]; 59 | } 60 | 61 | key = headerName; 62 | } else { 63 | if (/^\t/.test(headerName)) { 64 | headers[key] += `\r\n\t${headerName.trim()}`; 65 | } else if (!key) { 66 | headers[0] = headerName.trim(); 67 | } 68 | headerName.trim(); 69 | } 70 | } 71 | 72 | return headers; 73 | } 74 | -------------------------------------------------------------------------------- /test/unit/ParserTest.js: -------------------------------------------------------------------------------- 1 | const { describe, it } = (exports.lab = require('@hapi/lab').script()); 2 | const expect = require('@hapi/code').expect; 3 | const Parser = require('../../src/Parser'); 4 | 5 | describe('Parser Class', () => { 6 | describe('Creating Parse with string', () => { 7 | it('should work', () => { 8 | const parser = new Parser('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)'); 9 | 10 | expect(parser).to.be.instanceOf(Parser); 11 | 12 | expect(parser.isBrowser('Internet Explorer', '=', '6.0')).to.be.true(); 13 | }); 14 | }); 15 | 16 | describe('Creating Parse with headers object', () => { 17 | it('should work', () => { 18 | const parser = new Parser({ 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)' }); 19 | 20 | expect(parser).to.be.instanceOf(Parser); 21 | 22 | expect(parser.isBrowser('Internet Explorer', '=', '6.0')).to.be.true(); 23 | }); 24 | }); 25 | 26 | describe('Creating Parse with options', () => { 27 | it('should work', () => { 28 | const parser = new Parser({ 29 | headers: { 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)' }, 30 | }); 31 | 32 | expect(parser).to.be.instanceOf(Parser); 33 | 34 | expect(parser.isBrowser('Internet Explorer', '=', '6.0')).to.be.true(); 35 | }); 36 | }); 37 | 38 | describe('Creating Parse without arguments', () => { 39 | it('an calling analyse should work', () => { 40 | const parser = new Parser(); 41 | parser.analyse('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; InfoPath.1)'); 42 | 43 | expect(parser).to.be.instanceOf(Parser); 44 | 45 | expect(parser.isBrowser('Internet Explorer', '=', '6.0')).to.be.true(); 46 | }); 47 | }); 48 | }); 49 | --------------------------------------------------------------------------------