1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | const os = require('os');
|
17 | const fs = require('fs');
|
18 | const spawn = require('child_process').spawn;
|
19 | const exec = require('child_process').exec;
|
20 | const execSync = require('child_process').execSync;
|
21 | const util = require('util');
|
22 |
|
23 | let _platform = process.platform;
|
24 | const _linux = (_platform === 'linux');
|
25 | const _darwin = (_platform === 'darwin');
|
26 | const _windows = (_platform === 'win32');
|
27 | const _freebsd = (_platform === 'freebsd');
|
28 | const _openbsd = (_platform === 'openbsd');
|
29 | const _netbsd = (_platform === 'netbsd');
|
30 |
|
31 |
|
32 | let _cores = 0;
|
33 | let wmicPath = '';
|
34 | let codepage = '';
|
35 |
|
36 | const execOptsWin = {
|
37 | windowsHide: true,
|
38 | maxBuffer: 1024 * 20000,
|
39 | encoding: 'UTF-8',
|
40 | env: util._extend({}, process.env, { LANG: 'en_US.UTF-8' })
|
41 | };
|
42 |
|
43 | function toInt(value) {
|
44 | let result = parseInt(value, 10);
|
45 | if (isNaN(result)) {
|
46 | result = 0;
|
47 | }
|
48 | return result;
|
49 | }
|
50 |
|
51 | function isFunction(functionToCheck) {
|
52 | let getType = {};
|
53 | return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
|
54 | }
|
55 |
|
56 | function unique(obj) {
|
57 | let uniques = [];
|
58 | let stringify = {};
|
59 | for (let i = 0; i < obj.length; i++) {
|
60 | let keys = Object.keys(obj[i]);
|
61 | keys.sort(function (a, b) { return a - b; });
|
62 | let str = '';
|
63 | for (let j = 0; j < keys.length; j++) {
|
64 | str += JSON.stringify(keys[j]);
|
65 | str += JSON.stringify(obj[i][keys[j]]);
|
66 | }
|
67 | if (!{}.hasOwnProperty.call(stringify, str)) {
|
68 | uniques.push(obj[i]);
|
69 | stringify[str] = true;
|
70 | }
|
71 | }
|
72 | return uniques;
|
73 | }
|
74 |
|
75 | function sortByKey(array, keys) {
|
76 | return array.sort(function (a, b) {
|
77 | let x = '';
|
78 | let y = '';
|
79 | keys.forEach(function (key) {
|
80 | x = x + a[key]; y = y + b[key];
|
81 | });
|
82 | return ((x < y) ? -1 : ((x > y) ? 1 : 0));
|
83 | });
|
84 | }
|
85 |
|
86 | function cores() {
|
87 | if (_cores === 0) {
|
88 | _cores = os.cpus().length;
|
89 | }
|
90 | return _cores;
|
91 | }
|
92 |
|
93 | function getValue(lines, property, separator, trimmed) {
|
94 | separator = separator || ':';
|
95 | property = property.toLowerCase();
|
96 | trimmed = trimmed || false;
|
97 | for (let i = 0; i < lines.length; i++) {
|
98 | let line = lines[i].toLowerCase().replace(/\t/g, '');
|
99 | if (trimmed) {
|
100 | line = line.trim();
|
101 | }
|
102 | if (line.startsWith(property)) {
|
103 | const parts = lines[i].split(separator);
|
104 | if (parts.length >= 2) {
|
105 | parts.shift();
|
106 | return parts.join(separator).trim();
|
107 | } else {
|
108 | return '';
|
109 | }
|
110 | }
|
111 | }
|
112 | return '';
|
113 | }
|
114 |
|
115 | function decodeEscapeSequence(str, base) {
|
116 | base = base || 16;
|
117 | return str.replace(/\\x([0-9A-Fa-f]{2})/g, function () {
|
118 | return String.fromCharCode(parseInt(arguments[1], base));
|
119 | });
|
120 | }
|
121 |
|
122 | function detectSplit(str) {
|
123 | let seperator = '';
|
124 | let part = 0;
|
125 | str.split('').forEach(element => {
|
126 | if (element >= '0' && element <= '9') {
|
127 | if (part === 1) { part++; }
|
128 | } else {
|
129 | if (part === 0) { part++; }
|
130 | if (part === 1) {
|
131 | seperator += element;
|
132 | }
|
133 | }
|
134 | });
|
135 | return seperator;
|
136 | }
|
137 |
|
138 | function parseTime(t, pmDesignator) {
|
139 | pmDesignator = pmDesignator || '';
|
140 | t = t.toUpperCase();
|
141 | let hour = 0;
|
142 | let min = 0;
|
143 | let splitter = detectSplit(t);
|
144 | let parts = t.split(splitter);
|
145 | if (parts.length >= 2) {
|
146 | if (parts[2]) {
|
147 | parts[1] += parts[2];
|
148 | }
|
149 | let isPM = (parts[1] && (parts[1].toLowerCase().indexOf('pm') > -1) || (parts[1].toLowerCase().indexOf('p.m.') > -1) || (parts[1].toLowerCase().indexOf('p. m.') > -1) || (parts[1].toLowerCase().indexOf('n') > -1) || (parts[1].toLowerCase().indexOf('ch') > -1) || (parts[1].toLowerCase().indexOf('ös') > -1) || (pmDesignator && parts[1].toLowerCase().indexOf(pmDesignator) > -1));
|
150 | hour = parseInt(parts[0], 10);
|
151 | min = parseInt(parts[1], 10);
|
152 | hour = isPM && hour < 12 ? hour + 12 : hour;
|
153 | return ('0' + hour).substr(-2) + ':' + ('0' + min).substr(-2);
|
154 | }
|
155 | }
|
156 |
|
157 | function parseDateTime(dt, culture) {
|
158 | const result = {
|
159 | date: '',
|
160 | time: ''
|
161 | };
|
162 | culture = culture || {};
|
163 | let dateFormat = (culture.dateFormat || '').toLowerCase();
|
164 | let pmDesignator = (culture.pmDesignator || '');
|
165 |
|
166 | const parts = dt.split(' ');
|
167 | if (parts[0]) {
|
168 | if (parts[0].indexOf('/') >= 0) {
|
169 |
|
170 | const dtparts = parts[0].split('/');
|
171 | if (dtparts.length === 3) {
|
172 | if (dtparts[0].length === 4) {
|
173 |
|
174 | result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
|
175 | } else if (dtparts[2].length === 2) {
|
176 | if ((dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1)) {
|
177 |
|
178 | result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
|
179 | } else {
|
180 |
|
181 | result.date = '20' + dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
|
182 | }
|
183 | } else {
|
184 |
|
185 | const isEN = ((dt.toLowerCase().indexOf('pm') > -1) || (dt.toLowerCase().indexOf('p.m.') > -1) || (dt.toLowerCase().indexOf('p. m.') > -1) || (dt.toLowerCase().indexOf('am') > -1) || (dt.toLowerCase().indexOf('a.m.') > -1) || (dt.toLowerCase().indexOf('a. m.') > -1));
|
186 | if ((isEN || dateFormat.indexOf('/d/') > -1 || dateFormat.indexOf('/dd/') > -1) && dateFormat.indexOf('dd/') !== 0) {
|
187 |
|
188 | result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
|
189 | } else {
|
190 |
|
191 | result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
|
192 | }
|
193 | }
|
194 | }
|
195 | }
|
196 | if (parts[0].indexOf('.') >= 0) {
|
197 | const dtparts = parts[0].split('.');
|
198 | if (dtparts.length === 3) {
|
199 | if (dateFormat.indexOf('.d.') > -1 || dateFormat.indexOf('.dd.') > -1) {
|
200 |
|
201 | result.date = dtparts[2] + '-' + ('0' + dtparts[0]).substr(-2) + '-' + ('0' + dtparts[1]).substr(-2);
|
202 | } else {
|
203 |
|
204 | result.date = dtparts[2] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[0]).substr(-2);
|
205 | }
|
206 | }
|
207 | }
|
208 | if (parts[0].indexOf('-') >= 0) {
|
209 |
|
210 | const dtparts = parts[0].split('-');
|
211 | if (dtparts.length === 3) {
|
212 | result.date = dtparts[0] + '-' + ('0' + dtparts[1]).substr(-2) + '-' + ('0' + dtparts[2]).substr(-2);
|
213 | }
|
214 | }
|
215 | }
|
216 | if (parts[1]) {
|
217 | parts.shift();
|
218 | let time = parts.join(' ');
|
219 | result.time = parseTime(time, pmDesignator);
|
220 | }
|
221 | return result;
|
222 | }
|
223 |
|
224 | function parseHead(head, rights) {
|
225 | let space = (rights > 0);
|
226 | let count = 1;
|
227 | let from = 0;
|
228 | let to = 0;
|
229 | let result = [];
|
230 | for (let i = 0; i < head.length; i++) {
|
231 | if (count <= rights) {
|
232 |
|
233 | if (/\s/.test(head[i]) && !space) {
|
234 | to = i - 1;
|
235 | result.push({
|
236 | from: from,
|
237 | to: to + 1,
|
238 | cap: head.substring(from, to + 1)
|
239 | });
|
240 | from = to + 2;
|
241 | count++;
|
242 | }
|
243 | space = head[i] === ' ';
|
244 | } else {
|
245 | if (!/\s/.test(head[i]) && space) {
|
246 | to = i - 1;
|
247 | if (from < to) {
|
248 | result.push({
|
249 | from: from,
|
250 | to: to,
|
251 | cap: head.substring(from, to)
|
252 | });
|
253 | }
|
254 | from = to + 1;
|
255 | count++;
|
256 | }
|
257 | space = head[i] === ' ';
|
258 | }
|
259 | }
|
260 | to = 1000;
|
261 | result.push({
|
262 | from: from,
|
263 | to: to,
|
264 | cap: head.substring(from, to)
|
265 | });
|
266 | let len = result.length;
|
267 | for (var i = 0; i < len; i++) {
|
268 | if (result[i].cap.replace(/\s/g, '').length === 0) {
|
269 | if (i + 1 < len) {
|
270 | result[i].to = result[i + 1].to;
|
271 | result[i].cap = result[i].cap + result[i + 1].cap;
|
272 | result.splice(i + 1, 1);
|
273 | len = len - 1;
|
274 | }
|
275 | }
|
276 | }
|
277 | return result;
|
278 | }
|
279 |
|
280 | function findObjectByKey(array, key, value) {
|
281 | for (let i = 0; i < array.length; i++) {
|
282 | if (array[i][key] === value) {
|
283 | return i;
|
284 | }
|
285 | }
|
286 | return -1;
|
287 | }
|
288 |
|
289 | function getWmic() {
|
290 | if (os.type() === 'Windows_NT' && !wmicPath) {
|
291 | wmicPath = process.env.WINDIR + '\\system32\\wbem\\wmic.exe';
|
292 | if (!fs.existsSync(wmicPath)) {
|
293 | try {
|
294 | const wmicPathArray = execSync('WHERE WMIC').toString().split('\r\n');
|
295 | if (wmicPathArray && wmicPathArray.length) {
|
296 | wmicPath = wmicPathArray[0];
|
297 | } else {
|
298 | wmicPath = 'wmic';
|
299 | }
|
300 | } catch (e) {
|
301 | wmicPath = 'wmic';
|
302 | }
|
303 | }
|
304 | }
|
305 | return wmicPath;
|
306 | }
|
307 |
|
308 | function wmic(command, options) {
|
309 | options = options || execOptsWin;
|
310 | return new Promise((resolve) => {
|
311 | process.nextTick(() => {
|
312 | try {
|
313 | exec(process.env.WINDIR + '\\system32\\chcp.com 65001 | ' + getWmic() + ' ' + command, options, function (error, stdout) {
|
314 | resolve(stdout, error);
|
315 | }).stdin.end();
|
316 | } catch (e) {
|
317 | resolve('', e);
|
318 | }
|
319 | });
|
320 | });
|
321 | }
|
322 |
|
323 | function getVboxmanage() {
|
324 | return _windows ? process.env.VBOX_INSTALL_PATH || process.env.VBOX_MSI_INSTALL_PATH + '\\VBoxManage.exe' + '" ' : 'vboxmanage';
|
325 | }
|
326 |
|
327 | function powerShell(cmd) {
|
328 |
|
329 | let result = '';
|
330 |
|
331 | return new Promise((resolve) => {
|
332 | process.nextTick(() => {
|
333 | try {
|
334 | const child = spawn('powershell.exe', ['-NoLogo', '-InputFormat', 'Text', '-NoExit', '-ExecutionPolicy', 'Unrestricted', '-Command', '-'], {
|
335 | stdio: 'pipe',
|
336 | windowsHide: true,
|
337 | maxBuffer: 1024 * 20000,
|
338 | encoding: 'UTF-8',
|
339 | env: util._extend({}, process.env, { LANG: 'en_US.UTF-8' })
|
340 | });
|
341 |
|
342 | if (child && !child.pid) {
|
343 | child.on('error', function () {
|
344 | resolve(result);
|
345 | });
|
346 | }
|
347 | if (child && child.pid) {
|
348 | child.stdout.on('data', function (data) {
|
349 | result = result + data.toString('utf8');
|
350 | });
|
351 | child.stderr.on('data', function () {
|
352 | child.kill();
|
353 | resolve(result);
|
354 | });
|
355 | child.on('close', function () {
|
356 | child.kill();
|
357 | resolve(result);
|
358 | });
|
359 | child.on('error', function () {
|
360 | child.kill();
|
361 | resolve(result);
|
362 | });
|
363 | try {
|
364 | child.stdin.write(cmd + os.EOL);
|
365 | child.stdin.write('exit' + os.EOL);
|
366 | child.stdin.end();
|
367 | } catch (e) {
|
368 | child.kill();
|
369 | resolve(result);
|
370 | }
|
371 | } else {
|
372 | resolve(result);
|
373 | }
|
374 | } catch (e) {
|
375 | resolve(result);
|
376 | }
|
377 | });
|
378 | });
|
379 | }
|
380 |
|
381 | function getCodepage() {
|
382 | if (_windows) {
|
383 | if (!codepage) {
|
384 | try {
|
385 | const stdout = execSync('chcp');
|
386 | const lines = stdout.toString().split('\r\n');
|
387 | const parts = lines[0].split(':');
|
388 | codepage = parts.length > 1 ? parts[1].replace('.', '') : '';
|
389 | } catch (err) {
|
390 | codepage = '437';
|
391 | }
|
392 | }
|
393 | return codepage;
|
394 | }
|
395 | if (_linux || _darwin || _freebsd || _openbsd || _netbsd) {
|
396 | if (!codepage) {
|
397 | try {
|
398 | const stdout = execSync('echo $LANG');
|
399 | const lines = stdout.toString().split('\r\n');
|
400 | const parts = lines[0].split('.');
|
401 | codepage = parts.length > 1 ? parts[1].trim() : '';
|
402 | if (!codepage) {
|
403 | codepage = 'UTF-8';
|
404 | }
|
405 | } catch (err) {
|
406 | codepage = 'UTF-8';
|
407 | }
|
408 | }
|
409 | return codepage;
|
410 | }
|
411 | }
|
412 |
|
413 | function isRaspberry() {
|
414 | const PI_MODEL_NO = [
|
415 | 'BCM2708',
|
416 | 'BCM2709',
|
417 | 'BCM2710',
|
418 | 'BCM2835',
|
419 | 'BCM2837B0'
|
420 | ];
|
421 | let cpuinfo = [];
|
422 | try {
|
423 | cpuinfo = fs.readFileSync('/proc/cpuinfo', { encoding: 'utf8' }).split('\n');
|
424 | } catch (e) {
|
425 | return false;
|
426 | }
|
427 | const hardware = getValue(cpuinfo, 'hardware');
|
428 | return (hardware && PI_MODEL_NO.indexOf(hardware) > -1);
|
429 | }
|
430 |
|
431 | function isRaspbian() {
|
432 | let osrelease = [];
|
433 | try {
|
434 | osrelease = fs.readFileSync('/etc/os-release', { encoding: 'utf8' }).split('\n');
|
435 | } catch (e) {
|
436 | return false;
|
437 | }
|
438 | const id = getValue(osrelease, 'id');
|
439 | return (id && id.indexOf('raspbian') > -1);
|
440 | }
|
441 |
|
442 | function execWin(cmd, opts, callback) {
|
443 | if (!callback) {
|
444 | callback = opts;
|
445 | opts = execOptsWin;
|
446 | }
|
447 | let newCmd = 'chcp 65001 > nul && cmd /C ' + cmd + ' && chcp ' + codepage + ' > nul';
|
448 | exec(newCmd, opts, function (error, stdout) {
|
449 | callback(error, stdout);
|
450 | });
|
451 | }
|
452 |
|
453 | function darwinXcodeExists() {
|
454 | const cmdLineToolsExists = fs.existsSync('/Library/Developer/CommandLineTools/usr/bin/');
|
455 | const xcodeAppExists = fs.existsSync('/Applications/Xcode.app/Contents/Developer/Tools');
|
456 | const xcodeExists = fs.existsSync('/Library/Developer/Xcode/');
|
457 | return (cmdLineToolsExists || xcodeExists || xcodeAppExists);
|
458 | }
|
459 |
|
460 | function nanoSeconds() {
|
461 | const time = process.hrtime();
|
462 | if (!Array.isArray(time) || time.length !== 2) {
|
463 | return 0;
|
464 | }
|
465 | return +time[0] * 1e9 + +time[1];
|
466 | }
|
467 |
|
468 | function countUniqueLines(lines, startingWith) {
|
469 | startingWith = startingWith || '';
|
470 | const uniqueLines = [];
|
471 | lines.forEach(line => {
|
472 | if (line.startsWith(startingWith)) {
|
473 | if (uniqueLines.indexOf(line) === -1) {
|
474 | uniqueLines.push(line);
|
475 | }
|
476 | }
|
477 | });
|
478 | return uniqueLines.length;
|
479 | }
|
480 |
|
481 | function countLines(lines, startingWith) {
|
482 | startingWith = startingWith || '';
|
483 | const uniqueLines = [];
|
484 | lines.forEach(line => {
|
485 | if (line.startsWith(startingWith)) {
|
486 | uniqueLines.push(line);
|
487 | }
|
488 | });
|
489 | return uniqueLines.length;
|
490 | }
|
491 |
|
492 | function sanitizeShellString(str) {
|
493 | let result = str;
|
494 | result = result.replace(/>/g, '');
|
495 | result = result.replace(/</g, '');
|
496 | result = result.replace(/\*/g, '');
|
497 | result = result.replace(/\?/g, '');
|
498 | result = result.replace(/\[/g, '');
|
499 | result = result.replace(/\]/g, '');
|
500 | result = result.replace(/\|/g, '');
|
501 | result = result.replace(/\`/g, '');
|
502 | result = result.replace(/\$/g, '');
|
503 | result = result.replace(/;/g, '');
|
504 | result = result.replace(/&/g, '');
|
505 | result = result.replace(/\)/g, '');
|
506 | result = result.replace(/\(/g, '');
|
507 | result = result.replace(/\$/g, '');
|
508 | result = result.replace(/#/g, '');
|
509 | result = result.replace(/\\/g, '');
|
510 | result = result.replace(/\t/g, '');
|
511 | result = result.replace(/\n/g, '');
|
512 | result = result.replace(/\"/g, '');
|
513 | return result;
|
514 | }
|
515 |
|
516 | function noop() { }
|
517 |
|
518 | exports.toInt = toInt;
|
519 | exports.execOptsWin = execOptsWin;
|
520 | exports.getCodepage = getCodepage;
|
521 | exports.execWin = execWin;
|
522 | exports.isFunction = isFunction;
|
523 | exports.unique = unique;
|
524 | exports.sortByKey = sortByKey;
|
525 | exports.cores = cores;
|
526 | exports.getValue = getValue;
|
527 | exports.decodeEscapeSequence = decodeEscapeSequence;
|
528 | exports.parseDateTime = parseDateTime;
|
529 | exports.parseHead = parseHead;
|
530 | exports.findObjectByKey = findObjectByKey;
|
531 | exports.getWmic = getWmic;
|
532 | exports.wmic = wmic;
|
533 | exports.darwinXcodeExists = darwinXcodeExists;
|
534 | exports.getVboxmanage = getVboxmanage;
|
535 | exports.powerShell = powerShell;
|
536 | exports.nanoSeconds = nanoSeconds;
|
537 | exports.countUniqueLines = countUniqueLines;
|
538 | exports.countLines = countLines;
|
539 | exports.noop = noop;
|
540 | exports.isRaspberry = isRaspberry;
|
541 | exports.isRaspbian = isRaspbian;
|
542 | exports.sanitizeShellString = sanitizeShellString;
|