mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 11:01:52 +00:00
Server bug fixing and new MeshAgent
This commit is contained in:
parent
562310bed1
commit
b274b782fa
21 changed files with 719 additions and 92 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -15,41 +15,41 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
|
||||
function borderController()
|
||||
{
|
||||
this.container = null;
|
||||
this.Start = function Start(user)
|
||||
{
|
||||
if (this.container == null) {
|
||||
if (process.platform == 'win32') {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId });
|
||||
}
|
||||
else {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.uid });
|
||||
}
|
||||
this.container.addModule('monitor-info', getJSModule('monitor-info'));
|
||||
this.container.addModule('monitor-border', getJSModule('monitor-border'));
|
||||
this.container.addModule('promise', getJSModule('promise'));
|
||||
this.container.ExecuteString("var border = require('monitor-border'); border.Start();");
|
||||
}
|
||||
}
|
||||
this.Stop = function Stop()
|
||||
{
|
||||
if (this.container != null)
|
||||
{
|
||||
this._container = this.container;
|
||||
this._container.parent = this;
|
||||
this.container = null;
|
||||
|
||||
this._container.once('exit', function () { this.parent._container = null; });
|
||||
this._container.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createMeshCore(agent) {
|
||||
var obj = {};
|
||||
|
||||
function borderController() {
|
||||
this.container = null;
|
||||
this.Start = function Start(user) {
|
||||
if (this.container == null) {
|
||||
if (process.platform == 'win32') {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.SessionId });
|
||||
}
|
||||
else {
|
||||
this.container = require('ScriptContainer').Create({ processIsolation: 1, sessionId: user.uid });
|
||||
}
|
||||
this.container.parent = this;
|
||||
this.container.addModule('monitor-info', getJSModule('monitor-info'));
|
||||
this.container.addModule('monitor-border', getJSModule('monitor-border'));
|
||||
this.container.addModule('promise', getJSModule('promise'));
|
||||
this.container.once('exit', function (code) { sendConsoleText('Border Process Exited with code: ' + code); this.parent.container = this.parent._container = null; });
|
||||
this.container.ExecuteString("var border = require('monitor-border'); border.Start();");
|
||||
}
|
||||
}
|
||||
this.Stop = function Stop() {
|
||||
if (this.container != null) {
|
||||
this._container = this.container;
|
||||
this._container.parent = this;
|
||||
this.container = null;
|
||||
|
||||
this._container.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
require('events').EventEmitter.call(obj, true).createEvent('loggedInUsers_Updated');
|
||||
obj.on('loggedInUsers_Updated', function ()
|
||||
{
|
||||
|
@ -1457,6 +1457,8 @@ function createMeshCore(agent) {
|
|||
});
|
||||
|
||||
require('user-sessions').emit('changed');
|
||||
require('user-sessions').on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); });
|
||||
require('user-sessions').on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); });
|
||||
//console.log('Stopping.');
|
||||
//process.exit();
|
||||
}
|
||||
|
|
|
@ -109,17 +109,22 @@ function serviceManager()
|
|||
}
|
||||
return admin;
|
||||
};
|
||||
this.getProgramFolder = function getProgramFolder() {
|
||||
if (require('os').arch() == 'x64') { // 64 bit Windows
|
||||
if (this.GM.PointerSize == 4) { return process.env['ProgramFiles(x86)']; } // 32 Bit App
|
||||
return process.env['ProgramFiles']; // 64 bit App
|
||||
}
|
||||
return process.env['ProgramFiles']; // 32 bit Windows
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder()
|
||||
this.getProgramFolder = function getProgramFolder()
|
||||
{
|
||||
return this.getProgramFolder() + '\\mesh';
|
||||
if (require('os').arch() == 'x64')
|
||||
{
|
||||
// 64 bit Windows
|
||||
if (this.GM.PointerSize == 4)
|
||||
{
|
||||
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||
}
|
||||
return process.env['ProgramFiles']; // 64 bit App
|
||||
}
|
||||
|
||||
// 32 bit Windows
|
||||
return process.env['ProgramFiles'];
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||
|
||||
this.enumerateService = function () {
|
||||
var machineName = this.GM.CreatePointer();
|
||||
|
|
|
@ -14,10 +14,28 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
var NOTIFY_FOR_THIS_SESSION = 0;
|
||||
var NOTIFY_FOR_ALL_SESSIONS = 1;
|
||||
var WM_WTSSESSION_CHANGE = 0x02B1;
|
||||
var WTS_CONSOLE_CONNECT = (0x1);
|
||||
var WTS_CONSOLE_DISCONNECT = (0x2);
|
||||
var WTS_REMOTE_CONNECT = (0x3);
|
||||
var WTS_REMOTE_DISCONNECT = (0x4);
|
||||
var WTS_SESSION_LOGON = (0x5);
|
||||
var WTS_SESSION_LOGOFF = (0x6);
|
||||
var WTS_SESSION_LOCK = (0x7);
|
||||
var WTS_SESSION_UNLOCK = (0x8);
|
||||
var WTS_SESSION_REMOTE_CONTROL = (0x9);
|
||||
var WTS_SESSION_CREATE = (0xA);
|
||||
var WTS_SESSION_TERMINATE = (0xB);
|
||||
|
||||
function UserSessions()
|
||||
{
|
||||
this._ObjectID = 'user-sessions';
|
||||
require('events').EventEmitter.call(this, true).createEvent('changed');
|
||||
require('events').EventEmitter.call(this, true)
|
||||
.createEvent('changed')
|
||||
.createEvent('locked')
|
||||
.createEvent('unlocked');
|
||||
|
||||
this.enumerateUsers = function enumerateUsers()
|
||||
{
|
||||
|
@ -37,12 +55,15 @@ function UserSessions()
|
|||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._serviceHooked = false;
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSFreeMemory');
|
||||
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
||||
this.InfoClass =
|
||||
|
@ -124,9 +145,52 @@ function UserSessions()
|
|||
if (cb) { cb(retVal); }
|
||||
return (retVal);
|
||||
};
|
||||
|
||||
this._immediate = setImmediate(function (self)
|
||||
{
|
||||
if (self._serviceHooked) { return; } // If we were hooked by a service, we won't need to do anything further
|
||||
|
||||
// We need to spin up a message pump, and fetch a window handle
|
||||
var message_pump = require('win-message-pump');
|
||||
self._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE });
|
||||
self._messagepump.on('exit', function (code) { self._wts.WTSUnRegisterSessionNotification(self.hwnd); });
|
||||
self._messagepump.on('hwnd', function (h)
|
||||
{
|
||||
self.hwnd = h;
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
self._wts.WTSRegisterSessionNotification(self.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
});
|
||||
self._messagepump.on('message', function (msg)
|
||||
{
|
||||
if (msg.message == WM_WTSSESSION_CHANGE)
|
||||
{
|
||||
switch(msg.wparam)
|
||||
{
|
||||
case WTS_SESSION_LOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('locked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
case WTS_SESSION_UNLOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('unlocked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._linuxWatcher = require('fs').watch('/var/run/utmp');
|
||||
this._linuxWatcher.user_session = this;
|
||||
this._linuxWatcher.on('change', function (a, b)
|
||||
{
|
||||
this.user_session.emit('changed');
|
||||
});
|
||||
this.Self = function Self()
|
||||
{
|
||||
var promise = require('promise');
|
||||
|
@ -277,13 +341,26 @@ function UserSessions()
|
|||
function showActiveOnly(source)
|
||||
{
|
||||
var retVal = [];
|
||||
var unique = {};
|
||||
var usernames = [];
|
||||
var tmp;
|
||||
|
||||
for (var i in source)
|
||||
{
|
||||
if (source[i].State == 'Active')
|
||||
{
|
||||
retVal.push(source[i]);
|
||||
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
||||
if (!unique[tmp]) { unique[tmp] = tmp;}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in unique)
|
||||
{
|
||||
usernames.push(i);
|
||||
}
|
||||
|
||||
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
||||
return (retVal);
|
||||
}
|
||||
function getTokens(str)
|
||||
|
|
401
agents/modules_meshcore/service-manager.js
Normal file
401
agents/modules_meshcore/service-manager.js
Normal file
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
Copyright 2018 Intel Corporation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
function parseServiceStatus(token)
|
||||
{
|
||||
var j = {};
|
||||
var serviceType = token.Deref(0, 4).IntVal;
|
||||
j.isFileSystemDriver = ((serviceType & 0x00000002) == 0x00000002);
|
||||
j.isKernelDriver = ((serviceType & 0x00000001) == 0x00000001);
|
||||
j.isSharedProcess = ((serviceType & 0x00000020) == 0x00000020);
|
||||
j.isOwnProcess = ((serviceType & 0x00000010) == 0x00000010);
|
||||
j.isInteractive = ((serviceType & 0x00000100) == 0x00000100);
|
||||
switch (token.Deref((1 * 4), 4).toBuffer().readUInt32LE())
|
||||
{
|
||||
case 0x00000005:
|
||||
j.state = 'CONTINUE_PENDING';
|
||||
break;
|
||||
case 0x00000006:
|
||||
j.state = 'PAUSE_PENDING';
|
||||
break;
|
||||
case 0x00000007:
|
||||
j.state = 'PAUSED';
|
||||
break;
|
||||
case 0x00000004:
|
||||
j.state = 'RUNNING';
|
||||
break;
|
||||
case 0x00000002:
|
||||
j.state = 'START_PENDING';
|
||||
break;
|
||||
case 0x00000003:
|
||||
j.state = 'STOP_PENDING';
|
||||
break;
|
||||
case 0x00000001:
|
||||
j.state = 'STOPPED';
|
||||
break;
|
||||
}
|
||||
var controlsAccepted = token.Deref((2 * 4), 4).toBuffer().readUInt32LE();
|
||||
j.controlsAccepted = [];
|
||||
if ((controlsAccepted & 0x00000010) == 0x00000010)
|
||||
{
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDADD');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDREMOVE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDENABLE');
|
||||
j.controlsAccepted.push('SERVICE_CONTROL_NETBINDDISABLE');
|
||||
}
|
||||
if ((controlsAccepted & 0x00000008) == 0x00000008) { j.controlsAccepted.push('SERVICE_CONTROL_PARAMCHANGE'); }
|
||||
if ((controlsAccepted & 0x00000002) == 0x00000002) { j.controlsAccepted.push('SERVICE_CONTROL_PAUSE'); j.controlsAccepted.push('SERVICE_CONTROL_CONTINUE'); }
|
||||
if ((controlsAccepted & 0x00000100) == 0x00000100) { j.controlsAccepted.push('SERVICE_CONTROL_PRESHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000004) == 0x00000004) { j.controlsAccepted.push('SERVICE_CONTROL_SHUTDOWN'); }
|
||||
if ((controlsAccepted & 0x00000001) == 0x00000001) { j.controlsAccepted.push('SERVICE_CONTROL_STOP'); }
|
||||
if ((controlsAccepted & 0x00000020) == 0x00000020) { j.controlsAccepted.push('SERVICE_CONTROL_HARDWAREPROFILECHANGE'); }
|
||||
if ((controlsAccepted & 0x00000040) == 0x00000040) { j.controlsAccepted.push('SERVICE_CONTROL_POWEREVENT'); }
|
||||
if ((controlsAccepted & 0x00000080) == 0x00000080) { j.controlsAccepted.push('SERVICE_CONTROL_SESSIONCHANGE'); }
|
||||
j.pid = token.Deref((7 * 4), 4).toBuffer().readUInt32LE();
|
||||
return (j);
|
||||
}
|
||||
|
||||
function serviceManager()
|
||||
{
|
||||
this._ObjectID = 'service-manager';
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this.GM = require('_GenericMarshal');
|
||||
this.proxy = this.GM.CreateNativeProxy('Advapi32.dll');
|
||||
this.proxy.CreateMethod('OpenSCManagerA');
|
||||
this.proxy.CreateMethod('EnumServicesStatusExA');
|
||||
this.proxy.CreateMethod('OpenServiceA');
|
||||
this.proxy.CreateMethod('QueryServiceStatusEx');
|
||||
this.proxy.CreateMethod('ControlService');
|
||||
this.proxy.CreateMethod('StartServiceA');
|
||||
this.proxy.CreateMethod('CloseServiceHandle');
|
||||
this.proxy.CreateMethod('CreateServiceA');
|
||||
this.proxy.CreateMethod('ChangeServiceConfig2A');
|
||||
this.proxy.CreateMethod('DeleteService');
|
||||
this.proxy.CreateMethod('AllocateAndInitializeSid');
|
||||
this.proxy.CreateMethod('CheckTokenMembership');
|
||||
this.proxy.CreateMethod('FreeSid');
|
||||
|
||||
this.proxy2 = this.GM.CreateNativeProxy('Kernel32.dll');
|
||||
this.proxy2.CreateMethod('GetLastError');
|
||||
|
||||
this.isAdmin = function isAdmin() {
|
||||
var NTAuthority = this.GM.CreateVariable(6);
|
||||
NTAuthority.toBuffer().writeInt8(5, 5);
|
||||
var AdministratorsGroup = this.GM.CreatePointer();
|
||||
var admin = false;
|
||||
|
||||
if (this.proxy.AllocateAndInitializeSid(NTAuthority, 2, 32, 544, 0, 0, 0, 0, 0, 0, AdministratorsGroup).Val != 0)
|
||||
{
|
||||
var member = this.GM.CreateInteger();
|
||||
if (this.proxy.CheckTokenMembership(0, AdministratorsGroup.Deref(), member).Val != 0)
|
||||
{
|
||||
if (member.toBuffer().readUInt32LE() != 0) { admin = true; }
|
||||
}
|
||||
this.proxy.FreeSid(AdministratorsGroup.Deref());
|
||||
}
|
||||
return admin;
|
||||
};
|
||||
this.getProgramFolder = function getProgramFolder()
|
||||
{
|
||||
if (require('os').arch() == 'x64')
|
||||
{
|
||||
// 64 bit Windows
|
||||
if (this.GM.PointerSize == 4)
|
||||
{
|
||||
return process.env['ProgramFiles(x86)']; // 32 Bit App
|
||||
}
|
||||
return process.env['ProgramFiles']; // 64 bit App
|
||||
}
|
||||
|
||||
// 32 bit Windows
|
||||
return process.env['ProgramFiles'];
|
||||
};
|
||||
this.getServiceFolder = function getServiceFolder() { return this.getProgramFolder() + '\\mesh'; };
|
||||
|
||||
this.enumerateService = function () {
|
||||
var machineName = this.GM.CreatePointer();
|
||||
var dbName = this.GM.CreatePointer();
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004);
|
||||
|
||||
var bytesNeeded = this.GM.CreatePointer();
|
||||
var servicesReturned = this.GM.CreatePointer();
|
||||
var resumeHandle = this.GM.CreatePointer();
|
||||
//var services = this.proxy.CreateVariable(262144);
|
||||
var success = this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, 0x00, 0x00, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
if (bytesNeeded.IntVal <= 0) {
|
||||
throw ('error enumerating services');
|
||||
}
|
||||
var sz = bytesNeeded.IntVal;
|
||||
var services = this.GM.CreateVariable(sz);
|
||||
this.proxy.EnumServicesStatusExA(handle, 0, 0x00000030, 0x00000003, services, sz, bytesNeeded, servicesReturned, resumeHandle, 0x00);
|
||||
console.log("servicesReturned", servicesReturned.IntVal);
|
||||
|
||||
var ptrSize = dbName._size;
|
||||
var blockSize = 36 + (2 * ptrSize);
|
||||
blockSize += ((ptrSize - (blockSize % ptrSize)) % ptrSize);
|
||||
var retVal = [];
|
||||
for (var i = 0; i < servicesReturned.IntVal; ++i) {
|
||||
var token = services.Deref(i * blockSize, blockSize);
|
||||
var j = {};
|
||||
j.name = token.Deref(0, ptrSize).Deref().String;
|
||||
j.displayName = token.Deref(ptrSize, ptrSize).Deref().String;
|
||||
j.status = parseServiceStatus(token.Deref(2 * ptrSize, 36));
|
||||
retVal.push(j);
|
||||
}
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (retVal);
|
||||
}
|
||||
this.getService = function (name) {
|
||||
var serviceName = this.GM.CreateVariable(name);
|
||||
var ptr = this.GM.CreatePointer();
|
||||
var bytesNeeded = this.GM.CreateVariable(ptr._size);
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0001 | 0x0004 | 0x0020 | 0x0010);
|
||||
if (handle.Val == 0) { throw ('could not open ServiceManager'); }
|
||||
var h = this.proxy.OpenServiceA(handle, serviceName, 0x0004 | 0x0020 | 0x0010 | 0x00010000);
|
||||
if (h.Val != 0) {
|
||||
var success = this.proxy.QueryServiceStatusEx(h, 0, 0, 0, bytesNeeded);
|
||||
var status = this.GM.CreateVariable(bytesNeeded.toBuffer().readUInt32LE());
|
||||
success = this.proxy.QueryServiceStatusEx(h, 0, status, status._size, bytesNeeded);
|
||||
if (success != 0) {
|
||||
retVal = {};
|
||||
retVal.status = parseServiceStatus(status);
|
||||
retVal._scm = handle;
|
||||
retVal._service = h;
|
||||
retVal._GM = this.GM;
|
||||
retVal._proxy = this.proxy;
|
||||
require('events').inherits(retVal);
|
||||
retVal.on('~', function () { this._proxy.CloseServiceHandle(this); this._proxy.CloseServiceHandle(this._scm); });
|
||||
retVal.name = name;
|
||||
retVal.stop = function () {
|
||||
if (this.status.state == 'RUNNING') {
|
||||
var newstate = this._GM.CreateVariable(36);
|
||||
var success = this._proxy.ControlService(this._service, 0x00000001, newstate);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.stop() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.stop(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
retVal.start = function () {
|
||||
if (this.status.state == 'STOPPED') {
|
||||
var success = this._proxy.StartServiceA(this._service, 0, 0);
|
||||
if (success == 0) {
|
||||
throw (this.name + '.start() failed');
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw ('cannot call ' + this.name + '.start(), when current state is: ' + this.status.state);
|
||||
}
|
||||
}
|
||||
return (retVal);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('could not find service: ' + name);
|
||||
}
|
||||
}
|
||||
this.installService = function installService(options)
|
||||
{
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Installing as Service, requires admin'); }
|
||||
|
||||
// Before we start, we need to copy the binary to the right place
|
||||
var folder = this.getServiceFolder();
|
||||
if (!require('fs').existsSync(folder)) { require('fs').mkdirSync(folder); }
|
||||
require('fs').copyFileSync(options.servicePath, folder + '\\' + options.name + '.exe');
|
||||
options.servicePath = folder + '\\' + options.name + '.exe';
|
||||
|
||||
var servicePath = this.GM.CreateVariable('"' + options.servicePath + '"');
|
||||
var handle = this.proxy.OpenSCManagerA(0x00, 0x00, 0x0002);
|
||||
if (handle.Val == 0) { throw ('error opening SCManager'); }
|
||||
var serviceName = this.GM.CreateVariable(options.name);
|
||||
var displayName = this.GM.CreateVariable(options.name);
|
||||
var allAccess = 0x000F01FF;
|
||||
var serviceType;
|
||||
|
||||
|
||||
switch (options.startType) {
|
||||
case 'BOOT_START':
|
||||
serviceType = 0x00;
|
||||
break;
|
||||
case 'SYSTEM_START':
|
||||
serviceType = 0x01;
|
||||
break;
|
||||
case 'AUTO_START':
|
||||
serviceType = 0x02;
|
||||
break;
|
||||
case 'DEMAND_START':
|
||||
serviceType = 0x03;
|
||||
break;
|
||||
default:
|
||||
serviceType = 0x04; // Disabled
|
||||
break;
|
||||
}
|
||||
|
||||
var h = this.proxy.CreateServiceA(handle, serviceName, displayName, allAccess, 0x10 | 0x100, serviceType, 0, servicePath, 0, 0, 0, 0, 0);
|
||||
if (h.Val == 0) { this.proxy.CloseServiceHandle(handle); throw ('Error Creating Service: ' + this.proxy2.GetLastError().Val); }
|
||||
if (options.description) {
|
||||
console.log(options.description);
|
||||
|
||||
var dscPtr = this.GM.CreatePointer();
|
||||
dscPtr.Val = this.GM.CreateVariable(options.description);
|
||||
|
||||
if (this.proxy.ChangeServiceConfig2A(h, 1, dscPtr) == 0) {
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
throw ('Unable to set description');
|
||||
}
|
||||
}
|
||||
this.proxy.CloseServiceHandle(h);
|
||||
this.proxy.CloseServiceHandle(handle);
|
||||
return (this.getService(options.name));
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
require('fs').copyFileSync(options.servicePath, '/etc/init.d/' + options.name);
|
||||
console.log('copying ' + options.servicePath);
|
||||
var m = require('fs').statSync('/etc/init.d/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/etc/init.d/' + options.name, m);
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.on('exit', function onUpdateRC_d() { console.log(this._moduleName + ' installed'); process.exit(); });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('update-rc.d ' + options.name + ' defaults\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
//update-rc.d meshagent defaults # creates symlinks for rc.d
|
||||
//service meshagent start
|
||||
|
||||
break;
|
||||
case 'systemd':
|
||||
var serviceDescription = options.description ? options.description : 'MeshCentral Agent';
|
||||
if (!require('fs').existsSync('/usr/local/mesh')) { require('fs').mkdirSync('/usr/local/mesh'); }
|
||||
require('fs').copyFileSync(options.servicePath, '/usr/local/mesh/' + options.name);
|
||||
var m = require('fs').statSync('/usr/local/mesh/' + options.name).mode;
|
||||
m |= (require('fs').CHMOD_MODES.S_IXUSR | require('fs').CHMOD_MODES.S_IXGRP);
|
||||
require('fs').chmodSync('/usr/local/mesh/' + options.name, m);
|
||||
require('fs').writeFileSync('/lib/systemd/system/' + options.name + '.service', '[Unit]\nDescription=' + serviceDescription + '\n[Service]\nExecStart=/usr/local/mesh/' + options.name + '\nStandardOutput=null\nRestart=always\nRestartSec=3\n[Install]\nWantedBy=multi-user.target\nAlias=' + options.name + '.service\n', { flags: 'w' });
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._moduleName = options.name;
|
||||
this._update.on('exit', function onUpdateRC_d() { console.log(this._moduleName + ' installed'); process.exit(); });
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl enable ' + options.name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.uninstallService = function uninstallService(name)
|
||||
{
|
||||
if (typeof (name) == 'object') { name = name.name; }
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
if (!this.isAdmin()) { throw ('Uninstalling a service, requires admin'); }
|
||||
|
||||
var service = this.getService(name);
|
||||
if (service.status.state == undefined || service.status.state == 'STOPPED')
|
||||
{
|
||||
if (this.proxy.DeleteService(service._service) == 0)
|
||||
{
|
||||
throw ('Uninstall Service for: ' + name + ', failed with error: ' + this.proxy2.GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
require('fs').unlinkSync(this.getServiceFolder() + '\\' + name + '.exe');
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ('Cannot uninstall service: ' + name + ', because it is: ' + service.status.state);
|
||||
}
|
||||
}
|
||||
else if(process.platform == 'linux')
|
||||
{
|
||||
switch (this.getServiceType())
|
||||
{
|
||||
case 'init':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._svcname = name;
|
||||
this._update.on('exit', function onUninstallExit() {
|
||||
try {
|
||||
require('fs').unlinkSync('/etc/init.d/' + this._svcname);
|
||||
console.log(this._svcname + ' uninstalled');
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
console.log(this._svcname + ' could not be uninstalled')
|
||||
}
|
||||
process.exit();
|
||||
});
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('service ' + name + ' stop\n');
|
||||
this._update.stdin.write('update-rc.d -f ' + name + ' remove\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
break;
|
||||
case 'systemd':
|
||||
this._update = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._update._svcname = name;
|
||||
this._update.on('exit', function onUninstallExit() {
|
||||
try {
|
||||
require('fs').unlinkSync('/usr/local/mesh/' + this._svcname);
|
||||
require('fs').unlinkSync('/lib/systemd/system/' + this._svcname + '.service');
|
||||
console.log(this._svcname + ' uninstalled');
|
||||
}
|
||||
catch (e) {
|
||||
console.log(this._svcname + ' could not be uninstalled')
|
||||
}
|
||||
process.exit();
|
||||
});
|
||||
this._update.stdout.on('data', function (chunk) { });
|
||||
this._update.stdin.write('systemctl stop ' + name + '.service\n');
|
||||
this._update.stdin.write('systemctl disable ' + name + '.service\n');
|
||||
this._update.stdin.write('exit\n');
|
||||
break;
|
||||
default: // unknown platform service type
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(process.platform == 'linux')
|
||||
{
|
||||
this.getServiceType = function getServiceType()
|
||||
{
|
||||
return (require('process-manager').getProcessInfo(1).Name);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = serviceManager;
|
|
@ -18,38 +18,40 @@ var toasters = {};
|
|||
|
||||
function Toaster()
|
||||
{
|
||||
this._ObjectID = 'Toaster';
|
||||
this._ObjectID = 'toaster';
|
||||
this.Toast = function Toast(title, caption)
|
||||
{
|
||||
if (process.platform != 'win32') return;
|
||||
|
||||
var retVal = {};
|
||||
var emitter = require('events').inherits(retVal);
|
||||
emitter.createEvent('Clicked');
|
||||
emitter.createEvent('Dismissed');
|
||||
|
||||
var session = require('user-sessions').Current();
|
||||
for (var i in session)
|
||||
{
|
||||
console.log(session[i]);
|
||||
}
|
||||
try
|
||||
{
|
||||
console.log('Attempting Toast Mechanism 1');
|
||||
retVal._child = require('ScriptContainer').Create({ processIsolation: true, sessionId: session.connected[0].SessionId });
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
console.log('Attempting Toast Mechanism 2');
|
||||
retVal._child = require('ScriptContainer').Create({ processIsolation: true });
|
||||
}
|
||||
retVal._child.parent = retVal;
|
||||
retVal.title = title;
|
||||
retVal.caption = caption;
|
||||
|
||||
retVal._child.on('exit', function (code) { this.parent.emit('Dismissed'); delete this.parent._child; });
|
||||
retVal._child.addModule('win-console', getJSModule('win-console'));
|
||||
retVal._child.addModule('win-messagepump', getJSModule('win-messagepump'));
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
emitter.createEvent('Clicked');
|
||||
|
||||
var str = "\
|
||||
var session = require('user-sessions').Current();
|
||||
for (var i in session) {
|
||||
console.log(session[i]);
|
||||
}
|
||||
try {
|
||||
console.log('Attempting Toast Mechanism 1');
|
||||
retVal._child = require('ScriptContainer').Create({ processIsolation: true, sessionId: session.Active[0].SessionId });
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
console.log('Attempting Toast Mechanism 2');
|
||||
retVal._child = require('ScriptContainer').Create({ processIsolation: true });
|
||||
}
|
||||
retVal._child.parent = retVal;
|
||||
|
||||
retVal._child.on('exit', function (code) { this.parent.emit('Dismissed'); delete this.parent._child; });
|
||||
retVal._child.addModule('win-console', getJSModule('win-console'));
|
||||
retVal._child.addModule('win-message-pump', getJSModule('win-message-pump'));
|
||||
|
||||
var str = "\
|
||||
try{\
|
||||
var toast = require('win-console');\
|
||||
var balloon = toast.SetTrayIcon({ szInfo: '" + caption + "', szInfoTitle: '" + title + "', balloonOnly: true });\
|
||||
|
@ -61,11 +63,62 @@ function Toaster()
|
|||
}\
|
||||
require('ScriptContainer').send('done');\
|
||||
";
|
||||
retVal._child.ExecuteString(str);
|
||||
toasters[retVal._hashCode()] = retVal;
|
||||
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||
console.log('Returning');
|
||||
return (retVal);
|
||||
retVal._child.ExecuteString(str);
|
||||
toasters[retVal._hashCode()] = retVal;
|
||||
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||
console.log('Returning');
|
||||
return (retVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!require('fs').existsSync('/usr/bin/notify-send'))
|
||||
{
|
||||
throw ('Toast not supported on this platform');
|
||||
}
|
||||
Object.defineProperty(retVal, '_sessions', {
|
||||
value: require('user-sessions').Current(function onCurrentSession(sessions)
|
||||
{
|
||||
this._cchild = require('child_process').execFile('/usr/bin/whoami', ['whoami'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this._cchild.stdout.on('data', function (chunk)
|
||||
{
|
||||
if (chunk.toString().split('\r\n')[0] == 'root')
|
||||
{
|
||||
if (sessions[':0'].State != 'Connected' && sessions[':0'].State != 'Active')
|
||||
{
|
||||
// No logged in user owns the display
|
||||
this.parent.parent.Parent.emit('Dismissed');
|
||||
return;
|
||||
}
|
||||
|
||||
// We root, so we need to direct to DISPLAY=:0
|
||||
this.parent.parent._notify = require('child_process').execFile('/bin/sh', ['sh'], { type: require('child_process').SpawnTypes.TERM });
|
||||
this.parent.parent._notify.stdin.write('su - ' + sessions[':0'].Username + ' -c "DISPLAY=:0 notify-send \'' + this.parent.parent.Parent.title + '\' \'' + this.parent.parent.Parent.caption + '\'"\n');
|
||||
this.parent.parent._notify.stdin.write('exit\n');
|
||||
this.parent.parent._notify.stdout.on('data', function (chunk) { });
|
||||
}
|
||||
else
|
||||
{
|
||||
// We ain't root, so that means we can just call send-notify directly
|
||||
this.parent.parent._notify = require('child_process').execFile('/usr/bin/notify-send', ['notify-send', this.parent.parent.Parent.title, this.parent.parent.Parent.caption], { type: require('child_process').SpawnTypes.TERM });
|
||||
this.parent.parent._notify.stdout.on('data', function (chunk) { });
|
||||
}
|
||||
|
||||
// NOTIFY-SEND has a bug where timeouts don't work, so the default is 10 seconds
|
||||
this.parent.parent.Parent._timeout = setTimeout(function onFakeDismissed(obj)
|
||||
{
|
||||
obj.emit('Dismissed');
|
||||
}, 10000, this.parent.parent.Parent);
|
||||
});
|
||||
this._cchild.parent = this;
|
||||
})
|
||||
});
|
||||
retVal._sessions.Parent = retVal;
|
||||
|
||||
toasters[retVal._hashCode()] = retVal;
|
||||
retVal.on('Dismissed', function () { delete toasters[this._hashCode()]; });
|
||||
|
||||
return (retVal);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,28 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
var NOTIFY_FOR_THIS_SESSION = 0;
|
||||
var NOTIFY_FOR_ALL_SESSIONS = 1;
|
||||
var WM_WTSSESSION_CHANGE = 0x02B1;
|
||||
var WTS_CONSOLE_CONNECT = (0x1);
|
||||
var WTS_CONSOLE_DISCONNECT = (0x2);
|
||||
var WTS_REMOTE_CONNECT = (0x3);
|
||||
var WTS_REMOTE_DISCONNECT = (0x4);
|
||||
var WTS_SESSION_LOGON = (0x5);
|
||||
var WTS_SESSION_LOGOFF = (0x6);
|
||||
var WTS_SESSION_LOCK = (0x7);
|
||||
var WTS_SESSION_UNLOCK = (0x8);
|
||||
var WTS_SESSION_REMOTE_CONTROL = (0x9);
|
||||
var WTS_SESSION_CREATE = (0xA);
|
||||
var WTS_SESSION_TERMINATE = (0xB);
|
||||
|
||||
function UserSessions()
|
||||
{
|
||||
this._ObjectID = 'user-sessions';
|
||||
require('events').EventEmitter.call(this, true).createEvent('changed');
|
||||
require('events').EventEmitter.call(this, true)
|
||||
.createEvent('changed')
|
||||
.createEvent('locked')
|
||||
.createEvent('unlocked');
|
||||
|
||||
this.enumerateUsers = function enumerateUsers()
|
||||
{
|
||||
|
@ -37,12 +55,15 @@ function UserSessions()
|
|||
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._serviceHooked = false;
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._kernel32 = this._marshal.CreateNativeProxy('Kernel32.dll');
|
||||
this._kernel32.CreateMethod('GetLastError');
|
||||
this._wts = this._marshal.CreateNativeProxy('Wtsapi32.dll');
|
||||
this._wts.CreateMethod('WTSEnumerateSessionsA');
|
||||
this._wts.CreateMethod('WTSQuerySessionInformationA');
|
||||
this._wts.CreateMethod('WTSRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSUnRegisterSessionNotification');
|
||||
this._wts.CreateMethod('WTSFreeMemory');
|
||||
this.SessionStates = ['Active', 'Connected', 'ConnectQuery', 'Shadow', 'Disconnected', 'Idle', 'Listening', 'Reset', 'Down', 'Init'];
|
||||
this.InfoClass =
|
||||
|
@ -124,9 +145,52 @@ function UserSessions()
|
|||
if (cb) { cb(retVal); }
|
||||
return (retVal);
|
||||
};
|
||||
|
||||
this._immediate = setImmediate(function (self)
|
||||
{
|
||||
if (self._serviceHooked) { return; } // If we were hooked by a service, we won't need to do anything further
|
||||
|
||||
// We need to spin up a message pump, and fetch a window handle
|
||||
var message_pump = require('win-message-pump');
|
||||
self._messagepump = new message_pump({ filter: WM_WTSSESSION_CHANGE });
|
||||
self._messagepump.on('exit', function (code) { self._wts.WTSUnRegisterSessionNotification(self.hwnd); });
|
||||
self._messagepump.on('hwnd', function (h)
|
||||
{
|
||||
self.hwnd = h;
|
||||
// Now that we have a window handle, we can register it to receive Windows Messages
|
||||
self._wts.WTSRegisterSessionNotification(self.hwnd, NOTIFY_FOR_ALL_SESSIONS);
|
||||
});
|
||||
self._messagepump.on('message', function (msg)
|
||||
{
|
||||
if (msg.message == WM_WTSSESSION_CHANGE)
|
||||
{
|
||||
switch(msg.wparam)
|
||||
{
|
||||
case WTS_SESSION_LOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('locked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
case WTS_SESSION_UNLOCK:
|
||||
self.enumerateUsers().then(function (users)
|
||||
{
|
||||
if (users[msg.lparam]) { self.emit('unlocked', users[msg.lparam]); }
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._linuxWatcher = require('fs').watch('/var/run/utmp');
|
||||
this._linuxWatcher.user_session = this;
|
||||
this._linuxWatcher.on('change', function (a, b)
|
||||
{
|
||||
this.user_session.emit('changed');
|
||||
});
|
||||
this.Self = function Self()
|
||||
{
|
||||
var promise = require('promise');
|
||||
|
@ -277,13 +341,26 @@ function UserSessions()
|
|||
function showActiveOnly(source)
|
||||
{
|
||||
var retVal = [];
|
||||
var unique = {};
|
||||
var usernames = [];
|
||||
var tmp;
|
||||
|
||||
for (var i in source)
|
||||
{
|
||||
if (source[i].State == 'Active')
|
||||
{
|
||||
retVal.push(source[i]);
|
||||
tmp = (source[i].Domain ? (source[i].Domain + '\\') : '') + source[i].Username;
|
||||
if (!unique[tmp]) { unique[tmp] = tmp;}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in unique)
|
||||
{
|
||||
usernames.push(i);
|
||||
}
|
||||
|
||||
Object.defineProperty(retVal, 'usernames', { value: usernames });
|
||||
return (retVal);
|
||||
}
|
||||
function getTokens(str)
|
||||
|
|
|
@ -37,7 +37,7 @@ function WindowsConsole()
|
|||
{
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
this._ObjectID = 'WindowsConsole';
|
||||
this._ObjectID = 'win-console';
|
||||
this._Marshal = require('_GenericMarshal');
|
||||
this._kernel32 = this._Marshal.CreateNativeProxy("kernel32.dll");
|
||||
this._user32 = this._Marshal.CreateNativeProxy("user32.dll");
|
||||
|
@ -102,7 +102,7 @@ function WindowsConsole()
|
|||
if (options.szInfoTitle) { Buffer.from(options.szInfoTitle).copy(szInfoTitle.toBuffer()); }
|
||||
|
||||
|
||||
var MessagePump = require('win-messagepump');
|
||||
var MessagePump = require('win-message-pump');
|
||||
retVal = { _ObjectID: 'WindowsConsole.TrayIcon', MessagePump: new MessagePump(options) };
|
||||
var retValEvents = require('events').inherits(retVal);
|
||||
retValEvents.createEvent('ToastClicked');
|
||||
|
|
|
@ -19,7 +19,7 @@ var WM_QUIT = 0x0012;
|
|||
|
||||
function WindowsMessagePump(options)
|
||||
{
|
||||
this._ObjectID = 'WindowsMessagePump';
|
||||
this._ObjectID = 'win-message-pump';
|
||||
this._options = options;
|
||||
var emitterUtils = require('events').inherits(this);
|
||||
emitterUtils.createEvent('hwnd');
|
||||
|
@ -29,11 +29,10 @@ function WindowsMessagePump(options)
|
|||
|
||||
this._child = require('ScriptContainer').Create({ processIsolation: 0 });
|
||||
this._child.MessagePump = this;
|
||||
this._child.prependListener('~', function _childFinalizer() { this.MessagePump.emit('exit', 0); console.log('calling stop'); this.MessagePump.stop(); });
|
||||
this._child.prependListener('~', function _childFinalizer() { this.MessagePump.emit('exit', 0); this.MessagePump.stop(); });
|
||||
this._child.once('exit', function onExit(code) { this.MessagePump.emit('exit', code); });
|
||||
this._child.once('ready', function onReady()
|
||||
{
|
||||
console.log('child ready');
|
||||
var execString =
|
||||
"var m = require('_GenericMarshal');\
|
||||
var h = null;\
|
||||
|
@ -110,7 +109,6 @@ function WindowsMessagePump(options)
|
|||
{
|
||||
if(this._child && this._child._hwnd)
|
||||
{
|
||||
console.log('posting WM_QUIT');
|
||||
var marshal = require('_GenericMarshal');
|
||||
var User32 = marshal.CreateNativeProxy('User32.dll');
|
||||
User32.CreateMethod('PostMessageA');
|
|
@ -35,7 +35,7 @@ var KEY_DATA_TYPES =
|
|||
|
||||
function windows_registry()
|
||||
{
|
||||
this._ObjectId = 'windows_registry';
|
||||
this._ObjectId = 'win-registry';
|
||||
this._marshal = require('_GenericMarshal');
|
||||
this._AdvApi = this._marshal.CreateNativeProxy('Advapi32.dll');
|
||||
this._AdvApi.CreateMethod('RegCreateKeyExA');
|
||||
|
|
|
@ -1204,6 +1204,10 @@ process.on('SIGINT', function () { if (meshserver != null) { meshserver.Stop();
|
|||
// Load the really basic modules
|
||||
var meshserver = null;
|
||||
function mainStart(args) {
|
||||
// Check the NodeJS is version 6 or better.
|
||||
if (Number(process.version.match(/^v(\d+\.\d+)/)[1]) < 6) { console.log("MeshCentral requires Node v6.x or above, current version is " + process.version + "."); return; }
|
||||
|
||||
// Check for any missing modules.
|
||||
InstallModules(['minimist'], function () {
|
||||
// Get the server configuration
|
||||
var config = getConfig();
|
||||
|
|
|
@ -493,7 +493,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||
if (chguser) {
|
||||
if (obj.common.validateString(command.email, 1, 256) && (chguser.email != command.email)) { chguser.email = command.email; change = 1; }
|
||||
if ((command.emailVerified === true || command.emailVerified === false) && (chguser.emailVerified != command.emailVerified)) { chguser.emailVerified = command.emailVerified; change = 1; }
|
||||
if (obj.common.validateInt(command.quota, 0) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
||||
if ((obj.common.validateInt(command.quota, 0) || command.quota == null) && (command.quota != chguser.quota)) { chguser.quota = command.quota; if (chguser.quota == null) { delete chguser.quota; } change = 1; }
|
||||
if ((user.siteadmin == 0xFFFFFFFF) && obj.common.validateInt(command.siteadmin) && (chguser.siteadmin != command.siteadmin)) { chguser.siteadmin = command.siteadmin; change = 1; }
|
||||
if (change == 1) {
|
||||
obj.db.SetUser(chguser);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.1.9-v",
|
||||
"version": "0.1.9-w",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4981,11 +4981,19 @@
|
|||
p5setActions();
|
||||
}
|
||||
|
||||
function getNiceSize(bytes) {
|
||||
if (bytes <= 0) return 'Storage limit exceed';
|
||||
if (bytes < 2048) return bytes + ' bytes remaining';
|
||||
if (bytes < 2097152) return Math.round(bytes / 1024) + ' kilobytes remaining';
|
||||
if (bytes < 2147483648) return Math.round(bytes / 1024 / 1024) + ' megabytes remaining';
|
||||
return Math.round(bytes / 1024 / 1024 / 1024) + ' gigabytes remaining';
|
||||
}
|
||||
|
||||
function p5getQuotabar(f) {
|
||||
while (f.t > 1 && f.t != 4) { f = f.parent; }
|
||||
if ((f.t != 1 && f.t != 4) || (f.maxbytes == null)) return '';
|
||||
var tf = Math.floor(f.s / 1024), tq = Math.floor((f.maxbytes - f.s) / 1024);
|
||||
return '<span title="' + tf + "k in " + f.c + " file" + (f.c > 1?'s':'') + ". " + (Math.floor(f.maxbytes / 1024)) + 'k maxinum">' + ((tq < 0)?('Storage limit exceed'):(tq + 'k remaining')) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' /></span>';
|
||||
var tf = Math.floor(f.s / 1024), tq = (f.maxbytes - f.s);
|
||||
return '<span title="' + tf + "k in " + f.c + " file" + (f.c > 1 ? 's' : '') + ". " + (Math.floor(f.maxbytes / 1024 / 1024)) + 'k maxinum">' + getNiceSize(tq) + ' <progress style=height:10px;width:100px value=' + f.s + ' max=' + f.maxbytes + ' /></span>';
|
||||
}
|
||||
|
||||
function p5showPublicLink(u) { setDialogMode(2, "Public Link", 1, null, '<input type=text style=width:100% value="' + u + '" readonly />'); }
|
||||
|
@ -5057,13 +5065,14 @@
|
|||
names.push(file.name);
|
||||
sizes.push(file.size);
|
||||
types.push(file.type);
|
||||
reader.onload = function(event) {
|
||||
reader.onload = function (event) {
|
||||
console.log(event.target.result.length);
|
||||
datas.push(event.target.result);
|
||||
if (--readercount == 0) {
|
||||
Q('p5fileDragName').value = names.join('*');
|
||||
Q('p5fileDragSize').value = sizes.join('*');
|
||||
Q('p5fileDragType').value = types.join('*');
|
||||
Q('p5fileDragData').value = datas.join('*');
|
||||
Q('p5fileDragData').value = datas.join('*'); // TODO: This will not work for large files!!! *****************
|
||||
Q('p5fileDragLink').value = encodeURIComponent(filetreelinkpath);
|
||||
Q('p5loginSubmit2').click();
|
||||
}
|
||||
|
|
17
webserver.js
17
webserver.js
|
@ -935,15 +935,16 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (objid.startsWith('user/')) {
|
||||
var user = obj.users[objid];
|
||||
if (user == null) return 0;
|
||||
if (user.siteadmin == 0xFFFFFFFF) return null; // Administrators have no user limit
|
||||
if ((user.quota != null) && (typeof user.quota == 'number')) { return user.quota; }
|
||||
if ((domain != null) && (domain.userQuota != null) && (typeof domain.userQuota == 'number')) { return domain.userQuota; }
|
||||
return 1048576; // By default, the server will have a 1 meg limit on user accounts
|
||||
if ((domain != null) && (domain.userquota != null) && (typeof domain.userquota == 'number')) { return domain.userquota; }
|
||||
return null; // By default, the user will have no limit
|
||||
} else if (objid.startsWith('mesh/')) {
|
||||
var mesh = obj.meshes[objid];
|
||||
if (mesh == null) return 0;
|
||||
if ((mesh.quota != null) && (typeof mesh.quota == 'number')) { return mesh.quota; }
|
||||
if ((domain != null) && (domain.meshQuota != null) && (typeof domain.meshQuota == 'number')) { return domain.meshQuota; }
|
||||
return 1048576; // By default, the server will have a 1 meg limit on mesh accounts
|
||||
if ((domain != null) && (domain.meshquota != null) && (typeof domain.meshquota == 'number')) { return domain.meshquota; }
|
||||
return null; // By default, the mesh will have no limit
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
@ -997,12 +998,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
var multiparty = require('multiparty');
|
||||
var form = new multiparty.Form();
|
||||
form.parse(req, function (err, fields, files) {
|
||||
if ((fields == null) || (fields.link == null) || (fields.link.length != 1)) { res.sendStatus(404); return; }
|
||||
if ((fields == null) || (fields.link == null) || (fields.link.length != 1)) { /*console.log('UploadFile, Invalid Fields:', fields, files);*/ res.sendStatus(404); return; }
|
||||
var xfile = obj.getServerFilePath(user, domain, decodeURIComponent(fields.link[0]));
|
||||
if (xfile == null) { res.sendStatus(404); return; }
|
||||
// Get total bytes in the path
|
||||
var totalsize = readTotalFileSize(xfile.fullpath);
|
||||
if (totalsize < xfile.quota) { // Check if the quota is not already broken
|
||||
if ((xfile.quota == null) || (totalsize < xfile.quota)) { // Check if the quota is not already broken
|
||||
if (fields.name != null) {
|
||||
// Upload method where all the file data is within the fields.
|
||||
var names = fields.name[0].split('*'), sizes = fields.size[0].split('*'), types = fields.type[0].split('*'), datas = fields.data[0].split('*');
|
||||
|
@ -1010,7 +1011,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
for (var i = 0; i < names.length; i++) {
|
||||
if (obj.common.IsFilenameValid(names[i]) == false) { res.sendStatus(404); return; }
|
||||
var filedata = new Buffer(datas[i].split(',')[1], 'base64');
|
||||
if ((totalsize + filedata.length) < xfile.quota) { // Check if quota would not be broken if we add this file
|
||||
if ((xfile.quota == null) || ((totalsize + filedata.length) < xfile.quota)) { // Check if quota would not be broken if we add this file
|
||||
// Create the user folder if needed
|
||||
(function (fullpath, filename, filedata) {
|
||||
obj.fs.mkdir(xfile.fullpath, function () {
|
||||
|
@ -1027,7 +1028,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
// More typical upload method, the file data is in a multipart mime post.
|
||||
for (var i in files.files) {
|
||||
var file = files.files[i], fpath = obj.path.join(xfile.fullpath, file.originalFilename);
|
||||
if (obj.common.IsFilenameValid(file.originalFilename) && ((totalsize + file.size) < xfile.quota)) { // Check if quota would not be broken if we add this file
|
||||
if (obj.common.IsFilenameValid(file.originalFilename) && ((xfile.quota == null) || ((totalsize + file.size) < xfile.quota))) { // Check if quota would not be broken if we add this file
|
||||
obj.fs.rename(file.path, fpath, function () {
|
||||
obj.parent.DispatchEvent([user._id], obj, 'updatefiles'); // Fire an event causing this user to update this files
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue