tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ua.js (3107B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 const BROWSERS = [
      8  {
      9    name: "Firefox",
     10    mustContain: new RegExp(`(?:Firefox|FxiOS)\/(${getVersionRegex(1, 1)})`),
     11  },
     12  {
     13    name: "Opera",
     14    mustContain: new RegExp(`(?:OPR|Opera)\/(${getVersionRegex(1, 1)})`),
     15  },
     16  {
     17    name: "Safari",
     18    mustContain: new RegExp(`Version\/(${getVersionRegex(1, 1)}).+Safari`),
     19    mustNotContain: new RegExp("Chrome|Chromium"),
     20  },
     21  {
     22    name: "Edge",
     23    mustContain: new RegExp(`Edge\/(${getVersionRegex(0, 1)})`),
     24  },
     25  {
     26    name: "Chrome",
     27    mustContain: new RegExp(`(?:Chrome|CriOS)\/(${getVersionRegex(1, 1)})`),
     28  },
     29  {
     30    name: "IE",
     31    mustContain: new RegExp(`MSIE (${getVersionRegex(1, 1)})`),
     32  },
     33 ];
     34 
     35 const OSES = [
     36  {
     37    name: "iOS",
     38    minMinorVersionCount: 0,
     39    mustContain: new RegExp(`CPU iPhone OS (${getVersionRegex(0, 2)})`),
     40  },
     41  {
     42    name: "iPadOS",
     43    minMinorVersionCount: 0,
     44    mustContain: new RegExp(`CPU OS (${getVersionRegex(0, 2)})`),
     45  },
     46  {
     47    name: "Windows Phone",
     48    minMinorVersionCount: 1,
     49    mustContain: new RegExp(`Windows Phone (${getVersionRegex(1, 2)})`),
     50  },
     51  {
     52    name: "Chrome OS",
     53    minMinorVersionCount: 1,
     54    mustContain: new RegExp(`CrOS .+ (${getVersionRegex(1, 2)})`),
     55  },
     56  {
     57    name: "Android",
     58    minMinorVersionCount: 0,
     59    mustContain: new RegExp(`Android (${getVersionRegex(0, 2)})`),
     60  },
     61  {
     62    name: "Windows NT",
     63    minMinorVersionCount: 1,
     64    mustContain: new RegExp(`Windows NT (${getVersionRegex(1, 2)})`),
     65  },
     66  {
     67    name: "Mac OSX",
     68    minMinorVersionCount: 1,
     69    mustContain: new RegExp(`Intel Mac OS X (${getVersionRegex(1, 2)})`),
     70  },
     71  {
     72    name: "Linux",
     73    mustContain: new RegExp("Linux"),
     74  },
     75 ];
     76 
     77 function getVersionRegex(minMinorVersionCount, maxMinorVersionCount) {
     78  return `\\d+(?:[._][0-9a-z]+){${minMinorVersionCount},${maxMinorVersionCount}}`;
     79 }
     80 
     81 function detect(ua, dataset) {
     82  for (const {
     83    name,
     84    mustContain,
     85    mustNotContain,
     86    minMinorVersionCount,
     87  } of dataset) {
     88    const result = mustContain.exec(ua);
     89 
     90    if (!result) {
     91      continue;
     92    }
     93 
     94    if (mustNotContain && mustNotContain.test(ua)) {
     95      continue;
     96    }
     97 
     98    let version = null;
     99 
    100    if (result && result.length === 2) {
    101      // Remove most minor version if that expresses 0.
    102      let parts = result[1].match(/([0-9a-z]+)/g);
    103      parts = parts.reverse();
    104      const validVersionIndex = parts.findIndex(
    105        part => parseInt(part, 10) !== 0
    106      );
    107      if (validVersionIndex !== -1) {
    108        parts = parts.splice(validVersionIndex);
    109        for (let i = 0; i < minMinorVersionCount + 1 - parts.length; i++) {
    110          parts.unshift(0);
    111        }
    112      }
    113      version = parts.reverse().join(".");
    114    }
    115 
    116    return { name, version };
    117  }
    118 
    119  return null;
    120 }
    121 
    122 function parseUserAgent(ua) {
    123  return {
    124    browser: detect(ua, BROWSERS),
    125    os: detect(ua, OSES),
    126  };
    127 }
    128 
    129 module.exports = { parseUserAgent };