move identifiers to server side to allow future updates (#5641)

* move identifiers to server side to allow future updates Signed-off-by: si458 <simonsmith5521@gmail.com> * add rpi support Signed-off-by: si458 <simonsmith5521@gmail.com> --------- Signed-off-by: si458 <simonsmith5521@gmail.com>

Simon Smith committed Dec 22, 2023 at 23:18 UTC bfae0d6c6e29b09f81a17778fa5adaed8c70d28c
2 files changed +792 -16
agents/meshcore.js
+17 -16
@@ -622,7 +622,7 @@ if ((require('fs').existsSync(process.cwd() + 'batterystate.txt')) && (require('
622 else {
623 try {
624 // Setup normal battery monitoring
625 - if (require('identifiers').isBatteryPowered && require('identifiers').isBatteryPowered()) {
625 + if (require('computer-identifiers').isBatteryPowered && require('computer-identifiers').isBatteryPowered()) {
626 require('MeshAgent')._battLevelChanged = function _battLevelChanged(val) {
627 _battLevelChanged.self._currentBatteryLevel = val;
628 _battLevelChanged.self.SendCommand({ action: 'battery', state: _battLevelChanged.self._currentPowerState, level: val });
@@ -657,14 +657,14 @@ try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; meshCoreO
657 // Get Volumes and BitLocker if Windows
658 try {
659 if (process.platform == 'win32'){
660 - if (require('identifiers').volumes_promise != null){
661 - var p = require('identifiers').volumes_promise();
660 + if (require('computer-identifiers').volumes_promise != null){
661 + var p = require('computer-identifiers').volumes_promise();
662 p.then(function (res){
663 meshCoreObj.volumes = res;
664 meshCoreObjChanged();
665 });
666 - }else if (require('identifiers').volumes != null){
667 - meshCoreObj.volumes = require('identifiers').volumes();
666 + }else if (require('computer-identifiers').volumes != null){
667 + meshCoreObj.volumes = require('computer-identifiers').volumes();
668 meshCoreObjChanged();
669 }
670 }
@@ -1813,7 +1813,7 @@ function onFileWatcher(a, b) {
1813 */
1814
1815 // Replace all key name spaces with _ in an object recursively.
1816 -// This is a workaround since require('identifiers').get() returns key names with spaces in them on Linux.
1816 +// This is a workaround since require('computer-identifiers').get() returns key names with spaces in them on Linux.
1817 function replaceSpacesWithUnderscoresRec(o) {
1818 if (typeof o != 'object') return;
1819 for (var i in o) { if (i.indexOf(' ') >= 0) { o[i.split(' ').join('_')] = o[i]; delete o[i]; } replaceSpacesWithUnderscoresRec(o[i]); }
@@ -1821,8 +1821,7 @@ function replaceSpacesWithUnderscoresRec(o) {
1821
1822 function getSystemInformation(func) {
1823 try {
1824 - var results = { hardware: require('identifiers').get() }; // Hardware info
1825 -
1824 + var results = { hardware: require('computer-identifiers').get() }; // Hardware info
1825 if (results.hardware && results.hardware.windows) {
1826 // Remove extra entries and things that change quickly
1827 var x = results.hardware.windows.osinfo;
@@ -1873,9 +1872,11 @@ function getSystemInformation(func) {
1872 }
1873 if(results.hardware && results.hardware.linux) {
1874 if (!results.hardware.identifiers['bios_serial']) {
1876 - if (require('fs').statSync('/sys/class/dmi/id/product_serial').isFile()){
1877 - results.hardware.identifiers['bios_serial'] = require('fs').readFileSync('/sys/class/dmi/id/product_serial').toString().trim();
1878 - }
1875 + try {
1876 + if (require('fs').statSync('/sys/class/dmi/id/product_serial').isFile()){
1877 + results.hardware.identifiers['bios_serial'] = require('fs').readFileSync('/sys/class/dmi/id/product_serial').toString().trim();
1878 + }
1879 + } catch (ex) { }
1880 }
1881 if (!results.hardware.identifiers['bios_mode']) {
1882 try {
@@ -1928,9 +1929,9 @@ function getSystemInformation(func) {
1929 {
1930 results.pendingReboot = require('win-info').pendingReboot(); // Pending reboot
1931
1931 - if (require('identifiers').volumes_promise != null)
1932 + if (require('computer-identifiers').volumes_promise != null)
1933 {
1933 - var p = require('identifiers').volumes_promise();
1934 + var p = require('computer-identifiers').volumes_promise();
1935 p.then(function (res)
1936 {
1937 results.hardware.windows.volumes = res;
@@ -1938,9 +1939,9 @@ function getSystemInformation(func) {
1939 func(results);
1940 });
1941 }
1941 - else if (require('identifiers').volumes != null)
1942 + else if (require('computer-identifiers').volumes != null)
1943 {
1943 - results.hardware.windows.volumes = require('identifiers').volumes();
1944 + results.hardware.windows.volumes = require('computer-identifiers').volumes();
1945 results.hash = hasher.syncHash(JSON.stringify(results)).toString('hex');
1946 func(results);
1947 }
@@ -4250,7 +4251,7 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
4251 }
4252 break;
4253 case 'vm':
4253 - response = 'Virtual Machine = ' + require('identifiers').isVM();
4254 + response = 'Virtual Machine = ' + require('computer-identifiers').isVM();
4255 break;
4256 case 'startupoptions':
4257 response = JSON.stringify(require('MeshAgent').getStartupOptions());
agents/modules_meshcore/computer-identifiers.js new
+775
@@ -0,0 +1,775 @@
1 +/*
2 +Copyright 2019-2021 Intel Corporation
3 +
4 +Licensed under the Apache License, Version 2.0 (the "License");
5 +you may not use this file except in compliance with the License.
6 +You may obtain a copy of the License at
7 +
8 + http://www.apache.org/licenses/LICENSE-2.0
9 +
10 +Unless required by applicable law or agreed to in writing, software
11 +distributed under the License is distributed on an "AS IS" BASIS,
12 +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 +See the License for the specific language governing permissions and
14 +limitations under the License.
15 +*/
16 +
17 +function trimIdentifiers(val)
18 +{
19 + for(var v in val)
20 + {
21 + if (!val[v] || val[v] == 'None' || val[v] == '') { delete val[v]; }
22 + }
23 +}
24 +function trimResults(val)
25 +{
26 + var i, x;
27 + for (i = 0; i < val.length; ++i)
28 + {
29 + for (x in val[i])
30 + {
31 + if (x.startsWith('_'))
32 + {
33 + delete val[i][x];
34 + }
35 + else
36 + {
37 + if (val[i][x] == null || val[i][x] == 0)
38 + {
39 + delete val[i][x];
40 + }
41 + }
42 + }
43 + }
44 +}
45 +function brief(headers, obj)
46 +{
47 + var i, x;
48 + for (x = 0; x < obj.length; ++x)
49 + {
50 + for (i in obj[x])
51 + {
52 + if (!headers.includes(i))
53 + {
54 + delete obj[x][i];
55 + }
56 + }
57 + }
58 + return (obj);
59 +}
60 +
61 +function dataHandler(c)
62 +{
63 + this.str += c.toString();
64 +}
65 +
66 +function linux_identifiers()
67 +{
68 + var identifiers = {};
69 + var ret = {};
70 + var values = {};
71 +
72 + if (!require('fs').existsSync('/sys/class/dmi/id')) {
73 + if(require('fs').existsSync('/sys/firmware/devicetree/base/model')){
74 + if(require('fs').readFileSync('/sys/firmware/devicetree/base/model').toString().trim().startsWith('Raspberry')){
75 + identifiers['board_vendor'] = 'Raspberry Pi';
76 + identifiers['board_name'] = require('fs').readFileSync('/sys/firmware/devicetree/base/model').toString().trim();
77 + identifiers['board_serial'] = require('fs').readFileSync('/sys/firmware/devicetree/base/serial-number').toString().trim();
78 + }else{
79 + throw('Unknown board');
80 + }
81 + }else {
82 + throw ('this platform does not have DMI statistics');
83 + }
84 + } else {
85 + var entries = require('fs').readdirSync('/sys/class/dmi/id');
86 + for(var i in entries)
87 + {
88 + if (require('fs').statSync('/sys/class/dmi/id/' + entries[i]).isFile())
89 + {
90 + try
91 + {
92 + ret[entries[i]] = require('fs').readFileSync('/sys/class/dmi/id/' + entries[i]).toString().trim();
93 + }
94 + catch(z)
95 + {
96 + }
97 + if (ret[entries[i]] == 'None') { delete ret[entries[i]];}
98 + }
99 + }
100 + entries = null;
101 +
102 + identifiers['bios_date'] = ret['bios_date'];
103 + identifiers['bios_vendor'] = ret['bios_vendor'];
104 + identifiers['bios_version'] = ret['bios_version'];
105 + identifiers['bios_serial'] = ret['product_serial'];
106 + identifiers['board_name'] = ret['board_name'];
107 + identifiers['board_serial'] = ret['board_serial'];
108 + identifiers['board_vendor'] = ret['board_vendor'];
109 + identifiers['board_version'] = ret['board_version'];
110 + identifiers['product_uuid'] = ret['product_uuid'];
111 + identifiers['product_name'] = ret['product_name'];
112 + }
113 +
114 + try {
115 + identifiers['bios_mode'] = (require('fs').statSync('/sys/firmware/efi').isDirectory() ? 'UEFI': 'Legacy');
116 + } catch (ex) { identifiers['bios_mode'] = 'Legacy'; }
117 +
118 + var child = require('child_process').execFile('/bin/sh', ['sh']);
119 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
120 + child.stdin.write('cat /proc/cpuinfo | grep "model name" | ' + "tr '\\n' ':' | awk -F: '{ print $2 }'\nexit\n");
121 + child.waitExit();
122 + identifiers['cpu_name'] = child.stdout.str.trim();
123 + child = null;
124 +
125 +
126 + // Fetch GPU info
127 + child = require('child_process').execFile('/bin/sh', ['sh']);
128 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
129 + child.stdin.write("lspci | grep ' VGA ' | tr '\\n' '`' | awk '{ a=split($0,lines" + ',"`"); printf "["; for(i=1;i<a;++i) { split(lines[i],gpu,"r: "); printf "%s\\"%s\\"", (i==1?"":","),gpu[2]; } printf "]"; }\'\nexit\n');
130 + child.waitExit();
131 + try { identifiers['gpu_name'] = JSON.parse(child.stdout.str.trim()); } catch (xx) { }
132 + child = null;
133 +
134 + // Fetch Storage Info
135 + child = require('child_process').execFile('/bin/sh', ['sh']);
136 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
137 + child.stdin.write("lshw -class disk | tr '\\n' '`' | awk '" + '{ len=split($0,lines,"*"); printf "["; for(i=2;i<=len;++i) { model=""; caption=""; size=""; clen=split(lines[i],item,"`"); for(j=2;j<clen;++j) { split(item[j],tokens,":"); split(tokens[1],key," "); if(key[1]=="description") { caption=substr(tokens[2],2); } if(key[1]=="product") { model=substr(tokens[2],2); } if(key[1]=="size") { size=substr(tokens[2],2); } } if(model=="") { model=caption; } if(caption!="" || model!="") { printf "%s{\\"Caption\\":\\"%s\\",\\"Model\\":\\"%s\\",\\"Size\\":\\"%s\\"}",(i==2?"":","),caption,model,size; } } printf "]"; }\'\nexit\n');
138 + child.waitExit();
139 + try { identifiers['storage_devices'] = JSON.parse(child.stdout.str.trim()); } catch (xx) { }
140 +
141 + values.identifiers = identifiers;
142 + values.linux = ret;
143 + trimIdentifiers(values.identifiers);
144 + child = null;
145 +
146 + var dmidecode = require('lib-finder').findBinary('dmidecode');
147 + if (dmidecode != null)
148 + {
149 + child = require('child_process').execFile('/bin/sh', ['sh']);
150 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
151 + child.stderr.str = ''; child.stderr.on('data', dataHandler);
152 + child.stdin.write(dmidecode + " -t memory | tr '\\n' '`' | ");
153 + child.stdin.write(" awk '{ ");
154 + child.stdin.write(' printf("[");');
155 + child.stdin.write(' comma="";');
156 + child.stdin.write(' c=split($0, lines, "``");');
157 + child.stdin.write(' for(i=1;i<=c;++i)');
158 + child.stdin.write(' {');
159 + child.stdin.write(' d=split(lines[i], val, "`");');
160 + child.stdin.write(' split(val[1], tokens, ",");');
161 + child.stdin.write(' split(tokens[2], dmitype, " ");');
162 + child.stdin.write(' dmi = dmitype[3]+0; ');
163 + child.stdin.write(' if(dmi == 5 || dmi == 6 || dmi == 16 || dmi == 17)');
164 + child.stdin.write(' {');
165 + child.stdin.write(' ccx="";');
166 + child.stdin.write(' printf("%s{\\"%s\\": {", comma, val[2]);');
167 + child.stdin.write(' for(j=3;j<d;++j)');
168 + child.stdin.write(' {');
169 + child.stdin.write(' sub(/^[ \\t]*/,"",val[j]);');
170 + child.stdin.write(' if(split(val[j],tmp,":")>1)');
171 + child.stdin.write(' {');
172 + child.stdin.write(' sub(/^[ \\t]*/,"",tmp[2]);');
173 + child.stdin.write(' gsub(/ /,"",tmp[1]);');
174 + child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", ccx, tmp[1], tmp[2]);');
175 + child.stdin.write(' ccx=",";');
176 + child.stdin.write(' }');
177 + child.stdin.write(' }');
178 + child.stdin.write(' printf("}}");');
179 + child.stdin.write(' comma=",";');
180 + child.stdin.write(' }');
181 + child.stdin.write(' }');
182 + child.stdin.write(' printf("]");');
183 + child.stdin.write("}'\nexit\n");
184 + child.waitExit();
185 +
186 + try
187 + {
188 + var j = JSON.parse(child.stdout.str);
189 + var i, key, key2;
190 + for (i = 0; i < j.length; ++i)
191 + {
192 + for (key in j[i])
193 + {
194 + delete j[i][key]['ArrayHandle'];
195 + delete j[i][key]['ErrorInformationHandle'];
196 + for (key2 in j[i][key])
197 + {
198 + if (j[i][key][key2] == 'Unknown' || j[i][key][key2] == 'Not Specified' || j[i][key][key2] == '')
199 + {
200 + delete j[i][key][key2];
201 + }
202 + }
203 + }
204 + }
205 +
206 + if(j.length > 0){
207 + var mem = {};
208 + for (i = 0; i < j.length; ++i)
209 + {
210 + for (key in j[i])
211 + {
212 + if (mem[key] == null) { mem[key] = []; }
213 + mem[key].push(j[i][key]);
214 + }
215 + }
216 + values.linux.memory = mem;
217 + }
218 + }
219 + catch (e)
220 + { }
221 + child = null;
222 + }
223 +
224 + var usbdevices = require('lib-finder').findBinary('usb-devices');
225 + if (usbdevices != null)
226 + {
227 + var child = require('child_process').execFile('/bin/sh', ['sh']);
228 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
229 + child.stderr.str = ''; child.stderr.on('data', dataHandler);
230 + child.stdin.write(usbdevices + " | tr '\\n' '`' | ");
231 + child.stdin.write(" awk '");
232 + child.stdin.write('{');
233 + child.stdin.write(' comma="";');
234 + child.stdin.write(' printf("[");');
235 + child.stdin.write(' len=split($0, group, "``");');
236 + child.stdin.write(' for(i=1;i<=len;++i)');
237 + child.stdin.write(' {');
238 + child.stdin.write(' comma2="";');
239 + child.stdin.write(' xlen=split(group[i], line, "`");');
240 + child.stdin.write(' scount=0;');
241 + child.stdin.write(' for(x=1;x<xlen;++x)');
242 + child.stdin.write(' {');
243 + child.stdin.write(' if(line[x] ~ "^S:")');
244 + child.stdin.write(' {');
245 + child.stdin.write(' ++scount;');
246 + child.stdin.write(' }');
247 + child.stdin.write(' }');
248 + child.stdin.write(' if(scount>0)');
249 + child.stdin.write(' {');
250 + child.stdin.write(' printf("%s{", comma); comma=",";');
251 + child.stdin.write(' for(x=1;x<xlen;++x)');
252 + child.stdin.write(' {');
253 + child.stdin.write(' if(line[x] ~ "^T:")');
254 + child.stdin.write(' {');
255 + child.stdin.write(' comma3="";');
256 + child.stdin.write(' printf("%s\\"hardware\\": {", comma2); comma2=",";');
257 + child.stdin.write(' sub(/^T:[ \\t]*/, "", line[x]);');
258 + child.stdin.write(' gsub(/= */, "=", line[x]);');
259 + child.stdin.write(' blen=split(line[x], tokens, " ");');
260 + child.stdin.write(' for(y=1;y<blen;++y)');
261 + child.stdin.write(' {');
262 + child.stdin.write(' match(tokens[y],/=/);');
263 + child.stdin.write(' h=substr(tokens[y],1,RSTART-1);');
264 + child.stdin.write(' v=substr(tokens[y],RSTART+1);');
265 + child.stdin.write(' sub(/#/, "", h);');
266 + child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", comma3, h, v); comma3=",";');
267 + child.stdin.write(' }');
268 + child.stdin.write(' printf("}");');
269 + child.stdin.write(' }');
270 + child.stdin.write(' if(line[x] ~ "^S:")');
271 + child.stdin.write(' {');
272 + child.stdin.write(' sub(/^S:[ \\t]*/, "", line[x]);');
273 + child.stdin.write(' match(line[x], /=/);');
274 + child.stdin.write(' h=substr(line[x],1,RSTART-1);');
275 + child.stdin.write(' v=substr(line[x],RSTART+1);');
276 + child.stdin.write(' printf("%s\\"%s\\": \\"%s\\"", comma2, h,v); comma2=",";');
277 + child.stdin.write(' }');
278 + child.stdin.write(' }');
279 + child.stdin.write(' printf("}");');
280 + child.stdin.write(' }');
281 + child.stdin.write(' }');
282 + child.stdin.write(' printf("]");');
283 + child.stdin.write("}'\nexit\n");
284 + child.waitExit();
285 +
286 + try
287 + {
288 + values.linux.usb = JSON.parse(child.stdout.str);
289 + }
290 + catch(x)
291 + { }
292 + child = null;
293 + }
294 +
295 + var pcidevices = require('lib-finder').findBinary('lspci');
296 + if (pcidevices != null)
297 + {
298 + var child = require('child_process').execFile('/bin/sh', ['sh']);
299 + child.stdout.str = ''; child.stdout.on('data', dataHandler);
300 + child.stderr.str = ''; child.stderr.on('data', dataHandler);
301 + child.stdin.write(pcidevices + " -m | tr '\\n' '`' | ");
302 + child.stdin.write(" awk '");
303 + child.stdin.write('{');
304 + child.stdin.write(' printf("[");');
305 + child.stdin.write(' comma="";');
306 + child.stdin.write(' alen=split($0, lines, "`");');
307 + child.stdin.write(' for(a=1;a<alen;++a)');
308 + child.stdin.write(' {');
309 + child.stdin.write(' match(lines[a], / /);');
310 + child.stdin.write(' blen=split(lines[a], meta, "\\"");');
311 + child.stdin.write(' bus=substr(lines[a], 1, RSTART);');
312 + child.stdin.write(' gsub(/ /, "", bus);');
313 + child.stdin.write(' printf("%s{\\"bus\\": \\"%s\\"", comma, bus); comma=",";');
314 + child.stdin.write(' printf(", \\"device\\": \\"%s\\"", meta[2]);');
315 + child.stdin.write(' printf(", \\"manufacturer\\": \\"%s\\"", meta[4]);');
316 + child.stdin.write(' printf(", \\"description\\": \\"%s\\"", meta[6]);');
317 + child.stdin.write(' if(meta[8] != "")');
318 + child.stdin.write(' {');
319 + child.stdin.write(' printf(", \\"subsystem\\": {");');
320 + child.stdin.write(' printf("\\"manufacturer\\": \\"%s\\"", meta[8]);');
321 + child.stdin.write(' printf(", \\"description\\": \\"%s\\"", meta[10]);');
322 + child.stdin.write(' printf("}");');
323 + child.stdin.write(' }');
324 + child.stdin.write(' printf("}");');
325 + child.stdin.write(' }');
326 + child.stdin.write(' printf("]");');
327 + child.stdin.write("}'\nexit\n");
328 + child.waitExit();
329 +
330 + try
331 + {
332 + values.linux.pci = JSON.parse(child.stdout.str);
333 + }
334 + catch (x)
335 + { }
336 + child = null;
337 + }
338 +
339 + return (values);
340 +}
341 +
342 +function windows_wmic_results(str)
343 +{
344 + var lines = str.trim().split('\r\n');
345 + var keys = lines[0].split(',');
346 + var i, key, keyval;
347 + var tokens;
348 + var result = [];
349 +
350 + console.log('Lines: ' + lines.length, 'Keys: ' + keys.length);
351 +
352 + for (i = 1; i < lines.length; ++i)
353 + {
354 + var obj = {};
355 + console.log('i: ' + i);
356 + tokens = lines[i].split(',');
357 + for (key = 0; key < keys.length; ++key)
358 + {
359 + var tmp = Buffer.from(tokens[key], 'binary').toString();
360 + console.log(tokens[key], tmp);
361 + tokens[key] = tmp == null ? '' : tmp;
362 + if (tokens[key].trim())
363 + {
364 + obj[keys[key].trim()] = tokens[key].trim();
365 + }
366 + }
367 + delete obj.Node;
368 + result.push(obj);
369 + }
370 + return (result);
371 +}
372 +
373 +function windows_volumes()
374 +{
375 + var promise = require('promise');
376 + var p1 = new promise(function (res, rej) { this._res = res; this._rej = rej; });
377 + var p2 = new promise(function (res, rej) { this._res = res; this._rej = rej; });
378 +
379 + p1._p2 = p2;
380 + p2._p1 = p1;
381 +
382 + var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-']);
383 + p1.child = child;
384 + child.promise = p1;
385 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
386 + child.stdin.write('Get-Volume | Select-Object -Property DriveLetter,FileSystemLabel,FileSystemType,Size,DriveType | ConvertTo-Csv -NoTypeInformation\nexit\n');
387 + child.on('exit', function (c)
388 + {
389 + var a, i, tokens, key;
390 + var ret = {};
391 +
392 + a = this.stdout.str.trim().split('\r\n');
393 + for (i = 1; i < a.length; ++i)
394 + {
395 + tokens = a[i].split(',');
396 + if (tokens[0] != '' && tokens[1] != undefined)
397 + {
398 + ret[tokens[0].split('"')[1]] =
399 + {
400 + name: tokens[1].split('"')[1],
401 + type: tokens[2].split('"')[1],
402 + size: tokens[3].split('"')[1],
403 + removable: tokens[4].split('"')[1] == 'Removable'
404 + };
405 + }
406 + }
407 + this.promise._res({ r: ret, t: tokens });
408 + });
409 +
410 + p1.then(function (j)
411 + {
412 + var ret = j.r;
413 + var tokens = j.t;
414 +
415 + var child = require('child_process').execFile(process.env['windir'] + '\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', ['powershell', '-noprofile', '-nologo', '-command', '-']);
416 + p2.child = child;
417 + child.promise = p2;
418 + child.tokens = tokens;
419 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
420 + child.stdin.write('Get-BitLockerVolume | Select-Object -Property MountPoint,VolumeStatus,ProtectionStatus | ConvertTo-Csv -NoTypeInformation\nexit\n');
421 + child.on('exit', function ()
422 + {
423 + var i;
424 + var a = this.stdout.str.trim().split('\r\n');
425 + for (i = 1; i < a.length; ++i)
426 + {
427 + tokens = a[i].split(',');
428 + key = tokens[0].split(':').shift().split('"').pop();
429 + if (ret[key] != null)
430 + {
431 + ret[key].volumeStatus = tokens[1].split('"')[1];
432 + ret[key].protectionStatus = tokens[2].split('"')[1];
433 + }
434 + }
435 + this.promise._res(ret);
436 + });
437 + });
438 + return (p2);
439 +}
440 +
441 +function windows_identifiers()
442 +{
443 + var ret = { windows: {} };
444 + var items, item, i;
445 +
446 + ret['identifiers'] = {};
447 +
448 + var values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_Bios", ['ReleaseDate', 'Manufacturer', 'SMBIOSBIOSVersion', 'SerialNumber']);
449 + if(values[0]){
450 + ret['identifiers']['bios_date'] = values[0]['ReleaseDate'];
451 + ret['identifiers']['bios_vendor'] = values[0]['Manufacturer'];
452 + ret['identifiers']['bios_version'] = values[0]['SMBIOSBIOSVersion'];
453 + ret['identifiers']['bios_serial'] = values[0]['SerialNumber'];
454 + }
455 + ret['identifiers']['bios_mode'] = 'Legacy';
456 +
457 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_BaseBoard", ['Product', 'SerialNumber', 'Manufacturer', 'Version']);
458 + if(values[0]){
459 + ret['identifiers']['board_name'] = values[0]['Product'];
460 + ret['identifiers']['board_serial'] = values[0]['SerialNumber'];
461 + ret['identifiers']['board_vendor'] = values[0]['Manufacturer'];
462 + ret['identifiers']['board_version'] = values[0]['Version'];
463 + }
464 +
465 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_ComputerSystemProduct", ['UUID', 'Name']);
466 + if(values[0]){
467 + ret['identifiers']['product_uuid'] = values[0]['UUID'];
468 + ret['identifiers']['product_name'] = values[0]['Name'];
469 + trimIdentifiers(ret.identifiers);
470 + }
471 +
472 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_PhysicalMemory");
473 + if(values[0]){
474 + trimResults(values);
475 + ret.windows.memory = values;
476 + }
477 +
478 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_OperatingSystem");
479 + if(values[0]){
480 + trimResults(values);
481 + ret.windows.osinfo = values[0];
482 + }
483 +
484 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_DiskPartition");
485 + if(values[0]){
486 + trimResults(values);
487 + ret.windows.partitions = values;
488 + for (var i in values) {
489 + if (values[i].Description=='GPT: System') {
490 + ret['identifiers']['bios_mode'] = 'UEFI';
491 + }
492 + }
493 + }
494 +
495 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_Processor", ['Caption', 'DeviceID', 'Manufacturer', 'MaxClockSpeed', 'Name', 'SocketDesignation']);
496 + if(values[0]){
497 + ret.windows.cpu = values;
498 + }
499 +
500 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_VideoController", ['Name', 'CurrentHorizontalResolution', 'CurrentVerticalResolution']);
501 + if(values[0]){
502 + ret.windows.gpu = values;
503 + }
504 +
505 + values = require('win-wmi').query('ROOT\\CIMV2', "SELECT * FROM Win32_DiskDrive", ['Caption', 'DeviceID', 'Model', 'Partitions', 'Size', 'Status']);
506 + if(values[0]){
507 + ret.windows.drives = values;
508 + }
509 +
510 + // Insert GPU names
511 + ret.identifiers.gpu_name = [];
512 + for (var gpuinfo in ret.windows.gpu)
513 + {
514 + if (ret.windows.gpu[gpuinfo].Name) { ret.identifiers.gpu_name.push(ret.windows.gpu[gpuinfo].Name); }
515 + }
516 +
517 + // Insert Storage Devices
518 + ret.identifiers.storage_devices = [];
519 + for (var dv in ret.windows.drives)
520 + {
521 + ret.identifiers.storage_devices.push({ Caption: ret.windows.drives[dv].Caption, Model: ret.windows.drives[dv].Model, Size: ret.windows.drives[dv].Size });
522 + }
523 +
524 + try { ret.identifiers.cpu_name = ret.windows.cpu[0].Name; } catch (x) { }
525 + return (ret);
526 +}
527 +function macos_identifiers()
528 +{
529 + var ret = { identifiers: {} };
530 + var child;
531 +
532 + child = require('child_process').execFile('/bin/sh', ['sh']);
533 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
534 + child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep board-id | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
535 + child.waitExit();
536 + ret.identifiers.board_name = child.stdout.str.trim();
537 +
538 + child = require('child_process').execFile('/bin/sh', ['sh']);
539 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
540 + child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformSerialNumber | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
541 + child.waitExit();
542 + ret.identifiers.board_serial = child.stdout.str.trim();
543 +
544 + child = require('child_process').execFile('/bin/sh', ['sh']);
545 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
546 + child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep manufacturer | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
547 + child.waitExit();
548 + ret.identifiers.board_vendor = child.stdout.str.trim();
549 +
550 + child = require('child_process').execFile('/bin/sh', ['sh']);
551 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
552 + child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep version | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
553 + child.waitExit();
554 + ret.identifiers.board_version = child.stdout.str.trim();
555 +
556 + child = require('child_process').execFile('/bin/sh', ['sh']);
557 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
558 + child.stdin.write('ioreg -d2 -c IOPlatformExpertDevice | grep IOPlatformUUID | awk -F= \'{ split($2, res, "\\""); print res[2]; }\'\nexit\n');
559 + child.waitExit();
560 + ret.identifiers.product_uuid = child.stdout.str.trim();
561 +
562 + child = require('child_process').execFile('/bin/sh', ['sh']);
563 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
564 + child.stdin.write('sysctl -n machdep.cpu.brand_string\nexit\n');
565 + child.waitExit();
566 + ret.identifiers.cpu_name = child.stdout.str.trim();
567 +
568 +
569 + trimIdentifiers(ret.identifiers);
570 +
571 +
572 + child = null;
573 + return (ret);
574 +}
575 +
576 +function win_chassisType()
577 +{
578 + var child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'SystemEnclosure', 'get', 'ChassisTypes']);
579 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
580 + child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
581 + child.waitExit();
582 +
583 + try
584 + {
585 + var tok = child.stdout.str.split('{')[1].split('}')[0];
586 + var val = tok.split(',')[0];
587 + return (parseInt(val));
588 + }
589 + catch (e)
590 + {
591 + return (2); // unknown
592 + }
593 +}
594 +
595 +function win_systemType()
596 +{
597 + var CSV = '/FORMAT:"' + require('util-language').wmicXslPath + 'csv"';
598 + var child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'ComputerSystem', 'get', 'PCSystemType', CSV]);
599 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
600 + child.stderr.str = ''; child.stderr.on('data', function (c) { this.str += c.toString(); });
601 + child.waitExit();
602 +
603 + return (parseInt(child.stdout.str.trim().split(',').pop()));
604 +}
605 +
606 +function win_formFactor(chassistype)
607 +{
608 + var ret = 'DESKTOP';
609 + switch (chassistype)
610 + {
611 + case 11: // Handheld
612 + case 30: // Tablet
613 + case 31: // Convertible
614 + case 32: // Detachable
615 + ret = 'TABLET';
616 + break;
617 + case 9: // Laptop
618 + case 10: // Notebook
619 + case 14: // Sub Notebook
620 + ret = 'LAPTOP';
621 + break;
622 + default:
623 + ret = win_systemType() == 2 ? 'MOBILE' : 'DESKTOP';
624 + break;
625 + }
626 +
627 + return (ret);
628 +}
629 +
630 +switch(process.platform)
631 +{
632 + case 'linux':
633 + module.exports = { _ObjectID: 'identifiers', get: linux_identifiers };
634 + break;
635 + case 'win32':
636 + module.exports = { _ObjectID: 'identifiers', get: windows_identifiers, chassisType: win_chassisType, formFactor: win_formFactor, systemType: win_systemType };
637 + break;
638 + case 'darwin':
639 + module.exports = { _ObjectID: 'identifiers', get: macos_identifiers };
640 + break;
641 + default:
642 + module.exports = { get: function () { throw ('Unsupported Platform'); } };
643 + break;
644 +}
645 +module.exports.isDocker = function isDocker()
646 +{
647 + if (process.platform != 'linux') { return (false); }
648 +
649 + var child = require('child_process').execFile('/bin/sh', ['sh']);
650 + child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
651 + child.stdin.write("cat /proc/self/cgroup | tr '\n' '`' | awk -F'`' '{ split($1, res, " + '"/"); if(res[2]=="docker"){print "1";} }\'\nexit\n');
652 + child.waitExit();
653 + return (child.stdout.str != '');
654 +};
655 +module.exports.isBatteryPowered = function isBatteryOperated()
656 +{
657 + var ret = false;
658 + switch(process.platform)
659 + {
660 + default:
661 + break;
662 + case 'linux':
663 + var devices = require('fs').readdirSync('/sys/class/power_supply');
664 + for (var i in devices)
665 + {
666 + if (require('fs').readFileSync('/sys/class/power_supply/' + devices[i] + '/type').toString().trim() == 'Battery')
667 + {
668 + ret = true;
669 + break;
670 + }
671 + }
672 + break;
673 + case 'win32':
674 + var GM = require('_GenericMarshal');
675 + var stats = GM.CreateVariable(12);
676 + var kernel32 = GM.CreateNativeProxy('Kernel32.dll');
677 + kernel32.CreateMethod('GetSystemPowerStatus');
678 + if (kernel32.GetSystemPowerStatus(stats).Val != 0)
679 + {
680 + if(stats.toBuffer()[1] != 128 && stats.toBuffer()[1] != 255)
681 + {
682 + ret = true;
683 + }
684 + else
685 + {
686 + // No Battery detected, so lets check if there is supposed to be one
687 + var formFactor = win_formFactor(win_chassisType());
688 + return (formFactor == 'LAPTOP' || formFactor == 'TABLET' || formFactor == 'MOBILE');
689 + }
690 + }
691 + break;
692 + case 'darwin':
693 + var child = require('child_process').execFile('/bin/sh', ['sh']);
694 + child.stdout.str = ''; child.stdout.on('data', function(c){ this.str += c.toString(); });
695 + child.stderr.str = ''; child.stderr.on('data', function(c){ this.str += c.toString(); });
696 + child.stdin.write("pmset -g batt | tr '\\n' '`' | awk -F'`' '{ if(NF>2) { print \"true\"; }}'\nexit\n");
697 + child.waitExit();
698 + if(child.stdout.str.trim() != '') { ret = true; }
699 + break;
700 + }
701 + return (ret);
702 +};
703 +module.exports.isVM = function isVM()
704 +{
705 + var ret = false;
706 + var id = this.get();
707 + if (id.linux && id.linux.sys_vendor)
708 + {
709 + switch (id.linux.sys_vendor)
710 + {
711 + case 'VMware, Inc.':
712 + case 'QEMU':
713 + case 'Xen':
714 + ret = true;
715 + break;
716 + default:
717 + break;
718 + }
719 + }
720 + if (id.identifiers.bios_vendor)
721 + {
722 + switch(id.identifiers.bios_vendor)
723 + {
724 + case 'VMware, Inc.':
725 + case 'Xen':
726 + case 'SeaBIOS':
727 + ret = true;
728 + break;
729 + default:
730 + break;
731 + }
732 + }
733 + if (id.identifiers.board_vendor && id.identifiers.board_vendor == 'VMware, Inc.') { ret = true; }
734 + if (id.identifiers.board_name)
735 + {
736 + switch (id.identifiers.board_name)
737 + {
738 + case 'VirtualBox':
739 + case 'Virtual Machine':
740 + ret = true;
741 + break;
742 + default:
743 + break;
744 + }
745 + }
746 +
747 + if (process.platform == 'win32' && !ret)
748 + {
749 + for(var i in id.identifiers.gpu_name)
750 + {
751 + if(id.identifiers.gpu_name[i].startsWith('VMware '))
752 + {
753 + ret = true;
754 + break;
755 + }
756 + }
757 + }
758 +
759 +
760 + if (!ret) { ret = this.isDocker(); }
761 + return (ret);
762 +};
763 +
764 +if (process.platform == 'win32')
765 +{
766 + module.exports.volumes_promise = windows_volumes;
767 +}
768 +
769 +// bios_date = BIOS->ReleaseDate
770 +// bios_vendor = BIOS->Manufacturer
771 +// bios_version = BIOS->SMBIOSBIOSVersion
772 +// board_name = BASEBOARD->Product = ioreg/board-id
773 +// board_serial = BASEBOARD->SerialNumber = ioreg/serial-number | ioreg/IOPlatformSerialNumber
774 +// board_vendor = BASEBOARD->Manufacturer = ioreg/manufacturer
775 +// board_version = BASEBOARD->Version
\ No newline at end of file