@depup/systeminformation 5.31.4-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/util.js ADDED
@@ -0,0 +1,2760 @@
1
+ 'use strict';
2
+ // @ts-check
3
+ // ==================================================================================
4
+ // utils.js
5
+ // ----------------------------------------------------------------------------------
6
+ // Description: System Information - library
7
+ // for Node.js
8
+ // Copyright: (c) 2014 - 2026
9
+ // Author: Sebastian Hildebrandt
10
+ // ----------------------------------------------------------------------------------
11
+ // License: MIT
12
+ // ==================================================================================
13
+ // 0. helper functions
14
+ // ----------------------------------------------------------------------------------
15
+
16
+ const os = require('os');
17
+ const fs = require('fs');
18
+ const path = require('path');
19
+ const spawn = require('child_process').spawn;
20
+ const exec = require('child_process').exec;
21
+ const execSync = require('child_process').execSync;
22
+ const util = require('util');
23
+
24
+ const _platform = process.platform;
25
+ const _linux = _platform === 'linux' || _platform === 'android';
26
+ const _darwin = _platform === 'darwin';
27
+ const _windows = _platform === 'win32';
28
+ const _freebsd = _platform === 'freebsd';
29
+ const _openbsd = _platform === 'openbsd';
30
+ const _netbsd = _platform === 'netbsd';
31
+
32
+ let _cores = 0;
33
+ let codepage = '';
34
+ let _smartMonToolsInstalled = null;
35
+ let _rpi_cpuinfo = null;
36
+
37
+ const WINDIR = process.env.WINDIR || 'C:\\Windows';
38
+
39
+ // powerShell
40
+ let _psChild;
41
+ let _psResult = '';
42
+ const _psCmds = [];
43
+ let _psPersistent = false;
44
+ let _powerShell = '';
45
+ const _psToUTF8 = '$OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8 ; ';
46
+ const _psCmdStart = '--###START###--';
47
+ const _psError = '--ERROR--';
48
+ const _psCmdSeperator = '--###ENDCMD###--';
49
+ const _psIdSeperator = '--##ID##--';
50
+
51
+ const execOptsWin = {
52
+ windowsHide: true,
53
+ maxBuffer: 1024 * 102400,
54
+ encoding: 'UTF-8',
55
+ env: Object.assign({}, process.env, { LANG: 'en_US.UTF-8' })
56
+ };
57
+
58
+ const execOptsLinux = {
59
+ maxBuffer: 1024 * 102400,
60
+ encoding: 'UTF-8',
61
+ stdio: ['pipe', 'pipe', 'ignore']
62
+ };
63
+
64
+ function toInt(value) {
65
+ let result = parseInt(value, 10);
66
+ if (isNaN(result)) {
67
+ result = 0;
68
+ }
69
+ return result;
70
+ }
71
+
72
+ function splitByNumber(str) {
73
+ let numberStarted = false;
74
+ let num = '';
75
+ let cpart = '';
76
+ for (const c of str) {
77
+ if ((c >= '0' && c <= '9') || numberStarted) {
78
+ numberStarted = true;
79
+ num += c;
80
+ } else {
81
+ cpart += c;
82
+ }
83
+ }
84
+ return [cpart, num];
85
+ }
86
+
87
+ const stringObj = new String();
88
+ const stringReplace = new String().replace;
89
+ const stringToLower = new String().toLowerCase;
90
+ const stringToString = new String().toString;
91
+ const stringSubstr = new String().substr;
92
+ const stringSubstring = new String().substring;
93
+ const stringTrim = new String().trim;
94
+ const stringStartWith = new String().startsWith;
95
+ const mathMin = Math.min;
96
+
97
+ function isFunction(functionToCheck) {
98
+ let getType = {};
99
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
100
+ }
101
+
102
+ function unique(obj) {
103
+ const uniques = [];
104
+ const stringify = {};
105
+ for (let i = 0; i < obj.length; i++) {
106
+ let keys = Object.keys(obj[i]);
107
+ keys.sort((a, b) => {
108
+ return a - b;
109
+ });
110
+ let str = '';
111
+ for (let j = 0; j < keys.length; j++) {
112
+ str += JSON.stringify(keys[j]);
113
+ str += JSON.stringify(obj[i][keys[j]]);
114
+ }
115
+ if (!{}.hasOwnProperty.call(stringify, str)) {
116
+ uniques.push(obj[i]);
117
+ stringify[str] = true;
118
+ }
119
+ }
120
+ return uniques;
121
+ }
122
+
123
+ function sortByKey(array, keys) {
124
+ return array.sort((a, b) => {
125
+ let x = '';
126
+ let y = '';
127
+ keys.forEach((key) => {
128
+ x = x + a[key];
129
+ y = y + b[key];
130
+ });
131
+ return x < y ? -1 : x > y ? 1 : 0;
132
+ });
133
+ }
134
+
135
+ function cores() {
136
+ if (_cores === 0) {
137
+ _cores = os.cpus().length;
138
+ }
139
+ return _cores;
140
+ }
141
+
142
+ function getValue(lines, property, separator, trimmed, lineMatch) {
143
+ separator = separator || ':';
144
+ property = property.toLowerCase();
145
+ trimmed = trimmed || false;
146
+ lineMatch = lineMatch || false;
147
+ let result = '';
148
+ lines.some((line) => {
149
+ let lineLower = line.toLowerCase().replace(/\t/g, '');
150
+ if (trimmed) {
151
+ lineLower = lineLower.trim();
152
+ }
153
+ if (lineLower.startsWith(property) && (lineMatch ? lineLower.match(property + separator) || lineLower.match(property + ' ' + separator) : true)) {
154
+ const parts = trimmed ? line.trim().split(separator) : line.split(separator);
155
+ if (parts.length >= 2) {
156
+ parts.shift();
157
+ result = parts.join(separator).trim();
158
+ return true;
159
+ }
160
+ }
161
+ return false;
162
+ });
163
+ return result;
164
+ }
165
+
166
+ function decodeEscapeSequence(str, base) {
167
+ base = base || 16;
168
+ return str.replace(/\\x([0-9A-Fa-f]{2})/g, function () {
169
+ return String.fromCharCode(parseInt(arguments[1], base));
170
+ });
171
+ }
172
+
173
+ function detectSplit(str) {
174
+ let seperator = '';
175
+ let part = 0;
176
+ str.split('').forEach((element) => {
177
+ if (element >= '0' && element <= '9') {
178
+ if (part === 1) {
179
+ part++;
180
+ }
181
+ } else {
182
+ if (part === 0) {
183
+ part++;
184
+ }
185
+ if (part === 1) {
186
+ seperator += element;
187
+ }
188
+ }
189
+ });
190
+ return seperator;
191
+ }
192
+
193
+ function parseTime(t, pmDesignator) {
194
+ pmDesignator = pmDesignator || '';
195
+ t = t.toUpperCase();
196
+ let hour = 0;
197
+ let min = 0;
198
+ const splitter = detectSplit(t);
199
+ const parts = t.split(splitter);
200
+ if (parts.length >= 2) {
201
+ if (parts[2]) {
202
+ parts[1] += parts[2];
203
+ }
204
+ let isPM =
205
+ (parts[1] && parts[1].toLowerCase().indexOf('pm') > -1) ||
206
+ parts[1].toLowerCase().indexOf('p.m.') > -1 ||
207
+ parts[1].toLowerCase().indexOf('p. m.') > -1 ||
208
+ parts[1].toLowerCase().indexOf('n') > -1 ||
209
+ parts[1].toLowerCase().indexOf('ch') > -1 ||
210
+ parts[1].toLowerCase().indexOf('ös') > -1 ||
211
+ (pmDesignator && parts[1].toLowerCase().indexOf(pmDesignator) > -1);
212
+ hour = parseInt(parts[0], 10);
213
+ min = parseInt(parts[1], 10);
214
+ hour = isPM && hour < 12 ? hour + 12 : hour;
215
+ return ('0' + hour).substr(-2) + ':' + ('0' + min).substr(-2);
216
+ }
217
+ }
218
+
219
+ function parseDateTime(dt, culture) {
220
+ const result = {
221
+ date: '',
222
+ time: ''
223
+ };
224
+ culture = culture || {};
225
+ const dateFormat = (culture.dateFormat || '').toLowerCase();
226
+ const pmDesignator = culture.pmDesignator || '';
227
+
228
+ const parts = dt.split(' ');
229
+ if (parts[0]) {
230
+ if (parts[0].indexOf('/') >= 0) {
231
+ // Dateformat: mm/dd/yyyy or dd/mm/yyyy or dd/mm/yy or yyyy/mm/dd
232
+ const dtparts = parts[0].split('/');
233
+ if (dtparts.length === 3) {
234
+ if (dtparts[0].length === 4) {
235
+ // Dateformat: yyyy/mm/dd
236
+ result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
237
+ } else if (dtparts[2].length === 2) {
238
+ if (dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) {
239
+ // Dateformat: mm/dd/yy
240
+ result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
241
+ } else {
242
+ // Dateformat: dd/mm/yy
243
+ result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
244
+ }
245
+ } else {
246
+ // Dateformat: mm/dd/yyyy or dd/mm/yyyy
247
+ const isEN =
248
+ dt.toLowerCase().indexOf('pm') > -1 ||
249
+ dt.toLowerCase().indexOf('p.m.') > -1 ||
250
+ dt.toLowerCase().indexOf('p. m.') > -1 ||
251
+ dt.toLowerCase().indexOf('am') > -1 ||
252
+ dt.toLowerCase().indexOf('a.m.') > -1 ||
253
+ dt.toLowerCase().indexOf('a. m.') > -1;
254
+ if ((isEN || dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) && dateFormat.indexOf('dd/') !== 0) {
255
+ // Dateformat: mm/dd/yyyy
256
+ result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
257
+ } else {
258
+ // Dateformat: dd/mm/yyyy
259
+ result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
260
+ }
261
+ }
262
+ }
263
+ }
264
+ if (parts[0].indexOf('.') >= 0) {
265
+ const dtparts = parts[0].split('.');
266
+ if (dtparts.length === 3) {
267
+ if (dateFormat.indexOf('.d.') > -1 || dateFormat.indexOf('.dd.') > -1) {
268
+ // Dateformat: mm.dd.yyyy
269
+ result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
270
+ } else {
271
+ // Dateformat: dd.mm.yyyy
272
+ result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
273
+ }
274
+ }
275
+ }
276
+ if (parts[0].indexOf('-') >= 0) {
277
+ // Dateformat: yyyy-mm-dd
278
+ const dtparts = parts[0].split('-');
279
+ if (dtparts.length === 3) {
280
+ result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
281
+ }
282
+ }
283
+ }
284
+ if (parts[1]) {
285
+ parts.shift();
286
+ const time = parts.join(' ');
287
+ result.time = parseTime(time, pmDesignator);
288
+ }
289
+ return result;
290
+ }
291
+
292
+ function parseHead(head, rights) {
293
+ let space = rights > 0;
294
+ let count = 1;
295
+ let from = 0;
296
+ let to = 0;
297
+ const result = [];
298
+ for (let i = 0; i < head.length; i++) {
299
+ if (count <= rights) {
300
+ if (/\s/.test(head[i]) && !space) {
301
+ to = i - 1;
302
+ result.push({
303
+ from: from,
304
+ to: to + 1,
305
+ cap: head.substring(from, to + 1)
306
+ });
307
+ from = to + 2;
308
+ count++;
309
+ }
310
+ space = head[i] === ' ';
311
+ } else {
312
+ if (!/\s/.test(head[i]) && space) {
313
+ to = i - 1;
314
+ if (from < to) {
315
+ result.push({
316
+ from: from,
317
+ to: to,
318
+ cap: head.substring(from, to)
319
+ });
320
+ }
321
+ from = to + 1;
322
+ count++;
323
+ }
324
+ space = head[i] === ' ';
325
+ }
326
+ }
327
+ to = 5000;
328
+ result.push({
329
+ from: from,
330
+ to: to,
331
+ cap: head.substring(from, to)
332
+ });
333
+ let len = result.length;
334
+ for (let i = 0; i < len; i++) {
335
+ if (result[i].cap.replace(/\s/g, '').length === 0) {
336
+ if (i + 1 < len) {
337
+ result[i].to = result[i + 1].to;
338
+ result[i].cap = result[i].cap + result[i + 1].cap;
339
+ result.splice(i + 1, 1);
340
+ len = len - 1;
341
+ }
342
+ }
343
+ }
344
+ return result;
345
+ }
346
+
347
+ function findObjectByKey(array, key, value) {
348
+ for (let i = 0; i < array.length; i++) {
349
+ if (array[i][key] === value) {
350
+ return i;
351
+ }
352
+ }
353
+ return -1;
354
+ }
355
+
356
+ function getPowershell() {
357
+ _powerShell = 'powershell.exe';
358
+ if (_windows) {
359
+ const defaultPath = `${WINDIR}\\system32\\WindowsPowerShell\\v1.0\\powershell.exe`;
360
+ if (fs.existsSync(defaultPath)) {
361
+ _powerShell = defaultPath;
362
+ }
363
+ }
364
+ }
365
+
366
+ function getVboxmanage() {
367
+ return _windows ? `"${process.env.VBOX_INSTALL_PATH || process.env.VBOX_MSI_INSTALL_PATH}\\VBoxManage.exe"` : 'vboxmanage';
368
+ }
369
+
370
+ function powerShellProceedResults(data) {
371
+ let id = '';
372
+ let parts;
373
+ let res = '';
374
+ // startID
375
+ if (data.indexOf(_psCmdStart) >= 0) {
376
+ parts = data.split(_psCmdStart);
377
+ const parts2 = parts[1].split(_psIdSeperator);
378
+ id = parts2[0];
379
+ if (parts2.length > 1) {
380
+ data = parts2.slice(1).join(_psIdSeperator);
381
+ }
382
+ }
383
+ // result;
384
+ if (data.indexOf(_psCmdSeperator) >= 0) {
385
+ parts = data.split(_psCmdSeperator);
386
+ res = parts[0];
387
+ }
388
+ let remove = -1;
389
+ for (let i = 0; i < _psCmds.length; i++) {
390
+ if (_psCmds[i].id === id) {
391
+ remove = i;
392
+ _psCmds[i].callback(res);
393
+ }
394
+ }
395
+ if (remove >= 0) {
396
+ _psCmds.splice(remove, 1);
397
+ }
398
+ }
399
+
400
+ function powerShellStart() {
401
+ if (!_psChild) {
402
+ _psChild = spawn(_powerShell, ['-NoProfile', '-NoLogo', '-InputFormat', 'Text', '-NoExit', '-Command', '-'], {
403
+ stdio: 'pipe',
404
+ windowsHide: true,
405
+ maxBuffer: 1024 * 102400,
406
+ encoding: 'UTF-8',
407
+ env: Object.assign({}, process.env, { LANG: 'en_US.UTF-8' })
408
+ });
409
+ if (_psChild && _psChild.pid) {
410
+ _psPersistent = true;
411
+ _psChild.stdout.on('data', (data) => {
412
+ _psResult = _psResult + data.toString('utf8');
413
+ if (data.indexOf(_psCmdSeperator) >= 0) {
414
+ powerShellProceedResults(_psResult);
415
+ _psResult = '';
416
+ }
417
+ });
418
+ _psChild.stderr.on('data', () => {
419
+ powerShellProceedResults(_psResult + _psError);
420
+ });
421
+ _psChild.on('error', () => {
422
+ powerShellProceedResults(_psResult + _psError);
423
+ });
424
+ _psChild.on('close', () => {
425
+ if (_psChild) {
426
+ _psChild.kill();
427
+ }
428
+ });
429
+ }
430
+ }
431
+ }
432
+
433
+ function powerShellRelease() {
434
+ try {
435
+ if (_psChild) {
436
+ _psChild.stdin.write('exit' + os.EOL);
437
+ _psChild.stdin.end();
438
+ }
439
+ } catch {
440
+ if (_psChild) {
441
+ _psChild.kill();
442
+ }
443
+ }
444
+ _psPersistent = false;
445
+ _psChild = null;
446
+ }
447
+
448
+ function powerShell(cmd) {
449
+ if (_psPersistent) {
450
+ const id = Math.random().toString(36).substring(2, 12);
451
+ return new Promise((resolve) => {
452
+ process.nextTick(() => {
453
+ function callback(data) {
454
+ resolve(data);
455
+ }
456
+ _psCmds.push({
457
+ id,
458
+ cmd,
459
+ callback,
460
+ start: new Date()
461
+ });
462
+ try {
463
+ if (_psChild && _psChild.pid) {
464
+ _psChild.stdin.write(_psToUTF8 + 'echo ' + _psCmdStart + id + _psIdSeperator + '; ' + os.EOL + cmd + os.EOL + 'echo ' + _psCmdSeperator + os.EOL);
465
+ }
466
+ } catch {
467
+ resolve('');
468
+ }
469
+ });
470
+ });
471
+ } else {
472
+ let result = '';
473
+
474
+ return new Promise((resolve) => {
475
+ process.nextTick(() => {
476
+ try {
477
+ const osVersion = os.release().split('.').map(Number);
478
+ // windows 7 compatibility issue
479
+ const spanOptions =
480
+ osVersion[0] < 10
481
+ ? ['-NoProfile', '-NoLogo', '-InputFormat', 'Text', '-NoExit', '-ExecutionPolicy', 'Unrestricted', '-Command', '-']
482
+ : ['-NoProfile', '-NoLogo', '-InputFormat', 'Text', '-ExecutionPolicy', 'Unrestricted', '-Command', _psToUTF8 + cmd];
483
+ const child = spawn(_powerShell, spanOptions, {
484
+ stdio: 'pipe',
485
+ windowsHide: true,
486
+ maxBuffer: 1024 * 102400,
487
+ encoding: 'UTF-8',
488
+ env: Object.assign({}, process.env, { LANG: 'en_US.UTF-8' })
489
+ });
490
+
491
+ if (child && !child.pid) {
492
+ child.on('error', () => {
493
+ resolve(result);
494
+ });
495
+ }
496
+ if (child && child.pid) {
497
+ child.stdout.on('data', (data) => {
498
+ result = result + data.toString('utf8');
499
+ });
500
+ child.stderr.on('data', () => {
501
+ child.kill();
502
+ resolve(result);
503
+ });
504
+ child.on('close', () => {
505
+ child.kill();
506
+
507
+ resolve(result);
508
+ });
509
+ child.on('error', () => {
510
+ child.kill();
511
+ resolve(result);
512
+ });
513
+ if (osVersion[0] < 10) {
514
+ try {
515
+ child.stdin.write(_psToUTF8 + cmd + os.EOL);
516
+ child.stdin.write('exit' + os.EOL);
517
+ child.stdin.end();
518
+ } catch {
519
+ child.kill();
520
+ resolve(result);
521
+ }
522
+ }
523
+ } else {
524
+ resolve(result);
525
+ }
526
+ } catch {
527
+ resolve(result);
528
+ }
529
+ });
530
+ });
531
+ }
532
+ }
533
+
534
+ function execSafe(cmd, args, options) {
535
+ let result = '';
536
+ options = options || {};
537
+
538
+ return new Promise((resolve) => {
539
+ process.nextTick(() => {
540
+ try {
541
+ const child = spawn(cmd, args, options);
542
+
543
+ if (child && !child.pid) {
544
+ child.on('error', () => {
545
+ resolve(result);
546
+ });
547
+ }
548
+ if (child && child.pid) {
549
+ child.stdout.on('data', (data) => {
550
+ result += data.toString();
551
+ });
552
+ child.on('close', () => {
553
+ child.kill();
554
+ resolve(result);
555
+ });
556
+ child.on('error', () => {
557
+ child.kill();
558
+ resolve(result);
559
+ });
560
+ } else {
561
+ resolve(result);
562
+ }
563
+ } catch {
564
+ resolve(result);
565
+ }
566
+ });
567
+ });
568
+ }
569
+
570
+ function getCodepage() {
571
+ if (_windows) {
572
+ if (!codepage) {
573
+ try {
574
+ const stdout = execSync('chcp', execOptsWin);
575
+ const lines = stdout.toString().split('\r\n');
576
+ const parts = lines[0].split(':');
577
+ codepage = parts.length > 1 ? parts[1].replace('.', '').trim() : '';
578
+ } catch {
579
+ codepage = '437';
580
+ }
581
+ }
582
+ return codepage;
583
+ }
584
+ if (_linux || _darwin || _freebsd || _openbsd || _netbsd) {
585
+ if (!codepage) {
586
+ try {
587
+ const stdout = execSync('echo $LANG', execOptsLinux);
588
+ const lines = stdout.toString().split('\r\n');
589
+ const parts = lines[0].split('.');
590
+ codepage = parts.length > 1 ? parts[1].trim() : '';
591
+ if (!codepage) {
592
+ codepage = 'UTF-8';
593
+ }
594
+ } catch {
595
+ codepage = 'UTF-8';
596
+ }
597
+ }
598
+ return codepage;
599
+ }
600
+ }
601
+
602
+ function smartMonToolsInstalled() {
603
+ if (_smartMonToolsInstalled !== null) {
604
+ return _smartMonToolsInstalled;
605
+ }
606
+ _smartMonToolsInstalled = false;
607
+ if (_windows) {
608
+ try {
609
+ const pathArray = execSync('WHERE smartctl 2>nul', execOptsWin).toString().split('\r\n');
610
+ if (pathArray && pathArray.length) {
611
+ _smartMonToolsInstalled = pathArray[0].indexOf(':\\') >= 0;
612
+ } else {
613
+ _smartMonToolsInstalled = false;
614
+ }
615
+ } catch {
616
+ _smartMonToolsInstalled = false;
617
+ }
618
+ }
619
+ if (_linux || _darwin || _freebsd || _openbsd || _netbsd) {
620
+ try {
621
+ const pathArray = execSync('which smartctl 2>/dev/null', execOptsLinux).toString().split('\r\n');
622
+ _smartMonToolsInstalled = pathArray.length > 0;
623
+ } catch {
624
+ util.noop();
625
+ }
626
+ }
627
+ return _smartMonToolsInstalled;
628
+ }
629
+
630
+ // reference values: https://elinux.org/RPi_HardwareHistory
631
+ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
632
+ // https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#hardware-revision-codes
633
+
634
+ function isRaspberry(cpuinfo) {
635
+ const PI_MODEL_NO = ['BCM2708', 'BCM2709', 'BCM2710', 'BCM2711', 'BCM2712', 'BCM2835', 'BCM2836', 'BCM2837', 'BCM2837B0'];
636
+ if (_rpi_cpuinfo !== null) {
637
+ cpuinfo = _rpi_cpuinfo;
638
+ } else if (cpuinfo === undefined) {
639
+ try {
640
+ cpuinfo = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
641
+ _rpi_cpuinfo = cpuinfo;
642
+ } catch {
643
+ return false;
644
+ }
645
+ }
646
+
647
+ const hardware = getValue(cpuinfo, 'hardware');
648
+ const model = getValue(cpuinfo, 'model');
649
+ return (hardware && PI_MODEL_NO.indexOf(hardware) > -1) || (model && model.indexOf('Raspberry Pi') > -1);
650
+ }
651
+
652
+ function isRaspbian() {
653
+ let osrelease = [];
654
+ try {
655
+ osrelease = fs.readFileSync('/etc/os-release', { encoding: 'utf8' }).toString().split('\n');
656
+ } catch {
657
+ return false;
658
+ }
659
+ const id = getValue(osrelease, 'id', '=');
660
+ return id && id.indexOf('raspbian') > -1;
661
+ }
662
+
663
+ function execWin(cmd, opts, callback) {
664
+ if (!callback) {
665
+ callback = opts;
666
+ opts = execOptsWin;
667
+ }
668
+ let newCmd = 'chcp 65001 > nul && cmd /C ' + cmd + ' && chcp ' + codepage + ' > nul';
669
+ exec(newCmd, opts, (error, stdout) => {
670
+ callback(error, stdout);
671
+ });
672
+ }
673
+
674
+ function darwinXcodeExists() {
675
+ const cmdLineToolsExists = fs.existsSync('/Library/Developer/CommandLineTools/usr/bin/');
676
+ const xcodeAppExists = fs.existsSync('/Applications/Xcode.app/Contents/Developer/Tools');
677
+ const xcodeExists = fs.existsSync('/Library/Developer/Xcode/');
678
+ return cmdLineToolsExists || xcodeExists || xcodeAppExists;
679
+ }
680
+
681
+ function nanoSeconds() {
682
+ const time = process.hrtime();
683
+ if (!Array.isArray(time) || time.length !== 2) {
684
+ return 0;
685
+ }
686
+ return +time[0] * 1e9 + +time[1];
687
+ }
688
+
689
+ function countUniqueLines(lines, startingWith) {
690
+ startingWith = startingWith || '';
691
+ const uniqueLines = [];
692
+ lines.forEach((line) => {
693
+ if (line.startsWith(startingWith)) {
694
+ if (uniqueLines.indexOf(line) === -1) {
695
+ uniqueLines.push(line);
696
+ }
697
+ }
698
+ });
699
+ return uniqueLines.length;
700
+ }
701
+
702
+ function countLines(lines, startingWith) {
703
+ startingWith = startingWith || '';
704
+ const uniqueLines = [];
705
+ lines.forEach((line) => {
706
+ if (line.startsWith(startingWith)) {
707
+ uniqueLines.push(line);
708
+ }
709
+ });
710
+ return uniqueLines.length;
711
+ }
712
+
713
+ function sanitizeShellString(str, strict) {
714
+ if (typeof strict === 'undefined') {
715
+ strict = false;
716
+ }
717
+ const s = str || '';
718
+ let result = '';
719
+ const l = mathMin(s.length, 2000);
720
+ for (let i = 0; i <= l; i++) {
721
+ if (
722
+ !(
723
+ s[i] === undefined ||
724
+ s[i] === '>' ||
725
+ s[i] === '<' ||
726
+ s[i] === '*' ||
727
+ s[i] === '?' ||
728
+ s[i] === '[' ||
729
+ s[i] === ']' ||
730
+ s[i] === '|' ||
731
+ s[i] === '˚' ||
732
+ s[i] === '$' ||
733
+ s[i] === ';' ||
734
+ s[i] === '&' ||
735
+ s[i] === ']' ||
736
+ s[i] === '#' ||
737
+ s[i] === '\\' ||
738
+ s[i] === '\t' ||
739
+ s[i] === '\n' ||
740
+ s[i] === '\r' ||
741
+ s[i] === "'" ||
742
+ s[i] === '`' ||
743
+ s[i] === '"' ||
744
+ s[i].length > 1 ||
745
+ (strict && s[i] === '(') ||
746
+ (strict && s[i] === ')') ||
747
+ (strict && s[i] === '@') ||
748
+ (strict && s[i] === ' ') ||
749
+ (strict && s[i] === '{') ||
750
+ (strict && s[i] === ';') ||
751
+ (strict && s[i] === '}')
752
+ )
753
+ ) {
754
+ result = result + s[i];
755
+ }
756
+ }
757
+ return result;
758
+ }
759
+
760
+ function isPrototypePolluted() {
761
+ const s = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
762
+ let notPolluted = true;
763
+ let st = '';
764
+
765
+ try {
766
+ st.__proto__.replace = stringReplace;
767
+ st.__proto__.toLowerCase = stringToLower;
768
+ st.__proto__.toString = stringToString;
769
+ st.__proto__.substr = stringSubstr;
770
+ st.__proto__.substring = stringSubstring;
771
+ st.__proto__.trim = stringTrim;
772
+ st.__proto__.startsWith = stringStartWith;
773
+ } catch (e) {
774
+ Object.setPrototypeOf(st, stringObj);
775
+ }
776
+ notPolluted = notPolluted || s.length !== 62;
777
+ const ms = Date.now();
778
+ if (typeof ms === 'number' && ms > 1600000000000) {
779
+ const l = (ms % 100) + 15;
780
+ for (let i = 0; i < l; i++) {
781
+ const r = Math.random() * 61.99999999 + 1;
782
+ const rs = parseInt(Math.floor(r).toString(), 10);
783
+ const rs2 = parseInt(r.toString().split('.')[0], 10);
784
+ const q = Math.random() * 61.99999999 + 1;
785
+ const qs = parseInt(Math.floor(q).toString(), 10);
786
+ const qs2 = parseInt(q.toString().split('.')[0], 10);
787
+ notPolluted = notPolluted && r !== q;
788
+ notPolluted = notPolluted && rs === rs2 && qs === qs2;
789
+ st += s[rs - 1];
790
+ }
791
+ notPolluted = notPolluted && st.length === l;
792
+ // string manipulation
793
+ let p = Math.random() * l * 0.9999999999;
794
+ let stm = st.substr(0, p) + ' ' + st.substr(p, 2000);
795
+ try {
796
+ stm.__proto__.replace = stringReplace;
797
+ } catch (e) {
798
+ Object.setPrototypeOf(stm, stringObj);
799
+ }
800
+ let sto = stm.replace(/ /g, '');
801
+ notPolluted = notPolluted && st === sto;
802
+ p = Math.random() * l * 0.9999999999;
803
+ stm = st.substr(0, p) + '{' + st.substr(p, 2000);
804
+ sto = stm.replace(/{/g, '');
805
+ notPolluted = notPolluted && st === sto;
806
+ p = Math.random() * l * 0.9999999999;
807
+ stm = st.substr(0, p) + '*' + st.substr(p, 2000);
808
+ sto = stm.replace(/\*/g, '');
809
+ notPolluted = notPolluted && st === sto;
810
+ p = Math.random() * l * 0.9999999999;
811
+ stm = st.substr(0, p) + '$' + st.substr(p, 2000);
812
+ sto = stm.replace(/\$/g, '');
813
+ notPolluted = notPolluted && st === sto;
814
+
815
+ // lower
816
+ const stl = st.toLowerCase();
817
+ notPolluted = notPolluted && stl.length === l && stl[l - 1] && !stl[l];
818
+ for (let i = 0; i < l; i++) {
819
+ const s1 = st[i];
820
+ try {
821
+ s1.__proto__.toLowerCase = stringToLower;
822
+ } catch {
823
+ Object.setPrototypeOf(st, stringObj);
824
+ }
825
+ const s2 = stl ? stl[i] : '';
826
+ const s1l = s1.toLowerCase();
827
+ notPolluted = notPolluted && s1l[0] === s2 && s1l[0] && !s1l[1];
828
+ }
829
+ }
830
+ return !notPolluted;
831
+ }
832
+
833
+ function hex2bin(hex) {
834
+ return ('00000000' + parseInt(hex, 16).toString(2)).substr(-8);
835
+ }
836
+
837
+ function getFilesInPath(source) {
838
+ const lstatSync = fs.lstatSync;
839
+ const readdirSync = fs.readdirSync;
840
+ const join = path.join;
841
+
842
+ function isDirectory(source) {
843
+ return lstatSync(source).isDirectory();
844
+ }
845
+ function isFile(source) {
846
+ return lstatSync(source).isFile();
847
+ }
848
+
849
+ function getDirectories(source) {
850
+ return readdirSync(source)
851
+ .map((name) => {
852
+ return join(source, name);
853
+ })
854
+ .filter(isDirectory);
855
+ }
856
+ function getFiles(source) {
857
+ return readdirSync(source)
858
+ .map((name) => {
859
+ return join(source, name);
860
+ })
861
+ .filter(isFile);
862
+ }
863
+
864
+ function getFilesRecursively(source) {
865
+ try {
866
+ const dirs = getDirectories(source);
867
+ const files = dirs
868
+ .map((dir) => {
869
+ return getFilesRecursively(dir);
870
+ })
871
+ .reduce((a, b) => {
872
+ return a.concat(b);
873
+ }, []);
874
+ return files.concat(getFiles(source));
875
+ } catch {
876
+ return [];
877
+ }
878
+ }
879
+
880
+ if (fs.existsSync(source)) {
881
+ return getFilesRecursively(source);
882
+ } else {
883
+ return [];
884
+ }
885
+ }
886
+
887
+ function decodePiCpuinfo(lines) {
888
+ if (_rpi_cpuinfo === null) {
889
+ _rpi_cpuinfo = lines;
890
+ } else if (lines === undefined) {
891
+ lines = _rpi_cpuinfo;
892
+ }
893
+
894
+ // https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
895
+
896
+ const oldRevisionCodes = {
897
+ '0002': {
898
+ type: 'B',
899
+ revision: '1.0',
900
+ memory: 256,
901
+ manufacturer: 'Egoman',
902
+ processor: 'BCM2835'
903
+ },
904
+ '0003': {
905
+ type: 'B',
906
+ revision: '1.0',
907
+ memory: 256,
908
+ manufacturer: 'Egoman',
909
+ processor: 'BCM2835'
910
+ },
911
+ '0004': {
912
+ type: 'B',
913
+ revision: '2.0',
914
+ memory: 256,
915
+ manufacturer: 'Sony UK',
916
+ processor: 'BCM2835'
917
+ },
918
+ '0005': {
919
+ type: 'B',
920
+ revision: '2.0',
921
+ memory: 256,
922
+ manufacturer: 'Qisda',
923
+ processor: 'BCM2835'
924
+ },
925
+ '0006': {
926
+ type: 'B',
927
+ revision: '2.0',
928
+ memory: 256,
929
+ manufacturer: 'Egoman',
930
+ processor: 'BCM2835'
931
+ },
932
+ '0007': {
933
+ type: 'A',
934
+ revision: '2.0',
935
+ memory: 256,
936
+ manufacturer: 'Egoman',
937
+ processor: 'BCM2835'
938
+ },
939
+ '0008': {
940
+ type: 'A',
941
+ revision: '2.0',
942
+ memory: 256,
943
+ manufacturer: 'Sony UK',
944
+ processor: 'BCM2835'
945
+ },
946
+ '0009': {
947
+ type: 'A',
948
+ revision: '2.0',
949
+ memory: 256,
950
+ manufacturer: 'Qisda',
951
+ processor: 'BCM2835'
952
+ },
953
+ '000d': {
954
+ type: 'B',
955
+ revision: '2.0',
956
+ memory: 512,
957
+ manufacturer: 'Egoman',
958
+ processor: 'BCM2835'
959
+ },
960
+ '000e': {
961
+ type: 'B',
962
+ revision: '2.0',
963
+ memory: 512,
964
+ manufacturer: 'Sony UK',
965
+ processor: 'BCM2835'
966
+ },
967
+ '000f': {
968
+ type: 'B',
969
+ revision: '2.0',
970
+ memory: 512,
971
+ manufacturer: 'Egoman',
972
+ processor: 'BCM2835'
973
+ },
974
+ '0010': {
975
+ type: 'B+',
976
+ revision: '1.2',
977
+ memory: 512,
978
+ manufacturer: 'Sony UK',
979
+ processor: 'BCM2835'
980
+ },
981
+ '0011': {
982
+ type: 'CM1',
983
+ revision: '1.0',
984
+ memory: 512,
985
+ manufacturer: 'Sony UK',
986
+ processor: 'BCM2835'
987
+ },
988
+ '0012': {
989
+ type: 'A+',
990
+ revision: '1.1',
991
+ memory: 256,
992
+ manufacturer: 'Sony UK',
993
+ processor: 'BCM2835'
994
+ },
995
+ '0013': {
996
+ type: 'B+',
997
+ revision: '1.2',
998
+ memory: 512,
999
+ manufacturer: 'Embest',
1000
+ processor: 'BCM2835'
1001
+ },
1002
+ '0014': {
1003
+ type: 'CM1',
1004
+ revision: '1.0',
1005
+ memory: 512,
1006
+ manufacturer: 'Embest',
1007
+ processor: 'BCM2835'
1008
+ },
1009
+ '0015': {
1010
+ type: 'A+',
1011
+ revision: '1.1',
1012
+ memory: 256,
1013
+ manufacturer: '512MB Embest',
1014
+ processor: 'BCM2835'
1015
+ }
1016
+ };
1017
+
1018
+ const processorList = ['BCM2835', 'BCM2836', 'BCM2837', 'BCM2711', 'BCM2712'];
1019
+ const manufacturerList = ['Sony UK', 'Egoman', 'Embest', 'Sony Japan', 'Embest', 'Stadium'];
1020
+ const typeList = {
1021
+ '00': 'A',
1022
+ '01': 'B',
1023
+ '02': 'A+',
1024
+ '03': 'B+',
1025
+ '04': '2B',
1026
+ '05': 'Alpha (early prototype)',
1027
+ '06': 'CM1',
1028
+ '08': '3B',
1029
+ '09': 'Zero',
1030
+ '0a': 'CM3',
1031
+ '0c': 'Zero W',
1032
+ '0d': '3B+',
1033
+ '0e': '3A+',
1034
+ '0f': 'Internal use only',
1035
+ 10: 'CM3+',
1036
+ 11: '4B',
1037
+ 12: 'Zero 2 W',
1038
+ 13: '400',
1039
+ 14: 'CM4',
1040
+ 15: 'CM4S',
1041
+ 16: 'Internal use only',
1042
+ 17: '5',
1043
+ 18: 'CM5',
1044
+ 19: '500/500+',
1045
+ '1a': 'CM5 Lite'
1046
+ };
1047
+
1048
+ const revisionCode = getValue(lines, 'revision', ':', true);
1049
+ const model = getValue(lines, 'model:', ':', true);
1050
+ const serial = getValue(lines, 'serial', ':', true);
1051
+
1052
+ let result = {};
1053
+ if ({}.hasOwnProperty.call(oldRevisionCodes, revisionCode)) {
1054
+ // old revision codes
1055
+ result = {
1056
+ model,
1057
+ serial,
1058
+ revisionCode,
1059
+ memory: oldRevisionCodes[revisionCode].memory,
1060
+ manufacturer: oldRevisionCodes[revisionCode].manufacturer,
1061
+ processor: oldRevisionCodes[revisionCode].processor,
1062
+ type: oldRevisionCodes[revisionCode].type,
1063
+ revision: oldRevisionCodes[revisionCode].revision
1064
+ };
1065
+ } else {
1066
+ // new revision code
1067
+ const revision = ('00000000' + getValue(lines, 'revision', ':', true).toLowerCase()).substr(-8);
1068
+ const memSizeCode = parseInt(hex2bin(revision.substr(2, 1)).substr(5, 3), 2) || 0;
1069
+ const manufacturer = manufacturerList[parseInt(revision.substr(3, 1), 10)];
1070
+ const processor = processorList[parseInt(revision.substr(4, 1), 10)];
1071
+ const typeCode = revision.substr(5, 2);
1072
+
1073
+ result = {
1074
+ model,
1075
+ serial,
1076
+ revisionCode,
1077
+ memory: 256 * Math.pow(2, memSizeCode),
1078
+ manufacturer,
1079
+ processor,
1080
+ type: {}.hasOwnProperty.call(typeList, typeCode) ? typeList[typeCode] : '',
1081
+ revision: '1.' + revision.substr(7, 1)
1082
+ };
1083
+ }
1084
+ return result;
1085
+ }
1086
+
1087
+ function getRpiGpu(cpuinfo) {
1088
+ if (_rpi_cpuinfo === null && cpuinfo !== undefined) {
1089
+ _rpi_cpuinfo = cpuinfo;
1090
+ } else if (cpuinfo === undefined && _rpi_cpuinfo !== null) {
1091
+ cpuinfo = _rpi_cpuinfo;
1092
+ } else {
1093
+ try {
1094
+ cpuinfo = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).toString().split('\n');
1095
+ _rpi_cpuinfo = cpuinfo;
1096
+ } catch {
1097
+ return false;
1098
+ }
1099
+ }
1100
+
1101
+ const rpi = decodePiCpuinfo(cpuinfo);
1102
+ if (rpi.type === '4B' || rpi.type === 'CM4' || rpi.type === 'CM4S' || rpi.type === '400') {
1103
+ return 'VideoCore VI';
1104
+ }
1105
+ if (rpi.type === '5' || rpi.type === '500') {
1106
+ return 'VideoCore VII';
1107
+ }
1108
+ return 'VideoCore IV';
1109
+ }
1110
+
1111
+ function promiseAll(promises) {
1112
+ const resolvingPromises = promises.map(
1113
+ (promise) =>
1114
+ new Promise((resolve) => {
1115
+ const payload = new Array(2);
1116
+ promise
1117
+ .then((result) => {
1118
+ payload[0] = result;
1119
+ })
1120
+ .catch((error) => {
1121
+ payload[1] = error;
1122
+ })
1123
+ .then(() => {
1124
+ // The wrapped Promise returns an array: 0 = result, 1 = error ... we resolve all
1125
+ resolve(payload);
1126
+ });
1127
+ })
1128
+ );
1129
+ const errors = [];
1130
+ const results = [];
1131
+
1132
+ // Execute all wrapped Promises
1133
+ return Promise.all(resolvingPromises).then((items) => {
1134
+ items.forEach((payload) => {
1135
+ if (payload[1]) {
1136
+ errors.push(payload[1]);
1137
+ results.push(null);
1138
+ } else {
1139
+ errors.push(null);
1140
+ results.push(payload[0]);
1141
+ }
1142
+ });
1143
+
1144
+ return {
1145
+ errors: errors,
1146
+ results: results
1147
+ };
1148
+ });
1149
+ }
1150
+
1151
+ function promisify(nodeStyleFunction) {
1152
+ return () => {
1153
+ const args = Array.prototype.slice.call(arguments);
1154
+ return new Promise((resolve, reject) => {
1155
+ args.push((err, data) => {
1156
+ if (err) {
1157
+ reject(err);
1158
+ } else {
1159
+ resolve(data);
1160
+ }
1161
+ });
1162
+ nodeStyleFunction.apply(null, args);
1163
+ });
1164
+ };
1165
+ }
1166
+
1167
+ function promisifySave(nodeStyleFunction) {
1168
+ return () => {
1169
+ const args = Array.prototype.slice.call(arguments);
1170
+ return new Promise((resolve) => {
1171
+ args.push((err, data) => {
1172
+ resolve(data);
1173
+ });
1174
+ nodeStyleFunction.apply(null, args);
1175
+ });
1176
+ };
1177
+ }
1178
+
1179
+ function linuxVersion() {
1180
+ let result = '';
1181
+ if (_linux) {
1182
+ try {
1183
+ result = execSync('uname -v', execOptsLinux).toString();
1184
+ } catch {
1185
+ result = '';
1186
+ }
1187
+ }
1188
+ return result;
1189
+ }
1190
+
1191
+ function plistParser(xmlStr) {
1192
+ const tags = ['array', 'dict', 'key', 'string', 'integer', 'date', 'real', 'data', 'boolean', 'arrayEmpty'];
1193
+ const startStr = '<plist version';
1194
+
1195
+ let pos = xmlStr.indexOf(startStr);
1196
+ let len = xmlStr.length;
1197
+ while (xmlStr[pos] !== '>' && pos < len) {
1198
+ pos++;
1199
+ }
1200
+
1201
+ let depth = 0;
1202
+ let inTagStart = false;
1203
+ let inTagContent = false;
1204
+ let inTagEnd = false;
1205
+ let metaData = [{ tagStart: '', tagEnd: '', tagContent: '', key: '', data: null }];
1206
+ let c = '';
1207
+ let cn = xmlStr[pos];
1208
+
1209
+ while (pos < len) {
1210
+ c = cn;
1211
+ if (pos + 1 < len) {
1212
+ cn = xmlStr[pos + 1];
1213
+ }
1214
+ if (c === '<') {
1215
+ inTagContent = false;
1216
+ if (cn === '/') {
1217
+ inTagEnd = true;
1218
+ } else if (metaData[depth].tagStart) {
1219
+ metaData[depth].tagContent = '';
1220
+ if (!metaData[depth].data) {
1221
+ metaData[depth].data = metaData[depth].tagStart === 'array' ? [] : {};
1222
+ }
1223
+ depth++;
1224
+ metaData.push({ tagStart: '', tagEnd: '', tagContent: '', key: null, data: null });
1225
+ inTagStart = true;
1226
+ inTagContent = false;
1227
+ } else if (!inTagStart) {
1228
+ inTagStart = true;
1229
+ }
1230
+ } else if (c === '>') {
1231
+ if (metaData[depth].tagStart === 'true/') {
1232
+ inTagStart = false;
1233
+ inTagEnd = true;
1234
+ metaData[depth].tagStart = '';
1235
+ metaData[depth].tagEnd = '/boolean';
1236
+ metaData[depth].data = true;
1237
+ }
1238
+ if (metaData[depth].tagStart === 'false/') {
1239
+ inTagStart = false;
1240
+ inTagEnd = true;
1241
+ metaData[depth].tagStart = '';
1242
+ metaData[depth].tagEnd = '/boolean';
1243
+ metaData[depth].data = false;
1244
+ }
1245
+ if (metaData[depth].tagStart === 'array/') {
1246
+ inTagStart = false;
1247
+ inTagEnd = true;
1248
+ metaData[depth].tagStart = '';
1249
+ metaData[depth].tagEnd = '/arrayEmpty';
1250
+ metaData[depth].data = [];
1251
+ }
1252
+ if (inTagContent) {
1253
+ inTagContent = false;
1254
+ }
1255
+ if (inTagStart) {
1256
+ inTagStart = false;
1257
+ inTagContent = true;
1258
+ if (metaData[depth].tagStart === 'array') {
1259
+ metaData[depth].data = [];
1260
+ }
1261
+ if (metaData[depth].tagStart === 'dict') {
1262
+ metaData[depth].data = {};
1263
+ }
1264
+ }
1265
+ if (inTagEnd) {
1266
+ inTagEnd = false;
1267
+ if (metaData[depth].tagEnd && tags.indexOf(metaData[depth].tagEnd.substr(1)) >= 0) {
1268
+ if (metaData[depth].tagEnd === '/dict' || metaData[depth].tagEnd === '/array') {
1269
+ if (depth > 1 && metaData[depth - 2].tagStart === 'array') {
1270
+ metaData[depth - 2].data.push(metaData[depth - 1].data);
1271
+ }
1272
+ if (depth > 1 && metaData[depth - 2].tagStart === 'dict') {
1273
+ metaData[depth - 2].data[metaData[depth - 1].key] = metaData[depth - 1].data;
1274
+ }
1275
+ depth--;
1276
+ metaData.pop();
1277
+ metaData[depth].tagContent = '';
1278
+ metaData[depth].tagStart = '';
1279
+ metaData[depth].tagEnd = '';
1280
+ } else {
1281
+ if (metaData[depth].tagEnd === '/key' && metaData[depth].tagContent) {
1282
+ metaData[depth].key = metaData[depth].tagContent;
1283
+ } else {
1284
+ if (metaData[depth].tagEnd === '/real' && metaData[depth].tagContent) {
1285
+ metaData[depth].data = parseFloat(metaData[depth].tagContent) || 0;
1286
+ }
1287
+ if (metaData[depth].tagEnd === '/integer' && metaData[depth].tagContent) {
1288
+ metaData[depth].data = parseInt(metaData[depth].tagContent) || 0;
1289
+ }
1290
+ if (metaData[depth].tagEnd === '/string' && metaData[depth].tagContent) {
1291
+ metaData[depth].data = metaData[depth].tagContent || '';
1292
+ }
1293
+ if (metaData[depth].tagEnd === '/boolean') {
1294
+ metaData[depth].data = metaData[depth].tagContent || false;
1295
+ }
1296
+ if (metaData[depth].tagEnd === '/arrayEmpty') {
1297
+ metaData[depth].data = metaData[depth].tagContent || [];
1298
+ }
1299
+ if (depth > 0 && metaData[depth - 1].tagStart === 'array') {
1300
+ metaData[depth - 1].data.push(metaData[depth].data);
1301
+ }
1302
+ if (depth > 0 && metaData[depth - 1].tagStart === 'dict') {
1303
+ metaData[depth - 1].data[metaData[depth].key] = metaData[depth].data;
1304
+ }
1305
+ }
1306
+ metaData[depth].tagContent = '';
1307
+ metaData[depth].tagStart = '';
1308
+ metaData[depth].tagEnd = '';
1309
+ }
1310
+ }
1311
+ metaData[depth].tagEnd = '';
1312
+ inTagStart = false;
1313
+ inTagContent = false;
1314
+ }
1315
+ } else {
1316
+ if (inTagStart) {
1317
+ metaData[depth].tagStart += c;
1318
+ }
1319
+ if (inTagEnd) {
1320
+ metaData[depth].tagEnd += c;
1321
+ }
1322
+ if (inTagContent) {
1323
+ metaData[depth].tagContent += c;
1324
+ }
1325
+ }
1326
+ pos++;
1327
+ }
1328
+ return metaData[0].data;
1329
+ }
1330
+
1331
+ function strIsNumeric(str) {
1332
+ return typeof str === 'string' && !isNaN(str) && !isNaN(parseFloat(str));
1333
+ }
1334
+
1335
+ function plistReader(output) {
1336
+ const lines = output.split('\n');
1337
+ for (let i = 0; i < lines.length; i++) {
1338
+ if (lines[i].indexOf(' = ') >= 0) {
1339
+ const lineParts = lines[i].split(' = ');
1340
+ lineParts[0] = lineParts[0].trim();
1341
+ if (!lineParts[0].startsWith('"')) {
1342
+ lineParts[0] = '"' + lineParts[0] + '"';
1343
+ }
1344
+ lineParts[1] = lineParts[1].trim();
1345
+ if (lineParts[1].indexOf('"') === -1 && lineParts[1].endsWith(';')) {
1346
+ const valueString = lineParts[1].substring(0, lineParts[1].length - 1);
1347
+ if (!strIsNumeric(valueString)) {
1348
+ lineParts[1] = `"${valueString}";`;
1349
+ }
1350
+ }
1351
+ if (lineParts[1].indexOf('"') >= 0 && lineParts[1].endsWith(';')) {
1352
+ const valueString = lineParts[1].substring(0, lineParts[1].length - 1).replace(/"/g, '');
1353
+ if (strIsNumeric(valueString)) {
1354
+ lineParts[1] = `${valueString};`;
1355
+ }
1356
+ }
1357
+ lines[i] = lineParts.join(' : ');
1358
+ }
1359
+ lines[i] = lines[i].replace(/\(/g, '[').replace(/\)/g, ']').replace(/;/g, ',').trim();
1360
+ if (lines[i].startsWith('}') && lines[i - 1] && lines[i - 1].endsWith(',')) {
1361
+ lines[i - 1] = lines[i - 1].substring(0, lines[i - 1].length - 1);
1362
+ }
1363
+ }
1364
+ output = lines.join('');
1365
+ let obj = {};
1366
+ try {
1367
+ obj = JSON.parse(output);
1368
+ } catch (e) {
1369
+ noop();
1370
+ }
1371
+ return obj;
1372
+ }
1373
+
1374
+ function semverCompare(v1, v2) {
1375
+ let res = 0;
1376
+ const parts1 = v1.split('.');
1377
+ const parts2 = v2.split('.');
1378
+ if (parts1[0] < parts2[0]) {
1379
+ res = 1;
1380
+ } else if (parts1[0] > parts2[0]) {
1381
+ res = -1;
1382
+ } else if (parts1[0] === parts2[0] && parts1.length >= 2 && parts2.length >= 2) {
1383
+ if (parts1[1] < parts2[1]) {
1384
+ res = 1;
1385
+ } else if (parts1[1] > parts2[1]) {
1386
+ res = -1;
1387
+ } else if (parts1[1] === parts2[1]) {
1388
+ if (parts1.length >= 3 && parts2.length >= 3) {
1389
+ if (parts1[2] < parts2[2]) {
1390
+ res = 1;
1391
+ } else if (parts1[2] > parts2[2]) {
1392
+ res = -1;
1393
+ }
1394
+ } else if (parts2.length >= 3) {
1395
+ res = 1;
1396
+ }
1397
+ }
1398
+ }
1399
+ return res;
1400
+ }
1401
+
1402
+ function getAppleModel(key) {
1403
+ const appleModelIds = [
1404
+ {
1405
+ key: 'Mac17,7',
1406
+ name: 'MacBook Pro',
1407
+ size: '16-inch',
1408
+ processor: 'M5 Max',
1409
+ year: '2026',
1410
+ additional: ''
1411
+ },
1412
+ {
1413
+ key: 'Mac17,6',
1414
+ name: 'MacBook Pro',
1415
+ size: '14-inch',
1416
+ processor: 'M5 Max',
1417
+ year: '2026',
1418
+ additional: ''
1419
+ },
1420
+ {
1421
+ key: 'Mac17,5',
1422
+ name: 'MacBook Pro',
1423
+ size: '16-inch',
1424
+ processor: 'M5 Pro',
1425
+ year: '2026',
1426
+ additional: ''
1427
+ },
1428
+ {
1429
+ key: 'Mac17,4',
1430
+ name: 'MacBook Pro',
1431
+ size: '14-inch',
1432
+ processor: 'M5 Pro',
1433
+ year: '2026',
1434
+ additional: ''
1435
+ },
1436
+ {
1437
+ key: 'Mac17,1',
1438
+ name: 'MacBook Neo',
1439
+ size: '14-inch',
1440
+ processor: 'A18 Pro',
1441
+ year: '2026',
1442
+ additional: ''
1443
+ },
1444
+ {
1445
+ key: 'Mac17,3',
1446
+ name: 'MacBook Pro',
1447
+ size: '16-inch',
1448
+ processor: 'M5',
1449
+ year: '2025',
1450
+ additional: ''
1451
+ },
1452
+ {
1453
+ key: 'Mac17,2',
1454
+ name: 'MacBook Pro',
1455
+ size: '14-inch',
1456
+ processor: 'M5',
1457
+ year: '2025',
1458
+ additional: ''
1459
+ },
1460
+ {
1461
+ key: 'Mac16,13',
1462
+ name: 'MacBook Air',
1463
+ size: '15-inch',
1464
+ processor: 'M4',
1465
+ year: '2025',
1466
+ additional: ''
1467
+ },
1468
+ {
1469
+ key: 'Mac16,12',
1470
+ name: 'MacBook Air',
1471
+ size: '13-inch',
1472
+ processor: 'M4',
1473
+ year: '2025',
1474
+ additional: ''
1475
+ },
1476
+ {
1477
+ key: 'Mac15,13',
1478
+ name: 'MacBook Air',
1479
+ size: '15-inch',
1480
+ processor: 'M3',
1481
+ year: '2024',
1482
+ additional: ''
1483
+ },
1484
+ {
1485
+ key: 'Mac15,12',
1486
+ name: 'MacBook Air',
1487
+ size: '13-inch',
1488
+ processor: 'M3',
1489
+ year: '2024',
1490
+ additional: ''
1491
+ },
1492
+ {
1493
+ key: 'Mac14,15',
1494
+ name: 'MacBook Air',
1495
+ size: '15-inch',
1496
+ processor: 'M2',
1497
+ year: '2024',
1498
+ additional: ''
1499
+ },
1500
+ {
1501
+ key: 'Mac14,2',
1502
+ name: 'MacBook Air',
1503
+ size: '13-inch',
1504
+ processor: 'M2',
1505
+ year: '2022',
1506
+ additional: ''
1507
+ },
1508
+ {
1509
+ key: 'MacBookAir10,1',
1510
+ name: 'MacBook Air',
1511
+ size: '13-inch',
1512
+ processor: 'M1',
1513
+ year: '2020',
1514
+ additional: ''
1515
+ },
1516
+ {
1517
+ key: 'MacBookAir9,1',
1518
+ name: 'MacBook Air',
1519
+ size: '13-inch',
1520
+ processor: '',
1521
+ year: '2020',
1522
+ additional: ''
1523
+ },
1524
+ {
1525
+ key: 'MacBookAir8,2',
1526
+ name: 'MacBook Air',
1527
+ size: '13-inch',
1528
+ processor: '',
1529
+ year: '2019',
1530
+ additional: ''
1531
+ },
1532
+ {
1533
+ key: 'MacBookAir8,1',
1534
+ name: 'MacBook Air',
1535
+ size: '13-inch',
1536
+ processor: '',
1537
+ year: '2018',
1538
+ additional: ''
1539
+ },
1540
+ {
1541
+ key: 'MacBookAir7,2',
1542
+ name: 'MacBook Air',
1543
+ size: '13-inch',
1544
+ processor: '',
1545
+ year: '2017',
1546
+ additional: ''
1547
+ },
1548
+ {
1549
+ key: 'MacBookAir7,2',
1550
+ name: 'MacBook Air',
1551
+ size: '13-inch',
1552
+ processor: '',
1553
+ year: 'Early 2015',
1554
+ additional: ''
1555
+ },
1556
+ {
1557
+ key: 'MacBookAir7,1',
1558
+ name: 'MacBook Air',
1559
+ size: '11-inch',
1560
+ processor: '',
1561
+ year: 'Early 2015',
1562
+ additional: ''
1563
+ },
1564
+ {
1565
+ key: 'MacBookAir6,2',
1566
+ name: 'MacBook Air',
1567
+ size: '13-inch',
1568
+ processor: '',
1569
+ year: 'Early 2014',
1570
+ additional: ''
1571
+ },
1572
+ {
1573
+ key: 'MacBookAir6,1',
1574
+ name: 'MacBook Air',
1575
+ size: '11-inch',
1576
+ processor: '',
1577
+ year: 'Early 2014',
1578
+ additional: ''
1579
+ },
1580
+ {
1581
+ key: 'MacBookAir6,2',
1582
+ name: 'MacBook Air',
1583
+ size: '13-inch',
1584
+ processor: '',
1585
+ year: 'Mid 2013',
1586
+ additional: ''
1587
+ },
1588
+ {
1589
+ key: 'MacBookAir6,1',
1590
+ name: 'MacBook Air',
1591
+ size: '11-inch',
1592
+ processor: '',
1593
+ year: 'Mid 2013',
1594
+ additional: ''
1595
+ },
1596
+ {
1597
+ key: 'MacBookAir5,2',
1598
+ name: 'MacBook Air',
1599
+ size: '13-inch',
1600
+ processor: '',
1601
+ year: 'Mid 2012',
1602
+ additional: ''
1603
+ },
1604
+ {
1605
+ key: 'MacBookAir5,1',
1606
+ name: 'MacBook Air',
1607
+ size: '11-inch',
1608
+ processor: '',
1609
+ year: 'Mid 2012',
1610
+ additional: ''
1611
+ },
1612
+ {
1613
+ key: 'MacBookAir4,2',
1614
+ name: 'MacBook Air',
1615
+ size: '13-inch',
1616
+ processor: '',
1617
+ year: 'Mid 2011',
1618
+ additional: ''
1619
+ },
1620
+ {
1621
+ key: 'MacBookAir4,1',
1622
+ name: 'MacBook Air',
1623
+ size: '11-inch',
1624
+ processor: '',
1625
+ year: 'Mid 2011',
1626
+ additional: ''
1627
+ },
1628
+ {
1629
+ key: 'MacBookAir3,2',
1630
+ name: 'MacBook Air',
1631
+ size: '13-inch',
1632
+ processor: '',
1633
+ year: 'Late 2010',
1634
+ additional: ''
1635
+ },
1636
+ {
1637
+ key: 'MacBookAir3,1',
1638
+ name: 'MacBook Air',
1639
+ size: '11-inch',
1640
+ processor: '',
1641
+ year: 'Late 2010',
1642
+ additional: ''
1643
+ },
1644
+ {
1645
+ key: 'MacBookAir2,1',
1646
+ name: 'MacBook Air',
1647
+ size: '13-inch',
1648
+ processor: '',
1649
+ year: 'Mid 2009',
1650
+ additional: ''
1651
+ },
1652
+ {
1653
+ key: 'Mac16,1',
1654
+ name: 'MacBook Pro',
1655
+ size: '14-inch',
1656
+ processor: 'M4',
1657
+ year: '2024',
1658
+ additional: ''
1659
+ },
1660
+ {
1661
+ key: 'Mac16,6',
1662
+ name: 'MacBook Pro',
1663
+ size: '14-inch',
1664
+ processor: 'M4 Pro',
1665
+ year: '2024',
1666
+ additional: ''
1667
+ },
1668
+ {
1669
+ key: 'Mac16,8',
1670
+ name: 'MacBook Pro',
1671
+ size: '14-inch',
1672
+ processor: 'M4 Max',
1673
+ year: '2024',
1674
+ additional: ''
1675
+ },
1676
+ {
1677
+ key: 'Mac16,5',
1678
+ name: 'MacBook Pro',
1679
+ size: '16-inch',
1680
+ processor: 'M4 Pro',
1681
+ year: '2024',
1682
+ additional: ''
1683
+ },
1684
+ {
1685
+ key: 'Mac16,6',
1686
+ name: 'MacBook Pro',
1687
+ size: '16-inch',
1688
+ processor: 'M4 Max',
1689
+ year: '2024',
1690
+ additional: ''
1691
+ },
1692
+ {
1693
+ key: 'Mac15,3',
1694
+ name: 'MacBook Pro',
1695
+ size: '14-inch',
1696
+ processor: 'M3',
1697
+ year: 'Nov 2023',
1698
+ additional: ''
1699
+ },
1700
+ {
1701
+ key: 'Mac15,6',
1702
+ name: 'MacBook Pro',
1703
+ size: '14-inch',
1704
+ processor: 'M3 Pro',
1705
+ year: 'Nov 2023',
1706
+ additional: ''
1707
+ },
1708
+ {
1709
+ key: 'Mac15,8',
1710
+ name: 'MacBook Pro',
1711
+ size: '14-inch',
1712
+ processor: 'M3 Pro',
1713
+ year: 'Nov 2023',
1714
+ additional: ''
1715
+ },
1716
+ {
1717
+ key: 'Mac15,10',
1718
+ name: 'MacBook Pro',
1719
+ size: '14-inch',
1720
+ processor: 'M3 Max',
1721
+ year: 'Nov 2023',
1722
+ additional: ''
1723
+ },
1724
+ {
1725
+ key: 'Mac15,7',
1726
+ name: 'MacBook Pro',
1727
+ size: '16-inch',
1728
+ processor: 'M3 Pro',
1729
+ year: 'Nov 2023',
1730
+ additional: ''
1731
+ },
1732
+ {
1733
+ key: 'Mac15,9',
1734
+ name: 'MacBook Pro',
1735
+ size: '16-inch',
1736
+ processor: 'M3 Pro',
1737
+ year: 'Nov 2023',
1738
+ additional: ''
1739
+ },
1740
+ {
1741
+ key: 'Mac15,11',
1742
+ name: 'MacBook Pro',
1743
+ size: '16-inch',
1744
+ processor: 'M3 Max',
1745
+ year: 'Nov 2023',
1746
+ additional: ''
1747
+ },
1748
+ {
1749
+ key: 'Mac14,5',
1750
+ name: 'MacBook Pro',
1751
+ size: '14-inch',
1752
+ processor: 'M2 Max',
1753
+ year: '2023',
1754
+ additional: ''
1755
+ },
1756
+ {
1757
+ key: 'Mac14,9',
1758
+ name: 'MacBook Pro',
1759
+ size: '14-inch',
1760
+ processor: 'M2 Max',
1761
+ year: '2023',
1762
+ additional: ''
1763
+ },
1764
+ {
1765
+ key: 'Mac14,6',
1766
+ name: 'MacBook Pro',
1767
+ size: '16-inch',
1768
+ processor: 'M2 Max',
1769
+ year: '2023',
1770
+ additional: ''
1771
+ },
1772
+ {
1773
+ key: 'Mac14,10',
1774
+ name: 'MacBook Pro',
1775
+ size: '16-inch',
1776
+ processor: 'M2 Max',
1777
+ year: '2023',
1778
+ additional: ''
1779
+ },
1780
+ {
1781
+ key: 'Mac14,7',
1782
+ name: 'MacBook Pro',
1783
+ size: '13-inch',
1784
+ processor: 'M2',
1785
+ year: '2022',
1786
+ additional: ''
1787
+ },
1788
+ {
1789
+ key: 'MacBookPro18,3',
1790
+ name: 'MacBook Pro',
1791
+ size: '14-inch',
1792
+ processor: 'M1 Pro',
1793
+ year: '2021',
1794
+ additional: ''
1795
+ },
1796
+ {
1797
+ key: 'MacBookPro18,4',
1798
+ name: 'MacBook Pro',
1799
+ size: '14-inch',
1800
+ processor: 'M1 Max',
1801
+ year: '2021',
1802
+ additional: ''
1803
+ },
1804
+ {
1805
+ key: 'MacBookPro18,1',
1806
+ name: 'MacBook Pro',
1807
+ size: '16-inch',
1808
+ processor: 'M1 Pro',
1809
+ year: '2021',
1810
+ additional: ''
1811
+ },
1812
+ {
1813
+ key: 'MacBookPro18,2',
1814
+ name: 'MacBook Pro',
1815
+ size: '16-inch',
1816
+ processor: 'M1 Max',
1817
+ year: '2021',
1818
+ additional: ''
1819
+ },
1820
+ {
1821
+ key: 'MacBookPro17,1',
1822
+ name: 'MacBook Pro',
1823
+ size: '13-inch',
1824
+ processor: 'M1',
1825
+ year: '2020',
1826
+ additional: ''
1827
+ },
1828
+ {
1829
+ key: 'MacBookPro16,3',
1830
+ name: 'MacBook Pro',
1831
+ size: '13-inch',
1832
+ processor: '',
1833
+ year: '2020',
1834
+ additional: 'Two Thunderbolt 3 ports'
1835
+ },
1836
+ {
1837
+ key: 'MacBookPro16,2',
1838
+ name: 'MacBook Pro',
1839
+ size: '13-inch',
1840
+ processor: '',
1841
+ year: '2020',
1842
+ additional: 'Four Thunderbolt 3 ports'
1843
+ },
1844
+ {
1845
+ key: 'MacBookPro16,1',
1846
+ name: 'MacBook Pro',
1847
+ size: '16-inch',
1848
+ processor: '',
1849
+ year: '2019',
1850
+ additional: ''
1851
+ },
1852
+ {
1853
+ key: 'MacBookPro16,4',
1854
+ name: 'MacBook Pro',
1855
+ size: '16-inch',
1856
+ processor: '',
1857
+ year: '2019',
1858
+ additional: ''
1859
+ },
1860
+ {
1861
+ key: 'MacBookPro15,3',
1862
+ name: 'MacBook Pro',
1863
+ size: '15-inch',
1864
+ processor: '',
1865
+ year: '2019',
1866
+ additional: ''
1867
+ },
1868
+ {
1869
+ key: 'MacBookPro15,2',
1870
+ name: 'MacBook Pro',
1871
+ size: '13-inch',
1872
+ processor: '',
1873
+ year: '2019',
1874
+ additional: ''
1875
+ },
1876
+ {
1877
+ key: 'MacBookPro15,1',
1878
+ name: 'MacBook Pro',
1879
+ size: '15-inch',
1880
+ processor: '',
1881
+ year: '2019',
1882
+ additional: ''
1883
+ },
1884
+ {
1885
+ key: 'MacBookPro15,4',
1886
+ name: 'MacBook Pro',
1887
+ size: '13-inch',
1888
+ processor: '',
1889
+ year: '2019',
1890
+ additional: 'Two Thunderbolt 3 ports'
1891
+ },
1892
+ {
1893
+ key: 'MacBookPro15,1',
1894
+ name: 'MacBook Pro',
1895
+ size: '15-inch',
1896
+ processor: '',
1897
+ year: '2018',
1898
+ additional: ''
1899
+ },
1900
+ {
1901
+ key: 'MacBookPro15,2',
1902
+ name: 'MacBook Pro',
1903
+ size: '13-inch',
1904
+ processor: '',
1905
+ year: '2018',
1906
+ additional: 'Four Thunderbolt 3 ports'
1907
+ },
1908
+ {
1909
+ key: 'MacBookPro14,1',
1910
+ name: 'MacBook Pro',
1911
+ size: '13-inch',
1912
+ processor: '',
1913
+ year: '2017',
1914
+ additional: 'Two Thunderbolt 3 ports'
1915
+ },
1916
+ {
1917
+ key: 'MacBookPro14,2',
1918
+ name: 'MacBook Pro',
1919
+ size: '13-inch',
1920
+ processor: '',
1921
+ year: '2017',
1922
+ additional: 'Four Thunderbolt 3 ports'
1923
+ },
1924
+ {
1925
+ key: 'MacBookPro14,3',
1926
+ name: 'MacBook Pro',
1927
+ size: '15-inch',
1928
+ processor: '',
1929
+ year: '2017',
1930
+ additional: ''
1931
+ },
1932
+ {
1933
+ key: 'MacBookPro13,1',
1934
+ name: 'MacBook Pro',
1935
+ size: '13-inch',
1936
+ processor: '',
1937
+ year: '2016',
1938
+ additional: 'Two Thunderbolt 3 ports'
1939
+ },
1940
+ {
1941
+ key: 'MacBookPro13,2',
1942
+ name: 'MacBook Pro',
1943
+ size: '13-inch',
1944
+ processor: '',
1945
+ year: '2016',
1946
+ additional: 'Four Thunderbolt 3 ports'
1947
+ },
1948
+ {
1949
+ key: 'MacBookPro13,3',
1950
+ name: 'MacBook Pro',
1951
+ size: '15-inch',
1952
+ processor: '',
1953
+ year: '2016',
1954
+ additional: ''
1955
+ },
1956
+ {
1957
+ key: 'MacBookPro11,4',
1958
+ name: 'MacBook Pro',
1959
+ size: '15-inch',
1960
+ processor: '',
1961
+ year: 'Mid 2015',
1962
+ additional: ''
1963
+ },
1964
+ {
1965
+ key: 'MacBookPro11,5',
1966
+ name: 'MacBook Pro',
1967
+ size: '15-inch',
1968
+ processor: '',
1969
+ year: 'Mid 2015',
1970
+ additional: ''
1971
+ },
1972
+ {
1973
+ key: 'MacBookPro12,1',
1974
+ name: 'MacBook Pro',
1975
+ size: '13-inch',
1976
+ processor: '',
1977
+ year: 'Early 2015',
1978
+ additional: ''
1979
+ },
1980
+ {
1981
+ key: 'MacBookPro11,2',
1982
+ name: 'MacBook Pro',
1983
+ size: '15-inch',
1984
+ processor: '',
1985
+ year: 'Late 2013',
1986
+ additional: ''
1987
+ },
1988
+ {
1989
+ key: 'MacBookPro11,3',
1990
+ name: 'MacBook Pro',
1991
+ size: '15-inch',
1992
+ processor: '',
1993
+ year: 'Late 2013',
1994
+ additional: ''
1995
+ },
1996
+ {
1997
+ key: 'MacBookPro11,1',
1998
+ name: 'MacBook Pro',
1999
+ size: '13-inch',
2000
+ processor: '',
2001
+ year: 'Late 2013',
2002
+ additional: ''
2003
+ },
2004
+ {
2005
+ key: 'MacBookPro10,1',
2006
+ name: 'MacBook Pro',
2007
+ size: '15-inch',
2008
+ processor: '',
2009
+ year: 'Mid 2012',
2010
+ additional: ''
2011
+ },
2012
+ {
2013
+ key: 'MacBookPro10,2',
2014
+ name: 'MacBook Pro',
2015
+ size: '13-inch',
2016
+ processor: '',
2017
+ year: 'Late 2012',
2018
+ additional: ''
2019
+ },
2020
+ {
2021
+ key: 'MacBookPro9,1',
2022
+ name: 'MacBook Pro',
2023
+ size: '15-inch',
2024
+ processor: '',
2025
+ year: 'Mid 2012',
2026
+ additional: ''
2027
+ },
2028
+ {
2029
+ key: 'MacBookPro9,2',
2030
+ name: 'MacBook Pro',
2031
+ size: '13-inch',
2032
+ processor: '',
2033
+ year: 'Mid 2012',
2034
+ additional: ''
2035
+ },
2036
+ {
2037
+ key: 'MacBookPro8,3',
2038
+ name: 'MacBook Pro',
2039
+ size: '17-inch',
2040
+ processor: '',
2041
+ year: 'Early 2011',
2042
+ additional: ''
2043
+ },
2044
+ {
2045
+ key: 'MacBookPro8,2',
2046
+ name: 'MacBook Pro',
2047
+ size: '15-inch',
2048
+ processor: '',
2049
+ year: 'Early 2011',
2050
+ additional: ''
2051
+ },
2052
+ {
2053
+ key: 'MacBookPro8,1',
2054
+ name: 'MacBook Pro',
2055
+ size: '13-inch',
2056
+ processor: '',
2057
+ year: 'Early 2011',
2058
+ additional: ''
2059
+ },
2060
+ {
2061
+ key: 'MacBookPro6,1',
2062
+ name: 'MacBook Pro',
2063
+ size: '17-inch',
2064
+ processor: '',
2065
+ year: 'Mid 2010',
2066
+ additional: ''
2067
+ },
2068
+ {
2069
+ key: 'MacBookPro6,2',
2070
+ name: 'MacBook Pro',
2071
+ size: '15-inch',
2072
+ processor: '',
2073
+ year: 'Mid 2010',
2074
+ additional: ''
2075
+ },
2076
+ {
2077
+ key: 'MacBookPro7,1',
2078
+ name: 'MacBook Pro',
2079
+ size: '13-inch',
2080
+ processor: '',
2081
+ year: 'Mid 2010',
2082
+ additional: ''
2083
+ },
2084
+ {
2085
+ key: 'MacBookPro5,2',
2086
+ name: 'MacBook Pro',
2087
+ size: '17-inch',
2088
+ processor: '',
2089
+ year: 'Early 2009',
2090
+ additional: ''
2091
+ },
2092
+ {
2093
+ key: 'MacBookPro5,3',
2094
+ name: 'MacBook Pro',
2095
+ size: '15-inch',
2096
+ processor: '',
2097
+ year: 'Mid 2009',
2098
+ additional: ''
2099
+ },
2100
+ {
2101
+ key: 'MacBookPro5,5',
2102
+ name: 'MacBook Pro',
2103
+ size: '13-inch',
2104
+ processor: '',
2105
+ year: 'Mid 2009',
2106
+ additional: ''
2107
+ },
2108
+ {
2109
+ key: 'MacBookPro5,1',
2110
+ name: 'MacBook Pro',
2111
+ size: '15-inch',
2112
+ processor: '',
2113
+ year: 'Late 2008',
2114
+ additional: ''
2115
+ },
2116
+ {
2117
+ key: 'MacBookPro4,1',
2118
+ name: 'MacBook Pro',
2119
+ size: '15-inch',
2120
+ processor: '',
2121
+ year: 'Early 2008',
2122
+ additional: ''
2123
+ },
2124
+ {
2125
+ key: 'MacBook10,1',
2126
+ name: 'MacBook',
2127
+ size: '12-inch',
2128
+ processor: '',
2129
+ year: '2017',
2130
+ additional: ''
2131
+ },
2132
+ {
2133
+ key: 'MacBook9,1',
2134
+ name: 'MacBook',
2135
+ size: '12-inch',
2136
+ processor: '',
2137
+ year: 'Early 2016',
2138
+ additional: ''
2139
+ },
2140
+ {
2141
+ key: 'MacBook8,1',
2142
+ name: 'MacBook',
2143
+ size: '12-inch',
2144
+ processor: '',
2145
+ year: 'Early 2015',
2146
+ additional: ''
2147
+ },
2148
+ {
2149
+ key: 'MacBook7,1',
2150
+ name: 'MacBook',
2151
+ size: '13-inch',
2152
+ processor: '',
2153
+ year: 'Mid 2010',
2154
+ additional: ''
2155
+ },
2156
+ {
2157
+ key: 'MacBook6,1',
2158
+ name: 'MacBook',
2159
+ size: '13-inch',
2160
+ processor: '',
2161
+ year: 'Late 2009',
2162
+ additional: ''
2163
+ },
2164
+ {
2165
+ key: 'MacBook5,2',
2166
+ name: 'MacBook',
2167
+ size: '13-inch',
2168
+ processor: '',
2169
+ year: 'Early 2009',
2170
+ additional: ''
2171
+ },
2172
+ {
2173
+ key: 'Mac14,13',
2174
+ name: 'Mac Studio',
2175
+ size: '',
2176
+ processor: 'M2 Max',
2177
+ year: '2023',
2178
+ additional: ''
2179
+ },
2180
+ {
2181
+ key: 'Mac14,14',
2182
+ name: 'Mac Studio',
2183
+ size: '',
2184
+ processor: 'M2 Ultra',
2185
+ year: '2023',
2186
+ additional: ''
2187
+ },
2188
+ {
2189
+ key: 'Mac15,14',
2190
+ name: 'Mac Studio',
2191
+ size: '',
2192
+ processor: 'M3 Ultra',
2193
+ year: '2025',
2194
+ additional: ''
2195
+ },
2196
+ {
2197
+ key: 'Mac16,9',
2198
+ name: 'Mac Studio',
2199
+ size: '',
2200
+ processor: 'M4 Max',
2201
+ year: '2025',
2202
+ additional: ''
2203
+ },
2204
+ {
2205
+ key: 'Mac13,1',
2206
+ name: 'Mac Studio',
2207
+ size: '',
2208
+ processor: 'M1 Max',
2209
+ year: '2022',
2210
+ additional: ''
2211
+ },
2212
+ {
2213
+ key: 'Mac13,2',
2214
+ name: 'Mac Studio',
2215
+ size: '',
2216
+ processor: 'M1 Ultra',
2217
+ year: '2022',
2218
+ additional: ''
2219
+ },
2220
+ {
2221
+ key: 'Mac16,11',
2222
+ name: 'Mac mini',
2223
+ size: '',
2224
+ processor: 'M4 Pro',
2225
+ year: '2024',
2226
+ additional: ''
2227
+ },
2228
+ {
2229
+ key: 'Mac16,10',
2230
+ name: 'Mac mini',
2231
+ size: '',
2232
+ processor: 'M4',
2233
+ year: '2024',
2234
+ additional: ''
2235
+ },
2236
+ {
2237
+ key: 'Mac14,3',
2238
+ name: 'Mac mini',
2239
+ size: '',
2240
+ processor: 'M2',
2241
+ year: '2023',
2242
+ additional: ''
2243
+ },
2244
+ {
2245
+ key: 'Mac14,12',
2246
+ name: 'Mac mini',
2247
+ size: '',
2248
+ processor: 'M2 Pro',
2249
+ year: '2023',
2250
+ additional: ''
2251
+ },
2252
+ {
2253
+ key: 'Macmini9,1',
2254
+ name: 'Mac mini',
2255
+ size: '',
2256
+ processor: 'M1',
2257
+ year: '2020',
2258
+ additional: ''
2259
+ },
2260
+ {
2261
+ key: 'Macmini8,1',
2262
+ name: 'Mac mini',
2263
+ size: '',
2264
+ processor: '',
2265
+ year: 'Late 2018',
2266
+ additional: ''
2267
+ },
2268
+ {
2269
+ key: 'Macmini7,1',
2270
+ name: 'Mac mini',
2271
+ size: '',
2272
+ processor: '',
2273
+ year: 'Late 2014',
2274
+ additional: ''
2275
+ },
2276
+ {
2277
+ key: 'Macmini6,1',
2278
+ name: 'Mac mini',
2279
+ size: '',
2280
+ processor: '',
2281
+ year: 'Late 2012',
2282
+ additional: ''
2283
+ },
2284
+ {
2285
+ key: 'Macmini6,2',
2286
+ name: 'Mac mini',
2287
+ size: '',
2288
+ processor: '',
2289
+ year: 'Late 2012',
2290
+ additional: ''
2291
+ },
2292
+ {
2293
+ key: 'Macmini5,1',
2294
+ name: 'Mac mini',
2295
+ size: '',
2296
+ processor: '',
2297
+ year: 'Mid 2011',
2298
+ additional: ''
2299
+ },
2300
+ {
2301
+ key: 'Macmini5,2',
2302
+ name: 'Mac mini',
2303
+ size: '',
2304
+ processor: '',
2305
+ year: 'Mid 2011',
2306
+ additional: ''
2307
+ },
2308
+ {
2309
+ key: 'Macmini4,1',
2310
+ name: 'Mac mini',
2311
+ size: '',
2312
+ processor: '',
2313
+ year: 'Mid 2010',
2314
+ additional: ''
2315
+ },
2316
+ {
2317
+ key: 'Macmini3,1',
2318
+ name: 'Mac mini',
2319
+ size: '',
2320
+ processor: '',
2321
+ year: 'Early 2009',
2322
+ additional: ''
2323
+ },
2324
+ {
2325
+ key: 'Mac16,3',
2326
+ name: 'iMac',
2327
+ size: '24-inch',
2328
+ processor: 'M4',
2329
+ year: '2024',
2330
+ additional: 'Four ports'
2331
+ },
2332
+ {
2333
+ key: 'Mac16,2',
2334
+ name: 'iMac',
2335
+ size: '24-inch',
2336
+ processor: 'M4',
2337
+ year: '2024',
2338
+ additional: 'Two ports'
2339
+ },
2340
+ {
2341
+ key: 'Mac15,5',
2342
+ name: 'iMac',
2343
+ size: '24-inch',
2344
+ processor: 'M3',
2345
+ year: '2023',
2346
+ additional: 'Four ports'
2347
+ },
2348
+ {
2349
+ key: 'Mac15,4',
2350
+ name: 'iMac',
2351
+ size: '24-inch',
2352
+ processor: 'M3',
2353
+ year: '2023',
2354
+ additional: 'Two ports'
2355
+ },
2356
+ {
2357
+ key: 'iMac21,1',
2358
+ name: 'iMac',
2359
+ size: '24-inch',
2360
+ processor: 'M1',
2361
+ year: '2021',
2362
+ additional: ''
2363
+ },
2364
+ {
2365
+ key: 'iMac21,2',
2366
+ name: 'iMac',
2367
+ size: '24-inch',
2368
+ processor: 'M1',
2369
+ year: '2021',
2370
+ additional: ''
2371
+ },
2372
+ {
2373
+ key: 'iMac20,1',
2374
+ name: 'iMac',
2375
+ size: '27-inch',
2376
+ processor: '',
2377
+ year: '2020',
2378
+ additional: 'Retina 5K'
2379
+ },
2380
+ {
2381
+ key: 'iMac20,2',
2382
+ name: 'iMac',
2383
+ size: '27-inch',
2384
+ processor: '',
2385
+ year: '2020',
2386
+ additional: 'Retina 5K'
2387
+ },
2388
+ {
2389
+ key: 'iMac19,1',
2390
+ name: 'iMac',
2391
+ size: '27-inch',
2392
+ processor: '',
2393
+ year: '2019',
2394
+ additional: 'Retina 5K'
2395
+ },
2396
+ {
2397
+ key: 'iMac19,2',
2398
+ name: 'iMac',
2399
+ size: '21.5-inch',
2400
+ processor: '',
2401
+ year: '2019',
2402
+ additional: 'Retina 4K'
2403
+ },
2404
+ {
2405
+ key: 'iMacPro1,1',
2406
+ name: 'iMac Pro',
2407
+ size: '',
2408
+ processor: '',
2409
+ year: '2017',
2410
+ additional: ''
2411
+ },
2412
+ {
2413
+ key: 'iMac18,3',
2414
+ name: 'iMac',
2415
+ size: '27-inch',
2416
+ processor: '',
2417
+ year: '2017',
2418
+ additional: 'Retina 5K'
2419
+ },
2420
+ {
2421
+ key: 'iMac18,2',
2422
+ name: 'iMac',
2423
+ size: '21.5-inch',
2424
+ processor: '',
2425
+ year: '2017',
2426
+ additional: 'Retina 4K'
2427
+ },
2428
+ {
2429
+ key: 'iMac18,1',
2430
+ name: 'iMac',
2431
+ size: '21.5-inch',
2432
+ processor: '',
2433
+ year: '2017',
2434
+ additional: ''
2435
+ },
2436
+ {
2437
+ key: 'iMac17,1',
2438
+ name: 'iMac',
2439
+ size: '27-inch',
2440
+ processor: '',
2441
+ year: 'Late 2015',
2442
+ additional: 'Retina 5K'
2443
+ },
2444
+ {
2445
+ key: 'iMac16,2',
2446
+ name: 'iMac',
2447
+ size: '21.5-inch',
2448
+ processor: '',
2449
+ year: 'Late 2015',
2450
+ additional: 'Retina 4K'
2451
+ },
2452
+ {
2453
+ key: 'iMac16,1',
2454
+ name: 'iMac',
2455
+ size: '21.5-inch',
2456
+ processor: '',
2457
+ year: 'Late 2015',
2458
+ additional: ''
2459
+ },
2460
+ {
2461
+ key: 'iMac15,1',
2462
+ name: 'iMac',
2463
+ size: '27-inch',
2464
+ processor: '',
2465
+ year: 'Late 2014',
2466
+ additional: 'Retina 5K'
2467
+ },
2468
+ {
2469
+ key: 'iMac14,4',
2470
+ name: 'iMac',
2471
+ size: '21.5-inch',
2472
+ processor: '',
2473
+ year: 'Mid 2014',
2474
+ additional: ''
2475
+ },
2476
+ {
2477
+ key: 'iMac14,2',
2478
+ name: 'iMac',
2479
+ size: '27-inch',
2480
+ processor: '',
2481
+ year: 'Late 2013',
2482
+ additional: ''
2483
+ },
2484
+ {
2485
+ key: 'iMac14,1',
2486
+ name: 'iMac',
2487
+ size: '21.5-inch',
2488
+ processor: '',
2489
+ year: 'Late 2013',
2490
+ additional: ''
2491
+ },
2492
+ {
2493
+ key: 'iMac13,2',
2494
+ name: 'iMac',
2495
+ size: '27-inch',
2496
+ processor: '',
2497
+ year: 'Late 2012',
2498
+ additional: ''
2499
+ },
2500
+ {
2501
+ key: 'iMac13,1',
2502
+ name: 'iMac',
2503
+ size: '21.5-inch',
2504
+ processor: '',
2505
+ year: 'Late 2012',
2506
+ additional: ''
2507
+ },
2508
+ {
2509
+ key: 'iMac12,2',
2510
+ name: 'iMac',
2511
+ size: '27-inch',
2512
+ processor: '',
2513
+ year: 'Mid 2011',
2514
+ additional: ''
2515
+ },
2516
+ {
2517
+ key: 'iMac12,1',
2518
+ name: 'iMac',
2519
+ size: '21.5-inch',
2520
+ processor: '',
2521
+ year: 'Mid 2011',
2522
+ additional: ''
2523
+ },
2524
+ {
2525
+ key: 'iMac11,3',
2526
+ name: 'iMac',
2527
+ size: '27-inch',
2528
+ processor: '',
2529
+ year: 'Mid 2010',
2530
+ additional: ''
2531
+ },
2532
+ {
2533
+ key: 'iMac11,2',
2534
+ name: 'iMac',
2535
+ size: '21.5-inch',
2536
+ processor: '',
2537
+ year: 'Mid 2010',
2538
+ additional: ''
2539
+ },
2540
+ {
2541
+ key: 'iMac10,1',
2542
+ name: 'iMac',
2543
+ size: '21.5-inch',
2544
+ processor: '',
2545
+ year: 'Late 2009',
2546
+ additional: ''
2547
+ },
2548
+ {
2549
+ key: 'iMac9,1',
2550
+ name: 'iMac',
2551
+ size: '20-inch',
2552
+ processor: '',
2553
+ year: 'Early 2009',
2554
+ additional: ''
2555
+ },
2556
+ {
2557
+ key: 'Mac14,8',
2558
+ name: 'Mac Pro',
2559
+ size: '',
2560
+ processor: '',
2561
+ year: '2023',
2562
+ additional: ''
2563
+ },
2564
+ {
2565
+ key: 'Mac14,8',
2566
+ name: 'Mac Pro',
2567
+ size: '',
2568
+ processor: '',
2569
+ year: '2023',
2570
+ additional: 'Rack'
2571
+ },
2572
+ {
2573
+ key: 'MacPro7,1',
2574
+ name: 'Mac Pro',
2575
+ size: '',
2576
+ processor: '',
2577
+ year: '2019',
2578
+ additional: ''
2579
+ },
2580
+ {
2581
+ key: 'MacPro7,1',
2582
+ name: 'Mac Pro',
2583
+ size: '',
2584
+ processor: '',
2585
+ year: '2019',
2586
+ additional: 'Rack'
2587
+ },
2588
+ {
2589
+ key: 'MacPro6,1',
2590
+ name: 'Mac Pro',
2591
+ size: '',
2592
+ processor: '',
2593
+ year: 'Late 2013',
2594
+ additional: ''
2595
+ },
2596
+ {
2597
+ key: 'MacPro5,1',
2598
+ name: 'Mac Pro',
2599
+ size: '',
2600
+ processor: '',
2601
+ year: 'Mid 2012',
2602
+ additional: ''
2603
+ },
2604
+ {
2605
+ key: 'MacPro5,1',
2606
+ name: 'Mac Pro Server',
2607
+ size: '',
2608
+ processor: '',
2609
+ year: 'Mid 2012',
2610
+ additional: 'Server'
2611
+ },
2612
+ {
2613
+ key: 'MacPro5,1',
2614
+ name: 'Mac Pro',
2615
+ size: '',
2616
+ processor: '',
2617
+ year: 'Mid 2010',
2618
+ additional: ''
2619
+ },
2620
+ {
2621
+ key: 'MacPro5,1',
2622
+ name: 'Mac Pro Server',
2623
+ size: '',
2624
+ processor: '',
2625
+ year: 'Mid 2010',
2626
+ additional: 'Server'
2627
+ },
2628
+ {
2629
+ key: 'MacPro4,1',
2630
+ name: 'Mac Pro',
2631
+ size: '',
2632
+ processor: '',
2633
+ year: 'Early 2009',
2634
+ additional: ''
2635
+ }
2636
+ ];
2637
+
2638
+ const list = appleModelIds.filter((model) => model.key === key);
2639
+ if (list.length === 0) {
2640
+ return {
2641
+ key: key,
2642
+ model: 'Apple',
2643
+ version: 'Unknown'
2644
+ };
2645
+ }
2646
+ const features = [];
2647
+ if (list[0].size) {
2648
+ features.push(list[0].size);
2649
+ }
2650
+ if (list[0].processor) {
2651
+ features.push(list[0].processor);
2652
+ }
2653
+ if (list[0].year) {
2654
+ features.push(list[0].year);
2655
+ }
2656
+ if (list[0].additional) {
2657
+ features.push(list[0].additional);
2658
+ }
2659
+ return {
2660
+ key: key,
2661
+ model: list[0].name,
2662
+ version: list[0].name + ' (' + features.join(', ') + ')'
2663
+ };
2664
+ }
2665
+
2666
+ function checkWebsite(url, timeout = 5000) {
2667
+ const http = url.startsWith('https:') || url.indexOf(':443/') > 0 || url.indexOf(':8443/') > 0 ? require('https') : require('http');
2668
+ const t = Date.now();
2669
+ return new Promise((resolve) => {
2670
+ const request = http
2671
+ .get(url, (res) => {
2672
+ res.on('data', () => {});
2673
+ res.on('end', () => {
2674
+ resolve({
2675
+ url,
2676
+ statusCode: res.statusCode,
2677
+ message: res.statusMessage,
2678
+ time: Date.now() - t
2679
+ });
2680
+ });
2681
+ })
2682
+ .on('error', (e) => {
2683
+ resolve({
2684
+ url,
2685
+ statusCode: 404,
2686
+ message: e.message,
2687
+ time: Date.now() - t
2688
+ });
2689
+ })
2690
+ .setTimeout(timeout, () => {
2691
+ request.destroy();
2692
+ resolve({
2693
+ url,
2694
+ statusCode: 408,
2695
+ message: 'Request Timeout',
2696
+ time: Date.now() - t
2697
+ });
2698
+ });
2699
+ });
2700
+ }
2701
+
2702
+ function cleanString(str) {
2703
+ return str.replace(/To Be Filled By O.E.M./g, '');
2704
+ }
2705
+ function noop() {}
2706
+
2707
+ exports.toInt = toInt;
2708
+ exports.splitByNumber = splitByNumber;
2709
+ exports.execOptsWin = execOptsWin;
2710
+ exports.execOptsLinux = execOptsLinux;
2711
+ exports.getCodepage = getCodepage;
2712
+ exports.execWin = execWin;
2713
+ exports.isFunction = isFunction;
2714
+ exports.unique = unique;
2715
+ exports.sortByKey = sortByKey;
2716
+ exports.cores = cores;
2717
+ exports.getValue = getValue;
2718
+ exports.decodeEscapeSequence = decodeEscapeSequence;
2719
+ exports.parseDateTime = parseDateTime;
2720
+ exports.parseHead = parseHead;
2721
+ exports.findObjectByKey = findObjectByKey;
2722
+ exports.darwinXcodeExists = darwinXcodeExists;
2723
+ exports.getVboxmanage = getVboxmanage;
2724
+ exports.powerShell = powerShell;
2725
+ exports.powerShellStart = powerShellStart;
2726
+ exports.powerShellRelease = powerShellRelease;
2727
+ exports.execSafe = execSafe;
2728
+ exports.nanoSeconds = nanoSeconds;
2729
+ exports.countUniqueLines = countUniqueLines;
2730
+ exports.countLines = countLines;
2731
+ exports.noop = noop;
2732
+ exports.isRaspberry = isRaspberry;
2733
+ exports.isRaspbian = isRaspbian;
2734
+ exports.sanitizeShellString = sanitizeShellString;
2735
+ exports.isPrototypePolluted = isPrototypePolluted;
2736
+ exports.decodePiCpuinfo = decodePiCpuinfo;
2737
+ exports.getRpiGpu = getRpiGpu;
2738
+ exports.promiseAll = promiseAll;
2739
+ exports.promisify = promisify;
2740
+ exports.promisifySave = promisifySave;
2741
+ exports.smartMonToolsInstalled = smartMonToolsInstalled;
2742
+ exports.linuxVersion = linuxVersion;
2743
+ exports.plistParser = plistParser;
2744
+ exports.plistReader = plistReader;
2745
+ exports.stringObj = stringObj;
2746
+ exports.stringReplace = stringReplace;
2747
+ exports.stringToLower = stringToLower;
2748
+ exports.stringToString = stringToString;
2749
+ exports.stringSubstr = stringSubstr;
2750
+ exports.stringSubstring = stringSubstring;
2751
+ exports.stringTrim = stringTrim;
2752
+ exports.stringStartWith = stringStartWith;
2753
+ exports.mathMin = mathMin;
2754
+ exports.WINDIR = WINDIR;
2755
+ exports.getFilesInPath = getFilesInPath;
2756
+ exports.semverCompare = semverCompare;
2757
+ exports.getAppleModel = getAppleModel;
2758
+ exports.checkWebsite = checkWebsite;
2759
+ exports.cleanString = cleanString;
2760
+ exports.getPowershell = getPowershell;