mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-22 13:21:31 +03:00
Server bug fixing and new MeshAgent
This commit is contained in:
parent
562310bed1
commit
b274b782fa
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 New Issue
Block a user