Initial commit of my folder
This commit is contained in:
412
backend/node_modules/systeminformation/lib/users.js
generated
vendored
Normal file
412
backend/node_modules/systeminformation/lib/users.js
generated
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
'use strict';
|
||||
// @ts-check
|
||||
// ==================================================================================
|
||||
// users.js
|
||||
// ----------------------------------------------------------------------------------
|
||||
// Description: System Information - library
|
||||
// for Node.js
|
||||
// Copyright: (c) 2014 - 2026
|
||||
// Author: Sebastian Hildebrandt
|
||||
// ----------------------------------------------------------------------------------
|
||||
// License: MIT
|
||||
// ==================================================================================
|
||||
// 11. Users/Sessions
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
const exec = require('child_process').exec;
|
||||
const util = require('./util');
|
||||
|
||||
const _platform = process.platform;
|
||||
|
||||
const _linux = _platform === 'linux' || _platform === 'android';
|
||||
const _darwin = _platform === 'darwin';
|
||||
const _windows = _platform === 'win32';
|
||||
const _freebsd = _platform === 'freebsd';
|
||||
const _openbsd = _platform === 'openbsd';
|
||||
const _netbsd = _platform === 'netbsd';
|
||||
const _sunos = _platform === 'sunos';
|
||||
|
||||
function parseDate(dtMon, dtDay) {
|
||||
let dt = new Date().toISOString().slice(0, 10);
|
||||
try {
|
||||
dt = '' + new Date().getFullYear() + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(dtMon.toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + dtDay).slice(-2);
|
||||
if (new Date(dt) > new Date()) {
|
||||
dt = '' + (new Date().getFullYear() - 1) + '-' + ('0' + ('JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC'.indexOf(dtMon.toUpperCase()) / 3 + 1)).slice(-2) + '-' + ('0' + dtDay).slice(-2);
|
||||
}
|
||||
} catch {
|
||||
util.noop();
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
function parseUsersLinux(lines, phase) {
|
||||
const result = [];
|
||||
let result_who = [];
|
||||
const result_w = {};
|
||||
let w_first = true;
|
||||
let w_header = [];
|
||||
const w_pos = [];
|
||||
let who_line = {};
|
||||
|
||||
let is_whopart = true;
|
||||
let is_whoerror = false;
|
||||
lines.forEach((line) => {
|
||||
if (line === '---') {
|
||||
is_whopart = false;
|
||||
} else {
|
||||
const l = line.replace(/ +/g, ' ').split(' ');
|
||||
// who part
|
||||
if (is_whopart) {
|
||||
if (line.toLowerCase().indexOf('unexpected') >= 0 || line.toLowerCase().indexOf('unrecognized') >= 0) {
|
||||
is_whoerror = true;
|
||||
result_who = [];
|
||||
}
|
||||
if (!is_whoerror) {
|
||||
const timePos = l && l.length > 4 && l[4].indexOf(':') > 0 ? 4 : 3;
|
||||
result_who.push({
|
||||
user: l[0],
|
||||
tty: l[1],
|
||||
date: timePos === 4 ? parseDate(l[2], l[3]) : l[2],
|
||||
time: l[timePos],
|
||||
ip: l && l.length > timePos + 1 ? l[timePos + 1].replace(/\(/g, '').replace(/\)/g, '') : '',
|
||||
command: ''
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// w part
|
||||
if (w_first) {
|
||||
// header
|
||||
if (line[0] !== ' ') {
|
||||
w_header = l;
|
||||
w_header.forEach((item) => {
|
||||
w_pos.push(line.indexOf(item));
|
||||
});
|
||||
w_first = false;
|
||||
}
|
||||
} else {
|
||||
// split by w_pos
|
||||
result_w.user = line.substring(w_pos[0], w_pos[1] - 1).trim();
|
||||
result_w.tty = line.substring(w_pos[1], w_pos[2] - 1).trim();
|
||||
result_w.ip = line
|
||||
.substring(w_pos[2], w_pos[3] - 1)
|
||||
.replace(/\(/g, '')
|
||||
.replace(/\)/g, '')
|
||||
.trim();
|
||||
result_w.command = line.substring(w_pos[7], 1000).trim();
|
||||
// find corresponding 'who' line
|
||||
if (result_who.length || phase === 1) {
|
||||
who_line = result_who.filter((obj) => {
|
||||
return obj.user.substring(0, 8).trim() === result_w.user && obj.tty === result_w.tty;
|
||||
});
|
||||
} else {
|
||||
who_line = [{ user: result_w.user, tty: result_w.tty, date: '', time: '', ip: '' }];
|
||||
}
|
||||
if (who_line.length === 1 && who_line[0].user !== '') {
|
||||
result.push({
|
||||
user: who_line[0].user,
|
||||
tty: who_line[0].tty,
|
||||
date: who_line[0].date,
|
||||
time: who_line[0].time,
|
||||
ip: who_line[0].ip,
|
||||
command: result_w.command
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result.length === 0 && phase === 2) {
|
||||
return result_who;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
function parseUsersDarwin(lines) {
|
||||
const result = [];
|
||||
const result_who = [];
|
||||
const result_w = {};
|
||||
let who_line = {};
|
||||
|
||||
let is_whopart = true;
|
||||
lines.forEach((line) => {
|
||||
if (line === '---') {
|
||||
is_whopart = false;
|
||||
} else {
|
||||
const l = line.replace(/ +/g, ' ').split(' ');
|
||||
|
||||
// who part
|
||||
if (is_whopart) {
|
||||
result_who.push({
|
||||
user: l[0],
|
||||
tty: l[1],
|
||||
date: parseDate(l[2], l[3]),
|
||||
time: l[4]
|
||||
});
|
||||
} else {
|
||||
// w part
|
||||
// split by w_pos
|
||||
result_w.user = l[0];
|
||||
result_w.tty = l[1];
|
||||
result_w.ip = l[2] !== '-' ? l[2] : '';
|
||||
result_w.command = l.slice(5, 1000).join(' ');
|
||||
// find corresponding 'who' line
|
||||
who_line = result_who.filter((obj) => obj.user.substring(0, 10) === result_w.user.substring(0, 10) && (obj.tty.substring(3, 1000) === result_w.tty || obj.tty === result_w.tty));
|
||||
if (who_line.length === 1) {
|
||||
result.push({
|
||||
user: who_line[0].user,
|
||||
tty: who_line[0].tty,
|
||||
date: who_line[0].date,
|
||||
time: who_line[0].time,
|
||||
ip: result_w.ip,
|
||||
command: result_w.command
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function users(callback) {
|
||||
return new Promise((resolve) => {
|
||||
process.nextTick(() => {
|
||||
let result = [];
|
||||
|
||||
// linux
|
||||
if (_linux) {
|
||||
exec('export LC_ALL=C; who --ips; echo "---"; w; unset LC_ALL | tail -n +2', (error, stdout) => {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
let lines = stdout.toString().split('\n');
|
||||
result = parseUsersLinux(lines, 1);
|
||||
if (result.length === 0) {
|
||||
exec('who; echo "---"; w | tail -n +2', (error, stdout) => {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
lines = stdout.toString().split('\n');
|
||||
result = parseUsersLinux(lines, 2);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_freebsd || _openbsd || _netbsd) {
|
||||
exec('who; echo "---"; w -ih', (error, stdout) => {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
const lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_sunos) {
|
||||
exec('who; echo "---"; w -h', (error, stdout) => {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
const lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
|
||||
if (_darwin) {
|
||||
exec('export LC_ALL=C; who; echo "---"; w -ih; unset LC_ALL', (error, stdout) => {
|
||||
if (!error) {
|
||||
// lines / split
|
||||
const lines = stdout.toString().split('\n');
|
||||
result = parseUsersDarwin(lines);
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
}
|
||||
if (_windows) {
|
||||
try {
|
||||
let cmd = 'Get-CimInstance Win32_LogonSession | select LogonId,@{n="StartTime";e={$_.StartTime.ToString("yyyy-MM-dd HH:mm:ss")}} | fl' + "; echo '#-#-#-#';";
|
||||
cmd += 'Get-CimInstance Win32_LoggedOnUser | select antecedent,dependent | fl ' + "; echo '#-#-#-#';";
|
||||
cmd +=
|
||||
"$process = (Get-CimInstance Win32_Process -Filter \"name = 'explorer.exe'\"); Invoke-CimMethod -InputObject $process[0] -MethodName GetOwner | select user, domain | fl; get-process -name explorer | select-object sessionid | fl; echo '#-#-#-#';";
|
||||
cmd += 'query user';
|
||||
util.powerShell(cmd).then((data) => {
|
||||
if (data) {
|
||||
data = data.split('#-#-#-#');
|
||||
const sessions = parseWinSessions((data[0] || '').split(/\n\s*\n/));
|
||||
const loggedons = parseWinLoggedOn((data[1] || '').split(/\n\s*\n/));
|
||||
const queryUser = parseWinUsersQuery((data[3] || '').split('\r\n'));
|
||||
const users = parseWinUsers((data[2] || '').split(/\n\s*\n/), queryUser);
|
||||
for (let id in loggedons) {
|
||||
if ({}.hasOwnProperty.call(loggedons, id)) {
|
||||
loggedons[id].dateTime = {}.hasOwnProperty.call(sessions, id) ? sessions[id] : '';
|
||||
}
|
||||
}
|
||||
users.forEach((user) => {
|
||||
let dateTime = '';
|
||||
for (let id in loggedons) {
|
||||
if ({}.hasOwnProperty.call(loggedons, id)) {
|
||||
if (loggedons[id].user === user.user && (!dateTime || dateTime < loggedons[id].dateTime)) {
|
||||
dateTime = loggedons[id].dateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.push({
|
||||
user: user.user,
|
||||
tty: user.tty,
|
||||
date: `${dateTime.substring(0, 10)}`,
|
||||
time: `${dateTime.substring(11, 19)}`,
|
||||
ip: '',
|
||||
command: ''
|
||||
});
|
||||
});
|
||||
}
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} catch {
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
resolve(result);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function parseWinSessions(sessionParts) {
|
||||
const sessions = {};
|
||||
sessionParts.forEach((session) => {
|
||||
const lines = session.split('\r\n');
|
||||
const id = util.getValue(lines, 'LogonId');
|
||||
const starttime = util.getValue(lines, 'starttime');
|
||||
if (id) {
|
||||
sessions[id] = starttime;
|
||||
}
|
||||
});
|
||||
return sessions;
|
||||
}
|
||||
|
||||
function fuzzyMatch(name1, name2) {
|
||||
name1 = name1.toLowerCase();
|
||||
name2 = name2.toLowerCase();
|
||||
let eq = 0;
|
||||
let len = name1.length;
|
||||
if (name2.length > len) {
|
||||
len = name2.length;
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const c1 = name1[i] || '';
|
||||
const c2 = name2[i] || '';
|
||||
if (c1 === c2) {
|
||||
eq++;
|
||||
}
|
||||
}
|
||||
return len > 10 ? eq / len > 0.9 : len > 0 ? eq / len > 0.8 : false;
|
||||
}
|
||||
|
||||
function parseWinUsers(userParts, userQuery) {
|
||||
const users = [];
|
||||
userParts.forEach((user) => {
|
||||
const lines = user.split('\r\n');
|
||||
|
||||
const domain = util.getValue(lines, 'domain', ':', true);
|
||||
const username = util.getValue(lines, 'user', ':', true);
|
||||
const sessionid = util.getValue(lines, 'sessionid', ':', true);
|
||||
|
||||
if (username) {
|
||||
const quser = userQuery.filter((item) => fuzzyMatch(item.user, username));
|
||||
users.push({
|
||||
domain,
|
||||
user: username,
|
||||
tty: quser && quser[0] && quser[0].tty ? quser[0].tty : sessionid
|
||||
});
|
||||
}
|
||||
});
|
||||
return users;
|
||||
}
|
||||
|
||||
function parseWinLoggedOn(loggedonParts) {
|
||||
const loggedons = {};
|
||||
loggedonParts.forEach((loggedon) => {
|
||||
const lines = loggedon.split('\r\n');
|
||||
|
||||
const antecendent = util.getValue(lines, 'antecedent', ':', true);
|
||||
let parts = antecendent.split('=');
|
||||
const name = parts.length > 2 ? parts[1].split(',')[0].replace(/"/g, '').trim() : '';
|
||||
const domain = parts.length > 2 ? parts[2].replace(/"/g, '').replace(/\)/g, '').trim() : '';
|
||||
const dependent = util.getValue(lines, 'dependent', ':', true);
|
||||
parts = dependent.split('=');
|
||||
const id = parts.length > 1 ? parts[1].replace(/"/g, '').replace(/\)/g, '').trim() : '';
|
||||
if (id) {
|
||||
loggedons[id] = {
|
||||
domain,
|
||||
user: name
|
||||
};
|
||||
}
|
||||
});
|
||||
return loggedons;
|
||||
}
|
||||
|
||||
function parseWinUsersQuery(lines) {
|
||||
lines = lines.filter((item) => item);
|
||||
let result = [];
|
||||
const header = lines[0];
|
||||
const headerDelimiter = [];
|
||||
if (header) {
|
||||
const start = header[0] === ' ' ? 1 : 0;
|
||||
headerDelimiter.push(start - 1);
|
||||
let nextSpace = 0;
|
||||
for (let i = start + 1; i < header.length; i++) {
|
||||
if (header[i] === ' ' && (header[i - 1] === ' ' || header[i - 1] === '.')) {
|
||||
nextSpace = i;
|
||||
} else {
|
||||
if (nextSpace) {
|
||||
headerDelimiter.push(nextSpace);
|
||||
nextSpace = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
if (lines[i].trim()) {
|
||||
const user = lines[i].substring(headerDelimiter[0] + 1, headerDelimiter[1]).trim() || '';
|
||||
const tty = lines[i].substring(headerDelimiter[1] + 1, headerDelimiter[2] - 2).trim() || '';
|
||||
result.push({
|
||||
user: user,
|
||||
tty: tty
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.users = users;
|
||||
Reference in New Issue
Block a user