refactor: finish moving ssh-* scripts to own installers
[webi-installers/.git] / _webi / ua-detect.js
1 'use strict';
2
3 function getRequest(req) {
4   var ua = req.headers['user-agent'] || '';
5   var os = req.query.os;
6   var arch = req.query.arch;
7   var scheme = req.socket.encrypted ? 'https' : 'http';
8   var host = req.headers.host || 'beta.webinstall.dev';
9   var url = scheme + '://' + host + '/api/debug';
10   if (os && arch) {
11     ua = os + ' ' + arch;
12   } else if (os || arch) {
13     ua = os || arch;
14   }
15
16   return {
17     unix: 'curl -fsSA "$(uname -a)" ' + url,
18     windows: 'curl.exe -fsSA "MS $Env:PROCESSOR_ARCHITECTURE" ' + url,
19     ua: ua,
20     os: uaDetect.os(ua),
21     arch: uaDetect.arch(ua)
22   };
23 }
24
25 function getOs(ua) {
26   if ('-' === ua) {
27     return '-';
28   }
29
30   if (/Android/i.test(ua)) {
31     // android must be tested before linux
32     return 'android';
33   } else if (/iOS|iPhone|Macintosh|Darwin|OS\s*X|macOS|mac/i.test(ua)) {
34     return 'macos';
35   } else if (/Linux/i.test(ua) && !/cygwin|msysgit/i.test(ua)) {
36     // It's the year of the Linux Desktop!
37     // See also http://www.mslinux.org/
38     // 'linux' must be tested before 'Microsoft' because WSL
39     // (TODO: does this affect cygwin / msysgit?)
40     return 'linux';
41   } else if (/^ms$|Microsoft|Windows|win32|win|PowerShell/i.test(ua)) {
42     // 'win' must be tested after 'darwin'
43     return 'windows';
44   } else if (/Linux|curl|wget/i.test(ua)) {
45     // test 'linux' again, after 'win'
46     return 'linux';
47   } else {
48     return 'error';
49   }
50 }
51
52 function getArch(ua) {
53   if ('-' === ua) {
54     return '-';
55   }
56
57   // quick hack for Apple Silicon M1
58   // Native:  Darwin boomer.local 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec  2 20:40:21 PST 2020; root:xnu-7195.60.75~1/RELEASE_ARM64_T8101 arm64
59   // Resetta: Darwin boomer.local 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec  2 20:40:21 PST 2020; root:xnu-7195.60.75~1/RELEASE_ARM64_T8101 x86_64
60   ua = ua.replace(/xnu-.*RELEASE_[^\s]*/, '');
61   if (/aarch64|arm64|arm8|armv8/i.test(ua)) {
62     return 'arm64';
63   } else if (/aarch|arm7|armv7/i.test(ua)) {
64     return 'armv7l';
65   } else if (/arm6|armv6/i.test(ua)) {
66     return 'armv6l';
67   } else if (/ppc64/i.test(ua)) {
68     return 'ppc64';
69   } else if (/mips64/i.test(ua)) {
70     return 'mips64';
71   } else if (/mips/i.test(ua)) {
72     return 'mips';
73   } else if (/(amd64|x64|_64)\b/i.test(ua)) {
74     // must come after ppc64/mips64
75     return 'amd64';
76   } else if (/(3|6|x|_)86\b/i.test(ua)) {
77     // must come after x86_64
78     return 'x86';
79   } else {
80     // TODO handle explicit invalid different
81     return 'error';
82   }
83 }
84
85 var uaDetect = module.exports;
86 uaDetect.os = getOs;
87 uaDetect.arch = getArch;
88 uaDetect.request = getRequest;