Merge branch 'develop'

This commit is contained in:
Faisal Salman 2023-04-27 10:41:49 +07:00
commit 1a806453f9
14 changed files with 2314 additions and 179 deletions

1975
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -142,20 +142,21 @@
"Zach Bjornson <zbbjornson@gmail.com>"
],
"type": "commonjs",
"main": "src/ua-parser.js",
"module": "src/module/ua-parser.mjs",
"main": "src/main/ua-parser.js",
"module": "src/main/ua-parser.mjs",
"browser": "dist/ua-parser.pack.js",
"exports": {
".": {
"require": "./src/ua-parser.js",
"import": "./src/module/ua-parser.mjs"
"require": "./src/main/ua-parser.js",
"import": "./src/main/ua-parser.mjs"
},
"./enums": {
"require": "./src/ua-parser-enum.js",
"import": "./src/module/ua-parser-enum.mjs"
"require": "./src/enums/ua-parser-enums.js",
"import": "./src/enums/ua-parser-enums.mjs"
},
"./extensions": {
"require": "./src/ua-parser-extension.js",
"import": "./src/module/ua-parser-extension.mjs"
"require": "./src/extensions/ua-parser-extensions.js",
"import": "./src/extensions/ua-parser-extensions.mjs"
}
},
"files": [
@ -164,11 +165,13 @@
],
"scripts": {
"build": "./script/build-dist.sh && ./script/build-module.js",
"fuzz": "npx jazzer ./test/jazzer-fuzz-test.js --sync",
"test": "npm run build && ./script/test-all.sh"
},
"devDependencies": {
"@babel/parser": "7.15.8",
"@babel/traverse": "7.15.4",
"@jazzer.js/core": "^1.4.0",
"@playwright/test": "~1.32.2",
"jshint": "~2.13.6",
"mocha": "~8.2.0",

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
SRC_PATH="src/ua-parser.js"
SRC_PATH="src/main/ua-parser.js"
MIN_PATH="dist/ua-parser.min.js"
PACK_PATH="dist/ua-parser.pack.js"

View File

@ -3,19 +3,19 @@
const fs = require('fs');
const PATH = {
main : {
src : 'src/ua-parser.js',
dest : 'src/module/ua-parser.mjs',
src : 'src/main/ua-parser.js',
dest : 'src/main/ua-parser.mjs',
title : ''
},
enum : {
src : 'src/ua-parser-enum.js',
dest :'src/module/ua-parser-enum.mjs',
title : 'enum'
enums : {
src : 'src/enums/ua-parser-enums.js',
dest :'src/enums/ua-parser-enums.mjs',
title : 'enums'
},
extension : {
src : 'src/ua-parser-extension.js',
dest : 'src/module/ua-parser-extension.mjs',
title : 'extension'
extensions : {
src : 'src/extensions/ua-parser-extensions.js',
dest : 'src/extensions/ua-parser-extensions.mjs',
title : 'extensions'
}
};
const generateMJS = (module, replacers) => {
@ -30,15 +30,11 @@ const generateMJS = (module, replacers) => {
fs.writeFileSync(dest,
`// Generated ESM version of UAParser.js ${title}
// DO NOT EDIT THIS FILE!
// Source: /src/ua-parser.js
// Source: /${src}
${text}`, 'utf-8');
};
if (!fs.existsSync('src/module')) {
fs.mkdirSync('src/module', { recursive: true });
}
// ua-parser.mjs
generateMJS('main', [
[/\(func[\s\S]+strict\';/ig, ''],
@ -47,7 +43,7 @@ generateMJS('main', [
]);
// ua-parser-enum.mjs
generateMJS('enum', [[/module\.exports =/ig, 'export']]);
generateMJS('enums', [[/module\.exports =/ig, 'export']]);
// ua-parser-extension.mjs
generateMJS('extension', [[/module\.exports =/ig, 'export']]);
generateMJS('extensions', [[/module\.exports =/ig, 'export']]);

View File

@ -1,6 +1,6 @@
// Generated ESM version of UAParser.js enums
// DO NOT EDIT THIS FILE!
// Source: /src/ua-parser-enum.js
// Source: /src/enums/ua-parser-enums.js
///////////////////////////////////////////////
/* Enums for UAParser.js v2.0.0-alpha.2

View File

@ -0,0 +1,237 @@
///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-alpha.2
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
MIT License */
//////////////////////////////////////////////
/*jshint esversion: 6 */
const MODEL = 'model';
const NAME = 'name';
const TYPE = 'type';
const VENDOR = 'vendor';
const VERSION = 'version';
const MOBILE = 'mobile';
const TABLET = 'tablet';
const Apps = Object.freeze({
browser : [
[/chatlyio\/([\d\.]+)/i], [VERSION, 'Slack', [TYPE, 'app']]
]
});
const Bots = Object.freeze({
browser : [
// Googlebot / BingBot / MSNBot / FacebookBot
[/((?:google|bing|msn|facebook)bot(?:[\-imagevdo]{0,6})|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']],
// Slackbot - https://api.slack.com/robots
[/(slack(?:bot)?(?:-imgproxy|-linkexpanding)?) ([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
]
});
const CLIs = Object.freeze({
browser : [
// wget / curl / lynx
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'cli']]
]
});
const ExtraDevices = Object.freeze({
device : [[
/(nook)[\w ]+build\/(\w+)/i, // Nook
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
], [VENDOR, MODEL, [TYPE, TABLET]], [
/(u304aa)/i // AT&T
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
/\bsie-(\w*)/i // Siemens
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
/\b(rct\w+) b/i // RCA Tablets
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
/\b(tm\d{3}\w+) b/i
], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
/\b(k88) b/i // ZTE K Series Tablet
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
/\b(nx\d{3}j) b/i // ZTE Nubia
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
/\b(zur\d{3}) b/i // Swiss ZUR Tablet
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
/\b((zeki)?tb.*\b) b/i // Zeki Tablets
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
/\b([yr]\d{2}) b/i,
/\b(?:dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [
/\b(ns-?\w{0,9}) b/i // Insignia Tablets
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
/\b(ph-1) /i // Essential PH-1
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
/\btu_(1491) b/i // Rotor Tablets
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]]
]
});
const Emails = Object.freeze({
browser : [
// Microsoft Outlook / Thunderbird
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
]
});
const MediaPlayers = Object.freeze({
browser : [[
/(apple(?:coremedia|))\/([\w\._]+)/i, // Generic Apple CoreMedia
/(coremedia) v([\w\._]+)/i
], [NAME, VERSION], [
/(aqualung|lyssna|bsplayer)\/([\w\.-]+)/i // Aqualung/Lyssna/BSPlayer
], [NAME, VERSION], [
/(ares|ossproxy)\s([\w\.-]+)/i // Ares/OSSProxy
], [NAME, VERSION], [
/(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/([\w\.-]+)/i,
// Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC
// NSPlayer/PSP-InternetRadioPlayer/Videos
/(clementine|music player daemon)\s([\w\.-]+)/i, // Clementine/MPD
/(lg player|nexplayer)\s([\d\.]+)/i,
/player\/(nexplayer|lg player)\s([\w\.-]+)/i // NexPlayer/LG Player
], [NAME, VERSION], [
/(nexplayer)\s([\w\.-]+)/i // Nexplayer
], [NAME, VERSION], [
/(flrp)\/([\w\.-]+)/i // Flip Player
], [[NAME, 'Flip Player'], VERSION], [
/(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i
// FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit
], [NAME], [
/(gstreamer) souphttpsrc.+libsoup\/([\w\.-]+)/i
// Gstreamer
], [NAME, VERSION], [
/(htc streaming player)\s[\w_]+\s\/\s([\d\.]+)/i, // HTC Streaming Player
/(java|python-urllib|python-requests|wget|libcurl)\/([\w\.-_]+)/i,
// Java/urllib/requests/wget/cURL
/(lavf)([\d\.]+)/i // Lavf (FFMPEG)
], [NAME, VERSION], [
/(htc_one_s)\/([\d\.]+)/i, // HTC One S
], [[NAME, /_/g, ' '], VERSION], [
/(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+))/i,
// MPlayer SVN
], [NAME, VERSION], [
/(mplayer)(?:\s|\/)([\w\.-]+)/i, // MPlayer
/(mplayer) unknown-([\w\.\-]+)/i // MPlayer UNKNOWN
], [NAME, VERSION], [
/(mplayer)/i, // MPlayer (no other info)
/(yourmuze)/i, // YourMuze
/(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime
], [NAME], [
/(nero (?:home|scout))\/([\w\.-]+)/i // Nero Home/Nero Scout
], [NAME, VERSION], [
/(nokia\d+)\/([\w\.-]+)/i // Nokia
], [NAME, VERSION], [
/\s(songbird)\/([\w\.-]+)/i // Songbird/Philips-Songbird
], [NAME, VERSION], [
/(winamp)3 version ([\w\.-]+)/i, // Winamp
/(winamp)\s([\w\.-]+)/i,
/(winamp)mpeg\/([\w\.-]+)/i
], [NAME, VERSION], [
/(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info)
// inlight radio
], [NAME], [
/(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/([\w\.-]+)/i
// QuickTime/RealMedia/RadioApp/RadioClientApplication/
// SoundTap/Totem/Stagefright/Streamium
], [NAME, VERSION], [
/(smp)([\d\.]+)/i // SMP
], [NAME, VERSION], [
/(vlc) media player - version ([\w\.]+)/i, // VLC Videolan
/(vlc)\/([\w\.-]+)/i,
/(xbmc|gvfs|xine|xmms|irapp)\/([\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp
/(foobar2000)\/([\d\.]+)/i, // Foobar2000
/(itunes)\/([\d\.]+)/i // iTunes
], [NAME, VERSION], [
/(wmplayer)\/([\w\.-]+)/i, // Windows Media Player
/(windows-media-player)\/([\w\.-]+)/i
], [[NAME, /-/g, ' '], VERSION], [
/windows\/([\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i,
// Windows Media Server
], [VERSION, [NAME, 'Windows']], [
/(com\.riseupradioalarm)\/([\d\.]*)/i // RiseUP Radio Alarm
], [NAME, VERSION], [
/(rad.io)\s([\d\.]+)/i, // Rad.io
/(radio.(?:de|at|fr))\s([\d\.]+)/i
], [[NAME, 'rad.io'], VERSION]
]
});
module.exports = {
Apps,
Bots,
CLIs,
ExtraDevices,
Emails,
MediaPlayers
};

View File

@ -1,3 +1,7 @@
// Generated ESM version of UAParser.js extensions
// DO NOT EDIT THIS FILE!
// Source: /src/extensions/ua-parser-extensions.js
///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-alpha.2
https://github.com/faisalman/ua-parser-js
@ -123,7 +127,7 @@ const CLI = Object.freeze({
]
});
module.exports = {
export {
Apps,
Bots,
ExtraDevices,

View File

@ -1147,7 +1147,8 @@
['getResult', createItemFunc(UA_RESULT)],
['getUA', function () { return userAgent; }],
['setUA', function (ua) {
userAgent = (typeof ua === STR_TYPE && ua.length > UA_MAX_LENGTH) ? trim(ua, UA_MAX_LENGTH) : ua;
if (typeof ua === STR_TYPE)
userAgent = ua.length > UA_MAX_LENGTH ? trim(ua, UA_MAX_LENGTH) : ua;
return this;
}]
])

View File

@ -1,6 +1,6 @@
// Generated ESM version of UAParser.js
// DO NOT EDIT THIS FILE!
// Source: /src/ua-parser.js
// Source: /src/main/ua-parser.js
/////////////////////////////////////////////////////////////////////////////////
/* UAParser.js v2.0.0-alpha.2
@ -734,7 +734,7 @@
// iOS/macOS
/ip[honead]{2,4}\b(?:.*os ([\w]+) like mac|; opera)/i, // iOS
/ios;fbsv\/([\d\.]+)/i,
/(?:ios;fbsv\/|iphone.+ios[\/ ])([\d\.]+)/i,
/cfnetwork\/.+darwin/i
], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [
/(mac os x) ?([\w\. ]*)/i,
@ -920,10 +920,10 @@
// Constructor
////////////////
function UACHData (uach, isHTTP_UACH) {
function UACHData (uach, isHttpUACH) {
uach = uach || {};
setProps.call(this, CH_ALL_VALUES);
if (isHTTP_UACH) {
if (isHttpUACH) {
setProps.call(this, [
[BRANDS, itemListToArray(uach[CH_HEADER])],
[FULLVERLIST, itemListToArray(uach[CH_HEADER_FULL_VER_LIST])],
@ -1108,15 +1108,12 @@
return new UAParser(ua, extensions, headers).getResult();
}
var userAgent = ua ||
((NAVIGATOR && NAVIGATOR.userAgent) ?
NAVIGATOR.userAgent :
(headers && headers[USER_AGENT] ?
headers[USER_AGENT] :
EMPTY)),
HTTP_UACH = new UACHData(headers, true),
var userAgent = typeof ua === STR_TYPE ? ua : // Passed user-agent string
((NAVIGATOR && NAVIGATOR.userAgent) ? NAVIGATOR.userAgent : // navigator.userAgent
(headers && headers[USER_AGENT] ? headers[USER_AGENT] : // User-Agent from passed headers
EMPTY)), // empty string
httpUACH = new UACHData(headers, true),
regexMap = extensions ?
extend(defaultRegexes, extensions) :
defaultRegexes,
@ -1124,7 +1121,7 @@
createItemFunc = function (itemType) {
if (itemType == UA_RESULT) {
return function () {
return new UAItem(itemType, userAgent, regexMap, HTTP_UACH)
return new UAItem(itemType, userAgent, regexMap, httpUACH)
.set('ua', userAgent)
.set(UA_BROWSER, this.getBrowser())
.set(UA_CPU, this.getCPU())
@ -1135,7 +1132,7 @@
};
} else {
return function () {
return new UAItem(itemType, userAgent, regexMap[itemType], HTTP_UACH)
return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH)
.parseUA()
.get();
};

View File

@ -1,126 +0,0 @@
// Generated ESM version of UAParser.js extensions
// DO NOT EDIT THIS FILE!
// Source: /src/ua-parser-extension.js
///////////////////////////////////////////////
/* Extensions for UAParser.js v2.0.0-alpha.2
https://github.com/faisalman/ua-parser-js
Author: Faisal Salman <f@faisalman.com>
MIT License */
//////////////////////////////////////////////
/*jshint esversion: 6 */
const MODEL = 'model';
const NAME = 'name';
const TYPE = 'type';
const VENDOR = 'vendor';
const VERSION = 'version';
const MOBILE = 'mobile';
const TABLET = 'tablet';
const Bots = Object.freeze({
browser : [
// Googlebot / BingBot / MSNBot / FacebookBot
[/((?:google|bing|msn|facebook)bot(?:\-[imagevdo]{5})?|bingpreview)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'bot']]
]
});
const ExtraDevices = Object.freeze({
device : [
[
/(nook)[\w ]+build\/(\w+)/i, // Nook
/(dell) (strea[kpr\d ]*[\dko])/i, // Dell Streak
/(le[- ]+pan)[- ]+(\w{1,9}) bui/i, // Le Pan Tablets
/(trinity)[- ]*(t\d{3}) bui/i, // Trinity Tablets
/(gigaset)[- ]+(q\w{1,9}) bui/i, // Gigaset Tablets
/(vodafone) ([\w ]+)(?:\)| bui)/i // Vodafone
], [VENDOR, MODEL, [TYPE, TABLET]], [
/(u304aa)/i // AT&T
], [MODEL, [VENDOR, 'AT&T'], [TYPE, MOBILE]], [
/\bsie-(\w*)/i // Siemens
], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [
/\b(rct\w+) b/i // RCA Tablets
], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [
/\b(venue[\d ]{2,7}) b/i // Dell Venue Tablets
], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [
/\b(q(?:mv|ta)\w+) b/i // Verizon Tablet
], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [
/\b(?:barnes[& ]+noble |bn[rt])([\w\+ ]*) b/i // Barnes & Noble Tablet
], [MODEL, [VENDOR, 'Barnes & Noble'], [TYPE, TABLET]], [
/\b(tm\d{3}\w+) b/i
], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [
/\b(k88) b/i // ZTE K Series Tablet
], [MODEL, [VENDOR, 'ZTE'], [TYPE, TABLET]], [
/\b(nx\d{3}j) b/i // ZTE Nubia
], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [
/\b(gen\d{3}) b.+49h/i // Swiss GEN Mobile
], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [
/\b(zur\d{3}) b/i // Swiss ZUR Tablet
], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [
/\b((zeki)?tb.*\b) b/i // Zeki Tablets
], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [
/\b([yr]\d{2}) b/i,
/\b(?:dragon[- ]+touch |dt)(\w{5}) b/i // Dragon Touch Tablet
], [MODEL, [VENDOR, 'Dragon Touch'], [TYPE, TABLET]], [
/\b(ns-?\w{0,9}) b/i // Insignia Tablets
], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [
/\b((nxa|next)-?\w{0,9}) b/i // NextBook Tablets
], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [
/\b(xtreme\_)?(v(1[045]|2[015]|[3469]0|7[05])) b/i // Voice Xtreme Phones
], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [
/\b(lvtel\-)?(v1[12]) b/i // LvTel Phones
], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [
/\b(ph-1) /i // Essential PH-1
], [MODEL, [VENDOR, 'Essential'], [TYPE, MOBILE]], [
/\b(v(100md|700na|7011|917g).*\b) b/i // Envizen Tablets
], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [
/\b(trio[-\w\. ]+) b/i // MachSpeed Tablets
], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [
/\btu_(1491) b/i // Rotor Tablets
], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]
]
]
});
const Emails = Object.freeze({
browser : [
// Microsoft Outlook / Thunderbird
[/(microsoft outlook|thunderbird)[\s\/]([\w\.]+)/i], [NAME, VERSION, [TYPE, 'email']]
]
});
const Tools = Object.freeze({
browser : [
// wget / curl / lynx
[/(wget|curl|lynx)\/([\w\.]+)/i], [NAME, VERSION, [TYPE, 'tool']]
]
});
export {
Bots,
ExtraDevices,
Emails,
Tools
};

View File

@ -0,0 +1,15 @@
const UAParser = require('ua-parser-js');
module.exports.fuzz = function (buffer) {
const userAgent = buffer.toString();
const start = process.hrtime();
UAParser(userAgent);
const elapsed = process.hrtime(start);
const milisec = (elapsed[0]*1e3+elapsed[1]*1e-6).toFixed(3);
if (milisec > 1000) {
throw new Error(
`Potential ReDoS\n` +
`Time taken: ${milisec} ms.\n` +
`User agent: ${userAgent}`);
}
};

View File

@ -1,7 +1,10 @@
const fs = require('fs');
const assert = require('assert');
const safeRegex = require('safe-regex');
const parseJS = require('@babel/parser').parse;
const traverse = require('@babel/traverse').default;
const safe = require('safe-regex');
const UAParser = require('ua-parser-js');
const { Bots, Emails, CLI } = require('ua-parser-js/extensions');
const Ext = require('ua-parser-js/extensions');
describe('Bots', () => {
it('Can detect bots', () => {
@ -14,23 +17,53 @@ describe('Bots', () => {
const outlook = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; Microsoft Outlook 16.0.9126; Microsoft Outlook 16.0.9126; ms-office; MSOffice 16)';
const thunderbird = 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.13.0';
const botParser = new UAParser(Bots);
const botParser = new UAParser(Ext.Bots);
assert.deepEqual(botParser.setUA(googleBot).getBrowser(), {name: "Googlebot-Video", version: "1.0", major: "1", type: "bot"});
assert.deepEqual(botParser.setUA(msnBot).getBrowser(), {name: "msnbot-media", version: "1.1", major: "1", type: "bot"});
assert.deepEqual(botParser.setUA(bingPreview).getBrowser(), {name: "BingPreview", version: "1.0b", major: "1", type: "bot"});
assert.deepEqual(botParser.setUA(opera).getBrowser(), {name: "Opera", version: "8.5", major: "8"});
// try merging Bots & CLIs
const botsAndCLIs = { browser : [...Bots.browser, ...CLI.browser]};
const botsAndCLIs = { browser : [...Ext.Bots.browser, ...Ext.CLIs.browser]};
const botsAndCLIsParser = new UAParser(botsAndCLIs);
assert.deepEqual(botsAndCLIsParser.setUA(wget).getBrowser(), {name: "Wget", version: "1.21.1", major: "1", type:"cli"});
assert.deepEqual(botsAndCLIsParser.setUA(facebookBot).getBrowser(), {name: "FacebookBot", version: "1.0", major: "1", type:"bot"});
const emailParser = new UAParser(Emails);
const emailParser = new UAParser(Ext.Emails);
assert.deepEqual(emailParser.setUA(outlook).getBrowser(), {name: "Microsoft Outlook", version: "16.0.9126", major: "16", type: "email"});
assert.deepEqual(emailParser.setUA(thunderbird).getBrowser(), {name: "Thunderbird", version: "78.13.0", major: "78", type: "email"});
});
});
// TODO : move test spec to JSON file
// TODO : check for safe-regex
describe('Testing regexes', () => {
let regexes;
before('Read main js file', () => {
let code = fs.readFileSync('src/extensions/ua-parser-extensions.js', 'utf8').toString();
let ast = parseJS(code, { sourceType: 'script' });
regexes = [];
traverse(ast, {
RegExpLiteral: (path) => {
regexes.push(path.node.pattern);
}
});
if (regexes.length === 0) {
throw new Error('Regexes cannot be empty!');
}
});
describe('Begin testing', () => {
it('all regexes in extension file', () => {
regexes.forEach(regex => {
describe('Test against `safe-regex` : ' + regex, () => {
it('should be safe from potentially vulnerable regex', () => {
assert.strictEqual(safe(regex), true);
});
});
});
});
});
});

View File

@ -4,7 +4,7 @@ var assert = require('assert');
var requirejs = require('requirejs');
var parseJS = require('@babel/parser').parse;
var traverse = require('@babel/traverse').default;
var UAParser = require('../src/ua-parser');
var UAParser = require('ua-parser-js');
var browsers = require('./specs/browser-all.json');
var cpus = require('./specs/cpu-all.json');
var devices = require('./specs/device-all.json');
@ -159,7 +159,7 @@ describe('Testing regexes', function () {
var regexes;
before('Read main js file', function () {
var code = fs.readFileSync('src/ua-parser.js', 'utf8').toString();
var code = fs.readFileSync('src/main/ua-parser.js', 'utf8').toString();
var ast = parseJS(code, { sourceType: "script" });
regexes = [];
traverse(ast, {